// Events / Calendar Module function Events() { const [view, setView] = React.useState('month'); const [events, setEvents] = React.useState([]); const [loading, setLoading] = React.useState(true); const [selectedEvent, setSelectedEvent] = React.useState(null); const [addModal, setAddModal] = React.useState(false); const [form, setForm] = React.useState({ name: '', client: '', type: 'Corporativo', date: '2026-04-22', time: '09:00', location: '', budget: '' }); const [toast, setToast] = React.useState(null); const showToast = (msg, type = 'success') => { setToast({ msg, type }); setTimeout(() => setToast(null), 3000); }; const mapRow = (row) => { const d = row.event_date ? new Date(row.event_date + 'T00:00:00') : null; return { id: row.id, name: row.name, client: row.client_name, type: row.type, day: d ? d.getDate() : 1, month: d ? d.getMonth() + 1 : 1, time: row.event_time || '', duration: row.duration || '', color: row.color || '#3B82F6', status: row.status || 'Planejamento', team: row.team || [], budget: row.budget || 0, location: row.location || '', }; }; React.useEffect(() => { sb.from('events').select('*').order('event_date').then(({ data, error }) => { if (data) setEvents(data.map(mapRow)); setLoading(false); }); }, []); const addEvent = async () => { if (!form.name.trim()) return; const { data, error } = await sb.from('events').insert({ name: form.name, client_name: form.client, type: form.type, event_date: form.date, event_time: form.time, duration: '1 dia', color: '#3B82F6', status: 'Planejamento', team: [], budget: parseFloat(form.budget) || 0, location: form.location, }).select().single(); if (data) { setEvents(prev => [...prev, mapRow(data)]); showToast('Evento criado com sucesso!'); } else { showToast('Erro ao criar evento', 'danger'); } setAddModal(false); setForm({ name: '', client: '', type: 'Corporativo', date: '2026-04-22', time: '09:00', location: '', budget: '' }); }; const checklist = [ { label: 'Confirmação do espaço', done: true }, { label: 'Contratação de equipe técnica', done: true }, { label: 'Briefing aprovado pelo cliente', done: true }, { label: 'Decoração definida', done: false }, { label: 'Sonorização contratada', done: false }, { label: 'Transporte da equipe confirmado', done: false }, { label: 'Montagem agendada', done: false }, ]; const [checks, setChecks] = React.useState(checklist); const typeColor = { 'Corporativo': '#3B82F6', 'Casamento': '#8B5CF6', 'Social': '#10B981', 'Institucional': '#F59E0B' }; const statusVariant = { 'Confirmado': 'success', 'Planejamento': 'warning', 'Orçamento': 'default', 'Em andamento': 'primary' }; const daysInMonth = 30; const startDay = 3; const today = 22; const getEventsForDay = (day) => events.filter(e => e.day === day && e.month === 4); const MonthView = () => (
{['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'].map(d => (
{d}
))} {Array.from({ length: startDay }).map((_, i) => (
))} {Array.from({ length: daysInMonth }).map((_, i) => { const day = i + 1; const dayEvents = getEventsForDay(day); const isToday = day === today; return (
{day}
{dayEvents.map(ev => (
setSelectedEvent(ev)} style={{ background: ev.color, color: '#fff', borderRadius: 4, padding: '2px 6px', fontSize: 10, fontWeight: 600, marginBottom: 2, cursor: 'pointer', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }}> {ev.time} {ev.name}
))}
); })}
); const ListView = () => (
{events.sort((a, b) => a.day - b.day).map(ev => ( setSelectedEvent(ev)} style={{ padding: '16px 20px' }}>
{ev.day}
ABR
{ev.name}
{ev.client} · {ev.location}
{ev.type} {ev.status}
R$ {ev.budget.toLocaleString('pt-BR')}
))}
); return (

Agenda de Eventos

Abril 2026 · {events.length} eventos programados

{[['month', 'Mensal'], ['week', 'Semanal'], ['list', 'Lista']].map(([v, l]) => ( ))}
setAddModal(true)}>Novo evento
{loading ? : ( <> {(view === 'month' || view === 'week') && } {view === 'list' &&
} )}
{/* Event detail modal */} setSelectedEvent(null)} title={selectedEvent?.name || ''} width={600}> {selectedEvent && (
{[ { label: 'Cliente', value: selectedEvent.client }, { label: 'Data e hora', value: `${selectedEvent.day} Abr · ${selectedEvent.time}` }, { label: 'Tipo', value: selectedEvent.type }, { label: 'Local', value: selectedEvent.location }, { label: 'Duração', value: selectedEvent.duration }, { label: 'Status', value: selectedEvent.status }, ].map(({ label, value }) => (
{label}
{value}
))}
Equipe vinculada
{selectedEvent.team.length > 0 ? (
{selectedEvent.team.map(name => (
{name}
))}
) : Nenhuma equipe vinculada ainda}
Checklist
{checks.map((c, i) => (
setChecks(ch => ch.map((item, idx) => idx === i ? { ...item, done: !item.done } : item))} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 12px', borderRadius: DS.radius.sm, cursor: 'pointer', background: c.done ? DS.colors.successLight : '#F8FAFC', transition: 'background 0.15s' }}>
{c.done && }
{c.label}
))}
showToast('Indo para tarefas...')}>Ver tarefas Editar evento
)}
{/* Add event modal */} setAddModal(false)} title="Novo Evento">
setForm(f => ({ ...f, name: v }))} placeholder="Ex: Congresso Tech 2027" /> setForm(f => ({ ...f, client: v }))} placeholder="Ex: TechCorp Brasil" />
setForm(f => ({ ...f, time: v }))} placeholder="09:00" />
setForm(f => ({ ...f, date: v }))} type="date" /> setForm(f => ({ ...f, budget: v }))} placeholder="Ex: 50000" type="number" />
setForm(f => ({ ...f, location: v }))} placeholder="Ex: Centro de Convenções SP" />
setAddModal(false)}>Cancelar Criar evento
{toast && setToast(null)} />}
); } Object.assign(window, { Events });