@greatapps/common 1.1.778 → 1.1.780

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.
Files changed (36) hide show
  1. package/dist/components/account/DisableTwoFactorAuthModal.mjs +40 -43
  2. package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -1
  3. package/dist/components/account/TwoFactorAuthModal.mjs +123 -129
  4. package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -1
  5. package/dist/components/account/sections/PreferencesSection.mjs +3 -1
  6. package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
  7. package/dist/components/modals/ModalManager.mjs.map +1 -1
  8. package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs +8 -11
  9. package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs.map +1 -1
  10. package/dist/hooks/useDomMutationGuardHit.mjs +36 -0
  11. package/dist/hooks/useDomMutationGuardHit.mjs.map +1 -0
  12. package/dist/i18n/resolve-locale.mjs +10 -0
  13. package/dist/i18n/resolve-locale.mjs.map +1 -1
  14. package/dist/index.mjs +4 -0
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/infra/api/client.mjs +10 -0
  17. package/dist/infra/api/client.mjs.map +1 -1
  18. package/dist/modules/auth/services/auth.service.mjs +12 -6
  19. package/dist/modules/auth/services/auth.service.mjs.map +1 -1
  20. package/dist/utils/dom/dom-mutation-guard.mjs +20 -0
  21. package/dist/utils/dom/dom-mutation-guard.mjs.map +1 -0
  22. package/dist/utils/intl/locales.mjs +6 -1
  23. package/dist/utils/intl/locales.mjs.map +1 -1
  24. package/package.json +1 -1
  25. package/src/components/account/DisableTwoFactorAuthModal.tsx +0 -1
  26. package/src/components/account/TwoFactorAuthModal.tsx +0 -2
  27. package/src/components/account/sections/PreferencesSection.tsx +3 -2
  28. package/src/components/modals/ModalManager.tsx +0 -4
  29. package/src/components/widgets/ImageUpload/ImageTooSmallModal.tsx +0 -1
  30. package/src/hooks/useDomMutationGuardHit.ts +55 -0
  31. package/src/i18n/resolve-locale.ts +19 -4
  32. package/src/index.ts +3 -0
  33. package/src/infra/api/client.ts +41 -0
  34. package/src/modules/auth/services/auth.service.ts +14 -6
  35. package/src/utils/dom/dom-mutation-guard.ts +46 -0
  36. package/src/utils/intl/locales.ts +7 -0
@@ -21,52 +21,49 @@ function DisableTwoFactorAuthModal({
21
21
  }) {
22
22
  const translate = useTranslations();
23
23
  const { code, setCode, isValid, isLoading, handleClose, handleSubmit } = useDisableTwoFactorAuthForm({ onClose, onSuccess });
24
- return (
25
- // Abre por cima do modal de configurações da conta, que é irmão na árvore.
26
- /* @__PURE__ */ jsx(DialogLayer, { children: /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsx(DialogContent, { className: "flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-117.5 lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]", children: /* @__PURE__ */ jsxs(
27
- "form",
28
- {
29
- onSubmit: (e) => {
30
- e.preventDefault();
31
- handleSubmit();
32
- },
33
- className: "flex flex-col flex-1 lg:flex-none",
34
- children: [
35
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 lg:gap-5 p-4 lg:p-5 flex-1 lg:flex-none", children: [
36
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center w-fit bg-gray-50 rounded-lg p-2", children: /* @__PURE__ */ jsx(IconShieldCheck, { size: 20, className: "text-gray-600" }) }),
37
- /* @__PURE__ */ jsxs(DialogHeader, { className: "p-0 gap-2", children: [
38
- /* @__PURE__ */ jsx(DialogTitle, { className: "paragraph-medium-semibold text-gray-950", children: translate("common.account.twoFactor.disableTitle") }),
39
- /* @__PURE__ */ jsx(DialogDescription, { className: "paragraph-small-regular text-gray-600", children: translate("common.account.twoFactor.disableDescription") })
40
- ] }),
41
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
42
- /* @__PURE__ */ jsx("span", { className: "paragraph-small-medium text-gray-700", children: translate("common.account.twoFactor.authenticatorCode") }),
43
- /* @__PURE__ */ jsx(InputOTP, { maxLength: 6, pattern: REGEXP_ONLY_DIGITS, value: code, onChange: setCode, children: /* @__PURE__ */ jsx(InputOTPGroup, { className: "gap-2", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(
44
- InputOTPSlot,
45
- {
46
- index: i,
47
- className: "w-11! lg:w-12! h-13! lg:h-14! rounded-lg! text-lg border-gray-200"
48
- },
49
- i
50
- )) }) })
51
- ] })
24
+ return /* @__PURE__ */ jsx(DialogLayer, { children: /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsx(DialogContent, { className: "flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-117.5 lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]", children: /* @__PURE__ */ jsxs(
25
+ "form",
26
+ {
27
+ onSubmit: (e) => {
28
+ e.preventDefault();
29
+ handleSubmit();
30
+ },
31
+ className: "flex flex-col flex-1 lg:flex-none",
32
+ children: [
33
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 lg:gap-5 p-4 lg:p-5 flex-1 lg:flex-none", children: [
34
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center w-fit bg-gray-50 rounded-lg p-2", children: /* @__PURE__ */ jsx(IconShieldCheck, { size: 20, className: "text-gray-600" }) }),
35
+ /* @__PURE__ */ jsxs(DialogHeader, { className: "p-0 gap-2", children: [
36
+ /* @__PURE__ */ jsx(DialogTitle, { className: "paragraph-medium-semibold text-gray-950", children: translate("common.account.twoFactor.disableTitle") }),
37
+ /* @__PURE__ */ jsx(DialogDescription, { className: "paragraph-small-regular text-gray-600", children: translate("common.account.twoFactor.disableDescription") })
52
38
  ] }),
53
- /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center gap-2 p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0", children: [
54
- /* @__PURE__ */ jsx(Button, { className: "h-10! flex-1", disabled: !isValid || isLoading, type: "submit", children: isLoading ? translate("common.account.twoFactor.disabling") : translate("common.account.twoFactor.disable") }),
55
- /* @__PURE__ */ jsx(
56
- Button,
39
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
40
+ /* @__PURE__ */ jsx("span", { className: "paragraph-small-medium text-gray-700", children: translate("common.account.twoFactor.authenticatorCode") }),
41
+ /* @__PURE__ */ jsx(InputOTP, { maxLength: 6, pattern: REGEXP_ONLY_DIGITS, value: code, onChange: setCode, children: /* @__PURE__ */ jsx(InputOTPGroup, { className: "gap-2", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(
42
+ InputOTPSlot,
57
43
  {
58
- variant: "secondary",
59
- className: "h-10! flex-1",
60
- type: "button",
61
- onClick: handleClose,
62
- children: translate("common.actions.cancel")
63
- }
64
- )
44
+ index: i,
45
+ className: "w-11! lg:w-12! h-13! lg:h-14! rounded-lg! text-lg border-gray-200"
46
+ },
47
+ i
48
+ )) }) })
65
49
  ] })
66
- ]
67
- }
68
- ) }) }) })
69
- );
50
+ ] }),
51
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center gap-2 p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0", children: [
52
+ /* @__PURE__ */ jsx(Button, { className: "h-10! flex-1", disabled: !isValid || isLoading, type: "submit", children: isLoading ? translate("common.account.twoFactor.disabling") : translate("common.account.twoFactor.disable") }),
53
+ /* @__PURE__ */ jsx(
54
+ Button,
55
+ {
56
+ variant: "secondary",
57
+ className: "h-10! flex-1",
58
+ type: "button",
59
+ onClick: handleClose,
60
+ children: translate("common.actions.cancel")
61
+ }
62
+ )
63
+ ] })
64
+ ]
65
+ }
66
+ ) }) }) });
70
67
  }
71
68
  export {
72
69
  DisableTwoFactorAuthModal as default
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/account/DisableTwoFactorAuthModal.tsx"],"sourcesContent":["'use client';\n\nimport { useTranslations } from 'next-intl';\nimport { IconShieldCheck } from '@tabler/icons-react';\nimport { Button } from '../ui/buttons/Button';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '../ui/overlay/Dialog';\nimport { DialogLayer } from '../ui/overlay/layers';\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from '../ui/form/InputOtp';\nimport { REGEXP_ONLY_DIGITS } from 'input-otp';\nimport useDisableTwoFactorAuthForm from './hooks/useDisableTwoFactorAuthForm';\n\ninterface DisableTwoFactorAuthModalProps {\n open: boolean;\n onClose: () => void;\n onSuccess?: () => void;\n}\n\nexport default function DisableTwoFactorAuthModal({\n open,\n onClose,\n onSuccess,\n}: DisableTwoFactorAuthModalProps) {\n const translate = useTranslations();\n const { code, setCode, isValid, isLoading, handleClose, handleSubmit } =\n useDisableTwoFactorAuthForm({ onClose, onSuccess });\n\n return (\n // Abre por cima do modal de configurações da conta, que é irmão na árvore.\n <DialogLayer>\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-117.5 lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]\">\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleSubmit();\n }}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className=\"flex flex-col gap-4 lg:gap-5 p-4 lg:p-5 flex-1 lg:flex-none\">\n <div className=\"flex items-center justify-center w-fit bg-gray-50 rounded-lg p-2\">\n <IconShieldCheck size={20} className=\"text-gray-600\" />\n </div>\n <DialogHeader className=\"p-0 gap-2\">\n <DialogTitle className=\"paragraph-medium-semibold text-gray-950\">\n {translate('common.account.twoFactor.disableTitle')}\n </DialogTitle>\n <DialogDescription className=\"paragraph-small-regular text-gray-600\">\n {translate('common.account.twoFactor.disableDescription')}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"flex flex-col gap-2\">\n <span className=\"paragraph-small-medium text-gray-700\">\n {translate('common.account.twoFactor.authenticatorCode')}\n </span>\n <InputOTP maxLength={6} pattern={REGEXP_ONLY_DIGITS} value={code} onChange={setCode}>\n <InputOTPGroup className=\"gap-2\">\n {Array.from({ length: 6 }).map((_, i) => (\n <InputOTPSlot\n key={i}\n index={i}\n className=\"w-11! lg:w-12! h-13! lg:h-14! rounded-lg! text-lg border-gray-200\"\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n </div>\n </div>\n\n <div className=\"flex flex-row items-center gap-2 p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0\">\n <Button className=\"h-10! flex-1\" disabled={!isValid || isLoading} type=\"submit\">\n {isLoading\n ? translate('common.account.twoFactor.disabling')\n : translate('common.account.twoFactor.disable')}\n </Button>\n <Button\n variant=\"secondary\"\n className=\"h-10! flex-1\"\n type=\"button\"\n onClick={handleClose}\n >\n {translate('common.actions.cancel')}\n </Button>\n </div>\n </form>\n </DialogContent>\n </Dialog>\n </DialogLayer>\n );\n}\n"],"mappings":";AA8CgB,cAEF,YAFE;AA5ChB,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAChC,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAmB;AAC5B,SAAS,UAAU,eAAe,oBAAoB;AACtD,SAAS,0BAA0B;AACnC,OAAO,iCAAiC;AAQzB,SAAR,0BAA2C;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AACF,GAAmC;AACjC,QAAM,YAAY,gBAAgB;AAClC,QAAM,EAAE,MAAM,SAAS,SAAS,WAAW,aAAa,aAAa,IACnE,4BAA4B,EAAE,SAAS,UAAU,CAAC;AAEpD;AAAA;AAAA,IAEE,oBAAC,eACC,8BAAC,UAAO,MAAY,cAAc,aAChC,8BAAC,iBAAc,WAAU,+SACvB;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,MAAM;AACf,YAAE,eAAe;AACjB,uBAAa;AAAA,QACf;AAAA,QACA,WAAU;AAAA,QAEV;AAAA,+BAAC,SAAI,WAAU,+DACb;AAAA,gCAAC,SAAI,WAAU,oEACb,8BAAC,mBAAgB,MAAM,IAAI,WAAU,iBAAgB,GACvD;AAAA,YACA,qBAAC,gBAAa,WAAU,aACtB;AAAA,kCAAC,eAAY,WAAU,2CACpB,oBAAU,uCAAuC,GACpD;AAAA,cACA,oBAAC,qBAAkB,WAAU,yCAC1B,oBAAU,6CAA6C,GAC1D;AAAA,eACF;AAAA,YAEA,qBAAC,SAAI,WAAU,uBACb;AAAA,kCAAC,UAAK,WAAU,wCACb,oBAAU,4CAA4C,GACzD;AAAA,cACA,oBAAC,YAAS,WAAW,GAAG,SAAS,oBAAoB,OAAO,MAAM,UAAU,SAC1E,8BAAC,iBAAc,WAAU,SACtB,gBAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MACjC;AAAA,gBAAC;AAAA;AAAA,kBAEC,OAAO;AAAA,kBACP,WAAU;AAAA;AAAA,gBAFL;AAAA,cAGP,CACD,GACH,GACF;AAAA,eACF;AAAA,aACF;AAAA,UAEA,qBAAC,SAAI,WAAU,wFACb;AAAA,gCAAC,UAAO,WAAU,gBAAe,UAAU,CAAC,WAAW,WAAW,MAAK,UACpE,sBACG,UAAU,oCAAoC,IAC9C,UAAU,kCAAkC,GAClD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,WAAU;AAAA,gBACV,MAAK;AAAA,gBACL,SAAS;AAAA,gBAER,oBAAU,uBAAuB;AAAA;AAAA,YACpC;AAAA,aACF;AAAA;AAAA;AAAA,IACF,GACF,GACF,GACF;AAAA;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/account/DisableTwoFactorAuthModal.tsx"],"sourcesContent":["'use client';\n\nimport { useTranslations } from 'next-intl';\nimport { IconShieldCheck } from '@tabler/icons-react';\nimport { Button } from '../ui/buttons/Button';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '../ui/overlay/Dialog';\nimport { DialogLayer } from '../ui/overlay/layers';\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from '../ui/form/InputOtp';\nimport { REGEXP_ONLY_DIGITS } from 'input-otp';\nimport useDisableTwoFactorAuthForm from './hooks/useDisableTwoFactorAuthForm';\n\ninterface DisableTwoFactorAuthModalProps {\n open: boolean;\n onClose: () => void;\n onSuccess?: () => void;\n}\n\nexport default function DisableTwoFactorAuthModal({\n open,\n onClose,\n onSuccess,\n}: DisableTwoFactorAuthModalProps) {\n const translate = useTranslations();\n const { code, setCode, isValid, isLoading, handleClose, handleSubmit } =\n useDisableTwoFactorAuthForm({ onClose, onSuccess });\n\n return (\n <DialogLayer>\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-117.5 lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]\">\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleSubmit();\n }}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className=\"flex flex-col gap-4 lg:gap-5 p-4 lg:p-5 flex-1 lg:flex-none\">\n <div className=\"flex items-center justify-center w-fit bg-gray-50 rounded-lg p-2\">\n <IconShieldCheck size={20} className=\"text-gray-600\" />\n </div>\n <DialogHeader className=\"p-0 gap-2\">\n <DialogTitle className=\"paragraph-medium-semibold text-gray-950\">\n {translate('common.account.twoFactor.disableTitle')}\n </DialogTitle>\n <DialogDescription className=\"paragraph-small-regular text-gray-600\">\n {translate('common.account.twoFactor.disableDescription')}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"flex flex-col gap-2\">\n <span className=\"paragraph-small-medium text-gray-700\">\n {translate('common.account.twoFactor.authenticatorCode')}\n </span>\n <InputOTP maxLength={6} pattern={REGEXP_ONLY_DIGITS} value={code} onChange={setCode}>\n <InputOTPGroup className=\"gap-2\">\n {Array.from({ length: 6 }).map((_, i) => (\n <InputOTPSlot\n key={i}\n index={i}\n className=\"w-11! lg:w-12! h-13! lg:h-14! rounded-lg! text-lg border-gray-200\"\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n </div>\n </div>\n\n <div className=\"flex flex-row items-center gap-2 p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0\">\n <Button className=\"h-10! flex-1\" disabled={!isValid || isLoading} type=\"submit\">\n {isLoading\n ? translate('common.account.twoFactor.disabling')\n : translate('common.account.twoFactor.disable')}\n </Button>\n <Button\n variant=\"secondary\"\n className=\"h-10! flex-1\"\n type=\"button\"\n onClick={handleClose}\n >\n {translate('common.actions.cancel')}\n </Button>\n </div>\n </form>\n </DialogContent>\n </Dialog>\n </DialogLayer>\n );\n}\n"],"mappings":";AA6CgB,cAEF,YAFE;AA3ChB,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAChC,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAmB;AAC5B,SAAS,UAAU,eAAe,oBAAoB;AACtD,SAAS,0BAA0B;AACnC,OAAO,iCAAiC;AAQzB,SAAR,0BAA2C;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AACF,GAAmC;AACjC,QAAM,YAAY,gBAAgB;AAClC,QAAM,EAAE,MAAM,SAAS,SAAS,WAAW,aAAa,aAAa,IACnE,4BAA4B,EAAE,SAAS,UAAU,CAAC;AAEpD,SACE,oBAAC,eACC,8BAAC,UAAO,MAAY,cAAc,aAChC,8BAAC,iBAAc,WAAU,+SACvB;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,CAAC,MAAM;AACf,UAAE,eAAe;AACjB,qBAAa;AAAA,MACf;AAAA,MACA,WAAU;AAAA,MAEV;AAAA,6BAAC,SAAI,WAAU,+DACb;AAAA,8BAAC,SAAI,WAAU,oEACb,8BAAC,mBAAgB,MAAM,IAAI,WAAU,iBAAgB,GACvD;AAAA,UACA,qBAAC,gBAAa,WAAU,aACtB;AAAA,gCAAC,eAAY,WAAU,2CACpB,oBAAU,uCAAuC,GACpD;AAAA,YACA,oBAAC,qBAAkB,WAAU,yCAC1B,oBAAU,6CAA6C,GAC1D;AAAA,aACF;AAAA,UAEA,qBAAC,SAAI,WAAU,uBACb;AAAA,gCAAC,UAAK,WAAU,wCACb,oBAAU,4CAA4C,GACzD;AAAA,YACA,oBAAC,YAAS,WAAW,GAAG,SAAS,oBAAoB,OAAO,MAAM,UAAU,SAC1E,8BAAC,iBAAc,WAAU,SACtB,gBAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MACjC;AAAA,cAAC;AAAA;AAAA,gBAEC,OAAO;AAAA,gBACP,WAAU;AAAA;AAAA,cAFL;AAAA,YAGP,CACD,GACH,GACF;AAAA,aACF;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,wFACb;AAAA,8BAAC,UAAO,WAAU,gBAAe,UAAU,CAAC,WAAW,WAAW,MAAK,UACpE,sBACG,UAAU,oCAAoC,IAC9C,UAAU,kCAAkC,GAClD;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,WAAU;AAAA,cACV,MAAK;AAAA,cACL,SAAS;AAAA,cAER,oBAAU,uBAAuB;AAAA;AAAA,UACpC;AAAA,WACF;AAAA;AAAA;AAAA,EACF,GACF,GACF,GACF;AAEJ;","names":[]}
@@ -32,74 +32,15 @@ function TwoFactorAuthModal({ open, onClose, onSuccess }) {
32
32
  onClose();
33
33
  };
34
34
  if (step === "recovery") {
35
- return (
36
- // Abre por cima do modal de configurações da conta, que é irmão na árvore.
37
- /* @__PURE__ */ jsx(DialogLayer, { children: /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(
38
- DialogContent,
39
- {
40
- showCloseButton: false,
41
- className: "flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]",
42
- children: [
43
- /* @__PURE__ */ jsx(DialogHeader, { className: "sr-only", children: /* @__PURE__ */ jsx(DialogTitle, { children: translate("common.account.twoFactor.recoveryTitle") }) }),
44
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0", children: [
45
- /* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950 text-center", children: translate("common.account.twoFactor.recoveryTitle") }),
46
- /* @__PURE__ */ jsx(
47
- Button,
48
- {
49
- type: "button",
50
- variant: "ghost",
51
- className: "size-8! p-0 absolute right-4",
52
- onClick: handleClose,
53
- children: /* @__PURE__ */ jsx(IconX, { size: 18 })
54
- }
55
- )
56
- ] }),
57
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-5 lg:gap-6 px-4 lg:px-5 py-5 lg:py-6 flex-1 lg:flex-none", children: [
58
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
59
- /* @__PURE__ */ jsx("h3", { className: "paragraph-medium-semibold text-gray-950 max-w-[269px]", children: translate("common.account.twoFactor.recoveryHeading") }),
60
- /* @__PURE__ */ jsxs("div", { className: "paragraph-small-regular text-gray-600", children: [
61
- /* @__PURE__ */ jsx("p", { children: translate("common.account.twoFactor.recoveryText1") }),
62
- /* @__PURE__ */ jsx("br", {}),
63
- /* @__PURE__ */ jsx("p", { children: translate("common.account.twoFactor.recoveryText2") })
64
- ] })
65
- ] }),
66
- /* @__PURE__ */ jsxs("div", { className: "bg-gray-50 rounded-lg p-4 flex flex-col gap-4", children: [
67
- /* @__PURE__ */ jsx("div", { className: "paragraph-small-medium text-gray-950 whitespace-nowrap", children: backupCodes.map((backupCode, i) => /* @__PURE__ */ jsx("p", { children: backupCode }, i)) }),
68
- /* @__PURE__ */ jsxs(
69
- Button,
70
- {
71
- type: "button",
72
- variant: "secondary",
73
- className: "h-8! w-fit",
74
- onClick: handleCopyCodes,
75
- children: [
76
- /* @__PURE__ */ jsx(IconCopy, { size: 16 }),
77
- translate("common.account.twoFactor.copyCodes")
78
- ]
79
- }
80
- )
81
- ] })
82
- ] }),
83
- /* @__PURE__ */ jsxs("div", { className: "flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between mt-auto lg:mt-0", children: [
84
- /* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: translate("common.actions.cancel") }),
85
- /* @__PURE__ */ jsx(Button, { className: "h-10!", type: "button", onClick: handleFinalize, children: translate("common.account.twoFactor.finish") })
86
- ] })
87
- ]
88
- }
89
- ) }) })
90
- );
91
- }
92
- return (
93
- // Abre por cima do modal de configurações da conta, que é irmão na árvore.
94
- /* @__PURE__ */ jsx(DialogLayer, { children: /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(
35
+ return /* @__PURE__ */ jsx(DialogLayer, { children: /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(
95
36
  DialogContent,
96
37
  {
97
38
  showCloseButton: false,
98
- className: "flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:max-h-[90vh] lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]",
39
+ className: "flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]",
99
40
  children: [
100
- /* @__PURE__ */ jsx(DialogHeader, { className: "sr-only", children: /* @__PURE__ */ jsx(DialogTitle, { children: translate("common.account.twoFactor.title") }) }),
101
- /* @__PURE__ */ jsxs("div", { className: "shrink-0 flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0", children: [
102
- /* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950 text-center", children: translate("common.account.twoFactor.title") }),
41
+ /* @__PURE__ */ jsx(DialogHeader, { className: "sr-only", children: /* @__PURE__ */ jsx(DialogTitle, { children: translate("common.account.twoFactor.recoveryTitle") }) }),
42
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0", children: [
43
+ /* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950 text-center", children: translate("common.account.twoFactor.recoveryTitle") }),
103
44
  /* @__PURE__ */ jsx(
104
45
  Button,
105
46
  {
@@ -111,75 +52,128 @@ function TwoFactorAuthModal({ open, onClose, onSuccess }) {
111
52
  }
112
53
  )
113
54
  ] }),
114
- /* @__PURE__ */ jsxs(
115
- "form",
55
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-5 lg:gap-6 px-4 lg:px-5 py-5 lg:py-6 flex-1 lg:flex-none", children: [
56
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
57
+ /* @__PURE__ */ jsx("h3", { className: "paragraph-medium-semibold text-gray-950 max-w-[269px]", children: translate("common.account.twoFactor.recoveryHeading") }),
58
+ /* @__PURE__ */ jsxs("div", { className: "paragraph-small-regular text-gray-600", children: [
59
+ /* @__PURE__ */ jsx("p", { children: translate("common.account.twoFactor.recoveryText1") }),
60
+ /* @__PURE__ */ jsx("br", {}),
61
+ /* @__PURE__ */ jsx("p", { children: translate("common.account.twoFactor.recoveryText2") })
62
+ ] })
63
+ ] }),
64
+ /* @__PURE__ */ jsxs("div", { className: "bg-gray-50 rounded-lg p-4 flex flex-col gap-4", children: [
65
+ /* @__PURE__ */ jsx("div", { className: "paragraph-small-medium text-gray-950 whitespace-nowrap", children: backupCodes.map((backupCode, i) => /* @__PURE__ */ jsx("p", { children: backupCode }, i)) }),
66
+ /* @__PURE__ */ jsxs(
67
+ Button,
68
+ {
69
+ type: "button",
70
+ variant: "secondary",
71
+ className: "h-8! w-fit",
72
+ onClick: handleCopyCodes,
73
+ children: [
74
+ /* @__PURE__ */ jsx(IconCopy, { size: 16 }),
75
+ translate("common.account.twoFactor.copyCodes")
76
+ ]
77
+ }
78
+ )
79
+ ] })
80
+ ] }),
81
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between mt-auto lg:mt-0", children: [
82
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: translate("common.actions.cancel") }),
83
+ /* @__PURE__ */ jsx(Button, { className: "h-10!", type: "button", onClick: handleFinalize, children: translate("common.account.twoFactor.finish") })
84
+ ] })
85
+ ]
86
+ }
87
+ ) }) });
88
+ }
89
+ return /* @__PURE__ */ jsx(DialogLayer, { children: /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(
90
+ DialogContent,
91
+ {
92
+ showCloseButton: false,
93
+ className: "flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:max-h-[90vh] lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]",
94
+ children: [
95
+ /* @__PURE__ */ jsx(DialogHeader, { className: "sr-only", children: /* @__PURE__ */ jsx(DialogTitle, { children: translate("common.account.twoFactor.title") }) }),
96
+ /* @__PURE__ */ jsxs("div", { className: "shrink-0 flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0", children: [
97
+ /* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950 text-center", children: translate("common.account.twoFactor.title") }),
98
+ /* @__PURE__ */ jsx(
99
+ Button,
116
100
  {
117
- className: "flex-1 min-h-0 flex flex-col",
118
- onSubmit: (e) => {
119
- e.preventDefault();
120
- if (isCodeComplete) handleSubmit();
121
- },
122
- children: [
123
- /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-y-auto overscroll-contain lg:overflow-visible", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4 lg:gap-8 px-4 lg:px-5 py-4 lg:py-6 pb-60 lg:pb-6", children: [
124
- /* @__PURE__ */ jsx("p", { className: "paragraph-small-regular text-gray-950 text-center max-w-full lg:max-w-[412px]", children: translate.rich("common.account.twoFactor.instructions", {
125
- link: (chunks) => /* @__PURE__ */ jsx(
126
- "a",
127
- {
128
- href: "https://support.google.com/accounts/answer/1066447",
129
- target: "_blank",
130
- rel: "noopener noreferrer",
131
- className: "paragraph-small-medium underline",
132
- children: chunks
133
- }
134
- )
135
- }) }),
136
- /* @__PURE__ */ jsx("div", { className: "border border-gray-200 rounded-lg overflow-hidden p-2 lg:p-3 flex items-center justify-center w-[136px] h-[136px] lg:w-[203px] lg:h-[203px]", children: generateFailed ? /* @__PURE__ */ jsxs(
137
- "button",
101
+ type: "button",
102
+ variant: "ghost",
103
+ className: "size-8! p-0 absolute right-4",
104
+ onClick: handleClose,
105
+ children: /* @__PURE__ */ jsx(IconX, { size: 18 })
106
+ }
107
+ )
108
+ ] }),
109
+ /* @__PURE__ */ jsxs(
110
+ "form",
111
+ {
112
+ className: "flex-1 min-h-0 flex flex-col",
113
+ onSubmit: (e) => {
114
+ e.preventDefault();
115
+ if (isCodeComplete) handleSubmit();
116
+ },
117
+ children: [
118
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-y-auto overscroll-contain lg:overflow-visible", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4 lg:gap-8 px-4 lg:px-5 py-4 lg:py-6 pb-60 lg:pb-6", children: [
119
+ /* @__PURE__ */ jsx("p", { className: "paragraph-small-regular text-gray-950 text-center max-w-full lg:max-w-[412px]", children: translate.rich("common.account.twoFactor.instructions", {
120
+ link: (chunks) => /* @__PURE__ */ jsx(
121
+ "a",
138
122
  {
139
- type: "button",
140
- onClick: () => retryGenerate(),
141
- className: "flex flex-col items-center gap-1.5 text-center",
142
- children: [
143
- /* @__PURE__ */ jsx(IconRefresh, { size: 20, className: "text-gray-400" }),
144
- /* @__PURE__ */ jsx("span", { className: "paragraph-xsmall-medium text-gray-500", children: translate("common.account.twoFactor.retry") })
145
- ]
123
+ href: "https://support.google.com/accounts/answer/1066447",
124
+ target: "_blank",
125
+ rel: "noopener noreferrer",
126
+ className: "paragraph-small-medium underline",
127
+ children: chunks
146
128
  }
147
- ) : isGenerating || !qrcode ? /* @__PURE__ */ jsx("div", { className: "skeleton w-full h-full rounded" }) : (
148
- // eslint-disable-next-line @next/next/no-img-element
149
- /* @__PURE__ */ jsx(
150
- "img",
151
- {
152
- src: qrcode,
153
- alt: translate("common.account.twoFactor.qrAlt"),
154
- className: "w-full h-full"
155
- }
156
- )
157
- ) }),
158
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 w-full", children: [
159
- /* @__PURE__ */ jsx(Separator, { className: "flex-1" }),
160
- /* @__PURE__ */ jsx("span", { className: "paragraph-xsmall-medium text-gray-500 opacity-80 whitespace-nowrap", children: translate("common.account.twoFactor.pasteDigits") }),
161
- /* @__PURE__ */ jsx(Separator, { className: "flex-1" })
162
- ] }),
163
- /* @__PURE__ */ jsx("div", { className: "scroll-mt-20", children: /* @__PURE__ */ jsx(InputOTP, { maxLength: 6, pattern: REGEXP_ONLY_DIGITS, value: code, onChange: setCode, children: /* @__PURE__ */ jsx(InputOTPGroup, { className: "gap-2", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(
164
- InputOTPSlot,
129
+ )
130
+ }) }),
131
+ /* @__PURE__ */ jsx("div", { className: "border border-gray-200 rounded-lg overflow-hidden p-2 lg:p-3 flex items-center justify-center w-[136px] h-[136px] lg:w-[203px] lg:h-[203px]", children: generateFailed ? /* @__PURE__ */ jsxs(
132
+ "button",
133
+ {
134
+ type: "button",
135
+ onClick: () => retryGenerate(),
136
+ className: "flex flex-col items-center gap-1.5 text-center",
137
+ children: [
138
+ /* @__PURE__ */ jsx(IconRefresh, { size: 20, className: "text-gray-400" }),
139
+ /* @__PURE__ */ jsx("span", { className: "paragraph-xsmall-medium text-gray-500", children: translate("common.account.twoFactor.retry") })
140
+ ]
141
+ }
142
+ ) : isGenerating || !qrcode ? /* @__PURE__ */ jsx("div", { className: "skeleton w-full h-full rounded" }) : (
143
+ // eslint-disable-next-line @next/next/no-img-element
144
+ /* @__PURE__ */ jsx(
145
+ "img",
165
146
  {
166
- index: i,
167
- className: "w-11! lg:w-12! h-13! lg:h-14! rounded-lg! text-lg border-gray-200"
168
- },
169
- i
170
- )) }) }) })
171
- ] }) }),
172
- /* @__PURE__ */ jsxs("div", { className: "shrink-0 flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between gap-2 bg-white", children: [
173
- /* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: translate("common.actions.cancel") }),
174
- /* @__PURE__ */ jsx(Button, { type: "submit", className: "h-10!", disabled: !isCodeComplete || isConfirming, children: isConfirming ? translate("common.account.twoFactor.activating") : translate("common.account.twoFactor.activate") })
175
- ] })
176
- ]
177
- }
178
- )
179
- ]
180
- }
181
- ) }) })
182
- );
147
+ src: qrcode,
148
+ alt: translate("common.account.twoFactor.qrAlt"),
149
+ className: "w-full h-full"
150
+ }
151
+ )
152
+ ) }),
153
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 w-full", children: [
154
+ /* @__PURE__ */ jsx(Separator, { className: "flex-1" }),
155
+ /* @__PURE__ */ jsx("span", { className: "paragraph-xsmall-medium text-gray-500 opacity-80 whitespace-nowrap", children: translate("common.account.twoFactor.pasteDigits") }),
156
+ /* @__PURE__ */ jsx(Separator, { className: "flex-1" })
157
+ ] }),
158
+ /* @__PURE__ */ jsx("div", { className: "scroll-mt-20", children: /* @__PURE__ */ jsx(InputOTP, { maxLength: 6, pattern: REGEXP_ONLY_DIGITS, value: code, onChange: setCode, children: /* @__PURE__ */ jsx(InputOTPGroup, { className: "gap-2", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(
159
+ InputOTPSlot,
160
+ {
161
+ index: i,
162
+ className: "w-11! lg:w-12! h-13! lg:h-14! rounded-lg! text-lg border-gray-200"
163
+ },
164
+ i
165
+ )) }) }) })
166
+ ] }) }),
167
+ /* @__PURE__ */ jsxs("div", { className: "shrink-0 flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between gap-2 bg-white", children: [
168
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: translate("common.actions.cancel") }),
169
+ /* @__PURE__ */ jsx(Button, { type: "submit", className: "h-10!", disabled: !isCodeComplete || isConfirming, children: isConfirming ? translate("common.account.twoFactor.activating") : translate("common.account.twoFactor.activate") })
170
+ ] })
171
+ ]
172
+ }
173
+ )
174
+ ]
175
+ }
176
+ ) }) });
183
177
  }
184
178
  export {
185
179
  TwoFactorAuthModal as default
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/account/TwoFactorAuthModal.tsx"],"sourcesContent":["'use client';\n\nimport { useTranslations } from 'next-intl';\nimport { IconX, IconCopy, IconRefresh } from '@tabler/icons-react';\nimport { Button } from '../ui/buttons/Button';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';\nimport { DialogLayer } from '../ui/overlay/layers';\nimport { Separator } from '../ui/data-display/Separator';\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from '../ui/form/InputOtp';\nimport { REGEXP_ONLY_DIGITS } from 'input-otp';\nimport useTwoFactorAuthForm from './hooks/useTwoFactorAuthForm';\n\ninterface TwoFactorAuthModalProps {\n open: boolean;\n onClose: () => void;\n onSuccess?: () => void;\n}\n\nexport default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFactorAuthModalProps) {\n const translate = useTranslations();\n const {\n code,\n setCode,\n isCodeComplete,\n isGenerating,\n isConfirming,\n generateFailed,\n retryGenerate,\n qrcode,\n backupCodes,\n step,\n handleSubmit,\n handleFinalize,\n handleCopyCodes,\n resetForm,\n } = useTwoFactorAuthForm({ onSuccess, open });\n\n const handleClose = () => {\n resetForm();\n onClose();\n };\n\n if (step === 'recovery') {\n return (\n // Abre por cima do modal de configurações da conta, que é irmão na árvore.\n <DialogLayer>\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]\"\n >\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{translate('common.account.twoFactor.recoveryTitle')}</DialogTitle>\n </DialogHeader>\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0\">\n <span className=\"paragraph-medium-semibold text-gray-950 text-center\">\n {translate('common.account.twoFactor.recoveryTitle')}\n </span>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"size-8! p-0 absolute right-4\"\n onClick={handleClose}\n >\n <IconX size={18} />\n </Button>\n </div>\n\n <div className=\"flex flex-col gap-5 lg:gap-6 px-4 lg:px-5 py-5 lg:py-6 flex-1 lg:flex-none\">\n <div className=\"flex flex-col gap-2\">\n <h3 className=\"paragraph-medium-semibold text-gray-950 max-w-[269px]\">\n {translate('common.account.twoFactor.recoveryHeading')}\n </h3>\n <div className=\"paragraph-small-regular text-gray-600\">\n <p>{translate('common.account.twoFactor.recoveryText1')}</p>\n <br />\n <p>{translate('common.account.twoFactor.recoveryText2')}</p>\n </div>\n </div>\n\n <div className=\"bg-gray-50 rounded-lg p-4 flex flex-col gap-4\">\n <div className=\"paragraph-small-medium text-gray-950 whitespace-nowrap\">\n {backupCodes.map((backupCode, i) => (\n <p key={i}>{backupCode}</p>\n ))}\n </div>\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-8! w-fit\"\n onClick={handleCopyCodes}\n >\n <IconCopy size={16} />\n {translate('common.account.twoFactor.copyCodes')}\n </Button>\n </div>\n </div>\n\n <div className=\"flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n {translate('common.actions.cancel')}\n </Button>\n <Button className=\"h-10!\" type=\"button\" onClick={handleFinalize}>\n {translate('common.account.twoFactor.finish')}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n </DialogLayer>\n );\n }\n\n return (\n // Abre por cima do modal de configurações da conta, que é irmão na árvore.\n <DialogLayer>\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:max-h-[90vh] lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]\"\n >\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{translate('common.account.twoFactor.title')}</DialogTitle>\n </DialogHeader>\n <div className=\"shrink-0 flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0\">\n <span className=\"paragraph-medium-semibold text-gray-950 text-center\">\n {translate('common.account.twoFactor.title')}\n </span>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"size-8! p-0 absolute right-4\"\n onClick={handleClose}\n >\n <IconX size={18} />\n </Button>\n </div>\n\n <form\n className=\"flex-1 min-h-0 flex flex-col\"\n onSubmit={(e) => {\n e.preventDefault();\n if (isCodeComplete) handleSubmit();\n }}\n >\n <div className=\"flex-1 min-h-0 overflow-y-auto overscroll-contain lg:overflow-visible\">\n <div className=\"flex flex-col items-center gap-4 lg:gap-8 px-4 lg:px-5 py-4 lg:py-6 pb-60 lg:pb-6\">\n <p className=\"paragraph-small-regular text-gray-950 text-center max-w-full lg:max-w-[412px]\">\n {translate.rich('common.account.twoFactor.instructions', {\n link: (chunks) => (\n <a\n href=\"https://support.google.com/accounts/answer/1066447\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"paragraph-small-medium underline\"\n >\n {chunks}\n </a>\n ),\n })}\n </p>\n\n <div className=\"border border-gray-200 rounded-lg overflow-hidden p-2 lg:p-3 flex items-center justify-center w-[136px] h-[136px] lg:w-[203px] lg:h-[203px]\">\n {generateFailed ? (\n <button\n type=\"button\"\n onClick={() => retryGenerate()}\n className=\"flex flex-col items-center gap-1.5 text-center\"\n >\n <IconRefresh size={20} className=\"text-gray-400\" />\n <span className=\"paragraph-xsmall-medium text-gray-500\">\n {translate('common.account.twoFactor.retry')}\n </span>\n </button>\n ) : isGenerating || !qrcode ? (\n <div className=\"skeleton w-full h-full rounded\" />\n ) : (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={qrcode}\n alt={translate('common.account.twoFactor.qrAlt')}\n className=\"w-full h-full\"\n />\n )}\n </div>\n\n <div className=\"flex items-center gap-3 w-full\">\n <Separator className=\"flex-1\" />\n <span className=\"paragraph-xsmall-medium text-gray-500 opacity-80 whitespace-nowrap\">\n {translate('common.account.twoFactor.pasteDigits')}\n </span>\n <Separator className=\"flex-1\" />\n </div>\n\n <div className=\"scroll-mt-20\">\n <InputOTP maxLength={6} pattern={REGEXP_ONLY_DIGITS} value={code} onChange={setCode}>\n <InputOTPGroup className=\"gap-2\">\n {Array.from({ length: 6 }).map((_, i) => (\n <InputOTPSlot\n key={i}\n index={i}\n className=\"w-11! lg:w-12! h-13! lg:h-14! rounded-lg! text-lg border-gray-200\"\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n </div>\n </div>\n </div>\n\n <div className=\"shrink-0 flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between gap-2 bg-white\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n {translate('common.actions.cancel')}\n </Button>\n <Button type=\"submit\" className=\"h-10!\" disabled={!isCodeComplete || isConfirming}>\n {isConfirming\n ? translate('common.account.twoFactor.activating')\n : translate('common.account.twoFactor.activate')}\n </Button>\n </div>\n </form>\n </DialogContent>\n </Dialog>\n </DialogLayer>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/account/TwoFactorAuthModal.tsx"],"sourcesContent":["'use client';\n\nimport { useTranslations } from 'next-intl';\nimport { IconX, IconCopy, IconRefresh } from '@tabler/icons-react';\nimport { Button } from '../ui/buttons/Button';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';\nimport { DialogLayer } from '../ui/overlay/layers';\nimport { Separator } from '../ui/data-display/Separator';\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from '../ui/form/InputOtp';\nimport { REGEXP_ONLY_DIGITS } from 'input-otp';\nimport useTwoFactorAuthForm from './hooks/useTwoFactorAuthForm';\n\ninterface TwoFactorAuthModalProps {\n open: boolean;\n onClose: () => void;\n onSuccess?: () => void;\n}\n\nexport default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFactorAuthModalProps) {\n const translate = useTranslations();\n const {\n code,\n setCode,\n isCodeComplete,\n isGenerating,\n isConfirming,\n generateFailed,\n retryGenerate,\n qrcode,\n backupCodes,\n step,\n handleSubmit,\n handleFinalize,\n handleCopyCodes,\n resetForm,\n } = useTwoFactorAuthForm({ onSuccess, open });\n\n const handleClose = () => {\n resetForm();\n onClose();\n };\n\n if (step === 'recovery') {\n return (\n <DialogLayer>\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]\"\n >\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{translate('common.account.twoFactor.recoveryTitle')}</DialogTitle>\n </DialogHeader>\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0\">\n <span className=\"paragraph-medium-semibold text-gray-950 text-center\">\n {translate('common.account.twoFactor.recoveryTitle')}\n </span>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"size-8! p-0 absolute right-4\"\n onClick={handleClose}\n >\n <IconX size={18} />\n </Button>\n </div>\n\n <div className=\"flex flex-col gap-5 lg:gap-6 px-4 lg:px-5 py-5 lg:py-6 flex-1 lg:flex-none\">\n <div className=\"flex flex-col gap-2\">\n <h3 className=\"paragraph-medium-semibold text-gray-950 max-w-[269px]\">\n {translate('common.account.twoFactor.recoveryHeading')}\n </h3>\n <div className=\"paragraph-small-regular text-gray-600\">\n <p>{translate('common.account.twoFactor.recoveryText1')}</p>\n <br />\n <p>{translate('common.account.twoFactor.recoveryText2')}</p>\n </div>\n </div>\n\n <div className=\"bg-gray-50 rounded-lg p-4 flex flex-col gap-4\">\n <div className=\"paragraph-small-medium text-gray-950 whitespace-nowrap\">\n {backupCodes.map((backupCode, i) => (\n <p key={i}>{backupCode}</p>\n ))}\n </div>\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-8! w-fit\"\n onClick={handleCopyCodes}\n >\n <IconCopy size={16} />\n {translate('common.account.twoFactor.copyCodes')}\n </Button>\n </div>\n </div>\n\n <div className=\"flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n {translate('common.actions.cancel')}\n </Button>\n <Button className=\"h-10!\" type=\"button\" onClick={handleFinalize}>\n {translate('common.account.twoFactor.finish')}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n </DialogLayer>\n );\n }\n\n return (\n <DialogLayer>\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:max-h-[90vh] lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]\"\n >\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{translate('common.account.twoFactor.title')}</DialogTitle>\n </DialogHeader>\n <div className=\"shrink-0 flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0\">\n <span className=\"paragraph-medium-semibold text-gray-950 text-center\">\n {translate('common.account.twoFactor.title')}\n </span>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"size-8! p-0 absolute right-4\"\n onClick={handleClose}\n >\n <IconX size={18} />\n </Button>\n </div>\n\n <form\n className=\"flex-1 min-h-0 flex flex-col\"\n onSubmit={(e) => {\n e.preventDefault();\n if (isCodeComplete) handleSubmit();\n }}\n >\n <div className=\"flex-1 min-h-0 overflow-y-auto overscroll-contain lg:overflow-visible\">\n <div className=\"flex flex-col items-center gap-4 lg:gap-8 px-4 lg:px-5 py-4 lg:py-6 pb-60 lg:pb-6\">\n <p className=\"paragraph-small-regular text-gray-950 text-center max-w-full lg:max-w-[412px]\">\n {translate.rich('common.account.twoFactor.instructions', {\n link: (chunks) => (\n <a\n href=\"https://support.google.com/accounts/answer/1066447\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"paragraph-small-medium underline\"\n >\n {chunks}\n </a>\n ),\n })}\n </p>\n\n <div className=\"border border-gray-200 rounded-lg overflow-hidden p-2 lg:p-3 flex items-center justify-center w-[136px] h-[136px] lg:w-[203px] lg:h-[203px]\">\n {generateFailed ? (\n <button\n type=\"button\"\n onClick={() => retryGenerate()}\n className=\"flex flex-col items-center gap-1.5 text-center\"\n >\n <IconRefresh size={20} className=\"text-gray-400\" />\n <span className=\"paragraph-xsmall-medium text-gray-500\">\n {translate('common.account.twoFactor.retry')}\n </span>\n </button>\n ) : isGenerating || !qrcode ? (\n <div className=\"skeleton w-full h-full rounded\" />\n ) : (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={qrcode}\n alt={translate('common.account.twoFactor.qrAlt')}\n className=\"w-full h-full\"\n />\n )}\n </div>\n\n <div className=\"flex items-center gap-3 w-full\">\n <Separator className=\"flex-1\" />\n <span className=\"paragraph-xsmall-medium text-gray-500 opacity-80 whitespace-nowrap\">\n {translate('common.account.twoFactor.pasteDigits')}\n </span>\n <Separator className=\"flex-1\" />\n </div>\n\n <div className=\"scroll-mt-20\">\n <InputOTP maxLength={6} pattern={REGEXP_ONLY_DIGITS} value={code} onChange={setCode}>\n <InputOTPGroup className=\"gap-2\">\n {Array.from({ length: 6 }).map((_, i) => (\n <InputOTPSlot\n key={i}\n index={i}\n className=\"w-11! lg:w-12! h-13! lg:h-14! rounded-lg! text-lg border-gray-200\"\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n </div>\n </div>\n </div>\n\n <div className=\"shrink-0 flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between gap-2 bg-white\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n {translate('common.actions.cancel')}\n </Button>\n <Button type=\"submit\" className=\"h-10!\" disabled={!isCodeComplete || isConfirming}>\n {isConfirming\n ? translate('common.account.twoFactor.activating')\n : translate('common.account.twoFactor.activate')}\n </Button>\n </div>\n </form>\n </DialogContent>\n </Dialog>\n </DialogLayer>\n );\n}\n"],"mappings":"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","names":[]}
@@ -7,7 +7,9 @@ import { useRouter } from "next/navigation";
7
7
  import { toast } from "sonner";
8
8
  import { IconLock } from "@tabler/icons-react";
9
9
  import { cn } from "../../../infra/utils/clsx";
10
+ import { isLocale } from "../../../i18n/config";
10
11
  import { setLocaleCookie } from "../../../utils/intl/locale-cookie";
12
+ import { localeToApiLanguage } from "../../../utils/intl/locales";
11
13
  import { Button } from "../../ui/buttons/Button";
12
14
  import { Separator } from "../../ui/data-display/Separator";
13
15
  import { Toast } from "../../ui/feedback/Toast";
@@ -86,7 +88,7 @@ function PreferencesSection({ onClose }) {
86
88
  const doSave = async (data, accountFields) => {
87
89
  setIsSaving(true);
88
90
  try {
89
- const apiLanguage = LANGUAGE_OPTIONS.find((o) => o.value === data.language)?.apiValue ?? data.language.toLowerCase();
91
+ const apiLanguage = isLocale(data.language) ? localeToApiLanguage(data.language) : data.language.toLowerCase();
90
92
  await updateAccountUser.mutateAsync({
91
93
  language: apiLanguage,
92
94
  receive_sms: data.receive_sms,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/account/sections/PreferencesSection.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { useTranslations, useLocale } from 'next-intl';\nimport { useRouter } from 'next/navigation';\nimport { toast } from 'sonner';\nimport { IconLock } from '@tabler/icons-react';\nimport { cn } from '../../../infra/utils/clsx';\nimport type { Locale } from '../../../i18n/config';\nimport { setLocaleCookie } from '../../../utils/intl/locale-cookie';\nimport { Button } from '../../ui/buttons/Button';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { FormField } from '../../ui/form/FormField';\nimport { ComboboxField } from '../../ui/form/ComboboxField';\nimport { SelectField } from '../../ui/form/SelectField';\nimport ConfirmGlobalPreferencesModal from '../ConfirmGlobalPreferencesModal';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { useWhitelabel } from '../../../providers/whitelabel.provider';\nimport { UserProfile } from '../../../modules/users/schema';\nimport type { UpdateAccountRequest } from '../../../modules/accounts/types';\nimport {\n useUpdateAccountUser,\n useUpdateAccount,\n} from '../../../modules/accounts/hooks/useAccountManagement';\nimport {\n LANGUAGE_OPTIONS,\n TIME_FORMAT_OPTIONS,\n} from '../constants';\nimport { useTimezones } from '../../../modules/accounts/hooks/useTimezones';\nimport { useCurrencies } from '../../../modules/accounts/hooks/useCurrencies';\nimport { getCurrencyForGateway } from '../../../utils/format/currency';\n\ninterface PreferencesFormValues {\n companyName: string;\n language: string;\n currency: string;\n timezone: string;\n timeFormat: string;\n receive_sms: boolean;\n receive_email: boolean;\n}\n\ninterface PreferencesSectionProps {\n onClose: () => void;\n}\n\nexport function PreferencesSection({ onClose }: PreferencesSectionProps) {\n // Padrão raiz: um único `translate` chamado pela chave inteira (`common.<modulo>.<chave>`).\n const translate = useTranslations();\n // Exceção: chave dinâmica (option.value) numa lista → namespace escopado.\n const translateLanguage = useTranslations('common.languages');\n const currentLocale = useLocale();\n const router = useRouter();\n const { data: timezones = [] } = useTimezones();\n const { data: currencies = [] } = useCurrencies();\n const { user, account } = useAuth();\n const { whitelabel } = useWhitelabel();\n const languageOptions = LANGUAGE_OPTIONS.map((option) => ({\n ...option,\n label: translateLanguage(option.value as Locale),\n displayValue: translateLanguage(option.value as Locale),\n }));\n const timeFormatOptions = TIME_FORMAT_OPTIONS.map((option) => ({\n ...option,\n label: translate(\n `common.preferences.timeFormatOptions.${option.value === '24h' ? 'h24' : 'h12'}`,\n ),\n }));\n const isOwner = user?.profile === UserProfile.owner;\n const canEditPreferences = isOwner || user?.profile === UserProfile.admin;\n const updateAccountUser = useUpdateAccountUser();\n const updateAccount = useUpdateAccount();\n const [confirmGlobalOpen, setConfirmGlobalOpen] = useState(false);\n const [pendingSubmit, setPendingSubmit] = useState<{\n data: PreferencesFormValues;\n accountFields: UpdateAccountRequest;\n } | null>(null);\n const [isSaving, setIsSaving] = useState(false);\n\n const { watch, setValue, handleSubmit, reset, formState: { dirtyFields } } =\n useForm<PreferencesFormValues>({\n defaultValues: {\n companyName: '',\n language: '',\n currency: '',\n timezone: '',\n timeFormat: '24h',\n receive_sms: false,\n receive_email: false,\n },\n });\n\n useEffect(() => {\n if (!user || !account) return;\n reset({\n companyName: account.name ?? '',\n language: LANGUAGE_OPTIONS.find(\n (o) => o.apiValue === user.language?.toLowerCase()\n )?.value ?? 'pt-br',\n // A moeda é derivada do gateway da conta (read-only para o usuário) —\n // espelha o que useCurrencyFormatter usa no display de preços.\n currency: getCurrencyForGateway(account.gateway).toUpperCase(),\n timezone: account.timezone,\n timeFormat: '24h',\n receive_sms: user.receive_sms ?? false,\n receive_email: user.receive_email ?? false,\n });\n }, [user, account, reset]);\n\n const doSave = async (data: PreferencesFormValues, accountFields: UpdateAccountRequest) => {\n setIsSaving(true);\n try {\n const apiLanguage = LANGUAGE_OPTIONS.find((o) => o.value === data.language)?.apiValue ?? data.language.toLowerCase();\n await updateAccountUser.mutateAsync({\n language: apiLanguage,\n receive_sms: data.receive_sms,\n receive_email: data.receive_email,\n });\n\n if (canEditPreferences && Object.keys(accountFields).length > 0) {\n await updateAccount.mutateAsync(accountFields);\n }\n\n reset(data);\n toast.custom((toastId) => (\n <Toast variant=\"success\" message={translate('common.preferences.savedSuccess')} toastId={toastId} />\n ));\n onClose();\n if (data.language !== currentLocale) {\n setLocaleCookie(data.language, whitelabel?.domain);\n router.refresh();\n }\n } catch (error) {\n toast.custom((toastId) => (\n <Toast\n variant=\"error\"\n message={error instanceof Error ? error.message : translate('common.preferences.saveError')}\n toastId={toastId}\n />\n ));\n } finally {\n setIsSaving(false);\n }\n };\n\n const onSubmit = (data: PreferencesFormValues) => {\n const accountFields: UpdateAccountRequest = {\n ...(isOwner && dirtyFields.companyName && { name: data.companyName }),\n // currency é read-only (derivada do gateway) — não enviada no update.\n ...(canEditPreferences && dirtyFields.timezone && { timezone: data.timezone }),\n };\n const globalFieldChanged = Object.keys(accountFields).length > 0;\n\n if (globalFieldChanged) {\n setPendingSubmit({ data, accountFields });\n setConfirmGlobalOpen(true);\n } else {\n doSave(data, accountFields);\n }\n };\n\n const handleConfirmGlobal = () => {\n setConfirmGlobalOpen(false);\n if (pendingSubmit) {\n doSave(pendingSubmit.data, pendingSubmit.accountFields);\n setPendingSubmit(null);\n }\n };\n\n const handleCancelGlobal = () => {\n setConfirmGlobalOpen(false);\n setPendingSubmit(null);\n };\n\n return (\n <>\n <form onSubmit={handleSubmit(onSubmit)} className=\"flex flex-col h-full\">\n <div className=\"overflow-y-auto overscroll-contain px-4 pb-4 lg:p-5 flex flex-col gap-5 lg:gap-6 flex-1\">\n <span className=\"paragraph-medium-semibold text-gray-950\">{translate('common.preferences.title')}</span>\n <div className=\"flex flex-col gap-8\">\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <FormField\n label={translate('common.preferences.companyName')}\n placeholder={translate('common.preferences.companyNamePlaceholder')}\n classnameContainer={cn('w-full', !isOwner && 'cursor-not-allowed opacity-50')}\n value={watch('companyName')}\n onChange={(e) => setValue('companyName', e.target.value, { shouldDirty: true })}\n disabled={!isOwner}\n />\n </div>\n\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <ComboboxField\n label={translate('common.preferences.language')}\n placeholder={translate('common.preferences.languagePlaceholder')}\n searchPlaceholder={translate('common.preferences.languageSearch')}\n containerClassName=\"w-full\"\n options={languageOptions}\n value={watch('language')}\n onChange={(value) => setValue('language', value, { shouldDirty: true })}\n />\n <ComboboxField\n label={translate('common.preferences.currency')}\n placeholder={translate('common.preferences.currencyPlaceholder')}\n searchPlaceholder={translate('common.preferences.currencySearch')}\n containerClassName=\"w-full\"\n options={currencies}\n value={watch('currency')}\n onChange={() => undefined}\n icon={<IconLock className=\"size-4 text-gray-400\" />}\n disabled\n />\n </div>\n\n <Separator />\n\n <div className=\"flex flex-col gap-4\">\n <span className=\"paragraph-medium-semibold text-gray-950\">{translate('common.preferences.timeDisplay')}</span>\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <ComboboxField\n label={translate('common.preferences.timezone')}\n placeholder={translate('common.preferences.timezonePlaceholder')}\n searchPlaceholder={translate('common.preferences.timezoneSearch')}\n containerClassName=\"w-full\"\n options={timezones}\n value={watch('timezone')}\n onChange={(value) => setValue('timezone', value, { shouldDirty: true })}\n icon={!canEditPreferences ? <IconLock className=\"size-4 text-gray-400\" /> : undefined}\n disabled={!canEditPreferences}\n />\n <SelectField\n label={translate('common.preferences.timeFormat')}\n placeholder={translate('common.preferences.timeFormatPlaceholder')}\n className=\"h-10!\"\n containerClassName=\"w-full\"\n options={timeFormatOptions}\n value={watch('timeFormat')}\n onChange={(value) =>\n setValue('timeFormat', value as string, { shouldDirty: true })\n }\n icon={<IconLock className=\"size-4 text-gray-400\" />}\n disabled\n />\n </div>\n </div>\n\n </div>\n </div>\n\n <div className=\"fixed bottom-0 left-0 right-0 lg:absolute flex items-center h-20 px-4 lg:px-5 border-t border-gray-200 justify-between bg-white z-10\">\n <Button\n variant=\"secondary\"\n className=\"h-10!\"\n type=\"button\"\n disabled={isSaving}\n onClick={() => {\n reset();\n onClose();\n }}\n >\n {translate('common.actions.cancel')}\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={isSaving}>\n {isSaving ? translate('common.actions.saving') : translate('common.actions.saveChanges')}\n </Button>\n </div>\n </form>\n\n <ConfirmGlobalPreferencesModal\n open={confirmGlobalOpen}\n onConfirm={handleConfirmGlobal}\n onCancel={handleCancelGlobal}\n />\n </>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/components/account/sections/PreferencesSection.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { useTranslations, useLocale } from 'next-intl';\nimport { useRouter } from 'next/navigation';\nimport { toast } from 'sonner';\nimport { IconLock } from '@tabler/icons-react';\nimport { cn } from '../../../infra/utils/clsx';\nimport { isLocale, type Locale } from '../../../i18n/config';\nimport { setLocaleCookie } from '../../../utils/intl/locale-cookie';\nimport { localeToApiLanguage } from '../../../utils/intl/locales';\nimport { Button } from '../../ui/buttons/Button';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { FormField } from '../../ui/form/FormField';\nimport { ComboboxField } from '../../ui/form/ComboboxField';\nimport { SelectField } from '../../ui/form/SelectField';\nimport ConfirmGlobalPreferencesModal from '../ConfirmGlobalPreferencesModal';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { useWhitelabel } from '../../../providers/whitelabel.provider';\nimport { UserProfile } from '../../../modules/users/schema';\nimport type { UpdateAccountRequest } from '../../../modules/accounts/types';\nimport {\n useUpdateAccountUser,\n useUpdateAccount,\n} from '../../../modules/accounts/hooks/useAccountManagement';\nimport {\n LANGUAGE_OPTIONS,\n TIME_FORMAT_OPTIONS,\n} from '../constants';\nimport { useTimezones } from '../../../modules/accounts/hooks/useTimezones';\nimport { useCurrencies } from '../../../modules/accounts/hooks/useCurrencies';\nimport { getCurrencyForGateway } from '../../../utils/format/currency';\n\ninterface PreferencesFormValues {\n companyName: string;\n language: string;\n currency: string;\n timezone: string;\n timeFormat: string;\n receive_sms: boolean;\n receive_email: boolean;\n}\n\ninterface PreferencesSectionProps {\n onClose: () => void;\n}\n\nexport function PreferencesSection({ onClose }: PreferencesSectionProps) {\n // Padrão raiz: um único `translate` chamado pela chave inteira (`common.<modulo>.<chave>`).\n const translate = useTranslations();\n // Exceção: chave dinâmica (option.value) numa lista → namespace escopado.\n const translateLanguage = useTranslations('common.languages');\n const currentLocale = useLocale();\n const router = useRouter();\n const { data: timezones = [] } = useTimezones();\n const { data: currencies = [] } = useCurrencies();\n const { user, account } = useAuth();\n const { whitelabel } = useWhitelabel();\n const languageOptions = LANGUAGE_OPTIONS.map((option) => ({\n ...option,\n label: translateLanguage(option.value as Locale),\n displayValue: translateLanguage(option.value as Locale),\n }));\n const timeFormatOptions = TIME_FORMAT_OPTIONS.map((option) => ({\n ...option,\n label: translate(\n `common.preferences.timeFormatOptions.${option.value === '24h' ? 'h24' : 'h12'}`,\n ),\n }));\n const isOwner = user?.profile === UserProfile.owner;\n const canEditPreferences = isOwner || user?.profile === UserProfile.admin;\n const updateAccountUser = useUpdateAccountUser();\n const updateAccount = useUpdateAccount();\n const [confirmGlobalOpen, setConfirmGlobalOpen] = useState(false);\n const [pendingSubmit, setPendingSubmit] = useState<{\n data: PreferencesFormValues;\n accountFields: UpdateAccountRequest;\n } | null>(null);\n const [isSaving, setIsSaving] = useState(false);\n\n const { watch, setValue, handleSubmit, reset, formState: { dirtyFields } } =\n useForm<PreferencesFormValues>({\n defaultValues: {\n companyName: '',\n language: '',\n currency: '',\n timezone: '',\n timeFormat: '24h',\n receive_sms: false,\n receive_email: false,\n },\n });\n\n useEffect(() => {\n if (!user || !account) return;\n reset({\n companyName: account.name ?? '',\n language: LANGUAGE_OPTIONS.find(\n (o) => o.apiValue === user.language?.toLowerCase()\n )?.value ?? 'pt-br',\n // A moeda é derivada do gateway da conta (read-only para o usuário) —\n // espelha o que useCurrencyFormatter usa no display de preços.\n currency: getCurrencyForGateway(account.gateway).toUpperCase(),\n timezone: account.timezone,\n timeFormat: '24h',\n receive_sms: user.receive_sms ?? false,\n receive_email: user.receive_email ?? false,\n });\n }, [user, account, reset]);\n\n const doSave = async (data: PreferencesFormValues, accountFields: UpdateAccountRequest) => {\n setIsSaving(true);\n try {\n const apiLanguage = isLocale(data.language) ? localeToApiLanguage(data.language) : data.language.toLowerCase();\n await updateAccountUser.mutateAsync({\n language: apiLanguage,\n receive_sms: data.receive_sms,\n receive_email: data.receive_email,\n });\n\n if (canEditPreferences && Object.keys(accountFields).length > 0) {\n await updateAccount.mutateAsync(accountFields);\n }\n\n reset(data);\n toast.custom((toastId) => (\n <Toast variant=\"success\" message={translate('common.preferences.savedSuccess')} toastId={toastId} />\n ));\n onClose();\n if (data.language !== currentLocale) {\n setLocaleCookie(data.language, whitelabel?.domain);\n router.refresh();\n }\n } catch (error) {\n toast.custom((toastId) => (\n <Toast\n variant=\"error\"\n message={error instanceof Error ? error.message : translate('common.preferences.saveError')}\n toastId={toastId}\n />\n ));\n } finally {\n setIsSaving(false);\n }\n };\n\n const onSubmit = (data: PreferencesFormValues) => {\n const accountFields: UpdateAccountRequest = {\n ...(isOwner && dirtyFields.companyName && { name: data.companyName }),\n // currency é read-only (derivada do gateway) — não enviada no update.\n ...(canEditPreferences && dirtyFields.timezone && { timezone: data.timezone }),\n };\n const globalFieldChanged = Object.keys(accountFields).length > 0;\n\n if (globalFieldChanged) {\n setPendingSubmit({ data, accountFields });\n setConfirmGlobalOpen(true);\n } else {\n doSave(data, accountFields);\n }\n };\n\n const handleConfirmGlobal = () => {\n setConfirmGlobalOpen(false);\n if (pendingSubmit) {\n doSave(pendingSubmit.data, pendingSubmit.accountFields);\n setPendingSubmit(null);\n }\n };\n\n const handleCancelGlobal = () => {\n setConfirmGlobalOpen(false);\n setPendingSubmit(null);\n };\n\n return (\n <>\n <form onSubmit={handleSubmit(onSubmit)} className=\"flex flex-col h-full\">\n <div className=\"overflow-y-auto overscroll-contain px-4 pb-4 lg:p-5 flex flex-col gap-5 lg:gap-6 flex-1\">\n <span className=\"paragraph-medium-semibold text-gray-950\">{translate('common.preferences.title')}</span>\n <div className=\"flex flex-col gap-8\">\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <FormField\n label={translate('common.preferences.companyName')}\n placeholder={translate('common.preferences.companyNamePlaceholder')}\n classnameContainer={cn('w-full', !isOwner && 'cursor-not-allowed opacity-50')}\n value={watch('companyName')}\n onChange={(e) => setValue('companyName', e.target.value, { shouldDirty: true })}\n disabled={!isOwner}\n />\n </div>\n\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <ComboboxField\n label={translate('common.preferences.language')}\n placeholder={translate('common.preferences.languagePlaceholder')}\n searchPlaceholder={translate('common.preferences.languageSearch')}\n containerClassName=\"w-full\"\n options={languageOptions}\n value={watch('language')}\n onChange={(value) => setValue('language', value, { shouldDirty: true })}\n />\n <ComboboxField\n label={translate('common.preferences.currency')}\n placeholder={translate('common.preferences.currencyPlaceholder')}\n searchPlaceholder={translate('common.preferences.currencySearch')}\n containerClassName=\"w-full\"\n options={currencies}\n value={watch('currency')}\n onChange={() => undefined}\n icon={<IconLock className=\"size-4 text-gray-400\" />}\n disabled\n />\n </div>\n\n <Separator />\n\n <div className=\"flex flex-col gap-4\">\n <span className=\"paragraph-medium-semibold text-gray-950\">{translate('common.preferences.timeDisplay')}</span>\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <ComboboxField\n label={translate('common.preferences.timezone')}\n placeholder={translate('common.preferences.timezonePlaceholder')}\n searchPlaceholder={translate('common.preferences.timezoneSearch')}\n containerClassName=\"w-full\"\n options={timezones}\n value={watch('timezone')}\n onChange={(value) => setValue('timezone', value, { shouldDirty: true })}\n icon={!canEditPreferences ? <IconLock className=\"size-4 text-gray-400\" /> : undefined}\n disabled={!canEditPreferences}\n />\n <SelectField\n label={translate('common.preferences.timeFormat')}\n placeholder={translate('common.preferences.timeFormatPlaceholder')}\n className=\"h-10!\"\n containerClassName=\"w-full\"\n options={timeFormatOptions}\n value={watch('timeFormat')}\n onChange={(value) =>\n setValue('timeFormat', value as string, { shouldDirty: true })\n }\n icon={<IconLock className=\"size-4 text-gray-400\" />}\n disabled\n />\n </div>\n </div>\n\n </div>\n </div>\n\n <div className=\"fixed bottom-0 left-0 right-0 lg:absolute flex items-center h-20 px-4 lg:px-5 border-t border-gray-200 justify-between bg-white z-10\">\n <Button\n variant=\"secondary\"\n className=\"h-10!\"\n type=\"button\"\n disabled={isSaving}\n onClick={() => {\n reset();\n onClose();\n }}\n >\n {translate('common.actions.cancel')}\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={isSaving}>\n {isSaving ? translate('common.actions.saving') : translate('common.actions.saveChanges')}\n </Button>\n </div>\n </form>\n\n <ConfirmGlobalPreferencesModal\n open={confirmGlobalOpen}\n onConfirm={handleConfirmGlobal}\n onCancel={handleCancelGlobal}\n />\n </>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/modals/ModalManager.tsx"],"sourcesContent":["'use client';\n\nimport { ComponentType, useContext } from 'react';\nimport { useModalManager } from '../../store/useModalManager';\nimport { DialogDepthContext } from '../ui/overlay/layers';\n\ninterface ModalManagerProps {\n registry: Record<string, ComponentType>;\n}\n\nexport function ModalManager({ registry }: ModalManagerProps) {\n const { modalStack } = useModalManager();\n const depth = useContext(DialogDepthContext);\n\n if (modalStack.length === 0) return null;\n\n // Modais da pilha nascem irmaos na arvore React: sem isso, todos cairiam na\n // mesma profundidade e na mesma faixa de z-index (ver layers.tsx). A\n // posicao na pilha vira a profundidade, relativa a onde o ModalManager\n // esta montado.\n return (\n <>\n {modalStack.map((modal, index) => {\n const ModalComponent = registry[modal.key];\n\n if (!ModalComponent) {\n console.warn(`Modal \"${modal.key}\" not found in registry`);\n return null;\n }\n\n return (\n <DialogDepthContext.Provider value={depth + index} key={modal.key}>\n <ModalComponent />\n </DialogDepthContext.Provider>\n );\n })}\n </>\n );\n}\n"],"mappings":";AAqBI,mBAWQ,WAXR;AAnBJ,SAAwB,kBAAkB;AAC1C,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AAM5B,SAAS,aAAa,EAAE,SAAS,GAAsB;AAC5D,QAAM,EAAE,WAAW,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,kBAAkB;AAE3C,MAAI,WAAW,WAAW,EAAG,QAAO;AAMpC,SACE,gCACG,qBAAW,IAAI,CAAC,OAAO,UAAU;AAChC,UAAM,iBAAiB,SAAS,MAAM,GAAG;AAEzC,QAAI,CAAC,gBAAgB;AACnB,cAAQ,KAAK,UAAU,MAAM,GAAG,yBAAyB;AACzD,aAAO;AAAA,IACT;AAEA,WACE,oBAAC,mBAAmB,UAAnB,EAA4B,OAAO,QAAQ,OAC1C,8BAAC,kBAAe,KADsC,MAAM,GAE9D;AAAA,EAEJ,CAAC,GACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/modals/ModalManager.tsx"],"sourcesContent":["'use client';\n\nimport { ComponentType, useContext } from 'react';\nimport { useModalManager } from '../../store/useModalManager';\nimport { DialogDepthContext } from '../ui/overlay/layers';\n\ninterface ModalManagerProps {\n registry: Record<string, ComponentType>;\n}\n\nexport function ModalManager({ registry }: ModalManagerProps) {\n const { modalStack } = useModalManager();\n const depth = useContext(DialogDepthContext);\n\n if (modalStack.length === 0) return null;\n\n return (\n <>\n {modalStack.map((modal, index) => {\n const ModalComponent = registry[modal.key];\n\n if (!ModalComponent) {\n console.warn(`Modal \"${modal.key}\" not found in registry`);\n return null;\n }\n\n return (\n <DialogDepthContext.Provider value={depth + index} key={modal.key}>\n <ModalComponent />\n </DialogDepthContext.Provider>\n );\n })}\n </>\n );\n}\n"],"mappings":";AAiBI,mBAWQ,WAXR;AAfJ,SAAwB,kBAAkB;AAC1C,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AAM5B,SAAS,aAAa,EAAE,SAAS,GAAsB;AAC5D,QAAM,EAAE,WAAW,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,kBAAkB;AAE3C,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,SACE,gCACG,qBAAW,IAAI,CAAC,OAAO,UAAU;AAChC,UAAM,iBAAiB,SAAS,MAAM,GAAG;AAEzC,QAAI,CAAC,gBAAgB;AACnB,cAAQ,KAAK,UAAU,MAAM,GAAG,yBAAyB;AACzD,aAAO;AAAA,IACT;AAEA,WACE,oBAAC,mBAAmB,UAAnB,EAA4B,OAAO,QAAQ,OAC1C,8BAAC,kBAAe,KADsC,MAAM,GAE9D;AAAA,EAEJ,CAAC,GACH;AAEJ;","names":[]}