@greatapps/common 1.1.779 → 1.1.781

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 (43) hide show
  1. package/dist/components/account/sections/PreferencesSection.mjs +3 -1
  2. package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
  3. package/dist/components/layouts/AppMobileNavBar.mjs +64 -5
  4. package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
  5. package/dist/components/layouts/AppNavBar.mjs +2 -0
  6. package/dist/components/layouts/AppNavBar.mjs.map +1 -1
  7. package/dist/components/layouts/GreatDomainIcon.mjs +40 -0
  8. package/dist/components/layouts/GreatDomainIcon.mjs.map +1 -0
  9. package/dist/components/layouts/NavBar.mjs +109 -52
  10. package/dist/components/layouts/NavBar.mjs.map +1 -1
  11. package/dist/hooks/useDomMutationGuardHit.mjs +36 -0
  12. package/dist/hooks/useDomMutationGuardHit.mjs.map +1 -0
  13. package/dist/i18n/messages/en-us.mjs +3 -1
  14. package/dist/i18n/messages/en-us.mjs.map +1 -1
  15. package/dist/i18n/messages/es-es.mjs +3 -1
  16. package/dist/i18n/messages/es-es.mjs.map +1 -1
  17. package/dist/i18n/messages/pt-br.mjs +3 -1
  18. package/dist/i18n/messages/pt-br.mjs.map +1 -1
  19. package/dist/i18n/resolve-locale.mjs +10 -0
  20. package/dist/i18n/resolve-locale.mjs.map +1 -1
  21. package/dist/index.mjs +4 -0
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/modules/auth/services/auth.service.mjs +12 -6
  24. package/dist/modules/auth/services/auth.service.mjs.map +1 -1
  25. package/dist/utils/dom/dom-mutation-guard.mjs +20 -0
  26. package/dist/utils/dom/dom-mutation-guard.mjs.map +1 -0
  27. package/dist/utils/intl/locales.mjs +6 -1
  28. package/dist/utils/intl/locales.mjs.map +1 -1
  29. package/package.json +7 -8
  30. package/src/components/account/sections/PreferencesSection.tsx +3 -2
  31. package/src/components/layouts/AppMobileNavBar.tsx +90 -6
  32. package/src/components/layouts/AppNavBar.tsx +5 -1
  33. package/src/components/layouts/GreatDomainIcon.tsx +43 -0
  34. package/src/components/layouts/NavBar.tsx +158 -66
  35. package/src/hooks/useDomMutationGuardHit.ts +55 -0
  36. package/src/i18n/messages/en-us.ts +2 -0
  37. package/src/i18n/messages/es-es.ts +2 -0
  38. package/src/i18n/messages/pt-br.ts +2 -0
  39. package/src/i18n/resolve-locale.ts +19 -4
  40. package/src/index.ts +3 -0
  41. package/src/modules/auth/services/auth.service.ts +14 -6
  42. package/src/utils/dom/dom-mutation-guard.ts +46 -0
  43. package/src/utils/intl/locales.ts +7 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/auth/services/auth.service.ts"],"sourcesContent":["import { cookies } from \"next/headers\";\n\nimport { api, type RequestConfig } from \"../../../infra/api/client\";\nimport { ApiError } from \"../../../infra/api/types\";\nimport { whitelabelService } from \"../../whitelabel/services/whitelabel.service\";\nimport { buildWlOverrideFromJwt } from \"../utils/build-wl-override\";\nimport {\n ClientInfo,\n ForgotPasswordRequest,\n ForgotPasswordResponse,\n GeoLocation,\n LoginApiResponse,\n LoginRequest,\n LoginResponse,\n LogoutApiResponse,\n LogoutRequest,\n LogoutResponse,\n RegisterApiRequest,\n RegisterApiResponse,\n RegisterRequest,\n RegisterResponse,\n ResendVerificationRequest,\n ResendVerificationResponse,\n ResetPasswordRequest,\n ResetPasswordResponse,\n SearchPlansApiResponse,\n SessionKeepRequest,\n SessionKeepResponse,\n SocialGoogleApiResponse,\n SocialGoogleResponse,\n SocialOnboardingApiResponse,\n SocialOnboardingRequest,\n SocialOnboardingResponse,\n IsolatedLoginResponse,\n TwoFactorApiResponse,\n TwoFactorRequest,\n TwoFactorResponse,\n UnlinkGoogleApiResponse,\n UnlinkGoogleResponse,\n VerifyEmailRequest,\n VerifyEmailResponse,\n} from \"../schema\";\nimport { findWhitelabel } from \"../../../server\";\n\nconst AUTH_COOKIE_NAME = \"greatapps\";\nconst COOKIE_MAX_AGE = 60 * 60 * 24 * 30;\n\n/** Plano Free (ID fixo). */\nconst FREE_PLAN_ID = 5;\n\n/**\n * O cadastro pede o Free de duas formas, e as duas valem: ausência de plano (que o\n * `resolvePlanId` traduz para o sentinela -1) e o id do próprio Free.\n *\n * Olhar só o sentinela fazia `?id_plan=5` cair no ramo `trial` e criar um trial de 7 dias\n * do plano gratuito, com `date_due` e `trial_days` — estado que não existe no produto.\n */\nfunction isFreePlan(idPlan: number): boolean {\n return idPlan === -1 || idPlan === FREE_PLAN_ID;\n}\n\nconst COOKIE_OPTIONS = {\n httpOnly: true,\n secure: process.env.NODE_ENV === \"production\",\n sameSite: \"lax\" as const,\n path: \"/\",\n};\n\nclass AuthService {\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n ): Promise<LoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options: { setCookie: false },\n ): Promise<IsolatedLoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options?: { setCookie?: boolean },\n ): Promise<LoginResponse | IsolatedLoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options?: { setCookie?: boolean },\n ): Promise<LoginResponse | IsolatedLoginResponse> {\n let requestConfig: RequestConfig | undefined;\n if (credentials.id_wl) {\n const wlToken = await whitelabelService.getTokenByWhitelabelId(\n credentials.id_wl,\n );\n requestConfig = { whiteLabelId: credentials.id_wl, authToken: wlToken };\n }\n\n const response = await api.apps.post<LoginApiResponse>(\n \"/auth/login\",\n {\n email: credentials.email,\n password: credentials.password,\n source: credentials?.source,\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n },\n requestConfig,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"E-mail ou senha incorretos\",\n response.code || \"LOGIN_FAILED\",\n 401,\n );\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (response.two_factor_required) {\n return { result: \"two_factor_required\", cookie: response.cookie, twoFactorMode: response.two_factor_required };\n }\n\n // Modo isolado: caller só quer o token, sem afetar a sessão do navegador\n // nem pagar pelas chamadas de user/account (ex.: fluxo de SSO).\n if (options?.setCookie === false) {\n return { result: \"success\", accessToken: response.cookie };\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(\n requestConfig ? { authToken: requestConfig.authToken } : undefined,\n ),\n accountService.findCurrentAccount(requestConfig),\n ]);\n\n return {\n result: \"success\",\n user,\n account,\n accessToken: response.cookie,\n refreshToken: \"\",\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async verifyTwoFactor(\n cookie: string,\n code: string,\n clientInfo: ClientInfo,\n options?: { window?: number; setCookie?: boolean },\n ): Promise<TwoFactorResponse> {\n const payload: TwoFactorRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n code,\n };\n\n const endpoint = options?.window !== undefined ? `/auth/code?window=${options.window}` : '/auth/code';\n const response = await api.apps.post<TwoFactorApiResponse>(\n endpoint,\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\"Código 2FA inválido\", \"TWO_FACTOR_FAILED\", 401);\n }\n\n if (!response?.data?.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida após 2FA\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n // Modo isolado: devolve o token sem gravar o cookie — o caller redireciona\n // pra outro lugar (ex.: SSO callback) e não quer mexer na sessão atual.\n if (options?.setCookie === false) {\n return { status: 1, accessToken: response.data.cookie };\n }\n\n await this.setAuthCookie(response.data.cookie);\n\n return { status: 1 };\n }\n\n async socialLoginGoogle(\n code: string,\n clientInfo: ClientInfo,\n ): Promise<SocialGoogleResponse> {\n const response = await api.apps.post<SocialGoogleApiResponse>(\n \"/auth/social/google\",\n {\n code,\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n verification: true,\n },\n );\n\n if (response.status === 0) {\n if (response.code === \"link_requires_password\") {\n return {\n result: \"link_requires_password\",\n message:\n response.message ||\n \"Uma conta com esse e-mail já existe. Faça login com e-mail e senha para vincular sua conta Google.\",\n };\n }\n throw new ApiError(\n response.message || \"Falha no login com Google\",\n response.code || \"GOOGLE_LOGIN_FAILED\",\n 401,\n );\n }\n\n if (response.needs_onboarding) {\n if (!response.onboarding_token || !response.partial?.email) {\n throw new ApiError(\n \"Resposta de onboarding inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n return {\n result: \"needs_onboarding\",\n onboardingToken: response.onboarding_token,\n partial: response.partial,\n };\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (response.two_factor_required) {\n return {\n result: \"two_factor_required\",\n cookie: response.cookie,\n twoFactorMode: response.two_factor_required,\n };\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n result: \"success\",\n user,\n account,\n accessToken: response.cookie,\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async completeGoogleOnboarding(\n data: SocialOnboardingRequest,\n clientInfo: ClientInfo,\n ): Promise<SocialOnboardingResponse> {\n const today = new Date();\n const trialEndDate = new Date(today);\n const trialDays = Math.min(Math.max(data.trialDays ?? 7, 1), 90);\n trialEndDate.setDate(today.getDate() + trialDays);\n\n const idPlan = await this.resolvePlanId(data.idPlan);\n\n const payload = {\n onboarding_token: data.onboardingToken,\n name: data.user.name,\n bussiness_type: data.businessType ?? 0,\n language: \"pt-br\",\n timezone: \"America/Sao_Paulo\",\n currency: \"BRL\",\n location: clientInfo.location,\n ip: clientInfo.ip,\n agent: clientInfo.agent,\n id_affiliate: data.affiliateId || 0,\n origin: data.origin,\n user: {\n id_api: \"\",\n name: data.user.name || \"\",\n last_name: data.user.last_name || \"\",\n rg: data.user.rg || \"\",\n cpf: data.user.cpf || \"\",\n gender: data.user.gender ?? 1,\n ddi: data.user.ddi || \"55\",\n phone: data.user.phone || \"\",\n profile: \"owner\",\n language: \"pt-br\",\n },\n subscription:\n isFreePlan(idPlan)\n ? {\n type: \"free\",\n id_coupon: data.couponId || 0,\n id_plan: FREE_PLAN_ID,\n id_product: 1,\n }\n : {\n type: \"trial\",\n id_coupon: data.couponId || 0,\n id_plan: idPlan,\n date_due: trialEndDate.toISOString().split(\"T\")[0],\n trial_days: trialDays,\n id_product: 1,\n },\n };\n\n const response = await api.apps.post<SocialOnboardingApiResponse>(\n \"/auth/social/onboarding\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao finalizar cadastro com Google\",\n \"ONBOARDING_FAILED\",\n 400,\n );\n }\n\n if (!response.data?.length || !response.cookie) {\n throw new ApiError(\n \"Resposta de cadastro inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n user,\n account,\n accessToken: response.cookie,\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async unlinkGoogle(): Promise<UnlinkGoogleResponse> {\n const { id_account, id_user } = await import(\n \"../utils/get-user-context\"\n ).then((m) => m.getUserContext());\n\n const response = await api.apps.delete<UnlinkGoogleApiResponse>(\n `/accounts/${id_account}/users/${id_user}/social/google`,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao desvincular conta Google\",\n \"UNLINK_FAILED\",\n 400,\n );\n }\n\n return {\n success: true,\n message: response.message,\n };\n }\n\n async register(\n data: RegisterRequest,\n clientInfo: ClientInfo,\n ): Promise<RegisterResponse> {\n const today = new Date();\n const trialEndDate = new Date(today);\n const trialDays = Math.min(Math.max(data.trialDays ?? 7, 1), 90);\n trialEndDate.setDate(today.getDate() + trialDays);\n\n const idPlan = await this.resolvePlanId(data.idPlan);\n\n const payload: RegisterApiRequest = {\n name: data.accountName,\n bussiness_type: data.businessType ?? 0,\n language: \"pt-br\",\n timezone: \"America/Sao_Paulo\",\n currency: \"BRL\",\n location: clientInfo.location,\n ip: clientInfo.ip,\n agent: clientInfo.agent,\n id_affiliate: data.affiliateId || 0,\n origin: data.origin,\n user: {\n id_api: \"\",\n name: data.name,\n last_name: data.lastName || \"\",\n rg: data.rg || \"\",\n cpf: data.cpf || \"\",\n gender: data.gender,\n email: data.email,\n phone: data.phone,\n password: data.password,\n profile: \"owner\",\n language: \"pt-br\",\n },\n subscription:\n isFreePlan(idPlan)\n ? {\n type: \"free\",\n id_coupon: data.couponId || 0,\n id_plan: FREE_PLAN_ID,\n id_product: 1,\n }\n : {\n type: \"trial\",\n id_coupon: data.couponId || 0,\n id_plan: idPlan,\n // Fluxo não-Stripe lê `date_due`; fluxo Stripe lê `trial_days`.\n // Mandamos os dois pra cobrir ambos os caminhos da API.\n date_due: trialEndDate.toISOString().split(\"T\")[0],\n trial_days: trialDays,\n id_product: 1,\n },\n };\n\n const response = await api.apps.post<RegisterApiResponse>(\n \"/accounts\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao criar conta\",\n \"REGISTER_FAILED\",\n 400,\n );\n }\n\n if (!response.data || response.data.length === 0) {\n throw new ApiError(\n \"Resposta de registro inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n const accountData = response.data[0];\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n user,\n account,\n accessToken: response.cookie,\n refreshToken: \"\",\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n requiresEmailVerification: !accountData.verified,\n };\n }\n\n async logout(clientInfo: ClientInfo): Promise<LogoutResponse> {\n const cookie = await this.getToken();\n\n if (!cookie) {\n throw new ApiError(\n \"Usuário não autenticado\",\n \"NOT_AUTHENTICATED_LOGOUT\",\n 401\n );\n }\n\n const payload: LogoutRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n };\n\n try {\n const response = await api.apps.post<LogoutApiResponse>(\n \"/auth/logout\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao realizar logout\",\n response.code || \"LOGOUT_FAILED\",\n 400,\n );\n }\n } finally {\n await this.removeAuthCookie();\n }\n\n return {\n success: true,\n };\n }\n\n async forgotPassword(\n _data: ForgotPasswordRequest,\n ): Promise<ForgotPasswordResponse> {\n throw new ApiError(\n \"Recuperação de senha não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async resetPassword(\n _data: ResetPasswordRequest,\n ): Promise<ResetPasswordResponse> {\n throw new ApiError(\n \"Redefinição de senha não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async verifyEmail(_data: VerifyEmailRequest): Promise<VerifyEmailResponse> {\n throw new ApiError(\n \"Verificação de email não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async resendVerification(\n _data: ResendVerificationRequest,\n ): Promise<ResendVerificationResponse> {\n throw new ApiError(\n \"Reenvio de verificação não implementado\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async validateSession(clientInfo: ClientInfo): Promise<boolean> {\n const cookie = await this.getToken();\n\n if (!cookie) {\n return false;\n }\n\n try {\n const requestConfig = await buildWlOverrideFromJwt(cookie);\n\n const payload: SessionKeepRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n };\n\n const response = await api.apps.post<SessionKeepResponse>(\n \"/auth/keep\",\n payload,\n requestConfig,\n );\n\n return response.status === 1;\n } catch (error) {\n console.error(\"[AuthService] validateSession error\", error);\n return false;\n }\n }\n\n async isAuthenticated(): Promise<boolean> {\n const token = await this.getToken();\n return !!token;\n }\n\n async getToken(): Promise<string | undefined> {\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\n const cookieStore = await cookies();\n return cookieStore.get(AUTH_COOKIE_NAME)?.value;\n }\n\n private async resolvePlanId(idPlan?: number | string | null): Promise<number> {\n if (idPlan == null || idPlan === \"\") return -1;\n if (typeof idPlan === \"number\" || Number(idPlan)) return Number(idPlan);\n\n if (typeof idPlan === \"string\") {\n const response = await api.apps.get<SearchPlansApiResponse>(\n `/plans?search=${encodeURIComponent(idPlan)}`,\n );\n\n if (response.status === 1 && response.data?.length) {\n return response.data[0].id;\n }\n\n throw new ApiError(\n `Plano \"${idPlan}\" não encontrado`,\n \"PLAN_NOT_FOUND\",\n 404,\n );\n }\n return -1;\n }\n\n private async setAuthCookie(token: string): Promise<void> {\n const cookieStore = await cookies();\n const whitelabel = await findWhitelabel().catch(() => null);\n const cookieDomain =\n this.normalizeCookieDomain(whitelabel?.domain);\n\n cookieStore.set(AUTH_COOKIE_NAME, token, {\n ...COOKIE_OPTIONS,\n ...(cookieDomain ? { domain: cookieDomain } : {}),\n maxAge: COOKIE_MAX_AGE,\n });\n }\n\n async removeAuthCookie(): Promise<void> {\n const cookieStore = await cookies();\n const whitelabel = await findWhitelabel().catch(() => null);\n const cookieDomain =\n this.normalizeCookieDomain(whitelabel?.domain);\n\n cookieStore.delete({\n name: AUTH_COOKIE_NAME,\n ...COOKIE_OPTIONS,\n ...(cookieDomain ? { domain: cookieDomain } : {}),\n });\n }\n\n private normalizeCookieDomain(domain?: string | null): string | undefined {\n if (!domain) return undefined;\n\n const normalized = domain.trim();\n if (!normalized) return undefined;\n\n const rawHost = (() => {\n try {\n return new URL(normalized).hostname;\n } catch {\n return normalized\n .replace(/^https?:\\/\\//i, \"\")\n .replace(/^www\\./i, \"\")\n .split(\"/\")[0]\n .split(\":\")[0];\n }\n })();\n\n if (!rawHost || rawHost === \"localhost\") {\n return undefined;\n }\n\n return rawHost.startsWith(\".\") ? rawHost : `.${rawHost}`;\n }\n}\n\nexport const authService = new AuthService();\n\nexport type { ClientInfo, GeoLocation };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/modules/auth/services/auth.service.ts"],"sourcesContent":["import { cookies } from \"next/headers\";\n\nimport { api, type RequestConfig } from \"../../../infra/api/client\";\nimport { ApiError } from \"../../../infra/api/types\";\nimport { whitelabelService } from \"../../whitelabel/services/whitelabel.service\";\nimport { buildWlOverrideFromJwt } from \"../utils/build-wl-override\";\nimport {\n ClientInfo,\n ForgotPasswordRequest,\n ForgotPasswordResponse,\n GeoLocation,\n LoginApiResponse,\n LoginRequest,\n LoginResponse,\n LogoutApiResponse,\n LogoutRequest,\n LogoutResponse,\n RegisterApiRequest,\n RegisterApiResponse,\n RegisterRequest,\n RegisterResponse,\n ResendVerificationRequest,\n ResendVerificationResponse,\n ResetPasswordRequest,\n ResetPasswordResponse,\n SearchPlansApiResponse,\n SessionKeepRequest,\n SessionKeepResponse,\n SocialGoogleApiResponse,\n SocialGoogleResponse,\n SocialOnboardingApiResponse,\n SocialOnboardingRequest,\n SocialOnboardingResponse,\n IsolatedLoginResponse,\n TwoFactorApiResponse,\n TwoFactorRequest,\n TwoFactorResponse,\n UnlinkGoogleApiResponse,\n UnlinkGoogleResponse,\n VerifyEmailRequest,\n VerifyEmailResponse,\n} from \"../schema\";\nimport { findWhitelabel } from \"../../../server\";\nimport { resolveLocale } from \"../../../i18n/resolve-locale\";\nimport { localeToApiLanguage } from \"../../../utils/intl/locales\";\n\nconst AUTH_COOKIE_NAME = \"greatapps\";\nconst COOKIE_MAX_AGE = 60 * 60 * 24 * 30;\n\n/** Plano Free (ID fixo). */\nconst FREE_PLAN_ID = 5;\n\n/**\n * O cadastro pede o Free de duas formas, e as duas valem: ausência de plano (que o\n * `resolvePlanId` traduz para o sentinela -1) e o id do próprio Free.\n *\n * Olhar só o sentinela fazia `?id_plan=5` cair no ramo `trial` e criar um trial de 7 dias\n * do plano gratuito, com `date_due` e `trial_days` — estado que não existe no produto.\n */\nfunction isFreePlan(idPlan: number): boolean {\n return idPlan === -1 || idPlan === FREE_PLAN_ID;\n}\n\nconst COOKIE_OPTIONS = {\n httpOnly: true,\n secure: process.env.NODE_ENV === \"production\",\n sameSite: \"lax\" as const,\n path: \"/\",\n};\n\nclass AuthService {\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n ): Promise<LoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options: { setCookie: false },\n ): Promise<IsolatedLoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options?: { setCookie?: boolean },\n ): Promise<LoginResponse | IsolatedLoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options?: { setCookie?: boolean },\n ): Promise<LoginResponse | IsolatedLoginResponse> {\n let requestConfig: RequestConfig | undefined;\n if (credentials.id_wl) {\n const wlToken = await whitelabelService.getTokenByWhitelabelId(\n credentials.id_wl,\n );\n requestConfig = { whiteLabelId: credentials.id_wl, authToken: wlToken };\n }\n\n const response = await api.apps.post<LoginApiResponse>(\n \"/auth/login\",\n {\n email: credentials.email,\n password: credentials.password,\n source: credentials?.source,\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n },\n requestConfig,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"E-mail ou senha incorretos\",\n response.code || \"LOGIN_FAILED\",\n 401,\n );\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (response.two_factor_required) {\n return { result: \"two_factor_required\", cookie: response.cookie, twoFactorMode: response.two_factor_required };\n }\n\n // Modo isolado: caller só quer o token, sem afetar a sessão do navegador\n // nem pagar pelas chamadas de user/account (ex.: fluxo de SSO).\n if (options?.setCookie === false) {\n return { result: \"success\", accessToken: response.cookie };\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(\n requestConfig ? { authToken: requestConfig.authToken } : undefined,\n ),\n accountService.findCurrentAccount(requestConfig),\n ]);\n\n return {\n result: \"success\",\n user,\n account,\n accessToken: response.cookie,\n refreshToken: \"\",\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async verifyTwoFactor(\n cookie: string,\n code: string,\n clientInfo: ClientInfo,\n options?: { window?: number; setCookie?: boolean },\n ): Promise<TwoFactorResponse> {\n const payload: TwoFactorRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n code,\n };\n\n const endpoint = options?.window !== undefined ? `/auth/code?window=${options.window}` : '/auth/code';\n const response = await api.apps.post<TwoFactorApiResponse>(\n endpoint,\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\"Código 2FA inválido\", \"TWO_FACTOR_FAILED\", 401);\n }\n\n if (!response?.data?.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida após 2FA\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n // Modo isolado: devolve o token sem gravar o cookie — o caller redireciona\n // pra outro lugar (ex.: SSO callback) e não quer mexer na sessão atual.\n if (options?.setCookie === false) {\n return { status: 1, accessToken: response.data.cookie };\n }\n\n await this.setAuthCookie(response.data.cookie);\n\n return { status: 1 };\n }\n\n async socialLoginGoogle(\n code: string,\n clientInfo: ClientInfo,\n ): Promise<SocialGoogleResponse> {\n const response = await api.apps.post<SocialGoogleApiResponse>(\n \"/auth/social/google\",\n {\n code,\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n verification: true,\n },\n );\n\n if (response.status === 0) {\n if (response.code === \"link_requires_password\") {\n return {\n result: \"link_requires_password\",\n message:\n response.message ||\n \"Uma conta com esse e-mail já existe. Faça login com e-mail e senha para vincular sua conta Google.\",\n };\n }\n throw new ApiError(\n response.message || \"Falha no login com Google\",\n response.code || \"GOOGLE_LOGIN_FAILED\",\n 401,\n );\n }\n\n if (response.needs_onboarding) {\n if (!response.onboarding_token || !response.partial?.email) {\n throw new ApiError(\n \"Resposta de onboarding inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n return {\n result: \"needs_onboarding\",\n onboardingToken: response.onboarding_token,\n partial: response.partial,\n };\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (response.two_factor_required) {\n return {\n result: \"two_factor_required\",\n cookie: response.cookie,\n twoFactorMode: response.two_factor_required,\n };\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n result: \"success\",\n user,\n account,\n accessToken: response.cookie,\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async completeGoogleOnboarding(\n data: SocialOnboardingRequest,\n clientInfo: ClientInfo,\n ): Promise<SocialOnboardingResponse> {\n const today = new Date();\n const trialEndDate = new Date(today);\n const trialDays = Math.min(Math.max(data.trialDays ?? 7, 1), 90);\n trialEndDate.setDate(today.getDate() + trialDays);\n\n const idPlan = await this.resolvePlanId(data.idPlan);\n\n const whitelabel = await findWhitelabel().catch(() => null);\n const language = localeToApiLanguage(await resolveLocale({ whitelabelId: whitelabel?.id ?? null }));\n\n const payload = {\n onboarding_token: data.onboardingToken,\n name: data.user.name,\n bussiness_type: data.businessType ?? 0,\n language,\n timezone: clientInfo.timezone,\n currency: \"BRL\",\n location: clientInfo.location,\n ip: clientInfo.ip,\n agent: clientInfo.agent,\n id_affiliate: data.affiliateId || 0,\n origin: data.origin,\n user: {\n id_api: \"\",\n name: data.user.name || \"\",\n last_name: data.user.last_name || \"\",\n rg: data.user.rg || \"\",\n cpf: data.user.cpf || \"\",\n gender: data.user.gender ?? 1,\n ddi: data.user.ddi || \"55\",\n phone: data.user.phone || \"\",\n profile: \"owner\",\n language,\n },\n subscription:\n isFreePlan(idPlan)\n ? {\n type: \"free\",\n id_coupon: data.couponId || 0,\n id_plan: FREE_PLAN_ID,\n id_product: 1,\n }\n : {\n type: \"trial\",\n id_coupon: data.couponId || 0,\n id_plan: idPlan,\n date_due: trialEndDate.toISOString().split(\"T\")[0],\n trial_days: trialDays,\n id_product: 1,\n },\n };\n\n const response = await api.apps.post<SocialOnboardingApiResponse>(\n \"/auth/social/onboarding\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao finalizar cadastro com Google\",\n \"ONBOARDING_FAILED\",\n 400,\n );\n }\n\n if (!response.data?.length || !response.cookie) {\n throw new ApiError(\n \"Resposta de cadastro inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n user,\n account,\n accessToken: response.cookie,\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async unlinkGoogle(): Promise<UnlinkGoogleResponse> {\n const { id_account, id_user } = await import(\n \"../utils/get-user-context\"\n ).then((m) => m.getUserContext());\n\n const response = await api.apps.delete<UnlinkGoogleApiResponse>(\n `/accounts/${id_account}/users/${id_user}/social/google`,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao desvincular conta Google\",\n \"UNLINK_FAILED\",\n 400,\n );\n }\n\n return {\n success: true,\n message: response.message,\n };\n }\n\n async register(\n data: RegisterRequest,\n clientInfo: ClientInfo,\n ): Promise<RegisterResponse> {\n const today = new Date();\n const trialEndDate = new Date(today);\n const trialDays = Math.min(Math.max(data.trialDays ?? 7, 1), 90);\n trialEndDate.setDate(today.getDate() + trialDays);\n\n const idPlan = await this.resolvePlanId(data.idPlan);\n\n const whitelabel = await findWhitelabel().catch(() => null);\n const language = localeToApiLanguage(await resolveLocale({ whitelabelId: whitelabel?.id ?? null }));\n\n const payload: RegisterApiRequest = {\n name: data.accountName,\n bussiness_type: data.businessType ?? 0,\n language,\n timezone: clientInfo.timezone,\n currency: \"BRL\",\n location: clientInfo.location,\n ip: clientInfo.ip,\n agent: clientInfo.agent,\n id_affiliate: data.affiliateId || 0,\n origin: data.origin,\n user: {\n id_api: \"\",\n name: data.name,\n last_name: data.lastName || \"\",\n rg: data.rg || \"\",\n cpf: data.cpf || \"\",\n gender: data.gender,\n email: data.email,\n phone: data.phone,\n password: data.password,\n profile: \"owner\",\n language,\n },\n subscription:\n isFreePlan(idPlan)\n ? {\n type: \"free\",\n id_coupon: data.couponId || 0,\n id_plan: FREE_PLAN_ID,\n id_product: 1,\n }\n : {\n type: \"trial\",\n id_coupon: data.couponId || 0,\n id_plan: idPlan,\n // Fluxo não-Stripe lê `date_due`; fluxo Stripe lê `trial_days`.\n // Mandamos os dois pra cobrir ambos os caminhos da API.\n date_due: trialEndDate.toISOString().split(\"T\")[0],\n trial_days: trialDays,\n id_product: 1,\n },\n };\n\n const response = await api.apps.post<RegisterApiResponse>(\n \"/accounts\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao criar conta\",\n \"REGISTER_FAILED\",\n 400,\n );\n }\n\n if (!response.data || response.data.length === 0) {\n throw new ApiError(\n \"Resposta de registro inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n const accountData = response.data[0];\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n user,\n account,\n accessToken: response.cookie,\n refreshToken: \"\",\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n requiresEmailVerification: !accountData.verified,\n };\n }\n\n async logout(clientInfo: ClientInfo): Promise<LogoutResponse> {\n const cookie = await this.getToken();\n\n if (!cookie) {\n throw new ApiError(\n \"Usuário não autenticado\",\n \"NOT_AUTHENTICATED_LOGOUT\",\n 401\n );\n }\n\n const payload: LogoutRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n };\n\n try {\n const response = await api.apps.post<LogoutApiResponse>(\n \"/auth/logout\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao realizar logout\",\n response.code || \"LOGOUT_FAILED\",\n 400,\n );\n }\n } finally {\n await this.removeAuthCookie();\n }\n\n return {\n success: true,\n };\n }\n\n async forgotPassword(\n _data: ForgotPasswordRequest,\n ): Promise<ForgotPasswordResponse> {\n throw new ApiError(\n \"Recuperação de senha não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async resetPassword(\n _data: ResetPasswordRequest,\n ): Promise<ResetPasswordResponse> {\n throw new ApiError(\n \"Redefinição de senha não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async verifyEmail(_data: VerifyEmailRequest): Promise<VerifyEmailResponse> {\n throw new ApiError(\n \"Verificação de email não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async resendVerification(\n _data: ResendVerificationRequest,\n ): Promise<ResendVerificationResponse> {\n throw new ApiError(\n \"Reenvio de verificação não implementado\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async validateSession(clientInfo: ClientInfo): Promise<boolean> {\n const cookie = await this.getToken();\n\n if (!cookie) {\n return false;\n }\n\n try {\n const requestConfig = await buildWlOverrideFromJwt(cookie);\n\n const payload: SessionKeepRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n };\n\n const response = await api.apps.post<SessionKeepResponse>(\n \"/auth/keep\",\n payload,\n requestConfig,\n );\n\n return response.status === 1;\n } catch (error) {\n console.error(\"[AuthService] validateSession error\", error);\n return false;\n }\n }\n\n async isAuthenticated(): Promise<boolean> {\n const token = await this.getToken();\n return !!token;\n }\n\n async getToken(): Promise<string | undefined> {\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\n const cookieStore = await cookies();\n return cookieStore.get(AUTH_COOKIE_NAME)?.value;\n }\n\n private async resolvePlanId(idPlan?: number | string | null): Promise<number> {\n if (idPlan == null || idPlan === \"\") return -1;\n if (typeof idPlan === \"number\" || Number(idPlan)) return Number(idPlan);\n\n if (typeof idPlan === \"string\") {\n const response = await api.apps.get<SearchPlansApiResponse>(\n `/plans?search=${encodeURIComponent(idPlan)}`,\n );\n\n if (response.status === 1 && response.data?.length) {\n return response.data[0].id;\n }\n\n throw new ApiError(\n `Plano \"${idPlan}\" não encontrado`,\n \"PLAN_NOT_FOUND\",\n 404,\n );\n }\n return -1;\n }\n\n private async setAuthCookie(token: string): Promise<void> {\n const cookieStore = await cookies();\n const whitelabel = await findWhitelabel().catch(() => null);\n const cookieDomain =\n this.normalizeCookieDomain(whitelabel?.domain);\n\n cookieStore.set(AUTH_COOKIE_NAME, token, {\n ...COOKIE_OPTIONS,\n ...(cookieDomain ? { domain: cookieDomain } : {}),\n maxAge: COOKIE_MAX_AGE,\n });\n }\n\n async removeAuthCookie(): Promise<void> {\n const cookieStore = await cookies();\n const whitelabel = await findWhitelabel().catch(() => null);\n const cookieDomain =\n this.normalizeCookieDomain(whitelabel?.domain);\n\n cookieStore.delete({\n name: AUTH_COOKIE_NAME,\n ...COOKIE_OPTIONS,\n ...(cookieDomain ? { domain: cookieDomain } : {}),\n });\n }\n\n private normalizeCookieDomain(domain?: string | null): string | undefined {\n if (!domain) return undefined;\n\n const normalized = domain.trim();\n if (!normalized) return undefined;\n\n const rawHost = (() => {\n try {\n return new URL(normalized).hostname;\n } catch {\n return normalized\n .replace(/^https?:\\/\\//i, \"\")\n .replace(/^www\\./i, \"\")\n .split(\"/\")[0]\n .split(\":\")[0];\n }\n })();\n\n if (!rawHost || rawHost === \"localhost\") {\n return undefined;\n }\n\n return rawHost.startsWith(\".\") ? rawHost : `.${rawHost}`;\n }\n}\n\nexport const authService = new AuthService();\n\nexport type { ClientInfo, GeoLocation };\n"],"mappings":"AAAA,SAAS,eAAe;AAExB,SAAS,WAA+B;AACxC,SAAS,gBAAgB;AACzB,SAAS,yBAAyB;AAClC,SAAS,8BAA8B;AAqCvC,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AAEpC,MAAM,mBAAmB;AACzB,MAAM,iBAAiB,KAAK,KAAK,KAAK;AAGtC,MAAM,eAAe;AASrB,SAAS,WAAW,QAAyB;AAC3C,SAAO,WAAW,MAAM,WAAW;AACrC;AAEA,MAAM,iBAAiB;AAAA,EACrB,UAAU;AAAA,EACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,EACjC,UAAU;AAAA,EACV,MAAM;AACR;AAEA,MAAM,YAAY;AAAA,EAehB,MAAM,MACJ,aACA,YACA,SACgD;AAChD,QAAI;AACJ,QAAI,YAAY,OAAO;AACrB,YAAM,UAAU,MAAM,kBAAkB;AAAA,QACtC,YAAY;AAAA,MACd;AACA,sBAAgB,EAAE,cAAc,YAAY,OAAO,WAAW,QAAQ;AAAA,IACxE;AAEA,UAAM,WAAW,MAAM,IAAI,KAAK;AAAA,MAC9B;AAAA,MACA;AAAA,QACE,OAAO,YAAY;AAAA,QACnB,UAAU,YAAY;AAAA,QACtB,QAAQ,aAAa;AAAA,QACrB,UAAU,WAAW;AAAA,QACrB,IAAI,WAAW;AAAA,QACf,UAAU,WAAW;AAAA,QACrB,OAAO,WAAW;AAAA,MACpB;AAAA,MACA;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB,SAAS,QAAQ;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,QAAQ;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,qBAAqB;AAChC,aAAO,EAAE,QAAQ,uBAAuB,QAAQ,SAAS,QAAQ,eAAe,SAAS,oBAAoB;AAAA,IAC/G;AAIA,QAAI,SAAS,cAAc,OAAO;AAChC,aAAO,EAAE,QAAQ,WAAW,aAAa,SAAS,OAAO;AAAA,IAC3D;AAEA,UAAM,KAAK,cAAc,SAAS,MAAM;AAExC,UAAM,CAAC,EAAE,YAAY,GAAG,EAAE,eAAe,CAAC,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC9D,OAAO,mCAAmC;AAAA,MAC1C,OAAO,yCAAyC;AAAA,IAClD,CAAC;AACD,UAAM,CAAC,MAAM,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,MACxC,YAAY;AAAA,QACV,gBAAgB,EAAE,WAAW,cAAc,UAAU,IAAI;AAAA,MAC3D;AAAA,MACA,eAAe,mBAAmB,aAAa;AAAA,IACjD,CAAC;AAED,WAAO;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,aAAa,SAAS;AAAA,MACtB,cAAc;AAAA,MACd,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB,GAAI,EAAE,YAAY;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,QACA,MACA,YACA,SAC4B;AAC5B,UAAM,UAA4B;AAAA,MAChC,UAAU,WAAW;AAAA,MACrB,IAAI,WAAW;AAAA,MACf,UAAU,WAAW;AAAA,MACrB,OAAO,WAAW;AAAA,MAClB;AAAA,MACA;AAAA,IACF;AAEA,UAAM,WAAW,SAAS,WAAW,SAAY,qBAAqB,QAAQ,MAAM,KAAK;AACzF,UAAM,WAAW,MAAM,IAAI,KAAK;AAAA,MAC9B;AAAA,MACA;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI,SAAS,6BAAuB,qBAAqB,GAAG;AAAA,IACpE;AAEA,QAAI,CAAC,UAAU,MAAM,QAAQ;AAC3B,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAIA,QAAI,SAAS,cAAc,OAAO;AAChC,aAAO,EAAE,QAAQ,GAAG,aAAa,SAAS,KAAK,OAAO;AAAA,IACxD;AAEA,UAAM,KAAK,cAAc,SAAS,KAAK,MAAM;AAE7C,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA,EAEA,MAAM,kBACJ,MACA,YAC+B;AAC/B,UAAM,WAAW,MAAM,IAAI,KAAK;AAAA,MAC9B;AAAA,MACA;AAAA,QACE;AAAA,QACA,UAAU,WAAW;AAAA,QACrB,IAAI,WAAW;AAAA,QACf,UAAU,WAAW;AAAA,QACrB,OAAO,WAAW;AAAA,QAClB,cAAc;AAAA,MAChB;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,UAAI,SAAS,SAAS,0BAA0B;AAC9C,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,SACE,SAAS,WACT;AAAA,QACJ;AAAA,MACF;AACA,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB,SAAS,QAAQ;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,kBAAkB;AAC7B,UAAI,CAAC,SAAS,oBAAoB,CAAC,SAAS,SAAS,OAAO;AAC1D,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,iBAAiB,SAAS;AAAA,QAC1B,SAAS,SAAS;AAAA,MACpB;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,QAAQ;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,qBAAqB;AAChC,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,QAAQ,SAAS;AAAA,QACjB,eAAe,SAAS;AAAA,MAC1B;AAAA,IACF;AAEA,UAAM,KAAK,cAAc,SAAS,MAAM;AAExC,UAAM,CAAC,EAAE,YAAY,GAAG,EAAE,eAAe,CAAC,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC9D,OAAO,mCAAmC;AAAA,MAC1C,OAAO,yCAAyC;AAAA,IAClD,CAAC;AACD,UAAM,CAAC,MAAM,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,MACxC,YAAY,SAAS;AAAA,MACrB,eAAe,mBAAmB;AAAA,IACpC,CAAC;AAED,WAAO;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,aAAa,SAAS;AAAA,MACtB,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB,GAAI,EAAE,YAAY;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,MAAM,yBACJ,MACA,YACmC;AACnC,UAAM,QAAQ,oBAAI,KAAK;AACvB,UAAM,eAAe,IAAI,KAAK,KAAK;AACnC,UAAM,YAAY,KAAK,IAAI,KAAK,IAAI,KAAK,aAAa,GAAG,CAAC,GAAG,EAAE;AAC/D,iBAAa,QAAQ,MAAM,QAAQ,IAAI,SAAS;AAEhD,UAAM,SAAS,MAAM,KAAK,cAAc,KAAK,MAAM;AAEnD,UAAM,aAAa,MAAM,eAAe,EAAE,MAAM,MAAM,IAAI;AAC1D,UAAM,WAAW,oBAAoB,MAAM,cAAc,EAAE,cAAc,YAAY,MAAM,KAAK,CAAC,CAAC;AAElG,UAAM,UAAU;AAAA,MACd,kBAAkB,KAAK;AAAA,MACvB,MAAM,KAAK,KAAK;AAAA,MAChB,gBAAgB,KAAK,gBAAgB;AAAA,MACrC;AAAA,MACA,UAAU,WAAW;AAAA,MACrB,UAAU;AAAA,MACV,UAAU,WAAW;AAAA,MACrB,IAAI,WAAW;AAAA,MACf,OAAO,WAAW;AAAA,MAClB,cAAc,KAAK,eAAe;AAAA,MAClC,QAAQ,KAAK;AAAA,MACb,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,MAAM,KAAK,KAAK,QAAQ;AAAA,QACxB,WAAW,KAAK,KAAK,aAAa;AAAA,QAClC,IAAI,KAAK,KAAK,MAAM;AAAA,QACpB,KAAK,KAAK,KAAK,OAAO;AAAA,QACtB,QAAQ,KAAK,KAAK,UAAU;AAAA,QAC5B,KAAK,KAAK,KAAK,OAAO;AAAA,QACtB,OAAO,KAAK,KAAK,SAAS;AAAA,QAC1B,SAAS;AAAA,QACT;AAAA,MACF;AAAA,MACA,cACE,WAAW,MAAM,IACb;AAAA,QACE,MAAM;AAAA,QACN,WAAW,KAAK,YAAY;AAAA,QAC5B,SAAS;AAAA,QACT,YAAY;AAAA,MACd,IACA;AAAA,QACE,MAAM;AAAA,QACN,WAAW,KAAK,YAAY;AAAA,QAC5B,SAAS;AAAA,QACT,UAAU,aAAa,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,QACjD,YAAY;AAAA,QACZ,YAAY;AAAA,MACd;AAAA,IACR;AAEA,UAAM,WAAW,MAAM,IAAI,KAAK;AAAA,MAC9B;AAAA,MACA;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,MAAM,UAAU,CAAC,SAAS,QAAQ;AAC9C,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,KAAK,cAAc,SAAS,MAAM;AAExC,UAAM,CAAC,EAAE,YAAY,GAAG,EAAE,eAAe,CAAC,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC9D,OAAO,mCAAmC;AAAA,MAC1C,OAAO,yCAAyC;AAAA,IAClD,CAAC;AACD,UAAM,CAAC,MAAM,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,MACxC,YAAY,SAAS;AAAA,MACrB,eAAe,mBAAmB;AAAA,IACpC,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,aAAa,SAAS;AAAA,MACtB,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB,GAAI,EAAE,YAAY;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,MAAM,eAA8C;AAClD,UAAM,EAAE,YAAY,QAAQ,IAAI,MAAM,OACpC,2BACF,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC;AAEhC,UAAM,WAAW,MAAM,IAAI,KAAK;AAAA,MAC9B,aAAa,UAAU,UAAU,OAAO;AAAA,IAC1C;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,SAAS;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAM,SACJ,MACA,YAC2B;AAC3B,UAAM,QAAQ,oBAAI,KAAK;AACvB,UAAM,eAAe,IAAI,KAAK,KAAK;AACnC,UAAM,YAAY,KAAK,IAAI,KAAK,IAAI,KAAK,aAAa,GAAG,CAAC,GAAG,EAAE;AAC/D,iBAAa,QAAQ,MAAM,QAAQ,IAAI,SAAS;AAEhD,UAAM,SAAS,MAAM,KAAK,cAAc,KAAK,MAAM;AAEnD,UAAM,aAAa,MAAM,eAAe,EAAE,MAAM,MAAM,IAAI;AAC1D,UAAM,WAAW,oBAAoB,MAAM,cAAc,EAAE,cAAc,YAAY,MAAM,KAAK,CAAC,CAAC;AAElG,UAAM,UAA8B;AAAA,MAClC,MAAM,KAAK;AAAA,MACX,gBAAgB,KAAK,gBAAgB;AAAA,MACrC;AAAA,MACA,UAAU,WAAW;AAAA,MACrB,UAAU;AAAA,MACV,UAAU,WAAW;AAAA,MACrB,IAAI,WAAW;AAAA,MACf,OAAO,WAAW;AAAA,MAClB,cAAc,KAAK,eAAe;AAAA,MAClC,QAAQ,KAAK;AAAA,MACb,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,MAAM,KAAK;AAAA,QACX,WAAW,KAAK,YAAY;AAAA,QAC5B,IAAI,KAAK,MAAM;AAAA,QACf,KAAK,KAAK,OAAO;AAAA,QACjB,QAAQ,KAAK;AAAA,QACb,OAAO,KAAK;AAAA,QACZ,OAAO,KAAK;AAAA,QACZ,UAAU,KAAK;AAAA,QACf,SAAS;AAAA,QACT;AAAA,MACF;AAAA,MACA,cACE,WAAW,MAAM,IACb;AAAA,QACE,MAAM;AAAA,QACN,WAAW,KAAK,YAAY;AAAA,QAC5B,SAAS;AAAA,QACT,YAAY;AAAA,MACd,IACA;AAAA,QACE,MAAM;AAAA,QACN,WAAW,KAAK,YAAY;AAAA,QAC5B,SAAS;AAAA;AAAA;AAAA,QAGT,UAAU,aAAa,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,QACjD,YAAY;AAAA,QACZ,YAAY;AAAA,MACd;AAAA,IACR;AAEA,UAAM,WAAW,MAAM,IAAI,KAAK;AAAA,MAC9B;AAAA,MACA;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,QAAQ,SAAS,KAAK,WAAW,GAAG;AAChD,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,QAAQ;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cAAc,SAAS,KAAK,CAAC;AAEnC,UAAM,KAAK,cAAc,SAAS,MAAM;AAExC,UAAM,CAAC,EAAE,YAAY,GAAG,EAAE,eAAe,CAAC,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC9D,OAAO,mCAAmC;AAAA,MAC1C,OAAO,yCAAyC;AAAA,IAClD,CAAC;AACD,UAAM,CAAC,MAAM,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,MACxC,YAAY,SAAS;AAAA,MACrB,eAAe,mBAAmB;AAAA,IACpC,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,aAAa,SAAS;AAAA,MACtB,cAAc;AAAA,MACd,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB,GAAI,EAAE,YAAY;AAAA,MACpE,2BAA2B,CAAC,YAAY;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,YAAiD;AAC5D,UAAM,SAAS,MAAM,KAAK,SAAS;AAEnC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAyB;AAAA,MAC7B,UAAU,WAAW;AAAA,MACrB,IAAI,WAAW;AAAA,MACf,UAAU,WAAW;AAAA,MACrB,OAAO,WAAW;AAAA,MAClB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,IAAI,KAAK;AAAA,QAC9B;AAAA,QACA;AAAA,MACF;AAEA,UAAI,SAAS,WAAW,GAAG;AACzB,cAAM,IAAI;AAAA,UACR,SAAS,WAAW;AAAA,UACpB,SAAS,QAAQ;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAAA,IACF,UAAE;AACA,YAAM,KAAK,iBAAiB;AAAA,IAC9B;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,OACiC;AACjC,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,cACJ,OACgC;AAChC,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,OAAyD;AACzE,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,mBACJ,OACqC;AACrC,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,YAA0C;AAC9D,UAAM,SAAS,MAAM,KAAK,SAAS;AAEnC,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,gBAAgB,MAAM,uBAAuB,MAAM;AAEzD,YAAM,UAA8B;AAAA,QAClC,UAAU,WAAW;AAAA,QACrB,IAAI,WAAW;AAAA,QACf,UAAU,WAAW;AAAA,QACrB,OAAO,WAAW;AAAA,QAClB;AAAA,MACF;AAEA,YAAM,WAAW,MAAM,IAAI,KAAK;AAAA,QAC9B;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,aAAO,SAAS,WAAW;AAAA,IAC7B,SAAS,OAAO;AACd,cAAQ,MAAM,uCAAuC,KAAK;AAC1D,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,kBAAoC;AACxC,UAAM,QAAQ,MAAM,KAAK,SAAS;AAClC,WAAO,CAAC,CAAC;AAAA,EACX;AAAA,EAEA,MAAM,WAAwC;AAC5C,QAAI,QAAQ,IAAI,iBAAkB,QAAO,QAAQ,IAAI;AACrD,UAAM,cAAc,MAAM,QAAQ;AAClC,WAAO,YAAY,IAAI,gBAAgB,GAAG;AAAA,EAC5C;AAAA,EAEA,MAAc,cAAc,QAAkD;AAC5E,QAAI,UAAU,QAAQ,WAAW,GAAI,QAAO;AAC5C,QAAI,OAAO,WAAW,YAAY,OAAO,MAAM,EAAG,QAAO,OAAO,MAAM;AAEtE,QAAI,OAAO,WAAW,UAAU;AAC9B,YAAM,WAAW,MAAM,IAAI,KAAK;AAAA,QAC9B,iBAAiB,mBAAmB,MAAM,CAAC;AAAA,MAC7C;AAEA,UAAI,SAAS,WAAW,KAAK,SAAS,MAAM,QAAQ;AAClD,eAAO,SAAS,KAAK,CAAC,EAAE;AAAA,MAC1B;AAEA,YAAM,IAAI;AAAA,QACR,UAAU,MAAM;AAAA,QAChB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,cAAc,OAA8B;AACxD,UAAM,cAAc,MAAM,QAAQ;AAClC,UAAM,aAAa,MAAM,eAAe,EAAE,MAAM,MAAM,IAAI;AAC1D,UAAM,eACJ,KAAK,sBAAsB,YAAY,MAAM;AAE/C,gBAAY,IAAI,kBAAkB,OAAO;AAAA,MACvC,GAAG;AAAA,MACH,GAAI,eAAe,EAAE,QAAQ,aAAa,IAAI,CAAC;AAAA,MAC/C,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,mBAAkC;AACtC,UAAM,cAAc,MAAM,QAAQ;AAClC,UAAM,aAAa,MAAM,eAAe,EAAE,MAAM,MAAM,IAAI;AAC1D,UAAM,eACJ,KAAK,sBAAsB,YAAY,MAAM;AAE/C,gBAAY,OAAO;AAAA,MACjB,MAAM;AAAA,MACN,GAAG;AAAA,MACH,GAAI,eAAe,EAAE,QAAQ,aAAa,IAAI,CAAC;AAAA,IACjD,CAAC;AAAA,EACH;AAAA,EAEQ,sBAAsB,QAA4C;AACxE,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,aAAa,OAAO,KAAK;AAC/B,QAAI,CAAC,WAAY,QAAO;AAExB,UAAM,WAAW,MAAM;AACrB,UAAI;AACF,eAAO,IAAI,IAAI,UAAU,EAAE;AAAA,MAC7B,QAAQ;AACN,eAAO,WACJ,QAAQ,iBAAiB,EAAE,EAC3B,QAAQ,WAAW,EAAE,EACrB,MAAM,GAAG,EAAE,CAAC,EACZ,MAAM,GAAG,EAAE,CAAC;AAAA,MACjB;AAAA,IACF,GAAG;AAEH,QAAI,CAAC,WAAW,YAAY,aAAa;AACvC,aAAO;AAAA,IACT;AAEA,WAAO,QAAQ,WAAW,GAAG,IAAI,UAAU,IAAI,OAAO;AAAA,EACxD;AACF;AAEO,MAAM,cAAc,IAAI,YAAY;","names":[]}
@@ -0,0 +1,20 @@
1
+ const DOM_MUTATION_GUARD_SCRIPT = `(function(){
2
+ if(typeof Node==="undefined"||!Node.prototype)return;
3
+ if(window.__gpDomGuard)return;
4
+ var s={removeChild:0,insertBefore:0};
5
+ window.__gpDomGuard=s;
6
+ window.__gpDomGuardOnHit=window.__gpDomGuardOnHit||null;
7
+ function hit(k){s[k]++;try{if(window.__gpDomGuardOnHit)window.__gpDomGuardOnHit(k)}catch(e){}}
8
+ var removeChild=Node.prototype.removeChild;
9
+ Node.prototype.removeChild=function(child){
10
+ if(child&&child.parentNode!==this){hit("removeChild");return child}
11
+ return removeChild.apply(this,arguments)};
12
+ var insertBefore=Node.prototype.insertBefore;
13
+ Node.prototype.insertBefore=function(newNode,referenceNode){
14
+ if(referenceNode&&referenceNode.parentNode!==this){hit("insertBefore");return newNode}
15
+ return insertBefore.apply(this,arguments)};
16
+ })();`;
17
+ export {
18
+ DOM_MUTATION_GUARD_SCRIPT
19
+ };
20
+ //# sourceMappingURL=dom-mutation-guard.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/dom/dom-mutation-guard.ts"],"sourcesContent":["/**\n * Guarda contra mutação externa do DOM (tradutor do navegador, extensões).\n *\n * PROBLEMA: o Google Tradutor do Chrome substitui cada text node por `<font><font>…</font></font>`.\n * O React continua guardando a referência do text node ORIGINAL no fiber. No commit seguinte ele\n * chama `parent.insertBefore(novo, textNodeAntigo)` ou `parent.removeChild(textNodeAntigo)` — e o nó\n * já não é mais filho daquele pai. O DOM levanta `NotFoundError`, o erro sobe até o root e o app\n * inteiro cai no `global-error.tsx` (evento `render.root_crashed` no Sentry).\n *\n * Isso derrubou clientes reais em CO/PE/MX/AR/FR (zero casos no BR, onde a página já está no idioma\n * do usuário e o Chrome não oferece tradução), inclusive em cima da tela de trocar cartão — o cliente\n * ficava sem conseguir pagar.\n *\n * SOLUÇÃO: transformar essas duas operações em no-op quando o nó de referência já não pertence mais\n * ao pai. O React segue adiante, a página não morre, e o trecho traduzido apenas deixa de receber\n * aquela atualização pontual (o próximo re-render completo normaliza).\n *\n * Precisa rodar ANTES da hidratação, por isso é injetado como `<script>` inline no `<head>` do root\n * layout em vez de virar um `useEffect`.\n */\n\ndeclare global {\n interface Window {\n /** Contadores de quantas vezes a guarda entrou em ação nesta sessão. */\n __gpDomGuard?: { removeChild: number; insertBefore: number };\n /** Hook opcional preenchido pelo reporter para avisar o Sentry no primeiro disparo. */\n __gpDomGuardOnHit?: ((kind: 'removeChild' | 'insertBefore') => void) | null;\n }\n}\n\nexport const DOM_MUTATION_GUARD_SCRIPT = `(function(){\nif(typeof Node===\"undefined\"||!Node.prototype)return;\nif(window.__gpDomGuard)return;\nvar s={removeChild:0,insertBefore:0};\nwindow.__gpDomGuard=s;\nwindow.__gpDomGuardOnHit=window.__gpDomGuardOnHit||null;\nfunction hit(k){s[k]++;try{if(window.__gpDomGuardOnHit)window.__gpDomGuardOnHit(k)}catch(e){}}\nvar removeChild=Node.prototype.removeChild;\nNode.prototype.removeChild=function(child){\nif(child&&child.parentNode!==this){hit(\"removeChild\");return child}\nreturn removeChild.apply(this,arguments)};\nvar insertBefore=Node.prototype.insertBefore;\nNode.prototype.insertBefore=function(newNode,referenceNode){\nif(referenceNode&&referenceNode.parentNode!==this){hit(\"insertBefore\");return newNode}\nreturn insertBefore.apply(this,arguments)};\n})();`;\n"],"mappings":"AA8BO,MAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":[]}
@@ -6,8 +6,13 @@ const LANGUAGE_OPTIONS = [
6
6
  function buildLocaleOptions() {
7
7
  return LANGUAGE_OPTIONS;
8
8
  }
9
+ function localeToApiLanguage(locale) {
10
+ const option = LANGUAGE_OPTIONS.find((o) => o.value === locale);
11
+ return option?.apiValue ?? locale;
12
+ }
9
13
  export {
10
14
  LANGUAGE_OPTIONS,
11
- buildLocaleOptions
15
+ buildLocaleOptions,
16
+ localeToApiLanguage
12
17
  };
13
18
  //# sourceMappingURL=locales.mjs.map
@@ -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 { 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":[]}
1
+ {"version":3,"sources":["../../../src/utils/intl/locales.ts"],"sourcesContent":["import { Locale } from '../../i18n/config';\r\n\r\nexport 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\r\nexport function localeToApiLanguage(locale: Locale): string {\r\n const option = LANGUAGE_OPTIONS.find((o) => o.value === locale);\r\n return option?.apiValue ?? locale;\r\n}\r\n"],"mappings":"AASO,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;AAEO,SAAS,oBAAoB,QAAwB;AAC1D,QAAM,SAAS,iBAAiB,KAAK,CAAC,MAAM,EAAE,UAAU,MAAM;AAC9D,SAAO,QAAQ,YAAY;AAC7B;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.779",
3
+ "version": "1.1.781",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -46,12 +46,6 @@
46
46
  "dist",
47
47
  "src"
48
48
  ],
49
- "scripts": {
50
- "build": "tsup",
51
- "dev": "tsup --watch",
52
- "typecheck": "tsc --noEmit",
53
- "prepublishOnly": "npm run build"
54
- },
55
49
  "keywords": [],
56
50
  "author": "",
57
51
  "license": "ISC",
@@ -137,5 +131,10 @@
137
131
  "@faker-js/faker": {
138
132
  "optional": true
139
133
  }
134
+ },
135
+ "scripts": {
136
+ "build": "tsup",
137
+ "dev": "tsup --watch",
138
+ "typecheck": "tsc --noEmit"
140
139
  }
141
- }
140
+ }
@@ -7,8 +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 type { Locale } from '../../../i18n/config';
10
+ import { isLocale, type Locale } from '../../../i18n/config';
11
11
  import { setLocaleCookie } from '../../../utils/intl/locale-cookie';
12
+ import { localeToApiLanguage } from '../../../utils/intl/locales';
12
13
  import { Button } from '../../ui/buttons/Button';
13
14
  import { Separator } from '../../ui/data-display/Separator';
14
15
  import { Toast } from '../../ui/feedback/Toast';
@@ -112,7 +113,7 @@ export function PreferencesSection({ onClose }: PreferencesSectionProps) {
112
113
  const doSave = async (data: PreferencesFormValues, accountFields: UpdateAccountRequest) => {
113
114
  setIsSaving(true);
114
115
  try {
115
- const apiLanguage = LANGUAGE_OPTIONS.find((o) => o.value === data.language)?.apiValue ?? data.language.toLowerCase();
116
+ const apiLanguage = isLocale(data.language) ? localeToApiLanguage(data.language) : data.language.toLowerCase();
116
117
  await updateAccountUser.mutateAsync({
117
118
  language: apiLanguage,
118
119
  receive_sms: data.receive_sms,
@@ -2,8 +2,10 @@
2
2
 
3
3
  import { ReactNode } from "react";
4
4
  import Image from "next/image";
5
+ import { useTranslations } from "next-intl";
5
6
  import { IconMenu2, IconX } from "@tabler/icons-react";
6
7
  import { ProfilePopover } from "./ProfilePopover";
8
+ import { GreatDomainIcon } from "./GreatDomainIcon";
7
9
  import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/overlay/Tooltip";
8
10
  import { useMobileNavbarSheet } from "../../store/useMobileNavbarSheet";
9
11
  import {
@@ -15,11 +17,13 @@ import type { ProfileMenuItem } from "./ProfilePopover";
15
17
 
16
18
  export interface AppMobileNavBarProps {
17
19
  /** Which app is currently active — controls which icon gets the indicator */
18
- activeApp?: "gapps" | "gpages";
20
+ activeApp?: "gapps" | "gpages" | "gdomain";
19
21
  /** Called when the GreatApps logo is clicked */
20
22
  onLogoClick?: () => void;
21
23
  /** Called when the app icon (e.g. GreatPages) is clicked */
22
24
  onAppIconClick?: () => void;
25
+ /** Called when the GreatDomain icon is clicked; without it the icon is not rendered (app flag) */
26
+ onDomainIconClick?: () => void;
23
27
  /** Extra slot rendered after the app icon (e.g. project selector) */
24
28
  extraLeftSlot?: ReactNode;
25
29
  menuItems?: ProfileMenuItem[];
@@ -30,10 +34,12 @@ export function AppMobileNavBar({
30
34
  activeApp,
31
35
  onLogoClick,
32
36
  onAppIconClick,
37
+ onDomainIconClick,
33
38
  extraLeftSlot,
34
39
  menuItems = [],
35
40
  showMenuToggle = true,
36
41
  }: AppMobileNavBarProps) {
42
+ const translate = useTranslations();
37
43
  const { isOpen, toggle } = useMobileNavbarSheet();
38
44
  const { whitelabel } = useWhitelabel();
39
45
  const isDefaultWl = useIsDefaultWhitelabel();
@@ -42,6 +48,7 @@ export function AppMobileNavBar({
42
48
 
43
49
  const isGappsActive = activeApp === "gapps";
44
50
  const isGpagesActive = activeApp === "gpages";
51
+ const isGdomainActive = activeApp === "gdomain";
45
52
 
46
53
  const wlIcon = whitelabel?.secondary_logo ? (
47
54
  <Image
@@ -80,9 +87,9 @@ export function AppMobileNavBar({
80
87
 
81
88
  return (
82
89
  <div className="fixed top-0 left-0 right-0 flex md:hidden items-center justify-between p-4 bg-white z-50 border-b border-gray-200">
83
- <div className="flex items-center gap-1.5">
90
+ <div className="flex items-center gap-1.5 min-w-0">
84
91
  {/* GreatApps logo */}
85
- <div className="relative">
92
+ <div className="relative shrink-0">
86
93
  <Tooltip>
87
94
  <TooltipTrigger asChild>
88
95
  <div
@@ -119,7 +126,7 @@ export function AppMobileNavBar({
119
126
  </div>
120
127
 
121
128
  {/* GreatPages icon */}
122
- <div className="relative">
129
+ <div className="relative shrink-0">
123
130
  <Tooltip>
124
131
  <TooltipTrigger asChild>
125
132
  <div
@@ -187,9 +194,86 @@ export function AppMobileNavBar({
187
194
  />
188
195
  </div>
189
196
 
190
- {extraLeftSlot}
197
+ {/* GreatDomain icon */}
198
+ {onDomainIconClick ? (
199
+ <div className="relative shrink-0">
200
+ <Tooltip>
201
+ <TooltipTrigger asChild>
202
+ <div
203
+ aria-label={
204
+ isDefaultWl
205
+ ? translate("common.layout.navbar.greatDomain")
206
+ : translate("common.layout.navbar.domains")
207
+ }
208
+ className={cn(
209
+ "size-10 rounded-[10px] flex items-center justify-center border-2 ring-2 transition-colors duration-300",
210
+ isGdomainActive
211
+ ? isDefaultWl
212
+ ? "bg-[#EDE9FE] border-white ring-[#C092FF]"
213
+ : "border-white ring-transparent"
214
+ : isDefaultWl
215
+ ? "hover:bg-gray-100 border-transparent ring-transparent"
216
+ : "border-transparent ring-transparent",
217
+ "cursor-pointer",
218
+ )}
219
+ style={
220
+ !isDefaultWl
221
+ ? {
222
+ backgroundColor: primaryColor,
223
+ boxShadow: isGdomainActive
224
+ ? `0 0 0 2px ${primaryColor}40`
225
+ : undefined,
226
+ opacity: !isGdomainActive ? 0.2 : undefined,
227
+ }
228
+ : undefined
229
+ }
230
+ onClick={onDomainIconClick}
231
+ >
232
+ {isDefaultWl ? (
233
+ <GreatDomainIcon active={isGdomainActive} />
234
+ ) : (
235
+ <svg
236
+ xmlns="http://www.w3.org/2000/svg"
237
+ width="24"
238
+ height="24"
239
+ viewBox="0 0 24 24"
240
+ fill="none"
241
+ stroke="white"
242
+ strokeWidth="2"
243
+ strokeLinecap="round"
244
+ strokeLinejoin="round"
245
+ >
246
+ <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
247
+ <path d="M3.6 9h16.8" />
248
+ <path d="M3.6 15h16.8" />
249
+ <path d="M11.5 3a17 17 0 0 0 0 18" />
250
+ <path d="M12.5 3a17 17 0 0 1 0 18" />
251
+ </svg>
252
+ )}
253
+ </div>
254
+ </TooltipTrigger>
255
+ <TooltipContent side="bottom">
256
+ {isDefaultWl
257
+ ? translate("common.layout.navbar.greatDomain")
258
+ : translate("common.layout.navbar.domains")}
259
+ </TooltipContent>
260
+ </Tooltip>
261
+ <div
262
+ className={cn(
263
+ "absolute -bottom-[17px] left-1/2 -translate-x-1/2 w-5 h-[3px] rounded-t-xl transition-opacity duration-300",
264
+ isDefaultWl ? "bg-[#984DFF]" : "",
265
+ isGdomainActive ? "opacity-100" : "opacity-0",
266
+ )}
267
+ style={!isDefaultWl ? { backgroundColor: primaryColor } : undefined}
268
+ />
269
+ </div>
270
+ ) : null}
271
+
272
+ {extraLeftSlot ? (
273
+ <div className="min-w-0 shrink [&>*]:max-w-full">{extraLeftSlot}</div>
274
+ ) : null}
191
275
  </div>
192
- <div className="flex items-center gap-1.5">
276
+ <div className="flex items-center gap-1.5 shrink-0">
193
277
  <ProfilePopover
194
278
  side="bottom"
195
279
  align="end"
@@ -8,8 +8,10 @@ import type { ProfileMenuItem } from "./ProfilePopover";
8
8
  export interface AppNavBarProps {
9
9
  logoHref: string;
10
10
  appIconHref: string;
11
+ /** Sem href o ícone do GreatDomain não é renderizado: é a flag do app. */
12
+ domainIconHref?: string;
11
13
  /** Which app is currently active — controls which icon gets the indicator */
12
- activeApp?: "gapps" | "gpages";
14
+ activeApp?: "gapps" | "gpages" | "gdomain";
13
15
  showExpandButton?: boolean;
14
16
  onExpandClick?: () => void;
15
17
  menuItems?: ProfileMenuItem[];
@@ -19,6 +21,7 @@ export interface AppNavBarProps {
19
21
  export function AppNavBar({
20
22
  logoHref,
21
23
  appIconHref,
24
+ domainIconHref,
22
25
  activeApp,
23
26
  showExpandButton = false,
24
27
  onExpandClick,
@@ -29,6 +32,7 @@ export function AppNavBar({
29
32
  <NavBar
30
33
  logoHref={logoHref}
31
34
  appIconHref={appIconHref}
35
+ domainIconHref={domainIconHref}
32
36
  activeApp={activeApp}
33
37
  showExpandButton={showExpandButton}
34
38
  onExpandClick={onExpandClick}
@@ -0,0 +1,43 @@
1
+ "use client";
2
+
3
+ import { cn } from "../../infra/utils/clsx";
4
+
5
+ type GreatDomainIconProps = {
6
+ /** Em repouso o círculo é #650CE4; só no estado ativo vira #984DFF. */
7
+ active?: boolean;
8
+ className?: string;
9
+ };
10
+
11
+ /**
12
+ * Glifo do GreatDomain — geometria exportada do Figma (node 5929:2700), 23×23.
13
+ * O círculo só troca de cor quando ativo. No hover o container ganha fundo cinza
14
+ * (igual ao GreatPages) e o glifo fica como está.
15
+ */
16
+ function GreatDomainIcon({ active, className }: GreatDomainIconProps) {
17
+ return (
18
+ <svg
19
+ width="23"
20
+ height="23"
21
+ viewBox="0 0 23 23"
22
+ fill="none"
23
+ xmlns="http://www.w3.org/2000/svg"
24
+ className={className}
25
+ aria-hidden="true"
26
+ >
27
+ <path
28
+ d="M11.8444 17.0777C11.8444 20.3487 9.19292 23.0003 5.92218 23.0003C2.65145 23.0003 0 20.3487 0 17.0777C0 13.8068 2.65145 11.1551 5.92218 11.1551C9.19292 11.1551 11.8444 13.8068 11.8444 17.0777Z"
29
+ className={cn(
30
+ "transition-colors duration-300",
31
+ active ? "fill-[#984DFF]" : "fill-[#650CE4]",
32
+ )}
33
+ />
34
+ <path
35
+ d="M11.8436 3.06666C11.8436 1.37299 13.2166 0 14.9103 0H19.9331C21.6267 0 22.9997 1.37299 22.9997 3.06666V19.9333C22.9997 21.6269 21.6267 22.9999 19.9331 22.9999H14.9103C13.2166 22.9999 11.8436 21.6269 11.8436 19.9333V3.06666Z"
36
+ fill="#C9B2FF"
37
+ />
38
+ </svg>
39
+ );
40
+ }
41
+
42
+ export { GreatDomainIcon };
43
+ export type { GreatDomainIconProps };