From 630919adde3779baa7d6b60ad3a628882c042b2a Mon Sep 17 00:00:00 2001 From: Filip Borum Poulsen Date: Sun, 16 Apr 2023 18:49:46 +0200 Subject: [PATCH] Added trainer and center routes --- server/src/interfaces/center.ts | 8 ++ server/src/interfaces/trainer.ts | 8 ++ server/src/routes/center.ts | 102 ++++++++++++++++++++++ server/src/routes/index.ts | 4 + server/src/routes/trainer.ts | 140 +++++++++++++++++++++++++++++++ 5 files changed, 262 insertions(+) create mode 100644 server/src/interfaces/center.ts create mode 100644 server/src/interfaces/trainer.ts create mode 100644 server/src/routes/center.ts create mode 100644 server/src/routes/trainer.ts diff --git a/server/src/interfaces/center.ts b/server/src/interfaces/center.ts new file mode 100644 index 0000000..81c7e8d --- /dev/null +++ b/server/src/interfaces/center.ts @@ -0,0 +1,8 @@ +interface Center { + id: number + name: string + city: string + zip_code: number + address: string +} +export default Center; \ No newline at end of file diff --git a/server/src/interfaces/trainer.ts b/server/src/interfaces/trainer.ts new file mode 100644 index 0000000..d250dbb --- /dev/null +++ b/server/src/interfaces/trainer.ts @@ -0,0 +1,8 @@ +interface Trainer { + id: number + first_name: string + last_name: string + center_id: number + center_name: string +} +export default Trainer; \ No newline at end of file diff --git a/server/src/routes/center.ts b/server/src/routes/center.ts new file mode 100644 index 0000000..851cd49 --- /dev/null +++ b/server/src/routes/center.ts @@ -0,0 +1,102 @@ +import express, { Router, Request, Response } from "express"; +import Joi from "joi" + +import { client } from "../db"; +import { DatabaseError } from "pg"; +import Center from "../interfaces/center"; +import { AdminAuth, UserAuth } from "../middlewares/auth"; + +const router: Router = express.Router(); + +router.get("/center", async (req: Request, res: Response) => { + try { + const databaseResult = await client.query(` + SELECT id, name, city, zip_code, address FROM centers; + `); + + const centers: Center[] = databaseResult.rows; + + return res.status(200).send(centers); + } catch (error: DatabaseError | Error | any) { + console.error(error); + return res.sendStatus(500); + } +}) + +const centerSchema = Joi.object({ + name: Joi.string().required(), + city: Joi.string().required(), + zip_code: Joi.number().min(1000).max(9999).integer().positive().required(), + address: Joi.string().required() +}); + +router.post("/center", AdminAuth, async (req: Request, res: Response) => { + try { + const validation = centerSchema.validate(req.body, { abortEarly: false }); + if (validation.error !== undefined) { + return res.status(400).send(validation.error.details); + } + + const databaseResult = await client.query(` + INSERT INTO centers (name, city, zip_code, address) + VALUES ($1, $2, $3, $4) + RETURNING *; + `, [ + validation.value.name, + validation.value.city, + validation.value.zip_code, + validation.value.address + ]); + + const centers: Center[] = databaseResult.rows; + + return res.status(200).send(centers); + } catch (error: DatabaseError | Error | any) { + console.error(error); + return res.sendStatus(500); + } +}) + +router.put("/center/:id", AdminAuth, async (req: Request, res: Response) => { + try { + const lookupResult = await client.query(` + SELECT 1 FROM centers where id = $1; + `, [ + req.params.id + ]); + + if (lookupResult.rowCount < 1) { + return res.sendStatus(404); + } + + const validation = centerSchema.validate(req.body, { abortEarly: false }); + if (validation.error !== undefined) { + return res.status(400).send(validation.error.details); + } + + const databaseResult = await client.query(` + UPDATE centers SET + name = $1, + city = $2, + zip_code = $3, + address = $4 + WHERE id = $5 + RETURNING *; + `, [ + validation.value.name, + validation.value.city, + validation.value.zip_code, + validation.value.address, + req.params.id + ]); + + const centers: Center[] = databaseResult.rows; + + return res.status(200).send(centers); + } catch (error: DatabaseError | Error | any) { + console.error(error); + return res.sendStatus(500); + } +}) + +export default router; \ No newline at end of file diff --git a/server/src/routes/index.ts b/server/src/routes/index.ts index a8d9d67..2db7986 100644 --- a/server/src/routes/index.ts +++ b/server/src/routes/index.ts @@ -4,8 +4,12 @@ const router: Router = express.Router(); import login from "./login" import register from "./register" +import center from "./center"; +import trainer from "./trainer"; router.use(login); router.use(register); +router.use(center); +router.use(trainer); export default router; \ No newline at end of file diff --git a/server/src/routes/trainer.ts b/server/src/routes/trainer.ts new file mode 100644 index 0000000..2d9a87a --- /dev/null +++ b/server/src/routes/trainer.ts @@ -0,0 +1,140 @@ +import express, { Router, Request, Response } from "express"; +import Joi from "joi" + +import { client } from "../db"; +import { DatabaseError } from "pg"; +import Trainer from "../interfaces/trainer"; +import { AdminAuth, UserAuth } from "../middlewares/auth"; + +const router: Router = express.Router(); + +router.get("/trainer", async (req: Request, res: Response) => { + try { + const databaseResult = await client.query(` + SELECT trainers.id, first_name, last_name, center_id, centers.name as center_name FROM trainers + JOIN users ON trainers.user_id = users.id + JOIN centers on trainers.center_id = centers.id; + `); + + const trainers: Trainer[] = databaseResult.rows; + + return res.status(200).send(trainers); + } catch (error: DatabaseError | Error | any) { + console.error(error); + return res.sendStatus(500); + } +}) + +const createTrainerSchema = Joi.object({ + user_id: Joi.number().integer().positive().required(), + center_id: Joi.number().integer().positive().required(), + hourly_price: Joi.number().integer().positive().required() +}); + +router.post("/trainer", AdminAuth, async (req: Request, res: Response) => { + try { + const validation = createTrainerSchema.validate(req.body, { abortEarly: false }); + if (validation.error !== undefined) { + return res.status(400).send(validation.error.details); + } + + const databaseResult = await client.query(` + WITH inserted AS ( + INSERT INTO trainers (user_id, center_id, hourly_price) + VALUES ($1, $2, $3) + RETURNING * + ) + SELECT inserted.id, user_id, first_name, last_name, center_id, centers.name as center_name from inserted + JOIN users ON inserted.user_id = users.id + JOIN centers on inserted.center_id = centers.id; + `, [ + validation.value.user_id, + validation.value.center_id, + validation.value.hourly_price + ]); + + const trainers: Trainer[] = databaseResult.rows; + + return res.status(200).send(trainers); + } catch (error: DatabaseError | Error | any) { + if (error.constraint == "trainers_user_id_key") { + return res.status(400).send([{ + message: "\"user_id\" is already a trainer", + path: [ + "user_id" + ], + type: "user_id.unique" + }]); + } + if (error.constraint == "trainers_center_id_fkey") { + return res.status(400).send([{ + message: "\"center_id\" is not a valid center", + path: [ + "center_id" + ], + type: "center_id.not_found" + }]); + } + console.error(error); + return res.sendStatus(500); + } +}) + +const updateTrainerSchema = Joi.object({ + center_id: Joi.number().integer().positive().required(), + hourly_price: Joi.number().integer().positive().required() +}); + +router.put("/trainer/:id", AdminAuth, async (req: Request, res: Response) => { + try { + const lookupResult = await client.query(` + SELECT 1 FROM trainers where id = $1; + `, [ + req.params.id + ]); + + if (lookupResult.rowCount < 1) { + return res.sendStatus(404); + } + + const validation = updateTrainerSchema.validate(req.body, { abortEarly: false }); + if (validation.error !== undefined) { + return res.status(400).send(validation.error.details); + } + + const databaseResult = await client.query(` + WITH updated AS ( + UPDATE trainers SET + center_id = $1, + hourly_price = $2 + WHERE id = $3 + RETURNING * + ) + SELECT updated.id, user_id, first_name, last_name, center_id, centers.name as center_name from updated + JOIN users ON updated.user_id = users.id + JOIN centers on updated.center_id = centers.id; + `, [ + validation.value.center_id, + validation.value.hourly_price, + req.params.id + ]); + + const trainers: Trainer[] = databaseResult.rows; + + return res.status(200).send(trainers); + } catch (error: DatabaseError | Error | any) { + if (error.constraint == "trainers_center_id_fkey") { + return res.status(400).send([{ + message: "\"center_id\" is not a valid center", + path: [ + "center_id" + ], + type: "center_id.not_found" + }]); + } + console.error(error); + return res.sendStatus(500); + } +}) + +export default router; \ No newline at end of file