diff --git a/package-lock.json b/package-lock.json
index 87f2863..e6fea4e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,7 +24,8 @@
"playwright": "*",
"react": "^18.3.1",
"react-dom": "^18.3.1",
- "swiper": "^11.1.4"
+ "swiper": "^11.1.4",
+ "vitest": "^2.0.3"
},
"devDependencies": {
"@apify/tsconfig": "^0.1.0",
@@ -1857,6 +1858,81 @@
"vite": "^4.2.0 || ^5.0.0"
}
},
+ "node_modules/@vitest/expect": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.3.tgz",
+ "integrity": "sha512-X6AepoOYePM0lDNUPsGXTxgXZAl3EXd0GYe/MZyVE4HzkUqyUVC6S3PrY5mClDJ6/7/7vALLMV3+xD/Ko60Hqg==",
+ "dependencies": {
+ "@vitest/spy": "2.0.3",
+ "@vitest/utils": "2.0.3",
+ "chai": "^5.1.1",
+ "tinyrainbow": "^1.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.3.tgz",
+ "integrity": "sha512-URM4GLsB2xD37nnTyvf6kfObFafxmycCL8un3OC9gaCs5cti2u+5rJdIflZ2fUJUen4NbvF6jCufwViAFLvz1g==",
+ "dependencies": {
+ "tinyrainbow": "^1.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/runner": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.0.3.tgz",
+ "integrity": "sha512-EmSP4mcjYhAcuBWwqgpjR3FYVeiA4ROzRunqKltWjBfLNs1tnMLtF+qtgd5ClTwkDP6/DGlKJTNa6WxNK0bNYQ==",
+ "dependencies": {
+ "@vitest/utils": "2.0.3",
+ "pathe": "^1.1.2"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.0.3.tgz",
+ "integrity": "sha512-6OyA6v65Oe3tTzoSuRPcU6kh9m+mPL1vQ2jDlPdn9IQoUxl8rXhBnfICNOC+vwxWY684Vt5UPgtcA2aPFBb6wg==",
+ "dependencies": {
+ "@vitest/pretty-format": "2.0.3",
+ "magic-string": "^0.30.10",
+ "pathe": "^1.1.2"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/spy": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.3.tgz",
+ "integrity": "sha512-sfqyAw/ypOXlaj4S+w8689qKM1OyPOqnonqOc9T91DsoHbfN5mU7FdifWWv3MtQFf0lEUstEwR9L/q/M390C+A==",
+ "dependencies": {
+ "tinyspy": "^3.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.3.tgz",
+ "integrity": "sha512-c/UdELMuHitQbbc/EVctlBaxoYAwQPQdSNwv7z/vHyBKy2edYZaFgptE27BRueZB7eW8po+cllotMNTDpL3HWg==",
+ "dependencies": {
+ "@vitest/pretty-format": "2.0.3",
+ "estree-walker": "^3.0.3",
+ "loupe": "^3.1.1",
+ "tinyrainbow": "^1.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
"node_modules/@vladfrangu/async_event_emitter": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.0.tgz",
@@ -2139,6 +2215,14 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/astro": {
"version": "4.11.5",
"resolved": "https://registry.npmjs.org/astro/-/astro-4.11.5.tgz",
@@ -2429,6 +2513,14 @@
"ieee754": "^1.1.13"
}
},
+ "node_modules/cac": {
+ "version": "6.7.14",
+ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
+ "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/cacheable-lookup": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz",
@@ -2529,6 +2621,21 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/chai": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz",
+ "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==",
+ "dependencies": {
+ "assertion-error": "^2.0.1",
+ "check-error": "^2.1.1",
+ "deep-eql": "^5.0.1",
+ "loupe": "^3.1.0",
+ "pathval": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/chalk": {
"version": "5.3.0",
"license": "MIT",
@@ -2571,6 +2678,14 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"license": "MIT"
},
+ "node_modules/check-error": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
+ "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
+ "engines": {
+ "node": ">= 16"
+ }
+ },
"node_modules/cheerio": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
@@ -3053,6 +3168,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/deep-eql": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
+ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/defaults": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
@@ -3680,6 +3803,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/get-func-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
+ "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/get-stream": {
"version": "8.0.1",
"license": "MIT",
@@ -4966,6 +5097,14 @@
"loose-envify": "cli.js"
}
},
+ "node_modules/loupe": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz",
+ "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==",
+ "dependencies": {
+ "get-func-name": "^2.0.1"
+ }
+ },
"node_modules/lowercase-keys": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
@@ -6309,6 +6448,19 @@
"version": "6.2.2",
"license": "MIT"
},
+ "node_modules/pathe": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
+ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="
+ },
+ "node_modules/pathval": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
+ "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
+ "engines": {
+ "node": ">= 14.16"
+ }
+ },
"node_modules/pause-stream": {
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
@@ -7237,6 +7389,11 @@
"@types/hast": "^3.0.4"
}
},
+ "node_modules/siginfo": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
+ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="
+ },
"node_modules/signal-exit": {
"version": "4.1.0",
"license": "ISC",
@@ -7355,6 +7512,16 @@
"version": "1.0.3",
"license": "BSD-3-Clause"
},
+ "node_modules/stackback": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
+ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="
+ },
+ "node_modules/std-env": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz",
+ "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg=="
+ },
"node_modules/stdin-discarder": {
"version": "0.2.2",
"license": "MIT",
@@ -7542,6 +7709,35 @@
"integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==",
"license": "MIT"
},
+ "node_modules/tinybench": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz",
+ "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw=="
+ },
+ "node_modules/tinypool": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.0.tgz",
+ "integrity": "sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz",
+ "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tinyspy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.0.tgz",
+ "integrity": "sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/tldts": {
"version": "6.1.30",
"resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.30.tgz",
@@ -8060,6 +8256,27 @@
}
}
},
+ "node_modules/vite-node": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.0.3.tgz",
+ "integrity": "sha512-14jzwMx7XTcMB+9BhGQyoEAmSl0eOr3nrnn+Z12WNERtOvLN+d2scbRUvyni05rT3997Bg+rZb47NyP4IQPKXg==",
+ "dependencies": {
+ "cac": "^6.7.14",
+ "debug": "^4.3.5",
+ "pathe": "^1.1.2",
+ "tinyrainbow": "^1.2.0",
+ "vite": "^5.0.0"
+ },
+ "bin": {
+ "vite-node": "vite-node.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
"node_modules/vite/node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -8086,6 +8303,69 @@
}
}
},
+ "node_modules/vitest": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.0.3.tgz",
+ "integrity": "sha512-o3HRvU93q6qZK4rI2JrhKyZMMuxg/JRt30E6qeQs6ueaiz5hr1cPj+Sk2kATgQzMMqsa2DiNI0TIK++1ULx8Jw==",
+ "dependencies": {
+ "@ampproject/remapping": "^2.3.0",
+ "@vitest/expect": "2.0.3",
+ "@vitest/pretty-format": "^2.0.3",
+ "@vitest/runner": "2.0.3",
+ "@vitest/snapshot": "2.0.3",
+ "@vitest/spy": "2.0.3",
+ "@vitest/utils": "2.0.3",
+ "chai": "^5.1.1",
+ "debug": "^4.3.5",
+ "execa": "^8.0.1",
+ "magic-string": "^0.30.10",
+ "pathe": "^1.1.2",
+ "std-env": "^3.7.0",
+ "tinybench": "^2.8.0",
+ "tinypool": "^1.0.0",
+ "tinyrainbow": "^1.2.0",
+ "vite": "^5.0.0",
+ "vite-node": "2.0.3",
+ "why-is-node-running": "^2.2.2"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "@vitest/browser": "2.0.3",
+ "@vitest/ui": "2.0.3",
+ "happy-dom": "*",
+ "jsdom": "*"
+ },
+ "peerDependenciesMeta": {
+ "@edge-runtime/vm": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@vitest/browser": {
+ "optional": true
+ },
+ "@vitest/ui": {
+ "optional": true
+ },
+ "happy-dom": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/volar-service-css": {
"version": "0.0.59",
"resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.59.tgz",
@@ -8386,6 +8666,21 @@
"node": ">=4"
}
},
+ "node_modules/why-is-node-running": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
+ "dependencies": {
+ "siginfo": "^2.0.0",
+ "stackback": "0.0.2"
+ },
+ "bin": {
+ "why-is-node-running": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/widest-line": {
"version": "4.0.1",
"license": "MIT",
diff --git a/package.json b/package.json
index 19b5470..4213107 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,8 @@
"start": "astro dev",
"build": "astro check && astro build",
"preview": "astro preview",
- "astro": "astro"
+ "astro": "astro",
+ "test": "vitest"
},
"dependencies": {
"@astrojs/check": "^0.8.1",
@@ -26,7 +27,8 @@
"playwright": "*",
"react": "^18.3.1",
"react-dom": "^18.3.1",
- "swiper": "^11.1.4"
+ "swiper": "^11.1.4",
+ "vitest": "^2.0.3"
},
"devDependencies": {
"@apify/tsconfig": "^0.1.0",
diff --git a/src/data/categories.ts b/src/data/categories.ts
index e6eb421..12e24a7 100644
--- a/src/data/categories.ts
+++ b/src/data/categories.ts
@@ -1,3 +1,5 @@
+import { TreeNode } from "../types/tree";
+
/**
* Category of Products.
*/
@@ -22,10 +24,18 @@ export interface Category {
* Description of Product Category.
*/
description: string;
+ // /**
+ // * Sub-categories.
+ // */
+ // categories?: Category[];
+ // /**
+ // * Parent category (do not assign this, it will be automatically created.)
+ // */
+ // parentCategory?: Category;
}
/**
- *
+ * Static properties of categories.
*/
export class StaticCategory {
/**
@@ -42,80 +52,81 @@ export class StaticCategory {
}
}
-/**
- * A list of all the categories.
- */
-export const ALL_CATEGORIES: Category[] = [
- {
- id: StaticCategory.nextId(),
- category: "Vehicle Essentials",
- slug: "vehicle-essentials",
- imageUrl: "/assets/vehicle-essentials.png",
- description: "Essential items for your vehicle to ensure smooth deliveries.",
- },
- {
- id: StaticCategory.nextId(),
- category: "Delivery Gear",
- slug: "delivery-gear",
- imageUrl: "/assets/delivery-gear-3.jpg",
- description: "Gear to help you deliver food efficiently and keep it in top condition.",
- },
- {
- id: StaticCategory.nextId(),
- category: "Personal Items",
- slug: "personal-items",
- imageUrl: "/assets/personal-items.jpg",
- description: "Personal essentials to keep you comfortable and prepared on the go.",
- },
- {
- id: StaticCategory.nextId(),
- category: "Safety Equipment",
- slug: "safety-equipment",
- imageUrl: "/assets/safety-equipment.jpg",
- description: "Safety gear to protect you during deliveries.",
- },
- {
- id: StaticCategory.nextId(),
- category: "Tech Gadgets",
- slug: "tech-gadgets",
- imageUrl: "/assets/tech-gadgets.jpg",
- description: "Technology tools to enhance your efficiency and connectivity.",
- },
- {
- id: StaticCategory.nextId(),
- category: "Biking Gear",
- slug: "biking-gear",
- imageUrl: "/assets/biking-gear.jpg",
- description: "Equipment for Dashers who deliver by bike.",
- },
- {
- id: StaticCategory.nextId(),
- category: "Comfort and Convenience",
- slug: "comfort-convenience",
- imageUrl: "/assets/comfort-convenience.png",
- description: "Items to increase comfort and convenience during deliveries.",
- },
- {
- id: StaticCategory.nextId(),
- category: "Health and Wellness",
- slug: "health-wellness",
- imageUrl: "/assets/wearable-tech.jpg",
- description: "Products to help you stay healthy and well during your shifts.",
- },
- {
- id: StaticCategory.nextId(),
- category: "Miscellaneous",
- slug: "misc",
- imageUrl: "/assets/misc.jpg",
- description: "Various other items that can be useful for Dashers.",
- }
-].sort((a, b) => a.slug.localeCompare(b.slug));
+export const ALL_CATEGORIES = TreeNode.createRoot