← back to Marketing Command Center
modules/calendars/index.js
40 lines
// All Calendars — unified multi-layer calendar (activation SKUs + marketing dates
// + campaigns + optional Google), with a left-panel field-filter rail. Self-
// contained per the MODULE CONTRACT. Reads dw_unified (READ-only) via ./lib.js;
// fail-soft to mock mode if Postgres is unreachable (never crashes the shell).
const lib = require('./lib');
module.exports = {
id: 'calendars',
title: 'All Calendars',
icon: '📆',
mount(router) {
// GET /events — the whole unified feed (front-end holds it, filters + renders
// per month client-side). ?fresh=1 forces a re-projection from live dw_unified.
router.get('/events', async (req, res) => {
try {
const data = await lib.buildEvents(req.query.fresh === '1');
res.json(data);
} catch (e) {
res.status(200).json({ mock: true, error: e.message, items: [], counts: {}, window: {} });
}
});
// GET /refresh — force re-projection of the activation snapshot.
router.get('/refresh', async (_req, res) => {
try { const data = await lib.buildEvents(true); res.json({ ok: true, generated_at: data.generated_at, counts: data.counts, mock: data.mock }); }
catch (e) { res.status(200).json({ ok: false, error: e.message }); }
});
// POST /move — drag reschedule. { key, to_date:'YYYY-MM-DD', layer }
// activation → override file (survives regenerate); campaign → schedule store.
// Marketing holidays + Google events are read-only (not draggable).
router.post('/move', (req, res) => {
const r = lib.applyMove(req.body || {});
if (!r.ok) return res.status(400).json(r);
res.json(r);
});
},
};