From cb9320ee152201d9278836feb8fcef027f615857 Mon Sep 17 00:00:00 2001 From: keyhan Date: Wed, 8 Apr 2026 12:40:25 +0330 Subject: [PATCH] refactor: add useDebounce hook and replace manual debounce in admin search - Create reusable useDebounce hook in frontend/src/hooks/useDebounce.ts - Replace manual setTimeout/clearTimeout + extra state in AdminAppsPage with clean useDebounce(search, 400) pattern - Removes timer state and handleSearch wrapper function --- .../src/app/dashboard/admin/apps/page.tsx | 15 +++------- frontend/src/hooks/useDebounce.ts | 28 +++++++++++++++++++ frontend/tsconfig.tsbuildinfo | 2 +- 3 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 frontend/src/hooks/useDebounce.ts diff --git a/frontend/src/app/dashboard/admin/apps/page.tsx b/frontend/src/app/dashboard/admin/apps/page.tsx index 0b6e9e5..5933a6f 100644 --- a/frontend/src/app/dashboard/admin/apps/page.tsx +++ b/frontend/src/app/dashboard/admin/apps/page.tsx @@ -8,6 +8,7 @@ import { toast } from 'react-toastify'; import type { Application } from '@/types'; import { Search, X, Package, Hexagon, User, Database, Box } from 'lucide-react'; import { useConfirm } from '@/components/confirm-modal'; +import { useDebounce } from '@/hooks/useDebounce'; const statusColors: Record = { running: 'badge-green', @@ -23,15 +24,7 @@ export default function AdminAppsPage() { const queryClient = useQueryClient(); const confirm = useConfirm(); const [search, setSearch] = useState(''); - const [debouncedSearch, setDebouncedSearch] = useState(''); - const [timer, setTimer] = useState(null); - - const handleSearch = (value: string) => { - setSearch(value); - if (timer) clearTimeout(timer); - const t = setTimeout(() => setDebouncedSearch(value), 400); - setTimer(t); - }; + const debouncedSearch = useDebounce(search, 400); const { data: apps = [], isLoading } = useQuery({ queryKey: ['admin-applications', debouncedSearch], @@ -138,12 +131,12 @@ export default function AdminAppsPage() { type="text" placeholder="Search by app name, user name, email, or user ID…" value={search} - onChange={(e) => handleSearch(e.target.value)} + onChange={(e) => setSearch(e.target.value)} className="input pl-10 w-full" /> {search && (