← back to Butlr

routes/scheduled.js

81 lines

// routes/scheduled.js — scheduling + calendar endpoints
const express = require('express');
const router = express.Router();
const scheduling = require('../lib/scheduling');
const data = require('../lib/data');

// requireUser middleware — same gate as routes/admin.js uses
function requireUser(req, res, next) {
  if (!req.user) return res.status(401).json({ ok: false, error: 'login required' });
  next();
}

// GET /api/scheduled — list current user's scheduled calls
router.get('/api/scheduled', requireUser, (req, res) => {
  const opts = {};
  if (req.query.status) opts.status = String(req.query.status);
  if (req.query.from)   opts.from   = String(req.query.from);
  if (req.query.to)     opts.to     = String(req.query.to);
  const rows = scheduling.listScheduled(req.user.id, opts);
  res.json({ ok: true, count: rows.length, rows });
});

// POST /api/scheduled — schedule a new call (one-shot OR recurring)
router.post('/api/scheduled', requireUser, express.json({ limit: '8kb' }), (req, res) => {
  try {
    const b = req.body || {};
    const row = scheduling.addScheduled({
      user_id: req.user.id,
      business_name:   b.business_name,
      business_phone:  b.business_phone,
      goal:            b.goal,
      callback_phone:  b.callback_phone,
      callback_name:   b.callback_name,
      schedule_at:     b.schedule_at,
      cron_expr:       b.cron_expr,
      category:        b.category,
      max_hold_minutes: b.max_hold_minutes,
      max_spend_cents:  b.max_spend_cents,
      consent_recording: b.consent_recording,
    });
    res.json({ ok: true, scheduled: row });
  } catch (e) {
    res.status(400).json({ ok: false, error: e.message });
  }
});

// DELETE /api/scheduled/:id — cancel
router.delete('/api/scheduled/:id', requireUser, (req, res) => {
  const ok = scheduling.cancelScheduled(req.params.id, req.user.id);
  if (!ok) return res.status(404).json({ ok: false, error: 'not found' });
  res.json({ ok: true });
});

// GET /calendar — month view with scheduled + past calls
router.get('/calendar', (req, res) => {
  if (!req.user) return res.redirect('/login?return=/calendar');
  const year  = parseInt(req.query.year  || new Date().getFullYear(), 10);
  const month = parseInt(req.query.month || (new Date().getMonth() + 1), 10);

  // Fetch scheduled rows that intersect this month + past calls fired this month
  const monthStart = new Date(year, month - 1, 1);
  const monthEnd   = new Date(year, month,     1);
  const scheduled  = scheduling.listScheduled(req.user.id).filter(r => {
    const t = new Date(r.next_fire_at || r.last_fire_at || 0);
    return t >= monthStart && t < monthEnd;
  });
  const pastCalls  = data.getCalls(req.user.id).filter(c => {
    const t = new Date(c.created_at);
    return t >= monthStart && t < monthEnd;
  });

  res.render('public/calendar', {
    title: 'Calendar — Butlr',
    meta_desc: 'See scheduled + past calls on a calendar.',
    year, month,
    scheduled, pastCalls,
  });
});

module.exports = router;