Card de contato sempre visível no perfil do profissional

TLDR: o spec original assumia que o card de contato precisava ser construído do zero; na verdade ele já existe e convive com o widget de Agenda — o trabalho real é generalizar uma migração já em andamento para que o contato apareça para qualquer visitante.

Contexto

O spec original partia de uma premissa errada: que hoje existe só o widget de Agenda, e que o card de contato precisa ser construído do zero. Isso não é verdade — os dois componentes já existem e já convivem no mesmo container:

  • TerapistContact.tsx (src/containers/PublicProfile/components/) — card “Informações de Contato” completo: telefone, localização, e-mail, botão WhatsApp (wa.me/:number).
  • ProfileScheduler.tsx (mesma pasta) — o widget “Agenda” (calendário), título literal "Agenda", usa TRGScheduleCalendar.

A escolha entre os dois não é por tipo de profissional/plano — é por quem está vendo a página:

```ruby # trgclub-api/app/models/therapist_sections_manager.rb SECTIONS = { therapist: [“personal_contact”], patient: [“scheduling”] }.freeze

def sections return SECTIONS[:therapist] if user_logged? && user.is_therapist? SECTIONS[:patient] end ```

Chamado em Api::V1::TherapistsController com current_user = o visitante, não o dono do perfil. Hoje, um terapeuta logado vendo qualquer perfil público vê o card de contato; um visitante anônimo ou paciente vê a Agenda — independente de quem seja o profissional.

No frontend isso é consumido em PublicProfile.tsx (showTerapistContact / showSchedulling), com um fallback controlado pela feature flag Flag.COST_REDUCTION_PHASE_ONE: se a flag estiver desligada, sempre mostra Agenda, ignorando a lógica de seções.

As duas telas de referência do spec original (Vilson e Maria) muito provavelmente diferem pela sessão de quem tirou o print (terapeuta logado vs. não), não por serem profissionais de tiers diferentes. O badge “Master CITRG” é outra lógica, completamente desacoplada (user_has_valid_master_certificate? em user_profile.rb), só afeta o selo no header, não a sidebar.

Status das outras 3 histórias do spec original

História Spec original assumia Realidade no código
Vídeo Feature nova Já implementada por completo: campo video_url em UserProfile, upload via UserVideo.tsx, renderização com link “Assista meu vídeo” + modal em TerapeutaCardHeader.tsx. Tratar como verificação, não implementação.
Truncamento de bio Componente novo Componente reutilizável já existe: src/components/ui/TrucatedText/index.tsx (Typography com line-clamp + prop lines). O trabalho é aplicar esse componente ao campo de bio, não construir um novo.
Bandeiras de idioma Componente novo Confirmado como 100% trabalho novo. Não existe mapa idioma→bandeira; hoje idiomas são só texto (languages: string[] em TerapeutaCard.tsx).

Objetivos

  1. TherapistSectionsManager#sections deixa de depender de current_user (visitante) — sempre retorna ["personal_contact"], para qualquer tipo de visitante (anônimo, paciente, terapeuta).
  2. Renomear/ajustar o método e a classe se TherapistSectionsManager/SECTIONS deixar de fazer sentido sem a branch de paciente (remover a chave :patient e a lógica de scheduling se não for usada em mais nenhum lugar).
  3. Frontend: remover o fallback controlado por Flag.COST_REDUCTION_PHASE_ONE em PublicProfile.tsx — a flag deixa de ser condição para mostrar contato.
  4. ProfileScheduler.tsx deixa de ser importado/renderizado em PublicProfile.tsx (o componente e toda a stack de Availability/AvailabilityTool::* permanecem intactos — usados no fluxo de agendamento de reuniões e configuração de disponibilidade do terapeuta).
  5. Testes: request spec cobrindo os 3 papéis de visitante (anônimo, paciente, terapeuta) recebendo personal_contact em todos os casos.
  6. QA manual: validar formato do link wa.me para telefones salvos sem DDI (dado legado).
  7. Confirmar que os cenários das Histórias 2 (vídeo) e 3 (bio) já passam contra o ambiente atual antes de abrir PR.
  8. História 4 (bandeiras): manter o use case/componente sugerido no spec original (<LanguageTag idioma="pt-BR" /> + mapa centralizado idioma→bandeira) — único item 100% novo.

Fora de escopo

  • Não dá para depreciar o backend de Agenda: Availability, AvailabilityTool::*, Availabilities::FindByUser/DestroyByUser e TherapistAvailableTimes::UpdateByProfile continuam usados no fluxo de agendamento de reuniões e na configuração de disponibilidade do terapeuta (onboarding).
  • Extrair um utilitário compartilhado para montar o link do WhatsApp (hoje duplicado em TerapistContact.tsx, Menu/constants.ts, Footer/constants.ts) — boa oportunidade, mas fora do escopo para manter o PR pequeno.
  • Corrigir o typo Trucated → Truncated na pasta do componente de bio — pode ir no mesmo PR ou em um ticket de cleanup separado.

Mudanças

  • trgclub-api app/models/therapist_sections_manager.rb — sections sempre retorna ["personal_contact"].
  • PublicProfile.tsx — remove o fallback de Flag.COST_REDUCTION_PHASE_ONE e a renderização condicional de ProfileScheduler.tsx.
  • Use case sugerido no spec original (exibir_informacoes_contato.rb) precisa de nome em inglês, no padrão Namespace::Action do projeto (ex.: Invitations::AcceptFlow) — nome correto seria algo como TherapistContacts::Show.
  • Não existe campo whatsapp dedicado — o link é derivado do campo phone (+ phone_country); confirmar que todo phone salvo tem DDI antes de virar link wa.me.

Como verificar

```gherkin Cenário: Visitante anônimo vê o card de contato Dado que não estou autenticado Quando acesso a página de perfil de qualquer profissional Então devo ver o card “Informações de contato” na lateral direita E não devo ver o widget de “Agenda” com calendário

Cenário: Paciente logado vê o card de contato Dado que estou autenticado como paciente Quando acesso a página de perfil de qualquer profissional Então devo ver o card “Informações de contato” na lateral direita E não devo ver o widget de “Agenda” com calendário

Cenário: Terapeuta logado vê o card de contato (comportamento já existente, mantido) Dado que estou autenticado como terapeuta Quando acesso a página de perfil de qualquer profissional Então devo ver o card “Informações de contato” na lateral direita

Cenário: Botão de WhatsApp Dado que estou no card de informações de contato Quando clico no botão “WhatsApp” Então devo ser redirecionado para o WhatsApp com o número do profissional já preenchido, incluindo o DDI

Cenário: Feature flag de rollout não altera mais o resultado Dado que a flag “COST_REDUCTION_PHASE_ONE” está desligada para o meu usuário Quando acesso a página de perfil de qualquer profissional Então devo ver o card “Informações de contato” da mesma forma que veria com a flag ligada ```

Documentação

— (não registrado no documento original)