From 4aea7ca68c410399e99a08c9c9d6c9f92382751e Mon Sep 17 00:00:00 2001 From: Kevin Satria D <130447401+kevinnsd1@users.noreply.github.com> Date: Wed, 20 May 2026 15:27:22 +0700 Subject: [PATCH] feat: implement core event ticketing navigation, detailed event pages, checkout flow, and QR code integration. --- assets/image/logo/awh.png | Bin 0 -> 5781 bytes package-lock.json | 59 ++++++++++++- package.json | 1 + src/App.tsx | 4 + src/components/Hero.tsx | 18 ++-- src/pages/Checkout.tsx | 178 ++++++++++++++++++++++++++++++++++++++ src/pages/EventDetail.tsx | 76 ++++++++++++---- src/pages/Payment.tsx | 127 +++++++++++++++++++++++++++ 8 files changed, 435 insertions(+), 28 deletions(-) create mode 100644 assets/image/logo/awh.png create mode 100644 src/pages/Checkout.tsx create mode 100644 src/pages/Payment.tsx diff --git a/assets/image/logo/awh.png b/assets/image/logo/awh.png new file mode 100644 index 0000000000000000000000000000000000000000..6aedb31ccfb858565c359ae89bf3e0f9934a7bf3 GIT binary patch literal 5781 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.10.0" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -3493,6 +3514,17 @@ "node": ">= 0.8.0" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3503,6 +3535,12 @@ "node": ">=6" } }, + "node_modules/qr.js": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", + "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==", + "license": "MIT" + }, "node_modules/react": { "version": "19.2.6", "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", @@ -3524,6 +3562,25 @@ "react": "^19.2.6" } }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-qr-code": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.21.tgz", + "integrity": "sha512-xaywjo0eaF4S3LOz6ns5eoPbM2E+q9HYl4VATYpxK4bBniOhQ9noY2RJ9G4SnZFhUwzx63FUT6KdHzfKgUwyuQ==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1", + "qr.js": "0.0.0" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", diff --git a/package.json b/package.json index 0425926..133b098 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "lucide-react": "^0.475.0", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-qr-code": "^2.0.21", "react-router-dom": "^7.15.1" }, "devDependencies": { diff --git a/src/App.tsx b/src/App.tsx index a305aa9..adebf66 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,6 +5,8 @@ import Footer from './components/Footer'; import Home from './pages/Home'; import AllEvents from './pages/AllEvents'; import EventDetail from './pages/EventDetail'; +import Checkout from './pages/Checkout'; +import Payment from './pages/Payment'; function ScrollToTop() { const { pathname } = useLocation(); @@ -28,6 +30,8 @@ function App() { } /> } /> } /> + } /> + } /> diff --git a/src/components/Hero.tsx b/src/components/Hero.tsx index 3a2b739..4a295f2 100644 --- a/src/components/Hero.tsx +++ b/src/components/Hero.tsx @@ -5,15 +5,15 @@ import { Search } from "lucide-react"; const SLIDES = [ { id: 1, - videoId: "Fpn1imb9qZg", + videoUrl: "https://videos.pexels.com/video-files/3253245/3253245-uhd_2560_1440_25fps.mp4", }, { id: 2, - videoId: "PN7Pv23FrWg", + videoUrl: "https://videos.pexels.com/video-files/2086119/2086119-uhd_2560_1440_24fps.mp4", }, { id: 3, - videoId: "YsJqKjD2sXE", + videoUrl: "https://videos.pexels.com/video-files/3163534/3163534-uhd_2560_1440_30fps.mp4", }, ]; @@ -71,16 +71,18 @@ export default function Hero() {
{SLIDES.map((slide, idx) => ( -