From 5a05968ae9168717c980ae79a0c591e325fd5c4a Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Fri, 29 May 2026 00:23:07 +0200 Subject: [PATCH] fix(frontend): rewrite FiltersSortingPanel with shadcn, correct styling, useTransition --- .../components/filters-sorting-panel.tsx | 201 +++++++++++------- 1 file changed, 121 insertions(+), 80 deletions(-) diff --git a/thoughts-frontend/components/filters-sorting-panel.tsx b/thoughts-frontend/components/filters-sorting-panel.tsx index 20e1b58..9327f2f 100644 --- a/thoughts-frontend/components/filters-sorting-panel.tsx +++ b/thoughts-frontend/components/filters-sorting-panel.tsx @@ -1,6 +1,11 @@ "use client"; +import { useState, useTransition } from "react"; import { useRouter, useSearchParams } from "next/navigation"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import { Checkbox } from "@/components/ui/checkbox"; +import { Label } from "@/components/ui/label"; +import { Separator } from "@/components/ui/separator"; import { FeedSortOption } from "@/lib/api"; const SORT_OPTIONS: { value: FeedSortOption; label: string }[] = [ @@ -14,112 +19,148 @@ const SORT_OPTIONS: { value: FeedSortOption; label: string }[] = [ export function FiltersSortingPanel() { const router = useRouter(); const searchParams = useSearchParams(); + const [isPending, startTransition] = useTransition(); - const currentSort = (searchParams.get("sort") ?? "newest") as FeedSortOption; - const originalsOnly = searchParams.get("originals_only") === "true"; - const repliesOnly = searchParams.get("replies_only") === "true"; - const localOnly = searchParams.get("local_only") === "true"; - const hideSensitive = searchParams.get("hide_sensitive") === "true"; + const [sort, setSort] = useState( + (searchParams.get("sort") as FeedSortOption | null) ?? "newest" + ); + const [originalsOnly, setOriginalsOnly] = useState( + searchParams.get("originals_only") === "true" + ); + const [repliesOnly, setRepliesOnly] = useState( + searchParams.get("replies_only") === "true" + ); + const [localOnly, setLocalOnly] = useState( + searchParams.get("local_only") === "true" + ); + const [hideSensitive, setHideSensitive] = useState( + searchParams.get("hide_sensitive") === "true" + ); - function update(key: string, value: string | null) { + function pushParams(updates: Record) { const params = new URLSearchParams(searchParams.toString()); params.delete("page"); - if (value === null) { - params.delete(key); - } else { - params.set(key, value); + for (const [key, value] of Object.entries(updates)) { + if (value === null) { + params.delete(key); + } else { + params.set(key, value); + } } - router.push(`/?${params.toString()}`); + startTransition(() => router.replace(`/?${params.toString()}`)); } - function setSort(value: FeedSortOption) { - update("sort", value === "newest" ? null : value); + function handleSort(value: FeedSortOption) { + setSort(value); + pushParams({ sort: value === "newest" ? null : value }); } - function toggleFilter(key: string, current: boolean) { - update(key, current ? null : "true"); + function handleOriginalsOnly(checked: boolean) { + setOriginalsOnly(checked); + if (checked) setRepliesOnly(false); + const updates: Record = { + originals_only: checked ? "true" : null, + }; + if (checked) updates.replies_only = null; + pushParams(updates); + } + + function handleRepliesOnly(checked: boolean) { + setRepliesOnly(checked); + if (checked) setOriginalsOnly(false); + const updates: Record = { + replies_only: checked ? "true" : null, + }; + if (checked) updates.originals_only = null; + pushParams(updates); + } + + function handleLocalOnly(checked: boolean) { + setLocalOnly(checked); + pushParams({ local_only: checked ? "true" : null }); + } + + function handleHideSensitive(checked: boolean) { + setHideSensitive(checked); + pushParams({ hide_sensitive: checked ? "true" : null }); } return ( -
+
-

Sort by

-
+

+ Sort by +

+ handleSort(v as FeedSortOption)} + className="space-y-1" + > {SORT_OPTIONS.map((opt) => ( - +
+ + +
))} -
+
+ +
-

Filter

-
-