From b3c49c3794bba7756efd5d5d939f53768ff62c89 Mon Sep 17 00:00:00 2001 From: xCyanGrizzly Date: Sat, 4 Jul 2026 09:36:51 +0200 Subject: [PATCH] feat(stls): add searchable creator filter combobox to toolbar --- .../(app)/stls/_components/creator-filter.tsx | 82 +++++++++++++++++++ src/app/(app)/stls/_components/stl-table.tsx | 24 ++++++ src/app/(app)/stls/page.tsx | 6 +- src/lib/telegram/queries.ts | 9 ++ 4 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 src/app/(app)/stls/_components/creator-filter.tsx diff --git a/src/app/(app)/stls/_components/creator-filter.tsx b/src/app/(app)/stls/_components/creator-filter.tsx new file mode 100644 index 0000000..e744bc3 --- /dev/null +++ b/src/app/(app)/stls/_components/creator-filter.tsx @@ -0,0 +1,82 @@ +"use client"; + +import { useState } from "react"; +import { Check, ChevronsUpDown } from "lucide-react"; +import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from "@/components/ui/command"; +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; + +interface CreatorFilterProps { + creators: string[]; + value: string; // active creator, "" when none + onChange: (creator: string) => void; // "" clears the filter +} + +export function CreatorFilter({ creators, value, onChange }: CreatorFilterProps) { + const [open, setOpen] = useState(false); + + return ( + + + + + + + + + No creators found. + + { + onChange(""); + setOpen(false); + }} + > + + All Creators + + {creators.map((creator) => ( + { + onChange(creator); + setOpen(false); + }} + > + + {creator} + + ))} + + + + + + ); +} diff --git a/src/app/(app)/stls/_components/stl-table.tsx b/src/app/(app)/stls/_components/stl-table.tsx index fabc3ce..d914bb0 100644 --- a/src/app/(app)/stls/_components/stl-table.tsx +++ b/src/app/(app)/stls/_components/stl-table.tsx @@ -16,6 +16,7 @@ import { import { PackageFilesDrawer } from "./package-files-drawer"; import { IngestionStatus } from "./ingestion-status"; import { SkippedPackagesTab } from "./skipped-packages-tab"; +import { CreatorFilter } from "./creator-filter"; import { DataTable } from "@/components/shared/data-table"; import { DataTablePagination } from "@/components/shared/data-table-pagination"; import { DataTableViewOptions } from "@/components/shared/data-table-view-options"; @@ -60,6 +61,7 @@ interface StlTableProps { totalCount: number; ingestionStatus: IngestionAccountStatus[]; availableTags: string[]; + availableCreators: string[]; searchTerm: string; skippedData: SkippedRow[]; skippedPageCount: number; @@ -75,6 +77,7 @@ export function StlTable({ totalCount, ingestionStatus, availableTags, + availableCreators, searchTerm, skippedData, skippedPageCount, @@ -209,6 +212,20 @@ export function StlTable({ [router, pathname, searchParams] ); + const updateCreatorFilter = useCallback( + (value: string) => { + const params = new URLSearchParams(searchParams.toString()); + if (value) { + params.set("creator", value); + params.set("page", "1"); + } else { + params.delete("creator"); + } + router.push(`${pathname}?${params.toString()}`, { scroll: false }); + }, + [router, pathname, searchParams] + ); + const activeTab = searchParams.get("tab") ?? "packages"; const updateTab = useCallback( @@ -519,6 +536,13 @@ export function StlTable({ )} + {availableCreators.length > 0 && ( + + )}