Files
tm_panel/src/components/period-picker.tsx
T
2025-09-09 11:20:26 +03:30

98 lines
3.6 KiB
TypeScript

"use client";
import { ChevronUpIcon } from "@/assets/icons";
import { cn } from "@/lib/utils";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useState } from "react";
import { Dropdown, DropdownContent, DropdownTrigger } from "./ui/dropdown";
type PropsType<TItem> = {
defaultValue?: TItem;
items?: TItem[];
sectionKey: string;
minimal?: boolean;
};
const PARAM_KEY = "selected_time_frame";
export function PeriodPicker<TItem extends string>({
defaultValue,
sectionKey,
items,
minimal,
}: PropsType<TItem>) {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const [isOpen, setIsOpen] = useState(false);
return (
<Dropdown isOpen={isOpen} setIsOpen={setIsOpen}>
<DropdownTrigger
className={cn(
"flex h-8 w-full items-center justify-between gap-x-1 rounded-md border border-[#E8E8E8] bg-white px-3 py-2 text-sm font-medium text-dark-5 outline-none ring-offset-white disabled:cursor-not-allowed disabled:opacity-50 data-[placeholder]:text-neutral-500 dark:border-dark-3 dark:bg-dark-2 dark:text-white dark:ring-offset-neutral-950 dark:focus:ring-neutral-300 dark:data-[placeholder]:text-neutral-400 [&>span]:line-clamp-1 [&[data-state='open']>svg]:rotate-0",
minimal &&
"border-none bg-transparent p-0 text-dark dark:bg-transparent dark:text-white",
)}
>
<span className="capitalize">{defaultValue || "Time Period"}</span>
<ChevronUpIcon className="size-4 rotate-180 transition-transform" />
</DropdownTrigger>
<DropdownContent
align="end"
className="min-w-[7rem] overflow-hidden rounded-lg border border-[#E8E8E8] bg-white p-1 font-medium text-dark-5 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-dark-3 dark:bg-dark-2 dark:text-current"
>
<ul>
{(items || ["monthly", "yearly"]).map((item) => (
<li key={crypto.randomUUID()}>
<button
className="flex w-full select-none items-center truncate rounded-md px-3 py-2 text-sm capitalize outline-none hover:bg-[#F9FAFB] hover:text-dark-3 dark:hover:bg-[#FFFFFF1A] dark:hover:text-white"
onClick={() => {
const queryString = createQueryString({
sectionKey,
value: item,
selectedTimeFrame: searchParams.get(PARAM_KEY),
});
router.push(pathname + queryString, {
scroll: false,
});
setIsOpen(false);
}}
>
{item}
</button>
</li>
))}
</ul>
</DropdownContent>
</Dropdown>
);
}
const createQueryString = (props: {
sectionKey: string;
value: string;
selectedTimeFrame: string | null;
}) => {
const paramsValue = `${props.sectionKey}:${props.value}`;
if (!props.selectedTimeFrame) {
return `?${PARAM_KEY}=${paramsValue}`;
}
const newSearchParams = props.selectedTimeFrame
.split(",")
.filter((value) => !value.includes(props.sectionKey))
.join(",");
if (!newSearchParams) {
return `?${PARAM_KEY}=${paramsValue}`;
}
return `?${PARAM_KEY}=${newSearchParams},${paramsValue}`;
};