/* ============================================================ KeS Metas — Agendamentos (reuniões + Google Agenda central) ============================================================ */ const { useState, useEffect } = React; /* Banner da conta CENTRAL da KeS (uma agenda para toda a equipe). */ function GoogleBanner({ google, dispatch }) { const K = window.KES; const [busy, setBusy] = useState(false); async function connect() { setBusy(true); // // AQUI: integrar com Google Calendar API — OAuth da conta central da KeS const res = await K.GoogleCalendarService.connect(); setBusy(false); dispatch({ type: "SET_GOOGLE", connected: res.connected }); dispatch({ type: "TOAST", msg: "Google Agenda da KeS conectado com sucesso." }); } async function disconnect() { setBusy(true); await K.GoogleCalendarService.disconnect(); setBusy(false); dispatch({ type: "SET_GOOGLE", connected: false }); } return (
Google Agenda da KeS Assessoria {google.connected ? Conectado : Não conectado}
{google.connected ? <>Conta central {google.account}. Toda a equipe agenda nesta agenda — cada evento registra quem agendou. : <>Conecte a conta central {google.account} para sincronizar os agendamentos da equipe.}
{google.connected ? {busy ? "Desconectando…" : "Desconectar"} : }
); } const MESES_ABREV = ["jan", "fev", "mar", "abr", "mai", "jun", "jul", "ago", "set", "out", "nov", "dez"]; function MeetingRow({ m, autor, onDelete }) { const K = window.KES; const d = K.parseISO(m.date); return (
{String(d.getDate()).padStart(2, "0")}
{MESES_ABREV[d.getMonth()]}
{m.titulo} {m.googleSynced ? Na agenda da KeS : Pendente}
{m.hora} · {m.duracao} min {m.participante} {m.convidados && m.convidados.length > 0 && {m.convidados.length} convidado{m.convidados.length > 1 ? "s" : ""}}
{autor && (
Agendado por {autor.nome} · {autor.papel === "admin" ? "Administrador" : "Comercial"}
)} {m.meetLink && ( e.stopPropagation()}> {m.meetLink.replace("https://", "")} )} {m.observacoes ?
{m.observacoes}
: null}
{onDelete && ( )}
); } function AgendaScreen({ state, dispatch, viewer }) { const K = window.KES; const isAdmin = viewer.papel === "admin"; const usersById = {}; state.users.forEach((u) => { usersById[u.id] = u; }); const google = state.google; // "autor" = quem está agendando. Admin pode agendar em nome de qualquer um. const [autorId, setAutorId] = useState(viewer.id); const autor = state.users.find((u) => u.id === autorId) || viewer; const todayISO = K.iso(K.SIM_TODAY); const newBlank = () => ({ titulo: "", date: todayISO, hora: "09:00", duracao: "30", participante: "", contexto: "", observacoes: "", meetLink: "", convidados: [], leadId: null }); const [form, setForm] = useState(newBlank); const [guestInput, setGuestInput] = useState(""); const [syncing, setSyncing] = useState(false); const [err, setErr] = useState(""); const set = (k, v) => setForm((f) => ({ ...f, [k]: v })); // Pré-preenche a partir de um lead do CRM (ação "Agendar reunião"). useEffect(() => { const lead = state.agendaPrefill; if (!lead) return; if (isAdmin && lead.responsavelId) setAutorId(lead.responsavelId); const ctx = [ lead.empresa && `Empresa: ${lead.empresa}`, lead.porte && `Porte: ${lead.porte}`, lead.telefone && `Tel: ${lead.telefone}`, lead.valor && `Oportunidade: ${K.fmtMoeda(lead.valor)}`, ].filter(Boolean).join(" · "); setForm({ titulo: `Reunião — ${lead.empresa || lead.nome}`, date: todayISO, hora: "09:00", duracao: "30", participante: `${lead.nome}${lead.empresa ? " (" + lead.empresa + ")" : ""}`, contexto: ctx, observacoes: lead.observacoes || "", meetLink: "", convidados: lead.email ? [lead.email] : [], leadId: lead.id, }); dispatch({ type: "CLEAR_PREFILL" }); dispatch({ type: "TOAST", msg: `Agendando reunião com ${lead.nome}.` }); }, [state.agendaPrefill]); function addGuest(v) { const e = v.trim().toLowerCase(); if (!e) return; if (!/^\S+@\S+\.\S+$/.test(e)) { setErr("E-mail de convidado inválido."); return; } if (!form.convidados.includes(e)) set("convidados", [...form.convidados, e]); setGuestInput(""); setErr(""); } async function submit(e) { e.preventDefault(); if (!form.titulo.trim()) { setErr("Informe o título da reunião."); return; } if (!form.participante.trim()) { setErr("Informe o participante/contato."); return; } setErr(""); setSyncing(true); const meeting = { id: "m" + Date.now(), userId: autor.id, autorNome: autor.nome, titulo: form.titulo.trim(), date: form.date, hora: form.hora, duracao: parseInt(form.duracao, 10), participante: form.participante.trim(), contexto: form.contexto.trim(), observacoes: form.observacoes.trim(), meetLink: form.meetLink, convidados: form.convidados, leadId: form.leadId, calendar: google.account, googleSynced: false, eventId: null, }; // // AQUI: integrar com Google Calendar API — events.insert na agenda CENTRAL da KeS // (descrição do evento inclui autor + contexto; attendees = convidados; conferenceData = Meet) let synced = { synced: false, eventId: null, meetLink: form.meetLink }; if (google.connected) { const res = await K.GoogleCalendarService.createEvent(autor, meeting); synced = { synced: res.synced, eventId: res.eventId, meetLink: res.meetLink || form.meetLink }; } meeting.googleSynced = synced.synced; meeting.eventId = synced.eventId; meeting.meetLink = synced.meetLink; dispatch({ type: "ADD_MEETING", meeting }); setSyncing(false); setForm(newBlank()); setGuestInput(""); dispatch({ type: "TOAST", msg: google.connected ? "Reunião criada na agenda da KeS e convites enviados." : "Reunião criada (sincronização pendente — conecte a agenda da KeS)." }); } // Exclui a reunião do sistema E do Google Agenda da KeS. async function excluirReuniao(m) { dispatch({ type: "DELETE_MEETING", id: m.id }); if (m.eventId && google.connected) { const res = await K.GoogleCalendarService.deleteEvent(m.eventId); dispatch({ type: "TOAST", msg: res.ok ? "Reunião excluída da agenda da KeS." : "Reunião removida aqui (não foi possível excluir do Google)." }); } else { dispatch({ type: "TOAST", msg: "Reunião excluída." }); } } // Admin vê todas as próximas reuniões da equipe; comum vê só as suas. const upcoming = state.meetings .filter((m) => (isAdmin || m.userId === viewer.id) && m.date >= todayISO) .sort((a, b) => (a.date + a.hora).localeCompare(b.date + b.hora)); return (

Agendamentos

Uma agenda central da KeS para toda a equipe. Cada reunião registra quem agendou e alimenta o indicador "Reuniões Agendadas".

{/* Lista */}

{isAdmin ? "Próximas reuniões da equipe" : "Suas próximas reuniões"}

{upcoming.length}
{upcoming.length === 0 ? (
Nenhuma reunião futura
Crie a primeira no formulário ao lado.
) : (
{upcoming.map((m) => excluirReuniao(m)} />)}
)}
{/* Form */}

Nova reunião

{isAdmin && ( )} set("titulo", e.target.value)} />
set("date", e.target.value)} /> set("hora", e.target.value)} />
set("participante", e.target.value)} /> set("contexto", e.target.value)} />
{form.convidados.map((g) => ( {g[0].toUpperCase()}{g} ))} setGuestInput(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter" || e.key === ",") { e.preventDefault(); addGuest(guestInput); } }} />
O link do Google Meet é criado automaticamente pelo Google ao agendar.