const PID_WIDGET_TYPES = {
"calendario-individual": {
label: "Calendário Individual",
description: "Próximos compromissos da sua agenda pessoal.",
href: "calendario-individual.html",
linkLabel: "Ver calendário completo",
// Mesmo gate usado pra esconder o item "Calendário Individual" da sidebar
// (data-section="calendario-individual", pidApplyAccessVisibility em
// access.js) — sem isso, um perfil sem esse módulo habilitado ainda
// conseguia adicionar o widget (e, por ele, chegar ao calendário
// completo) mesmo com o link do menu corretamente escondido.
visibleIf: (me) => !!(me.permissoes_efetivas?.["calendario-individual"]?.enabled),
},
"links-favoritos": {
label: "Links Favoritos",
description: "Seus atalhos favoritos de Links & Ferramentas.",
href: "links-ferramentas.html",
linkLabel: "Ver todos os links",
visibleIf: (me) => !!(me.permissoes_efetivas?.["links-ferramentas"]?.apps?.["links-ferramentas-visualizar"]),
},
};
const PID_WIDGET_LINK_DEFAULT_ICON =
'';
const PID_WIDGET_DATA_FORMATO = new Intl.DateTimeFormat("pt-BR", { day: "2-digit", month: "2-digit" });
const PID_WIDGET_DATA_HORA_FORMATO = new Intl.DateTimeFormat("pt-BR", {
day: "2-digit",
month: "2-digit",
hour: "2-digit",
minute: "2-digit",
});
const PID_WIDGET_DEFAULT_WIDTH = 320;
const PID_WIDGET_DEFAULT_HEIGHT = 240;
async function pidFetchWidgets() {
return (await pidApiRequest("/widgets/")) || [];
}
async function pidAddWidget(tipo) {
return pidApiRequest("/widgets/", { method: "POST", body: { tipo } });
}
async function pidRemoveWidget(tipo) {
await pidApiRequest(`/widgets/${encodeURIComponent(tipo)}/`, { method: "DELETE" });
}
async function pidUpdateWidget(tipo, payload) {
return pidApiRequest(`/widgets/${encodeURIComponent(tipo)}/`, { method: "PATCH", body: payload });
}
document.addEventListener("DOMContentLoaded", async () => {
const widgetsGrid = document.getElementById("widgets-grid");
if (!widgetsGrid) return;
const me = await pidGetMe();
if (!me) return;
const widgetsEmpty = document.getElementById("widgets-empty");
const addBtn = document.getElementById("widget-add-btn");
const pickerModal = document.getElementById("widget-picker-modal");
const pickerList = document.getElementById("widget-picker-list");
const textoWidgetsVazio = widgetsEmpty ? widgetsEmpty.textContent : "";
const PID_WIDGET_ERRO_CARGA = "Não foi possível carregar. Recarregue a página; se persistir, contate a Inovação.";
function todayIso() {
const d = new Date();
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
}
function renderCalendarWidgetBody(events) {
const today = todayIso();
const upcoming = events
.filter((ev) => ev.data >= today)
.sort((a, b) => {
const dateCompare = a.data.localeCompare(b.data);
return dateCompare !== 0 ? dateCompare : (a.horario || "").localeCompare(b.horario || "");
})
.slice(0, 5);
if (!upcoming.length) {
return `
Nenhum compromisso agendado.
`;
}
return upcoming
.map((ev) => {
// ev.data é data pura ("AAAA-MM-DD"): monta pelas partes no fuso local
// (new Date("AAAA-MM-DD") seria UTC e cairia no dia anterior).
const [ano, mes, dia] = ev.data.split("-").map(Number);
const horario = ev.horario ? ev.horario.slice(0, 5) : "";
let dateLabel;
if (horario) {
const [hora, minuto] = horario.split(":").map(Number);
// pt-BR devolve "05/10, 09:03": tira a vírgula pra manter o "05/10 09:03" de antes.
dateLabel = PID_WIDGET_DATA_HORA_FORMATO.format(new Date(ano, mes - 1, dia, hora, minuto)).replace(",", "");
} else {
dateLabel = PID_WIDGET_DATA_FORMATO.format(new Date(ano, mes - 1, dia));
}
return `