// ============================================================ // 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 */}