// ============================================================
// JuFlow — Profissionais
// ============================================================
const { useState: useStPR } = React;
const UPR = window.JFUtils;
const PROF_COLORS = ['#7C3AED','#DB2777','#0891B2','#059669','#FF6B35','#F59E0B','#EF4444','#3B82F6','#14B8A6','#8B5CF6'];
const PROF_DAYS = ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'];
const EMPTY_PROF = {
id: null, name: '', role: '', email: '', phone: '',
color: '#7C3AED', commission: 30,
workDays: [1,2,3,4,5], startHour: 9, endHour: 18, bio: '',
};
const Profissionais = ({ appointments, addToast }) => {
const [selected, setSelected] = useStPR(null);
const [extraProfs, setExtraProfs] = useStPR([]);
const [removed, setRemoved] = useStPR([]);
const [modal, setModal] = useStPR({ open:false, mode:'create', form: EMPTY_PROF });
const [confirm, setConfirm] = useStPR({ open:false, prof:null });
const allProfs = [...window.JF.PROFESSIONALS, ...extraProfs].filter(p => !removed.includes(p.id));
const getStats = (profId) => {
const profAppts = appointments.filter(a => a.professionalId === profId);
const completed = profAppts.filter(a => a.status === 'completed');
const revenue = completed.reduce((s,a) => s + a.price, 0);
const profObj = allProfs.find(p => p.id === profId);
const commission = revenue * ((profObj?.commission || 0) / 100);
return { total: profAppts.length, completed: completed.length, revenue, commission };
};
const openCreate = () => setModal({ open:true, mode:'create', form: { ...EMPTY_PROF, color: PROF_COLORS[Math.floor(Math.random()*PROF_COLORS.length)] } });
const openEdit = (prof) => setModal({ open:true, mode:'edit', form: { ...EMPTY_PROF, ...prof } });
const closeModal = () => setModal(m => ({ ...m, open:false }));
const setForm = (k, v) => setModal(m => ({ ...m, form: { ...m.form, [k]: v } }));
const toggleDay = (i) => setForm('workDays', modal.form.workDays.includes(i) ? modal.form.workDays.filter(d=>d!==i) : [...modal.form.workDays, i].sort());
const saveProf = () => {
const f = modal.form;
if (!f.name.trim() || !f.role.trim()) { addToast('Preencha nome e função.', 'warning'); return; }
if (modal.mode === 'create') {
const id = Math.max(0, ...allProfs.map(p=>p.id)) + 1;
setExtraProfs(arr => [...arr, { ...f, id, lastName: f.name.split(' ').slice(-1)[0] }]);
addToast(`${f.name} adicionado(a) à equipe!`, 'success');
} else {
const isFromBase = window.JF.PROFESSIONALS.some(p => p.id === f.id);
if (isFromBase) {
Object.assign(window.JF.PROFESSIONALS.find(p=>p.id===f.id), f);
setExtraProfs(arr => [...arr]);
} else {
setExtraProfs(arr => arr.map(p => p.id === f.id ? { ...p, ...f } : p));
}
addToast('Profissional atualizado!', 'success');
}
closeModal();
};
const askRemove = (prof) => setConfirm({ open:true, prof });
const confirmRemove = () => {
setRemoved(arr => [...arr, confirm.prof.id]);
setSelected(null);
addToast(`${confirm.prof.name} foi desativado(a).`, 'success');
};
return (
p.role)).size} icon="Award" color="#0891B2" subtitle="áreas" />
a.status==='completed').length/allProfs.length) : 0} icon="Calendar" color="#059669" subtitle="por profissional" />
s+p.commission,0)/allProfs.length)}%` : '0%'} icon="Percent" color="#FF6B35" subtitle="média geral" />
{allProfs.map(prof => {
const stats = getStats(prof.id);
const isSelected = selected?.id === prof.id;
return (
setSelected(isSelected ? null : prof)}
>
{prof.name}
{prof.role}
{prof.commission}% comissão
e.stopPropagation()}>}
items={[
{label:'Editar',icon:'Edit2',onClick:()=>openEdit(prof)},
{label:'Ver agenda',icon:'Calendar',onClick:()=>addToast('Navegando para agenda...','info')},
'divider',
{label:'Desativar',icon:'UserX',onClick:()=>askRemove(prof),danger:true},
]}
/>
{[
{ label:'Sessões', value:stats.completed, color:'#059669' },
{ label:'Faturado', value:UPR.formatCurrency(stats.revenue), color:'#0891B2' },
{ label:'Comissão', value:UPR.formatCurrency(stats.commission), color:prof.color },
].map(stat => (
{stat.value}
{stat.label}
))}
{prof.email}
{prof.phone}
{isSelected && (
Horário de trabalho
{PROF_DAYS.map((d,i) => (
{d}
))}
{String(prof.startHour).padStart(2,'0')}:00 às {String(prof.endHour).padStart(2,'0')}:00
Serviços
{window.JF.SERVICES.filter(s=>s.professionals?.includes(prof.id)).map(s => (
{s.name}
))}
{window.JF.SERVICES.filter(s=>s.professionals?.includes(prof.id)).length === 0 && (
Nenhum serviço associado ainda
)}
)}
);
})}
{/* Add new card */}
{ e.currentTarget.style.borderColor='#FF6B35'; e.currentTarget.style.background='#FFF0EA'; }}
onMouseLeave={e=>{ e.currentTarget.style.borderColor='#D1D5DB'; e.currentTarget.style.background='transparent'; }}
onClick={openCreate}
>
Novo Profissional
{/* Form modal */}
>}
>
{/* Avatar preview + color picker */}
Cor do profissional
{PROF_COLORS.map(c => (
{/* Name + role */}
setForm('name',v)} icon="User" required autoFocus />
setForm('role',v)} icon="Award" required placeholder="Ex: Fisioterapeuta" />
{/* Email + phone */}
setForm('email',v)} icon="Mail" placeholder="nome@clinica.com" />
setForm('phone',v)} icon="Phone" placeholder="(11) 99999-9999" />
{/* Commission + hours */}
setForm('commission', Number(e.target.value))}
style={{ padding:'9px 12px', borderRadius:8, fontSize:13, border:'1.5px solid #E2E8F0', outline:'none', color:'#0A1F44', background:'#fff' }} />
setForm('startHour', Number(e.target.value))}
style={{ padding:'9px 12px', borderRadius:8, fontSize:13, border:'1.5px solid #E2E8F0', outline:'none', color:'#0A1F44', background:'#fff' }} />
setForm('endHour', Number(e.target.value))}
style={{ padding:'9px 12px', borderRadius:8, fontSize:13, border:'1.5px solid #E2E8F0', outline:'none', color:'#0A1F44', background:'#fff' }} />
{/* Work days */}
{PROF_DAYS.map((d,i) => {
const active = modal.form.workDays.includes(i);
return (
);
})}
{/* Bio */}
{/* Confirm remove */}
setConfirm(c => ({ ...c, open:false }))}
onConfirm={confirmRemove}
title="Desativar profissional"
message={confirm.prof ? `Tem certeza que deseja desativar ${confirm.prof.name}? Os atendimentos passados serão preservados, mas o profissional não aparecerá mais nas listas.` : ''}
confirmLabel="Desativar"
danger
/>
);
};
Object.assign(window, { Profissionais });