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", usaTRGScheduleCalendar.
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
TherapistSectionsManager#sectionsdeixa de depender decurrent_user(visitante) — sempre retorna["personal_contact"], para qualquer tipo de visitante (anônimo, paciente, terapeuta).- Renomear/ajustar o método e a classe se
TherapistSectionsManager/SECTIONSdeixar de fazer sentido sem a branch de paciente (remover a chave:patiente a lógica deschedulingse não for usada em mais nenhum lugar). - Frontend: remover o fallback controlado por
Flag.COST_REDUCTION_PHASE_ONEemPublicProfile.tsx— a flag deixa de ser condição para mostrar contato. ProfileScheduler.tsxdeixa de ser importado/renderizado emPublicProfile.tsx(o componente e toda a stack deAvailability/AvailabilityTool::*permanecem intactos — usados no fluxo de agendamento de reuniões e configuração de disponibilidade do terapeuta).- Testes: request spec cobrindo os 3 papéis de visitante (anônimo, paciente, terapeuta) recebendo
personal_contactem todos os casos. - QA manual: validar formato do link
wa.mepara telefones salvos sem DDI (dado legado). - Confirmar que os cenários das Histórias 2 (vídeo) e 3 (bio) já passam contra o ambiente atual antes de abrir PR.
- 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/DestroyByUsereTherapistAvailableTimes::UpdateByProfilecontinuam 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→Truncatedna pasta do componente de bio — pode ir no mesmo PR ou em um ticket de cleanup separado.
Mudanças
trgclub-apiapp/models/therapist_sections_manager.rb—sectionssempre retorna["personal_contact"].PublicProfile.tsx— remove o fallback deFlag.COST_REDUCTION_PHASE_ONEe a renderização condicional deProfileScheduler.tsx.- Use case sugerido no spec original (
exibir_informacoes_contato.rb) precisa de nome em inglês, no padrãoNamespace::Actiondo projeto (ex.:Invitations::AcceptFlow) — nome correto seria algo comoTherapistContacts::Show. - Não existe campo
whatsappdedicado — o link é derivado do campophone(+phone_country); confirmar que todophonesalvo tem DDI antes de virar linkwa.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)