import React, { useState } from 'react'; import { Building2, ArrowRight, Shield, MapPin, BadgeCheck, Palette, Save, Loader2, Plus, X } from 'lucide-react'; import { HybridBackend } from '../services/backend.ts'; import { PageHeader } from '../components/PageHeader.tsx'; import { EmptyState } from '../components/EmptyState.tsx'; import { useToast } from '../contexts/ToastContext.tsx'; // Cores profissionais permitidas const PRESET_COLORS = [ { name: 'Azul Score', value: '#2563eb' }, { name: 'Verde Esmeralda', value: '#059669' }, { name: 'Indigo Premium', value: '#4f46e5' }, { name: 'Vinho Elegante', value: '#9f1239' }, { name: 'Slate Moderno', value: '#334155' }, { name: 'Laranja Vibrante', value: '#ea580c' }, { name: 'Teal Clínico', value: '#0d9488' }, { name: 'Roxo Nobre', value: '#7c3aed' }, ]; export const ClinicasView: React.FC = () => { const workspaces = HybridBackend.getWorkspaces(); const activeWorkspace = HybridBackend.getActiveWorkspace(); const toast = useToast(); const currentRole = HybridBackend.getCurrentRole(); const isAdmin = currentRole === 'admin' || currentRole === 'donoclinica'; // Papel da CONTA (não da unidade ativa) — é o que o backend usa para decidir // se a nova unidade nasce como 'clinica' ou 'consultorio'. const accountRole = (() => { try { return JSON.parse(localStorage.getItem('SCOREODONTO_USER_DATA') || '{}').role as string | undefined; } catch { return undefined; } })(); const isConsultorioAccount = accountRole === 'donoconsultorio'; const unitLabel = isConsultorioAccount ? 'CONSULTÓRIO' : 'CLÍNICA'; const canCreate = ['donoclinica', 'donoconsultorio', 'admin'].includes(accountRole || ''); const [isEditingColor, setIsEditingColor] = useState(null); const [savingColor, setSavingColor] = useState(false); const [showCreate, setShowCreate] = useState(false); const [newNome, setNewNome] = useState(''); const [newDoc, setNewDoc] = useState(''); const [creating, setCreating] = useState(false); const handleCreate = async (e: React.FormEvent) => { e.preventDefault(); if (!newNome.trim()) return; setCreating(true); try { const result = await HybridBackend.createClinica(newNome.trim(), newDoc.trim() || undefined); if (!result.success) { toast.error(result.message || 'ERRO AO CRIAR UNIDADE.'); return; } // Recarrega a lista COMPLETA do servidor (acrescenta a nova unidade às existentes, // em vez de sobrescrever). A tela relê os workspaces no reload. await HybridBackend.refreshWorkspaces(); toast.success(`${unitLabel} CRIADA!`); setTimeout(() => window.location.reload(), 900); } catch { toast.error('ERRO DE CONEXÃO.'); } finally { setCreating(false); } }; const handleSwitch = (workspaceId: string) => { if (activeWorkspace?.id === workspaceId) { toast.info("VOCÊ JÁ ESTÁ NESTA UNIDADE."); return; } HybridBackend.switchWorkspace(workspaceId); toast.success("TROCANDO DE UNIDADE..."); }; const handleUpdateColor = async (workspaceId: string, color: string) => { setSavingColor(true); try { const token = localStorage.getItem('SCOREODONTO_AUTH_TOKEN'); const res = await fetch(`/api/clinicas/${workspaceId}/color`, { method: 'PUT', headers: { 'Content-Type': 'application/json', ...(token ? { 'Authorization': `Bearer ${token}` } : {}) }, body: JSON.stringify({ cor: color }) }); if (res.ok) { toast.success("COR DA UNIDADE ATUALIZADA!"); // Atualizar o localStorage local para refletir a mudança sem refresh imediato no objeto workspaces const updatedWorkspaces = workspaces.map(w => w.id === workspaceId ? { ...w, cor: color } : w); localStorage.setItem('SCOREODONTO_WORKSPACES', JSON.stringify(updatedWorkspaces)); // Se a clínica editada for a ativa, atualizamos ela também if (activeWorkspace?.id === workspaceId) { localStorage.setItem('SCOREODONTO_ACTIVE_WORKSPACE', JSON.stringify({ ...activeWorkspace, cor: color })); } setIsEditingColor(null); // Forçamos um reload após um pequeno delay para aplicar as cores globalmente via CSS/Variables se necessário setTimeout(() => window.location.reload(), 1000); } else { toast.error("ERRO AO SALVAR COR."); } } catch (err) { toast.error("ERRO DE CONEXÃO."); } finally { setSavingColor(false); } }; return (
{canCreate && (
)} {workspaces.length === 0 && ( )}
{workspaces.map((ws) => { const isActive = activeWorkspace?.id === ws.id; const clinColor = ws.cor || '#2563eb'; return (
{isActive && ( ATIVA )} {isAdmin && ( )}

{ws.nome}

{isEditingColor === ws.id ? (

Escolha a cor da marca

{PRESET_COLORS.map(c => ( ))}
) : ( <>
Unidade Operacional

Seu Perfil

{ws.role}

)}
); })}

Identidade Visual Dinâmica

A cor escolhida será aplicada automaticamente em toda a interface desta clínica.

{PRESET_COLORS.slice(0, 4).map(c => (
))}
{showCreate && (
{ if (!creating) setShowCreate(false); }} >
e.stopPropagation()}>

Nova {unitLabel.toLowerCase()}

setNewNome(e.target.value.toUpperCase())} className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-teal-500 outline-none text-sm font-medium uppercase" placeholder={isConsultorioAccount ? 'EX: DR. SILVA - CONSULTÓRIO' : 'EX: CLÍNICA SORRISO'} />
setNewDoc(e.target.value)} className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-teal-500 outline-none text-sm font-medium" placeholder="00.000.000/0000-00" />
)}
); };