diff --git a/client/src/components/OrderPopup.vue b/client/src/components/OrderPopup.vue index 4aef0e7..13bd131 100644 --- a/client/src/components/OrderPopup.vue +++ b/client/src/components/OrderPopup.vue @@ -93,7 +93,7 @@ export default { \ No newline at end of file diff --git a/client/src/components/UserOrderPopup.vue b/client/src/components/UserOrderPopup.vue new file mode 100644 index 0000000..f9feb83 --- /dev/null +++ b/client/src/components/UserOrderPopup.vue @@ -0,0 +1,204 @@ + + + + + \ No newline at end of file diff --git a/client/src/interfaces/order.ts b/client/src/interfaces/order.ts new file mode 100644 index 0000000..2d7547f --- /dev/null +++ b/client/src/interfaces/order.ts @@ -0,0 +1,11 @@ +import type { Trainer } from "./trainer" + +export interface Order { + id: number + startDate: string + endDate: string + createdAt: string + status: string + price: number + trainer: Trainer +} \ No newline at end of file diff --git a/client/src/views/Home.vue b/client/src/views/Home.vue index 65f1952..3465dd2 100644 --- a/client/src/views/Home.vue +++ b/client/src/views/Home.vue @@ -38,8 +38,8 @@ padding: 50px; } -.dateSelector { - grid-area: 1 / 1 / 2 / 2; +.Home :deep(.dateSelector) { + grid-area: 1 / 1 / 4 / 2; } .centerSelector { diff --git a/client/src/views/user/UserOrdersView.vue b/client/src/views/user/UserOrdersView.vue index 8da791d..87b8b26 100644 --- a/client/src/views/user/UserOrdersView.vue +++ b/client/src/views/user/UserOrdersView.vue @@ -1,23 +1,140 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/server/src/environment.ts b/server/src/environment.ts index 09c88a4..5623fea 100644 --- a/server/src/environment.ts +++ b/server/src/environment.ts @@ -27,6 +27,10 @@ if (process.env.STRIPE_WEBHOOK_SECRET === undefined) { throw ("The environment variable 'STRIPE_WEBHOOK_SECRET' has not been set"); } +if (process.env.BASE_URL === undefined) { + throw ("The environment variable 'BASE_URL' has not been set"); +} + export const public_key: string = fs.readFileSync(process.env.PUBLIC_KEY_LOCATION, { encoding: "utf-8" }); export const private_key: string = fs.readFileSync(process.env.PRIVATE_KEY_LOCATION, { encoding: "utf-8" }); @@ -36,3 +40,6 @@ export const port: string = process.env.PORT; export const stripePrivateKey: string = process.env.STRIPE_SECRET_KEY; export const stripePublicKey: string = process.env.STRIPE_PUBLIC_KEY; export const stripeWebhookSecret: string = process.env.STRIPE_WEBHOOK_SECRET; + +export const baseURL: string = process.env.BASE_URL; + diff --git a/server/src/routes/createOrder.ts b/server/src/routes/createOrder.ts index 368f0bd..b774e1d 100644 --- a/server/src/routes/createOrder.ts +++ b/server/src/routes/createOrder.ts @@ -14,6 +14,7 @@ import { AuthedRequest } from "../interfaces/auth"; import Stripe from 'stripe'; import { stripe } from "../stripe"; import Trainer from "../interfaces/trainer"; +import { baseURL } from "../environment"; dayjs.extend(isoWeek) dayjs.extend(utc) @@ -174,8 +175,8 @@ router.post("/order", UserAuth, async (req: AuthedRequest, res: Response) => { ], expires_at: Math.floor(Date.now()/1000 + 60*31), mode: 'payment', - success_url: `http://localhost:5173/orders`, - cancel_url: `http://localhost:5173`, + success_url: `${baseURL}/user/orders`, + cancel_url: `${baseURL}`, customer_email: email }); diff --git a/server/src/routes/orderNewTime.ts b/server/src/routes/orderNewTime.ts index 336af5b..0b340ad 100644 --- a/server/src/routes/orderNewTime.ts +++ b/server/src/routes/orderNewTime.ts @@ -83,6 +83,11 @@ router.put("/order/:id", UserAuth, async (req: AuthedRequest, res: Response) => return res.status(400).send(validation.error.details); } + const dateValidation = Joi.date().min(Date.now()).validate(order.start_time) + if (dateValidation.error !== undefined) { + return res.status(400).send({ message: "Timeslot has already occurred" }); + } + const orderBody: OrderBody = validation.value; const startDate: dayjs.Dayjs = dayjs(orderBody.startDate).utcOffset(0); @@ -105,10 +110,15 @@ router.put("/order/:id", UserAuth, async (req: AuthedRequest, res: Response) => ) as weekly_timeslot_available, EXISTS( SELECT 1 FROM public.reserved_timeslots + JOIN orders ON reserved_timeslots.id = orders.timeslot_id WHERE ((start_time >= $5 AND start_time < $6) OR (end_time > $5 AND end_time <= $6)) AND trainer_id = $1 + AND ( + orders.order_status = 'Confirmed' + OR orders.order_status = 'Created' + ) ) as time_already_reserved; `, [ order.trainer_id, diff --git a/server/src/routes/orderNewTimeProposal.ts b/server/src/routes/orderNewTimeProposal.ts index 4450e78..9a1ed76 100644 --- a/server/src/routes/orderNewTimeProposal.ts +++ b/server/src/routes/orderNewTimeProposal.ts @@ -61,11 +61,6 @@ router.get("/order/:id/newtimeslots", UserAuth, async (req: AuthedRequest, res: const order: OrderLookup = lookupResult.rows[0]; - const dateValiadtion = Joi.date().min(Date.now()).validate(order.start_time) - if (dateValiadtion.error !== undefined) { - return res.status(400).send({ message: "Timeslot has already occurred" }); - } - const filterValidation = newTimeslotPropsalFilterSchema.validate(req.query, { abortEarly: false, stripUnknown: true }); if (filterValidation.error !== undefined) { return res.status(400).send(filterValidation.error.details); @@ -157,6 +152,9 @@ router.get("/order/:id/newtimeslots", UserAuth, async (req: AuthedRequest, res: } } + if (startTime.isBefore(dayjs())) + continue weeklyTimeslots; + const proposedDuration: number = startTime.diff(endTime); if (proposedDuration !== originalDuration) continue; diff --git a/server/src/routes/timeslot.ts b/server/src/routes/timeslot.ts index 12caf78..1ada0ce 100644 --- a/server/src/routes/timeslot.ts +++ b/server/src/routes/timeslot.ts @@ -182,6 +182,10 @@ router.get("/timeslot", async (req: Request, res: Response) => { } const startTime = dayjs(`${day.toISOString().split("T")[0]}T${timeslot.start_time}`); const endTime = dayjs(`${day.toISOString().split("T")[0]}T${timeslot.end_time}`); + + if (startTime.isBefore(dayjs())) + continue timeslots; + for (const reservedTimeslot of reservedTimeslots) { const reservedTimeStart = dayjs(reservedTimeslot.start_time); const reservedTimeEnd = dayjs(reservedTimeslot.end_time);