Pular para o conteúdo principal
← Voltar ao changelog

Changelog - 30/04/2026

Dia muito pesado: 27 PRs no base + 8 PRs no core. O core foi quase todo dedicado a expandir o @cactus-agents/i18n para alimentar a leva grande de novas variants do base (mobile bottom nav, footer-stacked, quick-access menu, side sheets, tournament detail, FTD offer/cashback). No base, o destaque foi a reformulação completa do MobileBottomNav com 4 variantes tipadas, novo primitive CtaButton, footer-stacked do 7k-bet-br e revamp da página de detalhe de torneios.

i18n / Internacionalização

  • @cactus-agents/i18n recebeu 4 PRs de chaves novas no mesmo dia (#157, #158, #159, #160), todas em pt-br (autoritativo) + pt + es + en. Cada PR cobre um surface novo do base: mobile_nav.* para variantes de bottom nav, tournaments.* para a tela de detalhe, quick-access menu + side sheets, e footer-stacked.
  • mobile_nav expandido (PR #157, core): de home/casino/sports/deposit/menu para 13 intents — tournaments, missions, promotions, rewards, referral, wallet, profile, store, slots, withdraw, casino_live, sports_live. Suporta os 4 variants novos do MobileBottomNav (flat, trail-cta, fab-center, illustrated) sem brand precisar declarar namespace próprio.
  • tournaments.* na gamification (PR #158, core): 5 chaves para a revamp da tournament detail — information (título do stats carousel), show_more/show_less (collapse/expand das descrições e tabs), no_players/no_prizes (empty states de ranking e prêmios).
  • Quick-access menu + side sheets (PR #159, core): chaves nos namespaces layout, casino e gamification para o novo widget + no header e os painéis laterais de Favoritos, Recentes e Notificações usados em 7k-bet-br e cl-bet7k-com.
  • Footer-stacked (PR #160, core): 14 chaves por locale para o novo variant — col_doubts, col_vip_games, vip_*, payment_label, download_app_label, back_to_top_cta, central_atendimento. Antes os textos viviam na pasta overrides/7k-bet-br/app/locales e bloqueavam o uso compartilhado entre brands.
  • ftd_offer e ftd_cashback no namespace payments (PRs #152 e #155, core): chaves para o modal de oferta FTD e o fluxo de cashback FTD (D0) — first_modal.* e prize_modal.*. PT-BR neutra e brand-agnostic; PT, ES, EN traduzidos.
  • favorites.empty_* e recently_played.empty_* (PR #153, core): chaves para o EmptyRowPlaceholder quando o usuário tem favoritos/recentes vazios — labels de scroll, aria-labels do botão e variantes com sugestões ao lado.
  • casino:show_filters/hide_filters (PR #438, base via bump i18n ^0.78.0): chaves para o toggle de filtros recolhíveis nas páginas de games.
  • Normalização "Casino" → "Cassino" para BRA (PR #432, base): hook useCasinoNomenclature aplica regex whole-word só quando countryCode === "BRA" — corrige o fato do BFF retornar nomenclature_for_casino_games = "Casino" (com um 's') que vencia o i18n correto via fallback ||. Workaround temporário enquanto o @cactus-agents/brand.transformFeatures() está congelado; outros países (pt-PT, es-ES, en-GB) passam direto porque "Casino" é gramaticalmente correto neles.

Gamificação

  • Tournament detail revamp completo (PR #441): a rota vip/tournaments.$id.tsx passou de 304 linhas monolíticas para uma composição de 11 componentes novos em app/components/gamification/tournament-detail/TournamentHero, RegistrationCTA, TournamentDescription (com show_more/show_less), TournamentDetailTabs, TournamentStatsCarousel + TournamentStatCard, TournamentPrizesList + PrizeRow, TournamentRankingList, e helpers utilitários.
  • Sizing dos cards de missão e torneio é configurável por brand via app/types/mission-card.ts e app/types/tournament-card.ts novos. Brands 7k-bet-br, cl-bet7k-com declararam o widgets/mission-card.ts + widgets/tournament-card.ts próprios.
  • MissionCardClassic/Stacked e TournamentCardClassic/Stacked agora usam o novo primitive CtaButton em vez de implementar botão próprio — convergência visual entre cards e signature header.

UI e Componentes

  • Novo primitive CtaButton (PR #431, app/components/ui/cta-button/): substitui implementações ad-hoc de botão CTA em LoginModal, RegisterModal, GameCardClassic, GameIframe, DepositForm, HeaderUserArea e nos cards de missão/torneio. Vem em 2 variants — flat (botão sólido tradicional) e signature (estilo do botão "Depositar" do header 7k com brilho/gradient). Configurável por brand via app/config/widgets/cta-button.ts. Cobertura completa de tests (CtaButton.test.tsx, CtaButton.config.test.tsx).
  • MobileBottomNav reescrito do zero como sistema de variants tipado (PR #430): o componente legado (app/components/layout/MobileBottomNav.tsx, 204 linhas) foi removido. Substituído por dispatcher + 4 variants em app/layouts/variants/mobile-bottom-nav/MobileBottomNavFlat (5 tiles iguais), MobileBottomNavTrailCta (4 tiles + CTA destacado à direita), MobileBottomNavFabCenter (FAB no centro estilo Material), MobileBottomNavIllustrated (tiles com ilustração). Catálogo de intents typed (intents.ts), resolver com fallback (resolve.ts), specials (specials.ts), handlers compartilhados, plus shared shells (BottomNavShell, CtaPill, FabButton, NavTile, RotatingLabel). Cobertura: resolve.test.ts (102 linhas) + variants.test.tsx (213 linhas).
  • CTA de depósito alinhado entre header / mobile-nav / game fullscreen (PR #439): o CtaPill do mobile-bottom-nav e o overlay do GameIframe agora reaproveitam o variant signature do CtaButton, evitando 3 implementações divergentes do mesmo botão "Depositar".
  • Filtros do cassino recolhíveis (PR #438): aplicado em /games, /games/live, /games/category/:slug e /games/providers/:slug. Novo ícone de filtro à esquerda da busca expande/recolhe o bloco de categorias e providers in-place. Mobile e desktop começam com filtros escondidos.
  • Breadcrumb do detalhe de jogo (PR #434): adicionada etapa "Início" como primeiro link e listagem do provider antes do nome do jogo (Início > Provider > Jogo). app/components/layout/InternalNavBar.tsx e app/routes/games/$provider.$game.tsx.
  • StoriesCircles ganha overlay de badge "NEW" (PR #453): novo campo badge em StoriesConfig controla enabled, asset e índices 1-based dos circles que recebem o ribbon. Asset padrão /assets/stories/new-badge.png é trocado pelo override overrides/<brand>/public/assets/stories/new-badge.png. Os 14 brand overrides ganharam o bloco badge preparado (enabled: false); ativado para 7k-bet-br (pt-br) e cl-bet7k-com (es) com items [1, 2].
  • FavoriteButton e LastGameFloatingWidget (PR #442): correção de SVG fill handling no botão de favoritar e ajustes de layout no widget flutuante de "última jogada".
  • Quick-access menu + side sheets (PR #445): novo widget + no header de 7k-bet-br e cl-bet7k-com abre painéis laterais para Favoritos, Recentes e Notificações. Adicionado widgets/quick-access-menu.ts no override do cl-bet7k-com; rotas e flags propagadas em todos os 14 brand overrides.

Cassino

  • Sidebar não roteia mais "Mines" e "Aviator" pro provider errado (PR #437): ambos estavam apontando para o provider Spribe, mas a curadoria desses jogos no catálogo Cactus é via Banana Games. Correção em app/config/layout/sidebar.ts e nos 11 brand overrides afetados.
  • Item permanente "Mini Games Diários" na sidebar do 7k-bet-br (PR #440): adicionado ao sidebar-buttons config do 7k. Doc operacional nova em docs/features/strategy/overview.md cobrindo a feature.
  • Rows pessoais (Favoritos / Jogados Recentemente) escondidas quando vazias (PR #436): novo flag hidePersonalRowsWhenEmpty em features.ts. Quando ativo, FavoritesRow e RecentlyPlayedRow somem da home se o usuário não tem dado em vez de mostrar empty state. Default false em todos os 14 overrides; ativado só no 7k-bet-br. Hook novo useRecentlyPlayedSlugs em app/hooks/.

Pagamentos

  • Allow-list de métodos de pagamento por brand + agrupamento de Pix providers (PR #435): app/config/payments/methods.ts e app/types/payments-config.ts novos. Brand declara quais métodos aceita; múltiplos providers de Pix são agrupados visualmente no DepositForm. Hook usePayments ganhou +83 linhas para resolver a lista permitida e o agrupamento.
  • Withdraw "Valor máximo" mostra cap da casa, não saldo do usuário (PR #450): a célula "Máximo" no WithdrawForm estava puxando availableBalance do user. Trocado para o teto que a casa permite por transação — fim das confusões em saques limitados pela política do operador.

Auth

  • Kill-switch front-end disableSocialAuth (PR #457): nova flag em app/config/features/auth.ts (type em app/types/auth-features.ts). Quando ligada, o RegisterModal esconde os botões "Continuar com Google/Facebook" e o SocialAccountsSection da área de Segurança fica oculto. Propagada para os 14 brand overrides com default false.

Sports

  • Header secundário pode ser renderizado dentro do header sticky em páginas de esportes (PR #469): novo flag em LayoutConfig + suporte nos shells HeaderTopShell e SplitShell. Adicionado secondaryHeader.stickyInsideHeader ao type. Ativado no overrides/7k-bet-br/app/config/layout/composition.ts.
  • useSportsAvailableHeight com ResizeObserver (PR #470): substitui o cálculo via useEffect + window.resize por observação contínua do header — o iframe do sportsbook se reajusta dinamicamente quando o header secundário muda de altura (ex: quando colapsa em scroll).
  • SEO copy do sports-seo do 7k removido (PR #466): conteúdo grande de copy SEO comentado em overrides/7k-bet-br/app/config/seo/sports-seo.ts para revisão futura. Rota de sports continua respondendo, só sem o bloco.
  • Novo variant footer-stacked para 7k-bet-br (PR #454): footer reorganizado em 6 partes empilhadas — FooterStackedMain (com 4 colunas: VIP games, dúvidas, downloads, central de atendimento), FooterStackedHeartRow, FooterStackedSeals, FooterStackedSponsors, FooterStackedPaymentBar, FooterStackedBottomBar, FooterStackedLegal. Inclui novo asset public/assets/seals/google-play.png. Config nova app/config/widgets/footer-socials.ts permite brand declarar quais redes sociais aparecem no footer.
  • topbarNotification agora é configurável via LayoutConfig (PR #455): adicionado em overrides/7k-bet-br/app/config/layout/composition.ts para deixar a barra de notificações controlada pelo composition em vez de hardcoded no shell.
  • Logo da sidebar do 7k-bet-br (PR #452): redimensionada para 52x24 e alinhada à esquerda.

Brand Overrides

  • 7k-bet-br absorveu o grosso do dia: MobileBottomNav variant configurada, sidebar-buttons com novo intent store (item "Loja" como 5º), footer-stacked ligado, topbarNotification no composition, sports header sticky com secondary nav inside, novo widgets/strategy/strategy.ts para o item permanente "Mini Games Diários", logo da sidebar shrunk, stories badge ativado em items [1, 2], hidePersonalRowsWhenEmpty: true, widgets/footer-socials.ts declarado.
  • cl-bet7k-com (chile, es): quick-access menu + side sheets ligados, widgets/quick-access-menu.ts adicionado, stories badge ativado em items [1, 2], widgets/cta-button.ts, widgets/mission-card.ts e widgets/tournament-card.ts declarados.
  • Propagação file-replacement em todos os 14 overrides (regra dura do brandOverridesPlugin): hidePersonalRowsWhenEmpty: false, notificationsSheet: { enabled: true }, disableSocialAuth: false, widgets/stories.ts com badge.enabled: false, novos paths em routes/paths.ts, widgets/cta-button.ts opcionais. PR #436 documenta o resolve de conflict entre hidePersonalRowsWhenEmpty (PR atual) e notificationsSheet (stage) em todos os overrides.
  • Sidebar do cassino corrigida em 11 overrides (7k-bet-br, betpontobet-bet-br, cassino-bet-br, ng-7k-bet, pb-bet, ph-state77-com, pt-state77-com, rj-bet, state77-com, vera-bet-br, x2b-bet): "Mines" e "Aviator" agora apontam para Banana Games em vez de Spribe.
  • sidebar-buttons do 7k-bet-br ganhou intent store apontando para a rota canônica gamification.store com ícone ShoppingBag. SidebarButtonIntent virou união backwards-compatível — outros brands não precisam fazer nada.

Segurança

  • Bloqueio de leak cross-user de saldo via cache classification (PR #428): bump de @cactus-agents/platform-cache para 0.12.0 + 85 linhas novas de classificação no workers/middleware.ts. Endpoints sensíveis a usuário (saldo, KYC status, transações) agora são marcados explicitamente para nunca atravessar o cache compartilhado da Cloudflare Cache API; só o cache scopado por user-key passa. Resolve incident report do dia anterior onde um usuário viu saldo de outro depois de um cache hit equivocado.
  • Suporte ao chat Zendesk abre instantâneo (PR #465): removido o setTimeout(..., 5000) legado do useLiveSupport que segurava o widget por 5s "esperando o script carregar". O script já tem promise própria de ready — o delay extra era redundante e quebrava o UX em sessões de suporte urgentes.

Strategy / Campaigns

  • strategy-campaign-api.client refatorado (PR #448): cliente de Campaign API trocou de fluxo imperativo (initfetchdispatch) para uma promise única que devolve user state + campaign manifest. app/store/strategy.ts fica mais enxuto (-26 linhas), tipos simplificados em app/types/strategy.ts. CampaignWidget.tsx consome o novo shape direto. Tests atualizados (strategy-campaign-api.client.test.ts: 192 linhas; strategy.test.ts: 71 linhas).

Core / SDK

8 PRs no front-cactus-core no mesmo dia — uma das maiores levas dos últimos 30 dias.

  • @cactus-agents/i18n ganhou 4 PRs consecutivos (#157 → 0.75.0, #158 → 0.78.x, #159 → 0.8x.0, #160 → 0.81.0). Todas as 4 keys-libraries seguem o pattern: pt-br autoritativo, pt + es + en como traduções equivalentes, brand-agnostic. As surfaces cobertas (mobile_nav expandido, tournaments detail, quick-access menu, footer-stacked) liberaram o base para parar de injetar traduções via app/locales/overrides/ (cumprindo a regra dura do AGENTS.md: traduções novas vão no core, não no base).
  • @cactus-agents/payments locales (PRs #152 e #155): namespaces ftd_offer.* (4 locales × 15 keys = 60 keys) e ftd_cashback.{first_modal,prize_modal}.* adicionados ao packages/i18n/locales/{pt-br,pt,es,en}/payments.json. Alimentam o modal de oferta FTD e o fluxo de cashback FTD (D0) que o base vai shipar nos próximos dias.
  • @cactus-agents/i18n com chaves de empty state pra Favoritos / Recentes (PR #153): casino.favorites.empty_scroll_label, empty_scroll_label2, empty_scroll_aria, empty_casino_aria + casino.recently_played.empty_scroll_aria. Suporta o EmptyRowPlaceholder do base nos modos com sugestões ao lado e variant botão.
  • @cactus-agents/brand com guards de OTP frequente e KYC integration (PR #156): transform/features.ts ganhou +50 linhas e bateria de tests (94 linhas em brand.test.ts). A função transformFeatures agora valida e gateia módulos de OTP frequente e integração KYC vindos do BFF antes de expô-los ao base — evita que feature flag mal-configurada do admin estoure UI no front.

Infra / CI / Deploy

  • Deploy prod-7k-bet-br agora sai da branch main-7k (PR #458, base): correção em .github/workflows/ci-deploy.yml — antes apontava para main, o que casava com o staging unificado mas não com o pipeline de produção do 7k que vive numa branch separada. Sem isso, hotfixes do 7k vinham com bundle errado.