mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-17 07:37:15 +00:00
feat(routing): add client picker to user rules (#6271)
* feat(routing): add client picker to user rules Replace the free-text user criterion with a searchable multi-select backed by existing panel clients. Preserve saved values that no longer exist so editing legacy rules remains lossless. * feat(routing): polish user picker states Align the routing user selector with the inbound-tag multi-select, including search, clear, loading, empty, and error states. Localize the new copy across every supported locale and cover legacy saved users with a regression test. * fix(routing): keep custom user identifiers Use tags mode with comma tokenization so the user picker suggests panel clients without rejecting HTTP, Mixed, or raw-template identifiers. Restore the comma hint and cover custom entries with a regression test.
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { HttpUtil } from '@/utils';
|
||||
import { parseMsg } from '@/utils/zodValidate';
|
||||
import { keys } from '@/api/queryKeys';
|
||||
import { ClientRecordSchema, type ClientRecord } from '@/schemas/client';
|
||||
|
||||
const ClientRecordListSchema = z
|
||||
.array(ClientRecordSchema)
|
||||
.nullable()
|
||||
.transform((value) => value ?? []);
|
||||
|
||||
async function fetchClients(): Promise<ClientRecord[]> {
|
||||
const msg = await HttpUtil.get('/panel/api/clients/list', undefined, { silent: true });
|
||||
if (!msg?.success) throw new Error(msg?.msg || 'Failed to load clients');
|
||||
const validated = parseMsg(msg, ClientRecordListSchema, 'clients/list');
|
||||
return validated.obj ?? [];
|
||||
}
|
||||
|
||||
export function useClientOptions(enabled = true) {
|
||||
return useQuery({
|
||||
queryKey: keys.clients.all(),
|
||||
queryFn: fetchClients,
|
||||
enabled,
|
||||
staleTime: 30_000,
|
||||
select: (clients) =>
|
||||
clients
|
||||
.map((client) => client.email.trim())
|
||||
.filter(Boolean)
|
||||
.sort((a, b) => a.localeCompare(b)),
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user