3x-ui/frontend/src/components
MHSanaei ef36757b88
refactor(frontend): port clients to react+ts
Step 6 of the planned vue->react migration. Clients is the biggest
data-CRUD page in the panel (1.1k-line ClientsPage, 4 modals, full
table + mobile card list, WebSocket-driven realtime traffic + online
updates).

New shared infra (lives alongside vue twins until inbounds migrates):

* hooks/useClients.ts — clients + inbounds list, CRUD + bulk delete +
  attach/detach + traffic reset, with WebSocket event handlers
  (traffic, client_stats, invalidate) and a small debounced refresh
  on the invalidate event. State managed via setState; the live
  client_stats event merges traffic snapshots row-by-row through a
  ref to avoid stale closure issues.
* hooks/useDatepicker.ts — singleton "gregorian"/"jalalian" cache
  with subscribe/notify so multiple components can read the panel's
  Calendar Type without re-fetching. Mirrors useDatepicker.js.
* components/DateTimePicker.tsx — AntD DatePicker wrapper.
  vue3-persian-datetime-picker has no React port; the Jalali UI
  calendar is deferred (read-only Jalali display via IntlUtil
  formatDate still works). The vue twin stays for inbounds.
* pages/inbounds/QrPanel.tsx — copy/download/copy-as-png QR helper
  shared between clients (qr modal) and inbounds (still on vue).
  Vue twin stays alive at QrPanel.vue.
* models/inbound.ts — slim port: only the TLS_FLOW_CONTROL constant
  the clients form needs. The full inbound model stays as
  inbound.js for now; inbounds will pull it in as inbound.ts.

The clients page itself uses Modal.useModal() for all confirm
dialogs (delete, bulk-delete, reset-traffic, delDepleted, reset-all)
so the dialogs render themed. Filter state persists to
localStorage under clientsFilterState. Sort + pagination state is
local; pageSize seeds from /panel/setting/defaultSettings.

The four modals share a controlled "open/onOpenChange" pattern
that replaces vue's v-model:open. ClientFormModal computes
attach/detach diffs from the inbound multi-select on submit; the
parent's onSave callback routes them through useClients's attach()/
detach() after the main update succeeds.

ESLint config: turned off four react-hooks v7 rules
(react-compiler, preserve-manual-memoization, set-state-in-effect,
purity). They're all React-Compiler-driven informational rules; we
don't run the compiler and the patterns they flag (initial-fetch
useEffect, derived computations using Date.now, inline arrow event
handlers) are all idiomatic React. Disabling globally instead of
per-line keeps the diff readable.
2026-05-21 22:03:31 +02:00
..
AppSidebar.css refactor(frontend): port api-docs to react+ts 2026-05-21 21:26:28 +02:00
AppSidebar.tsx refactor(frontend): port api-docs to react+ts 2026-05-21 21:26:28 +02:00
AppSidebar.vue Feat/multi inbound clients (#4469) 2026-05-19 12:20:24 +02:00
CustomStatistic.css refactor(frontend): port nodes to react+ts 2026-05-21 21:34:46 +02:00
CustomStatistic.tsx refactor(frontend): port nodes to react+ts 2026-05-21 21:34:46 +02:00
CustomStatistic.vue feat(xray/dns): align DNS settings with Xray docs + UI polish 2026-05-10 17:03:11 +02:00
DateTimePicker.tsx refactor(frontend): port clients to react+ts 2026-05-21 22:03:31 +02:00
DateTimePicker.vue feat(frontend): refresh dark theme + redesign login page 2026-05-11 01:10:05 +02:00
FinalMaskForm.vue feat(xray/dns): align DNS settings with Xray docs + UI polish 2026-05-10 17:03:11 +02:00
InfinityIcon.vue feat(xray/dns): align DNS settings with Xray docs + UI polish 2026-05-10 17:03:11 +02:00
JsonEditor.vue feat(json): swap raw textareas for a CodeMirror 6 JsonEditor 2026-05-14 00:02:59 +02:00
PromptModal.vue feat(xray/dns): align DNS settings with Xray docs + UI polish 2026-05-10 17:03:11 +02:00
SettingListItem.tsx refactor(frontend): port settings to react+ts 2026-05-21 21:48:15 +02:00
SettingListItem.vue feat(xray/dns): align DNS settings with Xray docs + UI polish 2026-05-10 17:03:11 +02:00
Sparkline.css refactor(frontend): port nodes to react+ts 2026-05-21 21:34:46 +02:00
Sparkline.tsx refactor(frontend): port nodes to react+ts 2026-05-21 21:34:46 +02:00
Sparkline.vue fix(graphs): increase y-axis paddingLeft from 32 to 56 to prevent clipped labels (#4309) 2026-05-13 01:47:54 +02:00
TableSortable.vue feat(xray/dns): align DNS settings with Xray docs + UI polish 2026-05-10 17:03:11 +02:00
TextModal.vue feat(xray/dns): align DNS settings with Xray docs + UI polish 2026-05-10 17:03:11 +02:00