@greatapps/common 1.1.673 → 1.1.674
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/account/constants.mjs +4 -4
- package/dist/components/account/constants.mjs.map +1 -1
- package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
- package/dist/i18n/messages/en-us.mjs +43 -1
- package/dist/i18n/messages/en-us.mjs.map +1 -1
- package/dist/i18n/messages/es-es.mjs +43 -1
- package/dist/i18n/messages/es-es.mjs.map +1 -1
- package/dist/i18n/messages/pt-br.mjs +43 -1
- package/dist/i18n/messages/pt-br.mjs.map +1 -1
- package/dist/modules/images/utils/validate-image.mjs +8 -8
- package/dist/modules/images/utils/validate-image.mjs.map +1 -1
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs +45 -30
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
- package/dist/modules/subscriptions/utils/periodicity.mjs +20 -14
- package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/account/constants.ts +8 -5
- package/src/components/ui/feedback/CircularProgress.tsx +4 -0
- package/src/i18n/messages/en-us.ts +44 -0
- package/src/i18n/messages/es-es.ts +44 -0
- package/src/i18n/messages/pt-br.ts +44 -0
- package/src/modules/images/utils/validate-image.ts +23 -8
- package/src/modules/plans/utils/map-api-plan-to-ui.ts +80 -46
- package/src/modules/subscriptions/utils/periodicity.ts +29 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/i18n/messages/pt-br.ts"],"sourcesContent":["/**\n * Catálogo de traduções pt-br dos componentes da @greatapps/common.\n * Os apps consumidores mesclam este objeto sob o namespace `common`.\n *\n * Padrão modular: cada chave de primeiro nível é um **módulo** (um agrupamento por\n * componente/domínio). Para adicionar traduções, crie/edite o módulo correspondente aqui\n * e replique a mesma estrutura em `en-us.ts` e `es-es.ts`.\n *\n * pt-br é a fonte da verdade — os textos saem verbatim do que o componente já exibe hoje.\n */\nconst messages = {\n // Vocabulário global de ações (botões, comandos).\n actions: {\n save: 'Salvar',\n saveChanges: 'Salvar alterações',\n cancel: 'Cancelar',\n confirm: 'Confirmar',\n delete: 'Excluir',\n edit: 'Editar',\n close: 'Fechar',\n back: 'Voltar',\n continue: 'Continuar',\n add: 'Adicionar',\n remove: 'Remover',\n search: 'Buscar',\n loading: 'Carregando...',\n saving: 'Salvando...',\n sending: 'Enviando...',\n copy: 'Copiar',\n copied: 'Copiado',\n },\n\n // Mensagens de validação de formulário.\n validations: {\n required: 'Campo obrigatório',\n invalidEmail: 'E-mail inválido',\n invalidPhone: 'Telefone inválido',\n },\n\n // Componente: PreferencesSection.\n preferences: {\n title: 'Preferências',\n companyName: 'Nome da empresa',\n companyNamePlaceholder: 'Digite o nome da empresa',\n language: 'Idioma',\n languagePlaceholder: 'Selecione o idioma',\n languageSearch: 'Buscar idioma...',\n currency: 'Moeda',\n currencyPlaceholder: 'Selecione a moeda',\n currencySearch: 'Buscar moeda...',\n timeDisplay: 'Exibição hora',\n timezone: 'Fuso horário',\n timezonePlaceholder: 'Selecione o fuso horário',\n timezoneSearch: 'Buscar fuso horário...',\n timeFormat: 'Formato hora',\n timeFormatPlaceholder: 'Selecione o formato',\n timeFormatOptions: {\n h24: '24 horas',\n h12: '12 horas (AM/PM)',\n },\n savedSuccess: 'Preferências salvas com sucesso',\n saveError: 'Erro ao salvar preferências',\n },\n\n // Conta — modais e seções. `<b>` = trecho em negrito (rich text); `{count}` = interpolação.\n account: {\n deleteAccount: {\n title: 'Excluir conta',\n description:\n 'Esta ação é <b>irreversível</b>. Ao confirmar, sua conta e todos os seus dados serão excluídos.',\n reasonLabel: 'Motivo do cancelamento',\n reasonPlaceholder: 'Selecione',\n descriptionLabel: 'Descreva o que levou a tomar essa decisão',\n descriptionPlaceholder: 'Explique sua decisão...',\n charactersCount: '{count}/400 caracteres',\n passwordLabel: 'Senha',\n passwordPlaceholder: 'Informe sua senha',\n submit: 'Excluir conta',\n requiredFields: 'Preencha todos os campos obrigatórios',\n reasons: {\n noFeature: 'A ferramenta não possui uma função que eu preciso',\n technical: 'Encontrei problemas técnicos ou erros no sistema',\n support: 'Tive problemas com o suporte ou atendimento',\n updates: 'As atualizações demoram mais do que o esperado',\n temporary: 'O cancelamento é temporário',\n other: 'Outro motivo',\n },\n },\n confirmDelete: {\n title: 'Uma pena te ver ir!',\n warning:\n 'Todas suas <b>{count} páginas</b> serão deletadas permanentemente. Essa ação é <b>irreversível!</b>',\n sessionExpired: 'Sessão expirada. Preencha os campos novamente.',\n success: 'Conta excluída com sucesso',\n error: 'Erro ao excluir. Tente novamente.',\n keepAccount: 'Manter minha conta',\n deleteAnyway: 'Excluir mesmo assim',\n deleting: 'Excluindo...',\n },\n cantDelete: {\n title: 'Não é possível excluir a conta',\n description:\n 'Você tem uma assinatura ativa. Para excluir sua conta, <b>primeiro cancele a assinatura</b> na página Assinatura e depois tente novamente.',\n confirm: 'Ok, entendi',\n goToSubscription: 'Ir para assinatura',\n },\n twoFactor: {\n title: 'Autenticação de dois fatores',\n instructions:\n 'Instale um aplicativo autenticador no seu celular (ex.: <link>Google Authenticator</link>), escaneie o QR Code ao lado ou copie a chave no aplicativo e, em seguida, digite o código de 6 dígitos gerado para continuar.',\n qrAlt: 'QR Code para autenticação de dois fatores',\n retry: 'Tentar novamente',\n pasteDigits: 'Cole os 6 dígitos abaixo',\n activating: 'Ativando...',\n activate: 'Ativar autenticação',\n recoveryTitle: 'Códigos de segurança',\n recoveryHeading: 'Salve estes códigos de recuperação de emergência',\n recoveryText1:\n 'Se você perder acesso ao seu telefone, não será possível fazer login em sua conta sem um código de dois fatores.',\n recoveryText2: 'Imprima, copie ou escreva em um local seguro os códigos abaixo.',\n copyCodes: 'Copiar códigos',\n finish: 'Finalizar',\n codesCopied: 'Códigos copiados com sucesso',\n generateError: 'Erro ao gerar QR Code. Tente novamente.',\n confirmError: 'Erro ao confirmar código. Tente novamente.',\n disableTitle: 'Desabilitar autenticação 2FA',\n disableDescription:\n 'Informe o código de 6 dígitos do seu aplicativo autenticador para confirmar a desativação.',\n authenticatorCode: 'Código do autenticador',\n disabling: 'Desabilitando...',\n disable: 'Desabilitar 2FA',\n disabledSuccess: 'Autenticação de dois fatores desabilitada',\n disableError: 'Erro ao desabilitar 2FA. Tente novamente.',\n invalidCode: 'Código inválido',\n codeResent: 'Código reenviado',\n resendError: 'Erro ao reenviar código. Tente novamente.',\n },\n profile: {\n title: 'Meu perfil',\n avatarAlt: 'Foto do usuário',\n changePhoto: 'Alterar foto',\n name: 'Nome',\n namePlaceholder: 'Digite seu nome',\n lastName: 'Sobrenome',\n lastNamePlaceholder: 'Digite seu sobrenome',\n gender: 'Gênero',\n genderPlaceholder: 'Selecione seu gênero',\n genderOptions: {\n male: 'Masculino',\n female: 'Feminino',\n },\n phone: 'Telefone',\n change: 'Alterar',\n accessData: 'Dados de acesso',\n email: 'E-mail',\n savedSuccess: 'Perfil atualizado com sucesso',\n saveError: 'Erro ao atualizar perfil',\n },\n otp: {\n validationCode: 'Código de validação',\n incorrectCode: 'Código incorreto',\n resend: 'Reenviar código',\n resendIn: 'Reenviar em <b>{time}</b>',\n validating: 'Validando...',\n },\n changeEmail: {\n title: 'Alterar e-mail',\n confirm: 'Alterar e-mail',\n sentCodeTo: 'Enviamos um código de validação para o E-mail <b>{email}.</b>',\n updateTitle: 'Atualizar E-mail de contato',\n updateDescription: 'Informe o seu novo E-mail para manter seu contato atualizado.',\n newEmail: 'Novo e-mail',\n newEmailPlaceholder: 'Digite seu novo e-mail',\n emailChanged: 'E-mail alterado com sucesso',\n emailExistsError: 'E-mail já existente ou ocorreu um erro. Tente novamente mais tarde.',\n },\n changePhone: {\n titleEdit: 'Alterar telefone',\n titleAdd: 'Adicionar telefone',\n sentCodeTo: 'Enviamos um código de validação para o número atual <b>{phone}.</b>',\n confirm: 'Alterar telefone',\n updateTitle: 'Atualizar telefone de contato',\n addTitle: 'Adicionar telefone de contato',\n updateDescription: 'Informe o novo número para manter seu contato atualizado.',\n addDescription: 'Informe seu número de telefone para contato.',\n newNumber: 'Novo número',\n numberLabel: 'Número de telefone',\n phoneChanged: 'Telefone alterado',\n phoneAdded: 'Telefone adicionado',\n invalidNumber: 'Número de telefone inválido',\n saveError: 'Ocorreu um erro ao salvar o telefone. Tente novamente mais tarde.',\n numberExistsError: 'Número já existente ou ocorreu um erro. Tente novamente mais tarde.',\n },\n security: {\n title: 'Segurança',\n googleLinkedTitle: 'Conta Google vinculada',\n googleLinkedDescription:\n 'Sua conta está vinculada ao Google. Se desvincular, use \"Esqueci minha senha\" para redefinir uma senha de acesso por e-mail.',\n unlinking: 'Desvinculando...',\n unlinkGoogle: 'Desvincular Google',\n unlinkError: 'Erro ao desvincular conta Google.',\n deleteAccountDescription:\n 'Esta ação é permanente e não pode ser desfeita. Todos os seus dados, projetos e configurações serão removidos definitivamente.',\n deleteMyAccount: 'Excluir minha conta',\n },\n token: {\n title: 'Token da conta',\n label: 'Token',\n copySuccess: 'Token copiado com sucesso',\n copyError: 'Não foi possível copiar o token',\n info: 'Este token é exclusivo da sua conta e permite acesso à API. Não compartilhe com terceiros.',\n docsLink: 'Acessar a documentação',\n },\n changePassword: {\n title: 'Alterar senha',\n currentPassword: 'Senha atual',\n currentPasswordPlaceholder: 'Digite sua senha atual',\n newPassword: 'Nova senha',\n newPasswordPlaceholder: 'Digite sua nova senha',\n submit: 'Salvar nova senha',\n changeError: 'Erro ao alterar senha',\n changedSuccess: 'Senha alterada com sucesso',\n genericError: 'Erro ao alterar senha. Tente novamente.',\n },\n globalPreferences: {\n title: 'Alterar preferências globais',\n srDescription: 'Confirmação de alteração de preferências globais da conta',\n warning:\n 'Você está alterando configurações que impactam <b>todos os usuários da conta</b>. Deseja confirmar?',\n },\n configurations: {\n title: 'Configurações',\n },\n },\n\n // Modais de créditos de IA.\n credits: {\n buy: {\n title: 'Comprar créditos de IA',\n externalTitle: 'Créditos de IA',\n externalDescription: 'Para adquirir créditos de IA, acesse sua área de assinatura.',\n externalButton: 'Acessar área de assinatura',\n creditsOptionLabel: '{credits} créditos de IA',\n creditsOptionDisplayValue: '{credits} créditos de IA',\n paymentOnConfirm: 'O pagamento será processado no momento da confirmação.',\n nextInvoiceChanges: 'As alterações entrarão em vigor a partir da sua próxima fatura.',\n defaultPrice: 'Padrão',\n immediateCharge: 'Cobrança imediata',\n totalPlanValue: 'Valor total do plano',\n confirmAndPay: 'Confirmar e pagar',\n creditsChangedToast: 'Créditos de IA alterados para {credits}',\n },\n disabled: {\n title: 'Compra de créditos indisponível',\n descriptionLine1: 'Apenas administradores e proprietários podem comprar créditos de IA.',\n descriptionLine2:\n 'Peça a um administrador ou proprietário da conta para adquirir mais créditos.',\n understood: 'Entendi',\n },\n paidPlanRequired: {\n defaultTitle: 'Recurso disponível em planos pagos',\n defaultDescription: 'Para acessar este recurso, faça upgrade para um plano pago',\n knowPlans: 'Conhecer planos',\n },\n },\n\n // Cartões: adicionar, formulário, excluir, não-pode-excluir, item, info de pagamento.\n cards: {\n add: {\n stepBilling: 'Cobrança',\n stepCard: 'Cartão',\n externalTitle: 'Gerenciamento de cartões indisponível',\n externalDescription: 'Acesse sua área de assinatura para gerenciar formas de pagamento.',\n externalButton: 'Acessar área de assinatura',\n title: 'Adicionar cartão',\n billingHeading: 'Adicione suas informações de cobrança',\n cardHeading: 'Adicione informações do seu cartão',\n authenticating: 'Autenticando...',\n submitting: 'Adicionando cartão...',\n submit: 'Adicionar cartão',\n errorInitAuth: 'Não foi possível iniciar a autenticação do cartão, tente novamente.',\n errorAuth: 'Falha na autenticação do cartão.',\n errorAuthStatus: 'Autenticação não concluída (status: {status}).',\n statusUnknown: 'desconhecido',\n successToast: 'Cartão adicionado com sucesso.',\n errorSave: 'Não foi possível salvar o seu novo cartão, tente novamente.',\n },\n form: {\n nameOnCard: 'Nome impresso no cartão',\n typeHere: 'Digite aqui',\n cardNumber: 'Número do cartão',\n cardExpiry: 'Data de validade',\n cardCvc: 'CVC',\n country: 'País',\n select: 'Selecione',\n personType: 'Tipo de pessoa',\n personTypePf: 'Pessoa física',\n personTypePj: 'Pessoa jurídica',\n cpf: 'CPF',\n cnpj: 'CNPJ',\n fullName: 'Nome completo',\n cep: 'CEP',\n street: 'Endereço',\n streetNumber: 'Número',\n city: 'Cidade',\n state: 'UF',\n neighborhood: 'Bairro',\n complement: 'Complemento',\n cardNumberRequired: 'Número do cartão é obrigatório',\n cardExpiryRequired: 'Data de validade é obrigatória',\n cardCvcRequired: 'Código de segurança é obrigatório',\n },\n delete: {\n title: 'Excluir cartão',\n description: 'Deseja realmente excluir o cartão:',\n confirmLabel: 'Digite EXCLUIR abaixo',\n confirmPlaceholder: 'EXCLUIR',\n deleting: 'Excluindo...',\n successToast: 'O cartão •••• {digits} foi excluído com sucesso',\n errorToast: 'Não foi possível excluir o cartão',\n },\n cannotDelete: {\n title: 'Não é possível excluir este cartão',\n description: 'Este cartão está em uso e tem uma assinatura ativa vinculada a ele. Selecione outro cartão como padrão ou adicione um novo.',\n selectDefault: 'Selecione um cartão como padrão:',\n addNewCard: 'Adicionar novo cartão',\n errorUpdateCard: 'Erro ao atualizar cartão da assinatura',\n },\n item: {\n defaultBadge: 'Padrão',\n makeDefault: 'Tornar padrão',\n setDefaultSuccess: 'Cartão definido como padrão',\n setDefaultError: 'Erro ao definir cartão padrão',\n },\n paymentInfo: {\n email: 'E-mail',\n payment: 'Pagamento',\n addCard: 'Adicionar cartão',\n selectPaymentMethod: 'Selecione a forma de pagamento',\n manageCards: 'Gerenciar cartões',\n newPaymentMethod: 'Nova forma de pagamento',\n },\n },\n\n // Componentes de navegação: banners de assinatura, seletor de projeto, links de rodapé, créditos, plano.\n navigation: {\n banners: {\n cancelled: {\n message: 'Assinatura cancelada! Suas páginas foram retiradas do ar.',\n choosePlan: 'Escolher um novo plano',\n },\n overdue: {\n message: 'Sua assinatura está atrasada e suas páginas podem ser retiradas do ar a qualquer momento.',\n details: 'Detalhes',\n },\n pending: {\n message: 'Sua assinatura foi cancelada, você possui até {limitDate} com suas páginas online.',\n reactivate: 'Reativar assinatura',\n },\n upcoming: {\n message: 'Fatura em aberto. Pague até {dueDate} para evitar a suspensão das suas páginas.',\n details: 'Detalhes',\n },\n },\n projectSelector: {\n title: 'Projetos',\n searchPlaceholder: 'Busque aqui',\n emptyLine1: 'Nenhum projeto encontrado.',\n emptyLine2: 'Crie um projeto para começar.',\n noResults: 'Nenhum resultado encontrado.',\n manageProjects: 'Gerenciar projetos',\n },\n bottomLinks: {\n news: 'Novidades',\n helpCenter: 'Central de ajuda',\n sendSuggestions: 'Enviar sugestões',\n },\n creditsCard: {\n label: 'Créditos usados',\n },\n planCard: {\n knowPlans: 'Conheça os planos',\n },\n },\n\n // Nomes dos idiomas exibidos no seletor.\n languages: {\n 'pt-br': 'Português (Brasil)',\n 'en-us': 'Inglês (EUA)',\n 'es-es': 'Espanhol',\n },\n\n // Componentes de formulário e entrada.\n forms: {\n combobox: {\n placeholder: 'Selecione uma opção',\n searchPlaceholder: 'Buscar...',\n emptyMessage: 'Nenhuma opção encontrada.',\n },\n datePicker: {\n placeholder: 'Selecione a data',\n },\n dateRangePicker: {\n placeholder: 'Selecione o período',\n },\n phoneInput: {\n optional: '(Opcional)',\n searchPlaceholder: 'Buscar país...',\n emptyMessage: 'Nenhum país encontrado',\n },\n select: {\n placeholder: 'Selecione uma opção',\n optional: '(Opcional)',\n },\n copyButton: {\n tooltipDefault: 'Copiar link',\n successDefault: 'Link copiado',\n errorMessage: 'Não foi possível copiar o link',\n },\n circularProgress: {\n ariaLabel: 'Progresso de exportação',\n },\n },\n\n // Componentes: ImageCropModal, ImageTooSmallModal.\n imageUpload: {\n cropTitle: 'Ajustar imagem',\n cropHint: 'Arraste para ajustar a área de corte',\n cropAlt: 'Crop',\n tooSmallTitleWithDimension: 'Foto menor que {dimensionText}',\n tooSmallTitleGeneric: 'Foto muito pequena',\n tooSmallBodyFileWithDimension: 'O arquivo \"{fileName}\" é menor que {dimensionText}. Faça envio de uma imagem com pelo menos {dimensionText} para continuar.',\n tooSmallBodyFileGeneric: 'O arquivo \"{fileName}\" é menor que o tamanho mínimo exigido. Faça envio de uma imagem maior para continuar.',\n tooSmallBodyNoFileWithDimension: 'A imagem selecionada é menor que {dimensionText}. Faça envio de uma imagem com pelo menos {dimensionText} para continuar.',\n tooSmallBodyNoFileGeneric: 'A imagem selecionada é menor que o tamanho mínimo exigido. Faça envio de uma imagem maior para continuar.',\n sendAnother: 'Enviar outra',\n },\n\n // Componentes: NotificationPageContent (Notifications.tsx), NotificationsPopover.tsx.\n notifications: {\n page: {\n title: 'Notificações',\n subtitle: 'Tenha controle total sobre páginas, experiências e conversões.',\n markAllReadDesktop: 'Marcar todos como lidos',\n markAllReadMobile: 'Marcar como lidos',\n tabAll: 'Todas as notificações',\n tabUnread: 'Não lidas',\n details: 'Detalhes',\n empty: 'Nenhuma notificação encontrada.',\n markAllSuccess: 'Todas as notificações foram marcadas como lidas',\n markAllError: 'Erro ao marcar notificações como lidas',\n },\n popover: {\n title: 'Últimas notificações',\n empty: 'Sem notificações por enquanto',\n viewAll: 'Todas as notificações',\n },\n },\n\n // Componentes: NavBar.tsx, ProfilePopover.tsx, UsersSelectorPopover.tsx.\n layout: {\n navbar: {\n expandMenu: 'Expandir menu',\n greatPages: 'GreatPages',\n pages: 'Páginas',\n },\n profile: {\n usedCredits: 'Créditos usados',\n loggingOut: 'Saindo da sua conta...',\n logout: 'Sair',\n },\n usersSelector: {\n title: 'Usuários',\n add: 'Adicionar',\n searchPlaceholder: 'Busque aqui',\n empty: 'Nenhum usuário encontrado.',\n noResults: 'Nenhum resultado encontrado.',\n addToProject: 'Adicionar ao projeto',\n removeFromProject: 'Remover do projeto',\n manageTeam: 'Gerenciar equipe',\n },\n },\n\n // Componente: NotFoundPage.tsx.\n notFound: {\n title: 'Página não foi encontrada!',\n description: 'A página que você está procurando não existe. Verifique se digitou corretamente o link que está procurando.',\n backToHome: 'Voltar para o início',\n },\n} as const;\n\nexport default messages;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/i18n/messages/pt-br.ts"],"sourcesContent":["/**\n * Catálogo de traduções pt-br dos componentes da @greatapps/common.\n * Os apps consumidores mesclam este objeto sob o namespace `common`.\n *\n * Padrão modular: cada chave de primeiro nível é um **módulo** (um agrupamento por\n * componente/domínio). Para adicionar traduções, crie/edite o módulo correspondente aqui\n * e replique a mesma estrutura em `en-us.ts` e `es-es.ts`.\n *\n * pt-br é a fonte da verdade — os textos saem verbatim do que o componente já exibe hoje.\n */\nconst messages = {\n // Vocabulário global de ações (botões, comandos).\n actions: {\n save: 'Salvar',\n saveChanges: 'Salvar alterações',\n cancel: 'Cancelar',\n confirm: 'Confirmar',\n delete: 'Excluir',\n edit: 'Editar',\n close: 'Fechar',\n back: 'Voltar',\n continue: 'Continuar',\n add: 'Adicionar',\n remove: 'Remover',\n search: 'Buscar',\n loading: 'Carregando...',\n saving: 'Salvando...',\n sending: 'Enviando...',\n copy: 'Copiar',\n copied: 'Copiado',\n },\n\n // Mensagens de validação de formulário.\n validations: {\n required: 'Campo obrigatório',\n invalidEmail: 'E-mail inválido',\n invalidPhone: 'Telefone inválido',\n },\n\n // Componente: PreferencesSection.\n preferences: {\n title: 'Preferências',\n companyName: 'Nome da empresa',\n companyNamePlaceholder: 'Digite o nome da empresa',\n language: 'Idioma',\n languagePlaceholder: 'Selecione o idioma',\n languageSearch: 'Buscar idioma...',\n currency: 'Moeda',\n currencyPlaceholder: 'Selecione a moeda',\n currencySearch: 'Buscar moeda...',\n timeDisplay: 'Exibição hora',\n timezone: 'Fuso horário',\n timezonePlaceholder: 'Selecione o fuso horário',\n timezoneSearch: 'Buscar fuso horário...',\n timeFormat: 'Formato hora',\n timeFormatPlaceholder: 'Selecione o formato',\n timeFormatOptions: {\n h24: '24 horas',\n h12: '12 horas (AM/PM)',\n },\n savedSuccess: 'Preferências salvas com sucesso',\n saveError: 'Erro ao salvar preferências',\n },\n\n // Conta — modais e seções. `<b>` = trecho em negrito (rich text); `{count}` = interpolação.\n account: {\n notificationTypes: {\n projectUpdates: 'Atualizações de projetos',\n securityAlerts: 'Alertas de segurança',\n planBilling: 'Mudanças no plano ou faturamento',\n scheduledMaintenance: 'Manutenções programadas',\n },\n deleteAccount: {\n title: 'Excluir conta',\n description:\n 'Esta ação é <b>irreversível</b>. Ao confirmar, sua conta e todos os seus dados serão excluídos.',\n reasonLabel: 'Motivo do cancelamento',\n reasonPlaceholder: 'Selecione',\n descriptionLabel: 'Descreva o que levou a tomar essa decisão',\n descriptionPlaceholder: 'Explique sua decisão...',\n charactersCount: '{count}/400 caracteres',\n passwordLabel: 'Senha',\n passwordPlaceholder: 'Informe sua senha',\n submit: 'Excluir conta',\n requiredFields: 'Preencha todos os campos obrigatórios',\n reasons: {\n noFeature: 'A ferramenta não possui uma função que eu preciso',\n technical: 'Encontrei problemas técnicos ou erros no sistema',\n support: 'Tive problemas com o suporte ou atendimento',\n updates: 'As atualizações demoram mais do que o esperado',\n temporary: 'O cancelamento é temporário',\n other: 'Outro motivo',\n },\n },\n confirmDelete: {\n title: 'Uma pena te ver ir!',\n warning:\n 'Todas suas <b>{count} páginas</b> serão deletadas permanentemente. Essa ação é <b>irreversível!</b>',\n sessionExpired: 'Sessão expirada. Preencha os campos novamente.',\n success: 'Conta excluída com sucesso',\n error: 'Erro ao excluir. Tente novamente.',\n keepAccount: 'Manter minha conta',\n deleteAnyway: 'Excluir mesmo assim',\n deleting: 'Excluindo...',\n },\n cantDelete: {\n title: 'Não é possível excluir a conta',\n description:\n 'Você tem uma assinatura ativa. Para excluir sua conta, <b>primeiro cancele a assinatura</b> na página Assinatura e depois tente novamente.',\n confirm: 'Ok, entendi',\n goToSubscription: 'Ir para assinatura',\n },\n twoFactor: {\n title: 'Autenticação de dois fatores',\n instructions:\n 'Instale um aplicativo autenticador no seu celular (ex.: <link>Google Authenticator</link>), escaneie o QR Code ao lado ou copie a chave no aplicativo e, em seguida, digite o código de 6 dígitos gerado para continuar.',\n qrAlt: 'QR Code para autenticação de dois fatores',\n retry: 'Tentar novamente',\n pasteDigits: 'Cole os 6 dígitos abaixo',\n activating: 'Ativando...',\n activate: 'Ativar autenticação',\n recoveryTitle: 'Códigos de segurança',\n recoveryHeading: 'Salve estes códigos de recuperação de emergência',\n recoveryText1:\n 'Se você perder acesso ao seu telefone, não será possível fazer login em sua conta sem um código de dois fatores.',\n recoveryText2: 'Imprima, copie ou escreva em um local seguro os códigos abaixo.',\n copyCodes: 'Copiar códigos',\n finish: 'Finalizar',\n codesCopied: 'Códigos copiados com sucesso',\n generateError: 'Erro ao gerar QR Code. Tente novamente.',\n confirmError: 'Erro ao confirmar código. Tente novamente.',\n disableTitle: 'Desabilitar autenticação 2FA',\n disableDescription:\n 'Informe o código de 6 dígitos do seu aplicativo autenticador para confirmar a desativação.',\n authenticatorCode: 'Código do autenticador',\n disabling: 'Desabilitando...',\n disable: 'Desabilitar 2FA',\n disabledSuccess: 'Autenticação de dois fatores desabilitada',\n disableError: 'Erro ao desabilitar 2FA. Tente novamente.',\n invalidCode: 'Código inválido',\n codeResent: 'Código reenviado',\n resendError: 'Erro ao reenviar código. Tente novamente.',\n },\n profile: {\n title: 'Meu perfil',\n avatarAlt: 'Foto do usuário',\n changePhoto: 'Alterar foto',\n name: 'Nome',\n namePlaceholder: 'Digite seu nome',\n lastName: 'Sobrenome',\n lastNamePlaceholder: 'Digite seu sobrenome',\n gender: 'Gênero',\n genderPlaceholder: 'Selecione seu gênero',\n genderOptions: {\n male: 'Masculino',\n female: 'Feminino',\n },\n phone: 'Telefone',\n change: 'Alterar',\n accessData: 'Dados de acesso',\n email: 'E-mail',\n savedSuccess: 'Perfil atualizado com sucesso',\n saveError: 'Erro ao atualizar perfil',\n },\n otp: {\n validationCode: 'Código de validação',\n incorrectCode: 'Código incorreto',\n resend: 'Reenviar código',\n resendIn: 'Reenviar em <b>{time}</b>',\n validating: 'Validando...',\n },\n changeEmail: {\n title: 'Alterar e-mail',\n confirm: 'Alterar e-mail',\n sentCodeTo: 'Enviamos um código de validação para o E-mail <b>{email}.</b>',\n updateTitle: 'Atualizar E-mail de contato',\n updateDescription: 'Informe o seu novo E-mail para manter seu contato atualizado.',\n newEmail: 'Novo e-mail',\n newEmailPlaceholder: 'Digite seu novo e-mail',\n emailChanged: 'E-mail alterado com sucesso',\n emailExistsError: 'E-mail já existente ou ocorreu um erro. Tente novamente mais tarde.',\n },\n changePhone: {\n titleEdit: 'Alterar telefone',\n titleAdd: 'Adicionar telefone',\n sentCodeTo: 'Enviamos um código de validação para o número atual <b>{phone}.</b>',\n confirm: 'Alterar telefone',\n updateTitle: 'Atualizar telefone de contato',\n addTitle: 'Adicionar telefone de contato',\n updateDescription: 'Informe o novo número para manter seu contato atualizado.',\n addDescription: 'Informe seu número de telefone para contato.',\n newNumber: 'Novo número',\n numberLabel: 'Número de telefone',\n phoneChanged: 'Telefone alterado',\n phoneAdded: 'Telefone adicionado',\n invalidNumber: 'Número de telefone inválido',\n saveError: 'Ocorreu um erro ao salvar o telefone. Tente novamente mais tarde.',\n numberExistsError: 'Número já existente ou ocorreu um erro. Tente novamente mais tarde.',\n },\n security: {\n title: 'Segurança',\n googleLinkedTitle: 'Conta Google vinculada',\n googleLinkedDescription:\n 'Sua conta está vinculada ao Google. Se desvincular, use \"Esqueci minha senha\" para redefinir uma senha de acesso por e-mail.',\n unlinking: 'Desvinculando...',\n unlinkGoogle: 'Desvincular Google',\n unlinkError: 'Erro ao desvincular conta Google.',\n deleteAccountDescription:\n 'Esta ação é permanente e não pode ser desfeita. Todos os seus dados, projetos e configurações serão removidos definitivamente.',\n deleteMyAccount: 'Excluir minha conta',\n },\n token: {\n title: 'Token da conta',\n label: 'Token',\n copySuccess: 'Token copiado com sucesso',\n copyError: 'Não foi possível copiar o token',\n info: 'Este token é exclusivo da sua conta e permite acesso à API. Não compartilhe com terceiros.',\n docsLink: 'Acessar a documentação',\n },\n changePassword: {\n title: 'Alterar senha',\n currentPassword: 'Senha atual',\n currentPasswordPlaceholder: 'Digite sua senha atual',\n newPassword: 'Nova senha',\n newPasswordPlaceholder: 'Digite sua nova senha',\n submit: 'Salvar nova senha',\n changeError: 'Erro ao alterar senha',\n changedSuccess: 'Senha alterada com sucesso',\n genericError: 'Erro ao alterar senha. Tente novamente.',\n },\n globalPreferences: {\n title: 'Alterar preferências globais',\n srDescription: 'Confirmação de alteração de preferências globais da conta',\n warning:\n 'Você está alterando configurações que impactam <b>todos os usuários da conta</b>. Deseja confirmar?',\n },\n configurations: {\n title: 'Configurações',\n },\n },\n\n // Modais de créditos de IA.\n credits: {\n buy: {\n title: 'Comprar créditos de IA',\n externalTitle: 'Créditos de IA',\n externalDescription: 'Para adquirir créditos de IA, acesse sua área de assinatura.',\n externalButton: 'Acessar área de assinatura',\n creditsOptionLabel: '{credits} créditos de IA',\n creditsOptionDisplayValue: '{credits} créditos de IA',\n paymentOnConfirm: 'O pagamento será processado no momento da confirmação.',\n nextInvoiceChanges: 'As alterações entrarão em vigor a partir da sua próxima fatura.',\n defaultPrice: 'Padrão',\n immediateCharge: 'Cobrança imediata',\n totalPlanValue: 'Valor total do plano',\n confirmAndPay: 'Confirmar e pagar',\n creditsChangedToast: 'Créditos de IA alterados para {credits}',\n },\n disabled: {\n title: 'Compra de créditos indisponível',\n descriptionLine1: 'Apenas administradores e proprietários podem comprar créditos de IA.',\n descriptionLine2:\n 'Peça a um administrador ou proprietário da conta para adquirir mais créditos.',\n understood: 'Entendi',\n },\n paidPlanRequired: {\n defaultTitle: 'Recurso disponível em planos pagos',\n defaultDescription: 'Para acessar este recurso, faça upgrade para um plano pago',\n knowPlans: 'Conhecer planos',\n },\n },\n\n // Cartões: adicionar, formulário, excluir, não-pode-excluir, item, info de pagamento.\n cards: {\n add: {\n stepBilling: 'Cobrança',\n stepCard: 'Cartão',\n externalTitle: 'Gerenciamento de cartões indisponível',\n externalDescription: 'Acesse sua área de assinatura para gerenciar formas de pagamento.',\n externalButton: 'Acessar área de assinatura',\n title: 'Adicionar cartão',\n billingHeading: 'Adicione suas informações de cobrança',\n cardHeading: 'Adicione informações do seu cartão',\n authenticating: 'Autenticando...',\n submitting: 'Adicionando cartão...',\n submit: 'Adicionar cartão',\n errorInitAuth: 'Não foi possível iniciar a autenticação do cartão, tente novamente.',\n errorAuth: 'Falha na autenticação do cartão.',\n errorAuthStatus: 'Autenticação não concluída (status: {status}).',\n statusUnknown: 'desconhecido',\n successToast: 'Cartão adicionado com sucesso.',\n errorSave: 'Não foi possível salvar o seu novo cartão, tente novamente.',\n },\n form: {\n nameOnCard: 'Nome impresso no cartão',\n typeHere: 'Digite aqui',\n cardNumber: 'Número do cartão',\n cardExpiry: 'Data de validade',\n cardCvc: 'CVC',\n country: 'País',\n select: 'Selecione',\n personType: 'Tipo de pessoa',\n personTypePf: 'Pessoa física',\n personTypePj: 'Pessoa jurídica',\n cpf: 'CPF',\n cnpj: 'CNPJ',\n fullName: 'Nome completo',\n cep: 'CEP',\n street: 'Endereço',\n streetNumber: 'Número',\n city: 'Cidade',\n state: 'UF',\n neighborhood: 'Bairro',\n complement: 'Complemento',\n cardNumberRequired: 'Número do cartão é obrigatório',\n cardExpiryRequired: 'Data de validade é obrigatória',\n cardCvcRequired: 'Código de segurança é obrigatório',\n },\n delete: {\n title: 'Excluir cartão',\n description: 'Deseja realmente excluir o cartão:',\n confirmLabel: 'Digite EXCLUIR abaixo',\n confirmPlaceholder: 'EXCLUIR',\n deleting: 'Excluindo...',\n successToast: 'O cartão •••• {digits} foi excluído com sucesso',\n errorToast: 'Não foi possível excluir o cartão',\n },\n cannotDelete: {\n title: 'Não é possível excluir este cartão',\n description: 'Este cartão está em uso e tem uma assinatura ativa vinculada a ele. Selecione outro cartão como padrão ou adicione um novo.',\n selectDefault: 'Selecione um cartão como padrão:',\n addNewCard: 'Adicionar novo cartão',\n errorUpdateCard: 'Erro ao atualizar cartão da assinatura',\n },\n item: {\n defaultBadge: 'Padrão',\n makeDefault: 'Tornar padrão',\n setDefaultSuccess: 'Cartão definido como padrão',\n setDefaultError: 'Erro ao definir cartão padrão',\n },\n paymentInfo: {\n email: 'E-mail',\n payment: 'Pagamento',\n addCard: 'Adicionar cartão',\n selectPaymentMethod: 'Selecione a forma de pagamento',\n manageCards: 'Gerenciar cartões',\n newPaymentMethod: 'Nova forma de pagamento',\n },\n },\n\n // Componentes de navegação: banners de assinatura, seletor de projeto, links de rodapé, créditos, plano.\n navigation: {\n banners: {\n cancelled: {\n message: 'Assinatura cancelada! Suas páginas foram retiradas do ar.',\n choosePlan: 'Escolher um novo plano',\n },\n overdue: {\n message: 'Sua assinatura está atrasada e suas páginas podem ser retiradas do ar a qualquer momento.',\n details: 'Detalhes',\n },\n pending: {\n message: 'Sua assinatura foi cancelada, você possui até {limitDate} com suas páginas online.',\n reactivate: 'Reativar assinatura',\n },\n upcoming: {\n message: 'Fatura em aberto. Pague até {dueDate} para evitar a suspensão das suas páginas.',\n details: 'Detalhes',\n },\n },\n projectSelector: {\n title: 'Projetos',\n searchPlaceholder: 'Busque aqui',\n emptyLine1: 'Nenhum projeto encontrado.',\n emptyLine2: 'Crie um projeto para começar.',\n noResults: 'Nenhum resultado encontrado.',\n manageProjects: 'Gerenciar projetos',\n },\n bottomLinks: {\n news: 'Novidades',\n helpCenter: 'Central de ajuda',\n sendSuggestions: 'Enviar sugestões',\n },\n creditsCard: {\n label: 'Créditos usados',\n },\n planCard: {\n knowPlans: 'Conheça os planos',\n },\n },\n\n // Nomes dos idiomas exibidos no seletor.\n // Planos: features e main features (mapApiPlanToUiPlan).\n plans: {\n features: {\n unlimitedVisits: 'Visitas ilimitadas',\n unlimitedLeads: 'Leads ilimitadas',\n sharePages: 'Compartilhar páginas',\n hosting: 'Hospedagem inclusa',\n freeTemplates: 'Templates gratuitos',\n onboarding: 'Reunião de Onboarding',\n projectManagement: 'Gestão de projetos',\n },\n mainFeatures: {\n pagesUnlimited: 'Páginas ilimitadas',\n pageSingular: '1 página',\n pagesPlural: '{count} páginas',\n domainsUnlimited: 'Domínios ilimitados',\n domainSingular: '1 domínio externo',\n domainsPlural: '{count} domínios externos',\n usersUnlimited: 'Usuários ilimitados',\n },\n },\n\n // Periodicidade de cobrança.\n periodicity: {\n monthly: 'Mensal',\n semiannual: 'Semestral',\n annual: 'Anual',\n suffixMonthly: '/mês',\n suffixSemiannual: '/semestre',\n suffixAnnual: '/ano',\n labelMonthly: 'mensal',\n labelSemiannual: 'semestral',\n labelAnnual: 'anual',\n },\n\n languages: {\n 'pt-br': 'Português (Brasil)',\n 'en-us': 'Inglês (EUA)',\n 'es-es': 'Espanhol',\n },\n\n // Componentes de formulário e entrada.\n forms: {\n combobox: {\n placeholder: 'Selecione uma opção',\n searchPlaceholder: 'Buscar...',\n emptyMessage: 'Nenhuma opção encontrada.',\n },\n datePicker: {\n placeholder: 'Selecione a data',\n },\n dateRangePicker: {\n placeholder: 'Selecione o período',\n },\n phoneInput: {\n optional: '(Opcional)',\n searchPlaceholder: 'Buscar país...',\n emptyMessage: 'Nenhum país encontrado',\n },\n select: {\n placeholder: 'Selecione uma opção',\n optional: '(Opcional)',\n },\n copyButton: {\n tooltipDefault: 'Copiar link',\n successDefault: 'Link copiado',\n errorMessage: 'Não foi possível copiar o link',\n },\n circularProgress: {\n ariaLabel: 'Progresso de exportação',\n },\n },\n\n // Componentes: ImageCropModal, ImageTooSmallModal.\n imageUpload: {\n cropTitle: 'Ajustar imagem',\n cropHint: 'Arraste para ajustar a área de corte',\n cropAlt: 'Crop',\n tooSmallTitleWithDimension: 'Foto menor que {dimensionText}',\n tooSmallTitleGeneric: 'Foto muito pequena',\n tooSmallBodyFileWithDimension: 'O arquivo \"{fileName}\" é menor que {dimensionText}. Faça envio de uma imagem com pelo menos {dimensionText} para continuar.',\n tooSmallBodyFileGeneric: 'O arquivo \"{fileName}\" é menor que o tamanho mínimo exigido. Faça envio de uma imagem maior para continuar.',\n tooSmallBodyNoFileWithDimension: 'A imagem selecionada é menor que {dimensionText}. Faça envio de uma imagem com pelo menos {dimensionText} para continuar.',\n tooSmallBodyNoFileGeneric: 'A imagem selecionada é menor que o tamanho mínimo exigido. Faça envio de uma imagem maior para continuar.',\n sendAnother: 'Enviar outra',\n errorSvg: 'Formato SVG não é suportado. Use PNG, JPEG, WebP ou GIF.',\n errorFormat: 'Formato não suportado. Use PNG, JPEG, WebP ou GIF.',\n errorTooLarge: 'Arquivo muito grande. Máximo {maxSize}MB.',\n },\n\n // Componentes: NotificationPageContent (Notifications.tsx), NotificationsPopover.tsx.\n notifications: {\n page: {\n title: 'Notificações',\n subtitle: 'Tenha controle total sobre páginas, experiências e conversões.',\n markAllReadDesktop: 'Marcar todos como lidos',\n markAllReadMobile: 'Marcar como lidos',\n tabAll: 'Todas as notificações',\n tabUnread: 'Não lidas',\n details: 'Detalhes',\n empty: 'Nenhuma notificação encontrada.',\n markAllSuccess: 'Todas as notificações foram marcadas como lidas',\n markAllError: 'Erro ao marcar notificações como lidas',\n },\n popover: {\n title: 'Últimas notificações',\n empty: 'Sem notificações por enquanto',\n viewAll: 'Todas as notificações',\n },\n },\n\n // Componentes: NavBar.tsx, ProfilePopover.tsx, UsersSelectorPopover.tsx.\n layout: {\n navbar: {\n expandMenu: 'Expandir menu',\n greatPages: 'GreatPages',\n pages: 'Páginas',\n },\n profile: {\n usedCredits: 'Créditos usados',\n loggingOut: 'Saindo da sua conta...',\n logout: 'Sair',\n },\n usersSelector: {\n title: 'Usuários',\n add: 'Adicionar',\n searchPlaceholder: 'Busque aqui',\n empty: 'Nenhum usuário encontrado.',\n noResults: 'Nenhum resultado encontrado.',\n addToProject: 'Adicionar ao projeto',\n removeFromProject: 'Remover do projeto',\n manageTeam: 'Gerenciar equipe',\n },\n },\n\n // Componente: NotFoundPage.tsx.\n notFound: {\n title: 'Página não foi encontrada!',\n description: 'A página que você está procurando não existe. Verifique se digitou corretamente o link que está procurando.',\n backToHome: 'Voltar para o início',\n },\n} as const;\n\nexport default messages;\n"],"mappings":"AAUA,MAAM,WAAW;AAAA;AAAA,EAEf,SAAS;AAAA,IACP,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,UAAU;AAAA,IACV,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA;AAAA,EAGA,aAAa;AAAA,IACX,UAAU;AAAA,IACV,cAAc;AAAA,IACd,cAAc;AAAA,EAChB;AAAA;AAAA,EAGA,aAAa;AAAA,IACX,OAAO;AAAA,IACP,aAAa;AAAA,IACb,wBAAwB;AAAA,IACxB,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,uBAAuB;AAAA,IACvB,mBAAmB;AAAA,MACjB,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,IACA,cAAc;AAAA,IACd,WAAW;AAAA,EACb;AAAA;AAAA,EAGA,SAAS;AAAA,IACP,mBAAmB;AAAA,MACjB,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,sBAAsB;AAAA,IACxB;AAAA,IACA,eAAe;AAAA,MACb,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa;AAAA,MACb,mBAAmB;AAAA,MACnB,kBAAkB;AAAA,MAClB,wBAAwB;AAAA,MACxB,iBAAiB;AAAA,MACjB,eAAe;AAAA,MACf,qBAAqB;AAAA,MACrB,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,SAAS;AAAA,QACP,WAAW;AAAA,QACX,WAAW;AAAA,QACX,SAAS;AAAA,QACT,SAAS;AAAA,QACT,WAAW;AAAA,QACX,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,eAAe;AAAA,MACb,OAAO;AAAA,MACP,SACE;AAAA,MACF,gBAAgB;AAAA,MAChB,SAAS;AAAA,MACT,OAAO;AAAA,MACP,aAAa;AAAA,MACb,cAAc;AAAA,MACd,UAAU;AAAA,IACZ;AAAA,IACA,YAAY;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,SAAS;AAAA,MACT,kBAAkB;AAAA,IACpB;AAAA,IACA,WAAW;AAAA,MACT,OAAO;AAAA,MACP,cACE;AAAA,MACF,OAAO;AAAA,MACP,OAAO;AAAA,MACP,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,eAAe;AAAA,MACf,iBAAiB;AAAA,MACjB,eACE;AAAA,MACF,eAAe;AAAA,MACf,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,eAAe;AAAA,MACf,cAAc;AAAA,MACd,cAAc;AAAA,MACd,oBACE;AAAA,MACF,mBAAmB;AAAA,MACnB,WAAW;AAAA,MACX,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,aAAa;AAAA,IACf;AAAA,IACA,SAAS;AAAA,MACP,OAAO;AAAA,MACP,WAAW;AAAA,MACX,aAAa;AAAA,MACb,MAAM;AAAA,MACN,iBAAiB;AAAA,MACjB,UAAU;AAAA,MACV,qBAAqB;AAAA,MACrB,QAAQ;AAAA,MACR,mBAAmB;AAAA,MACnB,eAAe;AAAA,QACb,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,MACA,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,cAAc;AAAA,MACd,WAAW;AAAA,IACb;AAAA,IACA,KAAK;AAAA,MACH,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,IACd;AAAA,IACA,aAAa;AAAA,MACX,OAAO;AAAA,MACP,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,mBAAmB;AAAA,MACnB,UAAU;AAAA,MACV,qBAAqB;AAAA,MACrB,cAAc;AAAA,MACd,kBAAkB;AAAA,IACpB;AAAA,IACA,aAAa;AAAA,MACX,WAAW;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU;AAAA,MACV,mBAAmB;AAAA,MACnB,gBAAgB;AAAA,MAChB,WAAW;AAAA,MACX,aAAa;AAAA,MACb,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,WAAW;AAAA,MACX,mBAAmB;AAAA,IACrB;AAAA,IACA,UAAU;AAAA,MACR,OAAO;AAAA,MACP,mBAAmB;AAAA,MACnB,yBACE;AAAA,MACF,WAAW;AAAA,MACX,cAAc;AAAA,MACd,aAAa;AAAA,MACb,0BACE;AAAA,MACF,iBAAiB;AAAA,IACnB;AAAA,IACA,OAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,MAAM;AAAA,MACN,UAAU;AAAA,IACZ;AAAA,IACA,gBAAgB;AAAA,MACd,OAAO;AAAA,MACP,iBAAiB;AAAA,MACjB,4BAA4B;AAAA,MAC5B,aAAa;AAAA,MACb,wBAAwB;AAAA,MACxB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB;AAAA,IACA,mBAAmB;AAAA,MACjB,OAAO;AAAA,MACP,eAAe;AAAA,MACf,SACE;AAAA,IACJ;AAAA,IACA,gBAAgB;AAAA,MACd,OAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,SAAS;AAAA,IACP,KAAK;AAAA,MACH,OAAO;AAAA,MACP,eAAe;AAAA,MACf,qBAAqB;AAAA,MACrB,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,MACpB,2BAA2B;AAAA,MAC3B,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,qBAAqB;AAAA,IACvB;AAAA,IACA,UAAU;AAAA,MACR,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBACE;AAAA,MACF,YAAY;AAAA,IACd;AAAA,IACA,kBAAkB;AAAA,MAChB,cAAc;AAAA,MACd,oBAAoB;AAAA,MACpB,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,OAAO;AAAA,IACL,KAAK;AAAA,MACH,aAAa;AAAA,MACb,UAAU;AAAA,MACV,eAAe;AAAA,MACf,qBAAqB;AAAA,MACrB,gBAAgB;AAAA,MAChB,OAAO;AAAA,MACP,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,eAAe;AAAA,MACf,WAAW;AAAA,MACX,iBAAiB;AAAA,MACjB,eAAe;AAAA,MACf,cAAc;AAAA,MACd,WAAW;AAAA,IACb;AAAA,IACA,MAAM;AAAA,MACJ,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,cAAc;AAAA,MACd,KAAK;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,MAAM;AAAA,MACN,OAAO;AAAA,MACP,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,oBAAoB;AAAA,MACpB,oBAAoB;AAAA,MACpB,iBAAiB;AAAA,IACnB;AAAA,IACA,QAAQ;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,MACb,cAAc;AAAA,MACd,oBAAoB;AAAA,MACpB,UAAU;AAAA,MACV,cAAc;AAAA,MACd,YAAY;AAAA,IACd;AAAA,IACA,cAAc;AAAA,MACZ,OAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,iBAAiB;AAAA,IACnB;AAAA,IACA,MAAM;AAAA,MACJ,cAAc;AAAA,MACd,aAAa;AAAA,MACb,mBAAmB;AAAA,MACnB,iBAAiB;AAAA,IACnB;AAAA,IACA,aAAa;AAAA,MACX,OAAO;AAAA,MACP,SAAS;AAAA,MACT,SAAS;AAAA,MACT,qBAAqB;AAAA,MACrB,aAAa;AAAA,MACb,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA;AAAA,EAGA,YAAY;AAAA,IACV,SAAS;AAAA,MACP,WAAW;AAAA,QACT,SAAS;AAAA,QACT,YAAY;AAAA,MACd;AAAA,MACA,SAAS;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,MACA,SAAS;AAAA,QACP,SAAS;AAAA,QACT,YAAY;AAAA,MACd;AAAA,MACA,UAAU;AAAA,QACR,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,OAAO;AAAA,MACP,mBAAmB;AAAA,MACnB,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,gBAAgB;AAAA,IAClB;AAAA,IACA,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,iBAAiB;AAAA,IACnB;AAAA,IACA,aAAa;AAAA,MACX,OAAO;AAAA,IACT;AAAA,IACA,UAAU;AAAA,MACR,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA,EAIA,OAAO;AAAA,IACL,UAAU;AAAA,MACR,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,mBAAmB;AAAA,IACrB;AAAA,IACA,cAAc;AAAA,MACZ,gBAAgB;AAAA,MAChB,cAAc;AAAA,MACd,aAAa;AAAA,MACb,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,gBAAgB;AAAA,IAClB;AAAA,EACF;AAAA;AAAA,EAGA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,aAAa;AAAA,EACf;AAAA,EAEA,WAAW;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AAAA;AAAA,EAGA,OAAO;AAAA,IACL,UAAU;AAAA,MACR,aAAa;AAAA,MACb,mBAAmB;AAAA,MACnB,cAAc;AAAA,IAChB;AAAA,IACA,YAAY;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,iBAAiB;AAAA,MACf,aAAa;AAAA,IACf;AAAA,IACA,YAAY;AAAA,MACV,UAAU;AAAA,MACV,mBAAmB;AAAA,MACnB,cAAc;AAAA,IAChB;AAAA,IACA,QAAQ;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,YAAY;AAAA,MACV,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB;AAAA,IACA,kBAAkB;AAAA,MAChB,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,aAAa;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,IACV,SAAS;AAAA,IACT,4BAA4B;AAAA,IAC5B,sBAAsB;AAAA,IACtB,+BAA+B;AAAA,IAC/B,yBAAyB;AAAA,IACzB,iCAAiC;AAAA,IACjC,2BAA2B;AAAA,IAC3B,aAAa;AAAA,IACb,UAAU;AAAA,IACV,aAAa;AAAA,IACb,eAAe;AAAA,EACjB;AAAA;AAAA,EAGA,eAAe;AAAA,IACb,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,UAAU;AAAA,MACV,oBAAoB;AAAA,MACpB,mBAAmB;AAAA,MACnB,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,SAAS;AAAA,MACT,OAAO;AAAA,MACP,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB;AAAA,IACA,SAAS;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,EACF;AAAA;AAAA,EAGA,QAAQ;AAAA,IACN,QAAQ;AAAA,MACN,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,OAAO;AAAA,IACT;AAAA,IACA,SAAS;AAAA,MACP,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,QAAQ;AAAA,IACV;AAAA,IACA,eAAe;AAAA,MACb,OAAO;AAAA,MACP,KAAK;AAAA,MACL,mBAAmB;AAAA,MACnB,OAAO;AAAA,MACP,WAAW;AAAA,MACX,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,YAAY;AAAA,IACd;AAAA,EACF;AAAA;AAAA,EAGA,UAAU;AAAA,IACR,OAAO;AAAA,IACP,aAAa;AAAA,IACb,YAAY;AAAA,EACd;AACF;AAEA,IAAO,gBAAQ;","names":[]}
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
ACCEPTED_IMAGE_FORMATS,
|
|
3
3
|
MAX_FILE_SIZE_MB
|
|
4
4
|
} from "../constants/image.constants";
|
|
5
|
-
function validateImageFormat(file) {
|
|
5
|
+
function validateImageFormat(file, translate) {
|
|
6
6
|
if (file.type === "image/svg+xml" || file.name.toLowerCase().endsWith(".svg")) {
|
|
7
7
|
return {
|
|
8
8
|
valid: false,
|
|
9
|
-
error: "Formato SVG n\xE3o \xE9 suportado. Use PNG, JPEG, WebP ou GIF."
|
|
9
|
+
error: translate ? translate("common.imageUpload.errorSvg") : "Formato SVG n\xE3o \xE9 suportado. Use PNG, JPEG, WebP ou GIF."
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
if (!ACCEPTED_IMAGE_FORMATS.includes(
|
|
@@ -14,24 +14,24 @@ function validateImageFormat(file) {
|
|
|
14
14
|
)) {
|
|
15
15
|
return {
|
|
16
16
|
valid: false,
|
|
17
|
-
error: "Formato n\xE3o suportado. Use PNG, JPEG, WebP ou GIF."
|
|
17
|
+
error: translate ? translate("common.imageUpload.errorFormat") : "Formato n\xE3o suportado. Use PNG, JPEG, WebP ou GIF."
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
return { valid: true };
|
|
21
21
|
}
|
|
22
|
-
function validateImageSize(file, maxSizeMB = MAX_FILE_SIZE_MB) {
|
|
22
|
+
function validateImageSize(file, maxSizeMB = MAX_FILE_SIZE_MB, translate) {
|
|
23
23
|
if (file.size > maxSizeMB * 1024 * 1024) {
|
|
24
24
|
return {
|
|
25
25
|
valid: false,
|
|
26
|
-
error: `Arquivo muito grande. M\xE1ximo ${maxSizeMB}MB.`
|
|
26
|
+
error: translate ? translate("common.imageUpload.errorTooLarge", { maxSize: maxSizeMB }) : `Arquivo muito grande. M\xE1ximo ${maxSizeMB}MB.`
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
return { valid: true };
|
|
30
30
|
}
|
|
31
|
-
function validateImage(file) {
|
|
32
|
-
const formatValidation = validateImageFormat(file);
|
|
31
|
+
function validateImage(file, translate) {
|
|
32
|
+
const formatValidation = validateImageFormat(file, translate);
|
|
33
33
|
if (!formatValidation.valid) return formatValidation;
|
|
34
|
-
const sizeValidation = validateImageSize(file);
|
|
34
|
+
const sizeValidation = validateImageSize(file, MAX_FILE_SIZE_MB, translate);
|
|
35
35
|
if (!sizeValidation.valid) return sizeValidation;
|
|
36
36
|
return { valid: true };
|
|
37
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/images/utils/validate-image.ts"],"sourcesContent":["import {\n ACCEPTED_IMAGE_FORMATS,\n MAX_FILE_SIZE_MB,\n} from '../constants/image.constants'\n\nexport interface ImageValidationResult {\n valid: boolean\n error?: string\n}\n\nexport function validateImageFormat(file: File): ImageValidationResult {\n // Bloqueia SVG explicitamente (segurança + não funciona com crop)\n if (file.type === 'image/svg+xml' || file.name.toLowerCase().endsWith('.svg')) {\n return {\n valid: false,\n error: 'Formato SVG não é suportado. Use PNG, JPEG, WebP ou GIF.',\n }\n }\n\n if (\n !ACCEPTED_IMAGE_FORMATS.includes(\n file.type as (typeof ACCEPTED_IMAGE_FORMATS)[number]\n )\n ) {\n return {\n valid: false,\n error: 'Formato não suportado. Use PNG, JPEG, WebP ou GIF.',\n }\n }\n return { valid: true }\n}\n\nexport function validateImageSize(\n file: File,\n maxSizeMB: number = MAX_FILE_SIZE_MB\n): ImageValidationResult {\n if (file.size > maxSizeMB * 1024 * 1024) {\n return {\n valid: false,\n error: `Arquivo muito grande. Máximo ${maxSizeMB}MB.`,\n }\n }\n return { valid: true }\n}\n\nexport function validateImage(file: File): ImageValidationResult {\n const formatValidation = validateImageFormat(file)\n if (!formatValidation.valid) return formatValidation\n\n const sizeValidation = validateImageSize(file)\n if (!sizeValidation.valid) return sizeValidation\n\n return { valid: true }\n}\n\nexport async function getImageDimensions(\n file: File\n): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => {\n const img = new Image()\n img.onload = () => {\n resolve({ width: img.naturalWidth, height: img.naturalHeight })\n URL.revokeObjectURL(img.src)\n }\n img.onerror = () => {\n reject(new Error('Falha ao carregar imagem'))\n URL.revokeObjectURL(img.src)\n }\n img.src = URL.createObjectURL(file)\n })\n}\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,OACK;
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/images/utils/validate-image.ts"],"sourcesContent":["import {\n ACCEPTED_IMAGE_FORMATS,\n MAX_FILE_SIZE_MB,\n} from '../constants/image.constants'\n\ntype TranslateFn = (key: any, values?: Record<string, string | number>) => string;\n\nexport interface ImageValidationResult {\n valid: boolean\n error?: string\n}\n\nexport function validateImageFormat(\n file: File,\n translate?: TranslateFn\n): ImageValidationResult {\n // Bloqueia SVG explicitamente (segurança + não funciona com crop)\n if (file.type === 'image/svg+xml' || file.name.toLowerCase().endsWith('.svg')) {\n return {\n valid: false,\n error: translate\n ? translate('common.imageUpload.errorSvg')\n : 'Formato SVG não é suportado. Use PNG, JPEG, WebP ou GIF.',\n }\n }\n\n if (\n !ACCEPTED_IMAGE_FORMATS.includes(\n file.type as (typeof ACCEPTED_IMAGE_FORMATS)[number]\n )\n ) {\n return {\n valid: false,\n error: translate\n ? translate('common.imageUpload.errorFormat')\n : 'Formato não suportado. Use PNG, JPEG, WebP ou GIF.',\n }\n }\n return { valid: true }\n}\n\nexport function validateImageSize(\n file: File,\n maxSizeMB: number = MAX_FILE_SIZE_MB,\n translate?: TranslateFn\n): ImageValidationResult {\n if (file.size > maxSizeMB * 1024 * 1024) {\n return {\n valid: false,\n error: translate\n ? translate('common.imageUpload.errorTooLarge', { maxSize: maxSizeMB })\n : `Arquivo muito grande. Máximo ${maxSizeMB}MB.`,\n }\n }\n return { valid: true }\n}\n\nexport function validateImage(\n file: File,\n translate?: TranslateFn\n): ImageValidationResult {\n const formatValidation = validateImageFormat(file, translate)\n if (!formatValidation.valid) return formatValidation\n\n const sizeValidation = validateImageSize(file, MAX_FILE_SIZE_MB, translate)\n if (!sizeValidation.valid) return sizeValidation\n\n return { valid: true }\n}\n\nexport async function getImageDimensions(\n file: File\n): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => {\n const img = new Image()\n img.onload = () => {\n resolve({ width: img.naturalWidth, height: img.naturalHeight })\n URL.revokeObjectURL(img.src)\n }\n img.onerror = () => {\n reject(new Error('Falha ao carregar imagem'))\n URL.revokeObjectURL(img.src)\n }\n img.src = URL.createObjectURL(file)\n })\n}\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AASA,SAAS,oBACd,MACA,WACuB;AAEvB,MAAI,KAAK,SAAS,mBAAmB,KAAK,KAAK,YAAY,EAAE,SAAS,MAAM,GAAG;AAC7E,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,YACH,UAAU,6BAA6B,IACvC;AAAA,IACN;AAAA,EACF;AAEA,MACE,CAAC,uBAAuB;AAAA,IACtB,KAAK;AAAA,EACP,GACA;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,YACH,UAAU,gCAAgC,IAC1C;AAAA,IACN;AAAA,EACF;AACA,SAAO,EAAE,OAAO,KAAK;AACvB;AAEO,SAAS,kBACd,MACA,YAAoB,kBACpB,WACuB;AACvB,MAAI,KAAK,OAAO,YAAY,OAAO,MAAM;AACvC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,YACH,UAAU,oCAAoC,EAAE,SAAS,UAAU,CAAC,IACpE,mCAAgC,SAAS;AAAA,IAC/C;AAAA,EACF;AACA,SAAO,EAAE,OAAO,KAAK;AACvB;AAEO,SAAS,cACd,MACA,WACuB;AACvB,QAAM,mBAAmB,oBAAoB,MAAM,SAAS;AAC5D,MAAI,CAAC,iBAAiB,MAAO,QAAO;AAEpC,QAAM,iBAAiB,kBAAkB,MAAM,kBAAkB,SAAS;AAC1E,MAAI,CAAC,eAAe,MAAO,QAAO;AAElC,SAAO,EAAE,OAAO,KAAK;AACvB;AAEA,eAAsB,mBACpB,MAC4C;AAC5C,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,MAAM,IAAI,MAAM;AACtB,QAAI,SAAS,MAAM;AACjB,cAAQ,EAAE,OAAO,IAAI,cAAc,QAAQ,IAAI,cAAc,CAAC;AAC9D,UAAI,gBAAgB,IAAI,GAAG;AAAA,IAC7B;AACA,QAAI,UAAU,MAAM;AAClB,aAAO,IAAI,MAAM,0BAA0B,CAAC;AAC5C,UAAI,gBAAgB,IAAI,GAAG;AAAA,IAC7B;AACA,QAAI,MAAM,IAAI,gBAAgB,IAAI;AAAA,EACpC,CAAC;AACH;","names":[]}
|
|
@@ -2,24 +2,46 @@ import { ADDON_IDS } from "../../subscriptions/constants/addons.constants";
|
|
|
2
2
|
import {
|
|
3
3
|
formatCurrencyNumber
|
|
4
4
|
} from "../../../utils/format/currency";
|
|
5
|
-
const
|
|
6
|
-
{ icon: "check",
|
|
7
|
-
{ icon: "check",
|
|
8
|
-
{ icon: "check",
|
|
9
|
-
{ icon: "check",
|
|
10
|
-
|
|
11
|
-
{ icon: "check",
|
|
5
|
+
const BASE_FEATURES_KEYS = [
|
|
6
|
+
{ icon: "check", key: "plans.features.unlimitedVisits", fallback: "Visitas ilimitadas" },
|
|
7
|
+
{ icon: "check", key: "plans.features.unlimitedLeads", fallback: "Leads ilimitadas" },
|
|
8
|
+
{ icon: "check", key: "plans.features.sharePages", fallback: "Compartilhar p\xE1ginas", tooltip: "sharePages" },
|
|
9
|
+
{ icon: "check", key: "plans.features.hosting", fallback: "Hospedagem inclusa" },
|
|
10
|
+
// SSL (HTTPS) + CDN — brand/acronym: never translated
|
|
11
|
+
{ icon: "check", key: null, fallback: "SSL (HTTPS) + CDN" },
|
|
12
|
+
{ icon: "check", key: "plans.features.freeTemplates", fallback: "Templates gratuitos" }
|
|
12
13
|
];
|
|
13
|
-
function
|
|
14
|
+
function buildBaseFeatures(translate) {
|
|
15
|
+
return BASE_FEATURES_KEYS.map(({ icon, key, fallback, ...rest }) => {
|
|
16
|
+
const text = key && translate ? translate(`common.${key}`) : fallback;
|
|
17
|
+
const feature = { icon, text };
|
|
18
|
+
if ("tooltip" in rest && rest.tooltip) feature.tooltip = rest.tooltip;
|
|
19
|
+
return feature;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function buildMainFeaturesFromItems(items, translate) {
|
|
14
23
|
const pagesItem = items.find((i) => i.id_addon === ADDON_IDS.PAGES);
|
|
15
24
|
const domainsItem = items.find((i) => i.id_addon === ADDON_IDS.DOMAINS);
|
|
16
25
|
const pagesQty = pagesItem?.quantity ?? 0;
|
|
17
26
|
const domainsQty = domainsItem?.quantity ?? 1;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
let pages;
|
|
28
|
+
if (pagesQty === 0) {
|
|
29
|
+
pages = translate ? translate("common.plans.mainFeatures.pagesUnlimited") : "P\xE1ginas ilimitadas";
|
|
30
|
+
} else if (pagesQty === 1) {
|
|
31
|
+
pages = translate ? translate("common.plans.mainFeatures.pageSingular") : "1 p\xE1gina";
|
|
32
|
+
} else {
|
|
33
|
+
pages = translate ? translate("common.plans.mainFeatures.pagesPlural", { count: pagesQty }) : `${pagesQty} p\xE1ginas`;
|
|
34
|
+
}
|
|
35
|
+
let domains;
|
|
36
|
+
if (domainsQty >= 999) {
|
|
37
|
+
domains = translate ? translate("common.plans.mainFeatures.domainsUnlimited") : "Dom\xEDnios ilimitados";
|
|
38
|
+
} else if (domainsQty === 1) {
|
|
39
|
+
domains = translate ? translate("common.plans.mainFeatures.domainSingular") : "1 dom\xEDnio externo";
|
|
40
|
+
} else {
|
|
41
|
+
domains = translate ? translate("common.plans.mainFeatures.domainsPlural", { count: domainsQty }) : `${domainsQty} dom\xEDnios externos`;
|
|
42
|
+
}
|
|
43
|
+
const users = translate ? translate("common.plans.mainFeatures.usersUnlimited") : "Usu\xE1rios ilimitados";
|
|
44
|
+
return { pages, domains, users };
|
|
23
45
|
}
|
|
24
46
|
function computePricingByPeriod(apiPlan, currency) {
|
|
25
47
|
const monthly = currency === "usd" ? apiPlan.value_usd ?? apiPlan.value : apiPlan.value;
|
|
@@ -30,33 +52,26 @@ function computePricingByPeriod(apiPlan, currency) {
|
|
|
30
52
|
annual: round2(monthly * (1 - apiPlan.discount_annual / 100))
|
|
31
53
|
};
|
|
32
54
|
}
|
|
33
|
-
function buildUiPlan(plan, currency) {
|
|
55
|
+
function buildUiPlan(plan, currency, translate) {
|
|
34
56
|
const popular = plan.id === 2 || plan.id_plan === 2;
|
|
35
57
|
const buttonVariant = popular ? "brand" : "default";
|
|
36
58
|
const pricingByPeriod = computePricingByPeriod(plan, currency);
|
|
37
59
|
const monthlyFinal = pricingByPeriod.monthly;
|
|
38
60
|
const lowerName = plan.name.toLowerCase();
|
|
39
61
|
const hasProjectAndOnboarding = lowerName.includes("ag\xEAncia") || lowerName.includes("agencia");
|
|
62
|
+
const onboardingText = translate ? translate("common.plans.features.onboarding") : "Reuni\xE3o de Onboarding";
|
|
63
|
+
const projectMgmtText = translate ? translate("common.plans.features.projectManagement") : "Gest\xE3o de projetos";
|
|
40
64
|
const features = [
|
|
41
|
-
...
|
|
42
|
-
hasProjectAndOnboarding ? { icon: "check", text:
|
|
43
|
-
hasProjectAndOnboarding ? {
|
|
44
|
-
icon: "check",
|
|
45
|
-
text: "Gest\xE3o de projetos",
|
|
46
|
-
tooltip: "projectManagement"
|
|
47
|
-
} : {
|
|
48
|
-
icon: "x",
|
|
49
|
-
text: "Gest\xE3o de projetos",
|
|
50
|
-
disabled: true,
|
|
51
|
-
tooltip: "projectManagement"
|
|
52
|
-
}
|
|
65
|
+
...buildBaseFeatures(translate),
|
|
66
|
+
hasProjectAndOnboarding ? { icon: "check", text: onboardingText } : { icon: "x", text: onboardingText, disabled: true },
|
|
67
|
+
hasProjectAndOnboarding ? { icon: "check", text: projectMgmtText, tooltip: "projectManagement" } : { icon: "x", text: projectMgmtText, disabled: true, tooltip: "projectManagement" }
|
|
53
68
|
];
|
|
54
69
|
return {
|
|
55
70
|
planId: plan.id,
|
|
56
71
|
name: plan.name,
|
|
57
72
|
isPopular: popular,
|
|
58
73
|
buttonVariant,
|
|
59
|
-
mainFeatures: buildMainFeaturesFromItems(plan.items),
|
|
74
|
+
mainFeatures: buildMainFeaturesFromItems(plan.items, translate),
|
|
60
75
|
features,
|
|
61
76
|
originalPrice: formatCurrencyNumber(monthlyFinal, 2, currency),
|
|
62
77
|
price: formatCurrencyNumber(monthlyFinal, 2, currency),
|
|
@@ -64,10 +79,10 @@ function buildUiPlan(plan, currency) {
|
|
|
64
79
|
items: plan.items
|
|
65
80
|
};
|
|
66
81
|
}
|
|
67
|
-
function mapApiPlanToUiPlan(plan) {
|
|
68
|
-
return buildUiPlan(plan, "brl");
|
|
82
|
+
function mapApiPlanToUiPlan(plan, translate) {
|
|
83
|
+
return buildUiPlan(plan, "brl", translate);
|
|
69
84
|
}
|
|
70
|
-
const mapApiPlanToUiPlanForCurrency = (currency) => (plan) => buildUiPlan(plan, currency);
|
|
85
|
+
const mapApiPlanToUiPlanForCurrency = (currency, translate) => (plan) => buildUiPlan(plan, currency, translate);
|
|
71
86
|
export {
|
|
72
87
|
mapApiPlanToUiPlan,
|
|
73
88
|
mapApiPlanToUiPlanForCurrency
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/plans/utils/map-api-plan-to-ui.ts"],"sourcesContent":["import type {\n Plan,\n PlanFeature,\n PlanMainFeatures,\n PlanPricingByPeriod,\n UiPlan,\n} from \"../types/plan.type\";\nimport { ADDON_IDS } from \"../../subscriptions/constants/addons.constants\";\nimport {\n formatCurrencyNumber,\n type CurrencyCode,\n} from \"../../../utils/format/currency\";\n\nexport type PlanBillingPeriod = \"monthly\" | \"semiannual\" | \"annual\";\n\
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/plans/utils/map-api-plan-to-ui.ts"],"sourcesContent":["import type {\n Plan,\n PlanFeature,\n PlanMainFeatures,\n PlanPricingByPeriod,\n UiPlan,\n} from \"../types/plan.type\";\nimport { ADDON_IDS } from \"../../subscriptions/constants/addons.constants\";\nimport {\n formatCurrencyNumber,\n type CurrencyCode,\n} from \"../../../utils/format/currency\";\n\nexport type PlanBillingPeriod = \"monthly\" | \"semiannual\" | \"annual\";\n\ntype TranslateFn = (key: any, values?: Record<string, string | number>) => string;\n\nconst BASE_FEATURES_KEYS = [\n { icon: \"check\", key: \"plans.features.unlimitedVisits\", fallback: \"Visitas ilimitadas\" },\n { icon: \"check\", key: \"plans.features.unlimitedLeads\", fallback: \"Leads ilimitadas\" },\n { icon: \"check\", key: \"plans.features.sharePages\", fallback: \"Compartilhar páginas\", tooltip: \"sharePages\" },\n { icon: \"check\", key: \"plans.features.hosting\", fallback: \"Hospedagem inclusa\" },\n // SSL (HTTPS) + CDN — brand/acronym: never translated\n { icon: \"check\", key: null, fallback: \"SSL (HTTPS) + CDN\" },\n { icon: \"check\", key: \"plans.features.freeTemplates\", fallback: \"Templates gratuitos\" },\n] as const;\n\nfunction buildBaseFeatures(translate?: TranslateFn): PlanFeature[] {\n return BASE_FEATURES_KEYS.map(({ icon, key, fallback, ...rest }) => {\n const text = key && translate ? translate(`common.${key}`) : fallback;\n const feature: PlanFeature = { icon, text };\n if (\"tooltip\" in rest && rest.tooltip) feature.tooltip = rest.tooltip;\n return feature;\n });\n}\n\nfunction buildMainFeaturesFromItems(\n items: Plan[\"items\"],\n translate?: TranslateFn\n): PlanMainFeatures {\n const pagesItem = items.find((i) => i.id_addon === ADDON_IDS.PAGES);\n const domainsItem = items.find((i) => i.id_addon === ADDON_IDS.DOMAINS);\n\n const pagesQty = pagesItem?.quantity ?? 0;\n const domainsQty = domainsItem?.quantity ?? 1;\n\n let pages: string;\n if (pagesQty === 0) {\n pages = translate\n ? translate(\"common.plans.mainFeatures.pagesUnlimited\")\n : \"Páginas ilimitadas\";\n } else if (pagesQty === 1) {\n pages = translate\n ? translate(\"common.plans.mainFeatures.pageSingular\")\n : \"1 página\";\n } else {\n pages = translate\n ? translate(\"common.plans.mainFeatures.pagesPlural\", { count: pagesQty })\n : `${pagesQty} páginas`;\n }\n\n let domains: string;\n if (domainsQty >= 999) {\n domains = translate\n ? translate(\"common.plans.mainFeatures.domainsUnlimited\")\n : \"Domínios ilimitados\";\n } else if (domainsQty === 1) {\n domains = translate\n ? translate(\"common.plans.mainFeatures.domainSingular\")\n : \"1 domínio externo\";\n } else {\n domains = translate\n ? translate(\"common.plans.mainFeatures.domainsPlural\", { count: domainsQty })\n : `${domainsQty} domínios externos`;\n }\n\n const users = translate\n ? translate(\"common.plans.mainFeatures.usersUnlimited\")\n : \"Usuários ilimitados\";\n\n return { pages, domains, users };\n}\n\nfunction computePricingByPeriod(apiPlan: Plan, currency: CurrencyCode): PlanPricingByPeriod {\n // Conta USD usa value_usd; fallback pro value (BRL) evita NaN quando o operador ainda\n // não cadastrou o preço internacional. Os descontos por período são percentuais — aplicam igual.\n const monthly = currency === \"usd\" ? (apiPlan.value_usd ?? apiPlan.value) : apiPlan.value;\n const round2 = (n: number) => Math.round(n * 100) / 100;\n return {\n monthly,\n semiannual: round2(monthly * (1 - apiPlan.discount_semester / 100)),\n annual: round2(monthly * (1 - apiPlan.discount_annual / 100)),\n };\n}\n\nfunction buildUiPlan(plan: Plan, currency: CurrencyCode, translate?: TranslateFn): UiPlan {\n const popular = plan.id === 2 || plan.id_plan === 2;\n const buttonVariant = popular ? \"brand\" : \"default\";\n\n const pricingByPeriod = computePricingByPeriod(plan, currency);\n const monthlyFinal = pricingByPeriod.monthly;\n\n const lowerName = plan.name.toLowerCase();\n const hasProjectAndOnboarding =\n lowerName.includes(\"agência\") || lowerName.includes(\"agencia\");\n\n const onboardingText = translate\n ? translate(\"common.plans.features.onboarding\")\n : \"Reunião de Onboarding\";\n const projectMgmtText = translate\n ? translate(\"common.plans.features.projectManagement\")\n : \"Gestão de projetos\";\n\n const features: PlanFeature[] = [\n ...buildBaseFeatures(translate),\n hasProjectAndOnboarding\n ? { icon: \"check\", text: onboardingText }\n : { icon: \"x\", text: onboardingText, disabled: true },\n hasProjectAndOnboarding\n ? { icon: \"check\", text: projectMgmtText, tooltip: \"projectManagement\" }\n : { icon: \"x\", text: projectMgmtText, disabled: true, tooltip: \"projectManagement\" },\n ];\n\n return {\n planId: plan.id,\n name: plan.name,\n isPopular: popular,\n buttonVariant,\n mainFeatures: buildMainFeaturesFromItems(plan.items, translate),\n features,\n originalPrice: formatCurrencyNumber(monthlyFinal, 2, currency),\n price: formatCurrencyNumber(monthlyFinal, 2, currency),\n pricingByPeriod,\n items: plan.items,\n };\n}\n\n/**\n * Mapeia um plano da API para UiPlan em BRL.\n * Assinatura de 1 argumento — seguro em `plans.map(mapApiPlanToUiPlan)`.\n * Passa `translate` opcional para i18n; sem ele cai nos literais pt-br (back-compat).\n */\nexport function mapApiPlanToUiPlan(plan: Plan, translate?: TranslateFn): UiPlan {\n return buildUiPlan(plan, \"brl\", translate);\n}\n\n/**\n * Variante currency-aware: a moeda vem do gateway da conta (getCurrencyForGateway).\n * Fábrica para uso ergonômico em `.map`: `plans.map(mapApiPlanToUiPlanForCurrency(currency, translate))`.\n * Mantida separada de mapApiPlanToUiPlan para não quebrar callers que passam a fn direto pro `.map`.\n */\nexport const mapApiPlanToUiPlanForCurrency =\n (currency: CurrencyCode, translate?: TranslateFn) =>\n (plan: Plan): UiPlan =>\n buildUiPlan(plan, currency, translate);\n"],"mappings":"AAOA,SAAS,iBAAiB;AAC1B;AAAA,EACE;AAAA,OAEK;AAMP,MAAM,qBAAqB;AAAA,EACzB,EAAE,MAAM,SAAS,KAAK,kCAAmC,UAAU,qBAAqB;AAAA,EACxF,EAAE,MAAM,SAAS,KAAK,iCAAmC,UAAU,mBAAmB;AAAA,EACtF,EAAE,MAAM,SAAS,KAAK,6BAAoC,UAAU,2BAAwB,SAAS,aAAa;AAAA,EAClH,EAAE,MAAM,SAAS,KAAK,0BAAoC,UAAU,qBAAqB;AAAA;AAAA,EAEzF,EAAE,MAAM,SAAS,KAAK,MAAoC,UAAU,oBAAoB;AAAA,EACxF,EAAE,MAAM,SAAS,KAAK,gCAAoC,UAAU,sBAAsB;AAC5F;AAEA,SAAS,kBAAkB,WAAwC;AACjE,SAAO,mBAAmB,IAAI,CAAC,EAAE,MAAM,KAAK,UAAU,GAAG,KAAK,MAAM;AAClE,UAAM,OAAO,OAAO,YAAY,UAAU,UAAU,GAAG,EAAE,IAAI;AAC7D,UAAM,UAAuB,EAAE,MAAM,KAAK;AAC1C,QAAI,aAAa,QAAQ,KAAK,QAAS,SAAQ,UAAU,KAAK;AAC9D,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,2BACP,OACA,WACkB;AAClB,QAAM,YAAY,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa,UAAU,KAAK;AAClE,QAAM,cAAc,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa,UAAU,OAAO;AAEtE,QAAM,WAAW,WAAW,YAAY;AACxC,QAAM,aAAa,aAAa,YAAY;AAE5C,MAAI;AACJ,MAAI,aAAa,GAAG;AAClB,YAAQ,YACJ,UAAU,0CAA0C,IACpD;AAAA,EACN,WAAW,aAAa,GAAG;AACzB,YAAQ,YACJ,UAAU,wCAAwC,IAClD;AAAA,EACN,OAAO;AACL,YAAQ,YACJ,UAAU,yCAAyC,EAAE,OAAO,SAAS,CAAC,IACtE,GAAG,QAAQ;AAAA,EACjB;AAEA,MAAI;AACJ,MAAI,cAAc,KAAK;AACrB,cAAU,YACN,UAAU,4CAA4C,IACtD;AAAA,EACN,WAAW,eAAe,GAAG;AAC3B,cAAU,YACN,UAAU,0CAA0C,IACpD;AAAA,EACN,OAAO;AACL,cAAU,YACN,UAAU,2CAA2C,EAAE,OAAO,WAAW,CAAC,IAC1E,GAAG,UAAU;AAAA,EACnB;AAEA,QAAM,QAAQ,YACV,UAAU,0CAA0C,IACpD;AAEJ,SAAO,EAAE,OAAO,SAAS,MAAM;AACjC;AAEA,SAAS,uBAAuB,SAAe,UAA6C;AAG1F,QAAM,UAAU,aAAa,QAAS,QAAQ,aAAa,QAAQ,QAAS,QAAQ;AACpF,QAAM,SAAS,CAAC,MAAc,KAAK,MAAM,IAAI,GAAG,IAAI;AACpD,SAAO;AAAA,IACL;AAAA,IACA,YAAY,OAAO,WAAW,IAAI,QAAQ,oBAAoB,IAAI;AAAA,IAClE,QAAQ,OAAO,WAAW,IAAI,QAAQ,kBAAkB,IAAI;AAAA,EAC9D;AACF;AAEA,SAAS,YAAY,MAAY,UAAwB,WAAiC;AACxF,QAAM,UAAU,KAAK,OAAO,KAAK,KAAK,YAAY;AAClD,QAAM,gBAAgB,UAAU,UAAU;AAE1C,QAAM,kBAAkB,uBAAuB,MAAM,QAAQ;AAC7D,QAAM,eAAe,gBAAgB;AAErC,QAAM,YAAY,KAAK,KAAK,YAAY;AACxC,QAAM,0BACJ,UAAU,SAAS,YAAS,KAAK,UAAU,SAAS,SAAS;AAE/D,QAAM,iBAAiB,YACnB,UAAU,kCAAkC,IAC5C;AACJ,QAAM,kBAAkB,YACpB,UAAU,yCAAyC,IACnD;AAEJ,QAAM,WAA0B;AAAA,IAC9B,GAAG,kBAAkB,SAAS;AAAA,IAC9B,0BACI,EAAE,MAAM,SAAS,MAAM,eAAe,IACtC,EAAE,MAAM,KAAK,MAAM,gBAAgB,UAAU,KAAK;AAAA,IACtD,0BACI,EAAE,MAAM,SAAS,MAAM,iBAAiB,SAAS,oBAAoB,IACrE,EAAE,MAAM,KAAS,MAAM,iBAAiB,UAAU,MAAM,SAAS,oBAAoB;AAAA,EAC3F;AAEA,SAAO;AAAA,IACL,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,IACX,WAAW;AAAA,IACX;AAAA,IACA,cAAc,2BAA2B,KAAK,OAAO,SAAS;AAAA,IAC9D;AAAA,IACA,eAAe,qBAAqB,cAAc,GAAG,QAAQ;AAAA,IAC7D,OAAO,qBAAqB,cAAc,GAAG,QAAQ;AAAA,IACrD;AAAA,IACA,OAAO,KAAK;AAAA,EACd;AACF;AAOO,SAAS,mBAAmB,MAAY,WAAiC;AAC9E,SAAO,YAAY,MAAM,OAAO,SAAS;AAC3C;AAOO,MAAM,gCACX,CAAC,UAAwB,cACzB,CAAC,SACC,YAAY,MAAM,UAAU,SAAS;","names":[]}
|
|
@@ -9,21 +9,27 @@ function billingPeriodToNumeric(billingPeriod) {
|
|
|
9
9
|
if (billingPeriod === "annual") return 365;
|
|
10
10
|
return 30;
|
|
11
11
|
}
|
|
12
|
-
function getPeriodicityLabel(periodicity) {
|
|
12
|
+
function getPeriodicityLabel(periodicity, translate) {
|
|
13
13
|
const period = periodicityToBillingPeriod(periodicity);
|
|
14
|
-
if (period === "semiannual")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
if (period === "semiannual")
|
|
15
|
+
return translate ? translate("common.periodicity.semiannual") : "Semestral";
|
|
16
|
+
if (period === "annual")
|
|
17
|
+
return translate ? translate("common.periodicity.annual") : "Anual";
|
|
18
|
+
return translate ? translate("common.periodicity.monthly") : "Mensal";
|
|
19
|
+
}
|
|
20
|
+
function getBillingPeriodSuffix(billingPeriod, translate) {
|
|
21
|
+
if (billingPeriod === "semiannual")
|
|
22
|
+
return translate ? translate("common.periodicity.suffixSemiannual") : "/semestre";
|
|
23
|
+
if (billingPeriod === "annual")
|
|
24
|
+
return translate ? translate("common.periodicity.suffixAnnual") : "/ano";
|
|
25
|
+
return translate ? translate("common.periodicity.suffixMonthly") : "/m\xEAs";
|
|
26
|
+
}
|
|
27
|
+
function getBillingPeriodLabel(billingPeriod, translate) {
|
|
28
|
+
if (billingPeriod === "semiannual")
|
|
29
|
+
return translate ? translate("common.periodicity.labelSemiannual") : "semestral";
|
|
30
|
+
if (billingPeriod === "annual")
|
|
31
|
+
return translate ? translate("common.periodicity.labelAnnual") : "anual";
|
|
32
|
+
return translate ? translate("common.periodicity.labelMonthly") : "mensal";
|
|
27
33
|
}
|
|
28
34
|
function getBillingPeriodMonths(billingPeriod) {
|
|
29
35
|
if (billingPeriod === "semiannual") return 6;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/subscriptions/utils/periodicity.ts"],"sourcesContent":["import type { BillingPeriod } from '../types/billing-period.type';\nimport type { CalculateSubscriptionResponse } from '../types/calculate-subscription.type';\n\nexport function periodicityToBillingPeriod(\n periodicity: number | string | null | undefined\n): BillingPeriod | null {\n if (periodicity === 30 || periodicity === 1 || periodicity === 'monthly') return 'monthly';\n if (periodicity === 180 || periodicity === 3 || periodicity === 'semiannual') return 'semiannual';\n if (periodicity === 365 || periodicity === 2 || periodicity === 'annual') return 'annual';\n return null;\n}\n\nexport function billingPeriodToNumeric(billingPeriod: BillingPeriod): 30 | 180 | 365 {\n if (billingPeriod === 'semiannual') return 180;\n if (billingPeriod === 'annual') return 365;\n return 30;\n}\n\nexport function getPeriodicityLabel(periodicity: number | string | null | undefined): string {\n const period = periodicityToBillingPeriod(periodicity);\n if (period === 'semiannual')
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/subscriptions/utils/periodicity.ts"],"sourcesContent":["import type { BillingPeriod } from '../types/billing-period.type';\nimport type { CalculateSubscriptionResponse } from '../types/calculate-subscription.type';\n\ntype TranslateFn = (key: any, values?: Record<string, string | number>) => string;\n\nexport function periodicityToBillingPeriod(\n periodicity: number | string | null | undefined\n): BillingPeriod | null {\n if (periodicity === 30 || periodicity === 1 || periodicity === 'monthly') return 'monthly';\n if (periodicity === 180 || periodicity === 3 || periodicity === 'semiannual') return 'semiannual';\n if (periodicity === 365 || periodicity === 2 || periodicity === 'annual') return 'annual';\n return null;\n}\n\nexport function billingPeriodToNumeric(billingPeriod: BillingPeriod): 30 | 180 | 365 {\n if (billingPeriod === 'semiannual') return 180;\n if (billingPeriod === 'annual') return 365;\n return 30;\n}\n\nexport function getPeriodicityLabel(\n periodicity: number | string | null | undefined,\n translate?: TranslateFn\n): string {\n const period = periodicityToBillingPeriod(periodicity);\n if (period === 'semiannual')\n return translate ? translate('common.periodicity.semiannual') : 'Semestral';\n if (period === 'annual')\n return translate ? translate('common.periodicity.annual') : 'Anual';\n return translate ? translate('common.periodicity.monthly') : 'Mensal';\n}\n\nexport function getBillingPeriodSuffix(\n billingPeriod: BillingPeriod,\n translate?: TranslateFn\n): string {\n if (billingPeriod === 'semiannual')\n return translate ? translate('common.periodicity.suffixSemiannual') : '/semestre';\n if (billingPeriod === 'annual')\n return translate ? translate('common.periodicity.suffixAnnual') : '/ano';\n return translate ? translate('common.periodicity.suffixMonthly') : '/mês';\n}\n\nexport function getBillingPeriodLabel(\n billingPeriod: BillingPeriod,\n translate?: TranslateFn\n): string {\n if (billingPeriod === 'semiannual')\n return translate ? translate('common.periodicity.labelSemiannual') : 'semestral';\n if (billingPeriod === 'annual')\n return translate ? translate('common.periodicity.labelAnnual') : 'anual';\n return translate ? translate('common.periodicity.labelMonthly') : 'mensal';\n}\n\nexport function getBillingPeriodMonths(billingPeriod: BillingPeriod): number {\n if (billingPeriod === 'semiannual') return 6;\n if (billingPeriod === 'annual') return 12;\n return 1;\n}\n\nexport function getPriceFromCalculatedData(\n data: CalculateSubscriptionResponse,\n periodicity: number | string | null | undefined\n): number {\n const period = periodicityToBillingPeriod(periodicity);\n if (period === 'annual') return data.year;\n if (period === 'semiannual') return data.semmester;\n return data.month;\n}\n\nexport function getOriginalPriceFromCalculatedData(\n data: CalculateSubscriptionResponse,\n periodicity: number | string | null | undefined\n): number {\n const period = periodicityToBillingPeriod(periodicity);\n if (period === 'annual') return data.year_original;\n if (period === 'semiannual') return data.semmester_original;\n return data.month_original;\n}\n"],"mappings":"AAKO,SAAS,2BACd,aACsB;AACtB,MAAI,gBAAgB,MAAM,gBAAgB,KAAK,gBAAgB,UAAW,QAAO;AACjF,MAAI,gBAAgB,OAAO,gBAAgB,KAAK,gBAAgB,aAAc,QAAO;AACrF,MAAI,gBAAgB,OAAO,gBAAgB,KAAK,gBAAgB,SAAU,QAAO;AACjF,SAAO;AACT;AAEO,SAAS,uBAAuB,eAA8C;AACnF,MAAI,kBAAkB,aAAc,QAAO;AAC3C,MAAI,kBAAkB,SAAU,QAAO;AACvC,SAAO;AACT;AAEO,SAAS,oBACd,aACA,WACQ;AACR,QAAM,SAAS,2BAA2B,WAAW;AACrD,MAAI,WAAW;AACb,WAAO,YAAY,UAAU,+BAA+B,IAAI;AAClE,MAAI,WAAW;AACb,WAAO,YAAY,UAAU,2BAA2B,IAAI;AAC9D,SAAO,YAAY,UAAU,4BAA4B,IAAI;AAC/D;AAEO,SAAS,uBACd,eACA,WACQ;AACR,MAAI,kBAAkB;AACpB,WAAO,YAAY,UAAU,qCAAqC,IAAI;AACxE,MAAI,kBAAkB;AACpB,WAAO,YAAY,UAAU,iCAAiC,IAAI;AACpE,SAAO,YAAY,UAAU,kCAAkC,IAAI;AACrE;AAEO,SAAS,sBACd,eACA,WACQ;AACR,MAAI,kBAAkB;AACpB,WAAO,YAAY,UAAU,oCAAoC,IAAI;AACvE,MAAI,kBAAkB;AACpB,WAAO,YAAY,UAAU,gCAAgC,IAAI;AACnE,SAAO,YAAY,UAAU,iCAAiC,IAAI;AACpE;AAEO,SAAS,uBAAuB,eAAsC;AAC3E,MAAI,kBAAkB,aAAc,QAAO;AAC3C,MAAI,kBAAkB,SAAU,QAAO;AACvC,SAAO;AACT;AAEO,SAAS,2BACd,MACA,aACQ;AACR,QAAM,SAAS,2BAA2B,WAAW;AACrD,MAAI,WAAW,SAAU,QAAO,KAAK;AACrC,MAAI,WAAW,aAAc,QAAO,KAAK;AACzC,SAAO,KAAK;AACd;AAEO,SAAS,mCACd,MACA,aACQ;AACR,QAAM,SAAS,2BAA2B,WAAW;AACrD,MAAI,WAAW,SAAU,QAAO,KAAK;AACrC,MAAI,WAAW,aAAc,QAAO,KAAK;AACzC,SAAO,KAAK;AACd;","names":[]}
|
package/package.json
CHANGED
|
@@ -18,9 +18,12 @@ export const TIME_FORMAT_OPTIONS = [
|
|
|
18
18
|
{ value: '12h', label: '12 horas (AM/PM)', displayValue: '12 horas (AM/PM)' },
|
|
19
19
|
];
|
|
20
20
|
|
|
21
|
+
// Catalog keys — consumers call translate(type) to get the localized label.
|
|
22
|
+
// pt-br values: 'Atualizações de projetos' | 'Alertas de segurança' |
|
|
23
|
+
// 'Mudanças no plano ou faturamento' | 'Manutenções programadas'
|
|
21
24
|
export const NOTIFICATION_TYPES = [
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
];
|
|
25
|
+
'common.account.notificationTypes.projectUpdates',
|
|
26
|
+
'common.account.notificationTypes.securityAlerts',
|
|
27
|
+
'common.account.notificationTypes.planBilling',
|
|
28
|
+
'common.account.notificationTypes.scheduledMaintenance',
|
|
29
|
+
] as const;
|
|
@@ -34,6 +34,10 @@ export default function CircularProgress({
|
|
|
34
34
|
aria-valuenow={current}
|
|
35
35
|
aria-valuemin={0}
|
|
36
36
|
aria-valuemax={total}
|
|
37
|
+
// i18n-TODO: aria-label hardcoded — CircularProgress has no 'use client' directive and
|
|
38
|
+
// receives no translate prop, so useTranslations() cannot be called here without
|
|
39
|
+
// converting it to a client component. Key to use: common.forms.progressAriaLabel ('Progresso').
|
|
40
|
+
// Either add 'use client' + useTranslations(), or accept a translate prop from the caller.
|
|
37
41
|
aria-label="Progresso"
|
|
38
42
|
>
|
|
39
43
|
<svg width={size} height={size} className="absolute">
|
|
@@ -55,6 +55,12 @@ const messages = {
|
|
|
55
55
|
},
|
|
56
56
|
|
|
57
57
|
account: {
|
|
58
|
+
notificationTypes: {
|
|
59
|
+
projectUpdates: 'Project updates',
|
|
60
|
+
securityAlerts: 'Security alerts',
|
|
61
|
+
planBilling: 'Plan or billing changes',
|
|
62
|
+
scheduledMaintenance: 'Scheduled maintenance',
|
|
63
|
+
},
|
|
58
64
|
deleteAccount: {
|
|
59
65
|
title: 'Delete account',
|
|
60
66
|
description:
|
|
@@ -410,6 +416,9 @@ const messages = {
|
|
|
410
416
|
tooSmallBodyNoFileWithDimension: 'The selected image is smaller than {dimensionText}. Upload an image with at least {dimensionText} to continue.',
|
|
411
417
|
tooSmallBodyNoFileGeneric: 'The selected image is smaller than the minimum required size. Upload a larger image to continue.',
|
|
412
418
|
sendAnother: 'Upload another',
|
|
419
|
+
errorSvg: 'SVG format is not supported. Use PNG, JPEG, WebP, or GIF.',
|
|
420
|
+
errorFormat: 'Unsupported format. Use PNG, JPEG, WebP, or GIF.',
|
|
421
|
+
errorTooLarge: 'File too large. Maximum {maxSize}MB.',
|
|
413
422
|
},
|
|
414
423
|
notifications: {
|
|
415
424
|
page: {
|
|
@@ -458,6 +467,41 @@ const messages = {
|
|
|
458
467
|
backToHome: 'Back to home',
|
|
459
468
|
},
|
|
460
469
|
|
|
470
|
+
// Planos: features e main features (mapApiPlanToUiPlan).
|
|
471
|
+
plans: {
|
|
472
|
+
features: {
|
|
473
|
+
unlimitedVisits: 'Unlimited visits',
|
|
474
|
+
unlimitedLeads: 'Unlimited leads',
|
|
475
|
+
sharePages: 'Share pages',
|
|
476
|
+
hosting: 'Hosting included',
|
|
477
|
+
freeTemplates: 'Free templates',
|
|
478
|
+
onboarding: 'Onboarding meeting',
|
|
479
|
+
projectManagement: 'Project management',
|
|
480
|
+
},
|
|
481
|
+
mainFeatures: {
|
|
482
|
+
pagesUnlimited: 'Unlimited pages',
|
|
483
|
+
pageSingular: '1 page',
|
|
484
|
+
pagesPlural: '{count} pages',
|
|
485
|
+
domainsUnlimited: 'Unlimited domains',
|
|
486
|
+
domainSingular: '1 external domain',
|
|
487
|
+
domainsPlural: '{count} external domains',
|
|
488
|
+
usersUnlimited: 'Unlimited users',
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
|
|
492
|
+
// Periodicidade de cobrança.
|
|
493
|
+
periodicity: {
|
|
494
|
+
monthly: 'Monthly',
|
|
495
|
+
semiannual: 'Semiannual',
|
|
496
|
+
annual: 'Annual',
|
|
497
|
+
suffixMonthly: '/month',
|
|
498
|
+
suffixSemiannual: '/semester',
|
|
499
|
+
suffixAnnual: '/year',
|
|
500
|
+
labelMonthly: 'monthly',
|
|
501
|
+
labelSemiannual: 'semiannual',
|
|
502
|
+
labelAnnual: 'annual',
|
|
503
|
+
},
|
|
504
|
+
|
|
461
505
|
languages: {
|
|
462
506
|
'pt-br': 'Portuguese (Brazil)',
|
|
463
507
|
'en-us': 'English (US)',
|
|
@@ -55,6 +55,12 @@ const messages = {
|
|
|
55
55
|
},
|
|
56
56
|
|
|
57
57
|
account: {
|
|
58
|
+
notificationTypes: {
|
|
59
|
+
projectUpdates: 'Actualizaciones de proyectos',
|
|
60
|
+
securityAlerts: 'Alertas de seguridad',
|
|
61
|
+
planBilling: 'Cambios en el plan o facturación',
|
|
62
|
+
scheduledMaintenance: 'Mantenimientos programados',
|
|
63
|
+
},
|
|
58
64
|
deleteAccount: {
|
|
59
65
|
title: 'Eliminar cuenta',
|
|
60
66
|
description:
|
|
@@ -411,6 +417,9 @@ const messages = {
|
|
|
411
417
|
tooSmallBodyNoFileWithDimension: 'La imagen seleccionada es menor que {dimensionText}. Sube una imagen de al menos {dimensionText} para continuar.',
|
|
412
418
|
tooSmallBodyNoFileGeneric: 'La imagen seleccionada es menor que el tamaño mínimo requerido. Sube una imagen más grande para continuar.',
|
|
413
419
|
sendAnother: 'Enviar otra',
|
|
420
|
+
errorSvg: 'El formato SVG no es compatible. Usa PNG, JPEG, WebP o GIF.',
|
|
421
|
+
errorFormat: 'Formato no compatible. Usa PNG, JPEG, WebP o GIF.',
|
|
422
|
+
errorTooLarge: 'Archivo demasiado grande. Máximo {maxSize}MB.',
|
|
414
423
|
},
|
|
415
424
|
notifications: {
|
|
416
425
|
page: {
|
|
@@ -459,6 +468,41 @@ const messages = {
|
|
|
459
468
|
backToHome: 'Volver al inicio',
|
|
460
469
|
},
|
|
461
470
|
|
|
471
|
+
// Planos: features e main features (mapApiPlanToUiPlan).
|
|
472
|
+
plans: {
|
|
473
|
+
features: {
|
|
474
|
+
unlimitedVisits: 'Visitas ilimitadas',
|
|
475
|
+
unlimitedLeads: 'Leads ilimitados',
|
|
476
|
+
sharePages: 'Compartir páginas',
|
|
477
|
+
hosting: 'Hosting incluido',
|
|
478
|
+
freeTemplates: 'Plantillas gratuitas',
|
|
479
|
+
onboarding: 'Reunión de Onboarding',
|
|
480
|
+
projectManagement: 'Gestión de proyectos',
|
|
481
|
+
},
|
|
482
|
+
mainFeatures: {
|
|
483
|
+
pagesUnlimited: 'Páginas ilimitadas',
|
|
484
|
+
pageSingular: '1 página',
|
|
485
|
+
pagesPlural: '{count} páginas',
|
|
486
|
+
domainsUnlimited: 'Dominios ilimitados',
|
|
487
|
+
domainSingular: '1 dominio externo',
|
|
488
|
+
domainsPlural: '{count} dominios externos',
|
|
489
|
+
usersUnlimited: 'Usuarios ilimitados',
|
|
490
|
+
},
|
|
491
|
+
},
|
|
492
|
+
|
|
493
|
+
// Periodicidade de cobrança.
|
|
494
|
+
periodicity: {
|
|
495
|
+
monthly: 'Mensual',
|
|
496
|
+
semiannual: 'Semestral',
|
|
497
|
+
annual: 'Anual',
|
|
498
|
+
suffixMonthly: '/mes',
|
|
499
|
+
suffixSemiannual: '/semestre',
|
|
500
|
+
suffixAnnual: '/año',
|
|
501
|
+
labelMonthly: 'mensual',
|
|
502
|
+
labelSemiannual: 'semestral',
|
|
503
|
+
labelAnnual: 'anual',
|
|
504
|
+
},
|
|
505
|
+
|
|
462
506
|
languages: {
|
|
463
507
|
'pt-br': 'Portugués (Brasil)',
|
|
464
508
|
'en-us': 'Inglés (EE. UU.)',
|