Initial commit for new panel
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
"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}`;
|
||||
};
|
||||
Reference in New Issue
Block a user