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 | 30x 530x 530x 530x 2x 2x 530x 530x 530x 2x 1x 1x 1x 1x 530x 2x 530x 246x 31x 31x 2x 2x 24x 12x | import React from "react";
import { useTranslation } from "react-i18next";
import { useBooleanState } from "~app/hooks/use-boolean-state";
import type { SearchParamState } from "~app/utils/navigation";
import { Button } from "~components/button";
import { Divider } from "~components/divider";
import { Icon } from "~components/icons";
import { Modal } from "~components/modal";
import { Select } from "~components/select";
import { Text } from "~components/text";
type Props = {
sortState: SearchParamState<"/_protected/receipts/", "sort">;
filtersState: SearchParamState<"/_protected/receipts/", "filters">;
};
export const FilterButton: React.FC<Props> = ({
sortState: [sort, setSort],
filtersState: [filters, setFilters],
}) => {
const { t } = useTranslation("receipts");
const [filterModalOpen, { switchValue: switchFilterModal }] =
useBooleanState(false);
const sortSelectOnPress = React.useCallback(
() =>
setSort((prevSort) =>
prevSort === "date-desc" ? "date-asc" : "date-desc",
),
[setSort],
);
const sortIconName = sort === "date-desc" ? "sort-down" : "sort-up";
const filterOwnerOptions: Record<"true" | "false" | "undefined", string> = {
undefined: t("list.filters.ownership.ownedByAnybody"),
true: t("list.filters.ownership.ownedByMe"),
false: t("list.filters.ownership.ownedNotByMe"),
};
const onFilterSelectionChange = React.useCallback(
(filterKey: keyof typeof filters, key: keyof typeof filterOwnerOptions) => {
switch (key) {
case "true":
setFilters((prev) => ({ ...prev, [filterKey]: true }));
break;
case "false":
setFilters((prev) => ({ ...prev, [filterKey]: false }));
break;
default:
setFilters((prev) => ({ ...prev, [filterKey]: undefined }));
}
},
[setFilters],
);
const onOwnedFilterSelectionChange = React.useCallback(
(selection: keyof typeof filterOwnerOptions) =>
onFilterSelectionChange("ownedByMe", selection),
[onFilterSelectionChange],
);
return (
<>
<Button color="primary" isIconOnly onPress={switchFilterModal}>
<Icon name="filter" className="size-6" />
</Button>
<Modal
isOpen={filterModalOpen}
onOpenChange={switchFilterModal}
bodyClassName="items-center"
>
<Button
variant="light"
onPress={sortSelectOnPress}
startContent={<Icon name={sortIconName} className="size-6" />}
>
{sort === "date-desc"
? t("list.sorting.newestFirst")
: t("list.sorting.oldestFirst")}
</Button>
<Divider />
<Text className="text-2xl font-medium">{t("list.filters.title")}</Text>
<Select
items={(["true", "false", "undefined"] as const).map((position) => ({
position,
}))}
label={t("list.filters.ownership.label")}
placeholder=""
renderValue={(values) =>
values.map(({ position }) => (
<Text key={position}>{filterOwnerOptions[position]}</Text>
))
}
selectedKeys={[
filters.ownedByMe === undefined
? "undefined"
: filters.ownedByMe
? "true"
: "false",
]}
onSelectionChange={(nextKeys) => {
Iif (!nextKeys[0]) {
return;
}
onOwnedFilterSelectionChange(nextKeys[0]);
}}
disallowEmptySelection
getKey={({ position }) => position}
>
{({ position }) => <Text>{filterOwnerOptions[position]}</Text>}
</Select>
</Modal>
</>
);
};
|