@greatapps/common 1.1.665 → 1.1.667

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 (106) hide show
  1. package/dist/components/account/ConfigurationsMyAccountModal.mjs +8 -6
  2. package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
  3. package/dist/components/account/ConfirmDeleteAccountModal.mjs +20 -19
  4. package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
  5. package/dist/components/account/ConfirmGlobalPreferencesModal.mjs +10 -11
  6. package/dist/components/account/ConfirmGlobalPreferencesModal.mjs.map +1 -1
  7. package/dist/components/account/DeleteAccountModal.mjs +34 -28
  8. package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
  9. package/dist/components/account/DisableTwoFactorAuthModal.mjs +7 -5
  10. package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -1
  11. package/dist/components/account/IsntPossibleDeleteAccountModal.mjs +8 -9
  12. package/dist/components/account/IsntPossibleDeleteAccountModal.mjs.map +1 -1
  13. package/dist/components/account/TwoFactorAuthModal.mjs +22 -23
  14. package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -1
  15. package/dist/components/account/hooks/useChangeEmailForm.mjs +5 -3
  16. package/dist/components/account/hooks/useChangeEmailForm.mjs.map +1 -1
  17. package/dist/components/account/hooks/useChangePasswordForm.mjs +26 -3
  18. package/dist/components/account/hooks/useChangePasswordForm.mjs.map +1 -1
  19. package/dist/components/account/hooks/useChangePhoneForm.mjs +18 -9
  20. package/dist/components/account/hooks/useChangePhoneForm.mjs.map +1 -1
  21. package/dist/components/account/hooks/useDisableTwoFactorAuthForm.mjs +26 -3
  22. package/dist/components/account/hooks/useDisableTwoFactorAuthForm.mjs.map +1 -1
  23. package/dist/components/account/hooks/useOtpVerification.mjs +19 -3
  24. package/dist/components/account/hooks/useOtpVerification.mjs.map +1 -1
  25. package/dist/components/account/hooks/useTwoFactorAuthForm.mjs +27 -4
  26. package/dist/components/account/hooks/useTwoFactorAuthForm.mjs.map +1 -1
  27. package/dist/components/account/sections/ChangeEmailModal.mjs +25 -28
  28. package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
  29. package/dist/components/account/sections/ChangePasswordSection.mjs +8 -6
  30. package/dist/components/account/sections/ChangePasswordSection.mjs.map +1 -1
  31. package/dist/components/account/sections/ChangePhoneModal.mjs +24 -27
  32. package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
  33. package/dist/components/account/sections/MyProfileSection.mjs +30 -21
  34. package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
  35. package/dist/components/account/sections/PreferencesSection.mjs +41 -23
  36. package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
  37. package/dist/components/account/sections/SecuritySection.mjs +11 -9
  38. package/dist/components/account/sections/SecuritySection.mjs.map +1 -1
  39. package/dist/components/account/sections/TokenSection.mjs +24 -8
  40. package/dist/components/account/sections/TokenSection.mjs.map +1 -1
  41. package/dist/components/embeds/CrispEmbed.mjs +9 -6
  42. package/dist/components/embeds/CrispEmbed.mjs.map +1 -1
  43. package/dist/i18n/config.mjs +13 -0
  44. package/dist/i18n/config.mjs.map +1 -0
  45. package/dist/i18n/country-language.mjs +74 -0
  46. package/dist/i18n/country-language.mjs.map +1 -0
  47. package/dist/i18n/messages/en-us.mjs +211 -0
  48. package/dist/i18n/messages/en-us.mjs.map +1 -0
  49. package/dist/i18n/messages/es-es.mjs +211 -0
  50. package/dist/i18n/messages/es-es.mjs.map +1 -0
  51. package/dist/i18n/messages/index.mjs +16 -0
  52. package/dist/i18n/messages/index.mjs.map +1 -0
  53. package/dist/i18n/messages/pt-br.mjs +216 -0
  54. package/dist/i18n/messages/pt-br.mjs.map +1 -0
  55. package/dist/i18n/normalize.mjs +12 -0
  56. package/dist/i18n/normalize.mjs.map +1 -0
  57. package/dist/i18n/resolve-locale.mjs +42 -0
  58. package/dist/i18n/resolve-locale.mjs.map +1 -0
  59. package/dist/i18n.mjs +14 -0
  60. package/dist/i18n.mjs.map +1 -0
  61. package/dist/providers/auth.provider.mjs +9 -1
  62. package/dist/providers/auth.provider.mjs.map +1 -1
  63. package/dist/server.mjs +2 -0
  64. package/dist/server.mjs.map +1 -1
  65. package/dist/utils/intl/cookie-domain.mjs +17 -0
  66. package/dist/utils/intl/cookie-domain.mjs.map +1 -0
  67. package/dist/utils/intl/locale-cookie.mjs +13 -0
  68. package/dist/utils/intl/locale-cookie.mjs.map +1 -0
  69. package/dist/utils/intl/locales.mjs +3 -2
  70. package/dist/utils/intl/locales.mjs.map +1 -1
  71. package/package.json +7 -1
  72. package/src/components/account/ConfigurationsMyAccountModal.tsx +10 -6
  73. package/src/components/account/ConfirmDeleteAccountModal.tsx +22 -13
  74. package/src/components/account/ConfirmGlobalPreferencesModal.tsx +12 -10
  75. package/src/components/account/DeleteAccountModal.tsx +34 -24
  76. package/src/components/account/DisableTwoFactorAuthModal.tsx +11 -6
  77. package/src/components/account/IsntPossibleDeleteAccountModal.tsx +8 -6
  78. package/src/components/account/TwoFactorAuthModal.tsx +33 -29
  79. package/src/components/account/hooks/useChangeEmailForm.tsx +5 -3
  80. package/src/components/account/hooks/useChangePasswordForm.tsx +20 -6
  81. package/src/components/account/hooks/useChangePhoneForm.tsx +16 -10
  82. package/src/components/account/hooks/useDisableTwoFactorAuthForm.tsx +20 -6
  83. package/src/components/account/hooks/useOtpVerification.tsx +16 -4
  84. package/src/components/account/hooks/useTwoFactorAuthForm.tsx +21 -7
  85. package/src/components/account/sections/ChangeEmailModal.tsx +35 -21
  86. package/src/components/account/sections/ChangePasswordSection.tsx +10 -6
  87. package/src/components/account/sections/ChangePhoneModal.tsx +50 -22
  88. package/src/components/account/sections/MyProfileSection.tsx +30 -22
  89. package/src/components/account/sections/PreferencesSection.tsx +45 -24
  90. package/src/components/account/sections/SecuritySection.tsx +19 -10
  91. package/src/components/account/sections/TokenSection.tsx +22 -10
  92. package/src/components/embeds/CrispEmbed.tsx +12 -8
  93. package/src/i18n/config.ts +17 -0
  94. package/src/i18n/country-language.ts +60 -0
  95. package/src/i18n/messages/en-us.ts +226 -0
  96. package/src/i18n/messages/es-es.ts +227 -0
  97. package/src/i18n/messages/index.ts +24 -0
  98. package/src/i18n/messages/pt-br.ts +236 -0
  99. package/src/i18n/normalize.ts +15 -0
  100. package/src/i18n/resolve-locale.ts +77 -0
  101. package/src/i18n.ts +10 -0
  102. package/src/providers/auth.provider.tsx +13 -1
  103. package/src/server.ts +2 -0
  104. package/src/utils/intl/cookie-domain.ts +29 -0
  105. package/src/utils/intl/locale-cookie.ts +18 -0
  106. package/src/utils/intl/locales.ts +3 -2
@@ -4,6 +4,7 @@ import {
4
4
  createContext,
5
5
  useCallback,
6
6
  useContext,
7
+ useEffect,
7
8
  useMemo
8
9
  } from "react";
9
10
  import { useQueryClient } from "@tanstack/react-query";
@@ -21,8 +22,10 @@ import {
21
22
  useCurrentAccount,
22
23
  ACCOUNT_QUERY_KEY
23
24
  } from "../modules/accounts/hooks/current-account.hook";
24
- import { useWhitelabelUrls } from "./whitelabel.provider";
25
+ import { useWhitelabelUrls, useWhitelabel } from "./whitelabel.provider";
25
26
  import { useWlQueryKey } from "../hooks/useAuthQueryKey";
27
+ import { normalizeLocale } from "../i18n/normalize";
28
+ import { setLocaleCookie } from "../utils/intl/locale-cookie";
26
29
  const AuthContext = createContext(
27
30
  void 0
28
31
  );
@@ -33,7 +36,12 @@ function AuthProvider({ children }) {
33
36
  const queryClient = useQueryClient();
34
37
  const setUserData = useSetUserData();
35
38
  const { accountsUrl, pagesUrl } = useWhitelabelUrls();
39
+ const { whitelabel } = useWhitelabel();
36
40
  const accountKey = useWlQueryKey([...ACCOUNT_QUERY_KEY]);
41
+ useEffect(() => {
42
+ const locale = normalizeLocale(user?.language);
43
+ if (locale) setLocaleCookie(locale, whitelabel?.domain);
44
+ }, [user?.language, whitelabel?.domain]);
37
45
  const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();
38
46
  const { mutateAsync: registerMutate, isPending: isRegistering } = useRegister();
39
47
  const { mutateAsync: logoutMutate, isPending: isLoggingOut } = useLogout();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/auth.provider.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n ReactNode,\n useCallback,\n useContext,\n useMemo,\n} from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport {\n useUserQuery,\n useSetUserData,\n useUserValidateSession,\n} from \"../modules/auth/hooks/useUserQuery\";\nimport { useLogin } from \"../modules/auth/hooks/login.hook\";\nimport { useRegister } from \"../modules/auth/hooks/register.hook\";\nimport { useLogout } from \"../modules/auth/hooks/logout.hook\";\nimport { useSocialGoogleLogin } from \"../modules/auth/hooks/social-google-login.hook\";\nimport { useSocialGoogleOnboarding } from \"../modules/auth/hooks/social-google-onboarding.hook\";\nimport {\n AuthState,\n LoginRequest,\n RegisterRequest,\n SocialGooglePartial,\n SocialOnboardingRequest,\n} from \"../modules/auth/schema\";\n\nexport type LoginResult =\n | { result: \"success\" }\n | { result: \"two_factor_required\"; cookie: string; twoFactorMode: \"verify\" | \"setup\" }\n | { result: \"error\"; message: string };\n\nexport type GoogleLoginResult =\n | { result: \"success\" }\n | { result: \"two_factor_required\"; cookie: string; twoFactorMode: \"verify\" | \"setup\" }\n | { result: \"needs_onboarding\"; onboardingToken: string; partial: SocialGooglePartial }\n | { result: \"link_requires_password\"; message: string }\n | { result: \"error\"; message: string };\nimport {\n useCurrentAccount,\n ACCOUNT_QUERY_KEY,\n} from \"../modules/accounts/hooks/current-account.hook\";\nimport { useWhitelabelUrls } from \"./whitelabel.provider\";\nimport { useWlQueryKey } from \"../hooks/useAuthQueryKey\";\n\ninterface AuthContextProps extends AuthState {\n login: (credentials: LoginRequest) => Promise<LoginResult>;\n register: (data: RegisterRequest) => Promise<void>;\n logout: () => Promise<void>;\n loginWithGoogle: (code: string) => Promise<GoogleLoginResult>;\n completeGoogleOnboarding: (data: SocialOnboardingRequest) => Promise<void>;\n}\n\nexport const AuthContext = createContext<AuthContextProps | undefined>(\n undefined,\n);\n\ninterface AuthProviderProps {\n children: ReactNode;\n}\n\nexport function AuthProvider({ children }: AuthProviderProps) {\n const { data: user, isLoading: isQueryLoading } = useUserQuery();\n const { data: account, isLoading: isAccountLoading } = useCurrentAccount();\n const { isLoading: isSessionLoading } = useUserValidateSession();\n\n const queryClient = useQueryClient();\n const setUserData = useSetUserData();\n const { accountsUrl, pagesUrl } = useWhitelabelUrls();\n const accountKey = useWlQueryKey([...ACCOUNT_QUERY_KEY]);\n\n const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();\n const { mutateAsync: registerMutate, isPending: isRegistering } =\n useRegister();\n const { mutateAsync: logoutMutate, isPending: isLoggingOut } = useLogout();\n const { mutateAsync: googleLoginMutate, isPending: isGoogleLogging } =\n useSocialGoogleLogin();\n const { mutateAsync: googleOnboardingMutate, isPending: isGoogleOnboarding } =\n useSocialGoogleOnboarding();\n\n const isAuthenticated = !!user;\n const isLoading =\n isLogging ||\n isRegistering ||\n isLoggingOut ||\n isGoogleLogging ||\n isGoogleOnboarding ||\n isQueryLoading ||\n isAccountLoading ||\n isSessionLoading;\n\n const login = useCallback(\n async (credentials: LoginRequest): Promise<LoginResult> => {\n try {\n const data = await loginMutate(credentials);\n\n if (data.result === \"two_factor_required\") {\n return { result: \"two_factor_required\", cookie: data.cookie, twoFactorMode: data.twoFactorMode };\n }\n\n queryClient.clear();\n setUserData(data.user);\n queryClient.setQueryData(accountKey, data.account);\n\n return { result: \"success\" };\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Ocorreu um erro ao fazer login. Tente novamente.\";\n return { result: \"error\", message };\n }\n },\n [queryClient, setUserData, accountKey],\n );\n\n const register = useCallback(\n async (data: RegisterRequest): Promise<void> => {\n await registerMutate(data, {\n onSuccess: (data) => {\n queryClient.clear();\n setUserData(data.user);\n queryClient.setQueryData(accountKey, data.account);\n },\n });\n },\n [queryClient, setUserData, accountKey],\n );\n\n const loginWithGoogle = useCallback(\n async (code: string): Promise<GoogleLoginResult> => {\n try {\n const data = await googleLoginMutate(code);\n\n if (data.result === \"two_factor_required\") {\n return {\n result: \"two_factor_required\",\n cookie: data.cookie,\n twoFactorMode: data.twoFactorMode,\n };\n }\n\n if (data.result === \"needs_onboarding\") {\n return {\n result: \"needs_onboarding\",\n onboardingToken: data.onboardingToken,\n partial: data.partial,\n };\n }\n\n if (data.result === \"link_requires_password\") {\n return { result: \"link_requires_password\", message: data.message };\n }\n\n queryClient.clear();\n setUserData(data.user);\n queryClient.setQueryData(accountKey, data.account);\n\n return { result: \"success\" };\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Ocorreu um erro ao fazer login com Google. Tente novamente.\";\n return { result: \"error\", message };\n }\n },\n [googleLoginMutate, queryClient, setUserData, accountKey],\n );\n\n const completeGoogleOnboarding = useCallback(\n async (data: SocialOnboardingRequest): Promise<void> => {\n await googleOnboardingMutate(data, {\n onSuccess: (data) => {\n queryClient.clear();\n setUserData(data.user);\n queryClient.setQueryData(accountKey, data.account);\n },\n });\n },\n [googleOnboardingMutate, queryClient, setUserData, accountKey],\n );\n\n const resolveLogoutRedirect = useCallback(() => {\n try {\n const currentOrigin = window.location.origin;\n const pagesOrigin = pagesUrl ? new URL(pagesUrl).origin : \"\";\n\n if (pagesOrigin && currentOrigin === pagesOrigin) {\n return `${accountsUrl}/login?redirect=${encodeURIComponent(pagesUrl)}`;\n }\n } catch {\n // fallback below\n }\n\n return `${accountsUrl}/login?redirect=${encodeURIComponent(pagesUrl || \"/\")}`;\n }, [accountsUrl, pagesUrl]);\n\n const logout = useCallback(async (): Promise<void> => {\n try {\n await logoutMutate(undefined);\n } catch {\n // cookie já removido no servidor mesmo se a API falhou\n } finally {\n queryClient.clear();\n window.location.assign(resolveLogoutRedirect());\n }\n }, [queryClient, logoutMutate, resolveLogoutRedirect]);\n\n const value: AuthContextProps = useMemo(\n () => ({\n user: user ?? null,\n account: account ?? null,\n isAuthenticated,\n isLoading,\n login,\n register,\n logout,\n loginWithGoogle,\n completeGoogleOnboarding,\n }),\n [\n user,\n account,\n isAuthenticated,\n isLoading,\n login,\n register,\n logout,\n loginWithGoogle,\n completeGoogleOnboarding,\n ],\n );\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\nexport function useAuth(): AuthContextProps {\n const context = useContext(AuthContext);\n\n if (context === undefined) {\n throw new Error(\"useAuth deve ser usado dentro de um AuthProvider\");\n }\n\n return context;\n}\n"],"mappings":"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","names":["data"]}
1
+ {"version":3,"sources":["../../src/providers/auth.provider.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n ReactNode,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n} from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport {\n useUserQuery,\n useSetUserData,\n useUserValidateSession,\n} from \"../modules/auth/hooks/useUserQuery\";\nimport { useLogin } from \"../modules/auth/hooks/login.hook\";\nimport { useRegister } from \"../modules/auth/hooks/register.hook\";\nimport { useLogout } from \"../modules/auth/hooks/logout.hook\";\nimport { useSocialGoogleLogin } from \"../modules/auth/hooks/social-google-login.hook\";\nimport { useSocialGoogleOnboarding } from \"../modules/auth/hooks/social-google-onboarding.hook\";\nimport {\n AuthState,\n LoginRequest,\n RegisterRequest,\n SocialGooglePartial,\n SocialOnboardingRequest,\n} from \"../modules/auth/schema\";\n\nexport type LoginResult =\n | { result: \"success\" }\n | { result: \"two_factor_required\"; cookie: string; twoFactorMode: \"verify\" | \"setup\" }\n | { result: \"error\"; message: string };\n\nexport type GoogleLoginResult =\n | { result: \"success\" }\n | { result: \"two_factor_required\"; cookie: string; twoFactorMode: \"verify\" | \"setup\" }\n | { result: \"needs_onboarding\"; onboardingToken: string; partial: SocialGooglePartial }\n | { result: \"link_requires_password\"; message: string }\n | { result: \"error\"; message: string };\nimport {\n useCurrentAccount,\n ACCOUNT_QUERY_KEY,\n} from \"../modules/accounts/hooks/current-account.hook\";\nimport { useWhitelabelUrls, useWhitelabel } from \"./whitelabel.provider\";\nimport { useWlQueryKey } from \"../hooks/useAuthQueryKey\";\nimport { normalizeLocale } from \"../i18n/normalize\";\nimport { setLocaleCookie } from \"../utils/intl/locale-cookie\";\n\ninterface AuthContextProps extends AuthState {\n login: (credentials: LoginRequest) => Promise<LoginResult>;\n register: (data: RegisterRequest) => Promise<void>;\n logout: () => Promise<void>;\n loginWithGoogle: (code: string) => Promise<GoogleLoginResult>;\n completeGoogleOnboarding: (data: SocialOnboardingRequest) => Promise<void>;\n}\n\nexport const AuthContext = createContext<AuthContextProps | undefined>(\n undefined,\n);\n\ninterface AuthProviderProps {\n children: ReactNode;\n}\n\nexport function AuthProvider({ children }: AuthProviderProps) {\n const { data: user, isLoading: isQueryLoading } = useUserQuery();\n const { data: account, isLoading: isAccountLoading } = useCurrentAccount();\n const { isLoading: isSessionLoading } = useUserValidateSession();\n\n const queryClient = useQueryClient();\n const setUserData = useSetUserData();\n const { accountsUrl, pagesUrl } = useWhitelabelUrls();\n const { whitelabel } = useWhitelabel();\n const accountKey = useWlQueryKey([...ACCOUNT_QUERY_KEY]);\n\n // Mantém o cookie NEXT_LOCALE alinhado à preferência da conta (login, sessão existente,\n // atualização). Compartilhado entre subdomínios via domínio do whitelabel. A próxima\n // navegação/requisição passa a resolver o locale pela preferência do usuário.\n useEffect(() => {\n const locale = normalizeLocale(user?.language);\n if (locale) setLocaleCookie(locale, whitelabel?.domain);\n }, [user?.language, whitelabel?.domain]);\n\n const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();\n const { mutateAsync: registerMutate, isPending: isRegistering } =\n useRegister();\n const { mutateAsync: logoutMutate, isPending: isLoggingOut } = useLogout();\n const { mutateAsync: googleLoginMutate, isPending: isGoogleLogging } =\n useSocialGoogleLogin();\n const { mutateAsync: googleOnboardingMutate, isPending: isGoogleOnboarding } =\n useSocialGoogleOnboarding();\n\n const isAuthenticated = !!user;\n const isLoading =\n isLogging ||\n isRegistering ||\n isLoggingOut ||\n isGoogleLogging ||\n isGoogleOnboarding ||\n isQueryLoading ||\n isAccountLoading ||\n isSessionLoading;\n\n const login = useCallback(\n async (credentials: LoginRequest): Promise<LoginResult> => {\n try {\n const data = await loginMutate(credentials);\n\n if (data.result === \"two_factor_required\") {\n return { result: \"two_factor_required\", cookie: data.cookie, twoFactorMode: data.twoFactorMode };\n }\n\n queryClient.clear();\n setUserData(data.user);\n queryClient.setQueryData(accountKey, data.account);\n\n return { result: \"success\" };\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Ocorreu um erro ao fazer login. Tente novamente.\";\n return { result: \"error\", message };\n }\n },\n [queryClient, setUserData, accountKey],\n );\n\n const register = useCallback(\n async (data: RegisterRequest): Promise<void> => {\n await registerMutate(data, {\n onSuccess: (data) => {\n queryClient.clear();\n setUserData(data.user);\n queryClient.setQueryData(accountKey, data.account);\n },\n });\n },\n [queryClient, setUserData, accountKey],\n );\n\n const loginWithGoogle = useCallback(\n async (code: string): Promise<GoogleLoginResult> => {\n try {\n const data = await googleLoginMutate(code);\n\n if (data.result === \"two_factor_required\") {\n return {\n result: \"two_factor_required\",\n cookie: data.cookie,\n twoFactorMode: data.twoFactorMode,\n };\n }\n\n if (data.result === \"needs_onboarding\") {\n return {\n result: \"needs_onboarding\",\n onboardingToken: data.onboardingToken,\n partial: data.partial,\n };\n }\n\n if (data.result === \"link_requires_password\") {\n return { result: \"link_requires_password\", message: data.message };\n }\n\n queryClient.clear();\n setUserData(data.user);\n queryClient.setQueryData(accountKey, data.account);\n\n return { result: \"success\" };\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Ocorreu um erro ao fazer login com Google. Tente novamente.\";\n return { result: \"error\", message };\n }\n },\n [googleLoginMutate, queryClient, setUserData, accountKey],\n );\n\n const completeGoogleOnboarding = useCallback(\n async (data: SocialOnboardingRequest): Promise<void> => {\n await googleOnboardingMutate(data, {\n onSuccess: (data) => {\n queryClient.clear();\n setUserData(data.user);\n queryClient.setQueryData(accountKey, data.account);\n },\n });\n },\n [googleOnboardingMutate, queryClient, setUserData, accountKey],\n );\n\n const resolveLogoutRedirect = useCallback(() => {\n try {\n const currentOrigin = window.location.origin;\n const pagesOrigin = pagesUrl ? new URL(pagesUrl).origin : \"\";\n\n if (pagesOrigin && currentOrigin === pagesOrigin) {\n return `${accountsUrl}/login?redirect=${encodeURIComponent(pagesUrl)}`;\n }\n } catch {\n // fallback below\n }\n\n return `${accountsUrl}/login?redirect=${encodeURIComponent(pagesUrl || \"/\")}`;\n }, [accountsUrl, pagesUrl]);\n\n const logout = useCallback(async (): Promise<void> => {\n try {\n await logoutMutate(undefined);\n } catch {\n // cookie já removido no servidor mesmo se a API falhou\n } finally {\n queryClient.clear();\n window.location.assign(resolveLogoutRedirect());\n }\n }, [queryClient, logoutMutate, resolveLogoutRedirect]);\n\n const value: AuthContextProps = useMemo(\n () => ({\n user: user ?? null,\n account: account ?? null,\n isAuthenticated,\n isLoading,\n login,\n register,\n logout,\n loginWithGoogle,\n completeGoogleOnboarding,\n }),\n [\n user,\n account,\n isAuthenticated,\n isLoading,\n login,\n register,\n logout,\n loginWithGoogle,\n completeGoogleOnboarding,\n ],\n );\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\nexport function useAuth(): AuthContextProps {\n const context = useContext(AuthContext);\n\n if (context === undefined) {\n throw new Error(\"useAuth deve ser usado dentro de um AuthProvider\");\n }\n\n return context;\n}\n"],"mappings":"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","names":["data"]}
package/dist/server.mjs CHANGED
@@ -60,6 +60,7 @@ import {
60
60
  } from "./modules/accounts/actions/account-management.action";
61
61
  import { getClientInfoFromRequest } from "./infra/utils/client-info";
62
62
  import { getUserContext } from "./modules/auth/utils/get-user-context";
63
+ import { resolveLocale } from "./i18n/resolve-locale";
63
64
  import { requireValidSession } from "./modules/auth/utils/require-valid-session";
64
65
  import { requireTokenNotExpired } from "./modules/auth/utils/require-token-not-expired";
65
66
  import { buildWlOverride, buildWlOverrideFromJwt } from "./modules/auth/utils/build-wl-override";
@@ -120,6 +121,7 @@ export {
120
121
  requestPhoneChangeAction,
121
122
  requireTokenNotExpired,
122
123
  requireValidSession,
124
+ resolveLocale,
123
125
  resolvePlanExtrasPrices,
124
126
  revalidateWhitelabelAction,
125
127
  safeMutationAction,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts"],"sourcesContent":["import 'server-only';\r\n\r\n// API Client\r\nexport { ApiClient, api, apiClient } from './infra/api/client';\r\n\r\n// Services\r\nexport { authService } from './modules/auth/services/auth.service';\r\nexport { whitelabelService } from './modules/whitelabel/services/whitelabel.service';\r\nexport { revalidateWhitelabelAction } from './modules/whitelabel/actions/revalidate-whitelabel.action';\r\nexport { assertManagementPermission } from './modules/auth/utils/assert-management-permission';\r\nexport { assertManagementSubscription } from './modules/auth/utils/assert-management-subscription';\r\nexport { assertSubscriptionAddon } from './modules/auth/utils/assert-subscription-addon';\r\nexport { assertPaidSubscription } from './modules/auth/utils/assert-paid-subscription';\r\nexport { subscriptionsService } from './modules/subscriptions/services/subscriptions.service';\r\nexport { plansService } from './modules/plans/services/plans.service';\r\nexport { cardsService } from './modules/cards/services/cards.service';\r\nexport { chargesService } from './modules/charges/services/charges.service';\r\nexport { iaCreditsService } from './modules/ia-credits/services/ia-credits.service';\r\n\r\n// Actions\r\nexport { findWhitelabel } from './modules/whitelabel/actions/find-whitelabel.action';\r\nexport { validateSessionAction } from './modules/auth/actions/validate-session.action';\r\nexport { socialGoogleLoginAction } from './modules/auth/actions/social-google-login.action';\r\nexport { socialGoogleOnboardingAction } from './modules/auth/actions/social-google-onboarding.action';\r\nexport { unlinkGoogleAction } from './modules/auth/actions/unlink-google.action';\r\nexport { findUserById } from './modules/users/action/find-user-by-id.action';\r\nexport { findCurrentAccount } from './modules/accounts/actions/find-current-account.action';\r\nexport { getAccountTokenAction } from './modules/accounts/actions/get-account-token.action';\r\nexport { listSubscriptionsAction } from './modules/subscriptions/actions/list-subscriptions.action';\r\nexport { calculateSubscriptionAction } from './modules/subscriptions/actions/calculate-subscription.action';\r\nexport { updateSubscriptionPlanAction } from './modules/subscriptions/actions/update-subscription-plan.action';\r\nexport { updateSubscriptionPaymentAction } from './modules/subscriptions/actions/update-subscription-payment.action';\r\nexport { createCardAction } from './modules/cards/actions/create-card.action';\r\nexport { createSetupIntentAction } from './modules/cards/actions/create-setup-intent.action';\r\nexport { chargeActionAction } from './modules/charges/actions/charge-action.action';\r\nexport { resolvePlanExtrasPrices } from './modules/subscriptions/utils/resolve-plan-extras-prices';\r\nexport { hasSubscriptionExpired } from './modules/subscriptions/utils/has-subscription-expired';\r\n\r\n// Project Services & Actions (server-only)\r\nexport { projectsService } from './modules/projects/services/projects.service';\r\nexport { listProjectsAction } from './modules/projects/actions/list-projects.action';\r\nexport { findProjectAction } from './modules/projects/actions/find-project.action';\r\nexport { createProjectAction } from './modules/projects/actions/create-project.action';\r\nexport { updateProjectAction } from './modules/projects/actions/update-project.action';\r\nexport { deleteProjectAction } from './modules/projects/actions/delete-project.action';\r\n\r\n// Project Users Services & Actions (server-only)\r\nexport { projectUsersService } from './modules/projects/services/project-users.service';\r\nexport { listProjectUsersAction } from './modules/projects/actions/list-project-users.action';\r\nexport { addProjectUserAction } from './modules/projects/actions/add-project-user.action';\r\nexport { removeProjectUserAction } from './modules/projects/actions/remove-project-user.action';\r\n\r\n// Account Services & Actions (server-only)\r\nexport { accountService } from './modules/accounts/services/account.service';\r\nexport { twoFactorService } from './modules/accounts/services/two-factor.service';\r\nexport {\r\n listAccountUsersAction,\r\n updateUserAction,\r\n updateAccountAction,\r\n updateAccountUserByIdAction,\r\n deleteAccountUserAction,\r\n deleteAccountAction,\r\n createAccountUserAction,\r\n changePasswordAction,\r\n requestEmailChangeAction,\r\n confirmEmailChangeAction,\r\n requestPhoneChangeAction,\r\n confirmPhoneChangeAction,\r\n generateTwoFactorAction,\r\n confirmTwoFactorAction,\r\n disableTwoFactorAction,\r\n} from './modules/accounts/actions/account-management.action';\r\n\r\n// Server Utils\r\nexport { getClientInfoFromRequest } from './infra/utils/client-info';\r\nexport { getUserContext } from './modules/auth/utils/get-user-context';\r\nexport { requireValidSession } from './modules/auth/utils/require-valid-session';\r\nexport { requireTokenNotExpired } from './modules/auth/utils/require-token-not-expired';\r\nexport { buildWlOverride, buildWlOverrideFromJwt } from './modules/auth/utils/build-wl-override';\r\nexport { safeServerAction } from './utils/safeServerAction';\r\nexport { safeMutationAction } from './utils/safeMutationAction';\r\n\r\n// Image Processing (server-side)\r\nexport { processImageAction } from './modules/images/actions/process-image.action';\r\nexport { processImage } from './modules/images/services/image-processing.service';\r\nexport type {\r\n ProcessImageInput,\r\n ProcessImageOutput,\r\n ProcessImageActionInput,\r\n ProcessImageActionOutput,\r\n} from './modules/images/types/image.type';\r\n"],"mappings":"AAAA,OAAO;AAGP,SAAS,WAAW,KAAK,iBAAiB;AAG1C,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,kCAAkC;AAC3C,SAAS,kCAAkC;AAC3C,SAAS,oCAAoC;AAC7C,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AAGjC,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,oCAAoC;AAC7C,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,mCAAmC;AAC5C,SAAS,oCAAoC;AAC7C,SAAS,uCAAuC;AAChD,SAAS,wBAAwB;AACjC,SAAS,+BAA+B;AACxC,SAAS,0BAA0B;AACnC,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AAGvC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AAGpC,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AACvC,SAAS,4BAA4B;AACrC,SAAS,+BAA+B;AAGxC,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,gCAAgC;AACzC,SAAS,sBAAsB;AAC/B,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AACvC,SAAS,iBAAiB,8BAA8B;AACxD,SAAS,wBAAwB;AACjC,SAAS,0BAA0B;AAGnC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;","names":[]}
1
+ {"version":3,"sources":["../src/server.ts"],"sourcesContent":["import 'server-only';\r\n\r\n// API Client\r\nexport { ApiClient, api, apiClient } from './infra/api/client';\r\n\r\n// Services\r\nexport { authService } from './modules/auth/services/auth.service';\r\nexport { whitelabelService } from './modules/whitelabel/services/whitelabel.service';\r\nexport { revalidateWhitelabelAction } from './modules/whitelabel/actions/revalidate-whitelabel.action';\r\nexport { assertManagementPermission } from './modules/auth/utils/assert-management-permission';\r\nexport { assertManagementSubscription } from './modules/auth/utils/assert-management-subscription';\r\nexport { assertSubscriptionAddon } from './modules/auth/utils/assert-subscription-addon';\r\nexport { assertPaidSubscription } from './modules/auth/utils/assert-paid-subscription';\r\nexport { subscriptionsService } from './modules/subscriptions/services/subscriptions.service';\r\nexport { plansService } from './modules/plans/services/plans.service';\r\nexport { cardsService } from './modules/cards/services/cards.service';\r\nexport { chargesService } from './modules/charges/services/charges.service';\r\nexport { iaCreditsService } from './modules/ia-credits/services/ia-credits.service';\r\n\r\n// Actions\r\nexport { findWhitelabel } from './modules/whitelabel/actions/find-whitelabel.action';\r\nexport { validateSessionAction } from './modules/auth/actions/validate-session.action';\r\nexport { socialGoogleLoginAction } from './modules/auth/actions/social-google-login.action';\r\nexport { socialGoogleOnboardingAction } from './modules/auth/actions/social-google-onboarding.action';\r\nexport { unlinkGoogleAction } from './modules/auth/actions/unlink-google.action';\r\nexport { findUserById } from './modules/users/action/find-user-by-id.action';\r\nexport { findCurrentAccount } from './modules/accounts/actions/find-current-account.action';\r\nexport { getAccountTokenAction } from './modules/accounts/actions/get-account-token.action';\r\nexport { listSubscriptionsAction } from './modules/subscriptions/actions/list-subscriptions.action';\r\nexport { calculateSubscriptionAction } from './modules/subscriptions/actions/calculate-subscription.action';\r\nexport { updateSubscriptionPlanAction } from './modules/subscriptions/actions/update-subscription-plan.action';\r\nexport { updateSubscriptionPaymentAction } from './modules/subscriptions/actions/update-subscription-payment.action';\r\nexport { createCardAction } from './modules/cards/actions/create-card.action';\r\nexport { createSetupIntentAction } from './modules/cards/actions/create-setup-intent.action';\r\nexport { chargeActionAction } from './modules/charges/actions/charge-action.action';\r\nexport { resolvePlanExtrasPrices } from './modules/subscriptions/utils/resolve-plan-extras-prices';\r\nexport { hasSubscriptionExpired } from './modules/subscriptions/utils/has-subscription-expired';\r\n\r\n// Project Services & Actions (server-only)\r\nexport { projectsService } from './modules/projects/services/projects.service';\r\nexport { listProjectsAction } from './modules/projects/actions/list-projects.action';\r\nexport { findProjectAction } from './modules/projects/actions/find-project.action';\r\nexport { createProjectAction } from './modules/projects/actions/create-project.action';\r\nexport { updateProjectAction } from './modules/projects/actions/update-project.action';\r\nexport { deleteProjectAction } from './modules/projects/actions/delete-project.action';\r\n\r\n// Project Users Services & Actions (server-only)\r\nexport { projectUsersService } from './modules/projects/services/project-users.service';\r\nexport { listProjectUsersAction } from './modules/projects/actions/list-project-users.action';\r\nexport { addProjectUserAction } from './modules/projects/actions/add-project-user.action';\r\nexport { removeProjectUserAction } from './modules/projects/actions/remove-project-user.action';\r\n\r\n// Account Services & Actions (server-only)\r\nexport { accountService } from './modules/accounts/services/account.service';\r\nexport { twoFactorService } from './modules/accounts/services/two-factor.service';\r\nexport {\r\n listAccountUsersAction,\r\n updateUserAction,\r\n updateAccountAction,\r\n updateAccountUserByIdAction,\r\n deleteAccountUserAction,\r\n deleteAccountAction,\r\n createAccountUserAction,\r\n changePasswordAction,\r\n requestEmailChangeAction,\r\n confirmEmailChangeAction,\r\n requestPhoneChangeAction,\r\n confirmPhoneChangeAction,\r\n generateTwoFactorAction,\r\n confirmTwoFactorAction,\r\n disableTwoFactorAction,\r\n} from './modules/accounts/actions/account-management.action';\r\n\r\n// Server Utils\r\nexport { getClientInfoFromRequest } from './infra/utils/client-info';\r\nexport { getUserContext } from './modules/auth/utils/get-user-context';\r\nexport { resolveLocale } from './i18n/resolve-locale';\r\nexport type { ResolveLocaleOptions } from './i18n/resolve-locale';\r\nexport { requireValidSession } from './modules/auth/utils/require-valid-session';\r\nexport { requireTokenNotExpired } from './modules/auth/utils/require-token-not-expired';\r\nexport { buildWlOverride, buildWlOverrideFromJwt } from './modules/auth/utils/build-wl-override';\r\nexport { safeServerAction } from './utils/safeServerAction';\r\nexport { safeMutationAction } from './utils/safeMutationAction';\r\n\r\n// Image Processing (server-side)\r\nexport { processImageAction } from './modules/images/actions/process-image.action';\r\nexport { processImage } from './modules/images/services/image-processing.service';\r\nexport type {\r\n ProcessImageInput,\r\n ProcessImageOutput,\r\n ProcessImageActionInput,\r\n ProcessImageActionOutput,\r\n} from './modules/images/types/image.type';\r\n"],"mappings":"AAAA,OAAO;AAGP,SAAS,WAAW,KAAK,iBAAiB;AAG1C,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,kCAAkC;AAC3C,SAAS,kCAAkC;AAC3C,SAAS,oCAAoC;AAC7C,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AAGjC,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,oCAAoC;AAC7C,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,mCAAmC;AAC5C,SAAS,oCAAoC;AAC7C,SAAS,uCAAuC;AAChD,SAAS,wBAAwB;AACjC,SAAS,+BAA+B;AACxC,SAAS,0BAA0B;AACnC,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AAGvC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AAGpC,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AACvC,SAAS,4BAA4B;AACrC,SAAS,+BAA+B;AAGxC,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,gCAAgC;AACzC,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAE9B,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AACvC,SAAS,iBAAiB,8BAA8B;AACxD,SAAS,wBAAwB;AACjC,SAAS,0BAA0B;AAGnC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;","names":[]}
@@ -0,0 +1,17 @@
1
+ function cookieDomainFromDomain(domain) {
2
+ if (!domain) return void 0;
3
+ const normalized = domain.trim();
4
+ if (!normalized) return void 0;
5
+ let rawHost;
6
+ try {
7
+ rawHost = new URL(normalized).hostname;
8
+ } catch {
9
+ rawHost = normalized.replace(/^https?:\/\//i, "").replace(/^www\./i, "").split("/")[0].split(":")[0];
10
+ }
11
+ if (!rawHost || rawHost === "localhost") return void 0;
12
+ return rawHost.startsWith(".") ? rawHost : `.${rawHost}`;
13
+ }
14
+ export {
15
+ cookieDomainFromDomain
16
+ };
17
+ //# sourceMappingURL=cookie-domain.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/intl/cookie-domain.ts"],"sourcesContent":["/**\n * Deriva o domínio de cookie compartilhável entre subdomínios a partir do domínio do\n * whitelabel (ex.: `https://app.greatpages.com.br` → `.app.greatpages.com.br`).\n *\n * Mesma normalização usada pelo cookie de auth `greatapps` (auth.service.normalizeCookieDomain),\n * para que o cookie de locale acompanhe o mesmo escopo. Pura (sem APIs de servidor) → client+server.\n * Retorna `undefined` para localhost/host inválido (cookie fica host-scoped).\n */\nexport function cookieDomainFromDomain(domain?: string | null): string | undefined {\n if (!domain) return undefined;\n\n const normalized = domain.trim();\n if (!normalized) return undefined;\n\n let rawHost: string;\n try {\n rawHost = new URL(normalized).hostname;\n } catch {\n rawHost = normalized\n .replace(/^https?:\\/\\//i, '')\n .replace(/^www\\./i, '')\n .split('/')[0]\n .split(':')[0];\n }\n\n if (!rawHost || rawHost === 'localhost') return undefined;\n\n return rawHost.startsWith('.') ? rawHost : `.${rawHost}`;\n}\n"],"mappings":"AAQO,SAAS,uBAAuB,QAA4C;AACjF,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,aAAa,OAAO,KAAK;AAC/B,MAAI,CAAC,WAAY,QAAO;AAExB,MAAI;AACJ,MAAI;AACF,cAAU,IAAI,IAAI,UAAU,EAAE;AAAA,EAChC,QAAQ;AACN,cAAU,WACP,QAAQ,iBAAiB,EAAE,EAC3B,QAAQ,WAAW,EAAE,EACrB,MAAM,GAAG,EAAE,CAAC,EACZ,MAAM,GAAG,EAAE,CAAC;AAAA,EACjB;AAEA,MAAI,CAAC,WAAW,YAAY,YAAa,QAAO;AAEhD,SAAO,QAAQ,WAAW,GAAG,IAAI,UAAU,IAAI,OAAO;AACxD;","names":[]}
@@ -0,0 +1,13 @@
1
+ import { LOCALE_COOKIE } from "../../i18n/config";
2
+ import { cookieDomainFromDomain } from "./cookie-domain";
3
+ const ONE_YEAR = 60 * 60 * 24 * 365;
4
+ function setLocaleCookie(locale, whitelabelDomain) {
5
+ if (typeof document === "undefined") return;
6
+ const domain = cookieDomainFromDomain(whitelabelDomain);
7
+ const domainAttr = domain ? `; domain=${domain}` : "";
8
+ document.cookie = `${LOCALE_COOKIE}=${locale}; path=/; max-age=${ONE_YEAR}; samesite=lax${domainAttr}`;
9
+ }
10
+ export {
11
+ setLocaleCookie
12
+ };
13
+ //# sourceMappingURL=locale-cookie.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/intl/locale-cookie.ts"],"sourcesContent":["import { LOCALE_COOKIE } from '../../i18n/config';\nimport { cookieDomainFromDomain } from './cookie-domain';\n\nconst ONE_YEAR = 60 * 60 * 24 * 365;\n\n/**\n * Persiste o locale escolhido no cookie `NEXT_LOCALE` (lido por `resolveLocale` no servidor).\n *\n * Passe `whitelabelDomain` (de `useWhitelabel().whitelabel?.domain`) para o cookie ser\n * compartilhado entre subdomínios (accounts. → pages. → apps.), no mesmo escopo do cookie\n * de auth. Sem ele, o cookie fica host-scoped.\n */\nexport function setLocaleCookie(locale: string, whitelabelDomain?: string | null): void {\n if (typeof document === 'undefined') return;\n const domain = cookieDomainFromDomain(whitelabelDomain);\n const domainAttr = domain ? `; domain=${domain}` : '';\n document.cookie = `${LOCALE_COOKIE}=${locale}; path=/; max-age=${ONE_YEAR}; samesite=lax${domainAttr}`;\n}\n"],"mappings":"AAAA,SAAS,qBAAqB;AAC9B,SAAS,8BAA8B;AAEvC,MAAM,WAAW,KAAK,KAAK,KAAK;AASzB,SAAS,gBAAgB,QAAgB,kBAAwC;AACtF,MAAI,OAAO,aAAa,YAAa;AACrC,QAAM,SAAS,uBAAuB,gBAAgB;AACtD,QAAM,aAAa,SAAS,YAAY,MAAM,KAAK;AACnD,WAAS,SAAS,GAAG,aAAa,IAAI,MAAM,qBAAqB,QAAQ,iBAAiB,UAAU;AACtG;","names":[]}
@@ -1,6 +1,7 @@
1
1
  const LANGUAGE_OPTIONS = [
2
- { value: "pt-BR", label: "Portugu\xEAs (Brasil)", displayValue: "Portugu\xEAs (Brasil)", apiValue: "pt-br" },
3
- { value: "en-US", label: "Ingl\xEAs (EUA)", displayValue: "Ingl\xEAs (EUA)", apiValue: "en" }
2
+ { value: "pt-br", label: "Portugu\xEAs (Brasil)", displayValue: "Portugu\xEAs (Brasil)", apiValue: "pt-br" },
3
+ { value: "en-us", label: "Ingl\xEAs (EUA)", displayValue: "Ingl\xEAs (EUA)", apiValue: "en" },
4
+ { value: "es-es", label: "Espanhol", displayValue: "Espanhol", apiValue: "es" }
4
5
  ];
5
6
  function buildLocaleOptions() {
6
7
  return LANGUAGE_OPTIONS;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/intl/locales.ts"],"sourcesContent":["export type LocaleOption = {\r\n value: string;\r\n label: string;\r\n displayValue: string;\r\n apiValue: string;\r\n};\r\n\r\nexport const LANGUAGE_OPTIONS: LocaleOption[] = [\r\n { value: 'pt-BR', label: 'Português (Brasil)', displayValue: 'Português (Brasil)', apiValue: 'pt-br' },\r\n { value: 'en-US', label: 'Inglês (EUA)', displayValue: 'Inglês (EUA)', apiValue: 'en' },\r\n];\r\n\r\nexport function buildLocaleOptions(): LocaleOption[] {\r\n return LANGUAGE_OPTIONS;\r\n}\r\n"],"mappings":"AAOO,MAAM,mBAAmC;AAAA,EAC9C,EAAE,OAAO,SAAS,OAAO,yBAAsB,cAAc,yBAAsB,UAAU,QAAQ;AAAA,EACrG,EAAE,OAAO,SAAS,OAAO,mBAAgB,cAAc,mBAAgB,UAAU,KAAK;AACxF;AAEO,SAAS,qBAAqC;AACnD,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/intl/locales.ts"],"sourcesContent":["export type LocaleOption = {\r\n value: string;\r\n label: string;\r\n displayValue: string;\r\n apiValue: string;\r\n};\r\n\r\nexport const LANGUAGE_OPTIONS: LocaleOption[] = [\r\n { value: 'pt-br', label: 'Português (Brasil)', displayValue: 'Português (Brasil)', apiValue: 'pt-br' },\r\n { value: 'en-us', label: 'Inglês (EUA)', displayValue: 'Inglês (EUA)', apiValue: 'en' },\r\n { value: 'es-es', label: 'Espanhol', displayValue: 'Espanhol', apiValue: 'es' },\r\n];\r\n\r\nexport function buildLocaleOptions(): LocaleOption[] {\r\n return LANGUAGE_OPTIONS;\r\n}\r\n"],"mappings":"AAOO,MAAM,mBAAmC;AAAA,EAC9C,EAAE,OAAO,SAAS,OAAO,yBAAsB,cAAc,yBAAsB,UAAU,QAAQ;AAAA,EACrG,EAAE,OAAO,SAAS,OAAO,mBAAgB,cAAc,mBAAgB,UAAU,KAAK;AAAA,EACtF,EAAE,OAAO,SAAS,OAAO,YAAY,cAAc,YAAY,UAAU,KAAK;AAChF;AAEO,SAAS,qBAAqC;AACnD,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.665",
3
+ "version": "1.1.667",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -28,6 +28,10 @@
28
28
  "./handlers": {
29
29
  "import": "./dist/handlers.mjs",
30
30
  "types": "./src/handlers.ts"
31
+ },
32
+ "./i18n": {
33
+ "import": "./dist/i18n.mjs",
34
+ "types": "./src/i18n.ts"
31
35
  }
32
36
  },
33
37
  "files": [
@@ -86,6 +90,7 @@
86
90
  "@types/react-dom": "^19.2.3",
87
91
  "glob": "^13.0.6",
88
92
  "next": "16.2.1",
93
+ "next-intl": "^4.12.0",
89
94
  "react": "19.1.4",
90
95
  "react-dom": "19.1.4",
91
96
  "react-hook-form": "^7.72.0",
@@ -97,6 +102,7 @@
97
102
  "@hookform/resolvers": ">=3.0.0",
98
103
  "@tanstack/react-query": ">=5.0.0",
99
104
  "next": ">=16.0.0",
105
+ "next-intl": ">=4.0.0",
100
106
  "react": ">=19.0.0",
101
107
  "react-dom": ">=19.0.0",
102
108
  "react-hook-form": ">=7.0.0",
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { IconKey, IconLock, IconSettings2, IconX } from '@tabler/icons-react';
4
+ import { useTranslations } from 'next-intl';
4
5
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
5
6
  import { Tabs, TabsList, TabsTrigger, TabsContent } from '../ui/data-display/Tabs';
6
7
  import { cn } from '../../infra/utils/clsx';
@@ -19,6 +20,7 @@ import { hasSubscriptionExpired } from '../../modules/subscriptions/utils/has-su
19
20
  import { useWhitelabel } from '../../providers/whitelabel.provider';
20
21
 
21
22
  export default function ConfigurationsMyAccountModal() {
23
+ const translate = useTranslations();
22
24
  const {
23
25
  activeModal,
24
26
  openDeleteAccount,
@@ -85,10 +87,12 @@ export default function ConfigurationsMyAccountModal() {
85
87
  lg:top-[50%] lg:bottom-auto lg:left-[50%] lg:right-auto lg:translate-x-[-50%] lg:translate-y-[-50%]"
86
88
  >
87
89
  <DialogHeader className="sr-only">
88
- <DialogTitle>Configurações</DialogTitle>
90
+ <DialogTitle>{translate('common.account.configurations.title')}</DialogTitle>
89
91
  </DialogHeader>
90
92
  <div className="md:hidden flex items-center justify-between px-5 py-3 border-b border-gray-200">
91
- <span className="text-gray-950 paragraph-medium-semibold">Configurações</span>
93
+ <span className="text-gray-950 paragraph-medium-semibold">
94
+ {translate('common.account.configurations.title')}
95
+ </span>
92
96
  <button
93
97
  type="button"
94
98
  className="size-8 flex items-center justify-center text-gray-500 cursor-pointer"
@@ -116,26 +120,26 @@ export default function ConfigurationsMyAccountModal() {
116
120
  )}
117
121
  >
118
122
  <span className="hidden lg:block paragraph-medium-semibold text-gray-950 mb-0">
119
- Configurações
123
+ {translate('common.account.configurations.title')}
120
124
  </span>
121
125
 
122
126
  <div className="lg:flex lg:flex-col flex flex-row lg:gap-0 gap-0 lg:w-full">
123
127
  <TabsTrigger value={AccountSectionType.PREFERENCES} className={tabTriggerClasses}>
124
128
  <IconSettings2 size={20} className="shrink-0" />
125
- <span className="paragraph-small-medium">Preferências</span>
129
+ <span className="paragraph-small-medium">{translate('common.preferences.title')}</span>
126
130
  </TabsTrigger>
127
131
 
128
132
  {isOwner && whitelabel?.id === 1 && (
129
133
  <TabsTrigger value={AccountSectionType.TOKEN} className={tabTriggerClasses}>
130
134
  <IconKey size={20} className="shrink-0" />
131
- <span className="paragraph-small-medium">Token da conta</span>
135
+ <span className="paragraph-small-medium">{translate('common.account.token.title')}</span>
132
136
  </TabsTrigger>
133
137
  )}
134
138
 
135
139
  {isOwner && (
136
140
  <TabsTrigger value={AccountSectionType.SECURITY} className={tabTriggerClasses}>
137
141
  <IconLock size={20} className="shrink-0" />
138
- <span className="paragraph-small-medium">Segurança</span>
142
+ <span className="paragraph-small-medium">{translate('common.account.security.title')}</span>
139
143
  </TabsTrigger>
140
144
  )}
141
145
  </div>
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { useTranslations } from 'next-intl';
3
4
  import { IconAlertTriangle } from '@tabler/icons-react';
4
5
  import { toast } from 'sonner';
5
6
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
@@ -15,6 +16,7 @@ import { useAuth } from '../../providers/auth.provider';
15
16
  import { UserProfile } from '../../modules/users/schema';
16
17
 
17
18
  export default function ConfirmDeleteAccountModal() {
19
+ const translate = useTranslations();
18
20
  const { activeModal, deleteAccountPayload, openDeleteAccount, close } = useAccountModals();
19
21
  const open = activeModal === 'confirmDelete';
20
22
 
@@ -33,7 +35,7 @@ export default function ConfirmDeleteAccountModal() {
33
35
  if (!deleteAccountPayload) {
34
36
  // Fluxo quebrado (usuário pulou o primeiro modal ou refresh) — manda
35
37
  // de volta pro modal inicial pra re-coletar a senha.
36
- openDeleteAccount('Sessão expirada. Preencha os campos novamente.');
38
+ openDeleteAccount(translate('common.account.confirmDelete.sessionExpired'));
37
39
  return;
38
40
  }
39
41
  await deleteAccount.mutateAsync({ password: deleteAccountPayload.password });
@@ -41,20 +43,25 @@ export default function ConfirmDeleteAccountModal() {
41
43
  await deleteAccountUser.mutateAsync(user!.id);
42
44
  }
43
45
  close();
44
- toast.custom((t) => (
45
- <Toast variant="success" message="Conta excluída com sucesso" toastId={t} />
46
+ toast.custom((toastId) => (
47
+ <Toast
48
+ variant="success"
49
+ message={translate('common.account.confirmDelete.success')}
50
+ toastId={toastId}
51
+ />
46
52
  ));
47
53
  await logout();
48
54
  } catch (error) {
49
- const message = error instanceof Error ? error.message : 'Erro ao excluir. Tente novamente.';
55
+ const message =
56
+ error instanceof Error ? error.message : translate('common.account.confirmDelete.error');
50
57
  if (isOwner) {
51
58
  // Falha no delete do owner (ex.: senha inválida) — volta pro primeiro
52
59
  // modal com a mensagem do backend pra o usuário corrigir e tentar de novo.
53
60
  openDeleteAccount(message);
54
61
  return;
55
62
  }
56
- toast.custom((t) => (
57
- <Toast variant="error" message={message} toastId={t} />
63
+ toast.custom((toastId) => (
64
+ <Toast variant="error" message={message} toastId={toastId} />
58
65
  ));
59
66
  }
60
67
  };
@@ -65,17 +72,17 @@ export default function ConfirmDeleteAccountModal() {
65
72
  <div className="flex flex-col gap-5 p-4 lg:p-5">
66
73
  <DialogHeader className="p-0">
67
74
  <DialogTitle className="paragraph-medium-semibold text-gray-950">
68
- Uma pena te ver ir!
75
+ {translate('common.account.confirmDelete.title')}
69
76
  </DialogTitle>
70
77
  </DialogHeader>
71
78
 
72
79
  <div className="bg-red-50 p-4 lg:p-5 rounded-lg flex items-center gap-4">
73
80
  <IconAlertTriangle size={20} className="text-red-500 shrink-0" strokeWidth={2} />
74
81
  <p className="paragraph-small-regular text-gray-600">
75
- Todas suas{' '}
76
- <span className="font-semibold text-gray-950">{pagesCount} páginas</span>{' '}
77
- serão deletadas permanentemente. Essa ação é{' '}
78
- <span className="font-semibold text-gray-950">irreversível!</span>
82
+ {translate.rich('common.account.confirmDelete.warning', {
83
+ count: pagesCount,
84
+ b: (chunks) => <span className="font-semibold text-gray-950">{chunks}</span>,
85
+ })}
79
86
  </p>
80
87
  </div>
81
88
  </div>
@@ -84,7 +91,7 @@ export default function ConfirmDeleteAccountModal() {
84
91
 
85
92
  <div className="flex items-center gap-2 p-4 lg:p-5">
86
93
  <Button className="h-10 flex-1" onClick={close} disabled={isDeleting}>
87
- Manter minha conta
94
+ {translate('common.account.confirmDelete.keepAccount')}
88
95
  </Button>
89
96
  <Button
90
97
  variant="secondary"
@@ -92,7 +99,9 @@ export default function ConfirmDeleteAccountModal() {
92
99
  onClick={handleConfirm}
93
100
  disabled={isDeleting}
94
101
  >
95
- {isDeleting ? 'Excluindo...' : 'Excluir mesmo assim'}
102
+ {isDeleting
103
+ ? translate('common.account.confirmDelete.deleting')
104
+ : translate('common.account.confirmDelete.deleteAnyway')}
96
105
  </Button>
97
106
  </div>
98
107
  </DialogContent>
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { useTranslations } from 'next-intl';
3
4
  import { IconAlertTriangle } from '@tabler/icons-react';
4
5
  import { Button } from '../ui/buttons/Button';
5
6
  import {
@@ -22,13 +23,14 @@ export default function ConfirmGlobalPreferencesModal({
22
23
  onConfirm,
23
24
  onCancel,
24
25
  }: ConfirmGlobalPreferencesModalProps) {
26
+ const translate = useTranslations();
25
27
  return (
26
28
  <Dialog open={open} onOpenChange={onCancel}>
27
29
  <DialogContent className="flex flex-col p-0 gap-0 md:w-[386px]! lg:w-[386px]! max-w-[386px]! max-[386px]:w-[calc(100%-32px)]">
28
30
  <DialogHeader className="sr-only">
29
- <DialogTitle>Alterar preferências globais</DialogTitle>
31
+ <DialogTitle>{translate('common.account.globalPreferences.title')}</DialogTitle>
30
32
  <DialogDescription>
31
- Confirmação de alteração de preferências globais da conta
33
+ {translate('common.account.globalPreferences.srDescription')}
32
34
  </DialogDescription>
33
35
  </DialogHeader>
34
36
 
@@ -38,14 +40,14 @@ export default function ConfirmGlobalPreferencesModal({
38
40
  </div>
39
41
  <div className="flex flex-col gap-2">
40
42
  <span className="paragraph-medium-semibold text-gray-950">
41
- Alterar preferências globais
43
+ {translate('common.account.globalPreferences.title')}
42
44
  </span>
43
45
  <span className="paragraph-small-regular text-gray-600">
44
- Você está alterando configurações que impactam{' '}
45
- <span className="paragraph-small-semibold text-gray-950">
46
- todos os usuários da conta
47
- </span>
48
- . Deseja confirmar?
46
+ {translate.rich('common.account.globalPreferences.warning', {
47
+ b: (chunks) => (
48
+ <span className="paragraph-small-semibold text-gray-950">{chunks}</span>
49
+ ),
50
+ })}
49
51
  </span>
50
52
  </div>
51
53
  </div>
@@ -54,10 +56,10 @@ export default function ConfirmGlobalPreferencesModal({
54
56
 
55
57
  <div className="flex items-center gap-2 p-5">
56
58
  <Button onClick={onConfirm} className="h-10!">
57
- Confirmar
59
+ {translate('common.actions.confirm')}
58
60
  </Button>
59
61
  <Button variant="secondary" onClick={onCancel} className="h-10!">
60
- Cancelar
62
+ {translate('common.actions.cancel')}
61
63
  </Button>
62
64
  </div>
63
65
  </DialogContent>
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useState, useCallback, useEffect } from 'react';
4
+ import { useTranslations } from 'next-intl';
4
5
  import { IconLock, IconAlertTriangle } from '@tabler/icons-react';
5
6
  import { toast } from 'sonner';
6
7
  import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
@@ -13,16 +14,16 @@ import usePasswordVisibility from '../../hooks/usePasswordVisibility';
13
14
  import { useAccountModals } from '../../store/useAccountModals';
14
15
  import { AccountSectionType } from '../../enums/AccountSectionType';
15
16
 
16
- const REASON_OPTIONS = [
17
- { value: 'sem-funcao', label: 'A ferramenta não possui uma função que eu preciso' },
18
- { value: 'problemas', label: 'Encontrei problemas técnicos ou erros no sistema' },
19
- { value: 'suporte', label: 'Tive problemas com o suporte ou atendimento' },
20
- { value: 'demora', label: 'As atualizações demoram mais do que o esperado' },
21
- { value: 'temporario', label: 'O cancelamento é temporário' },
22
- { value: 'outro', label: 'Outro motivo' },
23
- ];
24
-
25
17
  export default function DeleteAccountModal() {
18
+ const translate = useTranslations();
19
+ const reasonOptions = [
20
+ { value: 'sem-funcao', label: translate('common.account.deleteAccount.reasons.noFeature') },
21
+ { value: 'problemas', label: translate('common.account.deleteAccount.reasons.technical') },
22
+ { value: 'suporte', label: translate('common.account.deleteAccount.reasons.support') },
23
+ { value: 'demora', label: translate('common.account.deleteAccount.reasons.updates') },
24
+ { value: 'temporario', label: translate('common.account.deleteAccount.reasons.temporary') },
25
+ { value: 'outro', label: translate('common.account.deleteAccount.reasons.other') },
26
+ ];
26
27
  const {
27
28
  activeModal,
28
29
  deleteAccountError,
@@ -61,8 +62,12 @@ export default function DeleteAccountModal() {
61
62
  const handleDelete = (e: React.FormEvent) => {
62
63
  e.preventDefault();
63
64
  if (!isFormValid) {
64
- toast.custom((t) => (
65
- <Toast variant="error" message="Preencha todos os campos obrigatórios" toastId={t} />
65
+ toast.custom((toastId) => (
66
+ <Toast
67
+ variant="error"
68
+ message={translate('common.account.deleteAccount.requiredFields')}
69
+ toastId={toastId}
70
+ />
66
71
  ));
67
72
  return;
68
73
  }
@@ -80,18 +85,21 @@ export default function DeleteAccountModal() {
80
85
  <div className="flex items-center justify-center w-fit bg-red-50 rounded-lg p-2.5 mb-5">
81
86
  <IconAlertTriangle size={20} className="text-red-500" />
82
87
  </div>
83
- <DialogTitle>Excluir conta</DialogTitle>
88
+ <DialogTitle>{translate('common.account.deleteAccount.title')}</DialogTitle>
84
89
  <DialogDescription className="paragraph-small-regular">
85
- Esta ação é <span className="font-semibold text-gray-950">irreversível</span>. Ao
86
- confirmar, sua conta e todos os seus dados serão excluídos.
90
+ {translate.rich('common.account.deleteAccount.description', {
91
+ b: (chunks) => (
92
+ <span className="font-semibold text-gray-950">{chunks}</span>
93
+ ),
94
+ })}
87
95
  </DialogDescription>
88
96
  </DialogHeader>
89
97
 
90
98
  <SelectField
91
- label="Motivo do cancelamento"
99
+ label={translate('common.account.deleteAccount.reasonLabel')}
92
100
  required
93
- placeholder="Selecione"
94
- options={REASON_OPTIONS}
101
+ placeholder={translate('common.account.deleteAccount.reasonPlaceholder')}
102
+ options={reasonOptions}
95
103
  value={reason}
96
104
  onChange={(value) => setReason(value as string)}
97
105
  className="h-10!"
@@ -99,24 +107,26 @@ export default function DeleteAccountModal() {
99
107
 
100
108
  <div>
101
109
  <TextAreaField
102
- label="Descreva o que levou a tomar essa decisão"
110
+ label={translate('common.account.deleteAccount.descriptionLabel')}
103
111
  required
104
- placeholder="Explique sua decisão..."
112
+ placeholder={translate('common.account.deleteAccount.descriptionPlaceholder')}
105
113
  value={description}
106
114
  onChange={(e) => setDescription(e.target.value)}
107
115
  rows={4}
108
116
  maxLength={400}
109
117
  />
110
118
  <span className="paragraph-xsmall-medium text-gray-600 text-left mt-1 block">
111
- {description.length}/400 caracteres
119
+ {translate('common.account.deleteAccount.charactersCount', {
120
+ count: description.length,
121
+ })}
112
122
  </span>
113
123
  </div>
114
124
 
115
125
  <FormField
116
126
  className="text-gray-600"
117
- label="Senha"
127
+ label={translate('common.account.deleteAccount.passwordLabel')}
118
128
  type="password"
119
- placeholder="Informe sua senha"
129
+ placeholder={translate('common.account.deleteAccount.passwordPlaceholder')}
120
130
  leftIcon={IconLock}
121
131
  value={password}
122
132
  onChange={(e) => {
@@ -137,10 +147,10 @@ export default function DeleteAccountModal() {
137
147
  className="h-10"
138
148
  type="submit"
139
149
  >
140
- Excluir conta
150
+ {translate('common.account.deleteAccount.submit')}
141
151
  </Button>
142
152
  <Button variant="secondary" className="h-10" type="button" onClick={handleClose}>
143
- Fechar
153
+ {translate('common.actions.close')}
144
154
  </Button>
145
155
  </div>
146
156
  </form>