feat(areas): Fase 2c — UI multi-área no perfil e nas configurações da clínica
- perfil profissional: chips de áreas de atuação (getMyAreas/setMyAreas) - configurações da clínica: chips de áreas da unidade (getClinicaAreas/setClinicaAreas) - fix: handleSavePerfil agora envia logradouro/numero (rua/número não salvavam) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -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<any>({});
|
||||
const [allAreas, setAllAreas] = useState<{ slug: string; nome: string; cor: string }[]>([]);
|
||||
const [clinAreas, setClinAreas] = useState<string[]>([]);
|
||||
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 }> =
|
||||
<div><label className={LABEL_CLS}>Estado</label><input maxLength={2} className={`${FIELD_CLS} uppercase`} value={f.estado || ''} onChange={e => set('estado', e.target.value.toUpperCase())} /></div>
|
||||
<div><label className={LABEL_CLS}>Cor</label><input type="color" className="w-full h-10 border border-gray-200 rounded-xl px-1" value={f.cor || clinColor} onChange={e => set('cor', e.target.value)} /></div>
|
||||
</div>
|
||||
<div>
|
||||
<label className={LABEL_CLS}>Áreas de atuação da unidade</label>
|
||||
<div className="flex flex-wrap gap-2 mt-1">
|
||||
{allAreas.map(a => {
|
||||
const on = clinAreas.includes(a.slug);
|
||||
return (
|
||||
<button key={a.slug} type="button"
|
||||
onClick={() => setClinAreas(prev => on ? prev.filter(s => s !== a.slug) : [...prev, a.slug])}
|
||||
className={`text-[11px] font-black uppercase px-3 py-1.5 rounded-full border transition-all ${on ? 'text-white border-transparent' : 'text-gray-500 border-gray-200 bg-white hover:bg-gray-50'}`}
|
||||
style={on ? { backgroundColor: a.cor } : undefined}>
|
||||
{a.nome}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<p className="text-[10px] text-gray-400 mt-1">Uma unidade pode ter mais de uma área (ex.: odontologia + biomedicina).</p>
|
||||
</div>
|
||||
<div className="flex gap-2 pt-1">
|
||||
<button onClick={() => { setEditing(false); load(); }} className="px-4 py-2 border border-gray-200 rounded-xl text-[11px] font-black uppercase hover:bg-gray-50">Cancelar</button>
|
||||
<button onClick={save} disabled={saving} className="flex-1 py-2 bg-blue-600 text-white rounded-xl text-[11px] font-black uppercase disabled:opacity-50 flex items-center justify-center gap-2">{saving ? <Loader2 size={13} className="animate-spin" /> : <CheckCircle2 size={13} />} Salvar</button>
|
||||
|
||||
Reference in New Issue
Block a user