tractatus/src/routes/calendar.routes.js
TheFlow 7f6192cbd6 refactor(lint): fix code style and unused variables across src/
- Fixed unused function parameters by prefixing with underscore
- Removed unused imports and variables
- Applied eslint --fix for automatic style fixes
  - Property shorthand
  - String template literals
  - Prefer const over let where appropriate
  - Spacing and formatting

Reduces lint errors from 108+ to 78 (61 unused vars, 17 other issues)

Related to CI lint failures in previous commit

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 20:15:26 +13:00

414 lines
9.2 KiB
JavaScript

/**
* Calendar Routes - Scheduled Tasks API
*
* RESTful API for multi-project calendar and reminder system
*
* Copyright 2025 Tractatus Project
* Licensed under Apache License 2.0
*/
const express = require('express');
const router = express.Router();
const ScheduledTask = require('../models/ScheduledTask.model');
const { authenticateToken } = require('../middleware/auth.middleware');
// Apply authentication to all calendar routes
router.use(authenticateToken);
/**
* GET /api/calendar/tasks - Get all scheduled tasks with filters
*/
router.get('/tasks', async (req, res) => {
try {
const {
status,
category,
priority,
projectId,
includeCompleted,
limit = 100,
skip = 0
} = req.query;
const query = {};
// Filter by status
if (status) {
query.status = status;
} else if (includeCompleted !== 'true') {
query.status = { $in: ['pending', 'in_progress', 'overdue'] };
}
// Filter by category
if (category) {
query.category = category;
}
// Filter by priority
if (priority) {
query.priority = priority;
}
// Filter by project
if (projectId) {
query.projectId = projectId;
}
const tasks = await ScheduledTask.find(query)
.sort({ priority: -1, dueDate: 1 })
.limit(parseInt(limit))
.skip(parseInt(skip))
.populate('projectId', 'name active');
const total = await ScheduledTask.countDocuments(query);
res.json({
success: true,
tasks,
pagination: {
total,
limit: parseInt(limit),
skip: parseInt(skip),
hasMore: total > (parseInt(skip) + parseInt(limit))
}
});
} catch (error) {
console.error('Error fetching scheduled tasks:', error);
res.status(500).json({
success: false,
error: 'Failed to fetch scheduled tasks'
});
}
});
/**
* GET /api/calendar/tasks/due-soon - Get tasks due within N days (for session-init)
*/
router.get('/tasks/due-soon', async (req, res) => {
try {
const { days = 7 } = req.query;
const tasks = await ScheduledTask.getDueSoon(parseInt(days));
res.json({
success: true,
tasks,
count: tasks.length
});
} catch (error) {
console.error('Error fetching due-soon tasks:', error);
res.status(500).json({
success: false,
error: 'Failed to fetch due-soon tasks'
});
}
});
/**
* GET /api/calendar/tasks/overdue - Get overdue tasks
*/
router.get('/tasks/overdue', async (req, res) => {
try {
const tasks = await ScheduledTask.getOverdue();
res.json({
success: true,
tasks,
count: tasks.length
});
} catch (error) {
console.error('Error fetching overdue tasks:', error);
res.status(500).json({
success: false,
error: 'Failed to fetch overdue tasks'
});
}
});
/**
* GET /api/calendar/tasks/:id - Get single task
*/
router.get('/tasks/:id', async (req, res) => {
try {
const task = await ScheduledTask.findById(req.params.id)
.populate('projectId', 'name active');
if (!task) {
return res.status(404).json({
success: false,
error: 'Task not found'
});
}
res.json({
success: true,
task
});
} catch (error) {
console.error('Error fetching task:', error);
res.status(500).json({
success: false,
error: 'Failed to fetch task'
});
}
});
/**
* POST /api/calendar/tasks - Create new scheduled task
*/
router.post('/tasks', async (req, res) => {
try {
const {
title,
description,
dueDate,
priority,
category,
projectId,
projectName,
recurrence,
documentRef,
links,
assignedTo,
metadata,
tags,
showInSessionInit,
reminderDaysBefore
} = req.body;
// Validation
if (!title || !description || !dueDate) {
return res.status(400).json({
success: false,
error: 'Title, description, and dueDate are required'
});
}
const task = new ScheduledTask({
title,
description,
dueDate: new Date(dueDate),
priority: priority || 'MEDIUM',
category: category || 'other',
projectId: projectId || null,
projectName: projectName || null,
recurrence: recurrence || 'once',
documentRef: documentRef || null,
links: links || [],
createdBy: 'user',
assignedTo: assignedTo || 'PM',
metadata: metadata || {},
tags: tags || [],
showInSessionInit: showInSessionInit !== false,
reminderDaysBefore: reminderDaysBefore || 7
});
await task.save();
res.status(201).json({
success: true,
task,
message: 'Scheduled task created successfully'
});
} catch (error) {
console.error('Error creating scheduled task:', error);
res.status(500).json({
success: false,
error: 'Failed to create scheduled task'
});
}
});
/**
* PUT /api/calendar/tasks/:id - Update scheduled task
*/
router.put('/tasks/:id', async (req, res) => {
try {
const task = await ScheduledTask.findById(req.params.id);
if (!task) {
return res.status(404).json({
success: false,
error: 'Task not found'
});
}
// Update allowed fields
const allowedFields = [
'title', 'description', 'dueDate', 'priority', 'category',
'projectId', 'projectName', 'recurrence', 'status', 'documentRef',
'links', 'assignedTo', 'metadata', 'tags', 'showInSessionInit',
'reminderDaysBefore'
];
allowedFields.forEach(field => {
if (req.body[field] !== undefined) {
task[field] = req.body[field];
}
});
await task.save();
res.json({
success: true,
task,
message: 'Task updated successfully'
});
} catch (error) {
console.error('Error updating task:', error);
res.status(500).json({
success: false,
error: 'Failed to update task'
});
}
});
/**
* POST /api/calendar/tasks/:id/complete - Mark task as completed
*/
router.post('/tasks/:id/complete', async (req, res) => {
try {
const task = await ScheduledTask.findById(req.params.id);
if (!task) {
return res.status(404).json({
success: false,
error: 'Task not found'
});
}
await task.complete();
res.json({
success: true,
task,
message: 'Task marked as completed'
});
} catch (error) {
console.error('Error completing task:', error);
res.status(500).json({
success: false,
error: 'Failed to complete task'
});
}
});
/**
* POST /api/calendar/tasks/:id/dismiss - Dismiss task
*/
router.post('/tasks/:id/dismiss', async (req, res) => {
try {
const { reason } = req.body;
const task = await ScheduledTask.findById(req.params.id);
if (!task) {
return res.status(404).json({
success: false,
error: 'Task not found'
});
}
await task.dismiss(reason);
res.json({
success: true,
task,
message: 'Task dismissed'
});
} catch (error) {
console.error('Error dismissing task:', error);
res.status(500).json({
success: false,
error: 'Failed to dismiss task'
});
}
});
/**
* DELETE /api/calendar/tasks/:id - Delete scheduled task
*/
router.delete('/tasks/:id', async (req, res) => {
try {
const task = await ScheduledTask.findByIdAndDelete(req.params.id);
if (!task) {
return res.status(404).json({
success: false,
error: 'Task not found'
});
}
res.json({
success: true,
message: 'Task deleted successfully'
});
} catch (error) {
console.error('Error deleting task:', error);
res.status(500).json({
success: false,
error: 'Failed to delete task'
});
}
});
/**
* GET /api/calendar/stats - Get calendar statistics
*/
router.get('/stats', async (req, res) => {
try {
const stats = {
total: await ScheduledTask.countDocuments(),
pending: await ScheduledTask.countDocuments({ status: 'pending' }),
overdue: await ScheduledTask.countDocuments({ status: 'overdue' }),
completed: await ScheduledTask.countDocuments({ status: 'completed' }),
byCategory: {},
byPriority: {},
dueSoon: await ScheduledTask.countDocuments({
dueDate: { $lte: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) },
status: 'pending'
})
};
// Category breakdown
const categories = ['framework', 'governance', 'security', 'project', 'research', 'deployment', 'other'];
for (const cat of categories) {
stats.byCategory[cat] = await ScheduledTask.countDocuments({
category: cat,
status: { $in: ['pending', 'in_progress', 'overdue'] }
});
}
// Priority breakdown
const priorities = ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];
for (const pri of priorities) {
stats.byPriority[pri] = await ScheduledTask.countDocuments({
priority: pri,
status: { $in: ['pending', 'in_progress', 'overdue'] }
});
}
res.json({
success: true,
stats
});
} catch (error) {
console.error('Error fetching calendar stats:', error);
res.status(500).json({
success: false,
error: 'Failed to fetch calendar statistics'
});
}
});
module.exports = router;