diff --git a/.vscode/settings.json b/.vscode/settings.json
index e11b984..09c7543 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -20,5 +20,5 @@
"editor.formatOnSave": true
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
- "editor.formatOnSave": true,
-}
\ No newline at end of file
+ "editor.formatOnSave": true
+}
diff --git a/next.config.mjs b/next.config.mjs
index a14c397..0a38198 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -10,6 +10,10 @@ const nextConfig = {
pathname: "/pw/**",
protocol: "https",
},
+ {
+ hostname: "files.stripe.com",
+ protocol: "https",
+ },
],
},
reactStrictMode: true,
diff --git a/package.json b/package.json
index 7cd1b20..c7740f2 100644
--- a/package.json
+++ b/package.json
@@ -26,12 +26,14 @@
"react": "^18",
"react-countup": "^6.5.3",
"react-dom": "^18",
+ "react-icons": "^5.5.0",
"react-intersection-observer": "^9.13.1",
"react-lazy-load-image-component": "^1.6.2",
"react-multi-carousel": "^2.8.5",
"react-scroll": "^1.9.0",
"react-tsparticles": "^2.9.3",
"react-visibility-sensor": "^5.1.1",
+ "stripe": "^17.7.0",
"styled-components": "^6.1.13",
"tsparticles": "^2.9.3"
},
diff --git a/public/default-image.png b/public/default-image.png
new file mode 100644
index 0000000..587284b
Binary files /dev/null and b/public/default-image.png differ
diff --git a/src/components/Merch/MerchItems.tsx b/src/components/Merch/MerchItems.tsx
index ddea7d3..c63cdf5 100644
--- a/src/components/Merch/MerchItems.tsx
+++ b/src/components/Merch/MerchItems.tsx
@@ -1,46 +1,49 @@
import Image from "next/image";
-import Link from "next/link";
+import PaymentButton from "./PaymentButton";
export const MerchItems = ({
clothingImg,
- link,
price,
+ priceId,
title,
}: {
clothingImg: string;
- link: string;
- price: string;
+ price: number;
+ priceId: string;
title: string;
}) => {
return (
-
-
-
-
-
+
+
+
+
+
+
- {/* Title and Price Section */}
-
-
- {title}
-
-
${price} CAD
-
+ {/* Title and Price Section */}
+
+
+ {title}
+
+
+ {price?.toFixed(2)} CAD
+
+
- {/* Button Section */}
-
-
+
);
};
+
export default MerchItems;
diff --git a/src/components/Merch/MerchPageContent.tsx b/src/components/Merch/MerchPageContent.tsx
index 3c1b2e9..2c9596d 100644
--- a/src/components/Merch/MerchPageContent.tsx
+++ b/src/components/Merch/MerchPageContent.tsx
@@ -1,19 +1,55 @@
+"use client";
+
+import { useState, useEffect } from "react";
import { motion } from "framer-motion";
import { NewlineText } from "../../utility/Helpers";
import { merchPageLottieOptions } from "../../utility/LottieOptions";
import { MerchItems } from "./MerchItems";
-import { MerchItemsData } from "../../lib/data/MerchData";
import dynamic from "next/dynamic";
const Lottie = dynamic(() => import("lottie-react"), { ssr: false });
const MerchPageContent = () => {
+ const [merchItems, setMerchItems] = useState<
+ {
+ id: string;
+ price: number;
+ priceId: string;
+ title: string;
+ clothingImg: string;
+ active: boolean;
+ }[]
+ >([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState
(null);
+
+ // ✅ Fetch merch data when the component loads
+ useEffect(() => {
+ async function fetchMerchData() {
+ try {
+ const response = await fetch("/api/getProducts");
+
+ const data = await response.json();
+ if (!response.ok)
+ throw new Error(data.error || "Failed to load merch data");
+ setMerchItems(data.prices);
+ } catch (err) {
+ setError((err as Error).message);
+ } finally {
+ setLoading(false);
+ }
+ }
+ fetchMerchData();
+ }, []); // Runs only once when component mounts
+
+ if (loading) return Loading merch...
;
+ if (error) return Error: {error}
;
+
return (
- {/* Header Section */}
@@ -21,28 +57,34 @@ const MerchPageContent = () => {
-
{NewlineText("Our Merch")}
-
+
+
+ {JSON.stringify(merchItems)}
+
- {/* Merch Items Grid - Max 3 per row */}
+ {/* Merch Items Grid */}
- {MerchItemsData.map((merchItem) => (
-
-
-
- ))}
+ {merchItems.map(
+ (merchItem) =>
+ merchItem.active ? ( // Check if `active` is true
+
+
+
+ ) : null, // If not active, don't render anything
+ )}
);
diff --git a/src/components/Merch/PaymentButton.tsx b/src/components/Merch/PaymentButton.tsx
new file mode 100644
index 0000000..b6f32e2
--- /dev/null
+++ b/src/components/Merch/PaymentButton.tsx
@@ -0,0 +1,42 @@
+"use client";
+
+import { useState } from "react";
+
+export default function PaymentButton({ priceId }: { priceId: string }) {
+ const [loading, setLoading] = useState(false);
+
+ const handleCheckout = async () => {
+ setLoading(true);
+ try {
+ const res = await fetch("/api/checkout", {
+ body: JSON.stringify({ priceId }), // Send the priceId to the API
+ headers: {
+ "Content-Type": "application/json",
+ },
+ method: "POST",
+ });
+ const data = await res.json();
+
+ if (data.url) {
+ window.location.href = data.url; // Redirect user to Stripe Checkout
+ } else {
+ alert("Failed to create checkout session.");
+ }
+ } catch (error) {
+ console.error("Error:", error);
+ alert("Something went wrong.");
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+ );
+}
diff --git a/src/lib/data/MerchData.ts b/src/lib/data/MerchData.ts
index 908a970..dc018e9 100644
--- a/src/lib/data/MerchData.ts
+++ b/src/lib/data/MerchData.ts
@@ -4,6 +4,7 @@ type MerchItem = {
link: string;
price: string;
title: string;
+ priceId: string;
};
export const MerchItemsData: MerchItem[] = [
@@ -12,6 +13,7 @@ export const MerchItemsData: MerchItem[] = [
id: 0,
link: "https://docs.google.com/forms/d/e/1FAIpQLSfpXS4hisen7IBvMGZnrfYWH600W_vpJwW0-b7blsA-D5Dq2w/viewform",
price: "29.95",
+ priceId: "price_1QuK3UIJ8lAYncJXcSjd0Hkl",
title: "Classic Crew Neck",
},
{
@@ -19,6 +21,7 @@ export const MerchItemsData: MerchItem[] = [
id: 1,
link: "https://docs.google.com/forms/d/e/1FAIpQLSfpXS4hisen7IBvMGZnrfYWH600W_vpJwW0-b7blsA-D5Dq2w/viewform",
price: "49.99",
+ priceId: "price_1QuKSpIJ8lAYncJXBja1aLhU",
title: "Crew Neck with Custom Sleeve Print",
},
];
diff --git a/src/pages/api/checkout.ts b/src/pages/api/checkout.ts
new file mode 100644
index 0000000..a2dba5e
--- /dev/null
+++ b/src/pages/api/checkout.ts
@@ -0,0 +1,47 @@
+import { NextApiRequest, NextApiResponse } from "next";
+import Stripe from "stripe";
+
+// Initialize Stripe
+const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
+
+export default async function handler(
+ req: NextApiRequest,
+ res: NextApiResponse,
+) {
+ if (req.method !== "POST") {
+ return res.status(405).json({ error: "❌ Method Not Allowed" });
+ }
+
+ try {
+ // Extract the priceId from the request body
+ const { priceId } = req.body;
+ if (!priceId) {
+ return res.status(400).json({ error: "Price ID is required" });
+ }
+
+ // Create a Stripe Checkout Session using the provided price ID
+ const session = await stripe.checkout.sessions.create({
+ cancel_url: `${process.env.NEXT_PUBLIC_BASE_URL}/merch`,
+ custom_fields: [
+ {
+ key: "name",
+ label: {
+ custom: "Full Name",
+ type: "custom",
+ },
+ optional: false,
+ type: "text",
+ },
+ ],
+ line_items: [{ price: priceId, quantity: 1 }],
+ mode: "payment",
+ payment_method_types: ["card"],
+ success_url: `${process.env.NEXT_PUBLIC_BASE_URL}/success`,
+ });
+
+ return res.status(200).json({ url: session.url });
+ } catch (error) {
+ console.error("Error creating checkout session:", error);
+ return res.status(500).json({ error: "Internal Server Error" });
+ }
+}
diff --git a/src/pages/api/getProducts.ts b/src/pages/api/getProducts.ts
new file mode 100644
index 0000000..413ef19
--- /dev/null
+++ b/src/pages/api/getProducts.ts
@@ -0,0 +1,69 @@
+import { NextApiRequest, NextApiResponse } from "next";
+import Stripe from "stripe";
+
+if (!process.env.STRIPE_SECRET_KEY) {
+ throw new Error("STRIPE_SECRET_KEY is not set in environment variables.");
+}
+
+const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
+ apiVersion: "2025-02-24.acacia",
+});
+export default async function handler(
+ req: NextApiRequest,
+ res: NextApiResponse,
+) {
+ if (req.method !== "GET") {
+ return res
+ .setHeader("Cache-Control", "no-store")
+ .status(405)
+ .json({ error: "Method Not Allowed" });
+ }
+
+ try {
+ res.setHeader("Cache-Control", "no-store, max-age=0, must-revalidate");
+
+ // Fetch prices from Stripe
+ const prices = await stripe.prices.search({
+ query: 'active:"true"',
+ });
+
+ // Fetch product details for each price entry
+ const productDetails = await Promise.all(
+ prices.data.map(async (price) => {
+ try {
+ const product = await stripe.products.retrieve(
+ price.product as string,
+ );
+
+ return {
+ active: product.active ?? price.active, // Ensure active status is retrieved
+ clothingImg: product.images?.[0] || "/default-image.png",
+ currency: price.currency,
+ id: price.id,
+ price: (price.unit_amount ?? 0) / 100, // Convert cents to dollars
+ priceId: price.id,
+ productId: product.id,
+ title: product.name || "Unknown Product",
+ };
+ } catch (err) {
+ console.error(`Error fetching product ${price.product}:`, err);
+ return {
+ active: price.active, // Ensure active status is still included
+ clothingImg: "/default-image.png",
+ currency: price.currency,
+ id: price.id,
+ price: (price.unit_amount ?? 0) / 100, // Fix incorrect unit amount
+ priceId: price.id,
+ productId: price.product,
+ title: "Error Fetching Product",
+ };
+ }
+ }),
+ );
+
+ return res.status(200).json({ prices: productDetails });
+ } catch (error) {
+ console.error("Stripe API error:", error);
+ return res.status(500).json({ error: "Internal Server Error" });
+ }
+}
diff --git a/src/pages/api/test.ts b/src/pages/api/test.ts
new file mode 100644
index 0000000..0fb6b7d
--- /dev/null
+++ b/src/pages/api/test.ts
@@ -0,0 +1,8 @@
+import type { NextApiRequest, NextApiResponse } from "next";
+
+export default function handler(req: NextApiRequest, res: NextApiResponse) {
+ res.status(200).json({
+ stripeKey: process.env.STRIPE_SECRET_KEY || "Not found",
+ webhookKey: process.env.STRIPE_WEBHOOK_SECRET || "Not found",
+ });
+}
diff --git a/src/pages/success/index.tsx b/src/pages/success/index.tsx
new file mode 100644
index 0000000..5da21a5
--- /dev/null
+++ b/src/pages/success/index.tsx
@@ -0,0 +1,62 @@
+import { motion } from "framer-motion";
+import { FiCheckCircle } from "react-icons/fi";
+import Link from "next/link";
+
+// Common transition properties for all animations
+const commonTransition = {
+ duration: 1,
+ ease: "easeOut",
+};
+
+const SuccessPage = () => {
+ return (
+
+ {/* Animated Icon Intro */}
+
+
+
+
+ {/* Success Message */}
+
+ Payment Successful!
+
+
+ {/* Personalized Thank-You Message */}
+
+ Thank you for supporting TechStart UCalgary. Your transaction has been
+ completed.
+
+
+ {/* Return to Merch Button */}
+
+
+
+
+
+
+ );
+};
+
+export default SuccessPage;
diff --git a/yarn.lock b/yarn.lock
index fe18c5e..ff76088 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -832,6 +832,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/node@npm:>=8.1.0":
+ version: 22.13.4
+ resolution: "@types/node@npm:22.13.4"
+ dependencies:
+ undici-types: "npm:~6.20.0"
+ checksum: 10c0/3a234fa7766a3efc382cf81f66f474c26cdab2f54f43f757634c81c0444eb2160c2dabbde9741e4983078a318a88515b65416b5f1ab5478548579d7b3ead1d95
+ languageName: node
+ linkType: hard
+
"@types/node@npm:^20":
version: 20.16.11
resolution: "@types/node@npm:20.16.11"
@@ -1589,6 +1598,16 @@ __metadata:
languageName: node
linkType: hard
+"call-bind-apply-helpers@npm:^1.0.1":
+ version: 1.0.2
+ resolution: "call-bind-apply-helpers@npm:1.0.2"
+ dependencies:
+ es-errors: "npm:^1.3.0"
+ function-bind: "npm:^1.1.2"
+ checksum: 10c0/47bd9901d57b857590431243fea704ff18078b16890a6b3e021e12d279bbf211d039155e27d7566b374d49ee1f8189344bac9833dec7a20cdec370506361c938
+ languageName: node
+ linkType: hard
+
"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7":
version: 1.0.7
resolution: "call-bind@npm:1.0.7"
@@ -1602,6 +1621,16 @@ __metadata:
languageName: node
linkType: hard
+"call-bound@npm:^1.0.2":
+ version: 1.0.3
+ resolution: "call-bound@npm:1.0.3"
+ dependencies:
+ call-bind-apply-helpers: "npm:^1.0.1"
+ get-intrinsic: "npm:^1.2.6"
+ checksum: 10c0/45257b8e7621067304b30dbd638e856cac913d31e8e00a80d6cf172911acd057846572d0b256b45e652d515db6601e2974a1b1a040e91b4fc36fb3dd86fa69cf
+ languageName: node
+ linkType: hard
+
"callsites@npm:^3.0.0":
version: 3.1.0
resolution: "callsites@npm:3.1.0"
@@ -2060,6 +2089,17 @@ __metadata:
languageName: node
linkType: hard
+"dunder-proto@npm:^1.0.1":
+ version: 1.0.1
+ resolution: "dunder-proto@npm:1.0.1"
+ dependencies:
+ call-bind-apply-helpers: "npm:^1.0.1"
+ es-errors: "npm:^1.3.0"
+ gopd: "npm:^1.2.0"
+ checksum: 10c0/199f2a0c1c16593ca0a145dbf76a962f8033ce3129f01284d48c45ed4e14fea9bbacd7b3610b6cdc33486cef20385ac054948fefc6272fcce645c09468f93031
+ languageName: node
+ linkType: hard
+
"eastasianwidth@npm:^0.2.0":
version: 0.2.0
resolution: "eastasianwidth@npm:0.2.0"
@@ -2207,6 +2247,13 @@ __metadata:
languageName: node
linkType: hard
+"es-define-property@npm:^1.0.1":
+ version: 1.0.1
+ resolution: "es-define-property@npm:1.0.1"
+ checksum: 10c0/3f54eb49c16c18707949ff25a1456728c883e81259f045003499efba399c08bad00deebf65cccde8c0e07908c1a225c9d472b7107e558f2a48e28d530e34527c
+ languageName: node
+ linkType: hard
+
"es-errors@npm:^1.2.1, es-errors@npm:^1.3.0":
version: 1.3.0
resolution: "es-errors@npm:1.3.0"
@@ -2971,6 +3018,34 @@ __metadata:
languageName: node
linkType: hard
+"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6":
+ version: 1.2.7
+ resolution: "get-intrinsic@npm:1.2.7"
+ dependencies:
+ call-bind-apply-helpers: "npm:^1.0.1"
+ es-define-property: "npm:^1.0.1"
+ es-errors: "npm:^1.3.0"
+ es-object-atoms: "npm:^1.0.0"
+ function-bind: "npm:^1.1.2"
+ get-proto: "npm:^1.0.0"
+ gopd: "npm:^1.2.0"
+ has-symbols: "npm:^1.1.0"
+ hasown: "npm:^2.0.2"
+ math-intrinsics: "npm:^1.1.0"
+ checksum: 10c0/b475dec9f8bff6f7422f51ff4b7b8d0b68e6776ee83a753c1d627e3008c3442090992788038b37eff72e93e43dceed8c1acbdf2d6751672687ec22127933080d
+ languageName: node
+ linkType: hard
+
+"get-proto@npm:^1.0.0":
+ version: 1.0.1
+ resolution: "get-proto@npm:1.0.1"
+ dependencies:
+ dunder-proto: "npm:^1.0.1"
+ es-object-atoms: "npm:^1.0.0"
+ checksum: 10c0/9224acb44603c5526955e83510b9da41baf6ae73f7398875fba50edc5e944223a89c4a72b070fcd78beb5f7bdda58ecb6294adc28f7acfc0da05f76a2399643c
+ languageName: node
+ linkType: hard
+
"get-stream@npm:^8.0.1":
version: 8.0.1
resolution: "get-stream@npm:8.0.1"
@@ -3110,6 +3185,13 @@ __metadata:
languageName: node
linkType: hard
+"gopd@npm:^1.2.0":
+ version: 1.2.0
+ resolution: "gopd@npm:1.2.0"
+ checksum: 10c0/50fff1e04ba2b7737c097358534eacadad1e68d24cccee3272e04e007bed008e68d2614f3987788428fd192a5ae3889d08fb2331417e4fc4a9ab366b2043cead
+ languageName: node
+ linkType: hard
+
"graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6":
version: 4.2.11
resolution: "graceful-fs@npm:4.2.11"
@@ -3168,6 +3250,13 @@ __metadata:
languageName: node
linkType: hard
+"has-symbols@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "has-symbols@npm:1.1.0"
+ checksum: 10c0/dde0a734b17ae51e84b10986e651c664379018d10b91b6b0e9b293eddb32f0f069688c841fb40f19e9611546130153e0a2a48fd7f512891fb000ddfa36f5a20e
+ languageName: node
+ linkType: hard
+
"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.2":
version: 1.0.2
resolution: "has-tostringtag@npm:1.0.2"
@@ -3954,6 +4043,13 @@ __metadata:
languageName: node
linkType: hard
+"math-intrinsics@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "math-intrinsics@npm:1.1.0"
+ checksum: 10c0/7579ff94e899e2f76ab64491d76cf606274c874d8f2af4a442c016bd85688927fcfca157ba6bf74b08e9439dc010b248ce05b96cc7c126a354c3bae7fcb48b7f
+ languageName: node
+ linkType: hard
+
"merge-stream@npm:^2.0.0":
version: 2.0.0
resolution: "merge-stream@npm:2.0.0"
@@ -4314,6 +4410,13 @@ __metadata:
languageName: node
linkType: hard
+"object-inspect@npm:^1.13.3":
+ version: 1.13.4
+ resolution: "object-inspect@npm:1.13.4"
+ checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692
+ languageName: node
+ linkType: hard
+
"object-is@npm:^1.1.5":
version: 1.1.6
resolution: "object-is@npm:1.1.6"
@@ -4808,6 +4911,15 @@ __metadata:
languageName: node
linkType: hard
+"qs@npm:^6.11.0":
+ version: 6.14.0
+ resolution: "qs@npm:6.14.0"
+ dependencies:
+ side-channel: "npm:^1.1.0"
+ checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c
+ languageName: node
+ linkType: hard
+
"queue-microtask@npm:^1.2.2":
version: 1.2.3
resolution: "queue-microtask@npm:1.2.3"
@@ -4838,6 +4950,15 @@ __metadata:
languageName: node
linkType: hard
+"react-icons@npm:^5.5.0":
+ version: 5.5.0
+ resolution: "react-icons@npm:5.5.0"
+ peerDependencies:
+ react: "*"
+ checksum: 10c0/a24309bfc993c19cbcbfc928157e53a137851822779977b9588f6dd41ffc4d11ebc98b447f4039b0d309a858f0a42980f6bfb4477fb19f9f2d1bc2e190fcf79c
+ languageName: node
+ linkType: hard
+
"react-intersection-observer@npm:^9.13.1":
version: 9.13.1
resolution: "react-intersection-observer@npm:9.13.1"
@@ -5149,12 +5270,14 @@ __metadata:
react: "npm:^18"
react-countup: "npm:^6.5.3"
react-dom: "npm:^18"
+ react-icons: "npm:^5.5.0"
react-intersection-observer: "npm:^9.13.1"
react-lazy-load-image-component: "npm:^1.6.2"
react-multi-carousel: "npm:^2.8.5"
react-scroll: "npm:^1.9.0"
react-tsparticles: "npm:^2.9.3"
react-visibility-sensor: "npm:^5.1.1"
+ stripe: "npm:^17.7.0"
styled-components: "npm:^6.1.13"
tailwindcss: "npm:^3.4.4"
tsparticles: "npm:^2.9.3"
@@ -5277,6 +5400,41 @@ __metadata:
languageName: node
linkType: hard
+"side-channel-list@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "side-channel-list@npm:1.0.0"
+ dependencies:
+ es-errors: "npm:^1.3.0"
+ object-inspect: "npm:^1.13.3"
+ checksum: 10c0/644f4ac893456c9490ff388bf78aea9d333d5e5bfc64cfb84be8f04bf31ddc111a8d4b83b85d7e7e8a7b845bc185a9ad02c052d20e086983cf59f0be517d9b3d
+ languageName: node
+ linkType: hard
+
+"side-channel-map@npm:^1.0.1":
+ version: 1.0.1
+ resolution: "side-channel-map@npm:1.0.1"
+ dependencies:
+ call-bound: "npm:^1.0.2"
+ es-errors: "npm:^1.3.0"
+ get-intrinsic: "npm:^1.2.5"
+ object-inspect: "npm:^1.13.3"
+ checksum: 10c0/010584e6444dd8a20b85bc926d934424bd809e1a3af941cace229f7fdcb751aada0fb7164f60c2e22292b7fa3c0ff0bce237081fd4cdbc80de1dc68e95430672
+ languageName: node
+ linkType: hard
+
+"side-channel-weakmap@npm:^1.0.2":
+ version: 1.0.2
+ resolution: "side-channel-weakmap@npm:1.0.2"
+ dependencies:
+ call-bound: "npm:^1.0.2"
+ es-errors: "npm:^1.3.0"
+ get-intrinsic: "npm:^1.2.5"
+ object-inspect: "npm:^1.13.3"
+ side-channel-map: "npm:^1.0.1"
+ checksum: 10c0/71362709ac233e08807ccd980101c3e2d7efe849edc51455030327b059f6c4d292c237f94dc0685031dd11c07dd17a68afde235d6cf2102d949567f98ab58185
+ languageName: node
+ linkType: hard
+
"side-channel@npm:^1.0.4, side-channel@npm:^1.0.6":
version: 1.0.6
resolution: "side-channel@npm:1.0.6"
@@ -5289,6 +5447,19 @@ __metadata:
languageName: node
linkType: hard
+"side-channel@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "side-channel@npm:1.1.0"
+ dependencies:
+ es-errors: "npm:^1.3.0"
+ object-inspect: "npm:^1.13.3"
+ side-channel-list: "npm:^1.0.0"
+ side-channel-map: "npm:^1.0.1"
+ side-channel-weakmap: "npm:^1.0.2"
+ checksum: 10c0/cb20dad41eb032e6c24c0982e1e5a24963a28aa6122b4f05b3f3d6bf8ae7fd5474ef382c8f54a6a3ab86e0cac4d41a23bd64ede3970e5bfb50326ba02a7996e6
+ languageName: node
+ linkType: hard
+
"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0":
version: 4.1.0
resolution: "signal-exit@npm:4.1.0"
@@ -5550,6 +5721,16 @@ __metadata:
languageName: node
linkType: hard
+"stripe@npm:^17.7.0":
+ version: 17.7.0
+ resolution: "stripe@npm:17.7.0"
+ dependencies:
+ "@types/node": "npm:>=8.1.0"
+ qs: "npm:^6.11.0"
+ checksum: 10c0/df67c6d455bd0dd87140640924c220fa9581fc00c3267d171f407c8d088f946f61e3ae7e88a89e7dd705b10fd5254630fc943222eb6f003390ebafbd391f81b2
+ languageName: node
+ linkType: hard
+
"styled-components@npm:^6.1.13":
version: 6.1.13
resolution: "styled-components@npm:6.1.13"
@@ -6329,6 +6510,13 @@ __metadata:
languageName: node
linkType: hard
+"undici-types@npm:~6.20.0":
+ version: 6.20.0
+ resolution: "undici-types@npm:6.20.0"
+ checksum: 10c0/68e659a98898d6a836a9a59e6adf14a5d799707f5ea629433e025ac90d239f75e408e2e5ff086afc3cace26f8b26ee52155293564593fbb4a2f666af57fc59bf
+ languageName: node
+ linkType: hard
+
"unique-filename@npm:^3.0.0":
version: 3.0.0
resolution: "unique-filename@npm:3.0.0"