From 117ce5c4287c92e70a97eba11e173078c7c0c4ce Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Thu, 26 Oct 2023 00:36:28 +0530 Subject: [PATCH 01/35] Updated common module. --- orders/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/orders/package-lock.json b/orders/package-lock.json index 7ef1b4f..0f6c764 100644 --- a/orders/package-lock.json +++ b/orders/package-lock.json @@ -1368,9 +1368,9 @@ "dev": true }, "node_modules/@bookmyseat/common": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@bookmyseat/common/-/common-1.0.11.tgz", - "integrity": "sha512-1DI2vS8fTTnsvsl5N1IfMvGdVJs5WGEVNCTuyzISaf3B1UoE/qLHKrvCrallawXk4bTOLyr6MTo1DcWyS0xYfQ==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@bookmyseat/common/-/common-1.0.12.tgz", + "integrity": "sha512-HuKJrOIAQagz/ax8ZeV5og7ms8qhTUH5jXVW9B29e7h3izP91DUSmh9KBrxNQpTyI93RUgh6DhZ31InuIREViw==", "dependencies": { "@types/cookie-session": "^2.0.45", "@types/express": "^4.17.18", From 146fd8ef7a194e840af47bdb909801546d837f42 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Thu, 26 Oct 2023 00:37:49 +0530 Subject: [PATCH 02/35] Updated common module. --- tickets/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tickets/package-lock.json b/tickets/package-lock.json index 2bf402a..400690f 100644 --- a/tickets/package-lock.json +++ b/tickets/package-lock.json @@ -1368,9 +1368,9 @@ "dev": true }, "node_modules/@bookmyseat/common": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@bookmyseat/common/-/common-1.0.10.tgz", - "integrity": "sha512-+uQeZIU6BcJ5YDOCiWoVY2xB2Qc0oa3EZgHRSZt9guUHq0oSE7nKA3OX/iE+R9vee7ffOvQUWWjNfSTuRTwYlA==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@bookmyseat/common/-/common-1.0.12.tgz", + "integrity": "sha512-HuKJrOIAQagz/ax8ZeV5og7ms8qhTUH5jXVW9B29e7h3izP91DUSmh9KBrxNQpTyI93RUgh6DhZ31InuIREViw==", "dependencies": { "@types/cookie-session": "^2.0.45", "@types/express": "^4.17.18", From 2bc0764fcbef3daa16e28a5facd9f0746664ce43 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Thu, 26 Oct 2023 13:58:29 +0530 Subject: [PATCH 03/35] Created a payment created listener. --- .../listeners/payment-created-listener.ts | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 orders/src/events/listeners/payment-created-listener.ts diff --git a/orders/src/events/listeners/payment-created-listener.ts b/orders/src/events/listeners/payment-created-listener.ts new file mode 100644 index 0000000..76ff3ae --- /dev/null +++ b/orders/src/events/listeners/payment-created-listener.ts @@ -0,0 +1,39 @@ +import { Message } from "node-nats-streaming"; +import { + Listener, + EventSubjects, + PaymentCreatedEvent, + NotFoundError, + OrderStatus, +} from "@bookmyseat/common"; + +import { queueGroupName } from "../order-service-queue-group-name"; +import { Order } from "../../models/order"; + +export class PaymentCreatedListener extends Listener { + readonly subject = EventSubjects.PaymentCreated; + + queueGroupName = queueGroupName; + + async onMessage(data: PaymentCreatedEvent["data"], msg: Message) { + try { + // Destructure the ticket id, title, and price from data argument. + const { id, version, orderId, stripeId } = data; + + const order = await Order.findById(data.orderId); + + if (!order) { + throw new NotFoundError(); + } + + order.set({ status: OrderStatus.Complete }); + + await order.save(); + + // Acknowledge the Payment Created event to NATS server. + msg.ack(); + } catch (error) { + console.error("Error processing PaymentCreatedEvent", error); + } + } +} From e54a178773d7b5341d58b15df982509ea0bfb389 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Thu, 26 Oct 2023 13:59:20 +0530 Subject: [PATCH 04/35] Configured payment created listener in index file. --- orders/src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/orders/src/index.ts b/orders/src/index.ts index 3aaf385..dc9303d 100644 --- a/orders/src/index.ts +++ b/orders/src/index.ts @@ -7,6 +7,7 @@ import { natsClient } from "./nats-client"; import { TicketCreatedListener } from "./events/listeners/ticket-created-listener"; import { TicketUpdatedListener } from "./events/listeners/ticket-updated-listener"; import { OrderExpirationListener } from "./events/listeners/expiration-complete-listener"; +import { PaymentCreatedListener } from "./events/listeners/payment-created-listener"; const startServer = async () => { // Server Configuration @@ -84,6 +85,7 @@ const startServer = async () => { new TicketCreatedListener(natsClient.client).listen(); new TicketUpdatedListener(natsClient.client).listen(); new OrderExpirationListener(natsClient.client).listen(); + new PaymentCreatedListener(natsClient.client).listen(); } catch (err) { console.error( `Error Connecting ${SERVICE_NAME} Service to NATS CLUSTER: ${NATS_CLUSTER_ID}:`, From 7776dff40244532ec420571cff5ed38b2e0d9df7 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Thu, 26 Oct 2023 14:05:17 +0530 Subject: [PATCH 05/35] Configured Event Expired Listener to prevent cancellation of completed order and to ack message. --- orders/src/events/listeners/expiration-complete-listener.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/orders/src/events/listeners/expiration-complete-listener.ts b/orders/src/events/listeners/expiration-complete-listener.ts index d1e6ab8..09e48da 100644 --- a/orders/src/events/listeners/expiration-complete-listener.ts +++ b/orders/src/events/listeners/expiration-complete-listener.ts @@ -25,6 +25,11 @@ export class OrderExpirationListener extends Listener { throw new Error("Order not found !!!"); } + // If the order is already paid and marked complete, return early and acknowledge the event to NATS. + if (order.status === OrderStatus.Complete) { + return msg.ack(); + } + order.set({ status: OrderStatus.Cancelled }); await order.save(); From 308f92b971768d16ea4d6294a06a8dc29f026487 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 12:40:21 +0530 Subject: [PATCH 06/35] Added a additional props to pass down current user to all child component - so that child component can avoid making seperate network call for current user fetching. --- client/pages/_app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/pages/_app.js b/client/pages/_app.js index 187ad3d..7eb87b5 100644 --- a/client/pages/_app.js +++ b/client/pages/_app.js @@ -7,7 +7,7 @@ const AppComponent = ({ Component, pageProps, currentUser }) => { return (
- +
); }; From 8ee9d2262e92cea96e8d7f8c791357f6313aebc2 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 12:41:02 +0530 Subject: [PATCH 07/35] Modified to remove fetching current user. --- client/pages/index.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/client/pages/index.js b/client/pages/index.js index 6163abf..1db6e52 100644 --- a/client/pages/index.js +++ b/client/pages/index.js @@ -1,11 +1,9 @@ -import buildClient from "../api/build-client"; - const IndexPage = ({ currentUser }) => { if (!currentUser) { return ( <>

Landing Page

-
+
Signed Out
); @@ -21,14 +19,7 @@ const IndexPage = ({ currentUser }) => { }; IndexPage.getInitialProps = async (context) => { - try { - const client = buildClient(context); - const response = await client.get("/api/users/currentuser"); - return response.data; - } catch (err) { - console.error("Error in making request to get current user:", err.message); - return { currentUser: null }; - } + return {}; }; export default IndexPage; From 57f8af3702071c3cf04f9708cec95b1a5ff6e061 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 12:47:55 +0530 Subject: [PATCH 08/35] Added two new arguments to child components getInitial props function to pass axios client and currentUser. --- client/pages/_app.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/pages/_app.js b/client/pages/_app.js index 7eb87b5..69d040c 100644 --- a/client/pages/_app.js +++ b/client/pages/_app.js @@ -20,7 +20,11 @@ AppComponent.getInitialProps = async (appContext) => { // If the child component has getInitialProps method, then execute it manually from here. let pageProps = {}; if (appContext.Component.getInitialProps) { - pageProps = await appContext.Component.getInitialProps(appContext.ctx); + pageProps = await appContext.Component.getInitialProps( + appContext.ctx, + client, + data.currentUser + ); } return { pageProps, currentUser: response.data.currentUser }; From 15a7fead9b2b4706e7e7896006d9ac3ea6308e26 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 12:48:44 +0530 Subject: [PATCH 09/35] Modified to receive client and current user. --- client/pages/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/pages/index.js b/client/pages/index.js index 1db6e52..ab924c5 100644 --- a/client/pages/index.js +++ b/client/pages/index.js @@ -18,7 +18,7 @@ const IndexPage = ({ currentUser }) => { ); }; -IndexPage.getInitialProps = async (context) => { +IndexPage.getInitialProps = async (context, client, currentUser) => { return {}; }; From aadad8764efc4dd38039c9c04185225b19d7c7d8 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 14:57:08 +0530 Subject: [PATCH 10/35] Created a container div to align the component contents. --- client/pages/_app.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/pages/_app.js b/client/pages/_app.js index 69d040c..ad0dd0c 100644 --- a/client/pages/_app.js +++ b/client/pages/_app.js @@ -7,7 +7,9 @@ const AppComponent = ({ Component, pageProps, currentUser }) => { return (
- +
+ +
); }; From 65666591c61c38888674384f9f0b9a0104b4806e Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 15:16:12 +0530 Subject: [PATCH 11/35] Added a Ticket Creation Form. --- client/pages/tickets/new.js | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 client/pages/tickets/new.js diff --git a/client/pages/tickets/new.js b/client/pages/tickets/new.js new file mode 100644 index 0000000..c95517b --- /dev/null +++ b/client/pages/tickets/new.js @@ -0,0 +1,46 @@ +import { useState } from "react"; + +const NewTicket = () => { + const [title, setTitle] = useState(""); + const [price, setPrice] = useState(""); + + const roundOff = () => { + const roundedPrice = parseFloat(price); + + if (isNaN(roundedPrice)) { + // If price is not a number + return; + } + + setPrice(roundedPrice.toFixed(2)); + }; + return ( +
+

Create A Ticket

+
+
+ + setTitle(e.target.value)} + /> +
+
+ + setPrice(e.target.value)} + /> +
+ +
+
+ ); +}; + +export default NewTicket; From 6d2d2ed717ec3795cf69b5036c24692f825544c4 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 15:41:30 +0530 Subject: [PATCH 12/35] Added api call for form submission. --- client/pages/tickets/new.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/client/pages/tickets/new.js b/client/pages/tickets/new.js index c95517b..97853ae 100644 --- a/client/pages/tickets/new.js +++ b/client/pages/tickets/new.js @@ -1,8 +1,30 @@ import { useState } from "react"; +import useRequest from "../../hooks/use-request"; const NewTicket = () => { const [title, setTitle] = useState(""); const [price, setPrice] = useState(""); + const [makeRequest, errors] = useRequest({ + url: "/api/tickets", + method: "post", + body: { + title: title, + price: price, + }, + onSuccess: (ticket) => { + console.log(ticket); + }, + }); + + const handleSubmit = (event) => { + event.preventDefault(); + + if(!title || !price){ + return; + } + + makeRequest(); + }; const roundOff = () => { const roundedPrice = parseFloat(price); @@ -17,7 +39,7 @@ const NewTicket = () => { return (

Create A Ticket

-
+
{ onChange={(e) => setPrice(e.target.value)} />
+ {errors}
From d19b4a9df369f67311db7e98ddef0f35b71d38c2 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 16:08:59 +0530 Subject: [PATCH 13/35] Adder re-routing after ticket creation. --- client/pages/tickets/new.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/pages/tickets/new.js b/client/pages/tickets/new.js index 97853ae..1a2a197 100644 --- a/client/pages/tickets/new.js +++ b/client/pages/tickets/new.js @@ -1,4 +1,5 @@ import { useState } from "react"; +import Router from "next/router"; import useRequest from "../../hooks/use-request"; const NewTicket = () => { @@ -11,15 +12,15 @@ const NewTicket = () => { title: title, price: price, }, - onSuccess: (ticket) => { - console.log(ticket); + onSuccess: () => { + Router.push("/"); }, }); const handleSubmit = (event) => { event.preventDefault(); - if(!title || !price){ + if (!title || !price) { return; } From 796aea5dc976c3f83d465a4d14e8509effcf0f23 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 16:47:46 +0530 Subject: [PATCH 14/35] Fixed a reassignment bug. --- client/pages/_app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/pages/_app.js b/client/pages/_app.js index ad0dd0c..c7c8c7c 100644 --- a/client/pages/_app.js +++ b/client/pages/_app.js @@ -25,7 +25,7 @@ AppComponent.getInitialProps = async (appContext) => { pageProps = await appContext.Component.getInitialProps( appContext.ctx, client, - data.currentUser + response.data.currentUser ); } From 61e76fc119a2918f6637508a85ff989f3d3b2d8f Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 17:07:06 +0530 Subject: [PATCH 15/35] Configured Landing page to display created tickets. --- client/pages/index.js | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/client/pages/index.js b/client/pages/index.js index ab924c5..c77a92a 100644 --- a/client/pages/index.js +++ b/client/pages/index.js @@ -1,4 +1,4 @@ -const IndexPage = ({ currentUser }) => { +const IndexPage = ({ currentUser, tickets }) => { if (!currentUser) { return ( <> @@ -9,17 +9,40 @@ const IndexPage = ({ currentUser }) => { ); } + let ticketList; + if (currentUser) { + ticketList = tickets.map((ticket) => { + return ( + + {ticket.title} + {ticket.price} + + ); + }); + } + return ( <> -

Landing Page

-
Welcome {currentUser.email}
+ +

Tickets

+ + + + + + + + + {currentUser && ticketList} +
TitlePrice
); }; IndexPage.getInitialProps = async (context, client, currentUser) => { - return {}; + const { data } = await client.get("/api/tickets"); + return { tickets: data }; }; export default IndexPage; From 1513bd8a1652528fead91f06b127aca9105183c9 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 17:20:28 +0530 Subject: [PATCH 16/35] Added a single ticket details page. --- client/pages/tickets/[ticketId].js | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 client/pages/tickets/[ticketId].js diff --git a/client/pages/tickets/[ticketId].js b/client/pages/tickets/[ticketId].js new file mode 100644 index 0000000..3811b52 --- /dev/null +++ b/client/pages/tickets/[ticketId].js @@ -0,0 +1,5 @@ +const TicketShow = () => { + return
TicketShow
; +}; + +export default TicketShow; From 0705ed72880dd28690983d01126127bbb844af3c Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 17:21:06 +0530 Subject: [PATCH 17/35] Modified to provide wild-card route to show single ticket information. --- client/pages/index.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/pages/index.js b/client/pages/index.js index c77a92a..2401514 100644 --- a/client/pages/index.js +++ b/client/pages/index.js @@ -1,3 +1,5 @@ +import Link from 'next/link'; + const IndexPage = ({ currentUser, tickets }) => { if (!currentUser) { return ( @@ -16,6 +18,11 @@ const IndexPage = ({ currentUser, tickets }) => { {ticket.title} {ticket.price} + + + View + + ); }); @@ -31,6 +38,7 @@ const IndexPage = ({ currentUser, tickets }) => { Title Price + Action From 6e8c1685df6043435cdb6322db323050fb28c92d Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 18:30:08 +0530 Subject: [PATCH 18/35] Added purchase button. --- client/pages/tickets/[ticketId].js | 38 ++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/client/pages/tickets/[ticketId].js b/client/pages/tickets/[ticketId].js index 3811b52..d04e192 100644 --- a/client/pages/tickets/[ticketId].js +++ b/client/pages/tickets/[ticketId].js @@ -1,5 +1,39 @@ -const TicketShow = () => { - return
TicketShow
; +import useRequest from "../../hooks/use-request"; + +const TicketShow = ({ ticket }) => { + const [makeRequest, errors] = useRequest({ + url: "/api/orders", + method: "post", + body: { + ticketId: ticket.id, + }, + onSuccess: (data) => { + console.log(data); + }, + }); + + const handleClick = async () => { + makeRequest(); + }; + + return ( +
+

{ticket.title}

+

Price: {ticket.price} INR

+ {errors} + +
+ ); +}; + +TicketShow.getInitialProps = async (context, client) => { + const { ticketId } = context.query; + + const { data } = await client.get(`/api/tickets/${ticketId}`); + + return { ticket: data }; }; export default TicketShow; From 44bea0c2d9547c0e979a5d9f953a6160393fe948 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 21:16:32 +0530 Subject: [PATCH 19/35] Added a single order page. --- client/pages/orders/[orderId].js | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 client/pages/orders/[orderId].js diff --git a/client/pages/orders/[orderId].js b/client/pages/orders/[orderId].js new file mode 100644 index 0000000..624b5da --- /dev/null +++ b/client/pages/orders/[orderId].js @@ -0,0 +1,5 @@ +const OrderShow = () => { + return
OrderShow
; +}; + +export default OrderShow; From 0ca3376f7b7c6166612fb0366b3e15d1a3c44f54 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 21:17:07 +0530 Subject: [PATCH 20/35] Configured routing to orders page from tickets page. --- client/pages/tickets/[ticketId].js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/pages/tickets/[ticketId].js b/client/pages/tickets/[ticketId].js index d04e192..212f31f 100644 --- a/client/pages/tickets/[ticketId].js +++ b/client/pages/tickets/[ticketId].js @@ -1,3 +1,4 @@ +import Router from "next/router"; import useRequest from "../../hooks/use-request"; const TicketShow = ({ ticket }) => { @@ -7,8 +8,8 @@ const TicketShow = ({ ticket }) => { body: { ticketId: ticket.id, }, - onSuccess: (data) => { - console.log(data); + onSuccess: (orderData) => { + Router.push("/orders/[orderId]", `/orders/${orderData.id}`); }, }); From 9a61a40207a4fa45a9d29e593e8cb752ebe5b5b6 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 21:47:56 +0530 Subject: [PATCH 21/35] Added order expiration Timer. --- client/pages/orders/[orderId].js | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/client/pages/orders/[orderId].js b/client/pages/orders/[orderId].js index 624b5da..ddb3703 100644 --- a/client/pages/orders/[orderId].js +++ b/client/pages/orders/[orderId].js @@ -1,5 +1,32 @@ -const OrderShow = () => { - return
OrderShow
; +import { useEffect, useState } from "react"; + +const OrderShow = ({ order }) => { + const [timeLeft, setTimeLeft] = useState(""); + + useEffect(() => { + const findTimeLeft = () => { + const milliSecondsLeft = new Date(order.expiresAt) - new Date(); + const secondsLeft = Math.round(milliSecondsLeft / 1000); + + setTimeLeft(secondsLeft); + }; + + findTimeLeft(); + const timer = setInterval(findTimeLeft, 1000); + + return () => { + clearInterval(timer); + }; + }, [order]); + + return
Time left to complete payment: {timeLeft} seconds.
; +}; + +OrderShow.getInitialProps = async (context, client) => { + const { orderId } = context.query; + const { data } = await client.get(`/api/orders/${orderId}`); + + return { order: data }; }; export default OrderShow; From 9a9555368b5a2500ce8cd4fe89c53251fa91f094 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 21:56:02 +0530 Subject: [PATCH 22/35] Added Timer expiration logic. --- client/pages/orders/[orderId].js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/client/pages/orders/[orderId].js b/client/pages/orders/[orderId].js index ddb3703..e865cc7 100644 --- a/client/pages/orders/[orderId].js +++ b/client/pages/orders/[orderId].js @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; const OrderShow = ({ order }) => { - const [timeLeft, setTimeLeft] = useState(""); + const [timeLeft, setTimeLeft] = useState(0); useEffect(() => { const findTimeLeft = () => { @@ -19,6 +19,14 @@ const OrderShow = ({ order }) => { }; }, [order]); + if (timeLeft < 0) { + return ( +
+

Order Expired !!!

+
+ ); + } + return
Time left to complete payment: {timeLeft} seconds.
; }; From 940757c08ed43fb4fb03a43d03bf8853c6cde0ad Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 22:58:50 +0530 Subject: [PATCH 23/35] Installed react-stripe-checkout in clients service. --- client/package-lock.json | 8 +++++++- client/package.json | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 950faf0..0a17a58 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -13,7 +13,8 @@ "bootstrap": "^5.3.2", "next": "^13.5.4", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-stripe-checkout": "^2.6.3" } }, "node_modules/@next/env": { @@ -460,6 +461,11 @@ "react": "^18.2.0" } }, + "node_modules/react-stripe-checkout": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/react-stripe-checkout/-/react-stripe-checkout-2.6.3.tgz", + "integrity": "sha512-lnsCaAdlmwPGGMbQoI8FXtQUgEm+ktzPZ/ipAw4j0HYf80kef7CivGx6QitmgEn99/aa5hI/dmVXwfVZW/Mzfg==" + }, "node_modules/scheduler": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", diff --git a/client/package.json b/client/package.json index af83111..11b3d1d 100644 --- a/client/package.json +++ b/client/package.json @@ -14,6 +14,7 @@ "bootstrap": "^5.3.2", "next": "^13.5.4", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-stripe-checkout": "^2.6.3" } } From 7d5372b8a0a8eb928716d8b665fd82477323e419 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 23:20:48 +0530 Subject: [PATCH 24/35] Installed prop-types for Stripe module support. --- client/package-lock.json | 24 ++++++++++++++++++++++++ client/package.json | 1 + 2 files changed, 25 insertions(+) diff --git a/client/package-lock.json b/client/package-lock.json index 0a17a58..d8288fc 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,6 +12,7 @@ "axios": "^1.5.1", "bootstrap": "^5.3.2", "next": "^13.5.4", + "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-stripe-checkout": "^2.6.3" @@ -401,6 +402,14 @@ } } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -433,6 +442,16 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -461,6 +480,11 @@ "react": "^18.2.0" } }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/react-stripe-checkout": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/react-stripe-checkout/-/react-stripe-checkout-2.6.3.tgz", diff --git a/client/package.json b/client/package.json index 11b3d1d..4ff3d98 100644 --- a/client/package.json +++ b/client/package.json @@ -13,6 +13,7 @@ "axios": "^1.5.1", "bootstrap": "^5.3.2", "next": "^13.5.4", + "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-stripe-checkout": "^2.6.3" From 23a902c732272a673b668782cd3c9ca1c0c24bbb Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 23:21:48 +0530 Subject: [PATCH 25/35] Configured card checkout with Stripe module. --- client/pages/orders/[orderId].js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/client/pages/orders/[orderId].js b/client/pages/orders/[orderId].js index e865cc7..3cf46b1 100644 --- a/client/pages/orders/[orderId].js +++ b/client/pages/orders/[orderId].js @@ -1,6 +1,7 @@ import { useEffect, useState } from "react"; +import StripeCheckout from "react-stripe-checkout"; -const OrderShow = ({ order }) => { +const OrderShow = ({ order, currentUser }) => { const [timeLeft, setTimeLeft] = useState(0); useEffect(() => { @@ -27,7 +28,19 @@ const OrderShow = ({ order }) => { ); } - return
Time left to complete payment: {timeLeft} seconds.
; + return ( +
+ Time left to complete payment: {timeLeft} seconds. + { + console.log(token); + }} + stripeKey="pk_test_51O53zRSJtuYafghXhYNZzaJqYAh6afqRduQ3UAMs6Wm4vkv30ayq09gBPgU3jYkQPXrofQa9aRbIlb4uuCp3FC6O000J86xaKc" + amount={order.ticket.price * 100} + email={currentUser.email} + /> +
+ ); }; OrderShow.getInitialProps = async (context, client) => { From 931a5d024380b051ce4e42c73986e8bc7b6aef67 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 23:47:08 +0530 Subject: [PATCH 26/35] Modified useRequest hook to send additional data into request body if required. --- client/hooks/use-request.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/hooks/use-request.js b/client/hooks/use-request.js index 8d528d4..ed28ccb 100644 --- a/client/hooks/use-request.js +++ b/client/hooks/use-request.js @@ -4,11 +4,11 @@ import axios from "axios"; export default ({ url, method, body, onSuccess }) => { const [errors, setErrors] = useState(null); - const makeRequest = async () => { + const makeRequest = async (props={}) => { try { setErrors(null); // Setting error to null initially to prevent errors from being displayed always. - const response = await axios[method](url, body); + const response = await axios[method](url, {...body, ...props}); // If the call back exist, then return the call back with response data. if (onSuccess) { From 04c6566f3296c55a0941e4728c7cc2755cf3dec2 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Fri, 27 Oct 2023 23:58:20 +0530 Subject: [PATCH 27/35] Configured to make api call to complete payment with received token for payment request. --- client/pages/orders/[orderId].js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/client/pages/orders/[orderId].js b/client/pages/orders/[orderId].js index 3cf46b1..347ff66 100644 --- a/client/pages/orders/[orderId].js +++ b/client/pages/orders/[orderId].js @@ -1,8 +1,20 @@ import { useEffect, useState } from "react"; +import Router from "next/router"; import StripeCheckout from "react-stripe-checkout"; +import useRequest from "../../hooks/use-request"; const OrderShow = ({ order, currentUser }) => { const [timeLeft, setTimeLeft] = useState(0); + const [makeRequest, errors] = useRequest({ + url: "/api/payments", + method: "post", + body: { + orderId: order.id, + }, + onSuccess: (payment) => { + Router.push("/"); + }, + }); useEffect(() => { const findTimeLeft = () => { @@ -33,12 +45,13 @@ const OrderShow = ({ order, currentUser }) => { Time left to complete payment: {timeLeft} seconds. { - console.log(token); + makeRequest({ token: token.id }); }} stripeKey="pk_test_51O53zRSJtuYafghXhYNZzaJqYAh6afqRduQ3UAMs6Wm4vkv30ayq09gBPgU3jYkQPXrofQa9aRbIlb4uuCp3FC6O000J86xaKc" amount={order.ticket.price * 100} email={currentUser.email} /> + {errors} ); }; From c004a940e03f90b3d4b4edb34692d0e98b5b07cb Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Sat, 28 Oct 2023 00:17:18 +0530 Subject: [PATCH 28/35] Modified API response to return tickets that are available to book (unreserved Tickets). --- tickets/src/routes/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tickets/src/routes/index.ts b/tickets/src/routes/index.ts index 600d265..525b07b 100644 --- a/tickets/src/routes/index.ts +++ b/tickets/src/routes/index.ts @@ -4,7 +4,9 @@ import { Ticket } from "../models/ticket"; const router = express.Router(); router.get("/api/tickets", async (req: Request, res: Response) => { - const tickets = await Ticket.find({}); + + // Fetch all Tickets that are available to make a booking (ie, which are not reserved by any order) + const tickets = await Ticket.find({orderId: undefined}); res.send(tickets); }); From 91cbbee84550d50df10df35605daaaf1e6117d2b Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Sat, 28 Oct 2023 00:38:48 +0530 Subject: [PATCH 29/35] Added two new options in the Header. --- client/components/header.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/components/header.js b/client/components/header.js index b9dac96..77471a3 100644 --- a/client/components/header.js +++ b/client/components/header.js @@ -2,9 +2,11 @@ import Link from "next/link"; export default ({ currentUser }) => { const Links = [ - !currentUser && { label: "Sign Up", href: "auth/signup" }, - !currentUser && { label: "Sign In", href: "auth/signin" }, - currentUser && { label: "Sign Out", href: "auth/signout" }, + !currentUser && { label: "Sign Up", href: "/auth/signup" }, + !currentUser && { label: "Sign In", href: "/auth/signin" }, + currentUser && { label: "Sell Tickets", href: "/tickets/new" }, + currentUser && { label: "My Orders", href: "/orders" }, + currentUser && { label: "Sign Out", href: "/auth/signout" }, ] .filter((validLinks) => validLinks) .map(({ label, href }) => { From c56758fda027fafd8b5d545f46926e067158ef32 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Sat, 28 Oct 2023 01:01:03 +0530 Subject: [PATCH 30/35] Added orders listing page to list order history of user. --- client/pages/orders/index.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 client/pages/orders/index.js diff --git a/client/pages/orders/index.js b/client/pages/orders/index.js new file mode 100644 index 0000000..22f886b --- /dev/null +++ b/client/pages/orders/index.js @@ -0,0 +1,23 @@ +const OrderIndex = ({ orders }) => { + return ( + <> +
    + {orders.map((order) => { + return ( +
  • + {order.ticket.title} - {order.status} +
  • + ); + })} +
+ + ); +}; + +OrderIndex.getInitialProps = async (context, client) => { + const response = await client.get("/api/orders"); + + return { orders: response.data }; +}; + +export default OrderIndex; From 1cfecd5d0e4abc7178e7638731e26e32466d7175 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Sat, 28 Oct 2023 01:02:15 +0530 Subject: [PATCH 31/35] Modified the redirection - redirection configured to show orders page after payment success. --- client/pages/orders/[orderId].js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/pages/orders/[orderId].js b/client/pages/orders/[orderId].js index 347ff66..de0588a 100644 --- a/client/pages/orders/[orderId].js +++ b/client/pages/orders/[orderId].js @@ -12,7 +12,7 @@ const OrderShow = ({ order, currentUser }) => { orderId: order.id, }, onSuccess: (payment) => { - Router.push("/"); + Router.push("/orders"); }, }); From 9f30b4ce2488fac4ef9cd221b6d6e6ea4d3a5d80 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <87621111+alwinsimon@users.noreply.github.com> Date: Sat, 28 Oct 2023 18:47:10 +0530 Subject: [PATCH 32/35] Create CI - Tests - Auth Service.yml --- .github/workflows/CI - Tests - Auth Service.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/workflows/CI - Tests - Auth Service.yml diff --git a/.github/workflows/CI - Tests - Auth Service.yml b/.github/workflows/CI - Tests - Auth Service.yml new file mode 100644 index 0000000..c98b5ea --- /dev/null +++ b/.github/workflows/CI - Tests - Auth Service.yml @@ -0,0 +1,3 @@ +# ===================================================== Main Branch CI Configuration ===================================================== + +name: CI - Tests - Auth Service From da4fc7b59620a929cd2d2d4db82d062b14f528b8 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Sat, 28 Oct 2023 18:58:04 +0530 Subject: [PATCH 33/35] Configured CI Workflow for auth service tests. --- .github/workflows/CI - Tests - Auth Service.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI - Tests - Auth Service.yml b/.github/workflows/CI - Tests - Auth Service.yml index c98b5ea..c33ab5f 100644 --- a/.github/workflows/CI - Tests - Auth Service.yml +++ b/.github/workflows/CI - Tests - Auth Service.yml @@ -1,3 +1,13 @@ -# ===================================================== Main Branch CI Configuration ===================================================== +# ========================================= Main Branch ::: CI - Tests - Auth Service ========================================= name: CI - Tests - Auth Service + +on: pull_request + +jobs: + Production-Branch-Pre-Integration-Tests: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - run: cd auth && npm install && npm run test:ci From 9f78a3a3a1fe8c3a0d37fe1fae6f1b87b264e206 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Sat, 28 Oct 2023 19:10:55 +0530 Subject: [PATCH 34/35] Added Test Script for CI Testing. --- auth/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/auth/package.json b/auth/package.json index 604068e..b1cfa63 100644 --- a/auth/package.json +++ b/auth/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "start": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts", - "test": "jest --watchAll --no-cache" + "test": "jest --watchAll --no-cache", + "test:ci": "jest" }, "jest": { "preset": "ts-jest", From 105be2be8ee9abda2f4773094dbe8e8e189fe4f7 Mon Sep 17 00:00:00 2001 From: "Dr. Alwin Simon" <003alwin@gmail.com> Date: Sat, 28 Oct 2023 19:24:04 +0530 Subject: [PATCH 35/35] Added script for CI Testing. --- orders/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/orders/package.json b/orders/package.json index 010e589..0860052 100644 --- a/orders/package.json +++ b/orders/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "start": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts", - "test": "jest --watchAll --no-cache" + "test": "jest --watchAll --no-cache", + "test:ci": "jest" }, "jest": { "preset": "ts-jest",