feat: complete day 17

This commit is contained in:
Ayobami
2025-07-22 19:21:32 +01:00
parent 29e6eb82c7
commit 743187b216
19 changed files with 721 additions and 226 deletions
+69
View File
@@ -0,0 +1,69 @@
const express = require("express");
const router = express.Router();
const db = require("../models");
const {
validateInput,
handleValidationErrorForAPI,
} = require("../services/ValidationService");
// Validation rules for booking
const bookingValidation = {
name: "required|string",
email: "required|email",
company: "required|string",
phone: "required|string",
notes: "required|string",
date: "required|string",
time: "required|string",
timezone: "required|string",
};
// POST /api/bookings - Create a new booking
router.post(
"/bookings",
validateInput(bookingValidation, {
"name.required": "Name is required",
"email.required": "Email is required",
"email.email": "Invalid email address",
"company.required": "Company is required",
"phone.required": "Phone is required",
"notes.required": "Notes are required",
"date.required": "Date is required",
"time.required": "Time is required",
"timezone.required": "Timezone is required",
}),
handleValidationErrorForAPI,
async (req, res) => {
try {
const { name, email, company, phone, notes, date, time, timezone } =
req.body;
const booking = await db.booking.create({
name,
email,
company,
phone,
notes,
date,
time,
timezone,
});
res.status(201).json({ success: true, booking });
} catch (err) {
res.status(500).json({ error: err.message });
}
}
);
// GET /api/bookings - List all bookings
router.get("/bookings", async (req, res) => {
try {
const bookings = await db.booking.findAll({
order: [["created_at", "DESC"]],
});
res.json({ bookings });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
module.exports = router;
+20 -6
View File
@@ -28,8 +28,10 @@ function getTimezoneGroups() {
const groups = {};
for (const region in regions) {
groups[region] = regions[region].map((tz) => ({
value: tz,
label: moment().tz(tz).zoneAbbr() + " " + moment().tz(tz).format("h:mma"),
name: tz,
label: tz.replace(/_/g, " ").replace("America/", ""),
time_am: moment().tz(tz).format("h:mma"),
time_24: moment().tz(tz).format("HH:mm"),
}));
}
return groups;
@@ -44,9 +46,11 @@ function getAllTimezones() {
}
// Helper: Generate week days and slots
function getWeekDaysAndSlots(selectedTz) {
function getWeekDaysAndSlots(selectedTz, weekOffset = 0) {
const weekDays = [];
const today = moment().tz(selectedTz);
const today = moment()
.tz(selectedTz)
.add(weekOffset * 7, "days");
for (let i = 0; i < 7; i++) {
const day = today.clone().add(i, "days");
weekDays.push({
@@ -89,20 +93,30 @@ router.get("/timezone", function (req, res) {
// Calendar slot selection screen
router.get("/calendar", function (req, res) {
const selectedTimezone = req.query.tz || "America/New_York";
const { weekDays, maxSlots } = getWeekDaysAndSlots(selectedTimezone);
const weekOffset = parseInt(req.query.week) || 0;
const { weekDays, maxSlots } = getWeekDaysAndSlots(
selectedTimezone,
weekOffset
);
res.render("calendar", {
selectedTimezone,
weekDays,
maxSlots,
showPrevWeek: false, // For demo, only next week link
showPrevWeek: weekOffset > 0,
prevWeek: weekOffset - 1,
nextWeek: weekOffset + 1,
});
});
// Booking form screen
router.get("/book", function (req, res) {
const selectedTimezone = req.query.tz || "America/New_York";
const selectedDate = req.query.date || "";
const selectedTime = req.query.time || "";
res.render("booking-form", {
selectedTimezone,
selectedDate,
selectedTime,
});
});