diff --git a/frontend/services/backend.ts b/frontend/services/backend.ts index 9b04f2f..f3b8e8c 100644 --- a/frontend/services/backend.ts +++ b/frontend/services/backend.ts @@ -738,6 +738,15 @@ export const HybridBackend = { return r.ok; } catch { return false; } }, + getClinicaAreas: async (clinicaId: string): Promise => { + try { const r = await apiFetch(`${API_URL}/clinicas/${clinicaId}/areas`); const d = r.ok ? await r.json() : {}; return Array.isArray(d?.areas) ? d.areas : []; } catch { return []; } + }, + setClinicaAreas: async (clinicaId: string, areas: string[]): Promise => { + try { + const r = await apiFetch(`${API_URL}/clinicas/${clinicaId}/areas`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ areas }) }); + return r.ok; + } catch { return false; } + }, // Semeia o catálogo de biomedicina estética no workspace ativo (idempotente). seedBiomedicina: async (): Promise => { diff --git a/frontend/views/ConfiguracoesView.tsx b/frontend/views/ConfiguracoesView.tsx index 24e9db3..90068ee 100644 --- a/frontend/views/ConfiguracoesView.tsx +++ b/frontend/views/ConfiguracoesView.tsx @@ -95,11 +95,17 @@ const UnidadePerfilCard: React.FC<{ workspaceId?: string; clinColor: string }> = const [editing, setEditing] = useState(false); const [saving, setSaving] = useState(false); const [f, setF] = useState({}); + const [allAreas, setAllAreas] = useState<{ slug: string; nome: string; cor: string }[]>([]); + const [clinAreas, setClinAreas] = useState([]); + useEffect(() => { HybridBackend.getAreas().then(setAllAreas); }, []); const load = async () => { if (!workspaceId) { setLoading(false); return; } setLoading(true); - try { const r = await HybridBackend.getClinicaProfile(workspaceId); if (r.success) setF(r.clinica || {}); } + try { + const r = await HybridBackend.getClinicaProfile(workspaceId); if (r.success) setF(r.clinica || {}); + setClinAreas(await HybridBackend.getClinicaAreas(workspaceId)); + } catch { /* ignore */ } finally { setLoading(false); } }; useEffect(() => { load(); }, [workspaceId]); @@ -126,6 +132,7 @@ const UnidadePerfilCard: React.FC<{ workspaceId?: string; clinColor: string }> = logradouro: f.logradouro, numero: f.numero, bairro: f.bairro, cidade: f.cidade, estado: f.estado, cep: f.cep, }); if (!r.success) { toast.error(r.message || 'ERRO AO SALVAR.'); return; } + await HybridBackend.setClinicaAreas(workspaceId, clinAreas); toast.success('DADOS DA UNIDADE ATUALIZADOS!'); setEditing(false); } catch { toast.error('ERRO AO SALVAR.'); } finally { setSaving(false); } }; @@ -172,6 +179,23 @@ const UnidadePerfilCard: React.FC<{ workspaceId?: string; clinColor: string }> =
set('estado', e.target.value.toUpperCase())} />
set('cor', e.target.value)} />
+
+ +
+ {allAreas.map(a => { + const on = clinAreas.includes(a.slug); + return ( + + ); + })} +
+

Uma unidade pode ter mais de uma área (ex.: odontologia + biomedicina).

+
diff --git a/frontend/views/plugins/ProfissionaisPlugin.tsx b/frontend/views/plugins/ProfissionaisPlugin.tsx index 31e95ef..60920f4 100644 --- a/frontend/views/plugins/ProfissionaisPlugin.tsx +++ b/frontend/views/plugins/ProfissionaisPlugin.tsx @@ -156,7 +156,7 @@ export const ProfissionaisPlugin: React.FC = () => { // buscar const [lista, setLista] = useState([]); - const [areas, setAreas] = useState<{ slug: string; nome: string }[]>([]); + const [areas, setAreas] = useState<{ slug: string; nome: string; cor: string }[]>([]); const [fArea, setFArea] = useState(''); const [fTipo, setFTipo] = useState(''); const [fEstado, setFEstado] = useState(''); @@ -166,6 +166,7 @@ export const ProfissionaisPlugin: React.FC = () => { const [fRaio, setFRaio] = useState(''); // perfil const [perfil, setPerfil] = useState(null); + const [myAreas, setMyAreas] = useState([]); const [savingPerfil, setSavingPerfil] = useState(false); // propostas const [propostas, setPropostas] = useState<{ enviadas: Proposta[]; recebidas: Proposta[] }>({ enviadas: [], recebidas: [] }); @@ -214,7 +215,10 @@ export const ProfissionaisPlugin: React.FC = () => { const fetchPerfil = useCallback(async () => { setLoading(true); - try { const res = await apiFetch('/api/profissionais/perfil'); if (res.ok) setPerfil(await res.json()); } + try { + const res = await apiFetch('/api/profissionais/perfil'); if (res.ok) setPerfil(await res.json()); + setMyAreas(await HybridBackend.getMyAreas()); + } catch { /* silently fail */ } finally { setLoading(false); } }, []); @@ -253,13 +257,15 @@ export const ProfissionaisPlugin: React.FC = () => { const res = await apiFetch('/api/profissionais/perfil', { method: 'PUT', body: JSON.stringify({ - estado: perfil.estado, cidade: perfil.cidade, bairro: perfil.bairro, cep: perfil.cep, + estado: perfil.estado, cidade: perfil.cidade, bairro: perfil.bairro, + logradouro: perfil.logradouro, numero: perfil.numero, cep: perfil.cep, especialidade: perfil.especialidade_dir, raio_atuacao_km: perfil.raio_atuacao_km, bio_profissional: perfil.bio_profissional, disponivel_diretorio: perfil.disponivel_diretorio === true, }), }); const data = await res.json(); if (!res.ok) throw new Error(data.error || 'Erro ao salvar.'); + await HybridBackend.setMyAreas(myAreas); toast.success('PERFIL PROFISSIONAL ATUALIZADO!'); } catch (e: any) { toast.error(e.message.toUpperCase()); } finally { setSavingPerfil(false); } @@ -480,6 +486,23 @@ export const ProfissionaisPlugin: React.FC = () => { setP('raio_atuacao_km', e.target.value === '' ? null : +e.target.value)} placeholder="EX: 100" />
+
+ +
+ {areas.map(a => { + const on = myAreas.includes(a.slug); + return ( + + ); + })} +
+

Você pode atuar em mais de uma área (ex.: dentista que também faz harmonização).

+