const PID_NEW_TOOLS_NOTIFICATIONS = [ { id: "tool-calendario-individual", date: "01/08", title: "CALENDÁRIO INDIVIDUAL", breadcrumb: "Menu > Calendário Individual" }, { id: "tool-perfis-acesso", date: "03/08", title: "PERFIS DE ACESSO", breadcrumb: "Menu > Administração > Perfis de Acesso" }, { id: "tool-usuarios", date: "03/08", title: "USUÁRIOS", breadcrumb: "Menu > Administração > Usuários" }, { id: "tool-widgets", date: "10/08", title: "WIDGETS NA TELA INICIAL", breadcrumb: "Menu > Principal > Widgets" }, ]; const PID_NOTIF_ICON_TOOL = ''; const PID_NOTIF_ICON_EVENT = ''; const PID_NOTIF_ICON_RESTORE = ''; function pidFormatNotifDate(iso) { const [, month, day] = iso.split("-"); return `${day}/${month}`; } async function pidFetchDismissedNotifIds() { const list = await pidApiRequest("/notificacoes-dispensadas/"); return (list || []).map((n) => n.notif_id); } async function pidDismissNotification(id) { await pidApiRequest("/notificacoes-dispensadas/", { method: "POST", body: { notif_id: id } }); } async function pidRestoreNotification(id) { await pidApiRequest(`/notificacoes-dispensadas/${id}/`, { method: "DELETE" }); } function pidSortEventsByDate(a, b) { const dateCompare = a.data.localeCompare(b.data); return dateCompare !== 0 ? dateCompare : (a.horario || "").localeCompare(b.horario || ""); } function pidMapEventToNotification(ev) { return { id: `event-${ev.id}`, type: "event", date: pidFormatNotifDate(ev.data), title: ev.titulo.toUpperCase(), breadcrumb: ev.sou_dono ? "Menu > Calendário Individual" : `Menu > Calendário Individual > Compartilhado por ${ev.dono_nome}`, }; } /** Só os compromissos "elegíveis" a notificação agora (lembrete configurado, já * atingido e não no passado) — a mesma regra do sino. O histórico (ver * `renderHistory` abaixo) reconstrói a partir de todos os eventos, sem essas * duas restrições, já que um item dispensado pode ter saído desse recorte. */ function pidEventosElegiveisAgora(events) { const now = new Date(); const todayIso = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}`; return events .filter((ev) => ev.data >= todayIso && ev.notificar_em && new Date(ev.notificar_em) <= now) .sort(pidSortEventsByDate) .slice(0, 5) .map(pidMapEventToNotification); } document.addEventListener("DOMContentLoaded", async () => { const bell = document.getElementById("notif-bell"); const dropdown = document.getElementById("notif-dropdown"); const list = document.getElementById("notif-list"); const badge = document.getElementById("notif-badge"); const clearAllBtn = document.getElementById("notif-clear-all"); const historyBtn = document.getElementById("notif-history-btn"); const historyModal = document.getElementById("notif-history-modal"); const historyList = document.getElementById("notif-history-list"); const historyCloseBtn = document.getElementById("notif-history-close-btn"); if (!bell || !dropdown || !list) return; const me = await pidGetMe(); const events = me ? await pidFetchEvents() : []; const eventNotifications = pidEventosElegiveisAgora(events); const allEventNotifications = events.slice().sort(pidSortEventsByDate).map(pidMapEventToNotification); const toolNotifications = PID_NEW_TOOLS_NOTIFICATIONS.map((n) => ({ ...n, type: "tool" })); let dismissedIds = me ? await pidFetchDismissedNotifIds() : []; let notifications = [...eventNotifications, ...toolNotifications].filter((n) => !dismissedIds.includes(n.id)); function render() { list.innerHTML = notifications.length ? notifications .map( (n) => `
  • ${n.type === "event" ? PID_NOTIF_ICON_EVENT : PID_NOTIF_ICON_TOOL}

    ${n.date} - ${n.title}

    ${n.breadcrumb}

  • ` ) .join("") : `
  • Nenhuma notificação no momento.
  • `; if (badge) { badge.hidden = notifications.length === 0; badge.textContent = notifications.length; } } bell.addEventListener("click", (event) => { event.stopPropagation(); dropdown.hidden = !dropdown.hidden; }); list.addEventListener("click", async (event) => { const dismissBtn = event.target.closest("[data-notif-dismiss]"); if (!dismissBtn) return; event.stopPropagation(); const id = dismissBtn.getAttribute("data-notif-dismiss"); await pidDismissNotification(id); dismissedIds.push(id); notifications = notifications.filter((n) => n.id !== id); render(); }); if (clearAllBtn) { clearAllBtn.addEventListener("click", async () => { await Promise.all(notifications.map((n) => pidDismissNotification(n.id))); dismissedIds.push(...notifications.map((n) => n.id)); notifications = []; render(); }); } document.addEventListener("click", (event) => { if (!dropdown.hidden && !dropdown.contains(event.target) && event.target !== bell) { dropdown.hidden = true; } if (historyModal && !historyModal.hidden && event.target === historyModal) { historyModal.hidden = true; } }); function renderHistory() { if (!historyList) return; const historyItems = [...allEventNotifications, ...toolNotifications].filter((n) => dismissedIds.includes(n.id)); historyList.innerHTML = historyItems.length ? historyItems .map( (n) => `
  • ${n.type === "event" ? PID_NOTIF_ICON_EVENT : PID_NOTIF_ICON_TOOL}

    ${n.date} - ${n.title}

    ${n.breadcrumb}

  • ` ) .join("") : `
  • Nenhuma notificação no histórico.
  • `; } if (historyBtn && historyModal) { historyBtn.addEventListener("click", (event) => { event.stopPropagation(); dropdown.hidden = true; renderHistory(); historyModal.hidden = false; }); } if (historyCloseBtn) { historyCloseBtn.addEventListener("click", () => { historyModal.hidden = true; }); } if (historyList) { historyList.addEventListener("click", async (event) => { const restoreBtn = event.target.closest("[data-notif-restore]"); if (!restoreBtn) return; const id = restoreBtn.getAttribute("data-notif-restore"); await pidRestoreNotification(id); dismissedIds = dismissedIds.filter((dismissedId) => dismissedId !== id); notifications = [...eventNotifications, ...toolNotifications].filter((n) => !dismissedIds.includes(n.id)); renderHistory(); render(); }); } render(); });