Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | import * as React from "react";
// @mui
import Box from "@mui/material/Box";
// form
import * as Yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import { useForm, FormProvider, SubmitHandler } from "react-hook-form";
// components
import FilterMenu from "./FilterMenu";
import FilterButton from "./FilterButton";
import { RHFSelect } from "@common/Select";
import { Button } from "@common/Button";
import { Text } from "@common/Text";
import { ConditionallyRenderAmountForm } from "./FilterAmountRenderer";
// types
import { Options } from "types/data.types";
// redux
import { useAppDispatch } from "@redux/hooks";
import { ActionCreatorWithPayload } from "@reduxjs/toolkit";
// localization
import { useTranslation } from "react-i18next";
import { namespaces } from "localization/resources/i18n.constants";
type IFormValues = {
modifier: string;
amount: number;
amountOne: number;
amountTwo: number;
};
export default function FilterWithAmount({
title,
options,
apply,
disable,
filters,
unit = <sup>USD</sup>,
money = true,
}: {
title: string;
options: Options[];
apply: ActionCreatorWithPayload<any, string>;
disable: ActionCreatorWithPayload<any, string>;
filters: {
[key: string]: any;
};
unit?: React.ReactNode;
money?: boolean;
}) {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const dispatch = useAppDispatch();
const schema = Yup.object({
amount: Yup.number().typeError("").max(100000, "").required(""),
// amountOne should be less than amountTwo
amountOne: Yup.number().typeError("").max(100000, ""),
// amountTwo should be greater than amountOne
amountTwo: Yup.number()
.typeError("")
.max(100000, "")
.when("amountOne", {
is: (val: number) => val > 0,
then: (schema) =>
schema.test("is-greater-than-amountOne", "", function (value: any) {
const { amountOne } = this.parent;
return value > amountOne;
}),
otherwise: (schema) => schema.typeError("").max(100000, ""),
}),
});
const defaultValues = {
modifier: options[0].value,
amount: 0,
amountOne: 0,
amountTwo: 0,
};
const methods = useForm<IFormValues>({
resolver: yupResolver(schema),
defaultValues,
});
const { watch } = methods;
const values = watch();
const handleOpenMenu = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget.parentElement);
};
const handleClose = () => {
setAnchorEl(null);
};
const handleDisableFilter = () => {
setAnchorEl(null);
dispatch(disable(title));
};
const onSubmit: SubmitHandler<IFormValues> = (formValues) => {
setAnchorEl(null);
dispatch(apply({ title, values: formValues }));
};
const { t } = useTranslation(namespaces.common);
return (
<>
<FilterButton
title={title}
onClick={handleOpenMenu}
active={filters[title].length > 0}
onDisableFilter={handleDisableFilter}
>
{values.modifier.includes("between") ? (
<>
{filters[title][0]}
{unit} - {filters[title][1]}
{unit}
</>
) : (
<>
{filters[title][0]} {filters[title][1]}
{unit}
</>
)}
</FilterButton>
<FilterMenu anchorEl={anchorEl} open={open} onClose={handleClose}>
<FormProvider {...methods}>
<Box
mb={2}
component="form"
id="amount-filter"
onSubmit={methods.handleSubmit(onSubmit)}
>
<Text
variant="headline"
sx={{
marginBottom: 2,
fontWeight: 350,
color: "#575353",
span: { textTransform: "capitalize" },
}}
>
Filter by <span>{title}</span>
</Text>
<RHFSelect name="modifier" options={options} fullWidth />
<ConditionallyRenderAmountForm
value={values.modifier}
money={money}
/>
</Box>
</FormProvider>
<Button
fullWidth
size="small"
type="submit"
variant="primary"
form="amount-filter"
>
{t("filters.apply", { ns: namespaces.common })}
</Button>
</FilterMenu>
</>
);
}
|