From 3c9304b59fbe38fd9dfe5eba1e088c1d131068f5 Mon Sep 17 00:00:00 2001 From: GaneshArumugam05 Date: Thu, 11 Dec 2025 15:52:31 +0530 Subject: [PATCH 01/19] today front end part work with protected route --- backend/settings.py | 26 +- db.sqlite3 | Bin 0 -> 262144 bytes frontend/package-lock.json | 937 +++++++++++++++++- frontend/package.json | 8 +- frontend/postcss.config.js | 6 + frontend/src/App.jsx | 184 +--- frontend/src/Authentication/Login.jsx | 62 ++ frontend/src/Authentication/Signup.jsx | 86 ++ frontend/src/Pages/LandingPage.jsx | 2 +- frontend/src/Pages/ProductsPage.jsx | 228 +++++ .../src/ProtectedRoutes/ProtectedRote.jsx | 14 + frontend/src/main.jsx | 17 +- frontend/src/reusableComponents/Input.jsx | 25 +- frontend/src/reusableComponents/Navbar.jsx | 136 ++- frontend/tailwind.config.js | 35 + package-lock.json | 6 + 16 files changed, 1549 insertions(+), 223 deletions(-) create mode 100644 db.sqlite3 create mode 100644 frontend/postcss.config.js create mode 100644 frontend/src/Authentication/Login.jsx create mode 100644 frontend/src/Authentication/Signup.jsx create mode 100644 frontend/src/ProtectedRoutes/ProtectedRote.jsx create mode 100644 frontend/tailwind.config.js create mode 100644 package-lock.json diff --git a/backend/settings.py b/backend/settings.py index 9ce7553..2b08ffe 100644 --- a/backend/settings.py +++ b/backend/settings.py @@ -83,24 +83,24 @@ # Database # https://docs.djangoproject.com/en/5.2/ref/settings/#databases -# DATABASES = { -# "default": { -# "ENGINE": "django.db.backends.sqlite3", -# "NAME": BASE_DIR / "db.sqlite3", -# } -# } - DATABASES = { "default": { - "ENGINE": "django.db.backends.postgresql", - "NAME": config("DB_NAME"), - "USER": config("DB_USER"), - "PASSWORD": config("DB_PASSWORD"), - "HOST": config("DB_HOST"), - "PORT": config("DB_PORT"), + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", } } +# DATABASES = { +# "default": { +# "ENGINE": "django.db.backends.postgresql", +# "NAME": config("DB_NAME"), +# "USER": config("DB_USER"), +# "PASSWORD": config("DB_PASSWORD"), +# "HOST": config("DB_HOST"), +# "PORT": config("DB_PORT"), +# } +# } + BASE_URL = config("BASE_URL", "http://127.0.0.1:8000") diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..666a84dd097811c29aea83e2086f9e4e58b35243 GIT binary patch literal 262144 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� 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 literal 0 HcmV?d00001 diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 01aa678..e7546dd 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,21 +8,39 @@ "name": "frontend", "version": "0.0.0", "dependencies": { + "framer-motion": "^12.23.26", "react": "^19.2.0", - "react-dom": "^19.2.0" + "react-dom": "^19.2.0", + "react-icons": "^5.5.0", + "react-router-dom": "^7.10.1" }, "devDependencies": { "@eslint/js": "^9.39.1", "@types/react": "^19.2.5", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^5.1.1", + "autoprefixer": "^10.4.22", "eslint": "^9.39.1", "eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-refresh": "^0.4.24", "globals": "^16.5.0", + "postcss": "^8.5.6", + "tailwindcss": "^3.4.18", "vite": "^7.2.4" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -941,6 +959,41 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.53", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz", @@ -1376,12 +1429,86 @@ "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 + }, + "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, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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 + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/autoprefixer": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", + "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", + "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" + } + ], + "dependencies": { + "browserslist": "^4.27.0", + "caniuse-lite": "^1.0.30001754", + "fraction.js": "^5.3.4", + "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/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1397,6 +1524,18 @@ "baseline-browser-mapping": "dist/cli.js" } }, + "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, + "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", @@ -1407,6 +1546,18 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/browserslist": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", @@ -1449,6 +1600,15 @@ "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, + "engines": { + "node": ">= 6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001760", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", @@ -1485,6 +1645,42 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "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, + "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": ">= 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, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1503,6 +1699,15 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "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, + "engines": { + "node": ">= 6" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1515,6 +1720,18 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1529,6 +1746,18 @@ "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, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -1558,6 +1787,18 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "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 + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "node_modules/electron-to-chromium": { "version": "1.5.267", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", @@ -1806,6 +2047,34 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/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, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -1818,6 +2087,15 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -1847,6 +2125,18 @@ "node": ">=16.0.0" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -1882,6 +2172,45 @@ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/framer-motion": { + "version": "12.23.26", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.26.tgz", + "integrity": "sha512-cPcIhgR42xBn1Uj+PzOyheMtZ73H927+uWPDVhUMqxy8UHt6Okavb6xIz9J/phFUHUj0OncR6UvMfJTXoc/LKA==", + "dependencies": { + "motion-dom": "^12.23.23", + "motion-utils": "^12.23.6", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -1896,6 +2225,15 @@ "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", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -1938,6 +2276,18 @@ "node": ">=8" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hermes-estree": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", @@ -1987,6 +2337,33 @@ "node": ">=0.8.19" } }, + "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, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2008,12 +2385,30 @@ "node": ">=0.10.0" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "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, + "bin": { + "jiti": "bin/jiti.js" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2096,6 +2491,24 @@ "node": ">= 0.8.0" } }, + "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, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "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 + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2126,6 +2539,40 @@ "yallist": "^3.0.2" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2138,12 +2585,36 @@ "node": "*" } }, + "node_modules/motion-dom": { + "version": "12.23.23", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz", + "integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==", + "dependencies": { + "motion-utils": "^12.23.6" + } + }, + "node_modules/motion-utils": { + "version": "12.23.6", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz", + "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "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, + "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", @@ -2174,6 +2645,42 @@ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "dev": true }, + "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, + "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, + "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", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "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, + "engines": { + "node": ">= 6" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2251,6 +2758,12 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -2269,6 +2782,24 @@ "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, + "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, + "engines": { + "node": ">= 6" + } + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -2297,6 +2828,134 @@ "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, + "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.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "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" + } + ], + "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, + "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 + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2315,6 +2974,26 @@ "node": ">=6" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/react": { "version": "19.2.1", "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", @@ -2334,6 +3013,14 @@ "react": "^19.2.1" } }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-refresh": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", @@ -2343,6 +3030,95 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.10.1.tgz", + "integrity": "sha512-gHL89dRa3kwlUYtRQ+m8NmxGI6CgqN+k4XyGjwcFoQwwCWF6xXpOCUlDovkXClS0d0XJN/5q7kc5W3kiFEd0Yw==", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.10.1.tgz", + "integrity": "sha512-JNBANI6ChGVjA5bwsUIwJk7LHKmqB4JYnYfzFwyp2t12Izva11elds2jx7Yfoup2zssedntwU0oZ5DEmk5Sdaw==", + "dependencies": { + "react-router": "7.10.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "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, + "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, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2352,6 +3128,16 @@ "node": ">=4" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rollup": { "version": "4.53.3", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", @@ -2393,6 +3179,29 @@ "fsevents": "~2.3.2" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/scheduler": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", @@ -2407,6 +3216,11 @@ "semver": "bin/semver.js" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -2449,6 +3263,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "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", @@ -2461,6 +3297,76 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.18.tgz", + "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "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, + "dependencies": { + "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, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -2477,6 +3383,29 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "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 + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -2528,6 +3457,12 @@ "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 + }, "node_modules/vite": { "version": "7.2.7", "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.7.tgz", diff --git a/frontend/package.json b/frontend/package.json index 1d89f06..49077b6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,18 +10,24 @@ "preview": "vite preview" }, "dependencies": { + "framer-motion": "^12.23.26", "react": "^19.2.0", - "react-dom": "^19.2.0" + "react-dom": "^19.2.0", + "react-icons": "^5.5.0", + "react-router-dom": "^7.10.1" }, "devDependencies": { "@eslint/js": "^9.39.1", "@types/react": "^19.2.5", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^5.1.1", + "autoprefixer": "^10.4.22", "eslint": "^9.39.1", "eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-refresh": "^0.4.24", "globals": "^16.5.0", + "postcss": "^8.5.6", + "tailwindcss": "^3.4.18", "vite": "^7.2.4" } } diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 2a4cb67..eee40b7 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,174 +1,32 @@ -// src/App.jsx import React from "react"; +import { Routes, Route } from "react-router-dom"; import LandingPage from "./Pages/LandingPage"; +import Login from "./Authentication/Login"; +import Signup from "./Authentication/Signup"; +import ProductsPage from "./Pages/ProductsPage"; +import ProtectedRoute from "./ProtectedRoutes/ProtectedRote"; function App() { return (
- + + {/* Public Routes */} + } /> + } /> + } /> + + {/* Protected Routes */} + + + + } + /> +
); } export default App; - - - -// // src/App.jsx -// import { useState } from "react"; -// import { motion } from "framer-motion"; -// import Button from "./reusableComponents/Button"; -// import Input from "./reusableComponents/Input"; -// import ProductCard from "./reusableComponents/ProductCard"; -// import Navbar from "./reusableComponents/Navbar"; -// import Footer from "./reusableComponents/Footer"; -// import BentoGrid from "./reusableComponents/BentoGrid"; - -// import FilterOptions from "./reusableComponents/FilterOption"; -// import Modal from "./reusableComponents/ModalPopup"; -// import Carousel from "./reusableComponents/CarouselSlider"; -// import BannerCard from "./reusableComponents/BannerCard"; -// import SearchBar from "./reusableComponents/Searchbar"; - -// const products = [ -// { id: 1, name: "iPhone 15 Pro", price: 999, image: "https://images.unsplash.com/photo-1690489874296-ea89dd0ba3f3?w=300", category: "Electronics" }, -// { id: 2, name: "MacBook Air", price: 1299, image: "https://images.unsplash.com/photo-1517336714731-489689fd1ca8?w=300", category: "Electronics" }, -// { id: 3, name: "Nike Air Max", price: 129, image: "https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=300", category: "Clothing" }, -// { id: 4, name: "Adidas Ultraboost", price: 189, image: "https://images.unsplash.com/photo-1549298916-b41d501d3772?w=300", category: "Clothing" }, -// { id: 5, name: "Coffee Maker", price: 79, image: "https://images.unsplash.com/photo-1495474472287-4d71bcdd2085?w=300", category: "Home" }, -// { id: 6, name: "Yoga Mat", price: 39, image: "https://images.unsplash.com/photo-1588854337236-7947b26e6a62?w=300", category: "Sports" } -// ]; - -// function App() { -// const [cartCount, setCartCount] = useState(3); -// const [isModalOpen, setIsModalOpen] = useState(false); -// const [searchTerm, setSearchTerm] = useState(""); -// const [filters, setFilters] = useState([]); -// const [email, setEmail] = useState(""); - -// const categories = ["Electronics", "Clothing", "Home", "Sports"]; -// const carouselImages = [ -// "https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=1200", -// "https://images.unsplash.com/photo-1441986300917-64674bd600d8?w=1200", -// "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=1200" -// ]; - -// const filteredProducts = products.filter(product => -// product.name.toLowerCase().includes(searchTerm.toLowerCase()) && -// (filters.length === 0 || filters.includes(product.category)) -// ); - -// return ( -//
-// {/* Navbar */} -// - -//
-// {/* Hero Carousel */} -// -// -// - -// {/* Search + Filters Row */} -//
-// -// -//
- -// {/* Banner Cards */} -//
-// setFilters(["Electronics"])} -// /> -// alert("Free shipping on orders over $50!")} -// /> -// setFilters([])} -// /> -//
- -// {/* Featured Products */} -//
-//

Featured Products

-//
-// {filteredProducts.map(product => ( -// -// ))} -//
-//
- -// {/* Newsletter Signup */} -// -//

Stay Updated

-//
-// setEmail(e.target.value)} -// /> -// -//
-//
- -// {/* Bento Grid Demo */} -//
-//

Dashboard Preview

-// -//
- -// {/* Demo Modal Trigger */} -//
-// -//
-//
- -// {/* Modal */} -// setIsModalOpen(false)} -// title="iPhone 15 Pro - Quick View" -// > -//
-// iPhone -//

$999

-//

Latest iPhone with A17 Pro chip and titanium design.

-//
-// -// -//
-//
-//
- -// {/* Footer */} -//
-//
-// ); -// } - -// export default App; - diff --git a/frontend/src/Authentication/Login.jsx b/frontend/src/Authentication/Login.jsx new file mode 100644 index 0000000..ae2fe4f --- /dev/null +++ b/frontend/src/Authentication/Login.jsx @@ -0,0 +1,62 @@ +import React, { useState } from "react"; +import Input from "../reusableComponents/Input"; +import { Link, useNavigate } from "react-router-dom"; + +export default function Login() { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [errors, setErrors] = useState({}); + const navigate = useNavigate(); + + const handleLogin = (e) => { + e.preventDefault(); + let newErrors = {}; + if (!email) newErrors.email = "Email is required"; + if (!password) newErrors.password = "Password is required"; + setErrors(newErrors); + + if (Object.keys(newErrors).length === 0) { + // Successful login + localStorage.setItem("isAuthenticated", "true"); + navigate("/products"); + } + }; + + return ( +
+
+

Login

+
+ setEmail(e.target.value)} + placeholder="Enter your email" + error={errors.email} + /> + setPassword(e.target.value)} + placeholder="Enter your password" + error={errors.password} + /> + +
+

+ Don’t have an account?{" "} + + Sign Up + +

+
+
+ ); +} diff --git a/frontend/src/Authentication/Signup.jsx b/frontend/src/Authentication/Signup.jsx new file mode 100644 index 0000000..8bc3f13 --- /dev/null +++ b/frontend/src/Authentication/Signup.jsx @@ -0,0 +1,86 @@ +import React, { useState } from "react"; +import Input from "../reusableComponents/Input"; +import { Link, useNavigate } from "react-router-dom"; + +export default function Signup() { + const [form, setForm] = useState({ + name: "", + email: "", + password: "", + confirmPassword: "", + }); + const [errors, setErrors] = useState({}); + const navigate = useNavigate(); + + const handleChange = (key, value) => setForm({ ...form, [key]: value }); + + const handleSignup = (e) => { + e.preventDefault(); + let newErrors = {}; + if (!form.name) newErrors.name = "Name is required"; + if (!form.email) newErrors.email = "Email is required"; + if (!form.password) newErrors.password = "Password is required"; + if (form.password !== form.confirmPassword) + newErrors.confirmPassword = "Passwords do not match"; + setErrors(newErrors); + + if (Object.keys(newErrors).length === 0) { + // Successful signup + localStorage.setItem("isAuthenticated", "true"); + navigate("/products"); + } + }; + + return ( +
+
+

Create Account

+
+ handleChange("name", e.target.value)} + placeholder="Enter your full name" + error={errors.name} + /> + handleChange("email", e.target.value)} + placeholder="Enter your email" + error={errors.email} + /> + handleChange("password", e.target.value)} + placeholder="Enter password" + error={errors.password} + /> + handleChange("confirmPassword", e.target.value)} + placeholder="Re-enter password" + error={errors.confirmPassword} + /> + +
+

+ Already have an account?{" "} + + Login + +

+
+
+ ); +} diff --git a/frontend/src/Pages/LandingPage.jsx b/frontend/src/Pages/LandingPage.jsx index 13ec2c1..cbc30ad 100644 --- a/frontend/src/Pages/LandingPage.jsx +++ b/frontend/src/Pages/LandingPage.jsx @@ -13,7 +13,7 @@ import BannerCard from "../reusableComponents/BannerCard"; const LandingPage = () => { return (
- + {/* Carousel */} { + return ( +
+ + + +
+ + {/* Page Header */} +

Product List

+

+ Check out our newest offerings! Discover the latest innovations and + features now at your fingertips. +

+ + {/* Products Grid */} +
+ + {products.map((product) => ( +
+ {/* Image */} +
+ {product.title} + + {/* Tag Badge */} + {product.tag && ( + + {product.tag} + + )} +
+ + {/* Card Body */} +
+

+ {product.brand} +

+ +

+ {product.title} +

+ + {/* Features */} +
    + {product.features.map((f, index) => ( +
  • • {f}
  • + ))} +
+ + {/* Price Section */} +
+ + ₹{product.price} + + + ₹{product.oldPrice} + + + {product.discount} + +
+ + {/* Rating */} +
+ + {product.rating} + ({product.reviews}) +
+ + {/* EMI */} +

{product.emi}

+ + {/* Buttons */} +
+ + +
+ +
+
+ ))} + +
+
+ +
+ ); +}; + +export default ProductsPage; diff --git a/frontend/src/ProtectedRoutes/ProtectedRote.jsx b/frontend/src/ProtectedRoutes/ProtectedRote.jsx new file mode 100644 index 0000000..3e6883b --- /dev/null +++ b/frontend/src/ProtectedRoutes/ProtectedRote.jsx @@ -0,0 +1,14 @@ +import React from "react"; +import { Navigate } from "react-router-dom"; + +// Protect routes that require authentication +export default function ProtectedRoute({ children }) { + const isAuthenticated = localStorage.getItem("isAuthenticated") === "true"; + + if (!isAuthenticated) { + // Redirect to signup if not logged in + return ; + } + + return children; +} diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index b9a1a6d..5d8db83 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -1,10 +1,13 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import './index.css' -import App from './App.jsx' +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import { BrowserRouter } from 'react-router-dom'; +import './index.css'; +import App from './App.jsx'; createRoot(document.getElementById('root')).render( - - , -) + + + + +); diff --git a/frontend/src/reusableComponents/Input.jsx b/frontend/src/reusableComponents/Input.jsx index c0a88ed..a96129a 100644 --- a/frontend/src/reusableComponents/Input.jsx +++ b/frontend/src/reusableComponents/Input.jsx @@ -1,15 +1,30 @@ -// Input.jsx -export default function Input({ label, type="text", value, onChange, error, className="" }) { +export default function Input({ + label, + type = "text", + value, + onChange, + error, + placeholder +}) { return (
- {label && } + {label && ( + + )} + - {error &&

{error}

} + + {error &&

{error}

}
); } diff --git a/frontend/src/reusableComponents/Navbar.jsx b/frontend/src/reusableComponents/Navbar.jsx index cc68b08..53beef7 100644 --- a/frontend/src/reusableComponents/Navbar.jsx +++ b/frontend/src/reusableComponents/Navbar.jsx @@ -1,36 +1,60 @@ import { useState } from "react"; -import { FaShoppingCart, FaUserCircle, FaSearch, FaTimes } from "react-icons/fa"; -import Button from './Button'; - +import { useNavigate } from "react-router-dom"; +import { FaShoppingCart, FaUserCircle, FaSearch, FaTimes, FaBars } from "react-icons/fa"; export default function Navbar({ cartCount }) { + const navigate = useNavigate(); const [isSearchOpen, setSearchOpen] = useState(false); const [searchTerm, setSearchTerm] = useState(""); + const [mobileMenuOpen, setMobileMenuOpen] = useState(false); + + const isAuthenticated = localStorage.getItem("isAuthenticated") === "true"; + + // Navigate to shop (products) with auth check + const handleShopClick = () => { + if (!isAuthenticated) { + navigate("/signup"); + } else { + navigate("/products"); + } + setMobileMenuOpen(false); // close mobile menu on click + }; + + // Logout user + const handleLogout = () => { + localStorage.removeItem("isAuthenticated"); + navigate("/"); + }; return ( - ); } From 78dbeca113d019a895e281e5e9cb33b35f18da96 Mon Sep 17 00:00:00 2001 From: GaneshArumugam05 Date: Sat, 13 Dec 2025 16:46:35 +0530 Subject: [PATCH 13/19] update App.jsx added a new routes of About and Contact comp --- frontend/src/App.jsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 73d3643..170f592 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -5,6 +5,8 @@ import Signup from "./Authentication/Signup"; import ProductsPage from "./Pages/ProductsPage"; import ProductDetails from "./Pages/ProductsDetails"; import Cart from "./Pages/Cart"; +import AboutUs from "./Pages/About"; +import Contact from "./Pages/Contact"; export default function App() { return ( @@ -18,6 +20,10 @@ export default function App() { } /> } /> + + {/* NEW ROUTES */} + } /> + } />
); From 636ce62b03c322a22b687435b5ec04ec6a3eead1 Mon Sep 17 00:00:00 2001 From: GaneshArumugam05 Date: Sat, 13 Dec 2025 16:47:54 +0530 Subject: [PATCH 14/19] About.jsx comp created a component of About Page with Details dummy data --- frontend/src/Pages/About.jsx | 118 +++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 frontend/src/Pages/About.jsx diff --git a/frontend/src/Pages/About.jsx b/frontend/src/Pages/About.jsx new file mode 100644 index 0000000..ba83fec --- /dev/null +++ b/frontend/src/Pages/About.jsx @@ -0,0 +1,118 @@ +import Navbar from "../reusableComponents/Navbar"; +import Footer from "../reusableComponents/Footer"; + +/* ---------------- DUMMY DATA ---------------- */ + +const bannerData = { + title: "Clean Water. Clear Trust.", + description: + "We believe every drop counts. Our mission is to make safe, pure water accessible to every home through high-quality RO systems and reliable service.", + image: + "https://images.unsplash.com/photo-1581093458799-7b2b6c1a7a44?auto=format&fit=crop&w=900&q=80", +}; + +const brandStory = [ + "PureFlow started with a simple goal — to bring transparency and trust into water purification and after-sales service. We noticed how difficult it was for customers to find genuine products, spare parts, or skilled technicians.", + "So, we built a single platform where you can buy, book, and track everything related to your purifier — all in one place. From installation to maintenance, PureFlow connects you with verified technicians and quality products, ensuring your home always stays healthy.", +]; + +const valuesData = [ + { + title: "Sustainability", + desc: "Encouraging reuse, exchange, and eco-friendly water solutions.", + }, + { + title: "Purity First", + desc: "Only trusted, tested products and services.", + }, + { + title: "Reliability", + desc: "Certified technicians, transparent pricing, and no hidden charges.", + }, + { + title: "Ease of Use", + desc: "Designed for effortless shopping and service booking.", + }, +]; + +/* ---------------- COMPONENT ---------------- */ + +export default function AboutUs() { + return ( +
+ + + {/* CUSTOM ABOUT BANNER */} +
+
+ + {/* LEFT - Image */} +
+ Clean Water Purification +
+ + {/* RIGHT - Content */} +
+

+ {bannerData.title} +

+

+ {bannerData.description} +

+
+ +
+
+ + {/* MAIN CONTENT */} +
+ + {/* Brand Story */} +
+

+ Brand Story +

+ + {brandStory.map((para, index) => ( +

+ {para} +

+ ))} +
+ + {/* Values */} +
+

+ Our Values +

+ +
+ {valuesData.map((item, index) => ( +
+

+ {item.title} +

+

+ {item.desc} +

+
+ ))} +
+
+ +
+ +
+
+ ); +} From 8c536d2723efc6735079be8c00ef462a34b0ed89 Mon Sep 17 00:00:00 2001 From: GaneshArumugam05 Date: Sat, 13 Dec 2025 16:49:00 +0530 Subject: [PATCH 15/19] create Contact.jsx Created a Contact page Component with address and contact details with input fields --- frontend/src/Pages/Contact.jsx | 120 +++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 frontend/src/Pages/Contact.jsx diff --git a/frontend/src/Pages/Contact.jsx b/frontend/src/Pages/Contact.jsx new file mode 100644 index 0000000..72b684f --- /dev/null +++ b/frontend/src/Pages/Contact.jsx @@ -0,0 +1,120 @@ +import { FaMapMarkerAlt, FaEnvelope, FaPhoneAlt } from "react-icons/fa"; +import BannerCard from "../reusableComponents/BannerCard"; +import Footer from "../reusableComponents/Footer"; +import Navbar from "../reusableComponents/Navbar"; + +export default function Contact() { + return ( +
+ + + +
+ + {/* Header */} +
+

+ Let's Talk With Us +

+

+ Questions, comments, or suggestions? Simply fill in the form and + we’ll be in touch shortly. +

+
+ + {/* Content */} +
+ + {/* LEFT - Contact Info */} +
+ + {/* Address */} +
+
+ +
+
+

Address

+

+ 1055 Arthur Ave Elk Groot, 67.
+ New Palmas South Carolina. +

+
+
+ + {/* Email */} +
+
+ +
+
+

Email

+

Contact@moralizer.com

+
+
+ + {/* Phone */} +
+
+ +
+
+

Phone

+

+1 234 678 9108 99

+
+
+ +
+ + {/* RIGHT - Form */} +
+ +
+ + +
+ + + + + +