From ae1e1388b98bc09aacdeba9310299061f459ded7 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 21 May 2026 10:54:51 -0300 Subject: [PATCH] profile: UI dos campos de registro profissional (CFP #5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gap detectado em teste manual: migration 20260521000003 adicionou as 3 colunas (professional_registration_type/_number/_uf) e o DocumentGenerate.service.loadTherapistData ja le delas, mas a UI de edicao nao foi criada. ProfilePage.vue ganha novo card "Registro Profissional" (id= registro-profissional, cor #0ea5e9 ciano, antes do card de Redes Sociais): - Select tipo (CRP/CRM/CRFa/CREFITO/CRESS/CRN/RMS/outro — mesmas opcoes do CHECK constraint) - InputText numero - Select UF (27 estados, filterable) - Preview: "Aparecera nos documentos como: CRP 06/12345/SP" - Numero e UF disabled enquanto tipo nao escolhido Wire-up: SELECT/UPDATE do profile agora incluem as 3 colunas. form.* tem defaults vazios. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/views/pages/account/ProfilePage.vue | 121 +++++++++++++++++++++++- 1 file changed, 118 insertions(+), 3 deletions(-) diff --git a/src/views/pages/account/ProfilePage.vue b/src/views/pages/account/ProfilePage.vue index 79fd316..e23953f 100644 --- a/src/views/pages/account/ProfilePage.vue +++ b/src/views/pages/account/ProfilePage.vue @@ -103,6 +103,11 @@ const form = reactive({ bio: '', phone: '', + // Registro profissional (CFP #5 — exigido pra emissão de recibos/laudos) + professional_registration_type: '', + professional_registration_number: '', + professional_registration_uf: '', + site_url: '', social_instagram: '', social_youtube: '', @@ -117,6 +122,24 @@ const form = reactive({ notify_news: false }); +// Opções do CHECK constraint da migration 20260521000003 +const REGISTRATION_TYPE_OPTIONS = [ + { value: '', label: '— Não informado —' }, + { value: 'CRP', label: 'CRP — Psicólogo(a)' }, + { value: 'CRM', label: 'CRM — Médico(a)' }, + { value: 'CRFa', label: 'CRFa — Fonoaudiólogo(a)' }, + { value: 'CREFITO', label: 'CREFITO — Fisioterapeuta / T.O.' }, + { value: 'CRESS', label: 'CRESS — Assistente Social' }, + { value: 'CRN', label: 'CRN — Nutricionista' }, + { value: 'RMS', label: 'RMS — Residência Multiprofissional' }, + { value: 'outro', label: 'Outro' } +]; + +const UF_OPTIONS = [ + 'AC','AL','AP','AM','BA','CE','DF','ES','GO','MA','MT','MS','MG','PA','PB', + 'PR','PE','PI','RJ','RN','RS','RO','RR','SC','SP','SE','TO' +].map(uf => ({ value: uf, label: uf })); + const customSocials = ref([]); function addCustomSocial() { @@ -611,7 +634,7 @@ async function loadProfile() { const { data: prof, error: pErr } = await supabase .from('profiles') .select( - 'role, full_name, avatar_url, phone, bio, nickname, work_description, work_description_other, site_url, social_instagram, social_youtube, social_facebook, social_x, social_custom, language, timezone, notify_system_email, notify_reminders, notify_news' + 'role, full_name, avatar_url, phone, bio, nickname, work_description, work_description_other, site_url, social_instagram, social_youtube, social_facebook, social_x, social_custom, language, timezone, notify_system_email, notify_reminders, notify_news, professional_registration_type, professional_registration_number, professional_registration_uf' ) .eq('id', user.id) .maybeSingle(); @@ -631,6 +654,10 @@ async function loadProfile() { form.social_facebook = prof.social_facebook ?? ''; form.social_x = prof.social_x ?? ''; + form.professional_registration_type = prof.professional_registration_type ?? ''; + form.professional_registration_number = prof.professional_registration_number ?? ''; + form.professional_registration_uf = prof.professional_registration_uf ?? ''; + if (Array.isArray(prof.social_custom)) { customSocials.value = prof.social_custom; } @@ -707,7 +734,12 @@ async function saveAll() { notify_system_email: !!form.notify_system_email, notify_reminders: !!form.notify_reminders, - notify_news: !!form.notify_news + notify_news: !!form.notify_news, + + // Registro profissional (CFP) — null se vazio + professional_registration_type: String(form.professional_registration_type || '').trim() || null, + professional_registration_number: String(form.professional_registration_number || '').trim() || null, + professional_registration_uf: String(form.professional_registration_uf || '').trim() || null }; const { data: updatedProfile, error: pErr2 } = await supabase @@ -715,7 +747,7 @@ async function saveAll() { .update(profilePayload) .eq('id', userId.value) .select( - 'id, role, full_name, avatar_url, phone, bio, nickname, work_description, work_description_other, site_url, social_instagram, social_youtube, social_facebook, social_x, social_custom, language, timezone, notify_system_email, notify_reminders, notify_news, updated_at' + 'id, role, full_name, avatar_url, phone, bio, nickname, work_description, work_description_other, site_url, social_instagram, social_youtube, social_facebook, social_x, social_custom, language, timezone, notify_system_email, notify_reminders, notify_news, professional_registration_type, professional_registration_number, professional_registration_uf, updated_at' ) .single(); @@ -1105,6 +1137,89 @@ onBeforeUnmount(() => { + +
+
+ +
+
+ Registro Profissional +
+ +
Conselho regional
+
Exigido para emissão de recibos, atestados e laudos. Aparecerá no rodapé dos documentos.
+ +
+ +
+ +
+ + + + +
Estado do conselho.
+
+ + +
+
+ Aparecerá nos documentos como: + + {{ form.professional_registration_type }} + {{ form.professional_registration_number }}{{ form.professional_registration_uf ? '/' + form.professional_registration_uf : '' }} + +
+
+
+
+