From cfcc4c480e6f37c7321c2857a6f0aa3c6ca645f0 Mon Sep 17 00:00:00 2001 From: Sean S Date: Sun, 29 Jun 2025 07:12:20 -0400 Subject: [PATCH] first commit --- package-lock.json | 1625 +++++++++++++++++----------- package.json | 13 +- postcss.config.js | 6 + postcss.config.mjs | 5 - src/app/api/products/route.ts | 7 + src/app/build/page.tsx | 574 ++++++++++ src/app/builds/page.tsx | 430 ++++++++ src/app/components/productCard.tsx | 26 + src/app/globals.css | 29 +- src/app/layout.tsx | 18 +- src/app/page.tsx | 973 +++++++++++++++-- src/app/products/page.tsx | 27 + src/components/Navbar.tsx | 82 ++ src/mock/product.ts | 48 + src/mock/products.ts | 48 + tailwind.config.js | 12 + 16 files changed, 3156 insertions(+), 767 deletions(-) create mode 100644 postcss.config.js delete mode 100644 postcss.config.mjs create mode 100644 src/app/api/products/route.ts create mode 100644 src/app/build/page.tsx create mode 100644 src/app/builds/page.tsx create mode 100644 src/app/components/productCard.tsx create mode 100644 src/app/products/page.tsx create mode 100644 src/components/Navbar.tsx create mode 100644 src/mock/product.ts create mode 100644 src/mock/products.ts create mode 100644 tailwind.config.js diff --git a/package-lock.json b/package-lock.json index de08ebc..f2ad914 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,13 +14,14 @@ }, "devDependencies": { "@eslint/eslintrc": "^3", - "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", + "autoprefixer": "^10.4.21", "eslint": "^9", "eslint-config-next": "15.3.4", - "tailwindcss": "^4", + "postcss": "^8.5.6", + "tailwindcss": "^3.4.4", "typescript": "^5" } }, @@ -37,20 +38,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@emnapi/core": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", @@ -700,17 +687,22 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^7.0.4" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=12" } }, "node_modules/@jridgewell/gen-mapping": { @@ -971,6 +963,17 @@ "node": ">=12.4.0" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1000,282 +1003,6 @@ "tslib": "^2.8.0" } }, - "node_modules/@tailwindcss/node": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", - "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.3.0", - "enhanced-resolve": "^5.18.1", - "jiti": "^2.4.2", - "lightningcss": "1.30.1", - "magic-string": "^0.30.17", - "source-map-js": "^1.2.1", - "tailwindcss": "4.1.11" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", - "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.4", - "tar": "^7.4.3" - }, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.11", - "@tailwindcss/oxide-darwin-arm64": "4.1.11", - "@tailwindcss/oxide-darwin-x64": "4.1.11", - "@tailwindcss/oxide-freebsd-x64": "4.1.11", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", - "@tailwindcss/oxide-linux-x64-musl": "4.1.11", - "@tailwindcss/oxide-wasm32-wasi": "4.1.11", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", - "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", - "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", - "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", - "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", - "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", - "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", - "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", - "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", - "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", - "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@emnapi/wasi-threads": "^1.0.2", - "@napi-rs/wasm-runtime": "^0.2.11", - "@tybys/wasm-util": "^0.9.0", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", - "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", - "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/postcss": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.11.tgz", - "integrity": "sha512-q/EAIIpF6WpLhKEuQSEVMZNMIY8KhWoAemZ9eylNAih9jxMGAYPPWBn3I9QL/2jZ+e7OEz/tZkX5HwbBR4HohA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.1.11", - "@tailwindcss/oxide": "4.1.11", - "postcss": "^8.4.41", - "tailwindcss": "4.1.11" - } - }, "node_modules/@tybys/wasm-util": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", @@ -1934,6 +1661,19 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1950,6 +1690,34 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2144,6 +1912,44 @@ "node": ">= 0.4" } }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -2187,6 +1993,19 @@ "dev": true, "license": "MIT" }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -2211,6 +2030,39 @@ "node": ">=8" } }, + "node_modules/browserslist": { + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -2282,6 +2134,16 @@ "node": ">=6" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001726", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", @@ -2319,14 +2181,42 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, "engines": { - "node": ">=18" + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/client-only": { @@ -2380,6 +2270,16 @@ "simple-swizzle": "^0.2.2" } }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2402,6 +2302,19 @@ "node": ">= 8" } }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -2535,12 +2448,26 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", - "devOptional": true, "license": "Apache-2.0", + "optional": true, "engines": { "node": ">=8" } }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -2569,6 +2496,20 @@ "node": ">= 0.4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.177", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.177.tgz", + "integrity": "sha512-7EH2G59nLsEMj97fpDuvVcYi6lwTcM1xuWw3PssD8xzboAW7zj7iB3COEEEATUfjLHrs5uKBLQT03V/8URx06g==", + "dev": true, + "license": "ISC" + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -2576,20 +2517,6 @@ "dev": true, "license": "MIT" }, - "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/es-abstract": { "version": "1.24.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", @@ -2767,6 +2694,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -3347,6 +3284,52 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -3458,6 +3441,27 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -3471,6 +3475,32 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -3514,13 +3544,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -3735,6 +3758,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", @@ -3852,6 +3888,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-generator-function": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", @@ -4114,12 +4160,30 @@ "node": ">= 0.4" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jiti": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -4238,244 +4302,22 @@ "node": ">= 0.8.0" } }, - "node_modules/lightningcss": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, + "license": "MIT", "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-darwin-arm64": "1.30.1", - "lightningcss-darwin-x64": "1.30.1", - "lightningcss-freebsd-x64": "1.30.1", - "lightningcss-linux-arm-gnueabihf": "1.30.1", - "lightningcss-linux-arm64-gnu": "1.30.1", - "lightningcss-linux-arm64-musl": "1.30.1", - "lightningcss-linux-x64-gnu": "1.30.1", - "lightningcss-linux-x64-musl": "1.30.1", - "lightningcss-win32-arm64-msvc": "1.30.1", - "lightningcss-win32-x64-msvc": "1.30.1" + "node": ">=10" } }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", - "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", - "cpu": [ - "arm64" - ], + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", - "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", - "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", - "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", - "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", - "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", - "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", - "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", - "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "license": "MIT" }, "node_modules/locate-path": { "version": "6.0.0", @@ -4513,15 +4355,12 @@ "loose-envify": "cli.js" } }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } + "license": "ISC" }, "node_modules/math-intrinsics": { "version": "1.1.0", @@ -4590,35 +4429,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4626,6 +4436,18 @@ "dev": true, "license": "MIT" }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -4749,6 +4571,33 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4759,6 +4608,16 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -4940,6 +4799,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4980,6 +4846,23 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -4999,6 +4882,26 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -5038,6 +4941,91 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5119,6 +5107,29 @@ "dev": true, "license": "MIT" }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -5503,6 +5514,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -5551,6 +5575,70 @@ "node": ">=10.0.0" } }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.includes": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", @@ -5664,6 +5752,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -5710,6 +5838,29 @@ } } }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5737,38 +5888,123 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", - "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", + "integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/tapable": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "node_modules/tailwindcss/node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/tailwindcss/node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/tailwindcss/node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, - "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" }, "engines": { - "node": ">=18" + "node": ">=0.8" } }, "node_modules/tinyglobby": { @@ -5842,6 +6078,13 @@ "typescript": ">=4.8.4" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -6027,6 +6270,37 @@ "@unrs/resolver-binding-win32-x64-msvc": "1.9.2" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -6037,6 +6311,13 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6152,14 +6433,112 @@ "node": ">=0.10.0" } }, - "node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/yaml": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" } }, "node_modules/yocto-queue": { diff --git a/package.json b/package.json index 95d8e95..26682c0 100644 --- a/package.json +++ b/package.json @@ -9,19 +9,20 @@ "lint": "next lint" }, "dependencies": { + "next": "15.3.4", "react": "^19.0.0", - "react-dom": "^19.0.0", - "next": "15.3.4" + "react-dom": "^19.0.0" }, "devDependencies": { - "typescript": "^5", + "@eslint/eslintrc": "^3", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "@tailwindcss/postcss": "^4", - "tailwindcss": "^4", + "autoprefixer": "^10.4.21", "eslint": "^9", "eslint-config-next": "15.3.4", - "@eslint/eslintrc": "^3" + "postcss": "^8.5.6", + "tailwindcss": "^3.4.4", + "typescript": "^5" } } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..8567b4c --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; \ No newline at end of file diff --git a/postcss.config.mjs b/postcss.config.mjs deleted file mode 100644 index c7bcb4b..0000000 --- a/postcss.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -const config = { - plugins: ["@tailwindcss/postcss"], -}; - -export default config; diff --git a/src/app/api/products/route.ts b/src/app/api/products/route.ts new file mode 100644 index 0000000..bf4a5a2 --- /dev/null +++ b/src/app/api/products/route.ts @@ -0,0 +1,7 @@ +import { NextResponse } from 'next/server'; + +export async function GET() { + const res = await fetch('http://localhost:8080/api/products'); // <-- your Spring backend endpoint + const data = await res.json(); + return NextResponse.json(data); +} \ No newline at end of file diff --git a/src/app/build/page.tsx b/src/app/build/page.tsx new file mode 100644 index 0000000..afc3543 --- /dev/null +++ b/src/app/build/page.tsx @@ -0,0 +1,574 @@ +'use client'; + +import { useState } from 'react'; +import Link from 'next/link'; +import React from 'react'; + +// AR-15 Build Requirements grouped by main categories +const buildGroups = [ + { + name: 'Upper Parts', + description: 'Components that make up the upper receiver assembly', + components: [ + { + id: 'upper-receiver', + name: 'Upper Receiver', + category: 'Upper', + description: 'The upper receiver houses the barrel, bolt carrier group, and charging handle', + required: true, + status: 'pending', + estimatedPrice: 150, + notes: 'Can be purchased as complete upper or stripped' + }, + { + id: 'barrel', + name: 'Barrel', + category: 'Upper', + description: 'The barrel determines accuracy and caliber compatibility', + required: true, + status: 'pending', + estimatedPrice: 200, + notes: 'Common lengths: 16", 18", 20"' + }, + { + id: 'bolt-carrier-group', + name: 'Bolt Carrier Group (BCG)', + category: 'Upper', + description: 'Handles the firing, extraction, and ejection of rounds', + required: true, + status: 'pending', + estimatedPrice: 150, + notes: 'Mil-spec or enhanced options available' + }, + { + id: 'charging-handle', + name: 'Charging Handle', + category: 'Upper', + description: 'Allows manual operation of the bolt carrier group', + required: true, + status: 'pending', + estimatedPrice: 50, + notes: 'Standard or ambidextrous options' + }, + { + id: 'gas-block', + name: 'Gas Block', + category: 'Upper', + description: 'Controls gas flow from barrel to BCG', + required: true, + status: 'pending', + estimatedPrice: 30, + notes: 'Low-profile for free-float handguards' + }, + { + id: 'gas-tube', + name: 'Gas Tube', + category: 'Upper', + description: 'Transfers gas from barrel to BCG', + required: true, + status: 'pending', + estimatedPrice: 15, + notes: 'Carbine, mid-length, or rifle length' + }, + { + id: 'handguard', + name: 'Handguard', + category: 'Upper', + description: 'Provides grip and mounting points for accessories', + required: true, + status: 'pending', + estimatedPrice: 100, + notes: 'Free-float or drop-in options' + }, + { + id: 'muzzle-device', + name: 'Muzzle Device', + category: 'Upper', + description: 'Flash hider, compensator, or suppressor mount', + required: true, + status: 'pending', + estimatedPrice: 80, + notes: 'A2 flash hider is standard' + } + ] + }, + { + name: 'Lower Parts', + description: 'Components that make up the lower receiver assembly', + components: [ + { + id: 'lower-receiver', + name: 'Lower Receiver', + category: 'Lower', + description: 'The lower receiver contains the trigger group and magazine well', + required: true, + status: 'pending', + estimatedPrice: 100, + notes: 'Must be purchased through FFL dealer' + }, + { + id: 'trigger', + name: 'Trigger', + category: 'Lower', + description: 'Controls firing mechanism', + required: true, + status: 'pending', + estimatedPrice: 60, + notes: 'Mil-spec or enhanced triggers available' + }, + { + id: 'trigger-guard', + name: 'Trigger Guard', + category: 'Lower', + description: 'Protects trigger from accidental discharge', + required: true, + status: 'pending', + estimatedPrice: 10, + notes: 'Often included with lower receiver' + }, + { + id: 'pistol-grip', + name: 'Pistol Grip', + category: 'Lower', + description: 'Provides grip for firing hand', + required: true, + status: 'pending', + estimatedPrice: 25, + notes: 'Various ergonomic options available' + }, + { + id: 'buffer-tube', + name: 'Buffer Tube', + category: 'Lower', + description: 'Houses buffer and spring for recoil management', + required: true, + status: 'pending', + estimatedPrice: 40, + notes: 'Carbine, A5, or rifle length' + }, + { + id: 'buffer', + name: 'Buffer', + category: 'Lower', + description: 'Absorbs recoil energy', + required: true, + status: 'pending', + estimatedPrice: 20, + notes: 'H1, H2, H3 weights available' + }, + { + id: 'buffer-spring', + name: 'Buffer Spring', + category: 'Lower', + description: 'Returns BCG to battery position', + required: true, + status: 'pending', + estimatedPrice: 15, + notes: 'Standard or enhanced springs' + }, + { + id: 'stock', + name: 'Stock', + category: 'Lower', + description: 'Provides shoulder support and cheek weld', + required: true, + status: 'pending', + estimatedPrice: 60, + notes: 'Fixed or adjustable options' + } + ] + }, + { + name: 'Accessories', + description: 'Additional components needed for a complete build', + components: [ + { + id: 'magazine', + name: 'Magazine', + category: 'Accessory', + description: 'Holds and feeds ammunition', + required: true, + status: 'pending', + estimatedPrice: 15, + notes: '30-round capacity is standard' + }, + { + id: 'sights', + name: 'Sights', + category: 'Accessory', + description: 'Iron sights or optic for aiming', + required: true, + status: 'pending', + estimatedPrice: 100, + notes: 'Backup iron sights recommended' + } + ] + } +]; + +// Flatten all components for filtering and sorting +const allComponents = buildGroups.flatMap(group => group.components); + +const categories = ["All", "Upper", "Lower", "Accessory"]; + +type SortField = 'name' | 'category' | 'estimatedPrice' | 'status'; +type SortDirection = 'asc' | 'desc'; + +export default function BuildPage() { + const [sortField, setSortField] = useState('name'); + const [sortDirection, setSortDirection] = useState('asc'); + const [selectedCategory, setSelectedCategory] = useState('All'); + const [searchTerm, setSearchTerm] = useState(''); + + // Filter components + const filteredComponents = allComponents.filter(component => { + if (selectedCategory !== 'All' && component.category !== selectedCategory) { + return false; + } + + if (searchTerm && !component.name.toLowerCase().includes(searchTerm.toLowerCase()) && + !component.description.toLowerCase().includes(searchTerm.toLowerCase())) { + return false; + } + + return true; + }); + + // Sort components + const sortedComponents = [...filteredComponents].sort((a, b) => { + let aValue: any, bValue: any; + + if (sortField === 'estimatedPrice') { + aValue = a.estimatedPrice; + bValue = b.estimatedPrice; + } else if (sortField === 'category') { + aValue = a.category.toLowerCase(); + bValue = b.category.toLowerCase(); + } else if (sortField === 'status') { + aValue = a.status.toLowerCase(); + bValue = b.status.toLowerCase(); + } else { + aValue = a.name.toLowerCase(); + bValue = b.name.toLowerCase(); + } + + if (sortDirection === 'asc') { + return aValue > bValue ? 1 : -1; + } else { + return aValue < bValue ? 1 : -1; + } + }); + + const handleSort = (field: SortField) => { + if (sortField === field) { + setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc'); + } else { + setSortField(field); + setSortDirection('asc'); + } + }; + + const getSortIcon = (field: SortField) => { + if (sortField !== field) { + return '↕️'; + } + return sortDirection === 'asc' ? '↑' : '↓'; + }; + + const getStatusColor = (status: string) => { + switch (status) { + case 'completed': + return 'bg-green-100 text-green-800'; + case 'pending': + return 'bg-yellow-100 text-yellow-800'; + case 'in-progress': + return 'bg-blue-100 text-blue-800'; + default: + return 'bg-gray-100 text-gray-800'; + } + }; + + const totalEstimatedCost = sortedComponents.reduce((sum, component) => sum + component.estimatedPrice, 0); + const completedCount = sortedComponents.filter(component => component.status === 'completed').length; + + const hasActiveFilters = selectedCategory !== 'All' || searchTerm; + + return ( +
+ {/* Page Title */} +
+
+

AR-15 Build Checklist

+

Track your build progress and find required components

+
+
+ + {/* Build Summary */} +
+
+
+
+
{allComponents.length}
+
Total Components
+
+
+
{completedCount}
+
Completed
+
+
+
{allComponents.length - completedCount}
+
Remaining
+
+
+
${totalEstimatedCost}
+
Estimated Cost
+
+
+
+
+ + {/* Search and Filters */} +
+
+ {/* Search Row */} +
+
+ + setSearchTerm(e.target.value)} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + /> +
+
+ + {/* Filters Row */} +
+ {/* Category Dropdown */} +
+ + +
+ + {/* Status Filter */} +
+ + +
+ + {/* Sort by */} +
+ + +
+ + {/* Clear Filters */} +
+ +
+
+
+
+ + {/* Build Components Table */} +
+
+
+ + + + + + + + + + + + + + {sortedComponents.length > 0 ? ( + buildGroups.map((group) => { + // Filter components in this group that match current filters + const groupComponents = group.components.filter(component => + sortedComponents.some(sorted => sorted.id === component.id) + ); + + if (groupComponents.length === 0) return null; + + return ( + + {/* Group Header */} + + + + + {/* Group Components */} + {groupComponents.map((component) => ( + + + + + + + + + + ))} + + ); + }) + ) : ( + + + + )} + +
+ Status + handleSort('name')} + > +
+ Component + {getSortIcon('name')} +
+
handleSort('category')} + > +
+ Category + {getSortIcon('category')} +
+
+ Description + handleSort('estimatedPrice')} + > +
+ Est. Price + {getSortIcon('estimatedPrice')} +
+
+ Notes + + Actions +
+
+
+
+ + {group.name === 'Upper Parts' ? '🔫' : + group.name === 'Lower Parts' ? '🔧' : '📦'} + +
+
+
+

{group.name}

+

{group.description}

+
+
+
+ {groupComponents.length} components +
+
+
+
+ + {component.status} + + +
+ {component.name} +
+
+ {component.required ? 'Required' : 'Optional'} +
+
+ + {component.category} + + +
+ {component.description} +
+
+
+ ${component.estimatedPrice} +
+
+
+ {component.notes} +
+
+
+ + Find Parts + + +
+
+
+
No components found
+
Try adjusting your filters or search terms
+
+
+
+ + {/* Table Footer */} +
+
+
+ Showing {sortedComponents.length} of {allComponents.length} components + {hasActiveFilters && ( + + (filtered) + + )} +
+
+ Total Value: ${sortedComponents.reduce((sum, component) => sum + component.estimatedPrice, 0).toFixed(2)} +
+
+
+
+
+
+ ); +} \ No newline at end of file diff --git a/src/app/builds/page.tsx b/src/app/builds/page.tsx new file mode 100644 index 0000000..c05ac20 --- /dev/null +++ b/src/app/builds/page.tsx @@ -0,0 +1,430 @@ +'use client'; + +import { useState } from 'react'; + +// Sample build data +const sampleBuilds = [ + { + id: '1', + name: 'Budget AR-15 Build', + description: 'A cost-effective AR-15 build using quality budget components', + status: 'completed' as const, + totalCost: 847.50, + completedDate: '2024-01-15', + components: { + total: 18, + completed: 18, + categories: { + 'Upper': 8, + 'Lower': 7, + 'Accessory': 3 + } + }, + tags: ['Budget', '5.56 NATO', '16" Barrel'], + image: 'https://picsum.photos/400/250?random=1' + }, + { + id: '2', + name: 'Precision Long Range', + description: 'High-end precision build optimized for long-range accuracy', + status: 'in-progress' as const, + totalCost: 2847.99, + startedDate: '2024-02-01', + components: { + total: 18, + completed: 12, + categories: { + 'Upper': 6, + 'Lower': 4, + 'Accessory': 2 + } + }, + tags: ['Precision', '6.5 Creedmoor', '20" Barrel'], + image: 'https://picsum.photos/400/250?random=2' + }, + { + id: '3', + name: 'Home Defense Setup', + description: 'Compact AR-15 configured for home defense scenarios', + status: 'planning' as const, + totalCost: 0, + plannedDate: '2024-03-01', + components: { + total: 18, + completed: 0, + categories: { + 'Upper': 0, + 'Lower': 0, + 'Accessory': 0 + } + }, + tags: ['Home Defense', '5.56 NATO', '10.5" Barrel'], + image: 'https://picsum.photos/400/250?random=3' + }, + { + id: '4', + name: 'Competition Rifle', + description: 'Lightweight competition build for 3-gun matches', + status: 'completed' as const, + totalCost: 1650.75, + completedDate: '2023-12-10', + components: { + total: 18, + completed: 18, + categories: { + 'Upper': 8, + 'Lower': 7, + 'Accessory': 3 + } + }, + tags: ['Competition', '5.56 NATO', '18" Barrel'], + image: 'https://picsum.photos/400/250?random=4' + }, + { + id: '5', + name: 'Suppressed SBR', + description: 'Short-barreled rifle build with suppressor integration', + status: 'in-progress' as const, + totalCost: 1895.25, + startedDate: '2024-01-20', + components: { + total: 18, + completed: 8, + categories: { + 'Upper': 4, + 'Lower': 3, + 'Accessory': 1 + } + }, + tags: ['SBR', 'Suppressed', '300 BLK'], + image: 'https://picsum.photos/400/250?random=5' + }, + { + id: '6', + name: 'Retro M16A1 Clone', + description: 'Faithful reproduction of the classic M16A1 rifle', + status: 'planning' as const, + totalCost: 0, + plannedDate: '2024-04-01', + components: { + total: 18, + completed: 0, + categories: { + 'Upper': 0, + 'Lower': 0, + 'Accessory': 0 + } + }, + tags: ['Retro', '5.56 NATO', '20" Barrel'], + image: 'https://picsum.photos/400/250?random=6' + } +]; + +type BuildStatus = 'completed' | 'in-progress' | 'planning'; +type SortField = 'name' | 'status' | 'totalCost' | 'completedDate'; +type SortDirection = 'asc' | 'desc'; + +export default function BuildsPage() { + const [sortField, setSortField] = useState('completedDate'); + const [sortDirection, setSortDirection] = useState('desc'); + const [selectedStatus, setSelectedStatus] = useState('all'); + const [searchTerm, setSearchTerm] = useState(''); + + // Filter builds + const filteredBuilds = sampleBuilds.filter(build => { + if (selectedStatus !== 'all' && build.status !== selectedStatus) { + return false; + } + + if (searchTerm && !build.name.toLowerCase().includes(searchTerm.toLowerCase()) && + !build.description.toLowerCase().includes(searchTerm.toLowerCase())) { + return false; + } + + return true; + }); + + // Sort builds + const sortedBuilds = [...filteredBuilds].sort((a, b) => { + let aValue: any, bValue: any; + + if (sortField === 'totalCost') { + aValue = a.totalCost; + bValue = b.totalCost; + } else if (sortField === 'status') { + aValue = a.status; + bValue = b.status; + } else if (sortField === 'completedDate') { + aValue = a.completedDate || a.startedDate || a.plannedDate || ''; + bValue = b.completedDate || b.startedDate || b.plannedDate || ''; + } else { + aValue = a.name.toLowerCase(); + bValue = b.name.toLowerCase(); + } + + if (sortDirection === 'asc') { + return aValue > bValue ? 1 : -1; + } else { + return aValue < bValue ? 1 : -1; + } + }); + + const getStatusColor = (status: BuildStatus) => { + switch (status) { + case 'completed': + return 'bg-green-100 text-green-800'; + case 'in-progress': + return 'bg-blue-100 text-blue-800'; + case 'planning': + return 'bg-yellow-100 text-yellow-800'; + default: + return 'bg-gray-100 text-gray-800'; + } + }; + + const getStatusIcon = (status: BuildStatus) => { + switch (status) { + case 'completed': + return '✓'; + case 'in-progress': + return '🔄'; + case 'planning': + return '📋'; + default: + return '❓'; + } + }; + + const formatDate = (dateString: string) => { + return new Date(dateString).toLocaleDateString('en-US', { + year: 'numeric', + month: 'short', + day: 'numeric' + }); + }; + + const getProgressPercentage = (build: typeof sampleBuilds[0]) => { + return Math.round((build.components.completed / build.components.total) * 100); + }; + + const totalBuilds = sampleBuilds.length; + const completedBuilds = sampleBuilds.filter(build => build.status === 'completed').length; + const inProgressBuilds = sampleBuilds.filter(build => build.status === 'in-progress').length; + const totalValue = sampleBuilds.reduce((sum, build) => sum + build.totalCost, 0); + + return ( +
+ {/* Page Title */} +
+
+

My Builds

+

Track and manage your firearm builds

+
+
+ + {/* Build Summary */} +
+
+
+
+
{totalBuilds}
+
Total Builds
+
+
+
{completedBuilds}
+
Completed
+
+
+
{inProgressBuilds}
+
In Progress
+
+
+
${totalValue.toFixed(2)}
+
Total Value
+
+
+
+
+ + {/* Search and Filters */} +
+
+ {/* Search Row */} +
+
+ + setSearchTerm(e.target.value)} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + /> +
+
+ + {/* Filters Row */} +
+ {/* Status Filter */} +
+ + +
+ + {/* Sort by */} +
+ + +
+ + {/* Sort Direction */} +
+ + +
+ + {/* New Build Button */} +
+ +
+
+
+
+ + {/* Builds Grid */} +
+ {sortedBuilds.length > 0 ? ( +
+ {sortedBuilds.map((build) => ( +
+ {/* Build Image */} +
+ {build.name} { + const target = e.target as HTMLImageElement; + target.style.display = 'none'; + target.nextElementSibling?.classList.remove('hidden'); + }} + /> +
+
+
🔫
+
{build.name}
+
+
+
+ + {getStatusIcon(build.status)} {build.status} + +
+
+ + {/* Build Content */} +
+ {/* Build Title and Date */} +
+

{build.name}

+

{build.description}

+
+ {build.status === 'completed' && build.completedDate && `Completed ${formatDate(build.completedDate)}`} + {build.status === 'in-progress' && build.startedDate && `Started ${formatDate(build.startedDate)}`} + {build.status === 'planning' && build.plannedDate && `Planned for ${formatDate(build.plannedDate)}`} +
+
+ + {/* Progress Bar */} +
+
+ Progress + {build.components.completed}/{build.components.total} components +
+
+
+
+
+ + {/* Component Categories */} +
+
+ {Object.entries(build.components.categories).map(([category, count]) => ( + + {category}: {count} + + ))} +
+
+ + {/* Tags */} +
+
+ {build.tags.map((tag) => ( + + {tag} + + ))} +
+
+ + {/* Cost and Actions */} +
+
+ ${build.totalCost.toFixed(2)} +
+
+ + +
+
+
+
+ ))} +
+ ) : ( +
+
+
No builds found
+
Try adjusting your filters or create a new build
+
+
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/src/app/components/productCard.tsx b/src/app/components/productCard.tsx new file mode 100644 index 0000000..8645fff --- /dev/null +++ b/src/app/components/productCard.tsx @@ -0,0 +1,26 @@ +type Product = { + id: string; + name: string; + image_url: string; + brand: { name: string }; + description?: string; + price?: number; + vendor?: string; + }; + + export function ProductCard({ product }: { product: Product }) { + return ( +
+ {product.name} +

{product.name}

+

{product.brand?.name}

+ {product.price && ( +

${product.price.toFixed(2)}

+ )} +
+ ); + } \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index a2dc41e..bd6213e 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,26 +1,3 @@ -@import "tailwindcss"; - -:root { - --background: #ffffff; - --foreground: #171717; -} - -@theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } -} - -body { - background: var(--background); - color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; -} +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f7fa87e..21ca771 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ +import "./globals.css"; import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; -import "./globals.css"; +import { Navbar } from "@/components/Navbar"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -13,22 +14,21 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Pew Builder - Firearm Parts Catalog", + description: "Build your dream AR-15 with our comprehensive parts catalog and build checklist", }; export default function RootLayout({ children, -}: Readonly<{ +}: { children: React.ReactNode; -}>) { +}) { return ( - + + {children} ); -} +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index e68abe6..c730ff4 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,103 +1,880 @@ -import Image from "next/image"; +'use client'; + +import { useState, useEffect } from 'react'; +import { useSearchParams } from 'next/navigation'; + +// Sample firearm parts data +const parts = [ + { + id: '1', + name: 'Faxon 16" Gunner Barrel - 5.56 NATO', + description: 'Lightweight, high-performance AR-15 barrel with 1:8 twist rate', + image_url: 'https://picsum.photos/300/200?random=1', + brand: { + id: 'b1', + name: 'Faxon Firearms', + }, + category: { + id: 'c1', + name: 'Barrel', + }, + offers: [ + { + price: 189.99, + url: 'https://primaryarms.com/faxon-16-gunner-barrel', + vendor: { + name: 'Primary Arms', + }, + }, + ], + }, + { + id: '2', + name: 'BCM M4 Upper Receiver', + description: 'Forged upper receiver with M4 feed ramps and T-markings', + image_url: 'https://picsum.photos/300/200?random=2', + brand: { + id: 'b2', + name: 'BCM', + }, + category: { + id: 'c2', + name: 'Upper Receiver', + }, + offers: [ + { + price: 129.99, + url: 'https://rainierarms.com/bcm-m4-upper', + vendor: { + name: 'Rainier Arms', + }, + }, + ], + }, + { + id: '3', + name: 'Aero Precision Lower Receiver', + description: 'Mil-spec forged lower receiver with trigger guard and threaded bolt catch', + image_url: 'https://picsum.photos/300/200?random=3', + brand: { + id: 'b3', + name: 'Aero Precision', + }, + category: { + id: 'c3', + name: 'Lower Receiver', + }, + offers: [ + { + price: 89.99, + url: 'https://aeroprecisionusa.com/lower', + vendor: { + name: 'Aero Precision', + }, + }, + ], + }, + { + id: '4', + name: 'Toolcraft BCG - Nitride', + description: 'Mil-spec bolt carrier group with Carpenter 158 bolt and nitride finish', + image_url: 'https://picsum.photos/300/200?random=4', + brand: { + id: 'b4', + name: 'Toolcraft', + }, + category: { + id: 'c4', + name: 'BCG', + }, + offers: [ + { + price: 149.99, + url: 'https://wctoolcraft.com/bcg-nitride', + vendor: { + name: 'WC Toolcraft', + }, + }, + ], + }, + { + id: '5', + name: 'Geissele SSA-E Trigger', + description: 'Two-stage trigger with 3.5lb total pull weight and enhanced reliability', + image_url: 'https://picsum.photos/300/200?random=5', + brand: { + id: 'b5', + name: 'Geissele', + }, + category: { + id: 'c5', + name: 'Trigger', + }, + offers: [ + { + price: 249.99, + url: 'https://geissele.com/ssa-e', + vendor: { + name: 'Geissele', + }, + }, + ], + }, + { + id: '6', + name: 'Magpul CTR Stock', + description: 'Collapsible stock with friction lock system and QD sling mount', + image_url: 'https://picsum.photos/300/200?random=6', + brand: { + id: 'b6', + name: 'Magpul', + }, + category: { + id: 'c6', + name: 'Stock', + }, + offers: [ + { + price: 69.99, + url: 'https://magpul.com/ctr-stock', + vendor: { + name: 'Magpul', + }, + }, + ], + }, + { + id: '7', + name: 'Radian Raptor Charging Handle', + description: 'Ambidextrous charging handle with oversized latches and smooth operation', + image_url: 'https://picsum.photos/300/200?random=7', + brand: { + id: 'b7', + name: 'Radian Weapons', + }, + category: { + id: 'c7', + name: 'Charging Handle', + }, + offers: [ + { + price: 89.99, + url: 'https://radianweapons.com/raptor', + vendor: { + name: 'Radian Weapons', + }, + }, + ], + }, + { + id: '8', + name: 'BCM Gunfighter Handguard - 15" M-LOK', + description: 'Free-float handguard with M-LOK slots and integrated QD mounts', + image_url: 'https://picsum.photos/300/200?random=8', + brand: { + id: 'b2', + name: 'BCM', + }, + category: { + id: 'c8', + name: 'Handguard', + }, + offers: [ + { + price: 199.99, + url: 'https://bravocompanyusa.com/handguard', + vendor: { + name: 'BCM', + }, + }, + ], + }, + { + id: '9', + name: 'SureFire WarComp Flash Hider', + description: 'Compensator/flash hider hybrid with suppressor mount capability', + image_url: 'https://picsum.photos/300/200?random=9', + brand: { + id: 'b8', + name: 'SureFire', + }, + category: { + id: 'c9', + name: 'Muzzle Device', + }, + offers: [ + { + price: 159.99, + url: 'https://surefire.com/warcomp', + vendor: { + name: 'SureFire', + }, + }, + ], + }, + { + id: '10', + name: 'Aero Precision Gas Block - Low Profile', + description: 'Low-profile adjustable gas block for free-float handguards', + image_url: 'https://picsum.photos/300/200?random=10', + brand: { + id: 'b3', + name: 'Aero Precision', + }, + category: { + id: 'c10', + name: 'Gas Block', + }, + offers: [ + { + price: 49.99, + url: 'https://aeroprecisionusa.com/gas-block', + vendor: { + name: 'Aero Precision', + }, + }, + ], + }, + { + id: '11', + name: 'BCM Gas Tube - Mid Length', + description: 'Stainless steel gas tube for mid-length gas systems', + image_url: 'https://picsum.photos/300/200?random=11', + brand: { + id: 'b2', + name: 'BCM', + }, + category: { + id: 'c11', + name: 'Gas Tube', + }, + offers: [ + { + price: 19.99, + url: 'https://bravocompanyusa.com/gas-tube', + vendor: { + name: 'BCM', + }, + }, + ], + }, + { + id: '12', + name: 'Magpul MOE Pistol Grip', + description: 'Ergonomic pistol grip with storage compartment and enhanced texture', + image_url: 'https://picsum.photos/300/200?random=12', + brand: { + id: 'b6', + name: 'Magpul', + }, + category: { + id: 'c12', + name: 'Pistol Grip', + }, + offers: [ + { + price: 24.99, + url: 'https://magpul.com/moe-grip', + vendor: { + name: 'Magpul', + }, + }, + ], + }, + { + id: '13', + name: 'BCM Buffer Tube - Mil-Spec', + description: 'Mil-spec buffer tube with proper castle nut and end plate', + image_url: 'https://picsum.photos/300/200?random=13', + brand: { + id: 'b2', + name: 'BCM', + }, + category: { + id: 'c13', + name: 'Buffer Tube', + }, + offers: [ + { + price: 44.99, + url: 'https://bravocompanyusa.com/buffer-tube', + vendor: { + name: 'BCM', + }, + }, + ], + }, + { + id: '14', + name: 'H2 Buffer Weight', + description: 'Heavy buffer weight for improved recoil management', + image_url: 'https://picsum.photos/300/200?random=14', + brand: { + id: 'b9', + name: 'Spikes Tactical', + }, + category: { + id: 'c14', + name: 'Buffer', + }, + offers: [ + { + price: 29.99, + url: 'https://spikestactical.com/h2-buffer', + vendor: { + name: 'Spikes Tactical', + }, + }, + ], + }, + { + id: '15', + name: 'Sprinco Blue Buffer Spring', + description: 'Enhanced buffer spring for improved reliability and reduced wear', + image_url: 'https://picsum.photos/300/200?random=15', + brand: { + id: 'b10', + name: 'Sprinco', + }, + category: { + id: 'c15', + name: 'Buffer Spring', + }, + offers: [ + { + price: 19.99, + url: 'https://sprinco.com/blue-spring', + vendor: { + name: 'Sprinco', + }, + }, + ], + }, + { + id: '16', + name: 'Magpul PMAG 30-Round Magazine', + description: '30-round polymer magazine with anti-tilt follower and dust cover', + image_url: 'https://picsum.photos/300/200?random=16', + brand: { + id: 'b6', + name: 'Magpul', + }, + category: { + id: 'c16', + name: 'Magazine', + }, + offers: [ + { + price: 14.99, + url: 'https://magpul.com/pmag', + vendor: { + name: 'Magpul', + }, + }, + ], + }, + { + id: '17', + name: 'Troy Industries BUIS - Folding', + description: 'Folding backup iron sights with micro-adjustable elevation', + image_url: 'https://picsum.photos/300/200?random=17', + brand: { + id: 'b11', + name: 'Troy Industries', + }, + category: { + id: 'c17', + name: 'Sights', + }, + offers: [ + { + price: 129.99, + url: 'https://troyind.com/buis', + vendor: { + name: 'Troy Industries', + }, + }, + ], + }, + { + id: '18', + name: 'Aero Precision Trigger Guard', + description: 'Enhanced trigger guard with oversized opening for gloved hands', + image_url: 'https://picsum.photos/300/200?random=18', + brand: { + id: 'b3', + name: 'Aero Precision', + }, + category: { + id: 'c18', + name: 'Trigger Guard', + }, + offers: [ + { + price: 12.99, + url: 'https://aeroprecisionusa.com/trigger-guard', + vendor: { + name: 'Aero Precision', + }, + }, + ], + }, + { + id: '19', + name: 'Larue MBT-2S Trigger', + description: 'Two-stage trigger with 4.5lb total pull weight and excellent value', + image_url: 'https://picsum.photos/300/200?random=19', + brand: { + id: 'b12', + name: 'LaRue Tactical', + }, + category: { + id: 'c5', + name: 'Trigger', + }, + offers: [ + { + price: 89.99, + url: 'https://laruetactical.com/mbt-2s', + vendor: { + name: 'LaRue Tactical', + }, + }, + ], + }, + { + id: '20', + name: 'Daniel Defense 18" Barrel - 5.56 NATO', + description: 'Cold hammer forged barrel with 1:7 twist rate for precision shooting', + image_url: 'https://picsum.photos/300/200?random=20', + brand: { + id: 'b13', + name: 'Daniel Defense', + }, + category: { + id: 'c1', + name: 'Barrel', + }, + offers: [ + { + price: 399.99, + url: 'https://danieldefense.com/18-barrel', + vendor: { + name: 'Daniel Defense', + }, + }, + ], + }, + { + id: '21', + name: 'BCM Complete Lower Receiver', + description: 'Complete lower receiver with BCM trigger, grip, and stock', + image_url: 'https://picsum.photos/300/200?random=21', + brand: { + id: 'b2', + name: 'BCM', + }, + category: { + id: 'c3', + name: 'Lower Receiver', + }, + offers: [ + { + price: 449.99, + url: 'https://bravocompanyusa.com/complete-lower', + vendor: { + name: 'BCM', + }, + }, + ], + }, + { + id: '22', + name: 'Aimpoint PRO Red Dot Sight', + description: '2 MOA red dot sight with 2x magnification and 40mm objective', + image_url: 'https://picsum.photos/300/200?random=22', + brand: { + id: 'b14', + name: 'Aimpoint', + }, + category: { + id: 'c17', + name: 'Sights', + }, + offers: [ + { + price: 449.99, + url: 'https://aimpoint.com/pro', + vendor: { + name: 'Aimpoint', + }, + }, + ], + } +]; + +// Extract unique values for dropdowns +const categories = ['All', ...Array.from(new Set(parts.map(part => part.category.name)))]; +const brands = ['All', ...Array.from(new Set(parts.map(part => part.brand.name)))]; +const vendors = ['All', ...Array.from(new Set(parts.flatMap(part => part.offers.map(offer => offer.vendor.name))))]; + +type SortField = 'name' | 'category' | 'price'; +type SortDirection = 'asc' | 'desc'; export default function Home() { - return ( -
-
- Next.js logo -
    -
  1. - Get started by editing{" "} - - src/app/page.tsx - - . -
  2. -
  3. - Save and see your changes instantly. -
  4. -
+ const searchParams = useSearchParams(); + const [selectedCategory, setSelectedCategory] = useState('All'); + const [selectedBrand, setSelectedBrand] = useState('All'); + const [selectedVendor, setSelectedVendor] = useState('All'); + const [sortField, setSortField] = useState('name'); + const [sortDirection, setSortDirection] = useState('asc'); + const [searchTerm, setSearchTerm] = useState(''); + const [minPrice, setMinPrice] = useState(''); + const [maxPrice, setMaxPrice] = useState(''); -
- - Vercel logomark - Deploy now - - - Read our docs - + // Read category from URL parameter on page load + useEffect(() => { + const categoryParam = searchParams.get('category'); + if (categoryParam && categories.includes(categoryParam)) { + setSelectedCategory(categoryParam); + } + }, [searchParams]); + + // Filter parts by all criteria + const filteredParts = parts.filter(part => { + // Category filter + if (selectedCategory !== 'All' && part.category.name !== selectedCategory) { + return false; + } + + // Brand filter + if (selectedBrand !== 'All' && part.brand.name !== selectedBrand) { + return false; + } + + // Vendor filter + if (selectedVendor !== 'All' && !part.offers.some(offer => offer.vendor.name === selectedVendor)) { + return false; + } + + // Search filter + if (searchTerm && !part.name.toLowerCase().includes(searchTerm.toLowerCase()) && + !part.description.toLowerCase().includes(searchTerm.toLowerCase())) { + return false; + } + + // Price range filter + const minPriceNum = minPrice ? parseFloat(minPrice) : 0; + const maxPriceNum = maxPrice ? parseFloat(maxPrice) : Infinity; + const partPrice = Math.min(...part.offers.map(offer => offer.price)); + + if (partPrice < minPriceNum || partPrice > maxPriceNum) { + return false; + } + + return true; + }); + + // Sort parts + const sortedParts = [...filteredParts].sort((a, b) => { + let aValue: any, bValue: any; + + if (sortField === 'price') { + aValue = Math.min(...a.offers.map(offer => offer.price)); + bValue = Math.min(...b.offers.map(offer => offer.price)); + } else if (sortField === 'category') { + aValue = a.category.name.toLowerCase(); + bValue = b.category.name.toLowerCase(); + } else { + aValue = a.name.toLowerCase(); + bValue = b.name.toLowerCase(); + } + + if (sortDirection === 'asc') { + return aValue > bValue ? 1 : -1; + } else { + return aValue < bValue ? 1 : -1; + } + }); + + const handleSort = (field: SortField) => { + if (sortField === field) { + setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc'); + } else { + setSortField(field); + setSortDirection('asc'); + } + }; + + const getSortIcon = (field: SortField) => { + if (sortField !== field) { + return '↕️'; + } + return sortDirection === 'asc' ? '↑' : '↓'; + }; + + const clearFilters = () => { + setSelectedCategory('All'); + setSelectedBrand('All'); + setSelectedVendor('All'); + setSearchTerm(''); + setMinPrice(''); + setMaxPrice(''); + }; + + const hasActiveFilters = selectedCategory !== 'All' || selectedBrand !== 'All' || selectedVendor !== 'All' || searchTerm || minPrice || maxPrice; + + return ( +
+ {/* Page Title */} +
+
+

+ Parts Catalog + {selectedCategory !== 'All' && ( + + - {selectedCategory} + + )} +

+

+ {selectedCategory !== 'All' + ? `Showing ${selectedCategory} parts for your build` + : 'Browse and filter firearm parts for your build' + } +

-
- -
+
+ + {/* Search and Filters */} +
+
+ {/* Search Row */} +
+
+ + setSearchTerm(e.target.value)} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + /> +
+
+ + {/* Filters Row */} +
+ {/* Category Dropdown */} +
+ + +
+ + {/* Brand Dropdown */} +
+ + +
+ + {/* Vendor Dropdown */} +
+ + +
+ + {/* Min Price */} +
+ + setMinPrice(e.target.value)} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + /> +
+ + {/* Max Price */} +
+ + setMaxPrice(e.target.value)} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + /> +
+ + {/* Clear Filters */} +
+ +
+
+
+
+ + {/* Parts Table */} +
+
+
+ + + + + + + + + + + + + + {sortedParts.length > 0 ? ( + sortedParts.map((part) => ( + + + + + + + + + + )) + ) : ( + + + + )} + +
+ Category + handleSort('name')} + > +
+ Name + {getSortIcon('name')} +
+
+ Brand + + Description + handleSort('price')} + > +
+ Price + {getSortIcon('price')} +
+
+ Vendor + + Actions +
+ + {part.category.name} + + +
+ {part.name} +
+
+
+ {part.brand.name} +
+
+
+ {part.description} +
+
+
+ ${Math.min(...part.offers.map(offer => offer.price))} +
+
+
+ {part.offers[0]?.vendor.name} +
+
+
+ + +
+
+
+
No parts found
+
Try adjusting your filters or search terms
+
+
+
+ + {/* Table Footer */} +
+
+
+ Showing {sortedParts.length} of {parts.length} parts + {hasActiveFilters && ( + + (filtered) + + )} +
+ {/*
+ Total Value: ${sortedParts.reduce((sum, part) => sum + Math.min(...part.offers.map(offer => offer.price)), 0).toFixed(2)} +
*/} +
+
+
+
+ ); -} +} \ No newline at end of file diff --git a/src/app/products/page.tsx b/src/app/products/page.tsx new file mode 100644 index 0000000..808b7c6 --- /dev/null +++ b/src/app/products/page.tsx @@ -0,0 +1,27 @@ +'use client'; + +import { mockProducts } from '@/mock/products'; + +export default function ProductsPage() { + return ( +
+

All Products

+
+ {mockProducts.map((product) => ( +
+

{product.name}

+

{product.description}

+
+ + ${product.offers[0]?.price} + + +
+
+ ))} +
+
+ ); +} \ No newline at end of file diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx new file mode 100644 index 0000000..43b6222 --- /dev/null +++ b/src/components/Navbar.tsx @@ -0,0 +1,82 @@ +'use client'; + +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; + +export function Navbar() { + const pathname = usePathname(); + + const navItems = [ + { name: 'Parts Catalog', href: '/' }, + { name: 'Build Checklist', href: '/build' }, + { name: 'My Builds', href: '/builds' }, + ]; + + return ( + + ); +} \ No newline at end of file diff --git a/src/mock/product.ts b/src/mock/product.ts new file mode 100644 index 0000000..f03d3e0 --- /dev/null +++ b/src/mock/product.ts @@ -0,0 +1,48 @@ +export const mockProducts = [ + { + id: '1', + name: 'Faxon 16" Gunner Barrel - 5.56 NATO', + description: 'Lightweight, high-performance AR-15 barrel.', + image_url: 'https://via.placeholder.com/300x200?text=Barrel', + brand: { + id: 'b1', + name: 'Faxon Firearms', + }, + category: { + id: 'c1', + name: 'Barrel', + }, + offers: [ + { + price: 189.99, + url: 'https://primaryarms.com/faxon-16-gunner-barrel', + vendor: { + name: 'Primary Arms', + }, + }, + ], + }, + { + id: '2', + name: 'BCM M4 Upper Receiver', + description: 'Forged upper with M4 feed ramps.', + image_url: 'https://via.placeholder.com/300x200?text=Upper', + brand: { + id: 'b2', + name: 'BCM', + }, + category: { + id: 'c2', + name: 'Upper Receiver', + }, + offers: [ + { + price: 129.99, + url: 'https://rainierarms.com/bcm-m4-upper', + vendor: { + name: 'Rainier Arms', + }, + }, + ], + }, + ]; \ No newline at end of file diff --git a/src/mock/products.ts b/src/mock/products.ts new file mode 100644 index 0000000..0f896c9 --- /dev/null +++ b/src/mock/products.ts @@ -0,0 +1,48 @@ +export const mockProducts = [ + { + id: '1', + name: 'Faxon 16" Gunner Barrel - 5.56 NATO', + description: 'Lightweight, high-performance AR-15 barrel.', + image_url: 'https://via.placeholder.com/300x200?text=Barrel', + brand: { + id: 'b1', + name: 'Faxon Firearms', + }, + category: { + id: 'c1', + name: 'Barrel', + }, + offers: [ + { + price: 189.99, + url: 'https://primaryarms.com/faxon-16-gunner-barrel', + vendor: { + name: 'Primary Arms', + }, + }, + ], + }, + { + id: '2', + name: 'BCM M4 Upper Receiver', + description: 'Forged upper with M4 feed ramps.', + image_url: 'https://via.placeholder.com/300x200?text=Upper', + brand: { + id: 'b2', + name: 'BCM', + }, + category: { + id: 'c2', + name: 'Upper Receiver', + }, + offers: [ + { + price: 129.99, + url: 'https://rainierarms.com/bcm-m4-upper', + vendor: { + name: 'Rainier Arms', + }, + }, + ], + }, +]; \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..374251b --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,12 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./src/**/*.{js,ts,jsx,tsx}", + "./src/app/**/*.{js,ts,jsx,tsx}", + "./components/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: {}, + }, + plugins: [], + }; \ No newline at end of file