Add search, filters, pagination to admin users table
- Add emailVerified filter (true/false/any) to UsersSearch component - Wire emailVerified param through page searchParams, where clause, and pageUrl helper - Preserve emailVerified in pagination links alongside existing search/role/balance params - Update pagination label to "Страница X из Y · Всего: N" Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,20 +16,23 @@ const inputStyle: React.CSSProperties = {
|
||||
export function UsersSearch({
|
||||
initialSearch,
|
||||
initialRole,
|
||||
initialEmailVerified,
|
||||
initialBalance,
|
||||
}: {
|
||||
initialSearch: string;
|
||||
initialRole: string;
|
||||
initialEmailVerified: string;
|
||||
initialBalance: string;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const [, startTransition] = useTransition();
|
||||
|
||||
function update(search: string, role: string, balance: string) {
|
||||
function update(search: string, role: string, emailVerified: string, balance: string) {
|
||||
const params = new URLSearchParams();
|
||||
if (search) params.set("search", search);
|
||||
if (role) params.set("role", role);
|
||||
if (emailVerified) params.set("emailVerified", emailVerified);
|
||||
if (balance) params.set("balance", balance);
|
||||
startTransition(() => router.push(`${pathname}?${params.toString()}`));
|
||||
}
|
||||
@@ -45,7 +48,7 @@ export function UsersSearch({
|
||||
onFocus={(e) => (e.currentTarget.style.borderColor = "var(--foreground)")}
|
||||
onBlur={(e) => {
|
||||
e.currentTarget.style.borderColor = "var(--border)";
|
||||
update(e.currentTarget.value.trim(), initialRole, initialBalance);
|
||||
update(e.currentTarget.value.trim(), initialRole, initialEmailVerified, initialBalance);
|
||||
}}
|
||||
onKeyDown={(e) => { if (e.key === "Enter") e.currentTarget.blur(); }}
|
||||
/>
|
||||
@@ -53,7 +56,7 @@ export function UsersSearch({
|
||||
|
||||
<select
|
||||
defaultValue={initialRole}
|
||||
onChange={(e) => update(initialSearch, e.target.value, initialBalance)}
|
||||
onChange={(e) => update(initialSearch, e.target.value, initialEmailVerified, initialBalance)}
|
||||
style={{ ...inputStyle, appearance: "none", cursor: "pointer" }}
|
||||
onFocus={(e) => (e.currentTarget.style.borderColor = "var(--foreground)")}
|
||||
onBlur={(e) => (e.currentTarget.style.borderColor = "var(--border)")}
|
||||
@@ -64,9 +67,21 @@ export function UsersSearch({
|
||||
<option value="admin">Администраторы</option>
|
||||
</select>
|
||||
|
||||
<select
|
||||
defaultValue={initialEmailVerified}
|
||||
onChange={(e) => update(initialSearch, initialRole, e.target.value, initialBalance)}
|
||||
style={{ ...inputStyle, appearance: "none", cursor: "pointer" }}
|
||||
onFocus={(e) => (e.currentTarget.style.borderColor = "var(--foreground)")}
|
||||
onBlur={(e) => (e.currentTarget.style.borderColor = "var(--border)")}
|
||||
>
|
||||
<option value="">Любой статус</option>
|
||||
<option value="true">Email подтверждён</option>
|
||||
<option value="false">Не подтверждён</option>
|
||||
</select>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => update(initialSearch, initialRole, initialBalance === "nonzero" ? "" : "nonzero")}
|
||||
onClick={() => update(initialSearch, initialRole, initialEmailVerified, initialBalance === "nonzero" ? "" : "nonzero")}
|
||||
className="text-xs px-3"
|
||||
style={{
|
||||
border: "2px solid var(--border)",
|
||||
@@ -78,7 +93,7 @@ export function UsersSearch({
|
||||
С балансом
|
||||
</button>
|
||||
|
||||
{(initialSearch || initialRole || initialBalance) && (
|
||||
{(initialSearch || initialRole || initialEmailVerified || initialBalance) && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => startTransition(() => router.push(pathname))}
|
||||
|
||||
Reference in New Issue
Block a user