From b29a87e6b90cf73b73552aec965fce5eea8bd580 Mon Sep 17 00:00:00 2001 From: Aiden Suh Date: Tue, 8 Jul 2025 20:18:32 -0400 Subject: [PATCH 1/3] made payment backend logic --- package-lock.json | 70 ++++++++++++++++++-------- package.json | 4 +- src/app/api/checkout_sessions/route.ts | 34 +++++++++++++ 3 files changed, 87 insertions(+), 21 deletions(-) create mode 100644 src/app/api/checkout_sessions/route.ts diff --git a/package-lock.json b/package-lock.json index 0f1e34e..e00ede3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,8 @@ "react-countdown": "^2.3.6", "react-dom": "^19.0.0", "react-icons": "^5.5.0", - "react-intersection-observer": "^9.16.0" + "react-intersection-observer": "^9.16.0", + "stripe": "^18.3.0" }, "devDependencies": { "@eslint/eslintrc": "3.0.0", @@ -27,6 +28,7 @@ "@types/node": "20.0.0", "@types/react": "19.0.0", "@types/react-dom": "19.0.0", + "@types/stripe": "^8.0.416", "autoprefixer": "^10.4.21", "eslint": "9.0.0", "eslint-config-next": "15.2.4", @@ -689,7 +691,7 @@ "version": "20.0.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.0.0.tgz", "integrity": "sha512-cD2uPTDnQQCVpmRefonO98/PPijuOnnEy5oytWJFPY1N9aJCz2wJ5kSGWO+zJoed2cY2JxQh6yBuUq4vIn61hw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/react": { @@ -712,6 +714,16 @@ "@types/react": "*" } }, + "node_modules/@types/stripe": { + "version": "8.0.416", + "resolved": "https://registry.npmjs.org/@types/stripe/-/stripe-8.0.416.tgz", + "integrity": "sha512-LDA574j7g30dg4R+SI1JIpkS+rkIuXgbe6+/qlf62avd7ZNntbbl2DYZwAIj9CfJYVh7FG/PLeoNB5OXTsEehg==", + "dev": true, + "license": "MIT", + "dependencies": { + "stripe": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.29.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.1.tgz", @@ -1399,7 +1411,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -1412,7 +1423,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" @@ -1776,7 +1786,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -1889,7 +1898,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -1898,7 +1906,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -1935,7 +1942,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, "dependencies": { "es-errors": "^1.3.0" }, @@ -2651,7 +2657,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2689,7 +2694,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", @@ -2713,7 +2717,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" @@ -2846,7 +2849,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -2924,7 +2926,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -2951,7 +2952,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -3682,6 +3682,7 @@ "version": "0.525.0", "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.525.0.tgz", "integrity": "sha512-Tm1txJ2OkymCGkvwoHt33Y2JpN5xucVq1slHcgE6Lk0WjDfjgKWor5CdVER8U6DvcfMwh4M8XxmpTiyzfmfDYQ==", + "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } @@ -3700,7 +3701,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -3973,7 +3973,6 @@ "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -4387,6 +4386,21 @@ "node": ">=6" } }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4784,7 +4798,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", @@ -4803,7 +4816,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" @@ -4819,7 +4831,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -4837,7 +4848,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -5123,6 +5133,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stripe": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-18.3.0.tgz", + "integrity": "sha512-FkxrTUUcWB4CVN2yzgsfF/YHD6WgYHduaa7VmokCy5TLCgl5UNJkwortxcedrxSavQ8Qfa4Ir4JxcbIYiBsyLg==", + "license": "MIT", + "dependencies": { + "qs": "^6.11.0" + }, + "engines": { + "node": ">=12.*" + }, + "peerDependencies": { + "@types/node": ">=12.x.x" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, "node_modules/styled-jsx": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", diff --git a/package.json b/package.json index 9a3e1ca..d912957 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "react-countdown": "^2.3.6", "react-dom": "^19.0.0", "react-icons": "^5.5.0", - "react-intersection-observer": "^9.16.0" + "react-intersection-observer": "^9.16.0", + "stripe": "^18.3.0" }, "devDependencies": { "@eslint/eslintrc": "3.0.0", @@ -32,6 +33,7 @@ "@types/node": "20.0.0", "@types/react": "19.0.0", "@types/react-dom": "19.0.0", + "@types/stripe": "^8.0.416", "autoprefixer": "^10.4.21", "eslint": "9.0.0", "eslint-config-next": "15.2.4", diff --git a/src/app/api/checkout_sessions/route.ts b/src/app/api/checkout_sessions/route.ts new file mode 100644 index 0000000..2e39729 --- /dev/null +++ b/src/app/api/checkout_sessions/route.ts @@ -0,0 +1,34 @@ +import { Stripe } from 'stripe'; + +const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); + +export async function POST(request: Request) { + try { + const { name, price, email, ticketName } = await request.json(); + + const session = await stripe.checkout.sessions.create({ + payment_method_types: ['card'], + line_items: [ + { + price_data: { + currency: 'usd', + product_data: { name: ticketName }, + unit_amount: price * 100, // cents + }, + quantity: 1, + }, + ], + mode: 'payment', + customer_email: email, + success_url: `${request.headers.get('origin')}/?success=true&session_id={CHECKOUT_SESSION_ID}`, + cancel_url: `${request.headers.get('origin')}/get_ticket?canceled=true`, + metadata: { customerName: name } + }); + + return new Response(JSON.stringify({ session }), { status: 200 }); + } catch (err) { + console.error(err); + const errorMessage = err instanceof Error ? err.message : 'Internal server error'; + return new Response(JSON.stringify({ error: errorMessage }), { status: 500 }); + } +} \ No newline at end of file From aee05c889fd44dd5479f47913d904112af6bc35e Mon Sep 17 00:00:00 2001 From: Aiden Suh Date: Tue, 8 Jul 2025 20:30:58 -0400 Subject: [PATCH 2/3] chore: update pnpm-lock.yaml to match package.json --- pnpm-lock.yaml | 63 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2e7c63e..660f50e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ dependencies: gsap: specifier: ^3.13.0 version: 3.13.0 + lucide-react: + specifier: ^0.525.0 + version: 0.525.0(react@19.1.0) next: specifier: 15.2.4 version: 15.2.4(react-dom@19.1.0)(react@19.1.0) @@ -35,6 +38,9 @@ dependencies: react-intersection-observer: specifier: ^9.16.0 version: 9.16.0(react-dom@19.1.0)(react@19.1.0) + stripe: + specifier: ^18.3.0 + version: 18.3.0(@types/node@20.0.0) devDependencies: '@eslint/eslintrc': @@ -55,6 +61,9 @@ devDependencies: '@types/react-dom': specifier: 19.0.0 version: 19.0.0 + '@types/stripe': + specifier: ^8.0.416 + version: 8.0.417(@types/node@20.0.0) autoprefixer: specifier: ^10.4.21 version: 10.4.21(postcss@8.5.4) @@ -744,7 +753,6 @@ packages: /@types/node@20.0.0: resolution: {integrity: sha512-cD2uPTDnQQCVpmRefonO98/PPijuOnnEy5oytWJFPY1N9aJCz2wJ5kSGWO+zJoed2cY2JxQh6yBuUq4vIn61hw==} - dev: true /@types/react-dom@19.0.0: resolution: {integrity: sha512-1KfiQKsH1o00p9m5ag12axHQSb3FOU9H20UTrujVSkNhuCrRHiQWFqgEnTNK5ZNfnzZv8UWrnXVqCmCF9fgY3w==} @@ -758,6 +766,15 @@ packages: csstype: 3.1.3 dev: true + /@types/stripe@8.0.417(@types/node@20.0.0): + resolution: {integrity: sha512-PTuqskh9YKNENnOHGVJBm4sM0zE8B1jZw1JIskuGAPkMB+OH236QeN8scclhYGPA4nG6zTtPXgwpXdp+HPDTVw==} + deprecated: This is a stub types definition. stripe provides its own type definitions, so you do not need this installed. + dependencies: + stripe: 18.3.0(@types/node@20.0.0) + transitivePeerDependencies: + - '@types/node' + dev: true + /@typescript-eslint/eslint-plugin@8.33.1(@typescript-eslint/parser@8.33.1)(eslint@9.0.0)(typescript@5.8.3): resolution: {integrity: sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1293,7 +1310,6 @@ packages: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 - dev: true /call-bind@1.0.8: resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} @@ -1311,7 +1327,6 @@ packages: dependencies: call-bind-apply-helpers: 1.0.2 get-intrinsic: 1.3.0 - dev: true /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} @@ -1517,7 +1532,6 @@ packages: call-bind-apply-helpers: 1.0.2 es-errors: 1.3.0 gopd: 1.2.0 - dev: true /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -1606,12 +1620,10 @@ packages: /es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} - dev: true /es-errors@1.3.0: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - dev: true /es-iterator-helpers@1.2.1: resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} @@ -1640,7 +1652,6 @@ packages: engines: {node: '>= 0.4'} dependencies: es-errors: 1.3.0 - dev: true /es-set-tostringtag@2.1.0: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} @@ -2106,7 +2117,6 @@ packages: /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true /function.prototype.name@1.1.8: resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} @@ -2138,7 +2148,6 @@ packages: has-symbols: 1.1.0 hasown: 2.0.2 math-intrinsics: 1.1.0 - dev: true /get-proto@1.0.1: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} @@ -2146,7 +2155,6 @@ packages: dependencies: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 - dev: true /get-symbol-description@1.1.0: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} @@ -2212,7 +2220,6 @@ packages: /gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} - dev: true /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -2252,7 +2259,6 @@ packages: /has-symbols@1.1.0: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} - dev: true /has-tostringtag@1.0.2: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} @@ -2266,7 +2272,6 @@ packages: engines: {node: '>= 0.4'} dependencies: function-bind: 1.1.2 - dev: true /ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} @@ -2751,6 +2756,14 @@ packages: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} dev: true + /lucide-react@0.525.0(react@19.1.0): + resolution: {integrity: sha512-Tm1txJ2OkymCGkvwoHt33Y2JpN5xucVq1slHcgE6Lk0WjDfjgKWor5CdVER8U6DvcfMwh4M8XxmpTiyzfmfDYQ==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + dependencies: + react: 19.1.0 + dev: false + /magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} dependencies: @@ -2760,7 +2773,6 @@ packages: /math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - dev: true /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -2918,7 +2930,6 @@ packages: /object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} - dev: true /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} @@ -3167,6 +3178,12 @@ packages: engines: {node: '>=6'} dev: true + /qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.1.0 + /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true @@ -3420,7 +3437,6 @@ packages: dependencies: es-errors: 1.3.0 object-inspect: 1.13.4 - dev: true /side-channel-map@1.0.1: resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} @@ -3430,7 +3446,6 @@ packages: es-errors: 1.3.0 get-intrinsic: 1.3.0 object-inspect: 1.13.4 - dev: true /side-channel-weakmap@1.0.2: resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} @@ -3441,7 +3456,6 @@ packages: get-intrinsic: 1.3.0 object-inspect: 1.13.4 side-channel-map: 1.0.1 - dev: true /side-channel@1.1.0: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} @@ -3452,7 +3466,6 @@ packages: side-channel-list: 1.0.0 side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 - dev: true /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} @@ -3597,6 +3610,18 @@ packages: engines: {node: '>=8'} dev: true + /stripe@18.3.0(@types/node@20.0.0): + resolution: {integrity: sha512-FkxrTUUcWB4CVN2yzgsfF/YHD6WgYHduaa7VmokCy5TLCgl5UNJkwortxcedrxSavQ8Qfa4Ir4JxcbIYiBsyLg==} + engines: {node: '>=12.*'} + peerDependencies: + '@types/node': '>=12.x.x' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 20.0.0 + qs: 6.14.0 + /styled-jsx@5.1.6(react@19.1.0): resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} engines: {node: '>= 12.0.0'} From e44593bac9a5e090a121826cf2586352d5f4e388 Mon Sep 17 00:00:00 2001 From: Monica Date: Wed, 15 Oct 2025 21:02:20 -0400 Subject: [PATCH 3/3] landing page changes --- src/app/impact/page.tsx | 12 +-- src/app/page.tsx | 18 ++-- src/components/mission.tsx | 13 ++- src/components/nav.tsx | 154 +++++++++++++++++----------- src/components/pastTalks.tsx | 189 ++++++++++++++++++++++++----------- src/components/whatIsTed.tsx | 117 ++++++++++++---------- 6 files changed, 312 insertions(+), 191 deletions(-) diff --git a/src/app/impact/page.tsx b/src/app/impact/page.tsx index 87ae558..18a1cae 100644 --- a/src/app/impact/page.tsx +++ b/src/app/impact/page.tsx @@ -8,16 +8,16 @@ const ImpactPage: React.FC = () => { const isInView = useInView(ref, { once: true }); return ( -
-

+
+ {/*

Our Achievement{" "} in 2024 -

+

*/} { { - if ('scrollRestoration' in window.history) { - window.history.scrollRestoration = 'manual'; + if ("scrollRestoration" in window.history) { + window.history.scrollRestoration = "manual"; } }, []); return (
-
- +
@@ -52,11 +52,11 @@ export default function Home() {
); diff --git a/src/components/mission.tsx b/src/components/mission.tsx index 16e2d74..613d797 100644 --- a/src/components/mission.tsx +++ b/src/components/mission.tsx @@ -49,14 +49,13 @@ export default function Mission() {

Our Mission

-

+


- Dear all, -
-
- To unite the brightest minds within the University of Waterloo - community to create an environment where change-makers can share - their ideas and achievements with the world. + To convene the University of Waterloo community and amplify + Ideas Worth Spreading by creating inclusive platforms where + people from diverse backgrounds, our changemakers, hare their + ideas, achievements, and stories with the world, sparking + conversations that lead to impact

Sincerely, diff --git a/src/components/nav.tsx b/src/components/nav.tsx index c656188..35f8cb6 100644 --- a/src/components/nav.tsx +++ b/src/components/nav.tsx @@ -1,26 +1,30 @@ -'use client' +"use client"; import { useState, useEffect } from "react"; import Link from "next/link"; import { motion, type Variants } from "framer-motion"; interface Nav { - name: string, - path: string, + name: string; + path: string; } const navItems: Nav[] = [ { name: "Home", - path: "/"}, + path: "/", + }, { name: "Speakers", - path: "/speakers"}, + path: "/speakers", + }, { name: "Organizers", - path: "/organizers"}, + path: "/organizers", + }, { name: "Sponsors", - path: "/sponsors"}, + path: "/sponsors", + }, ]; export default function NavBar() { @@ -31,7 +35,7 @@ export default function NavBar() { // Handle mounting effect - useful for client-side animations useEffect(() => { setMounted(true); - + // Add scroll event listener with faster detection threshold const handleScroll = () => { if (window.scrollY > 20) { @@ -40,10 +44,10 @@ export default function NavBar() { setScrolled(false); } }; - - window.addEventListener('scroll', handleScroll); + + window.addEventListener("scroll", handleScroll); return () => { - window.removeEventListener('scroll', handleScroll); + window.removeEventListener("scroll", handleScroll); }; }, []); @@ -54,66 +58,81 @@ export default function NavBar() { // Animation variants const navbarVariants: Variants = { hidden: { y: -100, opacity: 0 }, - visible: { - y: 0, + visible: { + y: 0, opacity: 1, - transition: { - type: "spring", - stiffness: 100, + transition: { + type: "spring", + stiffness: 100, damping: 15, - duration: 0.8 - } - } + duration: 0.8, + }, + }, }; const mobileMenuVariants = { - closed: { + closed: { x: "100%", - transition: { - type: "spring", - stiffness: 300, - damping: 30 - } + transition: { + type: "spring", + stiffness: 300, + damping: 30, + }, }, - open: { + open: { x: 0, - transition: { - type: "spring", - stiffness: 300, - damping: 30 - } - } + transition: { + type: "spring", + stiffness: 300, + damping: 30, + }, + }, }; return (

{/* Mobile View Nav */} - -
+
- logo + logo -
{/* Mobile Menu Popup - using framer motion for slide animation */} -
- logo + logo University of Waterloo
-
- +
{navItems.map((item) => ( - ))}
- - @@ -166,28 +189,41 @@ export default function NavBar() { {/* Desktop View Nav */} -
- logo - {navItems.map(n => ( -
- {n.name} + + logo + + {navItems.map((n) => ( +
+ {n.name}
- ))} + ))}
- - + - @@ -195,4 +231,4 @@ export default function NavBar() {
); -} \ No newline at end of file +} diff --git a/src/components/pastTalks.tsx b/src/components/pastTalks.tsx index 24917d0..e78e6a3 100644 --- a/src/components/pastTalks.tsx +++ b/src/components/pastTalks.tsx @@ -1,27 +1,74 @@ "use client"; -import React, { useState, useEffect, useRef } from 'react' -import Image from 'next/image'; -import PastTalkCard from './pastTalkCard'; -import { motion, AnimatePresence } from 'framer-motion'; +import React, { useState, useEffect, useRef } from "react"; +import Image from "next/image"; +import PastTalkCard from "./pastTalkCard"; +import { motion, AnimatePresence } from "framer-motion"; // Example data: add your real YouTube links, titles, and descriptions const pastTalks = [ - { id: 1, title: 'Success Isn\'t Linear', desc: 'Jordan Howlett', youtube: 'https://www.youtube.com/watch?v=oKN1d6sremo' }, - { id: 2, title: 'I Draw Real World Inspiration from Things I Use to Escape from the Real World', desc: 'Arda Ocal', youtube: 'https://www.youtube.com/watch?v=2CJHCBLAeWo' }, - { id: 3, title: 'AI Will Set Education Back 2500 Years... And That\'s a Good Thing', desc: 'Robert Clapperton', youtube: 'https://www.youtube.com/watch?v=ZcIkF4gLvsc' }, - { id: 4, title: 'Why you need to think like an entrepreneur when it comes to your career', desc: 'Camelia Nunez', youtube: 'https://www.youtube.com/watch?v=KF8ZResRLLs' }, - { id: 5, title: 'Taking Unreasonable Bets', desc: 'Dhananja Jayalath', youtube: 'https://www.youtube.com/watch?v=2Y8Y49nqiN0' }, - { id: 6, title: 'Achieving Excellence: One Choice & Three Practices', desc: 'Anil Gupta', youtube: 'https://www.youtube.com/watch?v=3Ez9Lm-0Qu8' }, - { id: 7, title: 'Why you will fail to have a great career', desc: 'Larry Smith', youtube: 'https://www.youtube.com/watch?v=iKHTawgyKWQ' }, - { id: 8, title: 'A Friend in Debt', desc: 'Patrick Gill', youtube: 'https://www.youtube.com/watch?v=7BNBU484XOE' }, - { id: 9, title: 'Why life is all about REAL connections.', desc: 'Michael Bociurkiw', youtube: 'https://www.youtube.com/watch?v=BXu_V1qfw0I' }, + { + id: 1, + title: "Success Isn't Linear", + desc: "Jordan Howlett", + youtube: "https://www.youtube.com/watch?v=oKN1d6sremo", + }, + { + id: 2, + title: + "I Draw Real World Inspiration from Things I Use to Escape from the Real World", + desc: "Arda Ocal", + youtube: "https://www.youtube.com/watch?v=2CJHCBLAeWo", + }, + { + id: 3, + title: "AI Will Set Education Back 2500 Years... And That's a Good Thing", + desc: "Robert Clapperton", + youtube: "https://www.youtube.com/watch?v=ZcIkF4gLvsc", + }, + { + id: 4, + title: + "Why you need to think like an entrepreneur when it comes to your career", + desc: "Camelia Nunez", + youtube: "https://www.youtube.com/watch?v=KF8ZResRLLs", + }, + { + id: 5, + title: "Taking Unreasonable Bets", + desc: "Dhananja Jayalath", + youtube: "https://www.youtube.com/watch?v=2Y8Y49nqiN0", + }, + { + id: 6, + title: "Achieving Excellence: One Choice & Three Practices", + desc: "Anil Gupta", + youtube: "https://www.youtube.com/watch?v=3Ez9Lm-0Qu8", + }, + { + id: 7, + title: "Why you will fail to have a great career", + desc: "Larry Smith", + youtube: "https://www.youtube.com/watch?v=iKHTawgyKWQ", + }, + { + id: 8, + title: "A Friend in Debt", + desc: "Patrick Gill", + youtube: "https://www.youtube.com/watch?v=7BNBU484XOE", + }, + { + id: 9, + title: "Why life is all about REAL connections.", + desc: "Michael Bociurkiw", + youtube: "https://www.youtube.com/watch?v=BXu_V1qfw0I", + }, ]; const fadeUp = { initial: { opacity: 0, y: 40 }, whileInView: { opacity: 1, y: 0 }, - transition: { duration: 0.6, ease: 'easeOut' } + transition: { duration: 0.6, ease: "easeOut" }, }; const PastTalks: React.FC = () => { @@ -29,7 +76,7 @@ const PastTalks: React.FC = () => { const [direction, setDirection] = useState(0); const [isAnimating, setIsAnimating] = useState(false); const carouselRef = useRef(null); - const autoPlaySpeed = 5000; // 5 seconds per slide + const autoPlaySpeed = 8000; // 8 seconds per slide const totalSlides = Math.ceil(pastTalks.length / 3); // 3 cards per slide // Handle navigation @@ -65,15 +112,15 @@ const PastTalks: React.FC = () => { return (
- {/* Mobile white gradient overlay for title readability */} -
+ {/* White gradient overlay for title readability */} +
{/* Background image */}
Past Talks Background
@@ -91,53 +138,61 @@ const PastTalks: React.FC = () => { Past Talks
- + {/* Carousel */}
-
- setIsAnimating(false)}> +
+ setIsAnimating(false)} + > 0 ? '100%' : direction < 0 ? '-100%' : 0, + x: direction > 0 ? "100%" : direction < 0 ? "-100%" : 0, opacity: 0, - scale: 0.95 + scale: 0.95, }} animate={{ x: 0, opacity: 1, scale: 1, - transition: { - type: "spring", - stiffness: 300, + transition: { + type: "spring", + stiffness: 300, damping: 30, opacity: { duration: 0.2, ease: "easeOut" }, - } + }, }} exit={{ - x: direction < 0 ? '100%' : direction > 0 ? '-100%' : 0, + x: direction < 0 ? "100%" : direction > 0 ? "-100%" : 0, opacity: 0, scale: 0.95, - transition: { - duration: 0.4, - ease: [0.32, 0.72, 0, 1] // Custom easing curve for smooth exit - } + transition: { + duration: 0.4, + ease: [0.32, 0.72, 0, 1], // Custom easing curve for smooth exit + }, }} className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6 w-full h-full" > {slides[currentIndex].map((talk, i) => ( - @@ -149,44 +204,66 @@ const PastTalks: React.FC = () => {
{/* Navigation Buttons */} - - - + + - - - + + {/* Dots navigation */} -
+
{Array.from({ length: totalSlides }).map((_, i) => ( { if (isAnimating) return; @@ -194,7 +271,7 @@ const PastTalks: React.FC = () => { setDirection(i > currentIndex ? 1 : -1); setCurrentIndex(i); }} - className="h-3 mx-1 rounded-full focus:outline-none hover:bg-gray-400" + className="h-4 rounded-full focus:outline-none hover:bg-gray-600 transition-colors shadow-md" aria-label={`Go to slide ${i + 1}`} /> ))} @@ -209,7 +286,7 @@ const PastTalks: React.FC = () => { viewport={{ once: true }} >
- and{' '} + and{" "} { @@ -13,7 +13,7 @@ const WhatIsTed = () => { { {/* Enhanced decorative lines with animations */}
{/* Top left lines */} - - {/* Top right lines */} - {/* Middle left/right lines */} - - {/* Bottom left/right lines */} - - {/* Random red lines */} - - - {
{/* Title and Description */} - - - What is TEDxUW? + What is TED + xUW? - - - Founded in 2011, TEDxUW is the University of Waterloo's official TEDx experience. We aim to put the extended UW community onto a new type of global activity map that is being watched, shared, and talked about by the world's top thought leaders. + Founded in 2011, TEDxUW is the University of Waterloo's official + TEDx experience. We aim to put the extended UW community onto a new + type of global activity map that is being watched, shared, and talked + about by the world's top thought leaders. - + {/* Enhanced presenter image positioning */} {/*
{
*/} - + {/* Mobile presenter image */} - { {/* Enhanced Impact Text */} - { >

- With many of our Talks published on TED.com, YouTube, and other websites, TEDxUW continually triggers innovation in all corners of the globe beyond our conference date. + Many of our talks are shared on the TEDx Talks YouTube channel and + other platforms, helping the ideas from TEDxUW reach new audiences + and continue the conversation long after the event.

{/* Enhanced Interest Text */} -

- We got you interested?
- Buy our ticket today! + We got you interested? +
+ + Buy our ticket today! +

{/* Enhanced Red Trapezoid Buy Ticket Bar */} -
@@ -234,4 +243,4 @@ const WhatIsTed = () => { ); }; -export default WhatIsTed; \ No newline at end of file +export default WhatIsTed;