Liontix 11 сар өмнө
parent
commit
749278f964

+ 5 - 4
public/javascripts/appointments.js

@@ -104,9 +104,8 @@ function createAppointmentRow(appointment) {
 }
 
 /**
- * Creates a row in the appointment table for each appointment.
- * @param {String} appointmentId - AppointmentID
- * @returns {HTMLTableRowElement} The newly created table row element.
+ * Deletes an appointment from the server and updates the UI.
+ * @param {string} appointmentId - ID of the appointment to delete.
  */
 async function deleteAppointment(appointmentId) {
     const response = await fetchWithToken(`/api/users/delete`, {
@@ -120,7 +119,9 @@ async function deleteAppointment(appointmentId) {
     }
 }
 
-
+/**
+ * Fetches appointments from the server and updates the UI.
+ */
 async function fetchAppointments() {
     const response = await fetchWithToken("/api/users/appointments");
 

+ 15 - 1
public/javascripts/auth.js

@@ -8,6 +8,9 @@ const errorMessageParagraph = document.getElementById("login-error");
 const submitButtonLogin = document.getElementById("btn-login");
 const submitButtonRegister = document.getElementById("btn-register");
 
+/**
+ * Add button event listeners, for login and register
+ */
 window.addEventListener("load", function () {
     submitButtonLogin.addEventListener("click", async function () {
         await login();
@@ -18,6 +21,12 @@ window.addEventListener("load", function () {
     })
 });
 
+
+/**
+ * Function to handle sending authentication requests.
+ *
+ * @param {string} type - The type of request, either 'login' or 'register'.
+ */
 async function sendAuthRequest(type) {
     const response = await fetchRegular(
         "/api/auth/" + type,
@@ -37,7 +46,6 @@ async function sendAuthRequest(type) {
     const response_json = await response.json();
 
     if (response.status === 200) {
-        console.log("success")
         localStorage.setItem("token", response_json["token"]);
         window.location.replace("/html/appointments.html");
     } else {
@@ -51,10 +59,16 @@ async function sendAuthRequest(type) {
 
 }
 
+/**
+ * Function to handle user login.
+ */
 async function login() {
     await sendAuthRequest("login");
 }
 
+/**
+ * Function to handle user registration.
+ */
 async function register() {
     await sendAuthRequest("register");
 }

+ 85 - 12
public/javascripts/bookings.js

@@ -1,26 +1,53 @@
+/**
+ * Import necessary utility functions from utils.js
+ */
 import {fetchRegular, fetchWithToken, getTimeSpan, parseOrRedirect} from "./utils.js";
-"use strict";
 
+/**
+ * Event listener for the window load event.
+ * Retrieves the appointment ID from the URL query parameters and fetches the appointment details.
+ */
 window.addEventListener("load", async function () {
+    /**
+     * Get the URL query parameters
+     */
     const urlParams = new URLSearchParams(window.location.search);
     const appointment = urlParams.get('appointment');
+
+    /**
+     * If no appointment ID is found, redirect to the 404 page
+     */
     if (!appointment) {
         window.location.replace("/html/404.html");
     }
+
+    /**
+     * Fetch the appointment details and bookings
+     */
     await getAppointment(appointment);
     await fetchBookings(appointment);
 });
 
+/**
+ * Displays the appointment details in the appointment-info container.
+ * @param {Object} appointmentData - The appointment data object
+ */
 function displayAppointmentDetails(appointmentData) {
-    // Retrieve the container
+    /**
+     * Retrieve the appointment-info container
+     */
     const appointmentInfo = document.querySelector('.appointment-info');
 
-    // Clear existing content
+    /**
+     * Clear existing content
+     */
     while (appointmentInfo.firstChild) {
         appointmentInfo.removeChild(appointmentInfo.firstChild);
     }
 
-    // Create and append the updated appointment content
+    /**
+     * Create and append the updated appointment content
+     */
     const title = document.createElement('p');
     const titleLabel = document.createElement('strong');
     titleLabel.textContent = 'Title: ';
@@ -51,7 +78,9 @@ function displayAppointmentDetails(appointmentData) {
     timeSpan.appendChild(timeSpanLabel);
     timeSpan.appendChild(document.createTextNode(getTimeSpan(appointmentData.startDate, appointmentData.endDate)));
 
-    // Append all the updated elements
+    /**
+     * Append all the updated elements
+     */
     appointmentInfo.appendChild(title);
     appointmentInfo.appendChild(description);
     appointmentInfo.appendChild(place);
@@ -59,56 +88,100 @@ function displayAppointmentDetails(appointmentData) {
     appointmentInfo.appendChild(timeSpan);
 }
 
+/**
+ * Fetches the appointment details from the API.
+ * @param {string} appointment - The appointment ID
+ */
 async function getAppointment(appointment) {
+    /**
+     * Set the request options
+     */
     const options = {method: 'GET', headers: {'User-Agent': 'insomnia/10.0.0'}};
 
+    /**
+     * Set the query parameters
+     */
     const searchParams = new URLSearchParams({
         appointmentId: appointment,
         isUser: true
     });
 
+    /**
+     * Fetch the appointment details
+     */
     const response = await fetchRegular(`/api/schedule?` + searchParams.toString(), options)
         .catch(err => console.error('error:' + err));
 
+    /**
+     * Parse the response and display the appointment details
+     */
     const js = await parseOrRedirect(response);
     displayAppointmentDetails(js);
 }
 
-
+/**
+ * Renders the bookings data in the participants-table-body container.
+ * @param {Array<Object>} data - The bookings data array
+ */
 function renderBookings(data) {
+    /**
+     * Retrieve the participants-table-body container
+     */
     const tableBody = document.getElementById('participants-table-body');
     tableBody.innerHTML = ''; // Clear existing rows
 
+    /**
+     * Iterate over the bookings data and create table rows
+     */
     data.forEach(participant => {
-        // Create a new table row
+        /**
+         * Create a new table row
+         */
         const row = document.createElement('tr');
 
-        // Create table cells for first name, last name, and email
+        /**
+         * Create table cells for first name, last name, and email
+         */
         const firstNameCell = document.createElement('td');
         const lastNameCell = document.createElement('td');
         const emailCell = document.createElement('td');
 
-        // Populate cell content with participant data
+        /**
+         * Populate cell content with participant data
+         */
         firstNameCell.textContent = participant.firstname;
         lastNameCell.textContent = participant.lastname;
         emailCell.textContent = participant.email;
 
-        // Append cells to the row
+        /**
+         * Append cells to the row
+         */
         row.appendChild(firstNameCell);
         row.appendChild(lastNameCell);
         row.appendChild(emailCell);
 
-        // Append the row to the table body
+        /**
+         * Append the row to the table body
+         */
         tableBody.appendChild(row);
     });
 }
 
-
+/**
+ * Fetches the bookings data from the API.
+ * @param {string} appointmentId - The appointment ID
+ */
 async function fetchBookings(appointmentId) {
+    /**
+     * Set the query parameters
+     */
     const searchParams = new URLSearchParams({
         appointmentId: appointmentId,
     });
 
+    /**
+     * Fetch the bookings data
+     */
     const response = await fetchWithToken('/api/users/bookings?' + searchParams.toString());
     const js = await parseOrRedirect(response);
     renderBookings(js);

+ 44 - 8
public/javascripts/creator-appointments.js

@@ -1,7 +1,15 @@
+/**
+ * Appointment management script.
+ * Handles loading, creating, and editing appointments.
+ */
+
 "use strict";
 
 import {fetchRegular, fetchWithToken, parseOrRedirect} from "./utils.js";
 
+/**
+ * DOM elements for appointment form and error/success messages.
+ */
 const appointmentErrorParagraph = document.getElementById("appointment-error");
 const appointmentSuccessParagraph = document.getElementById("appointment-success");
 const titleInput = document.getElementById('title');
@@ -11,29 +19,40 @@ const startDateInput = document.getElementById('startDate');
 const endDateInput = document.getElementById('endDate');
 const placeInput = document.getElementById('place');
 
-
+/**
+ * Event listener for window load event.
+ * Checks if an appointment ID is provided in the URL query string.
+ * If an appointment ID is found, loads the appointment data and updates the form.
+ */
 window.addEventListener("load", async function () {
     const urlParams = new URLSearchParams(window.location.search);
     const appointment = urlParams.get('appointment');
 
     if (appointment) {
-        // load appointment data
+        // Load appointment data
         await loadAppointment(appointment);
         document.getElementById("appointment-btn").innerText = "Edit Appointment";
         document.getElementById("form-title").innerText = "Edit Appointment";
     }
 
+    /**
+     * Event listener for appointment button click event.
+     * Creates or edits an appointment based on the presence of an appointment ID.
+     */
     document.getElementById("appointment-btn").addEventListener('click', async () => {
         if (!appointment) {
             await createAppointment();
         } else {
-            // modify appointment
-            // TODO Add a modify appointment function
+            // Modify appointment
             await editAppointment(appointment);
         }
     })
 });
 
+/**
+ * Displays appointment data in the form.
+ * @param {Object} data - Appointment data object.
+ */
 async function displayAppointment(data) {
     titleInput.value = data.title;
     descriptionInput.value = data.description;
@@ -43,6 +62,10 @@ async function displayAppointment(data) {
     placeInput.value = data.place;
 }
 
+/**
+ * Loads appointment data from the server.
+ * @param {string} appointment - Appointment ID.
+ */
 async function loadAppointment(appointment) {
     let options = {method: 'GET', headers: {'User-Agent': 'insomnia/10.0.0'}};
 
@@ -60,6 +83,10 @@ async function loadAppointment(appointment) {
     await displayAppointment(js);
 }
 
+/**
+ * Retrieves form data as an object.
+ * @returns {Object} Form data object.
+ */
 function getParameters() {
     const title = titleInput.value;
     const description = descriptionInput.value;
@@ -71,21 +98,32 @@ function getParameters() {
     return {title, description, dueDate, startDate, endDate, place};
 }
 
-
+/**
+ * Edits an existing appointment.
+ * @param {string} appointment - Appointment ID.
+ */
 async function editAppointment(appointment) {
     await setAppointment("modify", appointment);
 }
 
+/**
+ * Creates a new appointment.
+ */
 async function createAppointment() {
     await setAppointment("create", "");
 }
 
+/**
+ * Sets an appointment (create or modify).
+ * @param {string} endpoint - API endpoint (create or modify).
+ * @param {string} appointment - Appointment ID (optional).
+ */
 async function setAppointment(endpoint, appointment) {
     const {title, description, dueDate, startDate, endDate, place} = getParameters();
 
     if (!title || !description || !dueDate || !startDate || !endDate) {
         appointmentSuccessParagraph.innerText = "";
-        appointmentErrorParagraph.innerText = "Not fields filled";
+        appointmentErrorParagraph.innerText = "Not all fields filled";
         return;
     }
 
@@ -122,5 +160,3 @@ async function setAppointment(endpoint, appointment) {
         await navigator.clipboard.writeText(`${window.location.origin}${path}`);
     }
 }
-
-

+ 3 - 1
public/javascripts/index.js

@@ -1,6 +1,8 @@
 "use strict";
 
+/**
+ * Redirect to appointment.html when page root is visited
+ */
 window.addEventListener("load", function() {
     window.location.replace("/html/appointments.html");
-
 });

+ 14 - 1
public/javascripts/navbar.js

@@ -1,10 +1,23 @@
+/**
+ * Logout functionality.
+ *
+ * This script is responsible for removing the user token from local storage and redirecting to the authentication page upon logout click.
+ */
+
 "use strict";
 
+/**
+ * Add an event listener to the window's load event.
+ * This function will be executed when the document has finished loading.
+ */
 window.addEventListener("load", function() {
     document.getElementById("logout-button").addEventListener("click", logout);
 });
 
+/**
+ * Removes the user token from local storage and redirects to the authentication page.
+ */
 function logout() {
     window.localStorage.removeItem('token');
     window.location.replace("/html/auth.html");
-}
+}

+ 33 - 14
public/javascripts/schedule.js

@@ -1,18 +1,25 @@
 "use strict";
 
-import {fetchRegular, getTimeSpan, parseOrRedirect} from "./utils.js";
+/**
+ * Import required functions from utils.js
+ */
+import { fetchRegular, getTimeSpan, parseOrRedirect } from "./utils.js";
 
 let appointment;
 const errorParagraph = document.getElementById('appointment-error');
 const successParagraph = document.getElementById('appointment-success');
 
-
+/**
+ * Event listener for window load
+ */
 window.addEventListener("load", async function () {
     document.getElementById("btn-attend").addEventListener("click", async () => {
         await attendEvent();
     })
+    
     const urlParams = new URLSearchParams(window.location.search);
     appointment = urlParams.get('appointment');
+    
     if (!appointment) {
         window.location.replace("/html/404.html");
     }
@@ -20,8 +27,14 @@ window.addEventListener("load", async function () {
     await getAppointment();
 });
 
+/**
+ * Get appointment details from API
+ *
+ * @async
+ * @returns {Promise<void>}
+ */
 async function getAppointment() {
-    let options = {method: 'GET', headers: {'User-Agent': 'insomnia/10.0.0'}};
+    let options = { method: 'GET', headers: {'User-Agent': 'insomnia/10.0.0'} };
 
     const searchParams = new URLSearchParams({
         appointmentId: appointment,
@@ -35,37 +48,44 @@ async function getAppointment() {
     displayAppointmentDetails(js);
 }
 
+/**
+ * Display appointment details on page
+ *
+ * @param {object} appointment - Appointment data from API
+ */
 function displayAppointmentDetails(appointment) {
-    // Update the innerHTML of the elements to display the appointment details
+    /**
+     * Update element values with appointment details
+     */
     document.getElementById('appointment-date').innerText = appointment._id;
     document.getElementById('title').innerText = appointment.title;
     document.getElementById('description').innerText = appointment.description;
 
-    // Format the dates to a more user-friendly format
     const dueDate = new Date(appointment.dueDate).toLocaleDateString();
     const startDate = new Date(appointment.startDate);
     const endDate = new Date(appointment.endDate);
     const startDateFormatted = startDate.toLocaleString();
-    const endDateFormatted = endDate.toLocaleString();
-
-    console.log(dueDate);
-    console.log(startDate);
-    console.log(endDate);
 
     document.getElementById('due-date').value = dueDate;
     document.getElementById('appointment-date').value = startDateFormatted;
     document.getElementById('time-span').value = getTimeSpan(startDate, endDate);
 
-    // Set place
     document.getElementById('place').innerText = appointment.place;
 }
 
+/**
+ * Attend event by creating a new schedule entry in API
+ *
+ * @async
+ * @returns {Promise<void>}
+ */
 async function attendEvent() {
     const email = document.getElementById('email').value;
     const firstname = document.getElementById('firstname').value;
     const lastname = document.getElementById('lastname').value;
 
     if (!email || !firstname || !lastname) {
+
         errorParagraph.innerText = "Fill in all fields.";
         return;
     }
@@ -81,6 +101,7 @@ async function attendEvent() {
                 lastname: lastname
             })
         });
+
     const js = await response.json();
 
     if (response.status !== 200) {
@@ -90,6 +111,4 @@ async function attendEvent() {
         errorParagraph.innerText = "";
         successParagraph.innerText = "Registered successfully.";
     }
-
-
-}
+}

+ 45 - 3
public/javascripts/utils.js

@@ -1,5 +1,18 @@
+/**
+ * @file utils.js
+ * @description Utility functions for making API requests and handling responses.
+ */
+
 "use strict";
 
+/**
+ * Fetches a resource from the server with authentication token.
+ *
+ * @async
+ * @param {string} url - The URL of the resource to fetch.
+ * @param {Object} options - Options for the fetch request (e.g. method, body).
+ * @returns {Promise<Object>} A promise resolving to the response data.
+ */
 async function fetchWithToken(url, options) {
     const authToken = localStorage.getItem('token');
     return await fetch(url, {...options, headers: {
@@ -9,6 +22,14 @@ async function fetchWithToken(url, options) {
         }});
 }
 
+/**
+ * Fetches a resource from the server without authentication token.
+ *
+ * @async
+ * @param {string} url - The URL of the resource to fetch.
+ * @param {Object} options - Options for the fetch request (e.g. method, body).
+ * @returns {Promise<Object>} A promise resolving to the response data.
+ */
 async function fetchRegular(url, options) {
     return await fetch(url, {...options, headers: {
             'Content-Type': 'application/json',
@@ -16,35 +37,56 @@ async function fetchRegular(url, options) {
         }});
 }
 
-// Function to format time as HH:MM
+/**
+ * Formats a time as HH:MM string.
+ *
+ * @param {Date} date - The date to format.
+ * @returns {string} The formatted time string (e.g. "09:00").
+ */
 function formatTime(date) {
     const hours = date.getHours().toString().padStart(2, '0');
     const minutes = date.getMinutes().toString().padStart(2, '0');
     return `${hours}:${minutes}`;
 }
 
-// Function to get the time span (e.g., 09:00 to 10:00)
+/**
+ * Gets the time span between two dates.
+ *
+ * @param {Date} start - The start date.
+ * @param {Date} end - The end date.
+ * @returns {string} The time span string (e.g. "09:00 to 10:00").
+ */
 function getTimeSpan(start, end) {
     return `${formatTime(new Date(start))} to ${formatTime(new Date(end))}`;
 }
 
+/**
+ * Parses the response data and redirects if necessary.
+ *
+ * @async
+ * @param {Response} response - The server response.
+ * @returns {Promise<Object>} A promise resolving to the parsed response data, or null if a redirect was taken.
+ */
 async function parseOrRedirect(response) {
     if (response.status === 401) {
+        // Handle unauthorized request (redirect to login page)
         window.location.replace("/html/auth.html");
         return;
     }
 
     if (response.status === 410) {
+        // Handle deprecated resource (redirect to deprecated page)
         window.location.replace("/html/410.html");
         return;
     }
 
     const js = await response.json();
     if (!response.ok) {
+        // Handle non-200 status code (redirect to error page)
         window.location.replace("/html/404.html");
     }
 
     return js;
 }
 
-export { fetchWithToken, getTimeSpan, parseOrRedirect, fetchRegular };
+export { fetchWithToken, getTimeSpan, parseOrRedirect, fetchRegular };

+ 4 - 4
public/stylesheets/create-appointment.css

@@ -4,8 +4,6 @@
     --button-hover-background: #5750d9;
 }
 
-/* General Reset */
-
 .content {
     min-height: 80vh;
     box-sizing: border-box;
@@ -28,7 +26,7 @@ textarea {
 
 .container {
     background: white;
-    padding: 20px 30px;
+    padding: 20px 40px;
     border-radius: 8px;
     width: 80%;
     max-width: 500px;
@@ -36,9 +34,11 @@ textarea {
     gap: 20px;
 }
 
-form {
+#appointment-form {
     display: grid;
     gap: 15px;
+    margin-inline: auto;
+    min-width: 95%;
 }
 
 .input-group {

+ 15 - 4
routes/appointments.js

@@ -1,10 +1,20 @@
+/**
+ * Import required dependencies.
+ */
 import express from 'express';
 import Appointment from "../schemas/appointmentSchema.js";
 import Booking from "../schemas/bookingSchema.js";
 import {isDueDatePassed, isValidEmail} from "../utils.js";
 import {app} from "../app.js";
+
+/**
+ * Create an Express router for handling appointment-related routes.
+ */
 const router = express.Router();
 
+/**
+ * Create a new appointment and associate it with a booking.
+ */
 router.post('/create', async function(req, res, next) {
     const { appointment, email, firstname, lastname } = req.body;
 
@@ -14,13 +24,13 @@ router.post('/create', async function(req, res, next) {
         res.status(400).json({ 'message': 'Parameters are incomplete' });
         return;
     }
+
     if (!isValidEmail(email)) {
         res.status(400).json({ 'message': 'Email is invalid' });
         return;
     }
 
     try {
-
         const existingAppointment = await Appointment.findOne({ _id: appointmentId });
         if (!existingAppointment) {
             return res.status(404).json({ message: 'appointment does not exist' });
@@ -39,7 +49,6 @@ router.post('/create', async function(req, res, next) {
             return res.status(404).json({ message: 'already registered' });
         }
 
-
         const newBooking = new Booking({ appointment, email, firstname, lastname });
 
         newBooking.save()
@@ -53,6 +62,9 @@ router.post('/create', async function(req, res, next) {
     }
 });
 
+/**
+ * Retrieve an appointment by ID.
+ */
 router.get('/', function (req, res, next) {
     const {appointmentId, isUser} = req.query;
     Appointment.findOne({ _id: appointmentId })
@@ -60,7 +72,7 @@ router.get('/', function (req, res, next) {
             if (appointment === null) {
                 res.status(404).json({'message': "Appointment not found"});
             } else {
-                // TODO check if a registered user accesses this / move the endpoint
+                // Check if a registered user accesses this endpoint
                 if (isDueDatePassed(appointment["dueDate"]) && !isUser) {
                     return res.status(410).json({ message: 'appointment registration is closed' });
                 } else {
@@ -73,5 +85,4 @@ router.get('/', function (req, res, next) {
         });
 });
 
-
 export { router };

+ 51 - 10
routes/auth.js

@@ -1,20 +1,54 @@
 import express from 'express';
-import {mongoose} from 'mongoose';
+import { mongoose } from 'mongoose';
 import bcrypt from "bcrypt";
 import jwt from "jsonwebtoken";
 import {SECRET_KEY} from "../passport.js";
 import {isValidEmail} from "../utils.js";
 
+/**
+ * Create an Express router instance.
+ *
+ * @type {Express.Router}
+ */
 const router = express.Router();
 
-
+/**
+ * Set the salt rounds for password hashing (10).
+ *
+ * @type {number}
+ */
 const saltRounds = 10;
 
+/**
+ * Define a Mongoose schema for users.
+ *
+ * @typedef {Object} UserSchema
+ * @property {String} email - The user's email address.
+ * @property {String} password - The user's password.
+ */
+
+/**
+ * Create a new Mongoose model from the user schema.
+ *
+ * @type {Model<UserSchema>}
+ */
 const userSchema = new mongoose.Schema({
+    /**
+     * The user's email address.
+     *
+     * @type {String}
+     * @required
+     */
     email: {
         type: String,
         required: true
     },
+    /**
+     * The user's password.
+     *
+     * @type {String}
+     * @required
+     */
     password: {
         type: String,
         required: true
@@ -22,13 +56,20 @@ const userSchema = new mongoose.Schema({
 })
 const User = mongoose.model('User', userSchema, 'users');
 
-// TODO split into different routes (/auth)
-
+/**
+ * Generate a JWT token for the given user.
+ *
+ * @param {Object} user - The user object.
+ * @returns {String} The generated JWT token.
+ */
 function generateToken(user) {
     const payload = { id: user._id };
     return jwt.sign(payload, SECRET_KEY, {expiresIn: '6h'});
 }
 
+/**
+ * Handle a login request.
+ */
 router.post('/login', function (req, res) {
     const email = req.body.email;
     const password = req.body.password;
@@ -57,11 +98,13 @@ router.post('/login', function (req, res) {
         })
         .catch(err => {
             console.log(err);
-            res.status(500).json({ error: err.message }); // Ensure you send the error message
+            res.status(500).json({ error: err.message }); 
         });
 });
 
-
+/**
+ * Handle a registration request.
+ */
 router.post('/register', async function (req, res) {
     const email = req.body.email;
     const password = req.body.password;
@@ -75,28 +118,26 @@ router.post('/register', async function (req, res) {
     }
 
     try {
-        // Check if user already exists
         const existingUser = await User.findOne({ email: email });
         if (existingUser) {
             return res.status(403).json({ message: 'user already exists' });
         }
+
         // Hash the password
         bcrypt.hash(password, saltRounds, async function (err, hash) {
             if (err) {
                 return res.status(500).json({ error: err.message });
             } else if (hash) {
-                // Insert user into database and generate token
                 await User.collection.insertOne({ email: email, password: hash });
                 const user = await User.findOne({ email: email });
+  
                 return res.json({ token: generateToken(user) });
             }
         });
     } catch (err) {
-        // Handle errors
         console.error(err);
         return res.status(500).json({ error: 'Internal Server Error' });
     }
 });
 
-
 export { router, User };

+ 27 - 9
routes/members.js

@@ -5,12 +5,20 @@ import Appointment from "../schemas/appointmentSchema.js";
 import Booking from "../schemas/bookingSchema.js";
 import AppointmentSchema from "../schemas/appointmentSchema.js";
 import {isDatePassed, isDueDatePassed} from "../utils.js";
-const router = express.Router();
-
 
+/**
+ * Router for handling appointments.
+ */
+const router = express.Router();
 
+/**
+ * Middleware to authenticate with passport
+ */
 router.use(passport.authenticate('jwt', { session: false }));
 
+/**
+ * Middleware to pass user ID to req.userId if it exists in the request.
+ */
 router.use((req, res, next) => {
     if (req.user && req.user.id) {
         req.userId = req.user.id; // Pass user ID to req.userId
@@ -18,12 +26,14 @@ router.use((req, res, next) => {
     next();
 });
 
-
+/**
+ * Create a new appointment.
+ */
 router.post('/create', function(req, res, next) {
     const user = req.userId;
     const { title, description, dueDate, place, startDate, endDate } = req.body;
 
-    if (!title || title.length === 0 || !dueDate || !dueDate || !description || !startDate || !endDate || !place) {
+    if (!title || title.length === 0 || !dueDate || !description || !startDate || !endDate || !place) {
         res.status(400).json({ 'message': 'Empty parameter' });
         return;
     }
@@ -38,7 +48,6 @@ router.post('/create', function(req, res, next) {
         return;
     }
 
-    // TODO check if end date is before start date
     if (isDatePassed(endDate, startDate)) {
         res.status(400).json({ 'message': 'End date is before start date' });
         return;
@@ -49,14 +58,16 @@ router.post('/create', function(req, res, next) {
     newTask.save()
         .then(doc => res.json({ "id": doc._id }))
         .catch(err => res.status(500).json({ 'message': err }));
-
 });
 
+/**
+ * Modify an existing appointment.
+ */
 router.post('/modify', function (req, res, next) {
     const user = req.userId;
 
     const { appointmentId, title, description, dueDate, place, startDate, endDate } = req.body;
-    if (!title || !dueDate || !dueDate || !description || !startDate || !endDate || !place || !appointmentId) {
+    if (!title || !dueDate || !description || !startDate || !endDate || !place || !appointmentId) {
         res.status(400).json({ 'error': 'Empty parameter' });
         return;
     }
@@ -80,6 +91,9 @@ router.post('/modify', function (req, res, next) {
         .catch(err => res.status(404).json({ 'message': 'Not found' }));
 });
 
+/**
+ * Delete an appointment.
+ */
 router.delete('/delete', function (req, res, next) {
     const user = req.userId;
     const {appointmentId} = req.body;
@@ -99,7 +113,9 @@ router.delete('/delete', function (req, res, next) {
         .catch(err => res.status(500).json({ 'message': err }));
 });
 
-
+/**
+ * Get all appointments for the authenticated user.
+ */
 router.get('/appointments', function (req, res, next) {
     const user = req.userId;
     Appointment.find({ user: user })
@@ -111,6 +127,9 @@ router.get('/appointments', function (req, res, next) {
         });
 });
 
+/**
+ * Get all bookings for a specific appointment.
+ */
 router.get('/bookings', function (req, res, next) {
     const { appointmentId } = req.query;
 
@@ -133,5 +152,4 @@ router.get('/bookings', function (req, res, next) {
 
 });
 
-
 export { router };

+ 26 - 0
schemas/appointmentSchema.js

@@ -1,6 +1,26 @@
 import mongoose from "mongoose";
 
+/**
+ * Define a schema for an appointment using mongoose.
+ *
+ * @description This schema represents an appointment between a user and a service provider.
+ * @typedef {Object} AppointmentSchema
+ * @property {String} user - The ID of the user making the appointment (e.g. "user123").
+ * @property {String} title - A brief title for the appointment (e.g. " haircut").
+ * @property {String} description - A longer description of the appointment.
+ * @property {Date} dueDate - The date and time when the appointment is scheduled.
+ * @property {String} place - The location where the appointment will take place.
+ * @property {Date} startDate - The start date and time of the appointment.
+ * @property {Date} endDate - The end date and time of the appointment.
+ */
 
+/**
+ * Create a mongoose model for appointments using the defined schema.
+ *
+ * @description This model allows you to interact with the appointments collection in your MongoDB database.
+ * @typedef {Object} Appointment
+ * @static
+ */
 const appointmentSchema = new mongoose.Schema({
     user: {
         type: String,
@@ -31,6 +51,12 @@ const appointmentSchema = new mongoose.Schema({
         required: true
     }
 });
+
+/**
+ * Create a mongoose model for appointments and name it "Appointment".
+ *
+ * @description This model allows you to interact with the appointments collection in your MongoDB database.
+ */
 const Appointment = mongoose.model('Appointment', appointmentSchema, 'appointment');
 
 export default Appointment;