fix(admin): debounce authorization user search
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { Loader2, Search, ShieldCheck, UserCog } from "lucide-react";
|
import { Loader2, Search, ShieldCheck, UserCog } from "lucide-react";
|
||||||
import { useAuth } from "@/contexts/AuthContext";
|
import { useAuth } from "@/contexts/AuthContext";
|
||||||
@@ -16,6 +16,11 @@ import { Switch } from "@/components/ui/switch";
|
|||||||
|
|
||||||
const PAGE_SIZE = 25;
|
const PAGE_SIZE = 25;
|
||||||
|
|
||||||
|
const normalizeSearchDigits = (value: string) =>
|
||||||
|
value
|
||||||
|
.replace(/[۰-۹]/g, (digit) => String("۰۱۲۳۴۵۶۷۸۹".indexOf(digit)))
|
||||||
|
.replace(/[٠-٩]/g, (digit) => String("٠١٢٣٤٥٦٧٨٩".indexOf(digit)));
|
||||||
|
|
||||||
function fullName(user: Pick<Types.UserListSchema, "first_name" | "last_name" | "username">) {
|
function fullName(user: Pick<Types.UserListSchema, "first_name" | "last_name" | "username">) {
|
||||||
return [user.first_name, user.last_name].filter(Boolean).join(" ") || user.username;
|
return [user.first_name, user.last_name].filter(Boolean).join(" ") || user.username;
|
||||||
}
|
}
|
||||||
@@ -34,6 +39,14 @@ export default function AdminAuthorizations() {
|
|||||||
queryFn: () => api.listUsers({ search: search || undefined, limit: PAGE_SIZE, offset: 0 }),
|
queryFn: () => api.listUsers({ search: search || undefined, limit: PAGE_SIZE, offset: 0 }),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timeoutId = window.setTimeout(() => {
|
||||||
|
setSearch(normalizeSearchDigits(searchDraft).trim());
|
||||||
|
}, 400);
|
||||||
|
|
||||||
|
return () => window.clearTimeout(timeoutId);
|
||||||
|
}, [searchDraft]);
|
||||||
|
|
||||||
const authQuery = useQuery({
|
const authQuery = useQuery({
|
||||||
queryKey: ["admin", "authorizations", selectedUserId],
|
queryKey: ["admin", "authorizations", selectedUserId],
|
||||||
queryFn: () => api.getUserAuthorization(selectedUserId as number),
|
queryFn: () => api.getUserAuthorization(selectedUserId as number),
|
||||||
@@ -104,18 +117,13 @@ export default function AdminAuthorizations() {
|
|||||||
<CardDescription>نام، موبایل، ایمیل یا نام کاربری را جستجو کنید.</CardDescription>
|
<CardDescription>نام، موبایل، ایمیل یا نام کاربری را جستجو کنید.</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-4" dir="ltr">
|
<CardContent className="space-y-4" dir="ltr">
|
||||||
<div className="flex gap-2">
|
<div className="relative">
|
||||||
<Button type="button" onClick={() => setSearch(searchDraft.trim())} size="icon" aria-label="جستجو">
|
<Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
||||||
<Search className="h-5 w-5 bold" />
|
|
||||||
</Button>
|
|
||||||
<Input
|
<Input
|
||||||
value={searchDraft}
|
value={searchDraft}
|
||||||
onChange={(event) => setSearchDraft(event.target.value)}
|
onChange={(event) => setSearchDraft(event.target.value)}
|
||||||
onKeyDown={(event) => {
|
|
||||||
if (event.key === "Enter") setSearch(searchDraft.trim());
|
|
||||||
}}
|
|
||||||
placeholder="جستجو..."
|
placeholder="جستجو..."
|
||||||
className="text-right"
|
className="pl-10 text-right"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{usersQuery.isLoading ? (
|
{usersQuery.isLoading ? (
|
||||||
@@ -140,7 +148,10 @@ export default function AdminAuthorizations() {
|
|||||||
</Badge>
|
</Badge>
|
||||||
<span className="font-medium">{fullName(item)}</span>
|
<span className="font-medium">{fullName(item)}</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="mt-1 text-xs text-muted-foreground">{item.mobile || item.email || item.username}</p>
|
<div className="mt-2 space-y-1 text-xs text-muted-foreground">
|
||||||
|
<p dir="ltr" className="text-right">{item.mobile || "بدون شماره موبایل"}</p>
|
||||||
|
<p>{item.email || item.username}</p>
|
||||||
|
</div>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user