diff --git a/server/routes.ts b/server/routes.ts index dd27996..f288d0b 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -294,26 +294,33 @@ export async function registerRoutes(app: Express): Promise { } }); - // Get guards availability for general planning + // Get guards availability for general planning with time slot conflict detection app.get("/api/guards/availability", isAuthenticated, async (req, res) => { try { - const { weekStart, siteId, location } = req.query; + const { start, end, siteId, location } = req.query; - if (!weekStart || !siteId || !location) { + if (!start || !end || !siteId || !location) { return res.status(400).json({ - message: "Missing required parameters: weekStart, siteId, location" + message: "Missing required parameters: start, end, siteId, location" }); } - const weekStartDate = parseISO(weekStart as string); - if (!isValid(weekStartDate)) { - return res.status(400).json({ message: "Invalid weekStart date format" }); + const startDate = parseISO(start as string); + const endDate = parseISO(end as string); + + if (!isValid(startDate) || !isValid(endDate)) { + return res.status(400).json({ message: "Invalid date format for start or end" }); + } + + if (endDate <= startDate) { + return res.status(400).json({ message: "End time must be after start time" }); } const availability = await storage.getGuardsAvailability( - weekStartDate, siteId as string, - location as string + location as string, + startDate, + endDate ); res.json(availability); @@ -1681,6 +1688,48 @@ export async function registerRoutes(app: Express): Promise { } }); + // Create shift assignment with planned time slots + app.post("/api/shifts/:shiftId/assignments", isAuthenticated, async (req, res) => { + try { + const { shiftId } = req.params; + const { guardId, plannedStartTime, plannedEndTime } = req.body; + + if (!guardId || !plannedStartTime || !plannedEndTime) { + return res.status(400).json({ + message: "Missing required fields: guardId, plannedStartTime, plannedEndTime" + }); + } + + // Validate times + const startDate = new Date(plannedStartTime); + const endDate = new Date(plannedEndTime); + + if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) { + return res.status(400).json({ message: "Invalid date format for plannedStartTime or plannedEndTime" }); + } + + if (endDate <= startDate) { + return res.status(400).json({ message: "plannedEndTime must be after plannedStartTime" }); + } + + // Create assignment + const assignment = await storage.createShiftAssignment({ + shiftId, + guardId, + plannedStartTime: startDate, + plannedEndTime: endDate, + }); + + res.json(assignment); + } catch (error: any) { + console.error("Error creating shift assignment with time slot:", error); + if (error.message?.includes('overlap') || error.message?.includes('conflict')) { + return res.status(409).json({ message: error.message }); + } + res.status(500).json({ message: "Failed to create shift assignment" }); + } + }); + // ============= NOTIFICATION ROUTES ============= app.get("/api/notifications", isAuthenticated, async (req: any, res) => { try {