import React, { useState, useEffect, useCallback, useRef } from 'react'; import { GraduationCap, MessageSquare, Clock, CheckCircle2, XCircle, ChevronRight, ArrowLeft, Send, Loader2, User, Camera, Activity, FileText, Heart, Stethoscope, ShieldAlert, DollarSign, Banknote } from 'lucide-react'; import { HybridBackend } from '../services/backend.ts'; import { useToast } from '../contexts/ToastContext.tsx'; import { PageHeader } from '../components/PageHeader.tsx'; // ─── Tipos ──────────────────────────────────────────────────────── interface Mensagem { id: string; autor_tipo: 'CLINICA' | 'TUTOR'; autor_nome?: string; conteudo: string; created_at: string; } interface Solicitacao { id: string; tratamento_id: string; paciente_nome?: string; tutor_nome?: string; tipo: string; descricao?: string; status: string; created_at: string; total_mensagens?: number; mensagens?: Mensagem[]; fotos?: { id: string; url: string; slot: string }[]; // Financeiro (vem de ortho_tutoring_request) valor_consultoria?: number | string; comissao_pct?: number | string; valor_tutor?: number | string; status_repasse?: string; } // ─── Helpers ────────────────────────────────────────────────────── const TIPO_LABELS: Record = { SEGUNDA_OPINIAO: 'SEGUNDA OPINIÃO', PLANEJAMENTO_COMPLETO: 'PLANEJAMENTO COMPLETO', DISCUSSAO_CASO: 'DISCUSSÃO DE CASO', ALINHADORES: 'ALINHADORES', ORTO_CIRURGICO: 'ORTO-CIRÚRGICO', ENCAMINHAMENTO: 'ENCAMINHAMENTO', }; const STATUS_STYLE: Record = { AGUARDANDO: { cls: 'bg-amber-100 text-amber-700', label: 'AGUARDANDO', icon: }, EM_ANALISE: { cls: 'bg-blue-100 text-blue-700', label: 'EM ANÁLISE', icon: }, RESPONDIDO: { cls: 'bg-green-100 text-green-700', label: 'RESPONDIDO', icon: }, FECHADO: { cls: 'bg-gray-100 text-gray-500', label: 'FECHADO', icon: }, }; const STATUS_ACTIONS: Record = { AGUARDANDO: [{ next: 'EM_ANALISE', label: 'ACEITAR CASO', cls: 'bg-teal-600 hover:bg-teal-700 text-white' }], EM_ANALISE: [ { next: 'RESPONDIDO', label: 'MARCAR COMO RESPONDIDO', cls: 'bg-green-600 hover:bg-green-700 text-white' }, { next: 'FECHADO', label: 'FECHAR CASO', cls: 'bg-gray-600 hover:bg-gray-700 text-white' }, ], RESPONDIDO: [{ next: 'FECHADO', label: 'FECHAR CASO', cls: 'bg-gray-600 hover:bg-gray-700 text-white' }], FECHADO: [], }; // ─── Chat do tutor ──────────────────────────────────────────────── const TutorResponseChat: React.FC<{ sol: Solicitacao; tutorNome: string; onUpdated: (updated: Solicitacao) => void; }> = ({ sol, tutorNome, onUpdated }) => { const toast = useToast(); const [texto, setTexto] = useState(''); const [enviando, setEnviando] = useState(false); const bottomRef = useRef(null); const msgs = sol.mensagens || []; useEffect(() => { bottomRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [msgs]); const send = async () => { const txt = texto.trim(); if (!txt) return; setEnviando(true); try { const res = await HybridBackend.sendMensagemTutoria(sol.id, txt, 'TUTOR', tutorNome); if (!res.success) { toast.error('ERRO AO ENVIAR.'); return; } onUpdated({ ...sol, mensagens: [...msgs, res.mensagem] }); setTexto(''); } catch { toast.error('ERRO AO ENVIAR.'); } finally { setEnviando(false); } }; const changeStatus = async (newStatus: string) => { const res = await HybridBackend.updateStatusTutoria(sol.id, newStatus); if (!res.success) { toast.error('ERRO AO ATUALIZAR STATUS.'); return; } toast.success('STATUS ATUALIZADO!'); onUpdated({ ...sol, status: newStatus }); }; return (
{/* Banner parecer consultivo */}

PARECER TÉCNICO CONSULTIVO

O seu parecer tem caráter estritamente consultivo e não vinculante. A decisão clínica e a execução do tratamento são de responsabilidade exclusiva do profissional solicitante.

{/* Info financeira */} {sol.valor_consultoria && (

VALOR TOTAL

R$ {Number(sol.valor_consultoria).toLocaleString('pt-BR', { minimumFractionDigits: 2 })}

SEU REPASSE ({sol.comissao_pct ? `${100 - Number(sol.comissao_pct)}%` : '—'})

{sol.valor_tutor ? `R$ ${Number(sol.valor_tutor).toLocaleString('pt-BR', { minimumFractionDigits: 2 })}` : '—'}

STATUS REPASSE

{sol.status_repasse || 'PENDENTE'}

)} {/* Chat */}

CONVERSA

{msgs.length === 0 ? (

NENHUMA MENSAGEM

) : msgs.map(m => (
{m.autor_nome && (

{m.autor_nome}

)}

{m.conteudo}

{new Date(m.created_at).toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })}

))}
{sol.status !== 'FECHADO' && (
setTexto(e.target.value)} onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }} placeholder="SUA RESPOSTA PARA A CLÍNICA..." className="flex-1 border border-gray-200 rounded-xl px-3 py-2 text-xs font-medium focus:outline-none focus:border-emerald-400 bg-white" />
)}
{/* Ações de status */} {STATUS_ACTIONS[sol.status]?.length > 0 && (
{STATUS_ACTIONS[sol.status].map(a => ( ))}
)}
); }; // ─── Detalhe da solicitação ─────────────────────────────────────── const SolicitacaoDetail: React.FC<{ solId: string; tutorNome: string; onBack: () => void; }> = ({ solId, tutorNome, onBack }) => { const [sol, setSol] = useState(null); const [loading, setLoading] = useState(true); const load = useCallback(async () => { const res = await HybridBackend.getSolicitacaoTutoria(solId); if (res.success) setSol(res.solicitacao); setLoading(false); }, [solId]); useEffect(() => { load(); }, [load]); if (loading) return (
); if (!sol) return

CASO NÃO ENCONTRADO.

; const st = STATUS_STYLE[sol.status] || STATUS_STYLE.AGUARDANDO; return (
{/* Topbar */}
{st.icon} {st.label}
{/* Info do caso */}
{sol.paciente_nome?.charAt(0) || 'P'}

{sol.paciente_nome || 'PACIENTE'}

{TIPO_LABELS[sol.tipo] || sol.tipo}

{new Date(sol.created_at).toLocaleDateString()}

{sol.descricao && (

DESCRIÇÃO DA CLÍNICA

{sol.descricao}

)}
{/* Fotos do pacote */} {sol.fotos && sol.fotos.length > 0 && (

FOTOS DO PACIENTE ({sol.fotos.length})

{sol.fotos.map(f => (
{f.slot}
))}
)} {/* Chat + ações */}
); }; // ─── View principal do painel do tutor ─────────────────────────── export const TutorPainelView: React.FC = () => { const [solicitacoes, setSolicitacoes] = useState([]); const [loading, setLoading] = useState(true); const [selected, setSelected] = useState(null); const tutorNome = HybridBackend.getCurrentUserName() || 'TUTOR'; const load = useCallback(async () => { setLoading(true); try { // Por enquanto busca todas — quando tutor tiver ID ligado ao usuário, filtrar const res = await HybridBackend.getSolicitacoesTutoria(); if (res.success) setSolicitacoes(res.solicitacoes || []); } catch {} finally { setLoading(false); } }, []); useEffect(() => { load(); }, [load]); if (selected) { return (
{ setSelected(null); load(); }} />
); } const groups: Record = { AGUARDANDO: [], EM_ANALISE: [], RESPONDIDO: [], FECHADO: [], }; for (const s of solicitacoes) { if (groups[s.status]) groups[s.status].push(s); } return (
{solicitacoes.length} CASO(S) {loading ? (
) : solicitacoes.length === 0 ? (

NENHUM CASO RECEBIDO

AS SOLICITAÇÕES DAS CLÍNICAS APARECEM AQUI.

) : (
{(['AGUARDANDO','EM_ANALISE','RESPONDIDO','FECHADO'] as const).map(status => { const items = groups[status]; if (!items.length) return null; const st = STATUS_STYLE[status]; return (
{st.icon} {st.label} {items.length} CASO(S)
{items.map(s => ( ))}
); })}
)}
); };