@tinyrack/tinyauth-server 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/services/account-selection.service.d.ts.map +1 -1
- package/dist/services/account-selection.service.js +5 -2
- package/dist/services/account-selection.service.js.map +1 -1
- package/dist/services/oauth-authorize.service.d.ts.map +1 -1
- package/dist/services/oauth-authorize.service.js +3 -1
- package/dist/services/oauth-authorize.service.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/2fa-DZSOQLyd.js +2 -0
- package/public/assets/{2fa-Cteolf9l.js.map → 2fa-DZSOQLyd.js.map} +1 -1
- package/public/assets/2fa-DvD9N_wj.js +2 -0
- package/public/assets/{2fa-BMEIiDXv.js.map → 2fa-DvD9N_wj.js.map} +1 -1
- package/public/assets/{2fa-BhCgCfEc.js → 2fa-P8YqnDXC.js} +2 -2
- package/public/assets/{2fa-BhCgCfEc.js.map → 2fa-P8YqnDXC.js.map} +1 -1
- package/public/assets/{2fa-E0x3Samn.js → 2fa-fLX-LED8.js} +2 -2
- package/public/assets/{2fa-E0x3Samn.js.map → 2fa-fLX-LED8.js.map} +1 -1
- package/public/assets/{admin-CXJ0z2QN.js → admin-BLPp8bT8.js} +2 -2
- package/public/assets/{admin-CXJ0z2QN.js.map → admin-BLPp8bT8.js.map} +1 -1
- package/public/assets/{consent-C-h_pWHQ.js → consent-CjXe4bU5.js} +2 -2
- package/public/assets/{consent-C-h_pWHQ.js.map → consent-CjXe4bU5.js.map} +1 -1
- package/public/assets/consent-Cq6tCfwA.js +2 -0
- package/public/assets/{consent-B17hGrta.js.map → consent-Cq6tCfwA.js.map} +1 -1
- package/public/assets/{email-DjE7mqnX.js → email-CpOX6Ig_.js} +2 -2
- package/public/assets/email-CpOX6Ig_.js.map +1 -0
- package/public/assets/email-DvD9N_wj.js +2 -0
- package/public/assets/email-DvD9N_wj.js.map +1 -0
- package/public/assets/{error-BKXsXhdR.js → error-DMzYyopT.js} +2 -2
- package/public/assets/{error-BKXsXhdR.js.map → error-DMzYyopT.js.map} +1 -1
- package/public/assets/forgot-DvD9N_wj.js +2 -0
- package/public/assets/{forgot-BMEIiDXv.js.map → forgot-DvD9N_wj.js.map} +1 -1
- package/public/assets/{forgot-C9zSfaX9.js → forgot-RbSzzjWF.js} +2 -2
- package/public/assets/{forgot-C9zSfaX9.js.map → forgot-RbSzzjWF.js.map} +1 -1
- package/public/assets/{index-BmfaaNx6.js → index-CgkA6nnx.js} +3 -3
- package/public/assets/index-CgkA6nnx.js.map +1 -0
- package/public/assets/{login-DG1Yfmb8.js → login-BQI7QY9W.js} +2 -2
- package/public/assets/login-BQI7QY9W.js.map +1 -0
- package/public/assets/login-DvD9N_wj.js +2 -0
- package/public/assets/login-DvD9N_wj.js.map +1 -0
- package/public/assets/{passkey-BDrX3jVg.js → passkey-C0BKdldQ.js} +2 -2
- package/public/assets/passkey-C0BKdldQ.js.map +1 -0
- package/public/assets/{passkey-C-h8Fvqn.js → passkey-D9qQ8xoR.js} +2 -2
- package/public/assets/passkey-D9qQ8xoR.js.map +1 -0
- package/public/assets/password-CqjbZggE.js +2 -0
- package/public/assets/password-CqjbZggE.js.map +1 -0
- package/public/assets/password-DvD9N_wj.js +2 -0
- package/public/assets/password-DvD9N_wj.js.map +1 -0
- package/public/assets/{profile-8buOY6GT.js → profile-B5qQlPwW.js} +2 -2
- package/public/assets/{profile-8buOY6GT.js.map → profile-B5qQlPwW.js.map} +1 -1
- package/public/assets/profile-fwH7_EJ0.js +2 -0
- package/public/assets/{profile-DcpL_XUt.js.map → profile-fwH7_EJ0.js.map} +1 -1
- package/public/assets/{recovery-Csf6dtvj.js → recovery-DqEhUHzv.js} +2 -2
- package/public/assets/{recovery-Csf6dtvj.js.map → recovery-DqEhUHzv.js.map} +1 -1
- package/public/assets/{register-X6dycne4.js → register-CntgI-rd.js} +2 -2
- package/public/assets/register-CntgI-rd.js.map +1 -0
- package/public/assets/register-DvD9N_wj.js +2 -0
- package/public/assets/register-DvD9N_wj.js.map +1 -0
- package/public/assets/{reset-1nsqPlxL.js → reset-BK1XYJiv.js} +2 -2
- package/public/assets/{reset-1nsqPlxL.js.map → reset-BK1XYJiv.js.map} +1 -1
- package/public/assets/reset-DvD9N_wj.js +2 -0
- package/public/assets/{reset-BMEIiDXv.js.map → reset-DvD9N_wj.js.map} +1 -1
- package/public/assets/{select-CDdb3jyc.js → select-DeUoTgDw.js} +2 -2
- package/public/assets/{select-CDdb3jyc.js.map → select-DeUoTgDw.js.map} +1 -1
- package/public/assets/select-DvD9N_wj.js +2 -0
- package/public/assets/{select-BMEIiDXv.js.map → select-DvD9N_wj.js.map} +1 -1
- package/public/assets/{terms-CUhvMN9k.js → terms-CPEuXMaO.js} +2 -2
- package/public/assets/{terms-CUhvMN9k.js.map → terms-CPEuXMaO.js.map} +1 -1
- package/public/assets/terms-fwH7_EJ0.js +2 -0
- package/public/assets/{terms-DcpL_XUt.js.map → terms-fwH7_EJ0.js.map} +1 -1
- package/public/assets/{totp-DB9WqW4V.js → totp-B1ebEiOW.js} +2 -2
- package/public/assets/totp-B1ebEiOW.js.map +1 -0
- package/public/assets/{totp-UDT2P91H.js → totp-DWWZe-tJ.js} +2 -2
- package/public/assets/totp-DWWZe-tJ.js.map +1 -0
- package/public/assets/{use-totp-setup-9fktn_he.js → use-totp-setup-Z96pOMXt.js} +2 -2
- package/public/assets/{use-totp-setup-9fktn_he.js.map → use-totp-setup-Z96pOMXt.js.map} +1 -1
- package/public/assets/{useMutation-Iu4AJCB4.js → useMutation-Biy2-pH_.js} +2 -2
- package/public/assets/{useMutation-Iu4AJCB4.js.map → useMutation-Biy2-pH_.js.map} +1 -1
- package/public/assets/{users-Bi7gjreq.js → users-YtDGJlDl.js} +2 -2
- package/public/assets/{users-Bi7gjreq.js.map → users-YtDGJlDl.js.map} +1 -1
- package/public/index.html +1 -1
- package/public/assets/2fa-BMEIiDXv.js +0 -2
- package/public/assets/2fa-Cteolf9l.js +0 -2
- package/public/assets/consent-B17hGrta.js +0 -2
- package/public/assets/email-BMEIiDXv.js +0 -2
- package/public/assets/email-BMEIiDXv.js.map +0 -1
- package/public/assets/email-DjE7mqnX.js.map +0 -1
- package/public/assets/forgot-BMEIiDXv.js +0 -2
- package/public/assets/index-BmfaaNx6.js.map +0 -1
- package/public/assets/login-BMEIiDXv.js +0 -2
- package/public/assets/login-BMEIiDXv.js.map +0 -1
- package/public/assets/login-DG1Yfmb8.js.map +0 -1
- package/public/assets/passkey-BDrX3jVg.js.map +0 -1
- package/public/assets/passkey-C-h8Fvqn.js.map +0 -1
- package/public/assets/password-86C-hCze.js +0 -2
- package/public/assets/password-86C-hCze.js.map +0 -1
- package/public/assets/password-BMEIiDXv.js +0 -2
- package/public/assets/password-BMEIiDXv.js.map +0 -1
- package/public/assets/profile-DcpL_XUt.js +0 -2
- package/public/assets/register-BMEIiDXv.js +0 -2
- package/public/assets/register-BMEIiDXv.js.map +0 -1
- package/public/assets/register-X6dycne4.js.map +0 -1
- package/public/assets/reset-BMEIiDXv.js +0 -2
- package/public/assets/select-BMEIiDXv.js +0 -2
- package/public/assets/terms-DcpL_XUt.js +0 -2
- package/public/assets/totp-DB9WqW4V.js.map +0 -1
- package/public/assets/totp-UDT2P91H.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-totp-setup-9fktn_he.js","names":["e","e","a","m","n"],"sources":["../../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@19.2.7_react@19.2.7__react@19.2.7/node_modules/@phosphor-icons/react/dist/defs/Copy.es.js","../../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@19.2.7_react@19.2.7__react@19.2.7/node_modules/@phosphor-icons/react/dist/defs/Info.es.js","../../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@19.2.7_react@19.2.7__react@19.2.7/node_modules/@phosphor-icons/react/dist/csr/Copy.es.js","../../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@19.2.7_react@19.2.7__react@19.2.7/node_modules/@phosphor-icons/react/dist/csr/Info.es.js","../../../frontend/src/components/totp/recovery-codes-step.tsx","../../../frontend/src/components/totp/verify-step.tsx","../../../frontend/src/components/totp/qr-step.tsx","../../../frontend/src/features/totp/use-totp-setup.ts"],"sourcesContent":["import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,40V168H168V88H88V40Z\", opacity: \"0.2\" }), /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32Zm-8,128H176V88a8,8,0,0,0-8-8H96V48H208Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,34H88a6,6,0,0,0-6,6V82H40a6,6,0,0,0-6,6V216a6,6,0,0,0,6,6H168a6,6,0,0,0,6-6V174h42a6,6,0,0,0,6-6V40A6,6,0,0,0,216,34ZM162,210H46V94H162Zm48-48H174V88a6,6,0,0,0-6-6H94V46H210Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,36H88a4,4,0,0,0-4,4V84H40a4,4,0,0,0-4,4V216a4,4,0,0,0,4,4H168a4,4,0,0,0,4-4V172h44a4,4,0,0,0,4-4V40A4,4,0,0,0,216,36ZM164,212H44V92H164Zm48-48H172V88a4,4,0,0,0-4-4H92V44H212Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M108,84a16,16,0,1,1,16,16A16,16,0,0,1,108,84Zm128,44A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128Zm-72,36.68V132a20,20,0,0,0-20-20,12,12,0,0,0-4,23.32V168a20,20,0,0,0,20,20,12,12,0,0,0,4-23.32Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,128a96,96,0,1,1-96-96A96,96,0,0,1,224,128Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M144,176a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176Zm88-48A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128ZM124,96a12,12,0,1,0-12-12A12,12,0,0,0,124,96Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm-4,48a12,12,0,1,1-12,12A12,12,0,0,1,124,72Zm12,112a16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40a8,8,0,0,1,0,16Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M142,176a6,6,0,0,1-6,6,14,14,0,0,1-14-14V128a2,2,0,0,0-2-2,6,6,0,0,1,0-12,14,14,0,0,1,14,14v40a2,2,0,0,0,2,2A6,6,0,0,1,142,176ZM124,94a10,10,0,1,0-10-10A10,10,0,0,0,124,94Zm106,34A102,102,0,1,1,128,26,102.12,102.12,0,0,1,230,128Zm-12,0a90,90,0,1,0-90,90A90.1,90.1,0,0,0,218,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-40a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176ZM112,84a12,12,0,1,1,12,12A12,12,0,0,1,112,84Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M140,176a4,4,0,0,1-4,4,12,12,0,0,1-12-12V128a4,4,0,0,0-4-4,4,4,0,0,1,0-8,12,12,0,0,1,12,12v40a4,4,0,0,0,4,4A4,4,0,0,1,140,176ZM124,92a8,8,0,1,0-8-8A8,8,0,0,0,124,92Zm104,36A100,100,0,1,1,128,28,100.11,100.11,0,0,1,228,128Zm-8,0a92,92,0,1,0-92,92A92.1,92.1,0,0,0,220,128Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as o from \"react\";\nimport a from \"../lib/IconBase.es.js\";\nimport m from \"../defs/Copy.es.js\";\nconst e = o.forwardRef((r, t) => /* @__PURE__ */ o.createElement(a, { ref: t, ...r, weights: m }));\ne.displayName = \"CopyIcon\";\nconst s = e;\nexport {\n s as Copy,\n e as CopyIcon\n};\n","import * as o from \"react\";\nimport n from \"../lib/IconBase.es.js\";\nimport a from \"../defs/Info.es.js\";\nconst e = o.forwardRef((r, t) => /* @__PURE__ */ o.createElement(n, { ref: t, ...r, weights: a }));\ne.displayName = \"InfoIcon\";\nconst c = e;\nexport {\n c as Info,\n e as InfoIcon\n};\n","import { CheckIcon, CopyIcon, WarningIcon } from '@phosphor-icons/react';\nimport { useCallback, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface RecoveryCodesStepProps {\n recoveryCodes: string[];\n onConfirm: () => void;\n isLoading?: boolean;\n className?: string;\n}\n\nexport function RecoveryCodesStep({\n recoveryCodes,\n onConfirm,\n isLoading = false,\n className = '',\n}: RecoveryCodesStepProps) {\n const { t } = useTranslation();\n const [copied, setCopied] = useState(false);\n const [confirmed, setConfirmed] = useState(false);\n\n const handleCopy = useCallback(async () => {\n const text = recoveryCodes.join('\\n');\n await navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, [recoveryCodes]);\n\n return (\n <div className={`space-y-3 ${className}`}>\n <p className=\"text-center text-base-content/60 text-xs\">\n {t('setupTotp.recoveryCodes.description')}\n </p>\n\n <div\n className=\"grid grid-cols-2 gap-2 rounded-lg bg-base-200 p-3\"\n data-testid=\"recovery-codes-grid\"\n >\n {recoveryCodes.map((code) => (\n <code\n className=\"rounded bg-base-300 px-2 py-1 text-center font-mono text-sm\"\n key={code}\n >\n {code}\n </code>\n ))}\n </div>\n\n <div className=\"flex items-start gap-2 rounded-lg bg-warning/10 p-2.5 text-warning\">\n <WarningIcon className=\"mt-0.5 size-4 shrink-0\" weight=\"fill\" />\n <p className=\"text-xs\">{t('setupTotp.recoveryCodes.warning')}</p>\n </div>\n\n <button\n className=\"btn btn-sm btn-outline btn-block gap-2\"\n onClick={handleCopy}\n type=\"button\"\n >\n {copied ? (\n <>\n <CheckIcon className=\"size-4\" />\n {t('setupTotp.recoveryCodes.copied')}\n </>\n ) : (\n <>\n <CopyIcon className=\"size-4\" />\n {t('setupTotp.recoveryCodes.copy')}\n </>\n )}\n </button>\n\n <label className=\"flex cursor-pointer items-center gap-2\">\n <input\n checked={confirmed}\n className=\"checkbox checkbox-sm\"\n data-testid=\"recovery-codes-confirm\"\n disabled={isLoading}\n onChange={(event) => setConfirmed(event.target.checked)}\n type=\"checkbox\"\n />\n <span className=\"text-sm\">\n {t('setupTotp.recoveryCodes.confirmCheckbox')}\n </span>\n </label>\n\n <button\n className=\"btn btn-sm btn-primary btn-block\"\n data-testid=\"recovery-codes-submit\"\n disabled={!confirmed || isLoading}\n onClick={onConfirm}\n type=\"button\"\n >\n {isLoading ? (\n <span className=\"loading loading-spinner loading-sm\" />\n ) : (\n t('setupTotp.recoveryCodes.confirm')\n )}\n </button>\n </div>\n );\n}\n","import { standardSchemaResolver } from '@hookform/resolvers/standard-schema';\nimport { useCallback, useMemo, useRef } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\nimport { z } from 'zod';\nimport { SubmitButton } from '#frontend/components/auth/submit-button.tsx';\nimport {\n PinInput,\n type PinInputRef,\n} from '#frontend/components/ui/pin-input.tsx';\n\nexport interface VerifyStepProps {\n onSubmit: (code: string) => Promise<void>;\n onBack?: (() => void) | undefined;\n isPending: boolean;\n invalidMessage?: string | undefined;\n submitLabel?: string | undefined;\n pendingText?: string | undefined;\n backLabel?: string | undefined;\n className?: string;\n}\n\ntype VerifyFormValues = {\n code: string;\n};\n\nexport function VerifyStep({\n onSubmit,\n onBack,\n isPending,\n invalidMessage,\n submitLabel,\n pendingText,\n backLabel,\n className = '',\n}: VerifyStepProps) {\n const { t } = useTranslation();\n const pinInputRef = useRef<PinInputRef>(null);\n\n const verifySchema = useMemo(\n () =>\n z.object({\n code: z\n .string()\n .length(6, t('validation.totp.length'))\n .regex(/^\\d{6}$/, t('validation.totp.digits')),\n }),\n [t],\n );\n\n const {\n setValue,\n setError,\n handleSubmit,\n watch,\n formState: { errors },\n } = useForm<VerifyFormValues>({\n defaultValues: { code: '' },\n resolver: standardSchemaResolver(verifySchema),\n });\n\n const codeValue = watch('code');\n\n const handleFormSubmit = useCallback(\n async (values: VerifyFormValues) => {\n try {\n await onSubmit(values.code);\n } catch {\n setError('code', {\n type: 'manual',\n message: invalidMessage ?? t('setupTotp.error.invalid'),\n });\n setValue('code', '');\n pinInputRef.current?.focus();\n }\n },\n [invalidMessage, onSubmit, setError, setValue, t],\n );\n\n return (\n <div className={className}>\n <form\n className=\"flex flex-col gap-3\"\n onSubmit={handleSubmit(handleFormSubmit)}\n >\n <PinInput\n autoFocus\n error={errors.code}\n length={6}\n onChange={(value) => setValue('code', value)}\n onComplete={() => handleSubmit(handleFormSubmit)()}\n ref={pinInputRef}\n value={codeValue}\n />\n\n <SubmitButton\n className=\"btn-sm mt-1\"\n isPending={isPending}\n pendingText={pendingText ?? t('setupTotp.verifying')}\n >\n {submitLabel ?? t('setupTotp.verify')}\n </SubmitButton>\n </form>\n\n {onBack && (\n <div className=\"mt-3 text-center\">\n <button\n className=\"btn btn-ghost btn-xs\"\n data-testid=\"totp-verify-back\"\n disabled={isPending}\n onClick={onBack}\n type=\"button\"\n >\n {backLabel ?? t('setupTotp.back')}\n </button>\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { TotpSetupData } from '#frontend/features/totp/use-totp-setup.ts';\n\nexport interface QrStepProps {\n setupData: TotpSetupData;\n onNext: () => void;\n additionalActions?: ReactNode;\n className?: string;\n}\n\nexport function QrStep({\n setupData,\n onNext,\n additionalActions,\n className = '',\n}: QrStepProps) {\n const { t } = useTranslation();\n\n return (\n <div className={`space-y-3 ${className}`}>\n <p className=\"text-center text-base-content/60 text-xs\">\n {t('setupTotp.qrDescription')}\n </p>\n\n <div className=\"flex justify-center\">\n <img\n alt=\"TOTP QR Code\"\n className=\"h-40 w-40 rounded-lg border\"\n src={setupData.qr_code}\n />\n </div>\n\n <div className=\"collapse-arrow collapse bg-base-200\">\n <input type=\"checkbox\" />\n <div className=\"collapse-title font-medium text-xs\">\n {t('setupTotp.manualEntry')}\n </div>\n <div className=\"collapse-content\">\n <code className=\"block break-all rounded bg-base-300 p-1.5 text-xs\">\n {setupData.secret}\n </code>\n </div>\n </div>\n\n <button\n className=\"btn btn-sm btn-primary btn-block\"\n data-testid=\"totp-qr-next\"\n onClick={onNext}\n type=\"button\"\n >\n {t('setupTotp.next')}\n </button>\n\n {additionalActions}\n </div>\n );\n}\n","import { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { getSessionQueryOptions } from '#frontend/queries/session.ts';\nimport {\n confirmTotpSetupMutationOptions,\n startTotpSetupMutationOptions,\n type TotpConfirmResponse,\n type TotpSetupResponse,\n type TotpSetupVerifyResponse,\n verifyTotpMutationOptions,\n} from '#frontend/queries/totp.ts';\n\nexport type TotpSetupStep = 'loading' | 'qr' | 'verify' | 'recovery' | 'error';\n\nexport interface TotpSetupData {\n qr_code: string;\n secret: string;\n}\n\nexport interface UseTotpSetupOptions {\n onSetupSuccess?: (data: TotpSetupResponse) => void;\n onSetupError?: (error: Error) => void;\n onVerifySuccess?: (data: TotpSetupVerifyResponse) => void;\n onVerifyError?: (error: Error) => void;\n onConfirmSuccess?: (data: TotpConfirmResponse) => void;\n onConfirmError?: (error: Error) => void;\n autoStart?: boolean;\n}\n\nexport interface UseTotpSetupReturn {\n step: TotpSetupStep;\n setupData: TotpSetupResponse | null;\n recoveryCodes: string[];\n isSetupPending: boolean;\n isVerifyPending: boolean;\n isConfirmPending: boolean;\n isPending: boolean;\n setupError: Error | null;\n verifyError: Error | null;\n confirmError: Error | null;\n startSetup: () => void;\n verify: (code: string) => Promise<TotpSetupVerifyResponse>;\n goToQr: () => void;\n goToVerify: () => void;\n confirmRecoveryCodes: () => Promise<TotpConfirmResponse>;\n reset: () => void;\n}\n\nexport function useTotpSetup(\n options: UseTotpSetupOptions = {},\n): UseTotpSetupReturn {\n const {\n onSetupSuccess,\n onSetupError,\n onVerifySuccess,\n onVerifyError,\n onConfirmSuccess,\n onConfirmError,\n autoStart = false,\n } = options;\n\n const queryClient = useQueryClient();\n const [step, setStep] = useState<TotpSetupStep>(autoStart ? 'loading' : 'qr');\n const [setupData, setSetupData] = useState<TotpSetupResponse | null>(null);\n const [recoveryCodes, setRecoveryCodes] = useState<string[]>([]);\n const setupInitiatedRef = useRef(false);\n\n const setupMutation = useMutation({\n ...startTotpSetupMutationOptions,\n onSuccess: (data) => {\n setSetupData(data);\n setStep('qr');\n onSetupSuccess?.(data);\n },\n onError: (error) => {\n setStep('error');\n onSetupError?.(error);\n },\n });\n\n const verifyMutation = useMutation({\n ...verifyTotpMutationOptions,\n onSuccess: (data) => {\n // Do NOT invalidate session here - TOTP is not fully enabled yet\n setRecoveryCodes(data.recovery_codes);\n setStep('recovery');\n onVerifySuccess?.(data);\n },\n onError: (error) => {\n onVerifyError?.(error);\n },\n });\n\n const confirmMutation = useMutation({\n ...confirmTotpSetupMutationOptions,\n onSuccess: (data) => {\n // Now TOTP is fully enabled, invalidate session\n queryClient.invalidateQueries({\n queryKey: getSessionQueryOptions.queryKey,\n });\n onConfirmSuccess?.(data);\n },\n onError: (error) => {\n onConfirmError?.(error);\n },\n });\n\n const startSetup = useCallback(() => {\n setupInitiatedRef.current = true;\n setStep('loading');\n setupMutation.mutate();\n }, [setupMutation]);\n\n const verify = useCallback(\n async (code: string) => {\n return verifyMutation.mutateAsync({ code });\n },\n [verifyMutation],\n );\n\n const goToQr = useCallback(() => {\n setStep('qr');\n }, []);\n\n const goToVerify = useCallback(() => {\n setStep('verify');\n }, []);\n\n const confirmRecoveryCodes = useCallback(async () => {\n return confirmMutation.mutateAsync();\n }, [confirmMutation]);\n\n const reset = useCallback(() => {\n setStep(autoStart ? 'loading' : 'qr');\n setSetupData(null);\n setRecoveryCodes([]);\n setupInitiatedRef.current = false;\n setupMutation.reset();\n verifyMutation.reset();\n confirmMutation.reset();\n }, [autoStart, setupMutation, verifyMutation, confirmMutation]);\n\n // Auto start setup on mount if enabled\n useEffect(() => {\n if (autoStart && !setupInitiatedRef.current && step === 'loading') {\n setupInitiatedRef.current = true;\n setupMutation.mutate();\n }\n }, [autoStart, step, setupMutation]);\n\n return {\n step,\n setupData,\n recoveryCodes,\n isSetupPending: setupMutation.isPending,\n isVerifyPending: verifyMutation.isPending,\n isConfirmPending: confirmMutation.isPending,\n isPending:\n setupMutation.isPending ||\n verifyMutation.isPending ||\n confirmMutation.isPending,\n setupError: setupMutation.error,\n verifyError: verifyMutation.error,\n confirmError: confirmMutation.error,\n startSetup,\n verify,\n goToQr,\n goToVerify,\n confirmRecoveryCodes,\n reset,\n };\n}\n"],"x_google_ignoreList":[0,1,2,3],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-totp-setup-Z96pOMXt.js","names":["e","e","a","m","n"],"sources":["../../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@19.2.7_react@19.2.7__react@19.2.7/node_modules/@phosphor-icons/react/dist/defs/Copy.es.js","../../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@19.2.7_react@19.2.7__react@19.2.7/node_modules/@phosphor-icons/react/dist/defs/Info.es.js","../../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@19.2.7_react@19.2.7__react@19.2.7/node_modules/@phosphor-icons/react/dist/csr/Copy.es.js","../../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@19.2.7_react@19.2.7__react@19.2.7/node_modules/@phosphor-icons/react/dist/csr/Info.es.js","../../../frontend/src/components/totp/recovery-codes-step.tsx","../../../frontend/src/components/totp/verify-step.tsx","../../../frontend/src/components/totp/qr-step.tsx","../../../frontend/src/features/totp/use-totp-setup.ts"],"sourcesContent":["import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,40V168H168V88H88V40Z\", opacity: \"0.2\" }), /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32Zm-8,128H176V88a8,8,0,0,0-8-8H96V48H208Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,34H88a6,6,0,0,0-6,6V82H40a6,6,0,0,0-6,6V216a6,6,0,0,0,6,6H168a6,6,0,0,0,6-6V174h42a6,6,0,0,0,6-6V40A6,6,0,0,0,216,34ZM162,210H46V94H162Zm48-48H174V88a6,6,0,0,0-6-6H94V46H210Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,36H88a4,4,0,0,0-4,4V84H40a4,4,0,0,0-4,4V216a4,4,0,0,0,4,4H168a4,4,0,0,0,4-4V172h44a4,4,0,0,0,4-4V40A4,4,0,0,0,216,36ZM164,212H44V92H164Zm48-48H172V88a4,4,0,0,0-4-4H92V44H212Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M108,84a16,16,0,1,1,16,16A16,16,0,0,1,108,84Zm128,44A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128Zm-72,36.68V132a20,20,0,0,0-20-20,12,12,0,0,0-4,23.32V168a20,20,0,0,0,20,20,12,12,0,0,0,4-23.32Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,128a96,96,0,1,1-96-96A96,96,0,0,1,224,128Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M144,176a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176Zm88-48A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128ZM124,96a12,12,0,1,0-12-12A12,12,0,0,0,124,96Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm-4,48a12,12,0,1,1-12,12A12,12,0,0,1,124,72Zm12,112a16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40a8,8,0,0,1,0,16Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M142,176a6,6,0,0,1-6,6,14,14,0,0,1-14-14V128a2,2,0,0,0-2-2,6,6,0,0,1,0-12,14,14,0,0,1,14,14v40a2,2,0,0,0,2,2A6,6,0,0,1,142,176ZM124,94a10,10,0,1,0-10-10A10,10,0,0,0,124,94Zm106,34A102,102,0,1,1,128,26,102.12,102.12,0,0,1,230,128Zm-12,0a90,90,0,1,0-90,90A90.1,90.1,0,0,0,218,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-40a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176ZM112,84a12,12,0,1,1,12,12A12,12,0,0,1,112,84Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M140,176a4,4,0,0,1-4,4,12,12,0,0,1-12-12V128a4,4,0,0,0-4-4,4,4,0,0,1,0-8,12,12,0,0,1,12,12v40a4,4,0,0,0,4,4A4,4,0,0,1,140,176ZM124,92a8,8,0,1,0-8-8A8,8,0,0,0,124,92Zm104,36A100,100,0,1,1,128,28,100.11,100.11,0,0,1,228,128Zm-8,0a92,92,0,1,0-92,92A92.1,92.1,0,0,0,220,128Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as o from \"react\";\nimport a from \"../lib/IconBase.es.js\";\nimport m from \"../defs/Copy.es.js\";\nconst e = o.forwardRef((r, t) => /* @__PURE__ */ o.createElement(a, { ref: t, ...r, weights: m }));\ne.displayName = \"CopyIcon\";\nconst s = e;\nexport {\n s as Copy,\n e as CopyIcon\n};\n","import * as o from \"react\";\nimport n from \"../lib/IconBase.es.js\";\nimport a from \"../defs/Info.es.js\";\nconst e = o.forwardRef((r, t) => /* @__PURE__ */ o.createElement(n, { ref: t, ...r, weights: a }));\ne.displayName = \"InfoIcon\";\nconst c = e;\nexport {\n c as Info,\n e as InfoIcon\n};\n","import { CheckIcon, CopyIcon, WarningIcon } from '@phosphor-icons/react';\nimport { useCallback, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface RecoveryCodesStepProps {\n recoveryCodes: string[];\n onConfirm: () => void;\n isLoading?: boolean;\n className?: string;\n}\n\nexport function RecoveryCodesStep({\n recoveryCodes,\n onConfirm,\n isLoading = false,\n className = '',\n}: RecoveryCodesStepProps) {\n const { t } = useTranslation();\n const [copied, setCopied] = useState(false);\n const [confirmed, setConfirmed] = useState(false);\n\n const handleCopy = useCallback(async () => {\n const text = recoveryCodes.join('\\n');\n await navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, [recoveryCodes]);\n\n return (\n <div className={`space-y-3 ${className}`}>\n <p className=\"text-center text-base-content/60 text-xs\">\n {t('setupTotp.recoveryCodes.description')}\n </p>\n\n <div\n className=\"grid grid-cols-2 gap-2 rounded-lg bg-base-200 p-3\"\n data-testid=\"recovery-codes-grid\"\n >\n {recoveryCodes.map((code) => (\n <code\n className=\"rounded bg-base-300 px-2 py-1 text-center font-mono text-sm\"\n key={code}\n >\n {code}\n </code>\n ))}\n </div>\n\n <div className=\"flex items-start gap-2 rounded-lg bg-warning/10 p-2.5 text-warning\">\n <WarningIcon className=\"mt-0.5 size-4 shrink-0\" weight=\"fill\" />\n <p className=\"text-xs\">{t('setupTotp.recoveryCodes.warning')}</p>\n </div>\n\n <button\n className=\"btn btn-sm btn-outline btn-block gap-2\"\n onClick={handleCopy}\n type=\"button\"\n >\n {copied ? (\n <>\n <CheckIcon className=\"size-4\" />\n {t('setupTotp.recoveryCodes.copied')}\n </>\n ) : (\n <>\n <CopyIcon className=\"size-4\" />\n {t('setupTotp.recoveryCodes.copy')}\n </>\n )}\n </button>\n\n <label className=\"flex cursor-pointer items-center gap-2\">\n <input\n checked={confirmed}\n className=\"checkbox checkbox-sm\"\n data-testid=\"recovery-codes-confirm\"\n disabled={isLoading}\n onChange={(event) => setConfirmed(event.target.checked)}\n type=\"checkbox\"\n />\n <span className=\"text-sm\">\n {t('setupTotp.recoveryCodes.confirmCheckbox')}\n </span>\n </label>\n\n <button\n className=\"btn btn-sm btn-primary btn-block\"\n data-testid=\"recovery-codes-submit\"\n disabled={!confirmed || isLoading}\n onClick={onConfirm}\n type=\"button\"\n >\n {isLoading ? (\n <span className=\"loading loading-spinner loading-sm\" />\n ) : (\n t('setupTotp.recoveryCodes.confirm')\n )}\n </button>\n </div>\n );\n}\n","import { standardSchemaResolver } from '@hookform/resolvers/standard-schema';\nimport { useCallback, useMemo, useRef } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\nimport { z } from 'zod';\nimport { SubmitButton } from '#frontend/components/auth/submit-button.tsx';\nimport {\n PinInput,\n type PinInputRef,\n} from '#frontend/components/ui/pin-input.tsx';\n\nexport interface VerifyStepProps {\n onSubmit: (code: string) => Promise<void>;\n onBack?: (() => void) | undefined;\n isPending: boolean;\n invalidMessage?: string | undefined;\n submitLabel?: string | undefined;\n pendingText?: string | undefined;\n backLabel?: string | undefined;\n className?: string;\n}\n\ntype VerifyFormValues = {\n code: string;\n};\n\nexport function VerifyStep({\n onSubmit,\n onBack,\n isPending,\n invalidMessage,\n submitLabel,\n pendingText,\n backLabel,\n className = '',\n}: VerifyStepProps) {\n const { t } = useTranslation();\n const pinInputRef = useRef<PinInputRef>(null);\n\n const verifySchema = useMemo(\n () =>\n z.object({\n code: z\n .string()\n .length(6, t('validation.totp.length'))\n .regex(/^\\d{6}$/, t('validation.totp.digits')),\n }),\n [t],\n );\n\n const {\n setValue,\n setError,\n handleSubmit,\n watch,\n formState: { errors },\n } = useForm<VerifyFormValues>({\n defaultValues: { code: '' },\n resolver: standardSchemaResolver(verifySchema),\n });\n\n const codeValue = watch('code');\n\n const handleFormSubmit = useCallback(\n async (values: VerifyFormValues) => {\n try {\n await onSubmit(values.code);\n } catch {\n setError('code', {\n type: 'manual',\n message: invalidMessage ?? t('setupTotp.error.invalid'),\n });\n setValue('code', '');\n pinInputRef.current?.focus();\n }\n },\n [invalidMessage, onSubmit, setError, setValue, t],\n );\n\n return (\n <div className={className}>\n <form\n className=\"flex flex-col gap-3\"\n onSubmit={handleSubmit(handleFormSubmit)}\n >\n <PinInput\n autoFocus\n error={errors.code}\n length={6}\n onChange={(value) => setValue('code', value)}\n onComplete={() => handleSubmit(handleFormSubmit)()}\n ref={pinInputRef}\n value={codeValue}\n />\n\n <SubmitButton\n className=\"btn-sm mt-1\"\n isPending={isPending}\n pendingText={pendingText ?? t('setupTotp.verifying')}\n >\n {submitLabel ?? t('setupTotp.verify')}\n </SubmitButton>\n </form>\n\n {onBack && (\n <div className=\"mt-3 text-center\">\n <button\n className=\"btn btn-ghost btn-xs\"\n data-testid=\"totp-verify-back\"\n disabled={isPending}\n onClick={onBack}\n type=\"button\"\n >\n {backLabel ?? t('setupTotp.back')}\n </button>\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { TotpSetupData } from '#frontend/features/totp/use-totp-setup.ts';\n\nexport interface QrStepProps {\n setupData: TotpSetupData;\n onNext: () => void;\n additionalActions?: ReactNode;\n className?: string;\n}\n\nexport function QrStep({\n setupData,\n onNext,\n additionalActions,\n className = '',\n}: QrStepProps) {\n const { t } = useTranslation();\n\n return (\n <div className={`space-y-3 ${className}`}>\n <p className=\"text-center text-base-content/60 text-xs\">\n {t('setupTotp.qrDescription')}\n </p>\n\n <div className=\"flex justify-center\">\n <img\n alt=\"TOTP QR Code\"\n className=\"h-40 w-40 rounded-lg border\"\n src={setupData.qr_code}\n />\n </div>\n\n <div className=\"collapse-arrow collapse bg-base-200\">\n <input type=\"checkbox\" />\n <div className=\"collapse-title font-medium text-xs\">\n {t('setupTotp.manualEntry')}\n </div>\n <div className=\"collapse-content\">\n <code className=\"block break-all rounded bg-base-300 p-1.5 text-xs\">\n {setupData.secret}\n </code>\n </div>\n </div>\n\n <button\n className=\"btn btn-sm btn-primary btn-block\"\n data-testid=\"totp-qr-next\"\n onClick={onNext}\n type=\"button\"\n >\n {t('setupTotp.next')}\n </button>\n\n {additionalActions}\n </div>\n );\n}\n","import { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { getSessionQueryOptions } from '#frontend/queries/session.ts';\nimport {\n confirmTotpSetupMutationOptions,\n startTotpSetupMutationOptions,\n type TotpConfirmResponse,\n type TotpSetupResponse,\n type TotpSetupVerifyResponse,\n verifyTotpMutationOptions,\n} from '#frontend/queries/totp.ts';\n\nexport type TotpSetupStep = 'loading' | 'qr' | 'verify' | 'recovery' | 'error';\n\nexport interface TotpSetupData {\n qr_code: string;\n secret: string;\n}\n\nexport interface UseTotpSetupOptions {\n onSetupSuccess?: (data: TotpSetupResponse) => void;\n onSetupError?: (error: Error) => void;\n onVerifySuccess?: (data: TotpSetupVerifyResponse) => void;\n onVerifyError?: (error: Error) => void;\n onConfirmSuccess?: (data: TotpConfirmResponse) => void;\n onConfirmError?: (error: Error) => void;\n autoStart?: boolean;\n}\n\nexport interface UseTotpSetupReturn {\n step: TotpSetupStep;\n setupData: TotpSetupResponse | null;\n recoveryCodes: string[];\n isSetupPending: boolean;\n isVerifyPending: boolean;\n isConfirmPending: boolean;\n isPending: boolean;\n setupError: Error | null;\n verifyError: Error | null;\n confirmError: Error | null;\n startSetup: () => void;\n verify: (code: string) => Promise<TotpSetupVerifyResponse>;\n goToQr: () => void;\n goToVerify: () => void;\n confirmRecoveryCodes: () => Promise<TotpConfirmResponse>;\n reset: () => void;\n}\n\nexport function useTotpSetup(\n options: UseTotpSetupOptions = {},\n): UseTotpSetupReturn {\n const {\n onSetupSuccess,\n onSetupError,\n onVerifySuccess,\n onVerifyError,\n onConfirmSuccess,\n onConfirmError,\n autoStart = false,\n } = options;\n\n const queryClient = useQueryClient();\n const [step, setStep] = useState<TotpSetupStep>(autoStart ? 'loading' : 'qr');\n const [setupData, setSetupData] = useState<TotpSetupResponse | null>(null);\n const [recoveryCodes, setRecoveryCodes] = useState<string[]>([]);\n const setupInitiatedRef = useRef(false);\n\n const setupMutation = useMutation({\n ...startTotpSetupMutationOptions,\n onSuccess: (data) => {\n setSetupData(data);\n setStep('qr');\n onSetupSuccess?.(data);\n },\n onError: (error) => {\n setStep('error');\n onSetupError?.(error);\n },\n });\n\n const verifyMutation = useMutation({\n ...verifyTotpMutationOptions,\n onSuccess: (data) => {\n // Do NOT invalidate session here - TOTP is not fully enabled yet\n setRecoveryCodes(data.recovery_codes);\n setStep('recovery');\n onVerifySuccess?.(data);\n },\n onError: (error) => {\n onVerifyError?.(error);\n },\n });\n\n const confirmMutation = useMutation({\n ...confirmTotpSetupMutationOptions,\n onSuccess: (data) => {\n // Now TOTP is fully enabled, invalidate session\n queryClient.invalidateQueries({\n queryKey: getSessionQueryOptions.queryKey,\n });\n onConfirmSuccess?.(data);\n },\n onError: (error) => {\n onConfirmError?.(error);\n },\n });\n\n const startSetup = useCallback(() => {\n setupInitiatedRef.current = true;\n setStep('loading');\n setupMutation.mutate();\n }, [setupMutation]);\n\n const verify = useCallback(\n async (code: string) => {\n return verifyMutation.mutateAsync({ code });\n },\n [verifyMutation],\n );\n\n const goToQr = useCallback(() => {\n setStep('qr');\n }, []);\n\n const goToVerify = useCallback(() => {\n setStep('verify');\n }, []);\n\n const confirmRecoveryCodes = useCallback(async () => {\n return confirmMutation.mutateAsync();\n }, [confirmMutation]);\n\n const reset = useCallback(() => {\n setStep(autoStart ? 'loading' : 'qr');\n setSetupData(null);\n setRecoveryCodes([]);\n setupInitiatedRef.current = false;\n setupMutation.reset();\n verifyMutation.reset();\n confirmMutation.reset();\n }, [autoStart, setupMutation, verifyMutation, confirmMutation]);\n\n // Auto start setup on mount if enabled\n useEffect(() => {\n if (autoStart && !setupInitiatedRef.current && step === 'loading') {\n setupInitiatedRef.current = true;\n setupMutation.mutate();\n }\n }, [autoStart, step, setupMutation]);\n\n return {\n step,\n setupData,\n recoveryCodes,\n isSetupPending: setupMutation.isPending,\n isVerifyPending: verifyMutation.isPending,\n isConfirmPending: confirmMutation.isPending,\n isPending:\n setupMutation.isPending ||\n verifyMutation.isPending ||\n confirmMutation.isPending,\n setupError: setupMutation.error,\n verifyError: verifyMutation.error,\n confirmError: confirmMutation.error,\n startSetup,\n verify,\n goToQr,\n goToVerify,\n confirmRecoveryCodes,\n reset,\n };\n}\n"],"x_google_ignoreList":[0,1,2,3],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{s as e,u as t}from"./IconBase.es-d5KP98Ac.js";import{At as n,Dt as r,Et as i,St as a,gt as o,ut as s,vt as c}from"./use-theme-cVUDAjtt.js";import{
|
|
2
|
-
//# sourceMappingURL=useMutation-
|
|
1
|
+
import{s as e,u as t}from"./IconBase.es-d5KP98Ac.js";import{At as n,Dt as r,Et as i,St as a,gt as o,ut as s,vt as c}from"./use-theme-cVUDAjtt.js";import{z as l}from"./index-CgkA6nnx.js";var u=class extends n{#e;#t=void 0;#n;#r;constructor(e,t){super(),this.#e=e,this.setOptions(t),this.bindMethods(),this.#i()}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(e){let t=this.options;this.options=this.#e.defaultMutationOptions(e),i(this.options,t)||this.#e.getMutationCache().notify({type:`observerOptionsUpdated`,mutation:this.#n,observer:this}),t?.mutationKey&&this.options.mutationKey&&c(t.mutationKey)!==c(this.options.mutationKey)?this.reset():this.#n?.state.status===`pending`&&this.#n.setOptions(this.options)}onUnsubscribe(){this.hasListeners()||this.#n?.removeObserver(this)}onMutationUpdate(e){this.#i(),this.#a(e)}getCurrentResult(){return this.#t}reset(){this.#n?.removeObserver(this),this.#n=void 0,this.#i(),this.#a()}mutate(e,t){return this.#r=t,this.#n?.removeObserver(this),this.#n=this.#e.getMutationCache().build(this.#e,this.options),this.#n.addObserver(this),this.#n.execute(e)}#i(){let e=this.#n?.state??l();this.#t={...e,isPending:e.status===`pending`,isSuccess:e.status===`success`,isError:e.status===`error`,isIdle:e.status===`idle`,mutate:this.mutate,reset:this.reset}}#a(e){o.batch(()=>{if(this.#r&&this.hasListeners()){let t=this.#t.variables,n=this.#t.context,r={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey};if(e?.type===`success`){try{this.#r.onSuccess?.(e.data,t,n,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(e.data,null,t,n,r)}catch(e){Promise.reject(e)}}else if(e?.type===`error`){try{this.#r.onError?.(e.error,t,n,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(void 0,e.error,t,n,r)}catch(e){Promise.reject(e)}}}this.listeners.forEach(e=>{e(this.#t)})})}},d=t(e(),1);function f(e,t){let n=s(t),[i]=d.useState(()=>new u(n,e));d.useEffect(()=>{i.setOptions(e)},[i,e]);let c=d.useSyncExternalStore(d.useCallback(e=>i.subscribe(o.batchCalls(e)),[i]),()=>i.getCurrentResult(),()=>i.getCurrentResult()),l=d.useCallback((e,t)=>{i.mutate(e,t).catch(a)},[i]);if(c.error&&r(i.options.throwOnError,[c.error]))throw c.error;return{...c,mutate:l,mutateAsync:c.mutate}}export{f as t};
|
|
2
|
+
//# sourceMappingURL=useMutation-Biy2-pH_.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMutation-
|
|
1
|
+
{"version":3,"file":"useMutation-Biy2-pH_.js","names":["#client","#updateResult","#currentMutation","#notify","#currentResult","#mutateOptions"],"sources":["../../../../node_modules/.pnpm/@tanstack+query-core@5.101.0/node_modules/@tanstack/query-core/build/modern/mutationObserver.js","../../../../node_modules/.pnpm/@tanstack+react-query@5.101.0_react@19.2.7/node_modules/@tanstack/react-query/build/modern/useMutation.js"],"sourcesContent":["// src/mutationObserver.ts\nimport { getDefaultState } from \"./mutation.js\";\nimport { notifyManager } from \"./notifyManager.js\";\nimport { Subscribable } from \"./subscribable.js\";\nimport { hashKey, shallowEqualObjects } from \"./utils.js\";\nvar MutationObserver = class extends Subscribable {\n #client;\n #currentResult = void 0;\n #currentMutation;\n #mutateOptions;\n constructor(client, options) {\n super();\n this.#client = client;\n this.setOptions(options);\n this.bindMethods();\n this.#updateResult();\n }\n bindMethods() {\n this.mutate = this.mutate.bind(this);\n this.reset = this.reset.bind(this);\n }\n setOptions(options) {\n const prevOptions = this.options;\n this.options = this.#client.defaultMutationOptions(options);\n if (!shallowEqualObjects(this.options, prevOptions)) {\n this.#client.getMutationCache().notify({\n type: \"observerOptionsUpdated\",\n mutation: this.#currentMutation,\n observer: this\n });\n }\n if (prevOptions?.mutationKey && this.options.mutationKey && hashKey(prevOptions.mutationKey) !== hashKey(this.options.mutationKey)) {\n this.reset();\n } else if (this.#currentMutation?.state.status === \"pending\") {\n this.#currentMutation.setOptions(this.options);\n }\n }\n onUnsubscribe() {\n if (!this.hasListeners()) {\n this.#currentMutation?.removeObserver(this);\n }\n }\n onMutationUpdate(action) {\n this.#updateResult();\n this.#notify(action);\n }\n getCurrentResult() {\n return this.#currentResult;\n }\n reset() {\n this.#currentMutation?.removeObserver(this);\n this.#currentMutation = void 0;\n this.#updateResult();\n this.#notify();\n }\n mutate(variables, options) {\n this.#mutateOptions = options;\n this.#currentMutation?.removeObserver(this);\n this.#currentMutation = this.#client.getMutationCache().build(this.#client, this.options);\n this.#currentMutation.addObserver(this);\n return this.#currentMutation.execute(variables);\n }\n #updateResult() {\n const state = this.#currentMutation?.state ?? getDefaultState();\n this.#currentResult = {\n ...state,\n isPending: state.status === \"pending\",\n isSuccess: state.status === \"success\",\n isError: state.status === \"error\",\n isIdle: state.status === \"idle\",\n mutate: this.mutate,\n reset: this.reset\n };\n }\n #notify(action) {\n notifyManager.batch(() => {\n if (this.#mutateOptions && this.hasListeners()) {\n const variables = this.#currentResult.variables;\n const onMutateResult = this.#currentResult.context;\n const context = {\n client: this.#client,\n meta: this.options.meta,\n mutationKey: this.options.mutationKey\n };\n if (action?.type === \"success\") {\n try {\n this.#mutateOptions.onSuccess?.(\n action.data,\n variables,\n onMutateResult,\n context\n );\n } catch (e) {\n void Promise.reject(e);\n }\n try {\n this.#mutateOptions.onSettled?.(\n action.data,\n null,\n variables,\n onMutateResult,\n context\n );\n } catch (e) {\n void Promise.reject(e);\n }\n } else if (action?.type === \"error\") {\n try {\n this.#mutateOptions.onError?.(\n action.error,\n variables,\n onMutateResult,\n context\n );\n } catch (e) {\n void Promise.reject(e);\n }\n try {\n this.#mutateOptions.onSettled?.(\n void 0,\n action.error,\n variables,\n onMutateResult,\n context\n );\n } catch (e) {\n void Promise.reject(e);\n }\n }\n }\n this.listeners.forEach((listener) => {\n listener(this.#currentResult);\n });\n });\n }\n};\nexport {\n MutationObserver\n};\n//# sourceMappingURL=mutationObserver.js.map","\"use client\";\n\n// src/useMutation.ts\nimport * as React from \"react\";\nimport {\n MutationObserver,\n noop,\n notifyManager,\n shouldThrowError\n} from \"@tanstack/query-core\";\nimport { useQueryClient } from \"./QueryClientProvider.js\";\nfunction useMutation(options, queryClient) {\n const client = useQueryClient(queryClient);\n const [observer] = React.useState(\n () => new MutationObserver(\n client,\n options\n )\n );\n React.useEffect(() => {\n observer.setOptions(options);\n }, [observer, options]);\n const result = React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer]\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult()\n );\n const mutate = React.useCallback(\n (variables, mutateOptions) => {\n observer.mutate(variables, mutateOptions).catch(noop);\n },\n [observer]\n );\n if (result.error && shouldThrowError(observer.options.throwOnError, [result.error])) {\n throw result.error;\n }\n return { ...result, mutate, mutateAsync: result.mutate };\n}\nexport {\n useMutation\n};\n//# sourceMappingURL=useMutation.js.map"],"x_google_ignoreList":[0,1],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{o as e,r as t,s as n,u as r}from"./IconBase.es-d5KP98Ac.js";import{Q as i,n as a,ut as o}from"./use-theme-cVUDAjtt.js";import{t as s}from"./useMutation-Iu4AJCB4.js";import{t as c}from"./page-layout-C475gs09.js";import{o as l}from"./index-BmfaaNx6.js";import{a as u,i as d,n as f,o as p,r as m,s as h,t as g}from"./admin-users-CTAQJl7w.js";var _=r(n()),v=e();function y(){let{t:e}=t(),n=l.useRouteContext({select:e=>e.user});return n?.role===`admin`?(0,v.jsx)(b,{user:n}):(0,v.jsxs)(c,{cardPadding:!0,maxWidth:`md`,children:[(0,v.jsx)(`h1`,{className:`mb-2 text-center font-bold text-2xl`,children:e(`admin.accessRequired`)}),(0,v.jsx)(`p`,{className:`text-center text-base-content/60`,children:e(`admin.accessRequiredDescription`)})]})}function b({user:e}){let{data:t}=i(a);return t.admin.enabled?(0,v.jsx)(x,{user:e}):(0,v.jsx)(h,{})}function x({user:e}){let{t:n}=t(),r=o(),[a,c]=(0,_.useState)(``),[l,h]=(0,_.useState)(!1),[y,b]=(0,_.useState)(()=>d()),[x,C]=(0,_.useState)(null),[E,A]=(0,_.useState)(null),{data:M}=i(g(y)),N=M.users.filter(e=>!e.deleted_at).length,P=M.users.filter(e=>e.managed_by===`config`).length,F=M.users.filter(e=>e.managed_by===`database`).length,I=D(y),L=y.query!==``||y.includeDeleted||y.managedBy!==void 0||y.role!==void 0,R=M.pagination.total===0?0:(M.pagination.page-1)*M.pagination.page_size+1,z=Math.min(M.pagination.page*M.pagination.page_size,M.pagination.total),B=s({mutationFn:f,onSuccess:({user:e})=>{r.invalidateQueries({queryKey:[`admin`,`users`]}),C({tone:`success`,message:n(`admin.users.createdNotice`,{email:e.email})}),A(null)},onError:()=>{C({tone:`error`,message:n(`admin.users.operationFailed`)})}}),V=s({mutationFn:u,onSuccess:({user:e})=>{r.invalidateQueries({queryKey:[`admin`,`users`]}),C({tone:`success`,message:n(`admin.users.updatedNotice`,{email:e.email})}),A(null)},onError:()=>{C({tone:`error`,message:n(`admin.users.operationFailed`)})}}),H=s({mutationFn:m,onSuccess:({user:e})=>{r.invalidateQueries({queryKey:[`admin`,`users`]}),C({tone:`success`,message:n(`admin.users.deletedNotice`,{email:e.email})}),A(null)},onError:()=>{C({tone:`error`,message:n(`admin.users.operationFailed`)})}}),U=B.isPending||V.isPending||H.isPending,W=()=>{b(e=>({...e,query:a.trim(),includeDeleted:l,page:1}))},G=()=>{c(``),h(!1),b(d())},K=e=>{b(t=>({...t,page:1,pageSize:e}))},q=e=>{b(t=>({...t,page:1,managedBy:e===`database`?`database`:e===`config`?`config`:void 0,role:e===`admins`?`admin`:void 0}))};return(0,v.jsxs)(p,{current:`users`,description:n(`admin.users.description`),title:n(`admin.users.title`),user:e,children:[(0,v.jsxs)(`div`,{className:`stats stats-vertical lg:stats-horizontal w-full overflow-hidden rounded-[1.5rem] border border-white/10 bg-white/[0.035] shadow-[0_24px_80px_rgba(0,0,0,0.24)] backdrop-blur-xl`,children:[(0,v.jsx)(k,{label:n(`admin.users.activeOnPage`),value:N}),(0,v.jsx)(k,{label:n(`admin.users.configOnPage`),value:P}),(0,v.jsx)(k,{label:n(`admin.users.databaseOnPage`),value:F})]}),x?(0,v.jsxs)(`div`,{"aria-live":x.tone===`success`?`polite`:`assertive`,className:x.tone===`success`?`alert mt-6 border-emerald-300/20 bg-emerald-300/10 text-emerald-100`:`alert mt-6 border-red-300/20 bg-red-300/10 text-red-100`,role:x.tone===`success`?`status`:`alert`,children:[(0,v.jsx)(`span`,{children:x.tone===`success`?`✓`:`!`}),(0,v.jsx)(`span`,{children:x.message}),(0,v.jsx)(`button`,{"aria-label":n(`common.close`),className:`btn btn-ghost btn-xs ml-auto text-current`,onClick:()=>C(null),type:`button`,children:`×`})]}):null,(0,v.jsx)(`section`,{className:`card mt-6 overflow-hidden border border-white/10 bg-white/[0.035] shadow-[0_24px_80px_rgba(0,0,0,0.24)] backdrop-blur-xl`,children:(0,v.jsxs)(`div`,{className:`card-body gap-5 p-0`,children:[(0,v.jsxs)(`div`,{className:`flex flex-col gap-4 border-white/10 border-b bg-white/[0.015] p-6 xl:flex-row xl:items-end xl:justify-between`,children:[(0,v.jsxs)(`div`,{children:[(0,v.jsxs)(`div`,{className:`mb-2 flex items-center gap-2`,children:[(0,v.jsx)(`span`,{className:`h-2 w-2 rounded-full bg-emerald-400 shadow-[0_0_18px_rgba(52,211,153,0.75)]`}),(0,v.jsx)(`span`,{className:`font-medium text-slate-500 text-xs uppercase tracking-[0.18em]`,children:n(`admin.users.directoryEyebrow`)})]}),(0,v.jsx)(`h2`,{className:`card-title text-slate-100`,children:n(`admin.users.directory`)}),(0,v.jsx)(`p`,{className:`mt-1 text-slate-400 text-sm`,children:n(`admin.users.total`,{count:M.pagination.total})})]}),(0,v.jsxs)(`div`,{className:`flex flex-col gap-3 xl:items-end`,children:[(0,v.jsxs)(`div`,{className:`flex flex-col gap-2 lg:flex-row lg:items-center`,children:[(0,v.jsx)(`input`,{"aria-label":n(`admin.users.searchPlaceholder`),className:`input input-bordered h-11 w-full border-white/10 bg-black/20 text-slate-200 placeholder:text-slate-500 focus:border-[#7170ff]/60 lg:w-80`,onChange:e=>c(e.target.value),onKeyDown:e=>{e.key===`Enter`&&W()},placeholder:n(`admin.users.searchPlaceholder`),type:`search`,value:a}),(0,v.jsxs)(`label`,{className:`label cursor-pointer justify-start gap-2 rounded-box border border-white/10 bg-black/20 px-3 py-2`,children:[(0,v.jsx)(`input`,{checked:l,className:`checkbox checkbox-sm border-white/20 bg-white/[0.04] checked:border-[#7170ff] checked:bg-[#7170ff]`,onChange:e=>h(e.target.checked),type:`checkbox`}),(0,v.jsx)(`span`,{className:`label-text text-slate-300`,children:n(`admin.users.includeDeleted`)})]}),(0,v.jsx)(`button`,{className:`btn btn-outline border-white/10 bg-white/[0.035] text-slate-200 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15`,onClick:W,type:`button`,children:n(`admin.users.search`)}),(0,v.jsx)(`button`,{className:`btn btn-primary border-0 bg-[#7170ff] text-white shadow-[0_14px_40px_rgba(113,112,255,0.32)] hover:bg-[#828fff]`,onClick:()=>A({type:`create`}),type:`button`,children:n(`admin.users.create`)})]}),(0,v.jsxs)(`div`,{className:`join rounded-box border border-white/10 bg-black/20 p-1`,children:[(0,v.jsx)(O,{active:I===`all`,label:n(`admin.users.filter.all`),onClick:()=>q(`all`)}),(0,v.jsx)(O,{active:I===`database`,label:n(`admin.users.filter.database`),onClick:()=>q(`database`)}),(0,v.jsx)(O,{active:I===`config`,label:n(`admin.users.filter.config`),onClick:()=>q(`config`)}),(0,v.jsx)(O,{active:I===`admins`,label:n(`admin.users.filter.admins`),onClick:()=>q(`admins`)})]})]})]}),(0,v.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3 px-6`,children:[(0,v.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2 text-sm`,children:[(0,v.jsx)(`span`,{className:`text-slate-500`,children:n(`admin.users.showingRange`,{from:R,to:z,total:M.pagination.total})}),y.query?(0,v.jsx)(`span`,{className:`badge badge-outline border-[#7170ff]/30 bg-[#7170ff]/10 text-[#c7c8ff]`,children:n(`admin.users.queryChip`,{query:y.query})}):null,y.includeDeleted?(0,v.jsx)(`span`,{className:`badge badge-outline border-amber-300/25 bg-amber-300/10 text-amber-100`,children:n(`admin.users.includeDeleted`)}):null,I===`all`?null:(0,v.jsx)(`span`,{className:`badge badge-outline border-white/15 text-slate-300`,children:n(`admin.users.filter.${I}`)}),L?(0,v.jsx)(`button`,{className:`btn btn-ghost btn-xs text-slate-400`,onClick:G,type:`button`,children:n(`admin.users.clearFilters`)}):null]}),(0,v.jsxs)(`label`,{className:`flex items-center gap-2 text-slate-500 text-sm`,children:[(0,v.jsx)(`span`,{children:n(`admin.users.pageSize`)}),(0,v.jsxs)(`select`,{"aria-label":n(`admin.users.pageSize`),className:`select select-bordered select-xs border-white/10 bg-black/20 text-slate-200`,onChange:e=>K(Number(e.target.value)),value:y.pageSize,children:[(0,v.jsx)(`option`,{value:10,children:`10`}),(0,v.jsx)(`option`,{value:20,children:`20`}),(0,v.jsx)(`option`,{value:50,children:`50`})]})]})]}),(0,v.jsx)(`div`,{className:`overflow-x-auto px-0 pb-2`,children:(0,v.jsxs)(`table`,{className:`table-zebra table [&_tbody_tr:hover]:bg-white/[0.04] [&_tbody_tr]:border-white/5 [&_tbody_tr]:transition [&_td]:border-white/5 [&_thead_th]:border-white/10 [&_thead_th]:bg-white/[0.035] [&_thead_th]:text-slate-500`,children:[(0,v.jsx)(`thead`,{children:(0,v.jsxs)(`tr`,{children:[(0,v.jsx)(`th`,{children:n(`profile.email.label`)}),(0,v.jsx)(`th`,{children:n(`admin.users.role`)}),(0,v.jsx)(`th`,{children:n(`admin.users.source`)}),(0,v.jsx)(`th`,{children:n(`admin.users.emailVerified`)}),(0,v.jsx)(`th`,{children:n(`admin.users.secondFactor`)}),(0,v.jsx)(`th`,{children:n(`admin.users.status`)}),(0,v.jsx)(`th`,{children:n(`admin.users.actions`)})]})}),(0,v.jsxs)(`tbody`,{children:[M.users.map(e=>(0,v.jsxs)(`tr`,{children:[(0,v.jsxs)(`td`,{children:[(0,v.jsx)(`div`,{className:`font-medium text-slate-100`,children:e.email}),(0,v.jsx)(`div`,{className:`max-w-64 truncate font-mono text-slate-600 text-xs`,children:e.sub})]}),(0,v.jsx)(`td`,{children:(0,v.jsx)(j,{tone:e.role===`admin`?`neutral`:`ghost`,children:w(n,e.role)})}),(0,v.jsx)(`td`,{children:(0,v.jsx)(j,{tone:e.managed_by===`config`?`warning`:`info`,children:T(n,e.managed_by)})}),(0,v.jsx)(`td`,{children:e.email_verified?n(`common.yes`):n(`common.no`)}),(0,v.jsx)(`td`,{children:e.totp_registered?n(`admin.users.secondFactorTotp`):e.passkey_count>0?n(e.passkey_count===1?`admin.users.secondFactorPasskey`:`admin.users.secondFactorPasskeys`,{count:e.passkey_count}):n(`common.none`)}),(0,v.jsx)(`td`,{children:(0,v.jsx)(j,{tone:e.deleted_at?`error`:`success`,children:e.deleted_at?n(`admin.users.deleted`):n(`admin.users.active`)})}),(0,v.jsx)(`td`,{children:e.managed_by===`database`&&!e.deleted_at?(0,v.jsxs)(`div`,{className:`join rounded-xl border border-white/10 bg-black/20`,children:[(0,v.jsx)(`button`,{"aria-label":n(`admin.users.editUser`,{email:e.email}),className:`btn join-item btn-ghost btn-xs text-slate-300 hover:bg-white/[0.06]`,onClick:()=>A({type:`edit`,user:e}),type:`button`,children:n(`admin.users.edit`)}),(0,v.jsx)(`button`,{"aria-label":n(`admin.users.deleteUser`,{email:e.email}),className:`btn join-item btn-error btn-outline btn-xs border-red-400/25 bg-red-400/5 text-red-200 hover:bg-red-400/15`,onClick:()=>A({type:`delete`,user:e}),type:`button`,children:n(`admin.users.delete`)})]}):(0,v.jsx)(`span`,{className:`badge badge-outline border-white/15 text-slate-400`,children:n(`admin.users.readonly`)})})]},e.sub)),M.users.length===0?(0,v.jsx)(`tr`,{children:(0,v.jsx)(`td`,{className:`py-12 text-center text-slate-500`,colSpan:7,children:n(`admin.users.emptyFiltered`)})}):null]})]})}),(0,v.jsxs)(`div`,{className:`flex items-center justify-between border-white/10 border-t bg-white/[0.015] p-5`,children:[(0,v.jsx)(`button`,{className:`btn btn-outline btn-sm border-white/10 bg-white/[0.035] text-slate-300 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15`,disabled:y.page<=1,onClick:()=>b(e=>({...e,page:e.page-1})),type:`button`,children:n(`admin.users.previous`)}),(0,v.jsx)(`span`,{className:`badge badge-ghost border-white/10 bg-black/20 text-slate-400`,children:n(`admin.users.page`,{page:M.pagination.page})}),(0,v.jsx)(`button`,{className:`btn btn-outline btn-sm border-white/10 bg-white/[0.035] text-slate-300 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15`,disabled:M.pagination.page*M.pagination.page_size>=M.pagination.total,onClick:()=>b(e=>({...e,page:e.page+1})),type:`button`,children:n(`admin.users.next`)})]})]})}),(0,v.jsx)(S,{isMutating:U,modal:E,onClose:()=>A(null),onCreate:e=>B.mutate(e),onDelete:e=>H.mutate(e),onUpdate:e=>V.mutate(e)})]})}function S({modal:e,isMutating:n,onClose:r,onCreate:i,onUpdate:a,onDelete:o}){let{t:s}=t(),c=(0,_.useMemo)(()=>e?.type===`edit`?e.user:null,[e]),l=(0,_.useRef)(null);if((0,_.useEffect)(()=>{if(!e)return;let t=document.activeElement instanceof HTMLElement?document.activeElement:null;return(l.current?.querySelector(`input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), a[href], [tabindex]:not([tabindex="-1"])`))?.focus(),()=>{t?.focus()}},[e]),!e)return null;if(e.type===`delete`)return(0,v.jsx)(`div`,{className:`modal modal-open bg-black/70 backdrop-blur-sm`,children:(0,v.jsxs)(`div`,{"aria-labelledby":`admin-delete-user-title`,"aria-modal":`true`,className:`modal-box border border-white/10 bg-[#101217] text-slate-100 shadow-[0_32px_100px_rgba(0,0,0,0.55)]`,onKeyDown:e=>C(e,r),ref:l,role:`dialog`,children:[(0,v.jsx)(`h3`,{className:`font-semibold text-xl tracking-[-0.03em]`,id:`admin-delete-user-title`,children:s(`admin.users.deleteTitle`,{email:e.user.email})}),(0,v.jsxs)(`div`,{className:`my-4 rounded-2xl border border-red-300/20 bg-red-400/10 p-4 text-red-100`,children:[(0,v.jsx)(`p`,{className:`font-medium`,children:s(`admin.users.deleteWarning`)}),(0,v.jsx)(`p`,{className:`mt-1 text-red-100/70 text-sm`,children:s(`admin.users.deleteDescription`)})]}),(0,v.jsxs)(`div`,{className:`modal-action`,children:[(0,v.jsx)(`button`,{className:`btn border-white/10 bg-white/[0.04] text-slate-200 hover:bg-white/[0.08]`,onClick:r,type:`button`,children:s(`admin.users.cancel`)}),(0,v.jsx)(`button`,{className:`btn btn-error border-0 bg-red-500/80 text-white hover:bg-red-500`,disabled:n,onClick:()=>o(e.user.sub),type:`button`,children:s(`admin.users.deleteConfirm`)})]})]})});let u=e.type===`create`?s(`admin.users.create`):s(`admin.users.editTitle`),d=e.type===`create`?s(`admin.users.createSubmit`):s(`admin.users.save`);return(0,v.jsx)(`div`,{className:`modal modal-open bg-black/70 backdrop-blur-sm`,children:(0,v.jsxs)(`div`,{"aria-labelledby":`admin-user-form-title`,"aria-modal":`true`,className:`modal-box border border-white/10 bg-[#101217] text-slate-100 shadow-[0_32px_100px_rgba(0,0,0,0.55)]`,onKeyDown:e=>C(e,r),ref:l,role:`dialog`,children:[(0,v.jsx)(`h3`,{className:`font-semibold text-xl tracking-[-0.03em]`,id:`admin-user-form-title`,children:u}),(0,v.jsx)(`p`,{className:`mt-2 text-slate-500 text-sm`,children:e.type===`create`?s(`admin.users.createHint`):s(`admin.users.editHint`)}),(0,v.jsxs)(`form`,{className:`mt-4 space-y-4`,onSubmit:t=>{t.preventDefault();let n=new FormData(t.currentTarget),r={email:String(n.get(`email`)??``),role:E(n.get(`role`)),email_verified:n.get(`email_verified`)===`on`};e.type===`create`?i({...r,password:String(n.get(`password`)??``)}):a({sub:e.user.sub,...r})},children:[(0,v.jsxs)(`fieldset`,{className:`fieldset`,children:[(0,v.jsx)(`legend`,{className:`fieldset-legend text-slate-400`,children:s(`profile.email.label`)}),(0,v.jsx)(`input`,{"aria-label":s(`profile.email.label`),className:`input input-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60`,defaultValue:c?.email??``,name:`email`,required:!0,type:`email`})]}),e.type===`create`?(0,v.jsxs)(`fieldset`,{className:`fieldset`,children:[(0,v.jsx)(`legend`,{className:`fieldset-legend text-slate-400`,children:s(`admin.users.password`)}),(0,v.jsx)(`input`,{"aria-label":s(`admin.users.password`),className:`input input-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60`,name:`password`,required:!0,type:`password`})]}):null,(0,v.jsxs)(`fieldset`,{className:`fieldset`,children:[(0,v.jsx)(`legend`,{className:`fieldset-legend text-slate-400`,children:s(`admin.users.role`)}),(0,v.jsxs)(`select`,{"aria-label":s(`admin.users.role`),className:`select select-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60`,defaultValue:c?.role??`user`,name:`role`,children:[(0,v.jsx)(`option`,{value:`user`,children:s(`admin.users.roleUser`)}),(0,v.jsx)(`option`,{value:`admin`,children:s(`admin.users.roleAdmin`)})]})]}),(0,v.jsxs)(`label`,{className:`label cursor-pointer justify-start gap-3 rounded-box border border-white/10 bg-black/20 px-3 py-2`,children:[(0,v.jsx)(`input`,{className:`checkbox border-white/20 bg-white/[0.04] checked:border-[#7170ff] checked:bg-[#7170ff]`,defaultChecked:c?.email_verified??!1,name:`email_verified`,type:`checkbox`}),(0,v.jsx)(`span`,{className:`label-text text-slate-300`,children:s(`admin.users.emailVerified`)})]}),(0,v.jsxs)(`div`,{className:`modal-action`,children:[(0,v.jsx)(`button`,{className:`btn border-white/10 bg-white/[0.04] text-slate-200 hover:bg-white/[0.08]`,onClick:r,type:`button`,children:s(`admin.users.cancel`)}),(0,v.jsx)(`button`,{className:`btn btn-primary border-0 bg-[#7170ff] text-white shadow-[0_14px_40px_rgba(113,112,255,0.32)] hover:bg-[#828fff]`,disabled:n,type:`submit`,children:d})]})]})]})})}function C(e,t){if(e.key===`Escape`){e.preventDefault(),t();return}if(e.key!==`Tab`)return;let n=Array.from(e.currentTarget.querySelectorAll(`a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])`));if(n.length===0)return;let r=n[0],i=n.at(-1);if(!(!r||!i)){if(e.shiftKey&&document.activeElement===r){e.preventDefault(),i.focus();return}!e.shiftKey&&document.activeElement===i&&(e.preventDefault(),r.focus())}}function w(e,t){return e(t===`admin`?`admin.users.roleAdmin`:`admin.users.roleUser`)}function T(e,t){return e(t===`database`?`admin.users.sourceDatabase`:`admin.users.sourceConfig`)}function E(e){return e===`admin`?`admin`:`user`}function D(e){return e.role===`admin`?`admins`:e.managedBy===`database`?`database`:e.managedBy===`config`?`config`:`all`}function O({active:e,label:t,onClick:n}){return(0,v.jsx)(`button`,{className:e?`btn join-item btn-xs border-0 bg-[#7170ff] text-white`:`btn join-item btn-ghost btn-xs text-slate-400 hover:bg-white/[0.06] hover:text-slate-100`,onClick:n,type:`button`,children:t})}function k({label:e,value:n}){let{t:r}=t();return(0,v.jsxs)(`div`,{className:`stat border-white/10 bg-transparent p-6`,children:[(0,v.jsx)(`div`,{className:`stat-title text-slate-500`,children:e}),(0,v.jsx)(`div`,{className:`stat-value mt-1 text-slate-50 tracking-[-0.06em]`,children:n}),(0,v.jsx)(`div`,{className:`stat-desc text-slate-600`,children:r(`admin.users.currentPage`)})]})}var A={neutral:`badge-primary border-[#7170ff]/30 bg-[#7170ff]/20 text-[#c7c8ff]`,ghost:`badge-ghost border-white/10 bg-white/[0.035] text-slate-400`,warning:`badge-warning border-amber-300/25 bg-amber-300/15 text-amber-100`,info:`badge-info border-sky-300/25 bg-sky-300/15 text-sky-100`,success:`badge-success border-emerald-300/25 bg-emerald-300/15 text-emerald-100`,error:`badge-error border-red-300/25 bg-red-300/15 text-red-100`};function j({tone:e,children:t}){return(0,v.jsx)(`span`,{className:`badge ${A[e]}`,children:t})}export{y as component};
|
|
2
|
-
//# sourceMappingURL=users-
|
|
1
|
+
import{o as e,r as t,s as n,u as r}from"./IconBase.es-d5KP98Ac.js";import{Q as i,n as a,ut as o}from"./use-theme-cVUDAjtt.js";import{t as s}from"./useMutation-Biy2-pH_.js";import{t as c}from"./page-layout-C475gs09.js";import{o as l}from"./index-CgkA6nnx.js";import{a as u,i as d,n as f,o as p,r as m,s as h,t as g}from"./admin-users-CTAQJl7w.js";var _=r(n()),v=e();function y(){let{t:e}=t(),n=l.useRouteContext({select:e=>e.user});return n?.role===`admin`?(0,v.jsx)(b,{user:n}):(0,v.jsxs)(c,{cardPadding:!0,maxWidth:`md`,children:[(0,v.jsx)(`h1`,{className:`mb-2 text-center font-bold text-2xl`,children:e(`admin.accessRequired`)}),(0,v.jsx)(`p`,{className:`text-center text-base-content/60`,children:e(`admin.accessRequiredDescription`)})]})}function b({user:e}){let{data:t}=i(a);return t.admin.enabled?(0,v.jsx)(x,{user:e}):(0,v.jsx)(h,{})}function x({user:e}){let{t:n}=t(),r=o(),[a,c]=(0,_.useState)(``),[l,h]=(0,_.useState)(!1),[y,b]=(0,_.useState)(()=>d()),[x,C]=(0,_.useState)(null),[E,A]=(0,_.useState)(null),{data:M}=i(g(y)),N=M.users.filter(e=>!e.deleted_at).length,P=M.users.filter(e=>e.managed_by===`config`).length,F=M.users.filter(e=>e.managed_by===`database`).length,I=D(y),L=y.query!==``||y.includeDeleted||y.managedBy!==void 0||y.role!==void 0,R=M.pagination.total===0?0:(M.pagination.page-1)*M.pagination.page_size+1,z=Math.min(M.pagination.page*M.pagination.page_size,M.pagination.total),B=s({mutationFn:f,onSuccess:({user:e})=>{r.invalidateQueries({queryKey:[`admin`,`users`]}),C({tone:`success`,message:n(`admin.users.createdNotice`,{email:e.email})}),A(null)},onError:()=>{C({tone:`error`,message:n(`admin.users.operationFailed`)})}}),V=s({mutationFn:u,onSuccess:({user:e})=>{r.invalidateQueries({queryKey:[`admin`,`users`]}),C({tone:`success`,message:n(`admin.users.updatedNotice`,{email:e.email})}),A(null)},onError:()=>{C({tone:`error`,message:n(`admin.users.operationFailed`)})}}),H=s({mutationFn:m,onSuccess:({user:e})=>{r.invalidateQueries({queryKey:[`admin`,`users`]}),C({tone:`success`,message:n(`admin.users.deletedNotice`,{email:e.email})}),A(null)},onError:()=>{C({tone:`error`,message:n(`admin.users.operationFailed`)})}}),U=B.isPending||V.isPending||H.isPending,W=()=>{b(e=>({...e,query:a.trim(),includeDeleted:l,page:1}))},G=()=>{c(``),h(!1),b(d())},K=e=>{b(t=>({...t,page:1,pageSize:e}))},q=e=>{b(t=>({...t,page:1,managedBy:e===`database`?`database`:e===`config`?`config`:void 0,role:e===`admins`?`admin`:void 0}))};return(0,v.jsxs)(p,{current:`users`,description:n(`admin.users.description`),title:n(`admin.users.title`),user:e,children:[(0,v.jsxs)(`div`,{className:`stats stats-vertical lg:stats-horizontal w-full overflow-hidden rounded-[1.5rem] border border-white/10 bg-white/[0.035] shadow-[0_24px_80px_rgba(0,0,0,0.24)] backdrop-blur-xl`,children:[(0,v.jsx)(k,{label:n(`admin.users.activeOnPage`),value:N}),(0,v.jsx)(k,{label:n(`admin.users.configOnPage`),value:P}),(0,v.jsx)(k,{label:n(`admin.users.databaseOnPage`),value:F})]}),x?(0,v.jsxs)(`div`,{"aria-live":x.tone===`success`?`polite`:`assertive`,className:x.tone===`success`?`alert mt-6 border-emerald-300/20 bg-emerald-300/10 text-emerald-100`:`alert mt-6 border-red-300/20 bg-red-300/10 text-red-100`,role:x.tone===`success`?`status`:`alert`,children:[(0,v.jsx)(`span`,{children:x.tone===`success`?`✓`:`!`}),(0,v.jsx)(`span`,{children:x.message}),(0,v.jsx)(`button`,{"aria-label":n(`common.close`),className:`btn btn-ghost btn-xs ml-auto text-current`,onClick:()=>C(null),type:`button`,children:`×`})]}):null,(0,v.jsx)(`section`,{className:`card mt-6 overflow-hidden border border-white/10 bg-white/[0.035] shadow-[0_24px_80px_rgba(0,0,0,0.24)] backdrop-blur-xl`,children:(0,v.jsxs)(`div`,{className:`card-body gap-5 p-0`,children:[(0,v.jsxs)(`div`,{className:`flex flex-col gap-4 border-white/10 border-b bg-white/[0.015] p-6 xl:flex-row xl:items-end xl:justify-between`,children:[(0,v.jsxs)(`div`,{children:[(0,v.jsxs)(`div`,{className:`mb-2 flex items-center gap-2`,children:[(0,v.jsx)(`span`,{className:`h-2 w-2 rounded-full bg-emerald-400 shadow-[0_0_18px_rgba(52,211,153,0.75)]`}),(0,v.jsx)(`span`,{className:`font-medium text-slate-500 text-xs uppercase tracking-[0.18em]`,children:n(`admin.users.directoryEyebrow`)})]}),(0,v.jsx)(`h2`,{className:`card-title text-slate-100`,children:n(`admin.users.directory`)}),(0,v.jsx)(`p`,{className:`mt-1 text-slate-400 text-sm`,children:n(`admin.users.total`,{count:M.pagination.total})})]}),(0,v.jsxs)(`div`,{className:`flex flex-col gap-3 xl:items-end`,children:[(0,v.jsxs)(`div`,{className:`flex flex-col gap-2 lg:flex-row lg:items-center`,children:[(0,v.jsx)(`input`,{"aria-label":n(`admin.users.searchPlaceholder`),className:`input input-bordered h-11 w-full border-white/10 bg-black/20 text-slate-200 placeholder:text-slate-500 focus:border-[#7170ff]/60 lg:w-80`,onChange:e=>c(e.target.value),onKeyDown:e=>{e.key===`Enter`&&W()},placeholder:n(`admin.users.searchPlaceholder`),type:`search`,value:a}),(0,v.jsxs)(`label`,{className:`label cursor-pointer justify-start gap-2 rounded-box border border-white/10 bg-black/20 px-3 py-2`,children:[(0,v.jsx)(`input`,{checked:l,className:`checkbox checkbox-sm border-white/20 bg-white/[0.04] checked:border-[#7170ff] checked:bg-[#7170ff]`,onChange:e=>h(e.target.checked),type:`checkbox`}),(0,v.jsx)(`span`,{className:`label-text text-slate-300`,children:n(`admin.users.includeDeleted`)})]}),(0,v.jsx)(`button`,{className:`btn btn-outline border-white/10 bg-white/[0.035] text-slate-200 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15`,onClick:W,type:`button`,children:n(`admin.users.search`)}),(0,v.jsx)(`button`,{className:`btn btn-primary border-0 bg-[#7170ff] text-white shadow-[0_14px_40px_rgba(113,112,255,0.32)] hover:bg-[#828fff]`,onClick:()=>A({type:`create`}),type:`button`,children:n(`admin.users.create`)})]}),(0,v.jsxs)(`div`,{className:`join rounded-box border border-white/10 bg-black/20 p-1`,children:[(0,v.jsx)(O,{active:I===`all`,label:n(`admin.users.filter.all`),onClick:()=>q(`all`)}),(0,v.jsx)(O,{active:I===`database`,label:n(`admin.users.filter.database`),onClick:()=>q(`database`)}),(0,v.jsx)(O,{active:I===`config`,label:n(`admin.users.filter.config`),onClick:()=>q(`config`)}),(0,v.jsx)(O,{active:I===`admins`,label:n(`admin.users.filter.admins`),onClick:()=>q(`admins`)})]})]})]}),(0,v.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3 px-6`,children:[(0,v.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2 text-sm`,children:[(0,v.jsx)(`span`,{className:`text-slate-500`,children:n(`admin.users.showingRange`,{from:R,to:z,total:M.pagination.total})}),y.query?(0,v.jsx)(`span`,{className:`badge badge-outline border-[#7170ff]/30 bg-[#7170ff]/10 text-[#c7c8ff]`,children:n(`admin.users.queryChip`,{query:y.query})}):null,y.includeDeleted?(0,v.jsx)(`span`,{className:`badge badge-outline border-amber-300/25 bg-amber-300/10 text-amber-100`,children:n(`admin.users.includeDeleted`)}):null,I===`all`?null:(0,v.jsx)(`span`,{className:`badge badge-outline border-white/15 text-slate-300`,children:n(`admin.users.filter.${I}`)}),L?(0,v.jsx)(`button`,{className:`btn btn-ghost btn-xs text-slate-400`,onClick:G,type:`button`,children:n(`admin.users.clearFilters`)}):null]}),(0,v.jsxs)(`label`,{className:`flex items-center gap-2 text-slate-500 text-sm`,children:[(0,v.jsx)(`span`,{children:n(`admin.users.pageSize`)}),(0,v.jsxs)(`select`,{"aria-label":n(`admin.users.pageSize`),className:`select select-bordered select-xs border-white/10 bg-black/20 text-slate-200`,onChange:e=>K(Number(e.target.value)),value:y.pageSize,children:[(0,v.jsx)(`option`,{value:10,children:`10`}),(0,v.jsx)(`option`,{value:20,children:`20`}),(0,v.jsx)(`option`,{value:50,children:`50`})]})]})]}),(0,v.jsx)(`div`,{className:`overflow-x-auto px-0 pb-2`,children:(0,v.jsxs)(`table`,{className:`table-zebra table [&_tbody_tr:hover]:bg-white/[0.04] [&_tbody_tr]:border-white/5 [&_tbody_tr]:transition [&_td]:border-white/5 [&_thead_th]:border-white/10 [&_thead_th]:bg-white/[0.035] [&_thead_th]:text-slate-500`,children:[(0,v.jsx)(`thead`,{children:(0,v.jsxs)(`tr`,{children:[(0,v.jsx)(`th`,{children:n(`profile.email.label`)}),(0,v.jsx)(`th`,{children:n(`admin.users.role`)}),(0,v.jsx)(`th`,{children:n(`admin.users.source`)}),(0,v.jsx)(`th`,{children:n(`admin.users.emailVerified`)}),(0,v.jsx)(`th`,{children:n(`admin.users.secondFactor`)}),(0,v.jsx)(`th`,{children:n(`admin.users.status`)}),(0,v.jsx)(`th`,{children:n(`admin.users.actions`)})]})}),(0,v.jsxs)(`tbody`,{children:[M.users.map(e=>(0,v.jsxs)(`tr`,{children:[(0,v.jsxs)(`td`,{children:[(0,v.jsx)(`div`,{className:`font-medium text-slate-100`,children:e.email}),(0,v.jsx)(`div`,{className:`max-w-64 truncate font-mono text-slate-600 text-xs`,children:e.sub})]}),(0,v.jsx)(`td`,{children:(0,v.jsx)(j,{tone:e.role===`admin`?`neutral`:`ghost`,children:w(n,e.role)})}),(0,v.jsx)(`td`,{children:(0,v.jsx)(j,{tone:e.managed_by===`config`?`warning`:`info`,children:T(n,e.managed_by)})}),(0,v.jsx)(`td`,{children:e.email_verified?n(`common.yes`):n(`common.no`)}),(0,v.jsx)(`td`,{children:e.totp_registered?n(`admin.users.secondFactorTotp`):e.passkey_count>0?n(e.passkey_count===1?`admin.users.secondFactorPasskey`:`admin.users.secondFactorPasskeys`,{count:e.passkey_count}):n(`common.none`)}),(0,v.jsx)(`td`,{children:(0,v.jsx)(j,{tone:e.deleted_at?`error`:`success`,children:e.deleted_at?n(`admin.users.deleted`):n(`admin.users.active`)})}),(0,v.jsx)(`td`,{children:e.managed_by===`database`&&!e.deleted_at?(0,v.jsxs)(`div`,{className:`join rounded-xl border border-white/10 bg-black/20`,children:[(0,v.jsx)(`button`,{"aria-label":n(`admin.users.editUser`,{email:e.email}),className:`btn join-item btn-ghost btn-xs text-slate-300 hover:bg-white/[0.06]`,onClick:()=>A({type:`edit`,user:e}),type:`button`,children:n(`admin.users.edit`)}),(0,v.jsx)(`button`,{"aria-label":n(`admin.users.deleteUser`,{email:e.email}),className:`btn join-item btn-error btn-outline btn-xs border-red-400/25 bg-red-400/5 text-red-200 hover:bg-red-400/15`,onClick:()=>A({type:`delete`,user:e}),type:`button`,children:n(`admin.users.delete`)})]}):(0,v.jsx)(`span`,{className:`badge badge-outline border-white/15 text-slate-400`,children:n(`admin.users.readonly`)})})]},e.sub)),M.users.length===0?(0,v.jsx)(`tr`,{children:(0,v.jsx)(`td`,{className:`py-12 text-center text-slate-500`,colSpan:7,children:n(`admin.users.emptyFiltered`)})}):null]})]})}),(0,v.jsxs)(`div`,{className:`flex items-center justify-between border-white/10 border-t bg-white/[0.015] p-5`,children:[(0,v.jsx)(`button`,{className:`btn btn-outline btn-sm border-white/10 bg-white/[0.035] text-slate-300 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15`,disabled:y.page<=1,onClick:()=>b(e=>({...e,page:e.page-1})),type:`button`,children:n(`admin.users.previous`)}),(0,v.jsx)(`span`,{className:`badge badge-ghost border-white/10 bg-black/20 text-slate-400`,children:n(`admin.users.page`,{page:M.pagination.page})}),(0,v.jsx)(`button`,{className:`btn btn-outline btn-sm border-white/10 bg-white/[0.035] text-slate-300 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15`,disabled:M.pagination.page*M.pagination.page_size>=M.pagination.total,onClick:()=>b(e=>({...e,page:e.page+1})),type:`button`,children:n(`admin.users.next`)})]})]})}),(0,v.jsx)(S,{isMutating:U,modal:E,onClose:()=>A(null),onCreate:e=>B.mutate(e),onDelete:e=>H.mutate(e),onUpdate:e=>V.mutate(e)})]})}function S({modal:e,isMutating:n,onClose:r,onCreate:i,onUpdate:a,onDelete:o}){let{t:s}=t(),c=(0,_.useMemo)(()=>e?.type===`edit`?e.user:null,[e]),l=(0,_.useRef)(null);if((0,_.useEffect)(()=>{if(!e)return;let t=document.activeElement instanceof HTMLElement?document.activeElement:null;return(l.current?.querySelector(`input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), a[href], [tabindex]:not([tabindex="-1"])`))?.focus(),()=>{t?.focus()}},[e]),!e)return null;if(e.type===`delete`)return(0,v.jsx)(`div`,{className:`modal modal-open bg-black/70 backdrop-blur-sm`,children:(0,v.jsxs)(`div`,{"aria-labelledby":`admin-delete-user-title`,"aria-modal":`true`,className:`modal-box border border-white/10 bg-[#101217] text-slate-100 shadow-[0_32px_100px_rgba(0,0,0,0.55)]`,onKeyDown:e=>C(e,r),ref:l,role:`dialog`,children:[(0,v.jsx)(`h3`,{className:`font-semibold text-xl tracking-[-0.03em]`,id:`admin-delete-user-title`,children:s(`admin.users.deleteTitle`,{email:e.user.email})}),(0,v.jsxs)(`div`,{className:`my-4 rounded-2xl border border-red-300/20 bg-red-400/10 p-4 text-red-100`,children:[(0,v.jsx)(`p`,{className:`font-medium`,children:s(`admin.users.deleteWarning`)}),(0,v.jsx)(`p`,{className:`mt-1 text-red-100/70 text-sm`,children:s(`admin.users.deleteDescription`)})]}),(0,v.jsxs)(`div`,{className:`modal-action`,children:[(0,v.jsx)(`button`,{className:`btn border-white/10 bg-white/[0.04] text-slate-200 hover:bg-white/[0.08]`,onClick:r,type:`button`,children:s(`admin.users.cancel`)}),(0,v.jsx)(`button`,{className:`btn btn-error border-0 bg-red-500/80 text-white hover:bg-red-500`,disabled:n,onClick:()=>o(e.user.sub),type:`button`,children:s(`admin.users.deleteConfirm`)})]})]})});let u=e.type===`create`?s(`admin.users.create`):s(`admin.users.editTitle`),d=e.type===`create`?s(`admin.users.createSubmit`):s(`admin.users.save`);return(0,v.jsx)(`div`,{className:`modal modal-open bg-black/70 backdrop-blur-sm`,children:(0,v.jsxs)(`div`,{"aria-labelledby":`admin-user-form-title`,"aria-modal":`true`,className:`modal-box border border-white/10 bg-[#101217] text-slate-100 shadow-[0_32px_100px_rgba(0,0,0,0.55)]`,onKeyDown:e=>C(e,r),ref:l,role:`dialog`,children:[(0,v.jsx)(`h3`,{className:`font-semibold text-xl tracking-[-0.03em]`,id:`admin-user-form-title`,children:u}),(0,v.jsx)(`p`,{className:`mt-2 text-slate-500 text-sm`,children:e.type===`create`?s(`admin.users.createHint`):s(`admin.users.editHint`)}),(0,v.jsxs)(`form`,{className:`mt-4 space-y-4`,onSubmit:t=>{t.preventDefault();let n=new FormData(t.currentTarget),r={email:String(n.get(`email`)??``),role:E(n.get(`role`)),email_verified:n.get(`email_verified`)===`on`};e.type===`create`?i({...r,password:String(n.get(`password`)??``)}):a({sub:e.user.sub,...r})},children:[(0,v.jsxs)(`fieldset`,{className:`fieldset`,children:[(0,v.jsx)(`legend`,{className:`fieldset-legend text-slate-400`,children:s(`profile.email.label`)}),(0,v.jsx)(`input`,{"aria-label":s(`profile.email.label`),className:`input input-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60`,defaultValue:c?.email??``,name:`email`,required:!0,type:`email`})]}),e.type===`create`?(0,v.jsxs)(`fieldset`,{className:`fieldset`,children:[(0,v.jsx)(`legend`,{className:`fieldset-legend text-slate-400`,children:s(`admin.users.password`)}),(0,v.jsx)(`input`,{"aria-label":s(`admin.users.password`),className:`input input-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60`,name:`password`,required:!0,type:`password`})]}):null,(0,v.jsxs)(`fieldset`,{className:`fieldset`,children:[(0,v.jsx)(`legend`,{className:`fieldset-legend text-slate-400`,children:s(`admin.users.role`)}),(0,v.jsxs)(`select`,{"aria-label":s(`admin.users.role`),className:`select select-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60`,defaultValue:c?.role??`user`,name:`role`,children:[(0,v.jsx)(`option`,{value:`user`,children:s(`admin.users.roleUser`)}),(0,v.jsx)(`option`,{value:`admin`,children:s(`admin.users.roleAdmin`)})]})]}),(0,v.jsxs)(`label`,{className:`label cursor-pointer justify-start gap-3 rounded-box border border-white/10 bg-black/20 px-3 py-2`,children:[(0,v.jsx)(`input`,{className:`checkbox border-white/20 bg-white/[0.04] checked:border-[#7170ff] checked:bg-[#7170ff]`,defaultChecked:c?.email_verified??!1,name:`email_verified`,type:`checkbox`}),(0,v.jsx)(`span`,{className:`label-text text-slate-300`,children:s(`admin.users.emailVerified`)})]}),(0,v.jsxs)(`div`,{className:`modal-action`,children:[(0,v.jsx)(`button`,{className:`btn border-white/10 bg-white/[0.04] text-slate-200 hover:bg-white/[0.08]`,onClick:r,type:`button`,children:s(`admin.users.cancel`)}),(0,v.jsx)(`button`,{className:`btn btn-primary border-0 bg-[#7170ff] text-white shadow-[0_14px_40px_rgba(113,112,255,0.32)] hover:bg-[#828fff]`,disabled:n,type:`submit`,children:d})]})]})]})})}function C(e,t){if(e.key===`Escape`){e.preventDefault(),t();return}if(e.key!==`Tab`)return;let n=Array.from(e.currentTarget.querySelectorAll(`a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])`));if(n.length===0)return;let r=n[0],i=n.at(-1);if(!(!r||!i)){if(e.shiftKey&&document.activeElement===r){e.preventDefault(),i.focus();return}!e.shiftKey&&document.activeElement===i&&(e.preventDefault(),r.focus())}}function w(e,t){return e(t===`admin`?`admin.users.roleAdmin`:`admin.users.roleUser`)}function T(e,t){return e(t===`database`?`admin.users.sourceDatabase`:`admin.users.sourceConfig`)}function E(e){return e===`admin`?`admin`:`user`}function D(e){return e.role===`admin`?`admins`:e.managedBy===`database`?`database`:e.managedBy===`config`?`config`:`all`}function O({active:e,label:t,onClick:n}){return(0,v.jsx)(`button`,{className:e?`btn join-item btn-xs border-0 bg-[#7170ff] text-white`:`btn join-item btn-ghost btn-xs text-slate-400 hover:bg-white/[0.06] hover:text-slate-100`,onClick:n,type:`button`,children:t})}function k({label:e,value:n}){let{t:r}=t();return(0,v.jsxs)(`div`,{className:`stat border-white/10 bg-transparent p-6`,children:[(0,v.jsx)(`div`,{className:`stat-title text-slate-500`,children:e}),(0,v.jsx)(`div`,{className:`stat-value mt-1 text-slate-50 tracking-[-0.06em]`,children:n}),(0,v.jsx)(`div`,{className:`stat-desc text-slate-600`,children:r(`admin.users.currentPage`)})]})}var A={neutral:`badge-primary border-[#7170ff]/30 bg-[#7170ff]/20 text-[#c7c8ff]`,ghost:`badge-ghost border-white/10 bg-white/[0.035] text-slate-400`,warning:`badge-warning border-amber-300/25 bg-amber-300/15 text-amber-100`,info:`badge-info border-sky-300/25 bg-sky-300/15 text-sky-100`,success:`badge-success border-emerald-300/25 bg-emerald-300/15 text-emerald-100`,error:`badge-error border-red-300/25 bg-red-300/15 text-red-100`};function j({tone:e,children:t}){return(0,v.jsx)(`span`,{className:`badge ${A[e]}`,children:t})}export{y as component};
|
|
2
|
+
//# sourceMappingURL=users-YtDGJlDl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"users-Bi7gjreq.js","names":["useMutation","useQueryClient","useSuspenseQuery","useEffect","useMemo","useRef","useState","useTranslation","AdminDisabledPanel","AdminShell","PageLayout","adminUsersQueryOptions","createAdminUser","deleteAdminUser","normalizeAdminUsersQuery","updateAdminUser","appConfigQueryOptions","Route","UserModalState","type","user","AdminUser","QuickFilter","NoticeState","tone","message","AdminUsersPage","t","useRouteContext","select","context","role","AdminUsersGate","SessionUser","data","config","admin","enabled","AdminUsersContent","queryClient","draftQuery","setDraftQuery","draftIncludeDeleted","setDraftIncludeDeleted","filters","setFilters","notice","setNotice","modal","setModal","activeUsers","users","filter","managedUser","deleted_at","length","configUsers","managed_by","databaseUsers","activeQuickFilter","getActiveQuickFilter","hasActiveFilters","query","includeDeleted","managedBy","undefined","pageStart","pagination","total","page","page_size","pageEnd","Math","min","createMutation","mutationFn","onSuccess","nextUser","invalidateQueries","queryKey","email","onError","updateMutation","deleteMutation","isMutating","isPending","applySearch","current","trim","clearFilters","setPageSize","pageSize","applyQuickFilter","nextFilter","count","event","target","value","key","checked","from","to","Number","map","sub","formatAdminRole","formatManagedBy","email_verified","totp_registered","passkey_count","values","mutate","UserFormModal","onClose","onCreate","onUpdate","onDelete","password","defaultValues","dialogRef","HTMLDivElement","previousFocus","document","activeElement","HTMLElement","firstFocusable","querySelector","focus","trapDialogFocus","title","submit","handleSubmit","FormEvent","HTMLFormElement","preventDefault","formData","FormData","currentTarget","String","get","parseUserRole","KeyboardEvent","focusableElements","Array","querySelectorAll","firstElement","lastElement","at","shiftKey","ReturnType","FormDataEntryValue","QuickFilterButton","active","label","onClick","SummaryStat","BadgeTone","badgeClasses","Record","neutral","ghost","warning","info","success","error","Badge","children","ReactNode","component"],"sources":["../../../frontend/src/routes/admin/users/index.tsx?tsr-split=component"],"sourcesContent":["import {\n useMutation,\n useQueryClient,\n useSuspenseQuery,\n} from '@tanstack/react-query';\nimport { createFileRoute, redirect } from '@tanstack/react-router';\nimport type { FormEvent, KeyboardEvent, ReactNode } from 'react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { AdminDisabledPanel } from '#frontend/features/admin/admin-disabled-panel.tsx';\nimport { AdminShell } from '#frontend/features/admin/admin-shell.tsx';\nimport { PageLayout } from '#frontend/features/layout/page-layout.tsx';\nimport {\n type AdminUser,\n adminUsersQueryOptions,\n createAdminUser,\n deleteAdminUser,\n normalizeAdminUsersQuery,\n updateAdminUser,\n} from '#frontend/queries/admin-users.ts';\nimport { appConfigQueryOptions } from '#frontend/queries/config.ts';\nimport type { SessionUser } from '#frontend/queries/session.ts';\n\nexport const Route = createFileRoute('/admin/users/')({\n component: AdminUsersPage,\n beforeLoad: async ({ context }) => {\n if (!context.user) {\n throw redirect({ to: '/login' });\n }\n },\n});\n\ntype UserModalState =\n | { type: 'create' }\n | { type: 'edit'; user: AdminUser }\n | { type: 'delete'; user: AdminUser }\n | null;\n\ntype QuickFilter = 'all' | 'database' | 'config' | 'admins';\n\ntype NoticeState = { tone: 'success' | 'error'; message: string } | null;\n\nfunction AdminUsersPage() {\n const { t } = useTranslation();\n const user = Route.useRouteContext({ select: (context) => context.user });\n\n if (user?.role !== 'admin') {\n return (\n <PageLayout cardPadding maxWidth=\"md\">\n <h1 className=\"mb-2 text-center font-bold text-2xl\">\n {t('admin.accessRequired')}\n </h1>\n <p className=\"text-center text-base-content/60\">\n {t('admin.accessRequiredDescription')}\n </p>\n </PageLayout>\n );\n }\n\n return <AdminUsersGate user={user} />;\n}\n\nfunction AdminUsersGate({ user }: { user: SessionUser }) {\n const { data: config } = useSuspenseQuery(appConfigQueryOptions);\n if (!config.admin.enabled) {\n return <AdminDisabledPanel />;\n }\n return <AdminUsersContent user={user} />;\n}\n\nfunction AdminUsersContent({ user }: { user: SessionUser }) {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n const [draftQuery, setDraftQuery] = useState('');\n const [draftIncludeDeleted, setDraftIncludeDeleted] = useState(false);\n const [filters, setFilters] = useState(() => normalizeAdminUsersQuery());\n const [notice, setNotice] = useState<NoticeState>(null);\n const [modal, setModal] = useState<UserModalState>(null);\n const { data } = useSuspenseQuery(adminUsersQueryOptions(filters));\n\n const activeUsers = data.users.filter(\n (managedUser) => !managedUser.deleted_at,\n ).length;\n const configUsers = data.users.filter(\n (managedUser) => managedUser.managed_by === 'config',\n ).length;\n const databaseUsers = data.users.filter(\n (managedUser) => managedUser.managed_by === 'database',\n ).length;\n const activeQuickFilter = getActiveQuickFilter(filters);\n const hasActiveFilters =\n filters.query !== '' ||\n filters.includeDeleted ||\n filters.managedBy !== undefined ||\n filters.role !== undefined;\n const pageStart =\n data.pagination.total === 0\n ? 0\n : (data.pagination.page - 1) * data.pagination.page_size + 1;\n const pageEnd = Math.min(\n data.pagination.page * data.pagination.page_size,\n data.pagination.total,\n );\n\n const createMutation = useMutation({\n mutationFn: createAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n setNotice({\n tone: 'success',\n message: t('admin.users.createdNotice', { email: nextUser.email }),\n });\n setModal(null);\n },\n onError: () => {\n setNotice({ tone: 'error', message: t('admin.users.operationFailed') });\n },\n });\n\n const updateMutation = useMutation({\n mutationFn: updateAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n setNotice({\n tone: 'success',\n message: t('admin.users.updatedNotice', { email: nextUser.email }),\n });\n setModal(null);\n },\n onError: () => {\n setNotice({ tone: 'error', message: t('admin.users.operationFailed') });\n },\n });\n\n const deleteMutation = useMutation({\n mutationFn: deleteAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n setNotice({\n tone: 'success',\n message: t('admin.users.deletedNotice', { email: nextUser.email }),\n });\n setModal(null);\n },\n onError: () => {\n setNotice({ tone: 'error', message: t('admin.users.operationFailed') });\n },\n });\n\n const isMutating =\n createMutation.isPending ||\n updateMutation.isPending ||\n deleteMutation.isPending;\n\n const applySearch = () => {\n setFilters((current) => ({\n ...current,\n query: draftQuery.trim(),\n includeDeleted: draftIncludeDeleted,\n page: 1,\n }));\n };\n\n const clearFilters = () => {\n setDraftQuery('');\n setDraftIncludeDeleted(false);\n setFilters(normalizeAdminUsersQuery());\n };\n\n const setPageSize = (pageSize: number) => {\n setFilters((current) => ({ ...current, page: 1, pageSize }));\n };\n\n const applyQuickFilter = (nextFilter: QuickFilter) => {\n setFilters((current) => ({\n ...current,\n page: 1,\n managedBy:\n nextFilter === 'database'\n ? 'database'\n : nextFilter === 'config'\n ? 'config'\n : undefined,\n role: nextFilter === 'admins' ? 'admin' : undefined,\n }));\n };\n\n return (\n <AdminShell\n current=\"users\"\n description={t('admin.users.description')}\n title={t('admin.users.title')}\n user={user}\n >\n <div className=\"stats stats-vertical lg:stats-horizontal w-full overflow-hidden rounded-[1.5rem] border border-white/10 bg-white/[0.035] shadow-[0_24px_80px_rgba(0,0,0,0.24)] backdrop-blur-xl\">\n <SummaryStat\n label={t('admin.users.activeOnPage')}\n value={activeUsers}\n />\n <SummaryStat\n label={t('admin.users.configOnPage')}\n value={configUsers}\n />\n <SummaryStat\n label={t('admin.users.databaseOnPage')}\n value={databaseUsers}\n />\n </div>\n\n {notice ? (\n <div\n aria-live={notice.tone === 'success' ? 'polite' : 'assertive'}\n className={\n notice.tone === 'success'\n ? 'alert mt-6 border-emerald-300/20 bg-emerald-300/10 text-emerald-100'\n : 'alert mt-6 border-red-300/20 bg-red-300/10 text-red-100'\n }\n role={notice.tone === 'success' ? 'status' : 'alert'}\n >\n <span>{notice.tone === 'success' ? '✓' : '!'}</span>\n <span>{notice.message}</span>\n <button\n aria-label={t('common.close')}\n className=\"btn btn-ghost btn-xs ml-auto text-current\"\n onClick={() => setNotice(null)}\n type=\"button\"\n >\n ×\n </button>\n </div>\n ) : null}\n\n <section className=\"card mt-6 overflow-hidden border border-white/10 bg-white/[0.035] shadow-[0_24px_80px_rgba(0,0,0,0.24)] backdrop-blur-xl\">\n <div className=\"card-body gap-5 p-0\">\n <div className=\"flex flex-col gap-4 border-white/10 border-b bg-white/[0.015] p-6 xl:flex-row xl:items-end xl:justify-between\">\n <div>\n <div className=\"mb-2 flex items-center gap-2\">\n <span className=\"h-2 w-2 rounded-full bg-emerald-400 shadow-[0_0_18px_rgba(52,211,153,0.75)]\" />\n <span className=\"font-medium text-slate-500 text-xs uppercase tracking-[0.18em]\">\n {t('admin.users.directoryEyebrow')}\n </span>\n </div>\n <h2 className=\"card-title text-slate-100\">\n {t('admin.users.directory')}\n </h2>\n <p className=\"mt-1 text-slate-400 text-sm\">\n {t('admin.users.total', { count: data.pagination.total })}\n </p>\n </div>\n <div className=\"flex flex-col gap-3 xl:items-end\">\n <div className=\"flex flex-col gap-2 lg:flex-row lg:items-center\">\n <input\n aria-label={t('admin.users.searchPlaceholder')}\n className=\"input input-bordered h-11 w-full border-white/10 bg-black/20 text-slate-200 placeholder:text-slate-500 focus:border-[#7170ff]/60 lg:w-80\"\n onChange={(event) => setDraftQuery(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') applySearch();\n }}\n placeholder={t('admin.users.searchPlaceholder')}\n type=\"search\"\n value={draftQuery}\n />\n <label className=\"label cursor-pointer justify-start gap-2 rounded-box border border-white/10 bg-black/20 px-3 py-2\">\n <input\n checked={draftIncludeDeleted}\n className=\"checkbox checkbox-sm border-white/20 bg-white/[0.04] checked:border-[#7170ff] checked:bg-[#7170ff]\"\n onChange={(event) =>\n setDraftIncludeDeleted(event.target.checked)\n }\n type=\"checkbox\"\n />\n <span className=\"label-text text-slate-300\">\n {t('admin.users.includeDeleted')}\n </span>\n </label>\n <button\n className=\"btn btn-outline border-white/10 bg-white/[0.035] text-slate-200 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15\"\n onClick={applySearch}\n type=\"button\"\n >\n {t('admin.users.search')}\n </button>\n <button\n className=\"btn btn-primary border-0 bg-[#7170ff] text-white shadow-[0_14px_40px_rgba(113,112,255,0.32)] hover:bg-[#828fff]\"\n onClick={() => setModal({ type: 'create' })}\n type=\"button\"\n >\n {t('admin.users.create')}\n </button>\n </div>\n <div className=\"join rounded-box border border-white/10 bg-black/20 p-1\">\n <QuickFilterButton\n active={activeQuickFilter === 'all'}\n label={t('admin.users.filter.all')}\n onClick={() => applyQuickFilter('all')}\n />\n <QuickFilterButton\n active={activeQuickFilter === 'database'}\n label={t('admin.users.filter.database')}\n onClick={() => applyQuickFilter('database')}\n />\n <QuickFilterButton\n active={activeQuickFilter === 'config'}\n label={t('admin.users.filter.config')}\n onClick={() => applyQuickFilter('config')}\n />\n <QuickFilterButton\n active={activeQuickFilter === 'admins'}\n label={t('admin.users.filter.admins')}\n onClick={() => applyQuickFilter('admins')}\n />\n </div>\n </div>\n </div>\n\n <div className=\"flex flex-wrap items-center justify-between gap-3 px-6\">\n <div className=\"flex flex-wrap items-center gap-2 text-sm\">\n <span className=\"text-slate-500\">\n {t('admin.users.showingRange', {\n from: pageStart,\n to: pageEnd,\n total: data.pagination.total,\n })}\n </span>\n {filters.query ? (\n <span className=\"badge badge-outline border-[#7170ff]/30 bg-[#7170ff]/10 text-[#c7c8ff]\">\n {t('admin.users.queryChip', { query: filters.query })}\n </span>\n ) : null}\n {filters.includeDeleted ? (\n <span className=\"badge badge-outline border-amber-300/25 bg-amber-300/10 text-amber-100\">\n {t('admin.users.includeDeleted')}\n </span>\n ) : null}\n {activeQuickFilter !== 'all' ? (\n <span className=\"badge badge-outline border-white/15 text-slate-300\">\n {t(`admin.users.filter.${activeQuickFilter}`)}\n </span>\n ) : null}\n {hasActiveFilters ? (\n <button\n className=\"btn btn-ghost btn-xs text-slate-400\"\n onClick={clearFilters}\n type=\"button\"\n >\n {t('admin.users.clearFilters')}\n </button>\n ) : null}\n </div>\n <label className=\"flex items-center gap-2 text-slate-500 text-sm\">\n <span>{t('admin.users.pageSize')}</span>\n <select\n aria-label={t('admin.users.pageSize')}\n className=\"select select-bordered select-xs border-white/10 bg-black/20 text-slate-200\"\n onChange={(event) => setPageSize(Number(event.target.value))}\n value={filters.pageSize}\n >\n <option value={10}>10</option>\n <option value={20}>20</option>\n <option value={50}>50</option>\n </select>\n </label>\n </div>\n\n <div className=\"overflow-x-auto px-0 pb-2\">\n <table className=\"table-zebra table [&_tbody_tr:hover]:bg-white/[0.04] [&_tbody_tr]:border-white/5 [&_tbody_tr]:transition [&_td]:border-white/5 [&_thead_th]:border-white/10 [&_thead_th]:bg-white/[0.035] [&_thead_th]:text-slate-500\">\n <thead>\n <tr>\n <th>{t('profile.email.label')}</th>\n <th>{t('admin.users.role')}</th>\n <th>{t('admin.users.source')}</th>\n <th>{t('admin.users.emailVerified')}</th>\n <th>{t('admin.users.secondFactor')}</th>\n <th>{t('admin.users.status')}</th>\n <th>{t('admin.users.actions')}</th>\n </tr>\n </thead>\n <tbody>\n {data.users.map((managedUser) => (\n <tr key={managedUser.sub}>\n <td>\n <div className=\"font-medium text-slate-100\">\n {managedUser.email}\n </div>\n <div className=\"max-w-64 truncate font-mono text-slate-600 text-xs\">\n {managedUser.sub}\n </div>\n </td>\n <td>\n <Badge\n tone={\n managedUser.role === 'admin' ? 'neutral' : 'ghost'\n }\n >\n {formatAdminRole(t, managedUser.role)}\n </Badge>\n </td>\n <td>\n <Badge\n tone={\n managedUser.managed_by === 'config'\n ? 'warning'\n : 'info'\n }\n >\n {formatManagedBy(t, managedUser.managed_by)}\n </Badge>\n </td>\n <td>\n {managedUser.email_verified\n ? t('common.yes')\n : t('common.no')}\n </td>\n <td>\n {managedUser.totp_registered\n ? t('admin.users.secondFactorTotp')\n : managedUser.passkey_count > 0\n ? t(\n managedUser.passkey_count === 1\n ? 'admin.users.secondFactorPasskey'\n : 'admin.users.secondFactorPasskeys',\n { count: managedUser.passkey_count },\n )\n : t('common.none')}\n </td>\n <td>\n <Badge\n tone={managedUser.deleted_at ? 'error' : 'success'}\n >\n {managedUser.deleted_at\n ? t('admin.users.deleted')\n : t('admin.users.active')}\n </Badge>\n </td>\n <td>\n {managedUser.managed_by === 'database' &&\n !managedUser.deleted_at ? (\n <div className=\"join rounded-xl border border-white/10 bg-black/20\">\n <button\n aria-label={t('admin.users.editUser', {\n email: managedUser.email,\n })}\n className=\"btn join-item btn-ghost btn-xs text-slate-300 hover:bg-white/[0.06]\"\n onClick={() =>\n setModal({ type: 'edit', user: managedUser })\n }\n type=\"button\"\n >\n {t('admin.users.edit')}\n </button>\n <button\n aria-label={t('admin.users.deleteUser', {\n email: managedUser.email,\n })}\n className=\"btn join-item btn-error btn-outline btn-xs border-red-400/25 bg-red-400/5 text-red-200 hover:bg-red-400/15\"\n onClick={() =>\n setModal({ type: 'delete', user: managedUser })\n }\n type=\"button\"\n >\n {t('admin.users.delete')}\n </button>\n </div>\n ) : (\n <span className=\"badge badge-outline border-white/15 text-slate-400\">\n {t('admin.users.readonly')}\n </span>\n )}\n </td>\n </tr>\n ))}\n {data.users.length === 0 ? (\n <tr>\n <td\n className=\"py-12 text-center text-slate-500\"\n colSpan={7}\n >\n {t('admin.users.emptyFiltered')}\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n\n <div className=\"flex items-center justify-between border-white/10 border-t bg-white/[0.015] p-5\">\n <button\n className=\"btn btn-outline btn-sm border-white/10 bg-white/[0.035] text-slate-300 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15\"\n disabled={filters.page <= 1}\n onClick={() =>\n setFilters((current) => ({\n ...current,\n page: current.page - 1,\n }))\n }\n type=\"button\"\n >\n {t('admin.users.previous')}\n </button>\n <span className=\"badge badge-ghost border-white/10 bg-black/20 text-slate-400\">\n {t('admin.users.page', { page: data.pagination.page })}\n </span>\n <button\n className=\"btn btn-outline btn-sm border-white/10 bg-white/[0.035] text-slate-300 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15\"\n disabled={\n data.pagination.page * data.pagination.page_size >=\n data.pagination.total\n }\n onClick={() =>\n setFilters((current) => ({\n ...current,\n page: current.page + 1,\n }))\n }\n type=\"button\"\n >\n {t('admin.users.next')}\n </button>\n </div>\n </div>\n </section>\n\n <UserFormModal\n isMutating={isMutating}\n modal={modal}\n onClose={() => setModal(null)}\n onCreate={(values) => createMutation.mutate(values)}\n onDelete={(sub) => deleteMutation.mutate(sub)}\n onUpdate={(values) => updateMutation.mutate(values)}\n />\n </AdminShell>\n );\n}\n\nfunction UserFormModal({\n modal,\n isMutating,\n onClose,\n onCreate,\n onUpdate,\n onDelete,\n}: {\n modal: UserModalState;\n isMutating: boolean;\n onClose: () => void;\n onCreate: (values: {\n email: string;\n password: string;\n role: 'user' | 'admin';\n email_verified: boolean;\n }) => void;\n onUpdate: (values: {\n sub: string;\n email: string;\n role: 'user' | 'admin';\n email_verified: boolean;\n }) => void;\n onDelete: (sub: string) => void;\n}) {\n const { t } = useTranslation();\n const defaultValues = useMemo(\n () => (modal?.type === 'edit' ? modal.user : null),\n [modal],\n );\n const dialogRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!modal) return undefined;\n\n const previousFocus =\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n const firstFocusable = dialogRef.current?.querySelector<HTMLElement>(\n 'input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), a[href], [tabindex]:not([tabindex=\"-1\"])',\n );\n firstFocusable?.focus();\n\n return () => {\n previousFocus?.focus();\n };\n }, [modal]);\n\n if (!modal) return null;\n\n if (modal.type === 'delete') {\n return (\n <div className=\"modal modal-open bg-black/70 backdrop-blur-sm\">\n <div\n aria-labelledby=\"admin-delete-user-title\"\n aria-modal=\"true\"\n className=\"modal-box border border-white/10 bg-[#101217] text-slate-100 shadow-[0_32px_100px_rgba(0,0,0,0.55)]\"\n onKeyDown={(event) => trapDialogFocus(event, onClose)}\n ref={dialogRef}\n role=\"dialog\"\n >\n <h3\n className=\"font-semibold text-xl tracking-[-0.03em]\"\n id=\"admin-delete-user-title\"\n >\n {t('admin.users.deleteTitle', { email: modal.user.email })}\n </h3>\n <div className=\"my-4 rounded-2xl border border-red-300/20 bg-red-400/10 p-4 text-red-100\">\n <p className=\"font-medium\">{t('admin.users.deleteWarning')}</p>\n <p className=\"mt-1 text-red-100/70 text-sm\">\n {t('admin.users.deleteDescription')}\n </p>\n </div>\n <div className=\"modal-action\">\n <button\n className=\"btn border-white/10 bg-white/[0.04] text-slate-200 hover:bg-white/[0.08]\"\n onClick={onClose}\n type=\"button\"\n >\n {t('admin.users.cancel')}\n </button>\n <button\n className=\"btn btn-error border-0 bg-red-500/80 text-white hover:bg-red-500\"\n disabled={isMutating}\n onClick={() => onDelete(modal.user.sub)}\n type=\"button\"\n >\n {t('admin.users.deleteConfirm')}\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n const title =\n modal.type === 'create'\n ? t('admin.users.create')\n : t('admin.users.editTitle');\n const submit =\n modal.type === 'create'\n ? t('admin.users.createSubmit')\n : t('admin.users.save');\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const formData = new FormData(event.currentTarget);\n const values = {\n email: String(formData.get('email') ?? ''),\n role: parseUserRole(formData.get('role')),\n email_verified: formData.get('email_verified') === 'on',\n };\n if (modal.type === 'create') {\n onCreate({\n ...values,\n password: String(formData.get('password') ?? ''),\n });\n } else {\n onUpdate({\n sub: modal.user.sub,\n ...values,\n });\n }\n };\n\n return (\n <div className=\"modal modal-open bg-black/70 backdrop-blur-sm\">\n <div\n aria-labelledby=\"admin-user-form-title\"\n aria-modal=\"true\"\n className=\"modal-box border border-white/10 bg-[#101217] text-slate-100 shadow-[0_32px_100px_rgba(0,0,0,0.55)]\"\n onKeyDown={(event) => trapDialogFocus(event, onClose)}\n ref={dialogRef}\n role=\"dialog\"\n >\n <h3\n className=\"font-semibold text-xl tracking-[-0.03em]\"\n id=\"admin-user-form-title\"\n >\n {title}\n </h3>\n <p className=\"mt-2 text-slate-500 text-sm\">\n {modal.type === 'create'\n ? t('admin.users.createHint')\n : t('admin.users.editHint')}\n </p>\n <form className=\"mt-4 space-y-4\" onSubmit={handleSubmit}>\n <fieldset className=\"fieldset\">\n <legend className=\"fieldset-legend text-slate-400\">\n {t('profile.email.label')}\n </legend>\n <input\n aria-label={t('profile.email.label')}\n className=\"input input-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60\"\n defaultValue={defaultValues?.email ?? ''}\n name=\"email\"\n required\n type=\"email\"\n />\n </fieldset>\n {modal.type === 'create' ? (\n <fieldset className=\"fieldset\">\n <legend className=\"fieldset-legend text-slate-400\">\n {t('admin.users.password')}\n </legend>\n <input\n aria-label={t('admin.users.password')}\n className=\"input input-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60\"\n name=\"password\"\n required\n type=\"password\"\n />\n </fieldset>\n ) : null}\n <fieldset className=\"fieldset\">\n <legend className=\"fieldset-legend text-slate-400\">\n {t('admin.users.role')}\n </legend>\n <select\n aria-label={t('admin.users.role')}\n className=\"select select-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60\"\n defaultValue={defaultValues?.role ?? 'user'}\n name=\"role\"\n >\n <option value=\"user\">{t('admin.users.roleUser')}</option>\n <option value=\"admin\">{t('admin.users.roleAdmin')}</option>\n </select>\n </fieldset>\n <label className=\"label cursor-pointer justify-start gap-3 rounded-box border border-white/10 bg-black/20 px-3 py-2\">\n <input\n className=\"checkbox border-white/20 bg-white/[0.04] checked:border-[#7170ff] checked:bg-[#7170ff]\"\n defaultChecked={defaultValues?.email_verified ?? false}\n name=\"email_verified\"\n type=\"checkbox\"\n />\n <span className=\"label-text text-slate-300\">\n {t('admin.users.emailVerified')}\n </span>\n </label>\n <div className=\"modal-action\">\n <button\n className=\"btn border-white/10 bg-white/[0.04] text-slate-200 hover:bg-white/[0.08]\"\n onClick={onClose}\n type=\"button\"\n >\n {t('admin.users.cancel')}\n </button>\n <button\n className=\"btn btn-primary border-0 bg-[#7170ff] text-white shadow-[0_14px_40px_rgba(113,112,255,0.32)] hover:bg-[#828fff]\"\n disabled={isMutating}\n type=\"submit\"\n >\n {submit}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n\nfunction trapDialogFocus(\n event: KeyboardEvent<HTMLDivElement>,\n onClose: () => void,\n) {\n if (event.key === 'Escape') {\n event.preventDefault();\n onClose();\n return;\n }\n\n if (event.key !== 'Tab') return;\n\n const focusableElements = Array.from(\n event.currentTarget.querySelectorAll<HTMLElement>(\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n ),\n );\n\n if (focusableElements.length === 0) return;\n\n const firstElement = focusableElements[0];\n const lastElement = focusableElements.at(-1);\n if (!firstElement || !lastElement) return;\n\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n return;\n }\n\n if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n}\n\nfunction formatAdminRole(\n t: ReturnType<typeof useTranslation>['t'],\n role: AdminUser['role'],\n) {\n return role === 'admin'\n ? t('admin.users.roleAdmin')\n : t('admin.users.roleUser');\n}\n\nfunction formatManagedBy(\n t: ReturnType<typeof useTranslation>['t'],\n managedBy: AdminUser['managed_by'],\n) {\n return managedBy === 'database'\n ? t('admin.users.sourceDatabase')\n : t('admin.users.sourceConfig');\n}\n\nfunction parseUserRole(value: FormDataEntryValue | null): 'user' | 'admin' {\n return value === 'admin' ? 'admin' : 'user';\n}\n\nfunction getActiveQuickFilter(\n filters: ReturnType<typeof normalizeAdminUsersQuery>,\n): QuickFilter {\n if (filters.role === 'admin') return 'admins';\n if (filters.managedBy === 'database') return 'database';\n if (filters.managedBy === 'config') return 'config';\n return 'all';\n}\n\nfunction QuickFilterButton({\n active,\n label,\n onClick,\n}: {\n active: boolean;\n label: string;\n onClick: () => void;\n}) {\n return (\n <button\n className={\n active\n ? 'btn join-item btn-xs border-0 bg-[#7170ff] text-white'\n : 'btn join-item btn-ghost btn-xs text-slate-400 hover:bg-white/[0.06] hover:text-slate-100'\n }\n onClick={onClick}\n type=\"button\"\n >\n {label}\n </button>\n );\n}\n\nfunction SummaryStat({ label, value }: { label: string; value: number }) {\n const { t } = useTranslation();\n return (\n <div className=\"stat border-white/10 bg-transparent p-6\">\n <div className=\"stat-title text-slate-500\">{label}</div>\n <div className=\"stat-value mt-1 text-slate-50 tracking-[-0.06em]\">\n {value}\n </div>\n <div className=\"stat-desc text-slate-600\">\n {t('admin.users.currentPage')}\n </div>\n </div>\n );\n}\n\ntype BadgeTone = 'neutral' | 'ghost' | 'warning' | 'info' | 'success' | 'error';\n\nconst badgeClasses: Record<BadgeTone, string> = {\n neutral: 'badge-primary border-[#7170ff]/30 bg-[#7170ff]/20 text-[#c7c8ff]',\n ghost: 'badge-ghost border-white/10 bg-white/[0.035] text-slate-400',\n warning: 'badge-warning border-amber-300/25 bg-amber-300/15 text-amber-100',\n info: 'badge-info border-sky-300/25 bg-sky-300/15 text-sky-100',\n success:\n 'badge-success border-emerald-300/25 bg-emerald-300/15 text-emerald-100',\n error: 'badge-error border-red-300/25 bg-red-300/15 text-red-100',\n};\n\nfunction Badge({ tone, children }: { tone: BadgeTone; children: ReactNode }) {\n return <span className={`badge ${badgeClasses[tone]}`}>{children}</span>;\n}\n"],"mappings":"6WA0CA,SAAS0B,GAAiB,CACxB,GAAM,CAAEC,KAAMpB,EAAe,EACvBa,EAAOH,EAAMW,gBAAgB,CAAEC,OAASC,GAAYA,EAAQV,IAAK,CAAC,EAexE,OAbIA,GAAMW,OAAS,SAaZ,EAAA,EAAA,KAAC,EAAD,CAAsBX,MAAK,CAAA,GAX9B,EAAA,EAAA,MAAC,EAAD,CAAY,YAAA,GAAY,SAAS,cAAjC,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,+CACXO,EAAE,sBAAsB,CACvB,CAAA,GACJ,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,4CACVA,EAAE,iCAAiC,CACnC,CAAA,CACO,GAKlB,CAEA,SAASK,EAAe,CAAEZ,QAA+B,CACvD,GAAM,CAAEc,KAAMC,GAAWjC,EAAiBc,CAAqB,EAI/D,OAHKmB,EAAOC,MAAMC,SAGX,EAAA,EAAA,KAAC,EAAD,CAAyBjB,MAAK,CAAA,GAF5B,EAAA,EAAA,KAAC,EAAD,CAAmB,CAAA,CAG9B,CAEA,SAASkB,EAAkB,CAAElB,QAA+B,CAC1D,GAAM,CAAEO,KAAMpB,EAAe,EACvBgC,EAActC,EAAe,EAC7B,CAACuC,EAAYC,IAAAA,EAAAA,EAAAA,UAA0B,EAAE,EACzC,CAACC,EAAqBC,IAAAA,EAAAA,EAAAA,UAAmC,EAAK,EAC9D,CAACC,EAASC,IAAAA,EAAAA,EAAAA,cAA6B/B,EAAyB,CAAC,EACjE,CAACgC,EAAQC,IAAAA,EAAAA,EAAAA,UAAmC,IAAI,EAChD,CAACC,EAAOC,IAAAA,EAAAA,EAAAA,UAAqC,IAAI,EACjD,CAAEf,QAAShC,EAAiBS,EAAuBiC,CAAO,CAAC,EAE3DM,EAAchB,EAAKiB,MAAMC,OAC5BC,GAAgB,CAACA,EAAYC,UAChC,EAAEC,OACIC,EAActB,EAAKiB,MAAMC,OAC5BC,GAAgBA,EAAYI,aAAe,QAC9C,EAAEF,OACIG,EAAgBxB,EAAKiB,MAAMC,OAC9BC,GAAgBA,EAAYI,aAAe,UAC9C,EAAEF,OACII,EAAoBC,EAAqBhB,CAAO,EAChDiB,EACJjB,EAAQkB,QAAU,IAClBlB,EAAQmB,gBACRnB,EAAQoB,YAAcC,IAAAA,IACtBrB,EAAQb,OAASkC,IAAAA,GACbC,EACJhC,EAAKiC,WAAWC,QAAU,EACtB,GACClC,EAAKiC,WAAWE,KAAO,GAAKnC,EAAKiC,WAAWG,UAAY,EACzDC,EAAUC,KAAKC,IACnBvC,EAAKiC,WAAWE,KAAOnC,EAAKiC,WAAWG,UACvCpC,EAAKiC,WAAWC,KAClB,EAEMM,EAAiB1E,EAAY,CACjC2E,WAAY/D,EACZgE,WAAY,CAAExD,KAAMyD,KAAe,CACjC,EAAiBC,kBAAkB,CAAEC,SAAU,CAAC,QAAS,OAAO,CAAE,CAAC,EACnEhC,EAAU,CACRvB,KAAM,UACNC,QAASE,EAAE,4BAA6B,CAAEqD,MAAOH,EAASG,KAAM,CAAC,CACnE,CAAC,EACD/B,EAAS,IAAI,CACf,EACAgC,YAAe,CACblC,EAAU,CAAEvB,KAAM,QAASC,QAASE,EAAE,6BAA6B,CAAE,CAAC,CACxE,CACF,CAAC,EAEKuD,EAAiBlF,EAAY,CACjC2E,WAAY5D,EACZ6D,WAAY,CAAExD,KAAMyD,KAAe,CACjC,EAAiBC,kBAAkB,CAAEC,SAAU,CAAC,QAAS,OAAO,CAAE,CAAC,EACnEhC,EAAU,CACRvB,KAAM,UACNC,QAASE,EAAE,4BAA6B,CAAEqD,MAAOH,EAASG,KAAM,CAAC,CACnE,CAAC,EACD/B,EAAS,IAAI,CACf,EACAgC,YAAe,CACblC,EAAU,CAAEvB,KAAM,QAASC,QAASE,EAAE,6BAA6B,CAAE,CAAC,CACxE,CACF,CAAC,EAEKwD,EAAiBnF,EAAY,CACjC2E,WAAY9D,EACZ+D,WAAY,CAAExD,KAAMyD,KAAe,CACjC,EAAiBC,kBAAkB,CAAEC,SAAU,CAAC,QAAS,OAAO,CAAE,CAAC,EACnEhC,EAAU,CACRvB,KAAM,UACNC,QAASE,EAAE,4BAA6B,CAAEqD,MAAOH,EAASG,KAAM,CAAC,CACnE,CAAC,EACD/B,EAAS,IAAI,CACf,EACAgC,YAAe,CACblC,EAAU,CAAEvB,KAAM,QAASC,QAASE,EAAE,6BAA6B,CAAE,CAAC,CACxE,CACF,CAAC,EAEKyD,EACJV,EAAeW,WACfH,EAAeG,WACfF,EAAeE,UAEXC,MAAoB,CACxBzC,EAAY0C,IAAa,CACvB,GAAGA,EACHzB,MAAOtB,EAAWgD,KAAK,EACvBzB,eAAgBrB,EAChB2B,KAAM,CACR,EAAE,CACJ,EAEMoB,MAAqB,CACzBhD,EAAc,EAAE,EAChBE,EAAuB,EAAK,EAC5BE,EAAW/B,EAAyB,CAAC,CACvC,EAEM4E,EAAeC,GAAqB,CACxC9C,EAAY0C,IAAa,CAAE,GAAGA,EAASlB,KAAM,EAAGsB,UAAS,EAAE,CAC7D,EAEMC,EAAoBC,GAA4B,CACpDhD,EAAY0C,IAAa,CACvB,GAAGA,EACHlB,KAAM,EACNL,UACE6B,IAAe,WACX,WACAA,IAAe,SACb,SACA5B,IAAAA,GACRlC,KAAM8D,IAAe,SAAW,QAAU5B,IAAAA,EAC5C,EAAE,CACJ,EAEA,OACE,EAAA,EAAA,MAAC,EAAD,CACE,QAAQ,QACR,YAAatC,EAAE,yBAAyB,EACxC,MAAOA,EAAE,mBAAmB,EACtBP,gBAJR,EAME,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,2LAAf,EACE,EAAA,EAAA,KAAC,EAAD,CACE,MAAOO,EAAE,0BAA0B,EACnC,MAAOuB,CAAY,CAAA,GAErB,EAAA,EAAA,KAAC,EAAD,CACE,MAAOvB,EAAE,0BAA0B,EACnC,MAAO6B,CAAY,CAAA,GAErB,EAAA,EAAA,KAAC,EAAD,CACE,MAAO7B,EAAE,4BAA4B,EACrC,MAAO+B,CAAc,CAAA,CAEpB,IAEJZ,GACC,EAAA,EAAA,MAAC,MAAD,CACE,YAAWA,EAAOtB,OAAS,UAAY,SAAW,YAClD,UACEsB,EAAOtB,OAAS,UACZ,sEACA,0DAEN,KAAMsB,EAAOtB,OAAS,UAAY,SAAW,iBAP/C,EASE,EAAA,EAAA,KAAC,OAAD,CAAA,SAAOsB,EAAOtB,OAAS,UAAY,IAAM,GAAU,CAAA,GACnD,EAAA,EAAA,KAAC,OAAD,CAAA,SAAOsB,EAAOrB,OAAc,CAAA,GAC5B,EAAA,EAAA,KAAC,SAAD,CACE,aAAYE,EAAE,cAAc,EAC5B,UAAU,4CACV,YAAeoB,EAAU,IAAI,EAC7B,KAAK,kBAAQ,GAGP,CAAA,CACL,IACH,MAEJ,EAAA,EAAA,KAAC,UAAD,CAAS,UAAU,qIACjB,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,+BAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,yHAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,wCAAf,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,6EAA6E,CAAA,GAC7F,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,0EACbpB,EAAE,8BAA8B,CAC7B,CAAA,CACH,KACL,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,qCACXA,EAAE,uBAAuB,CACxB,CAAA,GACJ,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,uCACVA,EAAE,oBAAqB,CAAEmE,MAAO5D,EAAKiC,WAAWC,KAAM,CAAC,CACvD,CAAA,CACA,CAAA,CAAA,GACL,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,4CAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,2DAAf,EACE,EAAA,EAAA,KAAC,QAAD,CACE,aAAYzC,EAAE,+BAA+B,EAC7C,UAAU,2IACV,SAAWoE,GAAUtD,EAAcsD,EAAMC,OAAOC,KAAK,EACrD,UAAYF,GAAU,CAChBA,EAAMG,MAAQ,SAASZ,EAAY,CACzC,EACA,YAAa3D,EAAE,+BAA+B,EAC9C,KAAK,SACL,MAAOa,CAAW,CAAA,GAEpB,EAAA,EAAA,MAAC,QAAD,CAAO,UAAU,6GAAjB,EACE,EAAA,EAAA,KAAC,QAAD,CACE,QAASE,EACT,UAAU,qGACV,SAAWqD,GACTpD,EAAuBoD,EAAMC,OAAOG,OAAO,EAE7C,KAAK,UAAU,CAAA,GAEjB,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,qCACbxE,EAAE,4BAA4B,CAC3B,CAAA,CACD,KACP,EAAA,EAAA,KAAC,SAAD,CACE,UAAU,kHACV,QAAS2D,EACT,KAAK,kBAEJ3D,EAAE,oBAAoB,CACjB,CAAA,GACR,EAAA,EAAA,KAAC,SAAD,CACE,UAAU,kHACV,YAAesB,EAAS,CAAE9B,KAAM,QAAS,CAAC,EAC1C,KAAK,kBAEJQ,EAAE,oBAAoB,CACjB,CAAA,CACL,KACL,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,mEAAf,EACE,EAAA,EAAA,KAAC,EAAD,CACE,OAAQgC,IAAsB,MAC9B,MAAOhC,EAAE,wBAAwB,EACjC,YAAeiE,EAAiB,KAAK,CAAE,CAAA,GAEzC,EAAA,EAAA,KAAC,EAAD,CACE,OAAQjC,IAAsB,WAC9B,MAAOhC,EAAE,6BAA6B,EACtC,YAAeiE,EAAiB,UAAU,CAAE,CAAA,GAE9C,EAAA,EAAA,KAAC,EAAD,CACE,OAAQjC,IAAsB,SAC9B,MAAOhC,EAAE,2BAA2B,EACpC,YAAeiE,EAAiB,QAAQ,CAAE,CAAA,GAE5C,EAAA,EAAA,KAAC,EAAD,CACE,OAAQjC,IAAsB,SAC9B,MAAOhC,EAAE,2BAA2B,EACpC,YAAeiE,EAAiB,QAAQ,CAAE,CAAA,CAEzC,GACF,GACF,KAEL,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,kEAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,qDAAf,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,0BACbjE,EAAE,2BAA4B,CAC7ByE,KAAMlC,EACNmC,GAAI9B,EACJH,MAAOlC,EAAKiC,WAAWC,KACzB,CAAC,CACG,CAAA,EACLxB,EAAQkB,OACP,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,kFACbnC,EAAE,wBAAyB,CAAEmC,MAAOlB,EAAQkB,KAAM,CAAC,CAChD,CAAA,EACJ,KACHlB,EAAQmB,gBACP,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,kFACbpC,EAAE,4BAA4B,CAC3B,CAAA,EACJ,KACHgC,IAAsB,MAInB,MAHF,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,8DACbhC,EAAE,sBAAsBgC,GAAmB,CACxC,CAAA,EAEPE,GACC,EAAA,EAAA,KAAC,SAAD,CACE,UAAU,sCACV,QAAS4B,EACT,KAAK,kBAEJ9D,EAAE,0BAA0B,CACvB,CAAA,EACN,IACD,KACL,EAAA,EAAA,MAAC,QAAD,CAAO,UAAU,0DAAjB,EACE,EAAA,EAAA,KAAC,OAAD,CAAA,SAAOA,EAAE,sBAAsB,CAAQ,CAAA,GACvC,EAAA,EAAA,MAAC,SAAD,CACE,aAAYA,EAAE,sBAAsB,EACpC,UAAU,8EACV,SAAWoE,GAAUL,EAAYY,OAAOP,EAAMC,OAAOC,KAAK,CAAC,EAC3D,MAAOrD,EAAQ+C,kBAJjB,EAME,EAAA,EAAA,KAAC,SAAD,CAAQ,MAAO,YAAI,IAAU,CAAA,GAC7B,EAAA,EAAA,KAAC,SAAD,CAAQ,MAAO,YAAI,IAAU,CAAA,GAC7B,EAAA,EAAA,KAAC,SAAD,CAAQ,MAAO,YAAI,IAAU,CAAA,CACvB,GACH,GACJ,KAEL,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,sCACb,EAAA,EAAA,MAAC,QAAD,CAAO,UAAU,iOAAjB,EACE,EAAA,EAAA,KAAC,QAAD,CAAA,UACE,EAAA,EAAA,MAAC,KAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,KAAD,CAAA,SAAKhE,EAAE,qBAAqB,CAAM,CAAA,GAClC,EAAA,EAAA,KAAC,KAAD,CAAA,SAAKA,EAAE,kBAAkB,CAAM,CAAA,GAC/B,EAAA,EAAA,KAAC,KAAD,CAAA,SAAKA,EAAE,oBAAoB,CAAM,CAAA,GACjC,EAAA,EAAA,KAAC,KAAD,CAAA,SAAKA,EAAE,2BAA2B,CAAM,CAAA,GACxC,EAAA,EAAA,KAAC,KAAD,CAAA,SAAKA,EAAE,0BAA0B,CAAM,CAAA,GACvC,EAAA,EAAA,KAAC,KAAD,CAAA,SAAKA,EAAE,oBAAoB,CAAM,CAAA,GACjC,EAAA,EAAA,KAAC,KAAD,CAAA,SAAKA,EAAE,qBAAqB,CAAM,CAAA,CAChC,CAAA,CAAA,CACC,CAAA,GACP,EAAA,EAAA,MAAC,QAAD,CAAA,SAAA,CACGO,EAAKiB,MAAMoD,IAAKlD,IACf,EAAA,EAAA,MAAC,KAAD,CAAA,SAAA,EACE,EAAA,EAAA,MAAC,KAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,sCACZA,EAAY2B,KACV,CAAA,GACL,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,8DACZ3B,EAAYmD,GACV,CAAA,CACH,CAAA,CAAA,GACJ,EAAA,EAAA,KAAC,KAAD,CAAA,UACE,EAAA,EAAA,KAAC,EAAD,CACE,KACEnD,EAAYtB,OAAS,QAAU,UAAY,iBAG5C0E,EAAgB9E,EAAG0B,EAAYtB,IAAI,CAC/B,CAAA,CACL,CAAA,GACJ,EAAA,EAAA,KAAC,KAAD,CAAA,UACE,EAAA,EAAA,KAAC,EAAD,CACE,KACEsB,EAAYI,aAAe,SACvB,UACA,gBAGLiD,EAAgB/E,EAAG0B,EAAYI,UAAU,CACrC,CAAA,CACL,CAAA,GACJ,EAAA,EAAA,KAAC,KAAD,CAAA,SACGJ,EAAYsD,eACThF,EAAE,YAAY,EACdA,EAAE,WAAW,CACf,CAAA,GACJ,EAAA,EAAA,KAAC,KAAD,CAAA,SACG0B,EAAYuD,gBACTjF,EAAE,8BAA8B,EAChC0B,EAAYwD,cAAgB,EAC1BlF,EACE0B,EAAYwD,gBAAkB,EAC1B,kCACA,mCACJ,CAAEf,MAAOzC,EAAYwD,aAAc,CACrC,EACAlF,EAAE,aAAa,CACnB,CAAA,GACJ,EAAA,EAAA,KAAC,KAAD,CAAA,UACE,EAAA,EAAA,KAAC,EAAD,CACE,KAAM0B,EAAYC,WAAa,QAAU,mBAExCD,EAAYC,WACT3B,EAAE,qBAAqB,EACvBA,EAAE,oBAAoB,CACrB,CAAA,CACL,CAAA,GACJ,EAAA,EAAA,KAAC,KAAD,CAAA,SACG0B,EAAYI,aAAe,YAC5B,CAACJ,EAAYC,YACX,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,8DAAf,EACE,EAAA,EAAA,KAAC,SAAD,CACE,aAAY3B,EAAE,uBAAwB,CACpCqD,MAAO3B,EAAY2B,KACrB,CAAC,EACD,UAAU,sEACV,YACE/B,EAAS,CAAE9B,KAAM,OAAQC,KAAMiC,CAAY,CAAC,EAE9C,KAAK,kBAEJ1B,EAAE,kBAAkB,CACf,CAAA,GACR,EAAA,EAAA,KAAC,SAAD,CACE,aAAYA,EAAE,yBAA0B,CACtCqD,MAAO3B,EAAY2B,KACrB,CAAC,EACD,UAAU,6GACV,YACE/B,EAAS,CAAE9B,KAAM,SAAUC,KAAMiC,CAAY,CAAC,EAEhD,KAAK,kBAEJ1B,EAAE,oBAAoB,CACjB,CAAA,CACL,KAEL,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,8DACbA,EAAE,sBAAsB,CACrB,CAAA,CAEN,CAAA,CACF,CAAA,EA1FK0B,EAAYmD,GA0FjB,CACL,EACAtE,EAAKiB,MAAMI,SAAW,GACrB,EAAA,EAAA,KAAC,KAAD,CAAA,UACE,EAAA,EAAA,KAAC,KAAD,CACE,UAAU,mCACV,QAAS,WAER5B,EAAE,2BAA2B,CAC5B,CAAA,CACF,CAAA,EACF,IACC,CAAA,CAAA,CACF,GACJ,CAAA,GAEL,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,2FAAf,EACE,EAAA,EAAA,KAAC,SAAD,CACE,UAAU,yHACV,SAAUiB,EAAQyB,MAAQ,EAC1B,YACExB,EAAY0C,IAAa,CACvB,GAAGA,EACHlB,KAAMkB,EAAQlB,KAAO,CACvB,EAAE,EAEJ,KAAK,kBAEJ1C,EAAE,sBAAsB,CACnB,CAAA,GACR,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,wEACbA,EAAE,mBAAoB,CAAE0C,KAAMnC,EAAKiC,WAAWE,IAAK,CAAC,CACjD,CAAA,GACN,EAAA,EAAA,KAAC,SAAD,CACE,UAAU,yHACV,SACEnC,EAAKiC,WAAWE,KAAOnC,EAAKiC,WAAWG,WACvCpC,EAAKiC,WAAWC,MAElB,YACEvB,EAAY0C,IAAa,CACvB,GAAGA,EACHlB,KAAMkB,EAAQlB,KAAO,CACvB,EAAE,EAEJ,KAAK,kBAEJ1C,EAAE,kBAAkB,CACf,CAAA,CACL,GACF,GACE,CAAA,GAET,EAAA,EAAA,KAAC,EAAD,CACcyD,aACLpC,QACP,YAAeC,EAAS,IAAI,EAC5B,SAAW6D,GAAWpC,EAAeqC,OAAOD,CAAM,EAClD,SAAWN,GAAQrB,EAAe4B,OAAOP,CAAG,EAC5C,SAAWM,GAAW5B,EAAe6B,OAAOD,CAAM,CAAE,CAAA,CAE5C,GAEhB,CAEA,SAASE,EAAc,CACrBhE,QACAoC,aACA6B,UACAC,WACAC,WACAC,YAkBC,CACD,GAAM,CAAEzF,KAAMpB,EAAe,EACvB+G,GAAAA,EAAAA,EAAAA,aACGtE,GAAO7B,OAAS,OAAS6B,EAAM5B,KAAO,KAC7C,CAAC4B,CAAK,CACR,EACMuE,GAAAA,EAAAA,EAAAA,QAAmC,IAAI,EAmB7C,IAjBApH,EAAAA,EAAAA,eAAgB,CACd,GAAI,CAAC6C,EAAO,OAEZ,IAAMyE,EACJC,SAASC,yBAAyBC,YAC9BF,SAASC,cACT,KAMN,OALuBJ,EAAUhC,SAASuC,cACxC,2IACF,IACgBC,MAAM,MAET,CACXN,GAAeM,MAAM,CACvB,CACF,EAAG,CAAC/E,CAAK,CAAC,EAEN,CAACA,EAAO,OAAO,KAEnB,GAAIA,EAAM7B,OAAS,SACjB,OACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,0DACb,EAAA,EAAA,MAAC,MAAD,CACE,kBAAgB,0BAChB,aAAW,OACX,UAAU,sGACV,UAAY4E,GAAUiC,EAAgBjC,EAAOkB,CAAO,EACpD,IAAKM,EACL,KAAK,kBANP,EAQE,EAAA,EAAA,KAAC,KAAD,CACE,UAAU,2CACV,GAAG,mCAEF5F,EAAE,0BAA2B,CAAEqD,MAAOhC,EAAM5B,KAAK4D,KAAM,CAAC,CACvD,CAAA,GACJ,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,oFAAf,EACE,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,uBAAerD,EAAE,2BAA2B,CAAK,CAAA,GAC9D,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,wCACVA,EAAE,+BAA+B,CACjC,CAAA,CACA,KACL,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,wBAAf,EACE,EAAA,EAAA,KAAC,SAAD,CACE,UAAU,2EACV,QAASsF,EACT,KAAK,kBAEJtF,EAAE,oBAAoB,CACjB,CAAA,GACR,EAAA,EAAA,KAAC,SAAD,CACE,UAAU,mEACV,SAAUyD,EACV,YAAegC,EAASpE,EAAM5B,KAAKoF,GAAG,EACtC,KAAK,kBAEJ7E,EAAE,2BAA2B,CACxB,CAAA,CACL,GACF,GACF,CAAA,EAIT,IAAMsG,EACJjF,EAAM7B,OAAS,SACXQ,EAAE,oBAAoB,EACtBA,EAAE,uBAAuB,EACzBuG,EACJlF,EAAM7B,OAAS,SACXQ,EAAE,0BAA0B,EAC5BA,EAAE,kBAAkB,EAuB1B,OACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,0DACb,EAAA,EAAA,MAAC,MAAD,CACE,kBAAgB,wBAChB,aAAW,OACX,UAAU,sGACV,UAAYoE,GAAUiC,EAAgBjC,EAAOkB,CAAO,EACpD,IAAKM,EACL,KAAK,kBANP,EAQE,EAAA,EAAA,KAAC,KAAD,CACE,UAAU,2CACV,GAAG,iCAEFU,CACC,CAAA,GACJ,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,uCACVjF,EAAM7B,OAAS,SACZQ,EAAE,wBAAwB,EAC1BA,EAAE,sBAAsB,CAC3B,CAAA,GACH,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,iBAAiB,SA1CjBoE,GAAsC,CAC1DA,EAAMuC,eAAe,EACrB,IAAMC,EAAW,IAAIC,SAASzC,EAAM0C,aAAa,EAC3C3B,EAAS,CACb9B,MAAO0D,OAAOH,EAASI,IAAI,OAAO,GAAK,EAAE,EACzC5G,KAAM6G,EAAcL,EAASI,IAAI,MAAM,CAAC,EACxChC,eAAgB4B,EAASI,IAAI,gBAAgB,IAAM,IACrD,EACI3F,EAAM7B,OAAS,SACjB+F,EAAS,CACP,GAAGJ,EACHO,SAAUqB,OAAOH,EAASI,IAAI,UAAU,GAAK,EAAE,CACjD,CAAC,EAEDxB,EAAS,CACPX,IAAKxD,EAAM5B,KAAKoF,IAChB,GAAGM,CACL,CAAC,CAEL,WAuBM,EACE,EAAA,EAAA,MAAC,WAAD,CAAU,UAAU,oBAApB,EACE,EAAA,EAAA,KAAC,SAAD,CAAQ,UAAU,0CACfnF,EAAE,qBAAqB,CAClB,CAAA,GACR,EAAA,EAAA,KAAC,QAAD,CACE,aAAYA,EAAE,qBAAqB,EACnC,UAAU,mGACV,aAAc2F,GAAetC,OAAS,GACtC,KAAK,QACL,SAAA,GACA,KAAK,OAAO,CAAA,CAEN,IACThC,EAAM7B,OAAS,UACd,EAAA,EAAA,MAAC,WAAD,CAAU,UAAU,oBAApB,EACE,EAAA,EAAA,KAAC,SAAD,CAAQ,UAAU,0CACfQ,EAAE,sBAAsB,CACnB,CAAA,GACR,EAAA,EAAA,KAAC,QAAD,CACE,aAAYA,EAAE,sBAAsB,EACpC,UAAU,mGACV,KAAK,WACL,SAAA,GACA,KAAK,UAAU,CAAA,CAET,IACR,MACJ,EAAA,EAAA,MAAC,WAAD,CAAU,UAAU,oBAApB,EACE,EAAA,EAAA,KAAC,SAAD,CAAQ,UAAU,0CACfA,EAAE,kBAAkB,CACf,CAAA,GACR,EAAA,EAAA,MAAC,SAAD,CACE,aAAYA,EAAE,kBAAkB,EAChC,UAAU,qGACV,aAAc2F,GAAevF,MAAQ,OACrC,KAAK,gBAJP,EAME,EAAA,EAAA,KAAC,SAAD,CAAQ,MAAM,gBAAQJ,EAAE,sBAAsB,CAAU,CAAA,GACxD,EAAA,EAAA,KAAC,SAAD,CAAQ,MAAM,iBAASA,EAAE,uBAAuB,CAAU,CAAA,CACpD,GACA,KACV,EAAA,EAAA,MAAC,QAAD,CAAO,UAAU,6GAAjB,EACE,EAAA,EAAA,KAAC,QAAD,CACE,UAAU,yFACV,eAAgB2F,GAAeX,gBAAkB,GACjD,KAAK,iBACL,KAAK,UAAU,CAAA,GAEjB,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,qCACbhF,EAAE,2BAA2B,CAC1B,CAAA,CACD,KACP,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,wBAAf,EACE,EAAA,EAAA,KAAC,SAAD,CACE,UAAU,2EACV,QAASsF,EACT,KAAK,kBAEJtF,EAAE,oBAAoB,CACjB,CAAA,GACR,EAAA,EAAA,KAAC,SAAD,CACE,UAAU,kHACV,SAAUyD,EACV,KAAK,kBAEJ8C,CACK,CAAA,CACL,GACD,GACH,GACF,CAAA,CAET,CAEA,SAASF,EACPjC,EACAkB,EACA,CACA,GAAIlB,EAAMG,MAAQ,SAAU,CAC1BH,EAAMuC,eAAe,EACrBrB,EAAQ,EACR,MACF,CAEA,GAAIlB,EAAMG,MAAQ,MAAO,OAEzB,IAAM4C,EAAoBC,MAAM3C,KAC9BL,EAAM0C,cAAcO,iBAClB,2IACF,CACF,EAEA,GAAIF,EAAkBvF,SAAW,EAAG,OAEpC,IAAM0F,EAAeH,EAAkB,GACjCI,EAAcJ,EAAkBK,GAAG,EAAE,EACvC,MAACF,GAAgB,CAACC,GAEtB,IAAInD,EAAMqD,UAAY1B,SAASC,gBAAkBsB,EAAc,CAC7DlD,EAAMuC,eAAe,EACrBY,EAAYnB,MAAM,EAClB,MACF,CAEI,CAAChC,EAAMqD,UAAY1B,SAASC,gBAAkBuB,IAChDnD,EAAMuC,eAAe,EACrBW,EAAalB,MAAM,EAJrB,CAMF,CAEA,SAAStB,EACP9E,EACAI,EACA,CACA,OACIJ,EADGI,IAAS,QACV,wBACA,sBAAsB,CAC9B,CAEA,SAAS2E,EACP/E,EACAqC,EACA,CACA,OACIrC,EADGqC,IAAc,WACf,6BACA,0BAA0B,CAClC,CAEA,SAAS4E,EAAc3C,EAAoD,CACzE,OAAOA,IAAU,QAAU,QAAU,MACvC,CAEA,SAASrC,EACPhB,EACa,CAIb,OAHIA,EAAQb,OAAS,QAAgB,SACjCa,EAAQoB,YAAc,WAAmB,WACzCpB,EAAQoB,YAAc,SAAiB,SACpC,KACT,CAEA,SAASuF,EAAkB,CACzBC,SACAC,QACAC,WAKC,CACD,OACE,EAAA,EAAA,KAAC,SAAD,CACE,UACEF,EACI,wDACA,2FAEGE,UACT,KAAK,kBAEJD,CACK,CAAA,CAEZ,CAEA,SAASE,EAAY,CAAEF,QAAOxD,SAA2C,CACvE,GAAM,CAAEtE,KAAMpB,EAAe,EAC7B,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,mDAAf,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,qCAA6BkJ,CAAW,CAAA,GACvD,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,4DACZxD,CACE,CAAA,GACL,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,oCACZtE,EAAE,yBAAyB,CACzB,CAAA,CACF,GAET,CAIA,IAAMkI,EAA0C,CAC9CE,QAAS,mEACTC,MAAO,8DACPC,QAAS,mEACTC,KAAM,0DACNC,QACE,yEACFC,MAAO,0DACT,EAEA,SAASC,EAAM,CAAE7I,OAAM8I,YAAsD,CAC3E,OAAO,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,SAAST,EAAarI,KAAU8I,UAAe,CAAA,CACzE"}
|
|
1
|
+
{"version":3,"file":"users-YtDGJlDl.js","names":["useMutation","useQueryClient","useSuspenseQuery","useEffect","useMemo","useRef","useState","useTranslation","AdminDisabledPanel","AdminShell","PageLayout","adminUsersQueryOptions","createAdminUser","deleteAdminUser","normalizeAdminUsersQuery","updateAdminUser","appConfigQueryOptions","Route","UserModalState","type","user","AdminUser","QuickFilter","NoticeState","tone","message","AdminUsersPage","t","useRouteContext","select","context","role","AdminUsersGate","SessionUser","data","config","admin","enabled","AdminUsersContent","queryClient","draftQuery","setDraftQuery","draftIncludeDeleted","setDraftIncludeDeleted","filters","setFilters","notice","setNotice","modal","setModal","activeUsers","users","filter","managedUser","deleted_at","length","configUsers","managed_by","databaseUsers","activeQuickFilter","getActiveQuickFilter","hasActiveFilters","query","includeDeleted","managedBy","undefined","pageStart","pagination","total","page","page_size","pageEnd","Math","min","createMutation","mutationFn","onSuccess","nextUser","invalidateQueries","queryKey","email","onError","updateMutation","deleteMutation","isMutating","isPending","applySearch","current","trim","clearFilters","setPageSize","pageSize","applyQuickFilter","nextFilter","count","event","target","value","key","checked","from","to","Number","map","sub","formatAdminRole","formatManagedBy","email_verified","totp_registered","passkey_count","values","mutate","UserFormModal","onClose","onCreate","onUpdate","onDelete","password","defaultValues","dialogRef","HTMLDivElement","previousFocus","document","activeElement","HTMLElement","firstFocusable","querySelector","focus","trapDialogFocus","title","submit","handleSubmit","FormEvent","HTMLFormElement","preventDefault","formData","FormData","currentTarget","String","get","parseUserRole","KeyboardEvent","focusableElements","Array","querySelectorAll","firstElement","lastElement","at","shiftKey","ReturnType","FormDataEntryValue","QuickFilterButton","active","label","onClick","SummaryStat","BadgeTone","badgeClasses","Record","neutral","ghost","warning","info","success","error","Badge","children","ReactNode","component"],"sources":["../../../frontend/src/routes/admin/users/index.tsx?tsr-split=component"],"sourcesContent":["import {\n useMutation,\n useQueryClient,\n useSuspenseQuery,\n} from '@tanstack/react-query';\nimport { createFileRoute, redirect } from '@tanstack/react-router';\nimport type { FormEvent, KeyboardEvent, ReactNode } from 'react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { AdminDisabledPanel } from '#frontend/features/admin/admin-disabled-panel.tsx';\nimport { AdminShell } from '#frontend/features/admin/admin-shell.tsx';\nimport { PageLayout } from '#frontend/features/layout/page-layout.tsx';\nimport {\n type AdminUser,\n adminUsersQueryOptions,\n createAdminUser,\n deleteAdminUser,\n normalizeAdminUsersQuery,\n updateAdminUser,\n} from '#frontend/queries/admin-users.ts';\nimport { appConfigQueryOptions } from '#frontend/queries/config.ts';\nimport type { SessionUser } from '#frontend/queries/session.ts';\n\nexport const Route = createFileRoute('/admin/users/')({\n component: AdminUsersPage,\n beforeLoad: async ({ context }) => {\n if (!context.user) {\n throw redirect({ to: '/login' });\n }\n },\n});\n\ntype UserModalState =\n | { type: 'create' }\n | { type: 'edit'; user: AdminUser }\n | { type: 'delete'; user: AdminUser }\n | null;\n\ntype QuickFilter = 'all' | 'database' | 'config' | 'admins';\n\ntype NoticeState = { tone: 'success' | 'error'; message: string } | null;\n\nfunction AdminUsersPage() {\n const { t } = useTranslation();\n const user = Route.useRouteContext({ select: (context) => context.user });\n\n if (user?.role !== 'admin') {\n return (\n <PageLayout cardPadding maxWidth=\"md\">\n <h1 className=\"mb-2 text-center font-bold text-2xl\">\n {t('admin.accessRequired')}\n </h1>\n <p className=\"text-center text-base-content/60\">\n {t('admin.accessRequiredDescription')}\n </p>\n </PageLayout>\n );\n }\n\n return <AdminUsersGate user={user} />;\n}\n\nfunction AdminUsersGate({ user }: { user: SessionUser }) {\n const { data: config } = useSuspenseQuery(appConfigQueryOptions);\n if (!config.admin.enabled) {\n return <AdminDisabledPanel />;\n }\n return <AdminUsersContent user={user} />;\n}\n\nfunction AdminUsersContent({ user }: { user: SessionUser }) {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n const [draftQuery, setDraftQuery] = useState('');\n const [draftIncludeDeleted, setDraftIncludeDeleted] = useState(false);\n const [filters, setFilters] = useState(() => normalizeAdminUsersQuery());\n const [notice, setNotice] = useState<NoticeState>(null);\n const [modal, setModal] = useState<UserModalState>(null);\n const { data } = useSuspenseQuery(adminUsersQueryOptions(filters));\n\n const activeUsers = data.users.filter(\n (managedUser) => !managedUser.deleted_at,\n ).length;\n const configUsers = data.users.filter(\n (managedUser) => managedUser.managed_by === 'config',\n ).length;\n const databaseUsers = data.users.filter(\n (managedUser) => managedUser.managed_by === 'database',\n ).length;\n const activeQuickFilter = getActiveQuickFilter(filters);\n const hasActiveFilters =\n filters.query !== '' ||\n filters.includeDeleted ||\n filters.managedBy !== undefined ||\n filters.role !== undefined;\n const pageStart =\n data.pagination.total === 0\n ? 0\n : (data.pagination.page - 1) * data.pagination.page_size + 1;\n const pageEnd = Math.min(\n data.pagination.page * data.pagination.page_size,\n data.pagination.total,\n );\n\n const createMutation = useMutation({\n mutationFn: createAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n setNotice({\n tone: 'success',\n message: t('admin.users.createdNotice', { email: nextUser.email }),\n });\n setModal(null);\n },\n onError: () => {\n setNotice({ tone: 'error', message: t('admin.users.operationFailed') });\n },\n });\n\n const updateMutation = useMutation({\n mutationFn: updateAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n setNotice({\n tone: 'success',\n message: t('admin.users.updatedNotice', { email: nextUser.email }),\n });\n setModal(null);\n },\n onError: () => {\n setNotice({ tone: 'error', message: t('admin.users.operationFailed') });\n },\n });\n\n const deleteMutation = useMutation({\n mutationFn: deleteAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n setNotice({\n tone: 'success',\n message: t('admin.users.deletedNotice', { email: nextUser.email }),\n });\n setModal(null);\n },\n onError: () => {\n setNotice({ tone: 'error', message: t('admin.users.operationFailed') });\n },\n });\n\n const isMutating =\n createMutation.isPending ||\n updateMutation.isPending ||\n deleteMutation.isPending;\n\n const applySearch = () => {\n setFilters((current) => ({\n ...current,\n query: draftQuery.trim(),\n includeDeleted: draftIncludeDeleted,\n page: 1,\n }));\n };\n\n const clearFilters = () => {\n setDraftQuery('');\n setDraftIncludeDeleted(false);\n setFilters(normalizeAdminUsersQuery());\n };\n\n const setPageSize = (pageSize: number) => {\n setFilters((current) => ({ ...current, page: 1, pageSize }));\n };\n\n const applyQuickFilter = (nextFilter: QuickFilter) => {\n setFilters((current) => ({\n ...current,\n page: 1,\n managedBy:\n nextFilter === 'database'\n ? 'database'\n : nextFilter === 'config'\n ? 'config'\n : undefined,\n role: nextFilter === 'admins' ? 'admin' : undefined,\n }));\n };\n\n return (\n <AdminShell\n current=\"users\"\n description={t('admin.users.description')}\n title={t('admin.users.title')}\n user={user}\n >\n <div className=\"stats stats-vertical lg:stats-horizontal w-full overflow-hidden rounded-[1.5rem] border border-white/10 bg-white/[0.035] shadow-[0_24px_80px_rgba(0,0,0,0.24)] backdrop-blur-xl\">\n <SummaryStat\n label={t('admin.users.activeOnPage')}\n value={activeUsers}\n />\n <SummaryStat\n label={t('admin.users.configOnPage')}\n value={configUsers}\n />\n <SummaryStat\n label={t('admin.users.databaseOnPage')}\n value={databaseUsers}\n />\n </div>\n\n {notice ? (\n <div\n aria-live={notice.tone === 'success' ? 'polite' : 'assertive'}\n className={\n notice.tone === 'success'\n ? 'alert mt-6 border-emerald-300/20 bg-emerald-300/10 text-emerald-100'\n : 'alert mt-6 border-red-300/20 bg-red-300/10 text-red-100'\n }\n role={notice.tone === 'success' ? 'status' : 'alert'}\n >\n <span>{notice.tone === 'success' ? '✓' : '!'}</span>\n <span>{notice.message}</span>\n <button\n aria-label={t('common.close')}\n className=\"btn btn-ghost btn-xs ml-auto text-current\"\n onClick={() => setNotice(null)}\n type=\"button\"\n >\n ×\n </button>\n </div>\n ) : null}\n\n <section className=\"card mt-6 overflow-hidden border border-white/10 bg-white/[0.035] shadow-[0_24px_80px_rgba(0,0,0,0.24)] backdrop-blur-xl\">\n <div className=\"card-body gap-5 p-0\">\n <div className=\"flex flex-col gap-4 border-white/10 border-b bg-white/[0.015] p-6 xl:flex-row xl:items-end xl:justify-between\">\n <div>\n <div className=\"mb-2 flex items-center gap-2\">\n <span className=\"h-2 w-2 rounded-full bg-emerald-400 shadow-[0_0_18px_rgba(52,211,153,0.75)]\" />\n <span className=\"font-medium text-slate-500 text-xs uppercase tracking-[0.18em]\">\n {t('admin.users.directoryEyebrow')}\n </span>\n </div>\n <h2 className=\"card-title text-slate-100\">\n {t('admin.users.directory')}\n </h2>\n <p className=\"mt-1 text-slate-400 text-sm\">\n {t('admin.users.total', { count: data.pagination.total })}\n </p>\n </div>\n <div className=\"flex flex-col gap-3 xl:items-end\">\n <div className=\"flex flex-col gap-2 lg:flex-row lg:items-center\">\n <input\n aria-label={t('admin.users.searchPlaceholder')}\n className=\"input input-bordered h-11 w-full border-white/10 bg-black/20 text-slate-200 placeholder:text-slate-500 focus:border-[#7170ff]/60 lg:w-80\"\n onChange={(event) => setDraftQuery(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') applySearch();\n }}\n placeholder={t('admin.users.searchPlaceholder')}\n type=\"search\"\n value={draftQuery}\n />\n <label className=\"label cursor-pointer justify-start gap-2 rounded-box border border-white/10 bg-black/20 px-3 py-2\">\n <input\n checked={draftIncludeDeleted}\n className=\"checkbox checkbox-sm border-white/20 bg-white/[0.04] checked:border-[#7170ff] checked:bg-[#7170ff]\"\n onChange={(event) =>\n setDraftIncludeDeleted(event.target.checked)\n }\n type=\"checkbox\"\n />\n <span className=\"label-text text-slate-300\">\n {t('admin.users.includeDeleted')}\n </span>\n </label>\n <button\n className=\"btn btn-outline border-white/10 bg-white/[0.035] text-slate-200 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15\"\n onClick={applySearch}\n type=\"button\"\n >\n {t('admin.users.search')}\n </button>\n <button\n className=\"btn btn-primary border-0 bg-[#7170ff] text-white shadow-[0_14px_40px_rgba(113,112,255,0.32)] hover:bg-[#828fff]\"\n onClick={() => setModal({ type: 'create' })}\n type=\"button\"\n >\n {t('admin.users.create')}\n </button>\n </div>\n <div className=\"join rounded-box border border-white/10 bg-black/20 p-1\">\n <QuickFilterButton\n active={activeQuickFilter === 'all'}\n label={t('admin.users.filter.all')}\n onClick={() => applyQuickFilter('all')}\n />\n <QuickFilterButton\n active={activeQuickFilter === 'database'}\n label={t('admin.users.filter.database')}\n onClick={() => applyQuickFilter('database')}\n />\n <QuickFilterButton\n active={activeQuickFilter === 'config'}\n label={t('admin.users.filter.config')}\n onClick={() => applyQuickFilter('config')}\n />\n <QuickFilterButton\n active={activeQuickFilter === 'admins'}\n label={t('admin.users.filter.admins')}\n onClick={() => applyQuickFilter('admins')}\n />\n </div>\n </div>\n </div>\n\n <div className=\"flex flex-wrap items-center justify-between gap-3 px-6\">\n <div className=\"flex flex-wrap items-center gap-2 text-sm\">\n <span className=\"text-slate-500\">\n {t('admin.users.showingRange', {\n from: pageStart,\n to: pageEnd,\n total: data.pagination.total,\n })}\n </span>\n {filters.query ? (\n <span className=\"badge badge-outline border-[#7170ff]/30 bg-[#7170ff]/10 text-[#c7c8ff]\">\n {t('admin.users.queryChip', { query: filters.query })}\n </span>\n ) : null}\n {filters.includeDeleted ? (\n <span className=\"badge badge-outline border-amber-300/25 bg-amber-300/10 text-amber-100\">\n {t('admin.users.includeDeleted')}\n </span>\n ) : null}\n {activeQuickFilter !== 'all' ? (\n <span className=\"badge badge-outline border-white/15 text-slate-300\">\n {t(`admin.users.filter.${activeQuickFilter}`)}\n </span>\n ) : null}\n {hasActiveFilters ? (\n <button\n className=\"btn btn-ghost btn-xs text-slate-400\"\n onClick={clearFilters}\n type=\"button\"\n >\n {t('admin.users.clearFilters')}\n </button>\n ) : null}\n </div>\n <label className=\"flex items-center gap-2 text-slate-500 text-sm\">\n <span>{t('admin.users.pageSize')}</span>\n <select\n aria-label={t('admin.users.pageSize')}\n className=\"select select-bordered select-xs border-white/10 bg-black/20 text-slate-200\"\n onChange={(event) => setPageSize(Number(event.target.value))}\n value={filters.pageSize}\n >\n <option value={10}>10</option>\n <option value={20}>20</option>\n <option value={50}>50</option>\n </select>\n </label>\n </div>\n\n <div className=\"overflow-x-auto px-0 pb-2\">\n <table className=\"table-zebra table [&_tbody_tr:hover]:bg-white/[0.04] [&_tbody_tr]:border-white/5 [&_tbody_tr]:transition [&_td]:border-white/5 [&_thead_th]:border-white/10 [&_thead_th]:bg-white/[0.035] [&_thead_th]:text-slate-500\">\n <thead>\n <tr>\n <th>{t('profile.email.label')}</th>\n <th>{t('admin.users.role')}</th>\n <th>{t('admin.users.source')}</th>\n <th>{t('admin.users.emailVerified')}</th>\n <th>{t('admin.users.secondFactor')}</th>\n <th>{t('admin.users.status')}</th>\n <th>{t('admin.users.actions')}</th>\n </tr>\n </thead>\n <tbody>\n {data.users.map((managedUser) => (\n <tr key={managedUser.sub}>\n <td>\n <div className=\"font-medium text-slate-100\">\n {managedUser.email}\n </div>\n <div className=\"max-w-64 truncate font-mono text-slate-600 text-xs\">\n {managedUser.sub}\n </div>\n </td>\n <td>\n <Badge\n tone={\n managedUser.role === 'admin' ? 'neutral' : 'ghost'\n }\n >\n {formatAdminRole(t, managedUser.role)}\n </Badge>\n </td>\n <td>\n <Badge\n tone={\n managedUser.managed_by === 'config'\n ? 'warning'\n : 'info'\n }\n >\n {formatManagedBy(t, managedUser.managed_by)}\n </Badge>\n </td>\n <td>\n {managedUser.email_verified\n ? t('common.yes')\n : t('common.no')}\n </td>\n <td>\n {managedUser.totp_registered\n ? t('admin.users.secondFactorTotp')\n : managedUser.passkey_count > 0\n ? t(\n managedUser.passkey_count === 1\n ? 'admin.users.secondFactorPasskey'\n : 'admin.users.secondFactorPasskeys',\n { count: managedUser.passkey_count },\n )\n : t('common.none')}\n </td>\n <td>\n <Badge\n tone={managedUser.deleted_at ? 'error' : 'success'}\n >\n {managedUser.deleted_at\n ? t('admin.users.deleted')\n : t('admin.users.active')}\n </Badge>\n </td>\n <td>\n {managedUser.managed_by === 'database' &&\n !managedUser.deleted_at ? (\n <div className=\"join rounded-xl border border-white/10 bg-black/20\">\n <button\n aria-label={t('admin.users.editUser', {\n email: managedUser.email,\n })}\n className=\"btn join-item btn-ghost btn-xs text-slate-300 hover:bg-white/[0.06]\"\n onClick={() =>\n setModal({ type: 'edit', user: managedUser })\n }\n type=\"button\"\n >\n {t('admin.users.edit')}\n </button>\n <button\n aria-label={t('admin.users.deleteUser', {\n email: managedUser.email,\n })}\n className=\"btn join-item btn-error btn-outline btn-xs border-red-400/25 bg-red-400/5 text-red-200 hover:bg-red-400/15\"\n onClick={() =>\n setModal({ type: 'delete', user: managedUser })\n }\n type=\"button\"\n >\n {t('admin.users.delete')}\n </button>\n </div>\n ) : (\n <span className=\"badge badge-outline border-white/15 text-slate-400\">\n {t('admin.users.readonly')}\n </span>\n )}\n </td>\n </tr>\n ))}\n {data.users.length === 0 ? (\n <tr>\n <td\n className=\"py-12 text-center text-slate-500\"\n colSpan={7}\n >\n {t('admin.users.emptyFiltered')}\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n\n <div className=\"flex items-center justify-between border-white/10 border-t bg-white/[0.015] p-5\">\n <button\n className=\"btn btn-outline btn-sm border-white/10 bg-white/[0.035] text-slate-300 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15\"\n disabled={filters.page <= 1}\n onClick={() =>\n setFilters((current) => ({\n ...current,\n page: current.page - 1,\n }))\n }\n type=\"button\"\n >\n {t('admin.users.previous')}\n </button>\n <span className=\"badge badge-ghost border-white/10 bg-black/20 text-slate-400\">\n {t('admin.users.page', { page: data.pagination.page })}\n </span>\n <button\n className=\"btn btn-outline btn-sm border-white/10 bg-white/[0.035] text-slate-300 hover:border-[#7170ff]/40 hover:bg-[#7170ff]/15\"\n disabled={\n data.pagination.page * data.pagination.page_size >=\n data.pagination.total\n }\n onClick={() =>\n setFilters((current) => ({\n ...current,\n page: current.page + 1,\n }))\n }\n type=\"button\"\n >\n {t('admin.users.next')}\n </button>\n </div>\n </div>\n </section>\n\n <UserFormModal\n isMutating={isMutating}\n modal={modal}\n onClose={() => setModal(null)}\n onCreate={(values) => createMutation.mutate(values)}\n onDelete={(sub) => deleteMutation.mutate(sub)}\n onUpdate={(values) => updateMutation.mutate(values)}\n />\n </AdminShell>\n );\n}\n\nfunction UserFormModal({\n modal,\n isMutating,\n onClose,\n onCreate,\n onUpdate,\n onDelete,\n}: {\n modal: UserModalState;\n isMutating: boolean;\n onClose: () => void;\n onCreate: (values: {\n email: string;\n password: string;\n role: 'user' | 'admin';\n email_verified: boolean;\n }) => void;\n onUpdate: (values: {\n sub: string;\n email: string;\n role: 'user' | 'admin';\n email_verified: boolean;\n }) => void;\n onDelete: (sub: string) => void;\n}) {\n const { t } = useTranslation();\n const defaultValues = useMemo(\n () => (modal?.type === 'edit' ? modal.user : null),\n [modal],\n );\n const dialogRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!modal) return undefined;\n\n const previousFocus =\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n const firstFocusable = dialogRef.current?.querySelector<HTMLElement>(\n 'input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), a[href], [tabindex]:not([tabindex=\"-1\"])',\n );\n firstFocusable?.focus();\n\n return () => {\n previousFocus?.focus();\n };\n }, [modal]);\n\n if (!modal) return null;\n\n if (modal.type === 'delete') {\n return (\n <div className=\"modal modal-open bg-black/70 backdrop-blur-sm\">\n <div\n aria-labelledby=\"admin-delete-user-title\"\n aria-modal=\"true\"\n className=\"modal-box border border-white/10 bg-[#101217] text-slate-100 shadow-[0_32px_100px_rgba(0,0,0,0.55)]\"\n onKeyDown={(event) => trapDialogFocus(event, onClose)}\n ref={dialogRef}\n role=\"dialog\"\n >\n <h3\n className=\"font-semibold text-xl tracking-[-0.03em]\"\n id=\"admin-delete-user-title\"\n >\n {t('admin.users.deleteTitle', { email: modal.user.email })}\n </h3>\n <div className=\"my-4 rounded-2xl border border-red-300/20 bg-red-400/10 p-4 text-red-100\">\n <p className=\"font-medium\">{t('admin.users.deleteWarning')}</p>\n <p className=\"mt-1 text-red-100/70 text-sm\">\n {t('admin.users.deleteDescription')}\n </p>\n </div>\n <div className=\"modal-action\">\n <button\n className=\"btn border-white/10 bg-white/[0.04] text-slate-200 hover:bg-white/[0.08]\"\n onClick={onClose}\n type=\"button\"\n >\n {t('admin.users.cancel')}\n </button>\n <button\n className=\"btn btn-error border-0 bg-red-500/80 text-white hover:bg-red-500\"\n disabled={isMutating}\n onClick={() => onDelete(modal.user.sub)}\n type=\"button\"\n >\n {t('admin.users.deleteConfirm')}\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n const title =\n modal.type === 'create'\n ? t('admin.users.create')\n : t('admin.users.editTitle');\n const submit =\n modal.type === 'create'\n ? t('admin.users.createSubmit')\n : t('admin.users.save');\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const formData = new FormData(event.currentTarget);\n const values = {\n email: String(formData.get('email') ?? ''),\n role: parseUserRole(formData.get('role')),\n email_verified: formData.get('email_verified') === 'on',\n };\n if (modal.type === 'create') {\n onCreate({\n ...values,\n password: String(formData.get('password') ?? ''),\n });\n } else {\n onUpdate({\n sub: modal.user.sub,\n ...values,\n });\n }\n };\n\n return (\n <div className=\"modal modal-open bg-black/70 backdrop-blur-sm\">\n <div\n aria-labelledby=\"admin-user-form-title\"\n aria-modal=\"true\"\n className=\"modal-box border border-white/10 bg-[#101217] text-slate-100 shadow-[0_32px_100px_rgba(0,0,0,0.55)]\"\n onKeyDown={(event) => trapDialogFocus(event, onClose)}\n ref={dialogRef}\n role=\"dialog\"\n >\n <h3\n className=\"font-semibold text-xl tracking-[-0.03em]\"\n id=\"admin-user-form-title\"\n >\n {title}\n </h3>\n <p className=\"mt-2 text-slate-500 text-sm\">\n {modal.type === 'create'\n ? t('admin.users.createHint')\n : t('admin.users.editHint')}\n </p>\n <form className=\"mt-4 space-y-4\" onSubmit={handleSubmit}>\n <fieldset className=\"fieldset\">\n <legend className=\"fieldset-legend text-slate-400\">\n {t('profile.email.label')}\n </legend>\n <input\n aria-label={t('profile.email.label')}\n className=\"input input-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60\"\n defaultValue={defaultValues?.email ?? ''}\n name=\"email\"\n required\n type=\"email\"\n />\n </fieldset>\n {modal.type === 'create' ? (\n <fieldset className=\"fieldset\">\n <legend className=\"fieldset-legend text-slate-400\">\n {t('admin.users.password')}\n </legend>\n <input\n aria-label={t('admin.users.password')}\n className=\"input input-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60\"\n name=\"password\"\n required\n type=\"password\"\n />\n </fieldset>\n ) : null}\n <fieldset className=\"fieldset\">\n <legend className=\"fieldset-legend text-slate-400\">\n {t('admin.users.role')}\n </legend>\n <select\n aria-label={t('admin.users.role')}\n className=\"select select-bordered w-full border-white/10 bg-black/20 text-slate-100 focus:border-[#7170ff]/60\"\n defaultValue={defaultValues?.role ?? 'user'}\n name=\"role\"\n >\n <option value=\"user\">{t('admin.users.roleUser')}</option>\n <option value=\"admin\">{t('admin.users.roleAdmin')}</option>\n </select>\n </fieldset>\n <label className=\"label cursor-pointer justify-start gap-3 rounded-box border border-white/10 bg-black/20 px-3 py-2\">\n <input\n className=\"checkbox border-white/20 bg-white/[0.04] checked:border-[#7170ff] checked:bg-[#7170ff]\"\n defaultChecked={defaultValues?.email_verified ?? false}\n name=\"email_verified\"\n type=\"checkbox\"\n />\n <span className=\"label-text text-slate-300\">\n {t('admin.users.emailVerified')}\n </span>\n </label>\n <div className=\"modal-action\">\n <button\n className=\"btn border-white/10 bg-white/[0.04] text-slate-200 hover:bg-white/[0.08]\"\n onClick={onClose}\n type=\"button\"\n >\n {t('admin.users.cancel')}\n </button>\n <button\n className=\"btn btn-primary border-0 bg-[#7170ff] text-white shadow-[0_14px_40px_rgba(113,112,255,0.32)] hover:bg-[#828fff]\"\n disabled={isMutating}\n type=\"submit\"\n >\n {submit}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n\nfunction trapDialogFocus(\n event: KeyboardEvent<HTMLDivElement>,\n onClose: () => void,\n) {\n if (event.key === 'Escape') {\n event.preventDefault();\n onClose();\n return;\n }\n\n if (event.key !== 'Tab') return;\n\n const focusableElements = Array.from(\n event.currentTarget.querySelectorAll<HTMLElement>(\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n ),\n );\n\n if (focusableElements.length === 0) return;\n\n const firstElement = focusableElements[0];\n const lastElement = focusableElements.at(-1);\n if (!firstElement || !lastElement) return;\n\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n return;\n }\n\n if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n}\n\nfunction formatAdminRole(\n t: ReturnType<typeof useTranslation>['t'],\n role: AdminUser['role'],\n) {\n return role === 'admin'\n ? t('admin.users.roleAdmin')\n : t('admin.users.roleUser');\n}\n\nfunction formatManagedBy(\n t: ReturnType<typeof useTranslation>['t'],\n managedBy: AdminUser['managed_by'],\n) {\n return managedBy === 'database'\n ? t('admin.users.sourceDatabase')\n : t('admin.users.sourceConfig');\n}\n\nfunction parseUserRole(value: FormDataEntryValue | null): 'user' | 'admin' {\n return value === 'admin' ? 'admin' : 'user';\n}\n\nfunction getActiveQuickFilter(\n filters: ReturnType<typeof normalizeAdminUsersQuery>,\n): QuickFilter {\n if (filters.role === 'admin') return 'admins';\n if (filters.managedBy === 'database') return 'database';\n if (filters.managedBy === 'config') return 'config';\n return 'all';\n}\n\nfunction QuickFilterButton({\n active,\n label,\n onClick,\n}: {\n active: boolean;\n label: string;\n onClick: () => void;\n}) {\n return (\n <button\n className={\n active\n ? 'btn join-item btn-xs border-0 bg-[#7170ff] text-white'\n : 'btn join-item btn-ghost btn-xs text-slate-400 hover:bg-white/[0.06] hover:text-slate-100'\n }\n onClick={onClick}\n type=\"button\"\n >\n {label}\n </button>\n );\n}\n\nfunction SummaryStat({ label, value }: { label: string; value: number }) {\n const { t } = useTranslation();\n return (\n <div className=\"stat border-white/10 bg-transparent p-6\">\n <div className=\"stat-title text-slate-500\">{label}</div>\n <div className=\"stat-value mt-1 text-slate-50 tracking-[-0.06em]\">\n {value}\n </div>\n <div className=\"stat-desc text-slate-600\">\n {t('admin.users.currentPage')}\n </div>\n </div>\n );\n}\n\ntype BadgeTone = 'neutral' | 'ghost' | 'warning' | 'info' | 'success' | 'error';\n\nconst badgeClasses: Record<BadgeTone, string> = {\n neutral: 'badge-primary border-[#7170ff]/30 bg-[#7170ff]/20 text-[#c7c8ff]',\n ghost: 'badge-ghost border-white/10 bg-white/[0.035] text-slate-400',\n warning: 'badge-warning border-amber-300/25 bg-amber-300/15 text-amber-100',\n info: 'badge-info border-sky-300/25 bg-sky-300/15 text-sky-100',\n success:\n 'badge-success border-emerald-300/25 bg-emerald-300/15 text-emerald-100',\n error: 'badge-error border-red-300/25 bg-red-300/15 text-red-100',\n};\n\nfunction Badge({ tone, children }: { tone: BadgeTone; children: ReactNode }) {\n return <span className={`badge ${badgeClasses[tone]}`}>{children}</span>;\n}\n"],"mappings":"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"}
|
package/public/index.html
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<!-- Preload critical API data for faster initial render -->
|
|
19
19
|
<link rel="preload" href="/api/config" as="fetch" crossorigin="anonymous" />
|
|
20
20
|
<link rel="preload" href="/api/user/session" as="fetch" crossorigin="anonymous" />
|
|
21
|
-
<script type="module" crossorigin src="/assets/index-
|
|
21
|
+
<script type="module" crossorigin src="/assets/index-CgkA6nnx.js"></script>
|
|
22
22
|
<link rel="modulepreload" crossorigin href="/assets/IconBase.es-d5KP98Ac.js">
|
|
23
23
|
<link rel="modulepreload" crossorigin href="/assets/use-theme-cVUDAjtt.js">
|
|
24
24
|
<link rel="modulepreload" crossorigin href="/assets/mutationOptions-Dfvzj6n2.js">
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{o as e}from"./IconBase.es-d5KP98Ac.js";import{A as t,N as n}from"./index-BmfaaNx6.js";var r=e();function i(e){return(0,r.jsx)(n,{...e,onUnauthorized:()=>{let e=new URLSearchParams(window.location.search),n=Object.fromEntries(e.entries());window.location.href=t(n)}})}export{i as errorComponent};
|
|
2
|
-
//# sourceMappingURL=consent-B17hGrta.js.map
|