From a7a04a7dbaafa198ad23239b00af14b3b95522a8 Mon Sep 17 00:00:00 2001 From: Nola Dodd Date: Tue, 4 Jun 2024 15:42:45 -0700 Subject: [PATCH] 5, 6 --- .../20210123122225_createReservationsTable.js | 1 + .../20240530112512_createTablesTable.js | 6 +- back-end/src/db/seeds/00-reservations.json | 97 ++++++++- back-end/src/db/seeds/01-tables.json | 12 +- .../reservations/reservations.controller.js | 66 +++++-- .../src/reservations/reservations.router.js | 8 + .../src/reservations/reservations.service.js | 27 ++- back-end/src/tables/tables.controller.js | 119 ++++++++++- back-end/src/tables/tables.router.js | 12 +- back-end/src/tables/tables.service.js | 42 +++- front-end/src/dashboard/Dashboard.js | 117 +++++++---- front-end/src/layout/AssignTable.js | 147 ++++++++++++++ front-end/src/layout/CreateEditReservation.js | 4 +- front-end/src/layout/CreateEditTable.js | 20 +- front-end/src/layout/RootRoutes.js | 27 +-- front-end/src/layout/Search.js | 45 ++++- front-end/src/utils/api.js | 187 +++++++++++++++++- 17 files changed, 844 insertions(+), 93 deletions(-) create mode 100644 front-end/src/layout/AssignTable.js diff --git a/back-end/src/db/migrations/20210123122225_createReservationsTable.js b/back-end/src/db/migrations/20210123122225_createReservationsTable.js index 6c93230..c648d8b 100644 --- a/back-end/src/db/migrations/20210123122225_createReservationsTable.js +++ b/back-end/src/db/migrations/20210123122225_createReservationsTable.js @@ -7,6 +7,7 @@ exports.up = function (knex) { table.date("reservation_date") table.time("reservation_time") table.integer("people") + table.string("status") table.timestamps(true, true); }); }; diff --git a/back-end/src/db/migrations/20240530112512_createTablesTable.js b/back-end/src/db/migrations/20240530112512_createTablesTable.js index 97d4630..8e11651 100644 --- a/back-end/src/db/migrations/20240530112512_createTablesTable.js +++ b/back-end/src/db/migrations/20240530112512_createTablesTable.js @@ -4,11 +4,15 @@ exports.up = function(knex) { table.increments("table_id").primary(); table.string("table_name") table.integer("capacity") + table.integer("reservation_id") + table.foreign("reservation_id") + .references("reservation_id") + .inTable("reservations") table.timestamps(true, true); }); }; exports.down = function(knex) { return knex.schema.dropTable("tables") - .then(() => console.log("Dropped Table Table")) + .then(() => console.log("Dropped Tables Table")) }; diff --git a/back-end/src/db/seeds/00-reservations.json b/back-end/src/db/seeds/00-reservations.json index 5d69c1f..259971a 100644 --- a/back-end/src/db/seeds/00-reservations.json +++ b/back-end/src/db/seeds/00-reservations.json @@ -6,6 +6,7 @@ "reservation_date": "2020-12-31", "reservation_time": "20:00:00", "people": 6, + "status": "Booked", "created_at": "2020-12-10T08:30:32.326Z", "updated_at": "2020-12-10T08:30:32.326Z" }, @@ -16,6 +17,7 @@ "reservation_date": "2020-12-30", "reservation_time": "20:00", "people": 1, + "status": "Booked", "created_at": "2020-12-10T08:31:32.326Z", "updated_at": "2020-12-10T08:31:32.326Z" }, @@ -26,6 +28,7 @@ "reservation_date": "2020-12-30", "reservation_time": "18:00", "people": 1, + "status": "Booked", "created_at": "2020-12-10T08:31:32.326Z", "updated_at": "2020-12-10T08:31:32.326Z" }, @@ -36,6 +39,7 @@ "reservation_date": "2025-12-30", "reservation_time": "18:00", "people": 3, + "status": "Booked", "created_at": "2020-12-10T08:31:32.326Z", "updated_at": "2020-12-10T08:31:32.326Z" }, @@ -46,6 +50,7 @@ "reservation_date": "2026-12-30", "reservation_time": "18:00", "people": 2, + "status": "Booked", "created_at": "2020-12-10T08:31:32.326Z", "updated_at": "2020-12-10T08:31:32.326Z" }, @@ -53,9 +58,10 @@ "first_name": "Clark", "last_name": "Kent", "mobile_number": "620-346-4852", - "reservation_date": "2024-05-30", + "reservation_date": "2024-05-31", "reservation_time": "18:00", "people": 2, + "status": "Booked", "created_at": "2024-05-29T08:31:32.326Z", "updated_at": "2024-05-29T08:31:32.326Z" }, @@ -63,9 +69,10 @@ "first_name": "Bruce", "last_name": "Wayne", "mobile_number": "212-453-4792", - "reservation_date": "2024-05-31", + "reservation_date": "2024-06-01", "reservation_time": "13:00", "people": 1, + "status": "Booked", "created_at": "2024-05-29T08:31:32.326Z", "updated_at": "2024-05-29T08:31:32.326Z" }, @@ -73,9 +80,10 @@ "first_name": "Peter", "last_name": "Parker", "mobile_number": "215-147-9053", - "reservation_date": "2024-06-01", + "reservation_date": "2024-06-02", "reservation_time": "10:40", "people": 4, + "status": "Booked", "created_at": "2024-05-29T08:31:32.326Z", "updated_at": "2024-05-29T08:31:32.326Z" }, @@ -83,9 +91,10 @@ "first_name": "Diana", "last_name": "Prince", "mobile_number": "808-333-4819", - "reservation_date": "2024-06-02", + "reservation_date": "2024-06-03", "reservation_time": "14:00", "people": 3, + "status": "Booked", "created_at": "2024-05-29T08:31:32.326Z", "updated_at": "2024-05-29T08:31:32.326Z" }, @@ -93,10 +102,88 @@ "first_name": "Mickey", "last_name": "Mouse", "mobile_number": "714-222-2468", - "reservation_date": "2024-06-03", + "reservation_date": "2024-06-04", "reservation_time": "12:00", "people": 6, + "status": "Booked", "created_at": "2024-05-29T08:31:32.326Z", "updated_at": "2024-05-29T08:31:32.326Z" + }, + { + "first_name": "Bugs", + "last_name": "Bunny", + "mobile_number": "714-808-5623", + "reservation_date": "2024-06-05", + "reservation_time": "14:00", + "people": 5, + "status": "Booked", + "created_at": "2024-06-01T08:31:32.326Z", + "updated_at": "2024-06-01T08:31:32.326Z" + }, + { + "first_name": "Daffy", + "last_name": "Duck", + "mobile_number": "714-238-1167", + "reservation_date": "2024-06-05", + "reservation_time": "15:00", + "people": 1, + "status": "Booked", + "created_at": "2024-06-01T08:31:32.326Z", + "updated_at": "2024-06-01T08:31:32.326Z" + }, + { + "first_name": "Mario", + "last_name": "Luigi", + "mobile_number": "714-808-5623", + "reservation_date": "2024-06-06", + "reservation_time": "11:00", + "people": 2, + "status": "Booked", + "created_at": "2024-06-01T08:31:32.326Z", + "updated_at": "2024-06-01T08:31:32.326Z" + }, + { + "first_name": "Ninja", + "last_name": "Turtles", + "mobile_number": "714-808-5623", + "reservation_date": "2024-06-06", + "reservation_time": "16:00", + "people": 4, + "status": "Booked", + "created_at": "2024-06-01T08:31:32.326Z", + "updated_at": "2024-06-01T08:31:32.326Z" + }, + { + "first_name": "Barbie", + "last_name": "Ken", + "mobile_number": "205-900-1093", + "reservation_date": "2024-06-07", + "reservation_time": "12:00", + "people": 2, + "status": "Booked", + "created_at": "2024-06-01T08:31:32.326Z", + "updated_at": "2024-06-01T08:31:32.326Z" + }, + { + "first_name": "Elle", + "last_name": "Woods", + "mobile_number": "808-356-1276", + "reservation_date": "2024-06-07", + "reservation_time": "18:00", + "people": 10, + "status": "Booked", + "created_at": "2024-06-01T08:31:32.326Z", + "updated_at": "2024-06-01T08:31:32.326Z" + }, + { + "first_name": "Indiana", + "last_name": "Jones", + "mobile_number": "750-547-0378", + "reservation_date": "2024-06-08", + "reservation_time": "15:00", + "people": 4, + "status": "Booked", + "created_at": "2024-06-01T08:31:32.326Z", + "updated_at": "2024-06-01T08:31:32.326Z" } ] diff --git a/back-end/src/db/seeds/01-tables.json b/back-end/src/db/seeds/01-tables.json index 97d3671..1ec4c85 100644 --- a/back-end/src/db/seeds/01-tables.json +++ b/back-end/src/db/seeds/01-tables.json @@ -1,18 +1,22 @@ [ { "table_name": "Bar #1", - "capacity": 1 + "capacity": 1, + "reservation_id": null }, { "table_name": "Bar #2", - "capacity": 1 + "capacity": 1, + "reservation_id": null }, { "table_name": "#1", - "capacity": 6 + "capacity": 6, + "reservation_id": null }, { "table_name": "#2", - "capacity": 6 + "capacity": 6, + "reservation_id": null } ] diff --git a/back-end/src/reservations/reservations.controller.js b/back-end/src/reservations/reservations.controller.js index 638248c..35d4765 100644 --- a/back-end/src/reservations/reservations.controller.js +++ b/back-end/src/reservations/reservations.controller.js @@ -8,7 +8,6 @@ const moment = require("moment-timezone") async function list(req, res, next) { const {date} = req.query - console.log("list date", date) let reservations if (date){ @@ -31,7 +30,7 @@ async function create (req, res){ } function correctTimesOnly(req, res, next){ - const {data} = req.body // Define 'data' here + const {data = {}} = req.body // Parse the reservation date and time in the server's time zone const reservationDateTime = moment.tz(`${data.reservation_date}T${data.reservation_time}`, 'America/Los_Angeles'); @@ -58,21 +57,19 @@ function correctTimesOnly(req, res, next){ } - - async function read(req, res){ - const data = res.locals.reservation_id + const data = res.locals.reservation res.json({data}) } function reservationExists(req, res, next){ - service.read(req.params.reservation_id) + service.read(req.params.reservationId) .then((reservation) => { if(reservation){ res.locals.reservation = reservation return next() } - next({status: 404, message: 'Reservation cannot be found'}) + next({status: 404, message: `Reservation ${req.params.reservationId} cannot be found`}) }) .catch(next) } @@ -89,15 +86,15 @@ function propertiesExist(req, res, next){ return next({status: 400, message: "Data is required"}); } - const { first_name, last_name, mobile_number, reservation_date, reservation_time, people } = data; + const { first_name, last_name, mobile_number, reservation_date, reservation_time, status, people } = data; - console.log(data); + console.log("propertiesExist", data); - if (!first_name || first_name === ""){ + if (!first_name || first_name.trim() === ""){ return next({status: 400, message: "Reservation must include a first_name"}); } - if (!last_name || last_name === ""){ + if (!last_name || last_name.trim() === ""){ return next({status: 400, message: "Reservation must include a last_name"}); } @@ -121,9 +118,54 @@ function propertiesExist(req, res, next){ } +async function updateStatus(req, res, next){ + const updatedReservation = { + ...req.body.data, + reservation_id: res.locals.reservation.reservation_id, + } + + const data = await service.updateStatus(updatedReservation) + console.log("status Updated", data) + + res.status(200).json({data: data[0]}) +} + +function reservationStatusCheck(req, res, next){ + const { data = {} } = req.body; + + if (Object.keys(data).length === 0){ + return next({status: 400, message: "Data is required"}); + } + + const { first_name, last_name, mobile_number, reservation_date, reservation_time, status, people } = data; + + console.log("reservationStatusCheck", data); + const validStatus = ["booked", "seated"] + + if (status.toLowerCase() === "seated" || status.toLowerCase() === "finished"){ + return next({status: 400, message: "Reservation status cannot be `seated` or `finished`."}) + } + + if (status.toLowerCase() === "finished"){ + return next({status: 400, message: "This reservation is already finished and cannot be updated"}) + } + + if (!status || status === undefined || status === null){ + return next({status: 400, message: "The reservation status is missing"}) + } + + if (!validStatus.includes(status.toLowerCase())){ + return next({status: 400, message: "This reservation status is unknown and must be a valid status."}) + } + + next(); +} + + module.exports = { list: [asyncErrorBoundary(list)], create: [propertiesExist, correctTimesOnly, asyncErrorBoundary(create)], - read: [asyncErrorBoundary(read)] + read: [reservationExists, asyncErrorBoundary(read)], + updateStatus: [reservationExists, reservationStatusCheck, asyncErrorBoundary(updateStatus)] }; diff --git a/back-end/src/reservations/reservations.router.js b/back-end/src/reservations/reservations.router.js index a518367..354153f 100644 --- a/back-end/src/reservations/reservations.router.js +++ b/back-end/src/reservations/reservations.router.js @@ -14,4 +14,12 @@ router.route("/") .post(controller.create) .all(methodNotAllowed) +router.route("/:reservationId") + .get(controller.read) + .all(methodNotAllowed) + +router.route("/:reservationId/status") + .put(controller.updateStatus) + .all(methodNotAllowed) + module.exports = router; diff --git a/back-end/src/reservations/reservations.service.js b/back-end/src/reservations/reservations.service.js index f8b62fd..62f1bc9 100644 --- a/back-end/src/reservations/reservations.service.js +++ b/back-end/src/reservations/reservations.service.js @@ -14,21 +14,42 @@ return knex("reservations") } function create(newReservation){ + newReservation.status = "Booked" + return knex("reservations") .insert(newReservation, "*") .then(createdReservation => createdReservation[0]) } - function read(reservation_id){ + function read(reservationId){ return knex("reservations") .select("*") - .where({reservation_id: reservation_id}) + .where({reservation_id: reservationId}) .first() } + function updateStatus(updatedReservation){ + console.log("knexUpdate", updatedReservation) + + return knex("reservations") + .select("*") + .where({reservation_id: updatedReservation.reservation_id}) + .update(updatedReservation, "*") + } + + function search(mobile_number) { + return knex("reservations") + .whereRaw( + "translate(mobile_number, '() -', '') like ?", + `%${mobile_number.replace(/\D/g, "")}%` + ) + .orderBy("reservation_date"); + } + module.exports = { list, listByDate, create, - read + read, + updateStatus } \ No newline at end of file diff --git a/back-end/src/tables/tables.controller.js b/back-end/src/tables/tables.controller.js index 5a98821..aa8f8de 100644 --- a/back-end/src/tables/tables.controller.js +++ b/back-end/src/tables/tables.controller.js @@ -1,12 +1,127 @@ const asyncErrorBoundary = require("../errors/asyncErrorBoundary"); const service = require("./tables.service") -const moment = require("moment") +const reservationService = require("../reservations/reservations.service") async function list(req, res) { - console.log("list tables") res.json({ data: await service.list() }); } +async function create (req, res){ + const data = await service.create(req.body.data) + console.log("created new table", data) + + res.status(201).json({data}) +} + +async function read(req, res){ + const data = res.locals.table + console.log("tablesread", data) + + res.json({data}) +} + +function tableCreateValid(req, res, next){ + const {data = {}} = req.body + + const {table_name, capacity} = data + + if (!data){ + return next({ status: 400, message: "The data is missing." }); + } + + if (!table_name || table_name.trim() === ""){ + return next({ status: 400, message: "The table_name is missing." }); + } + + if (table_name.length === 1){ + return next({ status: 400, message: "The table_name needs to be more than one character." }); + } + + if (!capacity || capacity === 0 || typeof capacity !== "number" ){ + return next({status: 400, message: "The table capacity must be 1 or above"}); + } + + next() +} + +function tableExists (req, res, next){ + service.read(req.params.tableId) + .then(table => { + if(table){ + res.locals.table = table + return next() + } + next({status: 404, message: `table_id ${req.params.tableId} cannot be found`}) + }) + .catch(next) +} + +async function tableCheck(req, res, next){ + const tableId = req.params.tableId; + const reservationId = req.body.data.reservation_id + + const table = await service.read(tableId) + const reservation = await reservationService.read(reservationId) + + if (table.capacity < reservation.people) { + return next({ status: 400, message: 'The table does not have enough capacity for the reservation.' }); + } + + if (table.reservation_id != null) { + return next({ status: 400, message: 'The table is already occupied.' }); + + } + + if (!req.body.data || !reservationId) { + return next({ status: 400, message: 'The reservation_id does not exist.' }); + } + + next() +} + +async function update(req, res, next){ + const reservationId = req.body.data.reservation_id; + console.log("updated table", reservationId) + + const updatedTable = {...req.body.data, + table_id: req.params.tableId, + reservation_id: reservationId + } + const data = await service.update(updatedTable) + res.status(200).json({data}) +} + +async function deleteCheck(req, res, next){ + const tableId = req.params.tableId; + const table = await service.read(tableId) + + if (table.reservation_id === null){ + return next({ status: 400, message: "This table is not occupied"}) + } + + if (!table.table_id){ + return next({ status: 404, message: "This table has no table_id"}) + } + + next() +} + +async function destroy(req, res, next){ + service.delete(res.locals.table.tableId) + +} + +async function freeTable(req, res){ + const {table} = res.locals + await service.freeTable(table.table_id); + res.sendStatus(200); +} + module.exports = { list: asyncErrorBoundary(list), + create: [tableCreateValid, asyncErrorBoundary(create)], + read: [tableExists, asyncErrorBoundary(read)], + update: [tableExists, tableCheck, asyncErrorBoundary(update)], + delete: [asyncErrorBoundary(deleteCheck), asyncErrorBoundary(destroy)], + freeTable: [tableExists, asyncErrorBoundary(deleteCheck), asyncErrorBoundary(freeTable) ] }; \ No newline at end of file diff --git a/back-end/src/tables/tables.router.js b/back-end/src/tables/tables.router.js index e930ba0..fa72269 100644 --- a/back-end/src/tables/tables.router.js +++ b/back-end/src/tables/tables.router.js @@ -5,8 +5,18 @@ */ const router = require("express").Router(); +const methodNotAllowed = require("../errors/methodNotAllowed"); const controller = require("./tables.controller"); -router.route("/").get(controller.list); +router.route("/") + .get(controller.list) + .post(controller.create) + .all(methodNotAllowed) + +router.route("/:tableId/seat") + .get(controller.read) + .put(controller.update) + .delete(controller.freeTable) + .all(methodNotAllowed) module.exports = router; \ No newline at end of file diff --git a/back-end/src/tables/tables.service.js b/back-end/src/tables/tables.service.js index 894ca2f..2d090fd 100644 --- a/back-end/src/tables/tables.service.js +++ b/back-end/src/tables/tables.service.js @@ -1,9 +1,49 @@ const knex = require("../db/connection") function list (){ - return knex("tables").select("*") + return knex("tables") + .select("*") + .orderBy("table_name", "asc") } +function read(tableId){ + return knex("tables") + .select("*") + .where({table_id: tableId}) + .first() +} + +function create(newTable){ + return knex("tables") + .insert(newTable, "*") + .then(createdTable => createdTable[0]) +} + +function update(updatedTable){ + return knex("tables") + .select("*") + .where({table_id: updatedTable.table_id}) + .update(updatedTable, "*") +} + +function destroy(selectedTable){ + return knex("tables") + .select("*") + .where({table_id: selectedTable.table_id}) + .del() +} + +function freeTable(tableId) { + return knex("tables") + .where({ table_id: tableId }) + .update({ reservation_id: null }); + } + module.exports = { list, + create, + read, + update, + delete: destroy, + freeTable, } \ No newline at end of file diff --git a/front-end/src/dashboard/Dashboard.js b/front-end/src/dashboard/Dashboard.js index d45bad1..9f1942f 100644 --- a/front-end/src/dashboard/Dashboard.js +++ b/front-end/src/dashboard/Dashboard.js @@ -1,6 +1,6 @@ import React, { useEffect, useState } from "react"; -import {useLocation, useNavigate} from "react-router-dom" -import { listReservations, listTables } from "../utils/api"; +import {useLocation, useNavigate, Link} from "react-router-dom" +import { updateReservationFinished, updateReservationSeated, deleteTableAssignment, listReservations, listTables } from "../utils/api"; import ErrorAlert from "../layout/ErrorAlert"; import { today, previous, next } from "../utils/date-time"; @@ -19,6 +19,7 @@ function Dashboard() { let location = useLocation() const query = new URLSearchParams(location.search); + let date = query.get("date"); if (!date) { date = today(); @@ -30,48 +31,91 @@ function Dashboard() { const abortController = new AbortController(); setReservationsError(null); listTables(abortController.signal) - .then(setTables); + .then(setTables) + .catch(error => { + if (error.name === 'AbortError') { + console.log('Fetch request for tables cancelled'); + } else { + throw error; + } + }); listReservations({ date }, abortController.signal) .then(setReservations) - .catch(setReservationsError); + .catch(error => { + if (error.name === 'AbortError') { + console.log('Fetch request for reservations cancelled'); + } else { + throw error; + } + }); return () => abortController.abort(); } + + const handleFinish = async (event) => { + console.log("handleSubmit") + event.preventDefault() + const confirm = window.confirm("Is this table ready to seat new guests? This cannot be undone.") - const reservationItems = reservations.map((reservation, index) => ( - reservation.reservation_date === date ? -
  • -
    -
    -
    Reservation {reservation.reservation_id}
    -

    Name: {reservation.first_name} {reservation.last_name}

    -

    Mobile Number: {reservation.mobile_number}

    -

    Reservation Time: {reservation.reservation_time} --- {reservation.reservation_date}

    -

    Number of People: {reservation.people}

    - - - -
    -
    -
  • - : null - )); + if (confirm){ + const selectedTableId = event.target.value; + const selectedTable = tables.find(table => table.table_id === Number(selectedTableId)) + const finishedReservation = reservations.find(reservation => reservation.reservation_id === Number(selectedTable.reservation_id)) + console.log("finishedRes", finishedReservation, selectedTable, selectedTableId) - const tableItems = tables.map((table, index) => ( -
  • -
    -
    -
    Table {table.table_name}
    -

    Table Capacity: {table.capacity}

    - - - -
    -
    -
  • + try { + await deleteTableAssignment(selectedTable) + await updateReservationFinished(finishedReservation) + navigate(0) + } catch (error){ + setReservationsError(error) + } + } + } + const validReservations = reservations.filter((reservation) => + reservation.reservation_date === date && reservation.status !== "Finished" + ); - )) + const reservationItems = validReservations.map((reservation, index) => ( +
  • +
    +
    +
    Reservation {reservation.reservation_id}
    +

    Name: {reservation.first_name} {reservation.last_name}

    +

    Mobile Number: {reservation.mobile_number}

    +

    Reservation Time: {reservation.reservation_time}

    +

    Number of People: {reservation.people}

    +

    + Status: {reservation.status} {reservation.status === "Booked" ? + Seat + : null} +

    + + +
    +
    +
  • + )); + + const tableItems = tables.map((table, index) => ( +
  • +
    +
    +
    {table.table_name}
    +

    Table Capacity: {table.capacity}

    +

    + Status: {table.reservation_id ? + <>Occupied: Reservation {table.reservation_id} + + : Free} + +

    +
    +
    +
  • + )); + return (
    @@ -83,10 +127,9 @@ function Dashboard() { - {JSON.stringify(reservations)}
    -

    Reservations

    +

    Today's Reservations

      {reservationItems}
    diff --git a/front-end/src/layout/AssignTable.js b/front-end/src/layout/AssignTable.js new file mode 100644 index 0000000..99ced03 --- /dev/null +++ b/front-end/src/layout/AssignTable.js @@ -0,0 +1,147 @@ +import React, { useEffect, useState } from "react"; +import {useNavigate, useParams} from "react-router-dom" +import { updateReservationSeated, loadReservation, listTables, updateTable } from "../utils/api"; +import ErrorAlert from "../layout/ErrorAlert"; + +/** + * Defines the dashboard page. + * @param date + * the date for which the user wants to view reservations. + * @returns {JSX.Element} + */ +function AssignTable() { + const [reservation, setReservation] = useState([]) + const [reservationsError, setReservationsError] = useState(null); + + const [tables, setTables] = useState([]) + const [selectedTable, setSelectedTable] = useState(null) + console.log(selectedTable) + + let navigate = useNavigate() + const { reservationId } = useParams(); + + useEffect(() => { + loadReservation(reservationId, null) + .then((result) => setReservation(result)) + .catch(error => { + console.error(`Error loading reservation: ${error}`); + }); + }, [reservationId]); + +useEffect(() => { + function loadDashboard(){ + const abortController = new AbortController() + setReservationsError(null) + listTables(abortController.signal) + .then((tables) => { + setTables(tables) + if (tables.length > 0){ + setSelectedTable(tables[0]) + } + }) + return () => abortController.abort() + } + loadDashboard() +}, []) + + const handleUpdateSubmit = async (event) => { + console.log("handleSubmit") + event.preventDefault() + + try { + await updateTable(selectedTable, reservation) + await updateReservationSeated(reservation) + + navigate(`/dashboard`) + } catch (error){ + setReservationsError(error) + } +} + +const handleChange = (event) => { + const selectedTableId = event.target.value; + const selectedTable = tables.find(table => table.table_id === Number(selectedTableId)); + setSelectedTable(selectedTable) +} + +const handleStatusSeated = async (reservationId) => { + +const selectedReservation = reservation.find(reserve => reserve.reservation_id === Number(reservationId)); +console.log("handleStatusChange", selectedReservation) + +try{ + await updateReservationSeated(selectedReservation) +} catch (error){ + setReservationsError(error) +} +} + + const reservationCard = + reservation ? +
    +
  • +
    +
    +
    Reservation {reservation.reservation_id}
    +

    Name: {reservation.first_name} {reservation.last_name}

    +

    Mobile Number: {reservation.mobile_number}

    +

    Reservation Time: {reservation.reservation_time}

    +

    Number of People: {reservation.people}

    +
    +
    +
  • +
    : null + + const tableItems = tables.map((table, index) => ( +
  • +
    +
    +
    {table.table_name}
    +

    Table Capacity: {table.capacity}

    +

    + Status: {table.reservation_id ? + <>Occupied: Reservation {table.reservation_id} + : Free} +

    +
    +
    +
  • + )); + + + + + const tableOptions = +
    + + + +
    + + return ( +
    +
    +
    +

    Assign Reservation {reservation.reservation_id} to Table

    + +
    +
    +
    + {reservationCard} +
    +
    + {tableOptions} + +
    +
    +
      {tableItems}
    +
    +
    + ); +} + +export default AssignTable; diff --git a/front-end/src/layout/CreateEditReservation.js b/front-end/src/layout/CreateEditReservation.js index 35b83c4..8247b2d 100644 --- a/front-end/src/layout/CreateEditReservation.js +++ b/front-end/src/layout/CreateEditReservation.js @@ -1,5 +1,5 @@ import React, {useState } from "react"; -import {Link, useNavigate} from "react-router-dom" +import {useNavigate} from "react-router-dom" import { createReservation } from "../utils/api"; import ErrorAlert from "./ErrorAlert"; @@ -135,7 +135,7 @@ function CreateEditReservation(){
    - Cancel +
    diff --git a/front-end/src/layout/CreateEditTable.js b/front-end/src/layout/CreateEditTable.js index df57a40..acc37e6 100644 --- a/front-end/src/layout/CreateEditTable.js +++ b/front-end/src/layout/CreateEditTable.js @@ -1,5 +1,7 @@ import React, {useState } from "react"; -import {Link, useNavigate} from "react-router-dom" +import {useNavigate} from "react-router-dom" +import ErrorAlert from "./ErrorAlert"; +import { createTable } from "../utils/api"; function CreateEditTable(){ const initialFormState ={ @@ -8,6 +10,8 @@ function CreateEditTable(){ } const [formData, setFormData] = useState({...initialFormState}) + const [formError, setFormError] = useState(null); + console.log(formData) const navigate = useNavigate() @@ -15,11 +19,18 @@ function CreateEditTable(){ const handleChange = ({target}) => { setFormData({...formData, [target.name]: target.value}) } + const handleSubmit = async (event) => { console.log("handleSubmit") event.preventDefault() - setFormData(initialFormState); - navigate(`/dashboard`) + + try { + await createTable(formData) + setFormData(initialFormState); + navigate(`/dashboard`) + } catch (error){ + setFormError(error) + } } const createTableForm = ( @@ -56,8 +67,9 @@ function CreateEditTable(){
    - Cancel + + ) diff --git a/front-end/src/layout/RootRoutes.js b/front-end/src/layout/RootRoutes.js index 85c4ac6..07f3ff7 100644 --- a/front-end/src/layout/RootRoutes.js +++ b/front-end/src/layout/RootRoutes.js @@ -7,6 +7,7 @@ import CreateEditReservation from "./CreateEditReservation"; import { listReservations } from "../utils/api"; import CreateEditTable from "./CreateEditTable"; import Search from "./Search"; +import AssignTable from "./AssignTable" /** * Defines all the routes for the application. @@ -19,17 +20,17 @@ function RootRoutes() { const [reservations, setReservations] = useState([]) - useEffect(() => { - async function fetchReservations(){ - try{ - const fetchedReservations = await listReservations() - setReservations(fetchedReservations) - } catch (error){ - console.error("Error fetching reservations:", error) + useEffect(() => { + async function fetchReservations(){ + try{ + const fetchedReservations = await listReservations({today}) + setReservations(fetchedReservations) + } catch (error){ + console.error("Error fetching reservations:", error) + } } - } - fetchReservations() - }, [setReservations]) + fetchReservations() + }, [setReservations]) return ( @@ -37,11 +38,11 @@ function RootRoutes() { } /> } /> } /> - } /> - } /> + } /> + } /> } /> }/> - } /> + } /> } /> ); diff --git a/front-end/src/layout/Search.js b/front-end/src/layout/Search.js index 6cbeb68..7632f48 100644 --- a/front-end/src/layout/Search.js +++ b/front-end/src/layout/Search.js @@ -1,5 +1,5 @@ import React, {useState } from "react"; -import {useNavigate} from "react-router-dom" +import {Link, useNavigate} from "react-router-dom" function Search({reservations}){ const initialFormState ={ @@ -7,6 +7,7 @@ function Search({reservations}){ } const [formData, setFormData] = useState({...initialFormState}) + const [currentSearch, setCurrentSearch] = useState() console.log(formData) const navigate = useNavigate() @@ -14,11 +15,13 @@ function Search({reservations}){ const handleChange = ({target}) => { setFormData({...formData, [target.name]: target.value}) } + const handleSubmit = async (event) => { - console.log("handleSubmit") + console.log("handleSearchSubmit") event.preventDefault() - setFormData(initialFormState); - navigate(`/dashboard`) + + setCurrentSearch(formData) + } const searchForm = ( @@ -26,7 +29,7 @@ function Search({reservations}){