From 47c2652c13a222c9878927eb591968b8a40ee530 Mon Sep 17 00:00:00 2001 From: Jeffery <61447509+jeffplays2005@users.noreply.github.com> Date: Wed, 24 Jul 2024 09:17:31 +1200 Subject: [PATCH 01/19] 671-readme-for-server (#675) I hope I didn't misunderstand this ticket... Created a README.md file with the Backend-Architecture part of the wiki. --- server/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 server/README.md diff --git a/server/README.md b/server/README.md new file mode 100644 index 000000000..6a2799a6c --- /dev/null +++ b/server/README.md @@ -0,0 +1,3 @@ +# Backend architecture information + +https://github.com/UoaWDCC/uasc-web/wiki/Backend-Architecture From 4541bc0f16461d59df48f62615dc5d57f6ef3081 Mon Sep 17 00:00:00 2001 From: Jeffery <61447509+jeffplays2005@users.noreply.github.com> Date: Wed, 24 Jul 2024 10:43:32 +1200 Subject: [PATCH 02/19] 669 Delete docs folder (#679) Removed --- docs/ARCHITECTURE.md | 105 ------------------------------------------- 1 file changed, 105 deletions(-) delete mode 100644 docs/ARCHITECTURE.md diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md deleted file mode 100644 index ea5e3a66f..000000000 --- a/docs/ARCHITECTURE.md +++ /dev/null @@ -1,105 +0,0 @@ -# Firestore Architecture - -We use [Firestore](https://firebase.google.com/docs/firestore) to manage the database infrastructure. Firestore index rules are currently not set up. - -## `users` collection - -After a user signs up through the web app, extra information will be populated through this collection on top of the Firebase [User](https://firebase.google.com/docs/auth/users) object. - -| **Field** | **Type** | **Example Value** | -| ------------------ | --------- | -------------------------- | -| date_of_birth | timestamp | 1 January 1970 at 00:00:00 | -| does_freestyle | boolean | true | -| does_racing | boolean | false | -| does_ski | boolean | true | -| emergency_name | string | Jane Doe | -| emergency_phone | string | 123 456 789 | -| emergency_relation | string | Friend | -| first_name | string | John | -| last_name | string | Doe | -| membership | string | "admin" or "member" | - -## `demographics` collection - -Users may contain metadata which is not strictly necessary and may be optionally entered by them. This collection tracks this information. - -| **Field** | **Type** | **Example Value** | -| --------------- | -------- | ----------------- | -| faculty | string | Engineering | -| gender | string | female | -| second_faculty | string | Software | -| student_id | string | 123456789 | -| university_year | string | 3rd | - -## `requests` collection - -This manages all requests by users to the executive team at UASC. - -| **Field** | **Type** | **Example Value** | -| ------------- | --------- | ----------------------------------- | -| user_id | reference | /users/lVsOjAp06AfD6atT8bnrVEpcdcg2 | -| booking_id | reference | /bookings/8mYj7rWOMH6hGy4FzMed | -| query | string | Hello, when is your next event? | -| query_type | string | cancellation | -| status | string | unresolved | -| creation_time | timestamp | 1970-01-01T00:00:00Z | - -- `query_type` allows for future different query types. Possible query types - are - - `cancellation` - - `dateChange` -- `status` indicates the status of the query for the executive team to see (can - be `unresolved` or `resolved`) - -Additional fields may be specified, depending on the `query_type`, as follows: - -### `cancellation` request - -Has no additional fields specified. - -### `dateChange` request - -The following additional fields are specified: - -| **Field** | **Type** | **Example Value** | -| ------------- | --------- | ----------------- | -| old_check_in | timestamp | 25-07-2023 | -| old_check_out | timestamp | 27-07-2023 | -| new_check_in | timestamp | 26-07-2023 | -| new_check_out | timestamp | 28-07-2023 | - -Implementors should ensure that the range between -`old_check_out - old_check_in` and `new_check_out` - `new_check_in` do not -differ (i.e., the amount of days in the booking does not change). - -Because Firebase does not have a timestamp without time, ensure that time is set to midnight. - -## `bookings` collection - -This manages the link between users and booking IDs, and references the current -check-in and check-out dates of the booking. - -| **Field** | **Type** | **Example Value** | -| --------- | --------- | ----------------------------------- | -| user_id | reference | /users/lVsOjAp06AfD6atT8bnrVEpcdcg2 | -| check_in | timestamp | 26-07-2023 | -| check_out | timestamp | 26-07-2023 | - -Times of timestamps should be set to midnight. - -## `booking_changes` collection - -This manages any changes that have happened to a specific booking. - -This collection primarily exists to have a documented record of any changes -applied to a booking. - -| **Field** | **Type** | **Example Value** | -| ------------- | --------- | ------------------------------ | -| booking_id | reference | /bookings/8mYj7rWOMH6hGy4FzMed | -| old_check_in | timestamp | 26-07-2023 | -| old_check_out | timestamp | 26-07-2023 | -| new_check_in | timestamp | 27-07-2023 | -| new_check_out | timestamp | 27-07-2023 | - -Times of timestamps should be set to midnight. From 9af22622d506a6b231a262646693205fabe7845c Mon Sep 17 00:00:00 2001 From: Jeffery <61447509+jeffplays2005@users.noreply.github.com> Date: Thu, 25 Jul 2024 10:21:03 +1200 Subject: [PATCH 03/19] 670 Create readme including frontend wiki page (#678) There was already a README.md file so instead, I just added another heading with a link redirecting to the wiki. --- client/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/README.md b/client/README.md index c4033664f..0ab378544 100644 --- a/client/README.md +++ b/client/README.md @@ -1,3 +1,7 @@ +# Frotend architecture information + +https://github.com/UoaWDCC/uasc-web/wiki/Frontend-Architecture + This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). ## Getting Started From ccc7fc8d7aa2ea9215c7508ae99b5af9b18a560d Mon Sep 17 00:00:00 2001 From: Jeffery <61447509+jeffplays2005@users.noreply.github.com> Date: Thu, 25 Jul 2024 14:54:38 +1200 Subject: [PATCH 04/19] 566 Delete preview channel upon merge (#680) * 566 Delete preview channel upon merge Have added the feature to the pre-existing workflow action as per [this pull request on action-hosting-deploy](https://github.com/FirebaseExtended/action-hosting-deploy/pull/65) * Add new workflow and revert changes Added a new delete firebase channel upon PR close action. Reverted the not implemented changes from the firebase deployment on PR. --- .../delete-firebase-client-on-close.yml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/delete-firebase-client-on-close.yml diff --git a/.github/workflows/delete-firebase-client-on-close.yml b/.github/workflows/delete-firebase-client-on-close.yml new file mode 100644 index 000000000..90d481b69 --- /dev/null +++ b/.github/workflows/delete-firebase-client-on-close.yml @@ -0,0 +1,20 @@ +name: Delete firebase channel upon PR close + +on: + pull_request: + types: [closed] + +jobs: + delete_firebase_channel: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v3 + + - uses: w9jds/firebase-action@v12.4.0 + with: + args: hosting:channel:delete ${{ github.head_ref }} --force + env: + # The Firebase service account key + GCP_SA_KEY: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_UASC_CEEBC }} + PROJECT_ID: uasc-ceebc From 94b8ca887c01b0dc77bcad379d621662b1705b22 Mon Sep 17 00:00:00 2001 From: Jeffery <61447509+jeffplays2005@users.noreply.github.com> Date: Thu, 25 Jul 2024 16:35:58 +1200 Subject: [PATCH 05/19] 566 delete preview channel on merge (#682) * 566 Delete preview channel upon merge Have added the feature to the pre-existing workflow action as per [this pull request on action-hosting-deploy](https://github.com/FirebaseExtended/action-hosting-deploy/pull/65) * Add new workflow and revert changes Added a new delete firebase channel upon PR close action. Reverted the not implemented changes from the firebase deployment on PR. * Changed the preview channel to delete Instead of just using the `github.head_ref` as the preview channel id, will need to make some changes as the preview channel created uses a different preview id. * Substring shell workaround for PR title --- .github/workflows/delete-firebase-client-on-close.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/delete-firebase-client-on-close.yml b/.github/workflows/delete-firebase-client-on-close.yml index 90d481b69..dc392cde5 100644 --- a/.github/workflows/delete-firebase-client-on-close.yml +++ b/.github/workflows/delete-firebase-client-on-close.yml @@ -9,11 +9,19 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: + # Substring workaround by using shell method + - name: Get short pull request title + id: get-short-pr + run: | + echo "pr=$(echo ${{github.head_ref}} | cut -c 1-20)" >> $GITHUB_OUTPUT" + - uses: actions/checkout@v3 - uses: w9jds/firebase-action@v12.4.0 with: - args: hosting:channel:delete ${{ github.head_ref }} --force + # as we didn't specify a specific channel id, firebase-action defaults + # with using pr- + args: hosting:channel:delete pr${{ github.event.pull_request.number }}-${{ steps.get-short-pr.outputs.pr }} --force env: # The Firebase service account key GCP_SA_KEY: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_UASC_CEEBC }} From 7571f2962d90400b5bccaa2c69fe4de9725a0554 Mon Sep 17 00:00:00 2001 From: Jeffery <61447509+jeffplays2005@users.noreply.github.com> Date: Thu, 25 Jul 2024 16:45:27 +1200 Subject: [PATCH 06/19] 566 delete preview channel on merge (#683) * 566 Delete preview channel upon merge Have added the feature to the pre-existing workflow action as per [this pull request on action-hosting-deploy](https://github.com/FirebaseExtended/action-hosting-deploy/pull/65) * Add new workflow and revert changes Added a new delete firebase channel upon PR close action. Reverted the not implemented changes from the firebase deployment on PR. * Changed the preview channel to delete Instead of just using the `github.head_ref` as the preview channel id, will need to make some changes as the preview channel created uses a different preview id. * Substring shell workaround for PR title * Remove extra " at the end --- .github/workflows/delete-firebase-client-on-close.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/delete-firebase-client-on-close.yml b/.github/workflows/delete-firebase-client-on-close.yml index dc392cde5..5dfc27a5d 100644 --- a/.github/workflows/delete-firebase-client-on-close.yml +++ b/.github/workflows/delete-firebase-client-on-close.yml @@ -13,7 +13,7 @@ jobs: - name: Get short pull request title id: get-short-pr run: | - echo "pr=$(echo ${{github.head_ref}} | cut -c 1-20)" >> $GITHUB_OUTPUT" + echo "pr=$(echo ${{github.head_ref}} | cut -c 1-20)" >> $GITHUB_OUTPUT - uses: actions/checkout@v3 From 4d2a901e4cce3c904fe85522100303398f00a501 Mon Sep 17 00:00:00 2001 From: Benson Cho <100653148+bcho892@users.noreply.github.com> Date: Fri, 26 Jul 2024 09:53:52 +1200 Subject: [PATCH 07/19] use the wrapped of the booking creation popup (#686) --- .../composite/Admin/AdminBookingView/AdminBookingView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/composite/Admin/AdminBookingView/AdminBookingView.tsx b/client/src/components/composite/Admin/AdminBookingView/AdminBookingView.tsx index 067b742cf..24f8092fb 100644 --- a/client/src/components/composite/Admin/AdminBookingView/AdminBookingView.tsx +++ b/client/src/components/composite/Admin/AdminBookingView/AdminBookingView.tsx @@ -9,7 +9,7 @@ import { import { useState, useRef } from "react" import { useClickOutside } from "@/components/utils/Utils" import ModalContainer from "@/components/generic/ModalContainer/ModalContainer" -import AdminBookingCreationPopUp from "./AdminBookingCreationPopUp" +import WrappedAdminBookingCreationPopUp from "./WrappedAdminBookingCreationPopUp" /** * The format of the columns in the admin booking view. @@ -167,7 +167,7 @@ export const AdminBookingView = ({ /> - setOpenAddBookingPopup(false)} /> From bd3bf703f791f468abd07b44e4e6202336d564f4 Mon Sep 17 00:00:00 2001 From: Benson Cho <100653148+bcho892@users.noreply.github.com> Date: Fri, 26 Jul 2024 19:42:51 +1200 Subject: [PATCH 08/19] update the email template and add pug for templating (#689) --- server/package.json | 2 + .../business-layer/services/MailService.ts | 21 +- .../business-layer/services/StripeService.ts | 4 + .../templates/BookingConfirmation.pug | 30 ++ yarn.lock | 265 +++++++++++++++++- 5 files changed, 311 insertions(+), 11 deletions(-) create mode 100644 server/src/business-layer/templates/BookingConfirmation.pug diff --git a/server/package.json b/server/package.json index b97c6af73..91060a922 100644 --- a/server/package.json +++ b/server/package.json @@ -11,6 +11,7 @@ "firebase-admin": "^12.0.0", "helmet": "^7.1.0", "nodemailer": "^6.9.14", + "pug": "^3.0.3", "stripe": "^14.22.0", "supertest": "^6.3.4", "swagger-jsdoc": "^6.2.8", @@ -24,6 +25,7 @@ "@types/helmet": "^4.0.0", "@types/node": "^20.11.22", "@types/nodemailer": "^6", + "@types/pug": "^2.0.10", "@types/supertest": "^6.0.2", "@types/swagger-jsdoc": "^6.0.4", "@types/swagger-ui-express": "^4.1.6", diff --git a/server/src/business-layer/services/MailService.ts b/server/src/business-layer/services/MailService.ts index 44704068c..076c43118 100644 --- a/server/src/business-layer/services/MailService.ts +++ b/server/src/business-layer/services/MailService.ts @@ -1,4 +1,8 @@ import * as NodeMailer from "nodemailer" +import path from "path" +import { compileFile } from "pug" + +const TEMPLATE_BASE_PATH = path.join(__dirname, "..", "templates") const transporter = NodeMailer.createTransport({ service: "Gmail", @@ -16,20 +20,29 @@ export default class MailService { * Sends an email to the user confirming their booking was made and specifying the dates * * @param recipientEmail the email for which the confirmation should be sent + * @param recipientName the **full** name of the intended recipient + * @param startDateString the pre-formatted date **string** of the *first* **night** in the user's booking + * @param endDateString the pre-formatted date **string** of the *last* **night** in the user's booking */ public async sendBookingConfirmationEmail( recipientEmail: string, + recipientName: string, startDateString: string, endDateString: string ) { + const compiledFunction = compileFile( + `${TEMPLATE_BASE_PATH}/BookingConfirmation.pug` + ) + const info = await transporter.sendMail({ from: '"UASC Bookings"', to: recipientEmail, subject: `Your booking from ${startDateString} to ${endDateString}`, - html: `

- Your booking from ${startDateString} to ${endDateString} has been confirmed. - Please email club.admin@uasc.co.nz for any queries -

` + html: compiledFunction({ + name: recipientName, + startDate: startDateString, + endDate: endDateString + }) }) console.log("Booking confirmation email sent: %s", info.messageId) diff --git a/server/src/business-layer/services/StripeService.ts b/server/src/business-layer/services/StripeService.ts index 8537962c1..b094337aa 100644 --- a/server/src/business-layer/services/StripeService.ts +++ b/server/src/business-layer/services/StripeService.ts @@ -431,9 +431,13 @@ export default class StripeService { const [userAuthData] = await new AuthService().bulkRetrieveUsersByUids([ { uid } ]) + const { first_name, last_name } = await new UserDataService().getUserData( + uid + ) await new MailService().sendBookingConfirmationEmail( userAuthData.email, + `${first_name} ${last_name}`, session.metadata[START_DATE], session.metadata[END_DATE] ) diff --git a/server/src/business-layer/templates/BookingConfirmation.pug b/server/src/business-layer/templates/BookingConfirmation.pug new file mode 100644 index 000000000..44adde657 --- /dev/null +++ b/server/src/business-layer/templates/BookingConfirmation.pug @@ -0,0 +1,30 @@ +p Kia ora #{name} + +p UASC is stoked to confirm your booking for an unforgettable stay at your lodge between the nights of: + +p #{startDate} to #{endDate} + +p Here's some info for both new and old members: + +p Getting to our lodge - Our lodge is nestled on the whakapapa side of Ruapehu, it is a 4 hour drive from Auckland. The drive up Bruce road to the lodge can be snow joke, please drive to the conditions and check Bruce roads status on the whakapapa website before departing. + +p Parking - Parking is available on the same road as the lodge. Parking can be hard to find from mid morning to afternoon. You can repark closer to the lodge later in the evening. + +p Getting into our lodge - The door code is 1627Y then turn the handle anticlockwise. + +p The Lodge - If this is your first time, welcome to your new home. The bottom floor houses the kitchen, lounge, conversation pit, drying and tuning room. Upstairs you’ll find two bunk rooms and bathrooms, feel free to find a spare bunk and set yourself up. Our lodge custodian, Issac, will be on hand to look after the lodge and answer any questions you might have. + +p Food - Dinner is provided + +p Expectations - To keep our lodge in top shape, we ask all guests to pitch in with chores. When you see Issac, be proactive and ask what needs doing. Please make sure to leave the lodge as clean (or cleaner!) than you found it. + +p By staying at our lodge you are agreeing to our policy and behavior rules, which you can find in detail on our website. + +p If at any point during your stay you feel unsafe, uncomfortable or want to report something please use our form below which is monitored by our wellbeing officer. +https://forms.gle/UTBB4TsMCTgyaatYA + +p Cheers, +p Dominic Chanwai +p University of Auckland Snowsports Club +p Instagram: uasc_nz | Email: bookings@uasc.co.nz | Website: uasc.co.nz + diff --git a/yarn.lock b/yarn.lock index 1c9bbb30d..f9caee01a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -811,7 +811,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.24.8": +"@babel/parser@npm:^7.24.8, @babel/parser@npm:^7.6.0, @babel/parser@npm:^7.9.6": version: 7.24.8 resolution: "@babel/parser@npm:7.24.8" bin: @@ -2474,6 +2474,17 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.6.1, @babel/types@npm:^7.9.6": + version: 7.24.9 + resolution: "@babel/types@npm:7.24.9" + dependencies: + "@babel/helper-string-parser": "npm:^7.24.8" + "@babel/helper-validator-identifier": "npm:^7.24.7" + to-fast-properties: "npm:^2.0.0" + checksum: 10c0/4970b3481cab39c5c3fdb7c28c834df5c7049f3c7f43baeafe121bb05270ebf0da7c65b097abf314877f213baa591109c82204f30d66cdd46c22ece4a2f32415 + languageName: node + linkType: hard + "@base2/pretty-print-object@npm:1.0.1": version: 1.0.1 resolution: "@base2/pretty-print-object@npm:1.0.1" @@ -8294,6 +8305,13 @@ __metadata: languageName: node linkType: hard +"@types/pug@npm:^2.0.10": + version: 2.0.10 + resolution: "@types/pug@npm:2.0.10" + checksum: 10c0/6fac37fd84ad4bcf755061caad274db70591699739070bc30c5c1b5f0aecf98646dc29ec8da11cfca82a2b7cc57d949a3ae50aba2f88bf098751ebdd25d9aaea + languageName: node + linkType: hard + "@types/qs@npm:*, @types/qs@npm:^6.9.5": version: 6.9.14 resolution: "@types/qs@npm:6.9.14" @@ -9262,7 +9280,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^7.4.1": +"acorn@npm:^7.1.1, acorn@npm:^7.4.1": version: 7.4.1 resolution: "acorn@npm:7.4.1" bin: @@ -9747,7 +9765,7 @@ __metadata: languageName: node linkType: hard -"asap@npm:^2.0.0": +"asap@npm:^2.0.0, asap@npm:~2.0.3": version: 2.0.6 resolution: "asap@npm:2.0.6" checksum: 10c0/c6d5e39fe1f15e4b87677460bd66b66050cd14c772269cee6688824c1410a08ab20254bb6784f9afb75af9144a9f9a7692d49547f4d19d715aeb7c0318f3136d @@ -9765,6 +9783,13 @@ __metadata: languageName: node linkType: hard +"assert-never@npm:^1.2.1": + version: 1.3.0 + resolution: "assert-never@npm:1.3.0" + checksum: 10c0/5dbd4fb93bca5c5639c04b5216feebe00e44005b2967e35490cb3154b0ffa48637f796fdb48141b40ffd5b32bd669eb675ba876e112f269fc4bf5a70e70374a8 + languageName: node + linkType: hard + "assert@npm:^2.0.0, assert@npm:^2.1.0": version: 2.1.0 resolution: "assert@npm:2.1.0" @@ -9999,6 +10024,15 @@ __metadata: languageName: node linkType: hard +"babel-walk@npm:3.0.0-canary-5": + version: 3.0.0-canary-5 + resolution: "babel-walk@npm:3.0.0-canary-5" + dependencies: + "@babel/types": "npm:^7.9.6" + checksum: 10c0/17b689874d15c37714cedf6797dd9321dcb998d8e0dda9a8fe8c8bbbf128bbdeb8935cf56e8630d6b67eae76d2a0bc1e470751e082c3b0e30b80d58beafb5e64 + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -10661,6 +10695,15 @@ __metadata: languageName: node linkType: hard +"character-parser@npm:^2.2.0": + version: 2.2.0 + resolution: "character-parser@npm:2.2.0" + dependencies: + is-regex: "npm:^1.0.3" + checksum: 10c0/5a8d3eff2c912a6878c84e2ebf9d42524e858aa7e1a1c7e8bb79ab54da109ad008fe9057a9d2b3230541d7ff858eda98983a2ae15db57ba01af2e989d29e932e + languageName: node + linkType: hard + "character-reference-invalid@npm:^1.0.0": version: 1.1.4 resolution: "character-reference-invalid@npm:1.1.4" @@ -11276,6 +11319,16 @@ __metadata: languageName: node linkType: hard +"constantinople@npm:^4.0.1": + version: 4.0.1 + resolution: "constantinople@npm:4.0.1" + dependencies: + "@babel/parser": "npm:^7.6.0" + "@babel/types": "npm:^7.6.1" + checksum: 10c0/15129adef19b1af2c3ade8bd38f97c34781bf461472a30ab414384b28d072be83070c8d2175787c045ef7c222c415101ae609936e7903427796a0c0eca8449fd + languageName: node + linkType: hard + "constants-browserify@npm:^1.0.0": version: 1.0.0 resolution: "constants-browserify@npm:1.0.0" @@ -12312,6 +12365,13 @@ __metadata: languageName: node linkType: hard +"doctypes@npm:^1.1.0": + version: 1.1.0 + resolution: "doctypes@npm:1.1.0" + checksum: 10c0/b3f9d597ad8b9ac6aeba9d64df61f0098174f7570e3d34f7ee245ebc736c7bee122d9738a18e22010b98983fd9a340d63043d3841f02d8a7742a2d96d2c72610 + languageName: node + linkType: hard + "dom-accessibility-api@npm:^0.5.9": version: 0.5.16 resolution: "dom-accessibility-api@npm:0.5.16" @@ -15750,6 +15810,16 @@ __metadata: languageName: node linkType: hard +"is-expression@npm:^4.0.0": + version: 4.0.0 + resolution: "is-expression@npm:4.0.0" + dependencies: + acorn: "npm:^7.1.1" + object-assign: "npm:^4.1.1" + checksum: 10c0/541831d39d3e7bfc8cecd966d6b0f3c0e6d9055342f17b634fb23e74f51ce90f1bfc3cf231c722fe003a61e8d4f0b9e07244fdaba57f4fc70a163c74006fd5a0 + languageName: node + linkType: hard + "is-extglob@npm:^2.1.1": version: 2.1.1 resolution: "is-extglob@npm:2.1.1" @@ -15947,7 +16017,14 @@ __metadata: languageName: node linkType: hard -"is-regex@npm:^1.1.4": +"is-promise@npm:^2.0.0": + version: 2.2.2 + resolution: "is-promise@npm:2.2.2" + checksum: 10c0/2dba959812380e45b3df0fb12e7cb4d4528c989c7abb03ececb1d1fd6ab1cbfee956ca9daa587b9db1d8ac3c1e5738cf217bdb3dfd99df8c691be4c00ae09069 + languageName: node + linkType: hard + +"is-regex@npm:^1.0.3, is-regex@npm:^1.1.4": version: 1.1.4 resolution: "is-regex@npm:1.1.4" dependencies: @@ -16747,6 +16824,13 @@ __metadata: languageName: node linkType: hard +"js-stringify@npm:^1.0.2": + version: 1.0.2 + resolution: "js-stringify@npm:1.0.2" + checksum: 10c0/a450c04fde3a7e1c27f1c3c4300433f8d79322f9e3c2e76266843cef8c0b5a69b5f11b5f173212b2f15f2df09e068ef7ddf46ef775e2486f3006a6f4e912578d + languageName: node + linkType: hard + "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -17038,6 +17122,16 @@ __metadata: languageName: node linkType: hard +"jstransformer@npm:1.0.0": + version: 1.0.0 + resolution: "jstransformer@npm:1.0.0" + dependencies: + is-promise: "npm:^2.0.0" + promise: "npm:^7.0.1" + checksum: 10c0/11f9b4f368a55878dd7973154cd83b0adca27f974d21217728652530775b2bec281e92109de66f0c9e37c76af796d5b76b33f3e38363214a83d102d523a7285b + languageName: node + linkType: hard + "jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.5": version: 3.3.5 resolution: "jsx-ast-utils@npm:3.3.5" @@ -19788,6 +19882,15 @@ __metadata: languageName: node linkType: hard +"promise@npm:^7.0.1": + version: 7.3.1 + resolution: "promise@npm:7.3.1" + dependencies: + asap: "npm:~2.0.3" + checksum: 10c0/742e5c0cc646af1f0746963b8776299701ad561ce2c70b49365d62c8db8ea3681b0a1bf0d4e2fe07910bf72f02d39e51e8e73dc8d7503c3501206ac908be107f + languageName: node + linkType: hard + "prompts@npm:^2.0.1, prompts@npm:^2.4.0": version: 2.4.2 resolution: "prompts@npm:2.4.2" @@ -19892,6 +19995,133 @@ __metadata: languageName: node linkType: hard +"pug-attrs@npm:^3.0.0": + version: 3.0.0 + resolution: "pug-attrs@npm:3.0.0" + dependencies: + constantinople: "npm:^4.0.1" + js-stringify: "npm:^1.0.2" + pug-runtime: "npm:^3.0.0" + checksum: 10c0/28178e91c05e8eb9130861c78dccc61eae3e1610931346065bd32ad0b08b023a8dcf2470c3b2409ba45a5098d6d7ed15687717e91cf77770c6381a18626e5194 + languageName: node + linkType: hard + +"pug-code-gen@npm:^3.0.3": + version: 3.0.3 + resolution: "pug-code-gen@npm:3.0.3" + dependencies: + constantinople: "npm:^4.0.1" + doctypes: "npm:^1.1.0" + js-stringify: "npm:^1.0.2" + pug-attrs: "npm:^3.0.0" + pug-error: "npm:^2.1.0" + pug-runtime: "npm:^3.0.1" + void-elements: "npm:^3.1.0" + with: "npm:^7.0.0" + checksum: 10c0/517a93930dbc80bc7fa5f60ff324229a07cc5ab70ed9d344ce105e2fe24de68db5121c8457a9ba99cdc8d48dd18779dd34956ebfcab009b3c1c6843a3cade109 + languageName: node + linkType: hard + +"pug-error@npm:^2.0.0, pug-error@npm:^2.1.0": + version: 2.1.0 + resolution: "pug-error@npm:2.1.0" + checksum: 10c0/bbce339b17fab9890de84975c0cd8723a847bf65f35653d3ebcf77018e8ad91529d56e978ab80f4c64c9f4f07ef9e56e7a9fda3be44249c344a93ba11fccff79 + languageName: node + linkType: hard + +"pug-filters@npm:^4.0.0": + version: 4.0.0 + resolution: "pug-filters@npm:4.0.0" + dependencies: + constantinople: "npm:^4.0.1" + jstransformer: "npm:1.0.0" + pug-error: "npm:^2.0.0" + pug-walk: "npm:^2.0.0" + resolve: "npm:^1.15.1" + checksum: 10c0/7ddd62f5eb97f5242858bd56d93ffed387fef3742210a53770c980020cf91a34384b84b7fc8f0de185b43dfa77de2c4d0f63f575a4c5b3887fdef4e64b8d559d + languageName: node + linkType: hard + +"pug-lexer@npm:^5.0.1": + version: 5.0.1 + resolution: "pug-lexer@npm:5.0.1" + dependencies: + character-parser: "npm:^2.2.0" + is-expression: "npm:^4.0.0" + pug-error: "npm:^2.0.0" + checksum: 10c0/24195a5681953ab91c6a3ccd80a643f760dddb65e2f266bf8ccba145018ba0271536efe1572de2c2224163eb00873c2f1df0ad7ea7aa8bcbf79a66b586ca8435 + languageName: node + linkType: hard + +"pug-linker@npm:^4.0.0": + version: 4.0.0 + resolution: "pug-linker@npm:4.0.0" + dependencies: + pug-error: "npm:^2.0.0" + pug-walk: "npm:^2.0.0" + checksum: 10c0/db754ff34cdd4ba9d9e2d9535cce2a74178f2172e848a5fa6381907cb5bfaa0d39d4cc3eb29893d35fc1c417e83ae3cfd434640ba7d3b635c63199104fae976c + languageName: node + linkType: hard + +"pug-load@npm:^3.0.0": + version: 3.0.0 + resolution: "pug-load@npm:3.0.0" + dependencies: + object-assign: "npm:^4.1.1" + pug-walk: "npm:^2.0.0" + checksum: 10c0/2a7659dfaf9872dd25d851f85e4c27fa447d907b1db3540030cd844614159ff181e067d8f2bedf90eb6b5b1ff03747253859ecbbb822e40f4834b15591d4e108 + languageName: node + linkType: hard + +"pug-parser@npm:^6.0.0": + version: 6.0.0 + resolution: "pug-parser@npm:6.0.0" + dependencies: + pug-error: "npm:^2.0.0" + token-stream: "npm:1.0.0" + checksum: 10c0/faa6cec43afdeb2705eb8c68dfdb2e65836238df8043ae55295ffb72450b8c7a990ea1be60adbde19f58988b9e1d18a84ea42453e2c4f104d0031f78fda737b2 + languageName: node + linkType: hard + +"pug-runtime@npm:^3.0.0, pug-runtime@npm:^3.0.1": + version: 3.0.1 + resolution: "pug-runtime@npm:3.0.1" + checksum: 10c0/0db8166d2e17695a6941d1de81dcb21c8a52921299b1e03bf6a0a3d2b0036b51cf98101b3937b731c745e8d3e0268cb0b728c02f61a80a25fcfaa15c594fb1be + languageName: node + linkType: hard + +"pug-strip-comments@npm:^2.0.0": + version: 2.0.0 + resolution: "pug-strip-comments@npm:2.0.0" + dependencies: + pug-error: "npm:^2.0.0" + checksum: 10c0/ca498adedaeba51dd836b20129bbd161e2d5a397a2baaa553b1e74e888caa2258dcd7326396fc6f8fed8c7b7f906cfebc4c386ccbee8888a27b2ca0d4d86d206 + languageName: node + linkType: hard + +"pug-walk@npm:^2.0.0": + version: 2.0.0 + resolution: "pug-walk@npm:2.0.0" + checksum: 10c0/005d63177bcf057f5a618b182f6d4600afb039200b07a381a0d89288a2b3126e763a0a6c40b758eab0731c8e63cad1bbcb46d96803b9ae9cfc879f6ef5a0f8f4 + languageName: node + linkType: hard + +"pug@npm:^3.0.3": + version: 3.0.3 + resolution: "pug@npm:3.0.3" + dependencies: + pug-code-gen: "npm:^3.0.3" + pug-filters: "npm:^4.0.0" + pug-lexer: "npm:^5.0.1" + pug-linker: "npm:^4.0.0" + pug-load: "npm:^3.0.0" + pug-parser: "npm:^6.0.0" + pug-runtime: "npm:^3.0.1" + pug-strip-comments: "npm:^2.0.0" + checksum: 10c0/bda53d3a6deea1d348cd5ab17427c77f3d74165510ad16f4fd182cc63618ad09388ecda317d17122ee890c8a68f9a54b96221fce7f44a332e463fdbb10a9d1e2 + languageName: node + linkType: hard + "pump@npm:^2.0.0": version: 2.0.1 resolution: "pump@npm:2.0.1" @@ -20806,7 +21036,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.10.1, resolve@npm:^1.14.2, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.2, resolve@npm:^1.22.4, resolve@npm:^1.22.8": +"resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.10.1, resolve@npm:^1.14.2, resolve@npm:^1.15.1, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.2, resolve@npm:^1.22.4, resolve@npm:^1.22.8": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -20832,7 +21062,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.10.1#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin": +"resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.10.1#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.15.1#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -21365,6 +21595,7 @@ __metadata: "@types/helmet": "npm:^4.0.0" "@types/node": "npm:^20.11.22" "@types/nodemailer": "npm:^6" + "@types/pug": "npm:^2.0.10" "@types/supertest": "npm:^6.0.2" "@types/swagger-jsdoc": "npm:^6.0.4" "@types/swagger-ui-express": "npm:^4.1.6" @@ -21378,6 +21609,7 @@ __metadata: helmet: "npm:^7.1.0" nodemailer: "npm:^6.9.14" nodemon: "npm:^3.1.0" + pug: "npm:^3.0.3" stripe: "npm:^14.22.0" supertest: "npm:^6.3.4" swagger-jsdoc: "npm:^6.2.8" @@ -22853,6 +23085,13 @@ __metadata: languageName: node linkType: hard +"token-stream@npm:1.0.0": + version: 1.0.0 + resolution: "token-stream@npm:1.0.0" + checksum: 10c0/c1924a89686fc035d579cbe856da12306571d5fe7408eeeebe80df7c25c5cc644b8ae102d5cbc0f085d0e105f391d1a48dc0e568520434c5b444ea6c7de2b822 + languageName: node + linkType: hard + "touch@npm:^3.1.0": version: 3.1.0 resolution: "touch@npm:3.1.0" @@ -23951,7 +24190,7 @@ __metadata: languageName: node linkType: hard -"void-elements@npm:3.1.0": +"void-elements@npm:3.1.0, void-elements@npm:^3.1.0": version: 3.1.0 resolution: "void-elements@npm:3.1.0" checksum: 10c0/0b8686f9f9aa44012e9bd5eabf287ae0cde409b9a2854c5a2335cb83920c957668ac5876e3f0d158dd424744ac411a7270e64128556b451ed3bec875ef18534d @@ -24281,6 +24520,18 @@ __metadata: languageName: node linkType: hard +"with@npm:^7.0.0": + version: 7.0.2 + resolution: "with@npm:7.0.2" + dependencies: + "@babel/parser": "npm:^7.9.6" + "@babel/types": "npm:^7.9.6" + assert-never: "npm:^1.2.1" + babel-walk: "npm:3.0.0-canary-5" + checksum: 10c0/99289e49afc4b1776afae0ef85e84cfa775e8e07464d2b9853a31b0822347031d1cf77f287d25adc8c3f81e4fa68f4ee31526a9c95d4981ba08a1fe24dee111a + languageName: node + linkType: hard + "wordwrap@npm:^1.0.0": version: 1.0.0 resolution: "wordwrap@npm:1.0.0" From a8a1368e41304278fe04732a9589586d2742154a Mon Sep 17 00:00:00 2001 From: Benson Cho <100653148+bcho892@users.noreply.github.com> Date: Fri, 26 Jul 2024 22:47:55 +1200 Subject: [PATCH 09/19] copy templates to build outputs (#691) * copy templates to build outputs * make email template only compile once * revert unneeded change --- server/package.json | 3 ++- server/src/business-layer/services/MailService.ts | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/server/package.json b/server/package.json index 91060a922..b34525e59 100644 --- a/server/package.json +++ b/server/package.json @@ -41,7 +41,8 @@ "scripts": { "start": "concurrently \"yarn nodemon -e ts,js --exec \" \"yarn tsoa spec-and-routes && yarn normalise-newlines && yarn workspace client generate-types\"", "nodemon": "nodemon", - "build": "tsc -p ./tsconfig.prod.json && tsc-alias", + "build": "tsc -p ./tsconfig.prod.json && tsc-alias && yarn copy-templates", + "copy-templates": "cp -r ./src/business-layer/templates ./dist/business-layer/templates", "serve": "node --es-module-specifier-resolution=node dist/index.js", "token": "ts-node ./tooling/login-prod.ts", "timestamp": "ts-node ./tooling/timestamp-conversion.ts", diff --git a/server/src/business-layer/services/MailService.ts b/server/src/business-layer/services/MailService.ts index 076c43118..ec100b505 100644 --- a/server/src/business-layer/services/MailService.ts +++ b/server/src/business-layer/services/MailService.ts @@ -4,6 +4,10 @@ import { compileFile } from "pug" const TEMPLATE_BASE_PATH = path.join(__dirname, "..", "templates") +const BOOKING_CONFIRMATION_TEMPLATE = compileFile( + `${TEMPLATE_BASE_PATH}/BookingConfirmation.pug` +) + const transporter = NodeMailer.createTransport({ service: "Gmail", host: "smtp.gmail.com", @@ -30,15 +34,11 @@ export default class MailService { startDateString: string, endDateString: string ) { - const compiledFunction = compileFile( - `${TEMPLATE_BASE_PATH}/BookingConfirmation.pug` - ) - const info = await transporter.sendMail({ from: '"UASC Bookings"', to: recipientEmail, subject: `Your booking from ${startDateString} to ${endDateString}`, - html: compiledFunction({ + html: BOOKING_CONFIRMATION_TEMPLATE({ name: recipientName, startDate: startDateString, endDate: endDateString From 34e8d9f3abfe97c91d365d9146768a5f4b86156f Mon Sep 17 00:00:00 2001 From: Jeffery <61447509+jeffplays2005@users.noreply.github.com> Date: Fri, 26 Jul 2024 23:59:40 +1200 Subject: [PATCH 10/19] Create interface in firebase.ts (#692) * Create interface in firebase.ts * Add other important data fields to the EventSlot interface Added start/end dates, location, image url. Fixed a typo * Update comments --- server/src/data-layer/models/firebase.ts | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/server/src/data-layer/models/firebase.ts b/server/src/data-layer/models/firebase.ts index 0c33264a7..ee76c95bc 100644 --- a/server/src/data-layer/models/firebase.ts +++ b/server/src/data-layer/models/firebase.ts @@ -129,3 +129,41 @@ export interface BookingChange { new_check_in: Timestamp // New check-in timestamp new_check_out: Timestamp // New check-out timestamp } + +export interface EventSlot { + /** + * The title of this event + * @example Snowboarding race! + */ + title: string + /** + * An optional description for this event + * This should be in markdown + * @example Come join your friends in this exciting UASC event and race! + */ + description?: string + /** + * The link for the image to display on the event page (essentially a thumbnail) + */ + image_url?: string + /** + * The location of this event + */ + location: string + /** + * The start date of the event. + * Note that this date is in UTC time. + * Use the same start and end day to show that its a 1 day event. + */ + start_date: Timestamp + /** + * The end date of the event. + * Note that this date is in UTC time. + */ + end_date: Timestamp + /** + * Max number of attendees at this event, left as optional for uncapped + * @example 30 + */ + max_occupancy?: number +} From 157b97950d0f0a36c853ecf76d9a69a3cb058dec Mon Sep 17 00:00:00 2001 From: Benson Cho <100653148+bcho892@users.noreply.github.com> Date: Sat, 27 Jul 2024 21:14:20 +1200 Subject: [PATCH 11/19] add docs (#690) --- .../AlertsComponent/AlertsComponent.tsx | 10 +++++ .../components/generic/Checkbox/Checkbox.tsx | 3 ++ .../generic/ContactDetail/ContactDetail.tsx | 15 +++++++ .../components/generic/Dropdown/Dropdown.tsx | 10 +++++ .../ExcitmentSlider/ExcitementSlider.tsx | 11 +++++ .../components/generic/MenuList/MenuList.tsx | 11 +++++ .../components/generic/MenuTab/MenuTab.tsx | 5 +++ .../PasswordSetupForm/PasswordSetupForm.tsx | 41 ++++++++++++++++++- .../generic/PricingBanner/PricingBanner.tsx | 9 ++++ .../generic/PricingCard/PricingCard.tsx | 14 +++++++ .../ProfileInformationPanel.tsx | 15 ++++++- .../generic/SignUpNotif/SignUpNotif.tsx | 6 +++ .../generic/StepperButtons/StepperButton.tsx | 7 ++++ .../StepperComponent/StepperComponent.tsx | 18 ++++++++ .../generic/TextInputComponent/TextInput.tsx | 5 +++ 15 files changed, 177 insertions(+), 3 deletions(-) diff --git a/client/src/components/generic/AlertsComponent/AlertsComponent.tsx b/client/src/components/generic/AlertsComponent/AlertsComponent.tsx index 65d395b67..b5b17da9e 100644 --- a/client/src/components/generic/AlertsComponent/AlertsComponent.tsx +++ b/client/src/components/generic/AlertsComponent/AlertsComponent.tsx @@ -7,8 +7,18 @@ import WarningIcon from "@/assets/icons/warning.svg" import XIcon from "@/assets/icons/x.svg" type AlertsInputProp = { + /** + * What should be displayed to the user inside the alert + */ message: string + /** + * Controls what the styling of the alert will be + */ variant?: "success" | "notification" | "error" + /** + * If there should be an embedded button into the alert to allow + * for the user to close it + */ isButton?: boolean } diff --git a/client/src/components/generic/Checkbox/Checkbox.tsx b/client/src/components/generic/Checkbox/Checkbox.tsx index d46a5bbca..55c13f54b 100644 --- a/client/src/components/generic/Checkbox/Checkbox.tsx +++ b/client/src/components/generic/Checkbox/Checkbox.tsx @@ -1,4 +1,7 @@ interface ICheckboxProps { + /** + * The text that appears for the checkbox + */ label: string } diff --git a/client/src/components/generic/ContactDetail/ContactDetail.tsx b/client/src/components/generic/ContactDetail/ContactDetail.tsx index 54720a96e..3b50d9424 100644 --- a/client/src/components/generic/ContactDetail/ContactDetail.tsx +++ b/client/src/components/generic/ContactDetail/ContactDetail.tsx @@ -1,6 +1,21 @@ export interface IContactDetail { + /** + * The main description of the contact + * + * @example "Admin" + */ title: string + /** + * The extended description of the contact + * + * @example "For all payment issues and queries" + */ description?: string + /** + * The email that is associated with the contact + * + * @example "mail@mail.com" + */ email?: string } diff --git a/client/src/components/generic/Dropdown/Dropdown.tsx b/client/src/components/generic/Dropdown/Dropdown.tsx index f28e3e21c..9c54b5076 100644 --- a/client/src/components/generic/Dropdown/Dropdown.tsx +++ b/client/src/components/generic/Dropdown/Dropdown.tsx @@ -1,7 +1,17 @@ import React from "react" type DropdownProps = React.SelectHTMLAttributes & { + /** + * The main text that appears above the dropdown + * + * @example "Favourite sport" + */ label?: string + /** + * The subheading of the textbox, i.e if the label was "Favourite sport": + * + * @example "Only include ones you have played in the last year" + */ description?: string } diff --git a/client/src/components/generic/ExcitmentSlider/ExcitementSlider.tsx b/client/src/components/generic/ExcitmentSlider/ExcitementSlider.tsx index 718788f6d..0fdb12687 100644 --- a/client/src/components/generic/ExcitmentSlider/ExcitementSlider.tsx +++ b/client/src/components/generic/ExcitmentSlider/ExcitementSlider.tsx @@ -3,7 +3,18 @@ import React, { useState } from "react" interface ExcitementSliderProps { + /** + * The lowest value the slider should go to + * + * @example -69 + */ min: number + + /** + * The lowest value the slider should go to + * + * @example 69 + */ max: number } diff --git a/client/src/components/generic/MenuList/MenuList.tsx b/client/src/components/generic/MenuList/MenuList.tsx index 278756ef4..23f164645 100644 --- a/client/src/components/generic/MenuList/MenuList.tsx +++ b/client/src/components/generic/MenuList/MenuList.tsx @@ -1,6 +1,17 @@ import { ReactNode } from "react" interface IMenuListProps { + /** + * Which side the children should start, + * + * e.g for `left`: + * + * /-start here--------------/ + * + * e.g for `right`: + * + * /------------start here--/ + */ anchor?: "left" | "right" children?: ReactNode } diff --git a/client/src/components/generic/MenuTab/MenuTab.tsx b/client/src/components/generic/MenuTab/MenuTab.tsx index 6f10a61de..a422d6bd0 100644 --- a/client/src/components/generic/MenuTab/MenuTab.tsx +++ b/client/src/components/generic/MenuTab/MenuTab.tsx @@ -3,6 +3,11 @@ import DownArrow from "@/assets/icons/downarrow.svg" import MenuList from "../MenuList/MenuList" interface IMenuTabProps { + /** + * What should be shown for the text on the tab + * + * @example "Home" + */ displayText: string } type props = IMenuTabProps & React.ButtonHTMLAttributes diff --git a/client/src/components/generic/PasswordSetupForm/PasswordSetupForm.tsx b/client/src/components/generic/PasswordSetupForm/PasswordSetupForm.tsx index fa25d1c72..034e883ac 100644 --- a/client/src/components/generic/PasswordSetupForm/PasswordSetupForm.tsx +++ b/client/src/components/generic/PasswordSetupForm/PasswordSetupForm.tsx @@ -5,27 +5,66 @@ import AlertsComponent from "../AlertsComponent/AlertsComponent" import { FormEvent, useState } from "react" export type HandlerResponse = { + /** + * If the setup worked + */ success: boolean + /** + * *Custom* message to display to the user on successful signup + */ successMessage?: string error?: { + /** + * The reason for the sign up failing + */ message: string } } type MessageTypes = { + /** + * Message to display on successful signup + */ success?: string + /** + * Message to display on failed signup + */ error?: string + /** + * Misc messages + */ other?: string } type FormState = { + /** + * The password that the user enters (wants to change their password to) + */ firstPassword: string + + /** + * The *confirm* password that the user enters, which should be checked + * against `firstPassword` + */ secondPassword: string } interface IPasswordSetupForm { - passwordSetUpHandler?: (firstPassword: string) => Promise + /** + * Called when the user requests a password change. Should return a + * promise with the results of the attempted password change + * + * @param password the *confirmed* password that the user wants to use + * as the new password + */ + passwordSetUpHandler?: (password: string) => Promise + /** + * A react `ref` + */ formRef?: React.RefObject + /** + * Callback to use if the password setup was successful + */ successHandler?: () => void } diff --git a/client/src/components/generic/PricingBanner/PricingBanner.tsx b/client/src/components/generic/PricingBanner/PricingBanner.tsx index be9a83d23..9984328be 100644 --- a/client/src/components/generic/PricingBanner/PricingBanner.tsx +++ b/client/src/components/generic/PricingBanner/PricingBanner.tsx @@ -1,6 +1,15 @@ export interface IPricingBanner { + /** + * @example "Great nightly rates" + */ headline: string + /** + * @example "$40 per night" + */ priceInformation: string + /** + * @example "*$60 for a single saturday" + */ disclaimer?: string } const PricingBanner = ({ diff --git a/client/src/components/generic/PricingCard/PricingCard.tsx b/client/src/components/generic/PricingCard/PricingCard.tsx index 5d74dac13..280701dc1 100644 --- a/client/src/components/generic/PricingCard/PricingCard.tsx +++ b/client/src/components/generic/PricingCard/PricingCard.tsx @@ -1,9 +1,23 @@ import tick from "@/assets/selectedtick.png" import Image from "next/image" interface IPricingCardDefault { + /** + * @example "UoA Member" + */ title: string + /** + * The **pre-formatted** string indicating the price of the item + * + * @example "$60" + */ priceString: string + /** + * @example "was $60 before!" + */ extraInfo?: string + /** + * If the card has been clicked on + */ selected?: boolean onClick?: () => void } diff --git a/client/src/components/generic/ProfileInformationPanel/ProfileInformationPanel.tsx b/client/src/components/generic/ProfileInformationPanel/ProfileInformationPanel.tsx index 81064225a..510b9d107 100644 --- a/client/src/components/generic/ProfileInformationPanel/ProfileInformationPanel.tsx +++ b/client/src/components/generic/ProfileInformationPanel/ProfileInformationPanel.tsx @@ -1,9 +1,20 @@ import { ReactNode } from "react" import EditIcon from "@/assets/icons/edit.svg" interface IProfileInformationPanel { - title: string // The title field + /** + * The main heading of the panel + */ + title: string children?: ReactNode - onEdit?: () => void // The edit button + /** + * Handler to be called when the user requests an edit for their profile + * + * @example + * () => { + * openEditPanel() + * } + */ + onEdit?: () => void } const ProfileInformationPanel = ({ diff --git a/client/src/components/generic/SignUpNotif/SignUpNotif.tsx b/client/src/components/generic/SignUpNotif/SignUpNotif.tsx index c5fcdcd72..330ac4b45 100644 --- a/client/src/components/generic/SignUpNotif/SignUpNotif.tsx +++ b/client/src/components/generic/SignUpNotif/SignUpNotif.tsx @@ -2,9 +2,15 @@ import { useRouter } from "next/navigation" import Button from "../FigmaButtons/FigmaButton" interface ISignUpNotif { + /** + * If there is a currently signed in user which determines the view to be shown + */ signedIn?: boolean } +/** + * For use in the bookings page when a non-signed in/guest member tries to view + */ export const SignUpNotif = ({ signedIn }: ISignUpNotif) => { const router = useRouter() function goToRegister() { diff --git a/client/src/components/generic/StepperButtons/StepperButton.tsx b/client/src/components/generic/StepperButtons/StepperButton.tsx index c27280ee0..cf6f9af1c 100644 --- a/client/src/components/generic/StepperButtons/StepperButton.tsx +++ b/client/src/components/generic/StepperButtons/StepperButton.tsx @@ -1,6 +1,10 @@ type buttonVariants = "normal" | "first" interface IStepperButtonProps { children?: React.ReactNode + /** + * `normal` or `first`. The `first` is special as it does not have the + * pointed edges. + */ variant?: buttonVariants } @@ -32,6 +36,9 @@ const First = ({ ) } +/** + * Used for displaying the navigation status of a paginated form + */ const StepperButton = ({ children, variant, diff --git a/client/src/components/generic/StepperComponent/StepperComponent.tsx b/client/src/components/generic/StepperComponent/StepperComponent.tsx index 6f0b5ab9c..d253a6d73 100644 --- a/client/src/components/generic/StepperComponent/StepperComponent.tsx +++ b/client/src/components/generic/StepperComponent/StepperComponent.tsx @@ -1,13 +1,31 @@ import StepperButton from "../StepperButtons/StepperButton" export type StepProps = { + /** + * The display name of the step + * + * @example "Confirm" + */ name: string + /** + * The current value from a set of `enum`s that determines which step should + * be highlighted on the stepper + */ index: number + /** + * Handler for if a button is clicked + */ onClick?: () => void } interface IStepperProps { + /** + * An `enum` value that defines what step should be active + */ currentStep: number + /** + * @example steps={["Details", "Confirmation"]} + */ steps: StepProps[] } diff --git a/client/src/components/generic/TextInputComponent/TextInput.tsx b/client/src/components/generic/TextInputComponent/TextInput.tsx index 5f72b584d..ea3958212 100644 --- a/client/src/components/generic/TextInputComponent/TextInput.tsx +++ b/client/src/components/generic/TextInputComponent/TextInput.tsx @@ -2,6 +2,11 @@ import React from "react" type TextInputProps = React.InputHTMLAttributes & { variant?: "success" | "error" + /** + * The description of the text box + * + * @example "First Name" + */ label?: string description?: string } From 44a011a1f61d5bf68e4438d642556b4d0c94dd07 Mon Sep 17 00:00:00 2001 From: zlrkw11 <64724157+zlrkw11@users.noreply.github.com> Date: Sat, 27 Jul 2024 21:32:55 +1200 Subject: [PATCH 12/19] Google map widget on contact page (#693) * implementation * fixed address --- client/src/components/composite/Contact/Contact.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/src/components/composite/Contact/Contact.tsx b/client/src/components/composite/Contact/Contact.tsx index 1814a98fa..ca961c4bc 100644 --- a/client/src/components/composite/Contact/Contact.tsx +++ b/client/src/components/composite/Contact/Contact.tsx @@ -13,6 +13,14 @@ const Contact = ({ items }: IContact) => {

Contact Us

+
+ +