// Client Portal Module function ClientPortal() { const [activeTab, setActiveTab] = React.useState('status'); const [message, setMessage] = React.useState(''); const [messages, setMessages] = React.useState([ { from: 'team', name: 'Ana Lima', text: 'Olá! Seu evento está confirmado para o dia 28. A equipe está montando tudo com carinho.', time: '10:23', date: 'Hoje' }, { from: 'client', name: 'Marcelo Andrade', text: 'Ótimo! Podemos confirmar o número de convidados VIP? Serão 45 pessoas.', time: '10:47', date: 'Hoje' }, { from: 'team', name: 'Ana Lima', text: 'Confirmado! Já estamos ajustando os assentos da área VIP para 45 pessoas. Qualquer dúvida estamos à disposição.', time: '11:02', date: 'Hoje' }, ]); const [toast, setToast] = React.useState(null); const showToast = (msg) => { setToast({ msg }); setTimeout(() => setToast(null), 3000); }; const event = { name: 'Congresso Tech 2026', date: '28–29 de Abril de 2026', location: 'Centro de Convenções Anhembi, São Paulo', status: 'Confirmado', progress: 72, }; const timeline = [ { label: 'Proposta enviada', date: '10 Abr', done: true }, { label: 'Orçamento aprovado', date: '14 Abr', done: true }, { label: 'Briefing finalizado', date: '18 Abr', done: true }, { label: 'Montagem e preparação', date: '26–27 Abr', done: false, active: true }, { label: 'Dia do evento', date: '28–29 Abr', done: false }, { label: 'Relatório pós-evento', date: '05 Mai', done: false }, ]; const budgetItems = [ { desc: 'Locação de espaço', value: 45000 }, { desc: 'Equipamento AV', value: 28000 }, { desc: 'Decoração', value: 22000 }, { desc: 'Buffet (200 pessoas)', value: 36000 }, { desc: 'Equipe de apoio', value: 9000 }, { desc: 'Coordenação geral', value: 5000 }, ]; const total = budgetItems.reduce((s, i) => s + i.value, 0); const sendMessage = () => { if (!message.trim()) return; setMessages(m => [...m, { from: 'client', name: 'Você', text: message, time: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' }), date: 'Hoje' }]); setMessage(''); setTimeout(() => { setMessages(m => [...m, { from: 'team', name: 'Ana Lima', text: 'Recebemos sua mensagem! Em breve retornaremos.', time: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' }), date: 'Hoje' }]); }, 1500); }; const tabs = [{ id: 'status', label: 'Status', icon: 'zap' }, { id: 'budget', label: 'Orçamento', icon: 'budget' }, { id: 'schedule', label: 'Cronograma', icon: 'calendar' }, { id: 'messages', label: 'Mensagens', icon: 'message' }]; return (

Portal do Cliente

Visão do cliente — TechCorp Brasil

{/* Client event header */}
Evento em andamento
{event.name}
{event.date}
{event.location}
Progresso geral
{event.progress}%
{/* Tabs */}
{tabs.map(t => ( ))}
{/* Status tab */} {activeTab === 'status' && (
{[ { label: 'Convidados confirmados', value: '200', icon: 'users', color: DS.colors.primary }, { label: 'Fornecedores', value: '8 / 10', icon: 'briefcase', color: DS.colors.success }, { label: 'Tarefas concluídas', value: '18 / 25', icon: 'tasks', color: DS.colors.warning }, ].map(s => (
{s.label}
{s.value}
))}
)} {/* Budget tab */} {activeTab === 'budget' && (
Orçamento aprovado
Aprovado em 14 Abr
{['Item', 'Valor'].map((h, i) => ( ))} {budgetItems.map((item, i) => ( ))}
{h}
{item.desc} R$ {item.value.toLocaleString('pt-BR')}
Total: R$ {total.toLocaleString('pt-BR')}
)} {/* Schedule tab */} {activeTab === 'schedule' && (
Cronograma do evento
{timeline.map((t, i) => (
{t.done && } {t.active &&
}
{t.label}
{t.date}
{t.active && Em progresso}
))}
)} {/* Messages tab */} {activeTab === 'messages' && (
{messages.map((m, i) => (
{m.from === 'team' && }
{m.name} · {m.time}
{m.text}
{m.from === 'client' && }
))}
setMessage(e.target.value)} onKeyDown={e => e.key === 'Enter' && sendMessage()} placeholder="Escreva uma mensagem..." style={{ flex: 1, border: `1px solid ${DS.colors.border}`, borderRadius: DS.radius.sm, padding: '10px 14px', fontSize: 13, outline: 'none', fontFamily: 'inherit' }} /> Enviar
)} {toast && setToast(null)} />}
); } Object.assign(window, { ClientPortal });