Add basic escape room ordering functionality with Stripe integration#433
Add basic escape room ordering functionality with Stripe integration#433
Conversation
…ndling and Stripe integration - Implemented the purchase page layout and form for selecting kit type and theme. - Integrated Stripe for payment processing with a backend API for creating checkout sessions. - Added validation for form inputs and error handling for payment processing. - Created Azure functions for handling checkout session creation and retrieval. - Implemented storage of purchase data in Azure Table Storage with proof code generation. - Added environment configuration example for Stripe and Azure settings.
… handling - Added session-status API to retrieve payment status using Stripe Checkout session ID. - Implemented Stripe webhook to handle checkout session completion and store purchase data. - Created verify-purchase API to validate purchase codes and manage user sessions. - Developed access.astro page for users to access their purchased escape room kits. - Configured Netlify deployment settings and added necessary environment variables. - Updated package.json and package-lock.json to include Stripe and UUID dependencies. feat: Basic implementation of post-purchase page according to Figma
Configure Vitest with a setup file and path alias for cleaner imports.
…ial and verify purchase APIs
- Removed the digital content API endpoint and its associated logic. - Simplified the escape room access page, enhancing the form for purchase code and email verification. - Added error handling for missing content in the new corporate escape room content page. - Introduced a new layout for displaying escape room content based on user sessions.
… createSession function
❌ Deploy Preview for accessiblecommunity failed.
|
astro/public/robots.txt
Outdated
| # Allow basic materials | ||
| Allow: /materials/basic/ | ||
|
|
||
| Sitemap: https://accessiblecommunity.github.io/sitemap.xml |
There was a problem hiding this comment.
sitemap-0.xml should be the right path
astro/public/robots.txt
Outdated
| Disallow: /api/verify-purchase | ||
|
|
||
| # Allow basic materials | ||
| Allow: /materials/basic/ |
There was a problem hiding this comment.
Thoughts on Allow: * and then the disallows? That way you automatically allow everything to be crawled and only have to disallow that which we don't want
| const price = kitType === 'build' ? 50000 : 350000; // Stripe uses cents | ||
| const kitTypeName = kitType === 'build' ? 'Build-your-own Kit' : 'Ready-made Kit'; | ||
|
|
||
| // Map theme values to display names |
There was a problem hiding this comment.
We should be able to pull these from a content collection, so we don't have to hardcode them.
| <fieldset class="mb-4"> | ||
| <legend class="h5">Choose Your Theme *</legend> | ||
| <div class="row gy-3"> | ||
| <div class="col-sm-6"> |
There was a problem hiding this comment.
Should be able to generate these from a content collection of some type.
| </ThemedSection> | ||
|
|
||
| <!-- Ready-Made Kit Coming Soon Section --> | ||
| <ThemedSection theme="secondary"> |
There was a problem hiding this comment.
Don't need these, we are no longer doing ready-made kits.
There was a problem hiding this comment.
Is there a reason you made this an actual endpoint and not a function?
| // Export for use in save-purchase-data | ||
| export { handleSuccessfulPayment }; | ||
|
|
||
| async function storePurchaseData(purchaseData: any) { |
There was a problem hiding this comment.
We probably will want to separate this out into a separate lib, like you did for the session memory store.
| return [...new Set(candidates.filter(Boolean) as string[])]; | ||
| } | ||
|
|
||
| async function loadPurchase(purchaseCode: string): Promise<PurchaseRecord | null> { |
There was a problem hiding this comment.
This should probably go in the same lib as the savePurchaseData function, so it can be easily rewritten to a DB or whatever.
There was a problem hiding this comment.
Is this supposed to be generic, or tied directly to each kit?
…irmation email content
… themes collection
Allows use of hideSiteHeader to hide vanilla header Added Footer slot
| { | ||
| userAgent: '*', | ||
| allow: ['/'], | ||
| allow: ['/', '/materials/basic/'], |
There was a problem hiding this comment.
interesting, do we have to explicitly allow /materials/basic even though we don't disallow it below?
| <div class="container"> | ||
| <div class="row g-4"> | ||
| <div class="col-md-4"> | ||
| <h3 class="h5">About Accessible Community</h3> |
There was a problem hiding this comment.
Can we always guarantee the heading right before this one is an h2?
| margin: 2rem 0; | ||
| } | ||
|
|
||
| @media (max-width: 991.98px) { |
There was a problem hiding this comment.
why this value for max-width? Do you want it in px?
| padding: 3rem 0 1.5rem; | ||
| } | ||
|
|
||
| .escape-room-footer .col-md-4 { |
There was a problem hiding this comment.
You could use owl selector/the stack approach if you wanted to not have to set last child explicitly to 0rem. This is good too though!
https://every-layout.dev/layouts/stack/
| </main> | ||
|
|
||
| <script> | ||
| // @ts-nocheck |
There was a problem hiding this comment.
Thoughts on this code being it's own js file? Maybe some code comments too for what it's calculating just so it's quicker to read?
| // - Mailgun | ||
| // etc. | ||
|
|
||
| // For now, we'll just log the email content |
There was a problem hiding this comment.
do we need to update this before release?
| const tokenData = downloadTokens.get(downloadToken); | ||
|
|
||
| if (!tokenData || Date.now() > tokenData.expiresAt || tokenData.used) { | ||
| if (tokenData) { |
There was a problem hiding this comment.
Could we make the above !tokenData into a && somehow so we don't have to do another check right after for if tokenData does exist?
Added support for online ordering of escape room kits, including:
astro/vite.config.tsfor testing.Main content access can be found at /services/escape-room/access
README is located here
\local-dev\README.mdwith more information on simulating purchase information.Test purchases can be simulated using the provided JSON format, this will need to be converted to use the future AzureDB system.