88 lines
3.4 KiB
TypeScript
88 lines
3.4 KiB
TypeScript
import { Transition } from "@headlessui/react";
|
|
import clsx from "clsx";
|
|
import { Fragment, useState } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Form } from "react-router";
|
|
import { ColumnDto } from "~/application/dtos/data/ColumnDto";
|
|
import { useOuterClick } from "~/utils/shared/KeypressUtils";
|
|
import { updateItemByIdx } from "~/utils/shared/ObjectUtils";
|
|
import DotsHorizontalFilledIcon from "../icons/DotsHorizontalFilledIcon";
|
|
import InputCheckboxInline from "../input/InputCheckboxInline";
|
|
import { translateLabel } from "~/utils/i18n/translateLabel";
|
|
|
|
interface Props {
|
|
items: ColumnDto[];
|
|
setItems: React.Dispatch<React.SetStateAction<ColumnDto[]>>;
|
|
onClear: () => void;
|
|
className?: string;
|
|
}
|
|
|
|
export default function ColumnSelector({ items, setItems, onClear, className }: Props) {
|
|
const { t, i18n } = useTranslation();
|
|
|
|
const [opened, setOpened] = useState(false);
|
|
|
|
const clickOutside = useOuterClick(() => setOpened(false));
|
|
|
|
return (
|
|
<div ref={clickOutside} className={clsx("relative", className)}>
|
|
<button
|
|
type="button"
|
|
aria-label={t("shared.columns")}
|
|
onClick={() => setOpened(!opened)}
|
|
className="hover:bg-surface-neutral-secondary focus:border-border-default focus:shadow-focus relative z-0 inline-flex rounded-md text-sm shadow-2xs focus:z-10 focus:outline-hidden"
|
|
>
|
|
<span
|
|
className={clsx(
|
|
"border-border-default text-text-neutral-tertiary bg-surface-neutral-primary relative inline-flex items-center space-x-2 rounded-md border px-2 py-3 font-medium"
|
|
)}
|
|
>
|
|
<div>
|
|
<DotsHorizontalFilledIcon className="h-3 w-3" />
|
|
</div>
|
|
</span>
|
|
</button>
|
|
|
|
<Transition
|
|
as={Fragment}
|
|
show={opened}
|
|
enter="transition ease-out duration-100"
|
|
enterFrom="transform opacity-0 scale-95"
|
|
enterTo="transform opacity-100 scale-100"
|
|
leave="transition ease-in duration-75"
|
|
leaveFrom="transform opacity-100 scale-100"
|
|
leaveTo="transform opacity-0 scale-95"
|
|
>
|
|
<Form
|
|
method="get"
|
|
className="divide-border-default bg-surface-neutral-primary absolute right-0 z-40 mt-2 w-64 origin-top-right divide-y overflow-visible rounded-md shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-hidden"
|
|
>
|
|
<div className="bg-surface-neutral-secondary flex items-center justify-between px-2 py-2 text-sm">
|
|
<div className="font-bold">{t("shared.columns")}</div>
|
|
</div>
|
|
<div className="divide-border-default divide-y text-sm">
|
|
{items.map((filter, idx) => {
|
|
return (
|
|
<div key={filter.name} className="divide-border-default divide-y">
|
|
<div className="divide-y divide-gray-300 px-2 py-2">
|
|
<InputCheckboxInline
|
|
name={filter.name}
|
|
title={translateLabel(t, i18n, filter.title)}
|
|
value={filter.visible}
|
|
setValue={(e) => {
|
|
updateItemByIdx(items, setItems, idx, {
|
|
visible: Boolean(e),
|
|
});
|
|
}}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</Form>
|
|
</Transition>
|
|
</div>
|
|
);
|
|
}
|