diff --git a/package-lock.json b/package-lock.json
index 46ad443..89c5767 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,6 +14,7 @@
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-toast": "^1.2.6",
+ "@react-pdf/renderer": "^4.3.0",
"@shadcn/ui": "^0.0.4",
"@types/date-fns": "^2.5.3",
"@types/react": "^19.0.12",
@@ -2812,6 +2813,180 @@
"integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==",
"license": "MIT"
},
+ "node_modules/@react-pdf/fns": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-3.1.2.tgz",
+ "integrity": "sha512-qTKGUf0iAMGg2+OsUcp9ffKnKi41RukM/zYIWMDJ4hRVYSr89Q7e3wSDW/Koqx3ea3Uy/z3h2y3wPX6Bdfxk6g==",
+ "license": "MIT"
+ },
+ "node_modules/@react-pdf/font": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@react-pdf/font/-/font-4.0.2.tgz",
+ "integrity": "sha512-/dAWu7Y2RD1RxarDZ9SkYPHgBYOhmcDnet4W/qN/m8k+A2Hr3ja54GymSR7GGxWBtxjKtNauVKrTa9LS1n8WUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-pdf/pdfkit": "^4.0.3",
+ "@react-pdf/types": "^2.9.0",
+ "fontkit": "^2.0.2",
+ "is-url": "^1.2.4"
+ }
+ },
+ "node_modules/@react-pdf/image": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@react-pdf/image/-/image-3.0.3.tgz",
+ "integrity": "sha512-lvP5ryzYM3wpbO9bvqLZYwEr5XBDX9jcaRICvtnoRqdJOo7PRrMnmB4MMScyb+Xw10mGeIubZAAomNAG5ONQZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-pdf/png-js": "^3.0.0",
+ "jay-peg": "^1.1.1"
+ }
+ },
+ "node_modules/@react-pdf/layout": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@react-pdf/layout/-/layout-4.4.0.tgz",
+ "integrity": "sha512-Aq+Cc6JYausWLoks2FvHe3PwK9cTuvksB2uJ0AnkKJEUtQbvCq8eCRb1bjbbwIji9OzFRTTzZij7LzkpKHjIeA==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-pdf/fns": "3.1.2",
+ "@react-pdf/image": "^3.0.3",
+ "@react-pdf/primitives": "^4.1.1",
+ "@react-pdf/stylesheet": "^6.1.0",
+ "@react-pdf/textkit": "^6.0.0",
+ "@react-pdf/types": "^2.9.0",
+ "emoji-regex": "^10.3.0",
+ "queue": "^6.0.1",
+ "yoga-layout": "^3.2.1"
+ }
+ },
+ "node_modules/@react-pdf/pdfkit": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-4.0.3.tgz",
+ "integrity": "sha512-k+Lsuq8vTwWsCqTp+CCB4+2N+sOTFrzwGA7aw3H9ix/PDWR9QksbmNg0YkzGbLAPI6CeawmiLHcf4trZ5ecLPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.20.13",
+ "@react-pdf/png-js": "^3.0.0",
+ "browserify-zlib": "^0.2.0",
+ "crypto-js": "^4.2.0",
+ "fontkit": "^2.0.2",
+ "jay-peg": "^1.1.1",
+ "linebreak": "^1.1.0",
+ "vite-compatible-readable-stream": "^3.6.1"
+ }
+ },
+ "node_modules/@react-pdf/png-js": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-3.0.0.tgz",
+ "integrity": "sha512-eSJnEItZ37WPt6Qv5pncQDxLJRK15eaRwPT+gZoujP548CodenOVp49GST8XJvKMFt9YqIBzGBV/j9AgrOQzVA==",
+ "license": "MIT",
+ "dependencies": {
+ "browserify-zlib": "^0.2.0"
+ }
+ },
+ "node_modules/@react-pdf/primitives": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-4.1.1.tgz",
+ "integrity": "sha512-IuhxYls1luJb7NUWy6q5avb1XrNaVj9bTNI40U9qGRuS6n7Hje/8H8Qi99Z9UKFV74bBP3DOf3L1wV2qZVgVrQ==",
+ "license": "MIT"
+ },
+ "node_modules/@react-pdf/reconciler": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@react-pdf/reconciler/-/reconciler-1.1.4.tgz",
+ "integrity": "sha512-oTQDiR/t4Z/Guxac88IavpU2UgN7eR0RMI9DRKvKnvPz2DUasGjXfChAdMqDNmJJxxV26mMy9xQOUV2UU5/okg==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4.1.1",
+ "scheduler": "0.25.0-rc-603e6108-20241029"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@react-pdf/reconciler/node_modules/scheduler": {
+ "version": "0.25.0-rc-603e6108-20241029",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0-rc-603e6108-20241029.tgz",
+ "integrity": "sha512-pFwF6H1XrSdYYNLfOcGlM28/j8CGLu8IvdrxqhjWULe2bPcKiKW4CV+OWqR/9fT52mywx65l7ysNkjLKBda7eA==",
+ "license": "MIT"
+ },
+ "node_modules/@react-pdf/render": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@react-pdf/render/-/render-4.3.0.tgz",
+ "integrity": "sha512-MdWfWaqO6d7SZD75TZ2z5L35V+cHpyA43YNRlJNG0RJ7/MeVGDQv12y/BXOJgonZKkeEGdzM3EpAt9/g4E22WA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.20.13",
+ "@react-pdf/fns": "3.1.2",
+ "@react-pdf/primitives": "^4.1.1",
+ "@react-pdf/textkit": "^6.0.0",
+ "@react-pdf/types": "^2.9.0",
+ "abs-svg-path": "^0.1.1",
+ "color-string": "^1.9.1",
+ "normalize-svg-path": "^1.1.0",
+ "parse-svg-path": "^0.1.2",
+ "svg-arc-to-cubic-bezier": "^3.2.0"
+ }
+ },
+ "node_modules/@react-pdf/renderer": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@react-pdf/renderer/-/renderer-4.3.0.tgz",
+ "integrity": "sha512-28gpA69fU9ZQrDzmd5xMJa1bDf8t0PT3ApUKBl2PUpoE/x4JlvCB5X66nMXrfFrgF2EZrA72zWQAkvbg7TE8zw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.20.13",
+ "@react-pdf/fns": "3.1.2",
+ "@react-pdf/font": "^4.0.2",
+ "@react-pdf/layout": "^4.4.0",
+ "@react-pdf/pdfkit": "^4.0.3",
+ "@react-pdf/primitives": "^4.1.1",
+ "@react-pdf/reconciler": "^1.1.4",
+ "@react-pdf/render": "^4.3.0",
+ "@react-pdf/types": "^2.9.0",
+ "events": "^3.3.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2",
+ "queue": "^6.0.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@react-pdf/stylesheet": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-6.1.0.tgz",
+ "integrity": "sha512-BGZ2sYNUp38VJUegjva/jsri3iiRGnVNjWI+G9dTwAvLNOmwFvSJzqaCsEnqQ/DW5mrTBk/577FhDY7pv6AidA==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-pdf/fns": "3.1.2",
+ "@react-pdf/types": "^2.9.0",
+ "color-string": "^1.9.1",
+ "hsl-to-hex": "^1.0.0",
+ "media-engine": "^1.0.3",
+ "postcss-value-parser": "^4.1.0"
+ }
+ },
+ "node_modules/@react-pdf/textkit": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-6.0.0.tgz",
+ "integrity": "sha512-fDt19KWaJRK/n2AaFoVm31hgGmpygmTV7LsHGJNGZkgzXcFyLsx+XUl63DTDPH3iqxj3xUX128t104GtOz8tTw==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-pdf/fns": "3.1.2",
+ "bidi-js": "^1.0.2",
+ "hyphen": "^1.6.4",
+ "unicode-properties": "^1.4.1"
+ }
+ },
+ "node_modules/@react-pdf/types": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/@react-pdf/types/-/types-2.9.0.tgz",
+ "integrity": "sha512-ckj80vZLlvl9oYrQ4tovEaqKWP3O06Eb1D48/jQWbdwz1Yh7Y9v1cEmwlP8ET+a1Whp8xfdM0xduMexkuPANCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-pdf/font": "^4.0.2",
+ "@react-pdf/primitives": "^4.1.1",
+ "@react-pdf/stylesheet": "^6.1.0"
+ }
+ },
"node_modules/@rollup/pluginutils": {
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz",
@@ -3175,6 +3350,15 @@
"integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
"license": "MIT"
},
+ "node_modules/@swc/helpers": {
+ "version": "0.5.17",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
+ "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
"node_modules/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -3775,6 +3959,12 @@
"license": "(Unlicense OR Apache-2.0)",
"optional": true
},
+ "node_modules/abs-svg-path": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz",
+ "integrity": "sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==",
+ "license": "MIT"
+ },
"node_modules/acorn": {
"version": "8.14.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
@@ -4206,6 +4396,15 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/bidi-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
+ "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
+ "license": "MIT",
+ "dependencies": {
+ "require-from-string": "^2.0.2"
+ }
+ },
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -4299,12 +4498,30 @@
"node": ">=8"
}
},
+ "node_modules/brotli": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz",
+ "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==",
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.1.2"
+ }
+ },
"node_modules/browser-or-node": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz",
"integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==",
"license": "MIT"
},
+ "node_modules/browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "license": "MIT",
+ "dependencies": {
+ "pako": "~1.0.5"
+ }
+ },
"node_modules/browserslist": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
@@ -4682,7 +4899,6 @@
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"license": "MIT",
- "optional": true,
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
@@ -4757,6 +4973,12 @@
"uncrypto": "^0.1.3"
}
},
+ "node_modules/crypto-js": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
+ "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
+ "license": "MIT"
+ },
"node_modules/css-selector-parser": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.1.2.tgz",
@@ -4956,6 +5178,12 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/dfa": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
+ "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==",
+ "license": "MIT"
+ },
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
@@ -5198,6 +5426,15 @@
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
"license": "MIT"
},
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
"node_modules/execa": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz",
@@ -5227,6 +5464,12 @@
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"license": "MIT"
},
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "license": "MIT"
+ },
"node_modules/fast-glob": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
@@ -5349,6 +5592,32 @@
"node": ">=8"
}
},
+ "node_modules/fontkit": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz",
+ "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@swc/helpers": "^0.5.12",
+ "brotli": "^1.3.2",
+ "clone": "^2.1.2",
+ "dfa": "^1.2.0",
+ "fast-deep-equal": "^3.1.3",
+ "restructure": "^3.0.0",
+ "tiny-inflate": "^1.0.3",
+ "unicode-properties": "^1.4.0",
+ "unicode-trie": "^2.0.0"
+ }
+ },
+ "node_modules/fontkit/node_modules/clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/for-each": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
@@ -6186,6 +6455,21 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/hsl-to-hex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/hsl-to-hex/-/hsl-to-hex-1.0.0.tgz",
+ "integrity": "sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==",
+ "license": "MIT",
+ "dependencies": {
+ "hsl-to-rgb-for-reals": "^1.1.0"
+ }
+ },
+ "node_modules/hsl-to-rgb-for-reals": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/hsl-to-rgb-for-reals/-/hsl-to-rgb-for-reals-1.1.1.tgz",
+ "integrity": "sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==",
+ "license": "ISC"
+ },
"node_modules/html-escaper": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
@@ -6227,6 +6511,12 @@
"node": ">=14.18.0"
}
},
+ "node_modules/hyphen": {
+ "version": "1.10.6",
+ "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.10.6.tgz",
+ "integrity": "sha512-fXHXcGFTXOvZTSkPJuGOQf5Lv5T/R2itiiCVPg9LxAje5D00O0pP83yJShFq5V89Ly//Gt6acj7z8pbBr34stw==",
+ "license": "ISC"
+ },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -6331,8 +6621,7 @@
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
- "license": "MIT",
- "optional": true
+ "license": "MIT"
},
"node_modules/is-binary-path": {
"version": "2.1.0",
@@ -6587,6 +6876,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/is-url": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
+ "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==",
+ "license": "MIT"
+ },
"node_modules/is-wsl": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz",
@@ -6623,6 +6918,15 @@
"@pkgjs/parseargs": "^0.11.0"
}
},
+ "node_modules/jay-peg": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/jay-peg/-/jay-peg-1.1.1.tgz",
+ "integrity": "sha512-D62KEuBxz/ip2gQKOEhk/mx14o7eiFRaU+VNNSP4MOiIkwb/D6B3G1Mfas7C/Fit8EsSV2/IWjZElx/Gs6A4ww==",
+ "license": "MIT",
+ "dependencies": {
+ "restructure": "^3.0.0"
+ }
+ },
"node_modules/jiti": {
"version": "1.21.7",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
@@ -6707,6 +7011,25 @@
"url": "https://github.com/sponsors/antonk52"
}
},
+ "node_modules/linebreak": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz",
+ "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "0.0.8",
+ "unicode-trie": "^2.0.0"
+ }
+ },
+ "node_modules/linebreak/node_modules/base64-js": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
+ "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -9301,6 +9624,12 @@
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
"license": "MIT"
},
+ "node_modules/media-engine": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz",
+ "integrity": "sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg==",
+ "license": "MIT"
+ },
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -11358,6 +11687,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/normalize-svg-path": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz",
+ "integrity": "sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==",
+ "license": "MIT",
+ "dependencies": {
+ "svg-arc-to-cubic-bezier": "^3.0.0"
+ }
+ },
"node_modules/not": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/not/-/not-0.1.0.tgz",
@@ -11535,6 +11873,12 @@
"integrity": "sha512-Y8f9qUlBzW8qauJjd/eu6jlpJZsuPJm2ZAV0cDVd420o4EdpH5RPdoCv+60/TdJflGatr4sDfpAL6ArWZbM5tA==",
"license": "MIT"
},
+ "node_modules/pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+ "license": "(MIT AND Zlib)"
+ },
"node_modules/parse-entities": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
@@ -11584,6 +11928,12 @@
"integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==",
"license": "ISC"
},
+ "node_modules/parse-svg-path": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz",
+ "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==",
+ "license": "MIT"
+ },
"node_modules/parse5": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
@@ -11909,6 +12259,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/queue": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
+ "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "~2.0.3"
+ }
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -13880,6 +14239,15 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/resolve": {
"version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
@@ -13940,6 +14308,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/restructure": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz",
+ "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==",
+ "license": "MIT"
+ },
"node_modules/retext": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz",
@@ -14295,7 +14669,6 @@
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"license": "MIT",
- "optional": true,
"dependencies": {
"is-arrayish": "^0.3.1"
}
@@ -14600,6 +14973,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/svg-arc-to-cubic-bezier": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz",
+ "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==",
+ "license": "ISC"
+ },
"node_modules/tailwind-merge": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.0.2.tgz",
@@ -14686,6 +15065,12 @@
"readable-stream": "3"
}
},
+ "node_modules/tiny-inflate": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
+ "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
+ "license": "MIT"
+ },
"node_modules/tinyexec": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
@@ -14828,6 +15213,32 @@
"integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
"license": "MIT"
},
+ "node_modules/unicode-properties": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz",
+ "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==",
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.0",
+ "unicode-trie": "^2.0.0"
+ }
+ },
+ "node_modules/unicode-trie": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
+ "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "pako": "^0.2.5",
+ "tiny-inflate": "^1.0.0"
+ }
+ },
+ "node_modules/unicode-trie/node_modules/pako": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
+ "license": "MIT"
+ },
"node_modules/unified": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
@@ -15474,6 +15885,20 @@
}
}
},
+ "node_modules/vite-compatible-readable-stream": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/vite-compatible-readable-stream/-/vite-compatible-readable-stream-3.6.1.tgz",
+ "integrity": "sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/vitefu": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.6.tgz",
@@ -15777,6 +16202,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/yoga-layout": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz",
+ "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==",
+ "license": "MIT"
+ },
"node_modules/zod": {
"version": "3.24.2",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz",
diff --git a/package.json b/package.json
index 069dc95..7326088 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-toast": "^1.2.6",
+ "@react-pdf/renderer": "^4.3.0",
"@shadcn/ui": "^0.0.4",
"@types/date-fns": "^2.5.3",
"@types/react": "^19.0.12",
diff --git a/public/assets/images/thumb-place.jpg b/public/assets/images/thumb-place.jpg
new file mode 100644
index 0000000..e00f520
Binary files /dev/null and b/public/assets/images/thumb-place.jpg differ
diff --git a/src/components/Login.tsx b/src/components/Login.tsx
index a5f27d6..6ab7239 100644
--- a/src/components/Login.tsx
+++ b/src/components/Login.tsx
@@ -8,6 +8,7 @@ import { Eye, EyeOff, Loader2 } from "lucide-react";
import { Separator } from "./ui/separator";
import { Label } from "./ui/label";
import { useIsLoggedIn } from '../lib/isLoggedIn';
+import Loader from "./ui/loader";
interface AuthStatus {
message: string;
isError: boolean;
@@ -17,6 +18,7 @@ interface UserRecord {
id: string;
email: string;
name?: string;
+ type?: string;
avatar?: string;
[key: string]: any;
}
@@ -43,6 +45,7 @@ const LoginPage = () => {
id: string;
email: string;
name: string;
+ type: string;
avatar: string;
};
}
@@ -54,6 +57,10 @@ const LoginPage = () => {
try {
const authData = await pb.collection("users").authWithPassword(email, password);
+ if (!authData?.token || !authData?.record) {
+ throw new Error("Authentication failed: No token or user record received");
+ }
+
const avatarUrl = authData.record.avatar ? pb.files.getUrl(authData.record, authData.record.avatar) : '';
const authResponse: AuthResponse = {
@@ -62,17 +69,18 @@ const LoginPage = () => {
query: 'new',
id: authData.record.id,
email: authData.record.email,
- name: authData.record.name || '',
+ name: authData.record.name || authData.record.email.split('@')[0], // Fallback name
+ type: authData.record.type || 'user',
avatar: authData.record.avatar || ''
}
};
await syncSessionWithBackend(authResponse, avatarUrl);
window.location.href = '/profile';
- } catch (error) {
+ } catch (error: any) {
console.error("Login failed:", error);
setStatus({
- message: "Login failed. Please check your credentials.",
+ message: error.message || "Login failed. Please check your credentials.",
isError: true
});
} finally {
@@ -99,6 +107,7 @@ const LoginPage = () => {
id: authData.record.id,
email: authData.record.email || '',
name: authData.record.name || '',
+ type: authData.record.type || '',
avatar: authData.record.avatar || ''
}
};
@@ -120,13 +129,14 @@ const LoginPage = () => {
try {
const response = await fetch('https://host-api.cs1.hz.siliconpin.com/v1/users/?query=login', {
method: 'POST',
- credentials: 'include', // Important for cookies
+ credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: 'new',
accessToken: authData.token,
email: authData.record.email,
name: authData.record.name,
+ type: authData.record.type,
avatar: avatarUrl,
isAuthenticated: true,
id: authData.record.id
@@ -134,20 +144,22 @@ const LoginPage = () => {
});
if (!response.ok) {
- throw new Error('Failed to sync session');
+ const errorData = await response.json().catch(() => ({}));
+ throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Session synced with backend:', data);
- } catch (error) {
+ return data;
+ } catch (error: any) {
console.error('Error syncing session:', error);
- throw error; // Re-throw the error if you want calling functions to handle it
+ throw new Error(`Session sync failed: ${error.message}`);
}
};
const { isLoggedIn, loading, error } = useIsLoggedIn();
// console.log(isLoggedIn)
if(loading){
- return
Loading...
+ return
}
if(isLoggedIn){
return (
diff --git a/src/components/Manager/AllSellingList.jsx b/src/components/Manager/AllSellingList.jsx
new file mode 100644
index 0000000..4f3c72f
--- /dev/null
+++ b/src/components/Manager/AllSellingList.jsx
@@ -0,0 +1,422 @@
+import React, { useEffect, useState } from "react";
+import { useIsLoggedIn } from '../../lib/isLoggedIn';
+import Loader from "../../components/ui/loader";
+import { PDFDownloadLink, PDFViewer } from '@react-pdf/renderer';
+import InvoicePDF from "../../lib/InvoicePDF"; // We'll create this component next
+
+export default function AllSellingList() {
+ const { isLoggedIn, loading, error, sessionData } = useIsLoggedIn();
+ const [billingData, setBillingData] = useState([]);
+ const [dataLoading, setDataLoading] = useState(true);
+ const [apiError, setApiError] = useState(null);
+ const [selectedItem, setSelectedItem] = useState(null);
+ const [showModal, setShowModal] = useState(false);
+ const [editMode, setEditMode] = useState(false);
+ const [formData, setFormData] = useState({
+ service: '',
+ tenure: 'monthly',
+ amount: '',
+ user: '',
+ status: 'pending'
+ });
+ const INVOICE_API_URL = 'https://host-api.cs1.hz.siliconpin.com/v1/users/';
+
+ useEffect(() => {
+ if (isLoggedIn && sessionData?.user_type === 'admin') {
+ fetchBillingData();
+ }
+ }, [isLoggedIn, sessionData]);
+
+ const fetchBillingData = async () => {
+ try {
+ const res = await fetch(`${INVOICE_API_URL}?query=all-selling-list`, {
+ method: 'GET',
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ });
+
+ if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
+ const data = await res.json();
+ setBillingData(data.data || []);
+ } catch (err) {
+ setApiError(err.message);
+ } finally {
+ setDataLoading(false);
+ }
+ };
+
+ const handleViewItem = (item) => {
+ setSelectedItem(item);
+ setShowModal(true);
+ setEditMode(false);
+ };
+
+ const handleEditItem = (item) => {
+ setSelectedItem(item);
+ setFormData({
+ service: item.service,
+ tenure: item.tenure,
+ amount: item.amount,
+ user: item.user,
+ status: item.status
+ });
+ setEditMode(true);
+ setShowModal(true);
+ };
+
+ const handleDeleteItem = async (id) => {
+ if (!window.confirm('Are you sure you want to delete this billing record?')) return;
+
+ try {
+ const res = await fetch(`${INVOICE_API_URL}?query=delete-billing&id=${id}`, {
+ method: 'DELETE',
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ });
+
+ if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
+ fetchBillingData();
+ } catch (err) {
+ setApiError(err.message);
+ }
+ };
+
+ const handleCreateNew = () => {
+ setSelectedItem(null);
+ setFormData({
+ service: '',
+ tenure: 'monthly',
+ amount: '',
+ user: '',
+ status: 'pending'
+ });
+ setEditMode(true);
+ setShowModal(true);
+ };
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ try {
+ const url = selectedItem
+ ? `${INVOICE_API_URL}?query=update-billing&id=${selectedItem.id}`
+ : `${INVOICE_API_URL}?query=create-billing`;
+
+ const method = selectedItem ? 'PUT' : 'POST';
+
+ const res = await fetch(url, {
+ method,
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(formData)
+ });
+
+ if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
+ fetchBillingData();
+ setShowModal(false);
+ } catch (err) {
+ setApiError(err.message);
+ }
+ };
+
+ const handleInputChange = (e) => {
+ const { name, value } = e.target;
+ setFormData(prev => ({
+ ...prev,
+ [name]: value
+ }));
+ };
+
+ const closeModal = () => {
+ setShowModal(false);
+ setSelectedItem(null);
+ setEditMode(false);
+ };
+
+ const getStatusColor = (status) => {
+ switch (status) {
+ case 'completed': return 'bg-green-100 text-green-800';
+ case 'pending': return 'bg-yellow-100 text-yellow-800';
+ case 'failed': return 'bg-red-100 text-red-800';
+ default: return 'bg-gray-100 text-gray-800';
+ }
+ };
+
+ const formatDate = (dateString) => {
+ if (!dateString) return 'N/A';
+ const options = { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' };
+ return new Date(dateString).toLocaleDateString(undefined, options);
+ };
+
+ const formatCurrency = (amount) => {
+ if (!amount) return '$0.00';
+ return new Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency: 'USD'
+ }).format(parseFloat(amount));
+ };
+
+ if (loading || dataLoading) return ;
+ if (error || apiError) return Error: {error?.message || apiError}
;
+ if (!isLoggedIn || sessionData?.user_type !== 'admin') {
+ return You are not authorized to view this page. Click Here to go to the homepage.
;
+ }
+
+ return (
+
+
+
Billing Management
+
+ Create New
+
+
+
+
+
+
+
+
+ Billing ID
+ Service
+ User
+ Amount
+ Status
+ Created At
+ Actions
+
+
+
+ {billingData.map((item) => (
+
+
+ {item.billing_id}
+
+
+ {item.service}
+
+
+ {item.user}
+
+
+ {formatCurrency(item.amount)}
+
+
+
+ {item.status.charAt(0).toUpperCase() + item.status.slice(1)}
+
+
+
+ {formatDate(item.created_at)}
+
+
+ handleViewItem(item)}
+ className="text-indigo-600 hover:text-indigo-900 mr-2"
+ >
+ View
+
+ handleEditItem(item)}
+ className="text-yellow-600 hover:text-yellow-900 mr-2"
+ >
+ Edit
+
+ handleDeleteItem(item.id)}
+ className="text-red-600 hover:text-red-900 mr-2"
+ >
+ Delete
+
+ }
+ fileName={`invoice_${item.billing_id}.pdf`}
+ className="text-green-600 hover:text-green-900"
+ >
+ {({ loading }) => (loading ? 'Preparing...' : 'PDF')}
+
+
+
+ ))}
+
+
+
+
+
+ {/* Modal for View/Edit */}
+ {showModal && (
+
+
+
+
+
+ {editMode ? (selectedItem ? 'Edit Billing' : 'Create New Billing') : 'Billing Details'}
+
+
+
+
+
+
+
+
+ {editMode ? (
+
+ ) : (
+ <>
+
+
+
Billing ID
+
{selectedItem.billing_id}
+
+
+
Service
+
{selectedItem.service}
+
+
+
User
+
{selectedItem.user}
+
+
+
Tenure
+
{selectedItem.tenure}
+
+
+
Amount
+
{formatCurrency(selectedItem.amount)}
+
+
+
Status
+
+ {selectedItem.status.charAt(0).toUpperCase() + selectedItem.status.slice(1)}
+
+
+
+
Created At
+
{formatDate(selectedItem.created_at)}
+
+
+
Updated At
+
{formatDate(selectedItem.updated_at)}
+
+
+
+
+
}
+ fileName={`invoice_${selectedItem.billing_id}.pdf`}
+ className="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700"
+ >
+ {({ loading }) => (loading ? 'Preparing PDF...' : 'Download PDF')}
+
+
handleEditItem(selectedItem)}
+ className="px-4 py-2 bg-yellow-600 text-white rounded hover:bg-yellow-700"
+ >
+ Edit
+
+
+ Close
+
+
+ >
+ )}
+
+
+
+ )}
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/MyTopic.jsx b/src/components/MyTopic.jsx
index f7b0866..dfbe367 100644
--- a/src/components/MyTopic.jsx
+++ b/src/components/MyTopic.jsx
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from "react";
import TopicItems from "./TopicItem";
import { useIsLoggedIn } from '../lib/isLoggedIn';
-
+import Loader from "./ui/loader";
const topicPageDesc = 'Cutting-edge discussions on tech, digital services, news, and digital freedom. Stay informed on AI, cybersecurity, privacy, and the future of innovation.';
export default function TopicCreation(props) {
@@ -38,7 +38,7 @@ export default function TopicCreation(props) {
}, []);
if (authLoading || loading) {
- return Loading...
;
+ return ;
}
if (authError || error) {
diff --git a/src/components/TopicDetail.jsx b/src/components/TopicDetail.jsx
index 7278c2b..df02073 100644
--- a/src/components/TopicDetail.jsx
+++ b/src/components/TopicDetail.jsx
@@ -11,7 +11,11 @@ export default function TopicDetail(props) {
return (
-
+ {
+ props.topic.img && (
+
+ )
+ }
{props.topic.title}
diff --git a/src/components/TopicEdit.jsx b/src/components/TopicEdit.jsx
index b9b892f..028240b 100644
--- a/src/components/TopicEdit.jsx
+++ b/src/components/TopicEdit.jsx
@@ -7,7 +7,7 @@ import { Button } from './ui/button';
import { Separator } from './ui/separator';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from './ui/dialog';
import { CustomTabs } from './ui/tabs';
-
+import Loader from "./ui/loader";
const TOPIC_API_URL = 'https://host-api.cs1.hz.siliconpin.com/v1/topics/';
const MINIO_UPLOAD_URL = 'https://your-minio-api-endpoint/upload';
@@ -269,10 +269,7 @@ export default function EditTopic (){
// Loading state
if (isLoading) {
return (
-
+
);
}
@@ -280,10 +277,10 @@ export default function EditTopic (){
if (success) {
return (
-
Topic has been successfully updated!
+
Topic has been successfully updated!
You are being automatically redirected to the topic page...
- navigate(`/topic/${formData.slug}`)}>Preview this Topic
+ window.location.href = `/topic/${formData.slug}`}>Preview this Topic
);
diff --git a/src/components/TopicItem.jsx b/src/components/TopicItem.jsx
index 234a3a5..89d4010 100644
--- a/src/components/TopicItem.jsx
+++ b/src/components/TopicItem.jsx
@@ -1,11 +1,13 @@
import React from "react";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "./ui/card";
import { Button } from "./ui/button";
+import { Input } from "./ui/input";
import { useIsLoggedIn } from '../lib/isLoggedIn';
-import { Pencil, Trash2 } from "lucide-react"; // Import icons for better visual
-
+import { Pencil, Trash2, Search } from "lucide-react";
+import { marked } from 'marked';
export default function TopicItems(props) {
const { isLoggedIn, loading, error, sessionData } = useIsLoggedIn();
+ const [localSearchTerm, setLocalSearchTerm] = React.useState(props.searchTerm || '');
if (loading) {
return
Loading...
;
@@ -15,11 +17,33 @@ export default function TopicItems(props) {
return
Error loading authentication status
;
}
+ const handleSearchChange = (e) => {
+ setLocalSearchTerm(e.target.value);
+ };
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+ props.onSearch(e);
+ };
+
return (
{props.title}
{props.description}
+
{
props.topics.length > 0 ? (
@@ -28,17 +52,13 @@ export default function TopicItems(props) {
props.topics.map((topic) => (
-
-
+
+
{topic.title}
-
- {topic.description}
+
- {
- // console.log('props.mytopic', props.mytopic)
- }
{isLoggedIn && sessionData.user_email === topic.user && props.mytopic === true && (
);
-}
\ No newline at end of file
+}
diff --git a/src/components/Topics _Old_copy.jsx b/src/components/Topics _Old_copy.jsx
new file mode 100644
index 0000000..250e832
--- /dev/null
+++ b/src/components/Topics _Old_copy.jsx
@@ -0,0 +1,232 @@
+import React, { useState, useEffect } from "react";
+import TopicItems from "./TopicItem";
+import { useIsLoggedIn } from '../lib/isLoggedIn';
+import { Button } from "./ui/button";
+
+const topicPageDesc = 'Cutting-edge discussions on tech, digital services, news, and digital freedom. Stay informed on AI, cybersecurity, privacy, and the future of innovation.';
+
+export default function TopicCreation() {
+ const { isLoggedIn, loading: authLoading, error: authError } = useIsLoggedIn();
+ const [topics, setTopics] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+ const [pagination, setPagination] = useState({
+ current_page: 1,
+ last_page: 1,
+ per_page: 10,
+ total: 0
+ });
+
+ // Get current page from URL or default to 1
+ const getCurrentPage = () => {
+ const params = new URLSearchParams(window.location.search);
+ const page = parseInt(params.get('page')) || 1;
+ return Math.max(1, Math.min(page, pagination.last_page));
+ };
+
+ // Fetch topics data with abort controller
+ const fetchTopics = async (page) => {
+ setLoading(true);
+ try {
+ const response = await fetch(
+ `https://host-api.cs1.hz.siliconpin.com/v1/topics/?query=get-all-topics&page=${page}`,
+ {
+ method: 'GET',
+ credentials: 'include'
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+
+ const data = await response.json();
+ setTopics(data.data || []);
+ setPagination(prev => ({
+ ...data.pagination,
+ current_page: Math.min(data.pagination.current_page, data.pagination.last_page)
+ }));
+ } catch (err) {
+ setError(err.message);
+ console.error('Fetch error:', err);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ // Handle page change
+ const handlePageChange = (newPage) => {
+ const validatedPage = Math.max(1, Math.min(newPage, pagination.last_page));
+ window.history.pushState({}, '', `?page=${validatedPage}`);
+ fetchTopics(validatedPage);
+ window.scrollTo({ top: 0, behavior: 'smooth' });
+ };
+
+ // Initial load and URL change handling
+ useEffect(() => {
+ fetchTopics(getCurrentPage());
+
+ const handlePopState = () => {
+ fetchTopics(getCurrentPage());
+ };
+
+ window.addEventListener('popstate', handlePopState);
+ return () => {
+ window.removeEventListener('popstate', handlePopState);
+ };
+ }, []);
+
+ if (authLoading) {
+ return ;
+ }
+
+ if (authError) {
+ return Error loading authentication status
;
+ }
+
+ return (
+ <>
+ {isLoggedIn && (
+
+ )}
+
+ {loading && !topics.length ? (
+
+ ) : error ? (
+ Error loading topics: {error}
+ ) : (
+ <>
+
+
+ {pagination.last_page > 1 && (
+
+
+ Showing {(pagination.current_page - 1) * pagination.per_page + 1}-
+ {Math.min(pagination.current_page * pagination.per_page, pagination.total)} of {pagination.total} topics
+
+
+
+ {
+ pagination.current_page > 1 && (
+ <>
+
handlePageChange(1)}
+ disabled={pagination.current_page <= 1}
+ className="hidden sm:inline-flex"
+ >
+ First
+
+
handlePageChange(pagination.current_page - 1)}
+ disabled={pagination.current_page <= 1}
+ >
+ Previous
+
+ >
+ )
+ }
+
+
+
+
+ {generatePageNumbers(pagination.current_page, pagination.last_page).map((page, i) => (
+ page === '...' ? (
+ ...
+ ) : (
+ handlePageChange(page)}
+ className="min-w-10"
+ >
+ {page}
+
+ )
+ ))}
+
+
+
handlePageChange(pagination.current_page + 1)}
+ disabled={pagination.current_page >= pagination.last_page}
+ >
+ Next
+
+
handlePageChange(pagination.last_page)}
+ disabled={pagination.current_page >= pagination.last_page}
+ className="hidden sm:inline-flex"
+ >
+ Last
+
+
+
+ )}
+ >
+ )}
+ >
+ );
+}
+
+// Helper function to generate smart page numbers
+function generatePageNumbers(currentPage, lastPage) {
+ const pages = [];
+ const maxVisible = 5; // Maximum visible page numbers
+
+ if (lastPage <= maxVisible) {
+ for (let i = 1; i <= lastPage; i++) {
+ pages.push(i);
+ }
+ } else {
+ // Always show first page
+ pages.push(1);
+
+ // Calculate start and end of middle pages
+ let start = Math.max(2, currentPage - 1);
+ let end = Math.min(lastPage - 1, currentPage + 1);
+
+ // Adjust if we're at the beginning
+ if (currentPage <= 3) {
+ end = maxVisible - 2;
+ }
+
+ // Adjust if we're at the end
+ if (currentPage >= lastPage - 2) {
+ start = lastPage - (maxVisible - 2);
+ }
+
+ // Add ellipsis if needed
+ if (start > 2) {
+ pages.push('...');
+ }
+
+ // Add middle pages
+ for (let i = start; i <= end; i++) {
+ pages.push(i);
+ }
+
+ // Add ellipsis if needed
+ if (end < lastPage - 1) {
+ pages.push('...');
+ }
+
+ // Always show last page
+ pages.push(lastPage);
+ }
+
+ return pages;
+}
\ No newline at end of file
diff --git a/src/components/Topics.jsx b/src/components/Topics.jsx
index fe41bfb..e98f499 100644
--- a/src/components/Topics.jsx
+++ b/src/components/Topics.jsx
@@ -1,29 +1,262 @@
-import React from "react";
+import React, { useState, useEffect } from "react";
import TopicItems from "./TopicItem";
import { useIsLoggedIn } from '../lib/isLoggedIn';
-
+import { Button } from "./ui/button";
+import Loader from "./ui/loader";
const topicPageDesc = 'Cutting-edge discussions on tech, digital services, news, and digital freedom. Stay informed on AI, cybersecurity, privacy, and the future of innovation.';
-export default function TopicCreation(props) {
- const { isLoggedIn, loading, error } = useIsLoggedIn();
+export default function TopicCreation() {
+ const { isLoggedIn, loading: authLoading, error: authError } = useIsLoggedIn();
+ const [topics, setTopics] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+ const [searchTerm, setSearchTerm] = useState('');
+ const [pagination, setPagination] = useState({
+ current_page: 1,
+ last_page: 1,
+ per_page: 10,
+ total: 0
+ });
- if (loading) {
- return Loading...
;
- }
+ // Get current page from URL or default to 1
+ const getCurrentPage = () => {
+ const params = new URLSearchParams(window.location.search);
+ const page = parseInt(params.get('page')) || 1;
+ return Math.max(1, Math.min(page, pagination.last_page));
+ };
- if (error) {
- return Error loading authentication status
;
- }
+ // Fetch topics data
+ const fetchTopics = async (page, search = '') => {
+ setLoading(true);
+ try {
+ let url = `https://host-api.cs1.hz.siliconpin.com/v1/topics/?query=get-all-topics&page=${page}`;
+
+ if (search) {
+ url += `&search=${encodeURIComponent(search)}`;
+ }
+
+ const response = await fetch(url, {
+ method: 'GET',
+ credentials: 'include'
+ });
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+
+ const data = await response.json();
+ setTopics(data.data || []);
+ setPagination(prev => ({
+ ...data.pagination,
+ current_page: Math.min(data.pagination.current_page, data.pagination.last_page)
+ }));
+ setSearchTerm(data.search_term || '');
+ } catch (err) {
+ setError(err.message);
+ console.error('Fetch error:', err);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ // Handle page change
+ const handlePageChange = (newPage) => {
+ const validatedPage = Math.max(1, Math.min(newPage, pagination.last_page));
+ const params = new URLSearchParams(window.location.search);
+ params.set('page', validatedPage);
+ window.history.pushState({}, '', `?${params.toString()}`);
+ fetchTopics(validatedPage, searchTerm);
+ window.scrollTo({ top: 0, behavior: 'smooth' });
+ };
+
+ // Handle search
+ const handleSearch = (e) => {
+ e.preventDefault();
+ const newSearchTerm = e.target.elements.search.value.trim();
+ setSearchTerm(newSearchTerm);
+
+ // Reset to page 1 when searching
+ const params = new URLSearchParams(window.location.search);
+ params.set('page', 1);
+ if (newSearchTerm) {
+ params.set('search', newSearchTerm);
+ } else {
+ params.delete('search');
+ }
+ window.history.pushState({}, '', `?${params.toString()}`);
+ fetchTopics(1, newSearchTerm);
+ };
+
+ // Initial load and URL change handling
+ useEffect(() => {
+ const params = new URLSearchParams(window.location.search);
+ const initialSearch = params.get('search') || '';
+ setSearchTerm(initialSearch);
+ fetchTopics(getCurrentPage(), initialSearch);
+
+ const handlePopState = () => {
+ const newParams = new URLSearchParams(window.location.search);
+ const newSearch = newParams.get('search') || '';
+ setSearchTerm(newSearch);
+ fetchTopics(getCurrentPage(), newSearch);
+ };
+
+ window.addEventListener('popstate', handlePopState);
+ return () => {
+ window.removeEventListener('popstate', handlePopState);
+ };
+ }, []);
+
+ // ... (keep existing authLoading and authError checks)
return (
<>
{isLoggedIn && (
-
+
)}
-
+
+ {loading && !topics.length ? (
+
+ ) : error ? (
+
Error loading topics: {error}
+ ) : (
+ <>
+
+
+ {pagination.last_page > 1 && (
+
+
+ Showing {(pagination.current_page - 1) * pagination.per_page + 1}-
+ {Math.min(pagination.current_page * pagination.per_page, pagination.total)} of {pagination.total} topics
+ {searchTerm && (
+ matching "{searchTerm}"
+ )}
+
+
+
+ {
+ pagination.current_page > 1 && (
+ <>
+
handlePageChange(1)}
+ disabled={pagination.current_page <= 1}
+ className="hidden sm:inline-flex"
+ >
+ First
+
+
handlePageChange(pagination.current_page - 1)}
+ disabled={pagination.current_page <= 1}
+ >
+ Previous
+
+ >
+ )
+ }
+
+
+
+
+ {generatePageNumbers(pagination.current_page, pagination.last_page).map((page, i) => (
+ page === '...' ? (
+ ...
+ ) : (
+ handlePageChange(page)}
+ className="min-w-10"
+ >
+ {page}
+
+ )
+ ))}
+
+
+
handlePageChange(pagination.current_page + 1)}
+ disabled={pagination.current_page >= pagination.last_page}
+ >
+ Next
+
+
handlePageChange(pagination.last_page)}
+ disabled={pagination.current_page >= pagination.last_page}
+ className="hidden sm:inline-flex"
+ >
+ Last
+
+
+
+ )}
+ >
+ )}
>
);
+}
+
+// Helper function to generate smart page numbers
+function generatePageNumbers(currentPage, lastPage) {
+ const pages = [];
+ const maxVisible = 5; // Maximum visible page numbers
+
+ if (lastPage <= maxVisible) {
+ for (let i = 1; i <= lastPage; i++) {
+ pages.push(i);
+ }
+ } else {
+ // Always show first page
+ pages.push(1);
+
+ // Calculate start and end of middle pages
+ let start = Math.max(2, currentPage - 1);
+ let end = Math.min(lastPage - 1, currentPage + 1);
+
+ // Adjust if we're at the beginning
+ if (currentPage <= 3) {
+ end = maxVisible - 2;
+ }
+
+ // Adjust if we're at the end
+ if (currentPage >= lastPage - 2) {
+ start = lastPage - (maxVisible - 2);
+ }
+
+ // Add ellipsis if needed
+ if (start > 2) {
+ pages.push('...');
+ }
+
+ // Add middle pages
+ for (let i = start; i <= end; i++) {
+ pages.push(i);
+ }
+
+ // Add ellipsis if needed
+ if (end < lastPage - 1) {
+ pages.push('...');
+ }
+
+ // Always show last page
+ pages.push(lastPage);
+ }
+
+ return pages;
}
\ No newline at end of file
diff --git a/src/components/UserProfile.tsx b/src/components/UserProfile.tsx
index d261539..c2cdf02 100644
--- a/src/components/UserProfile.tsx
+++ b/src/components/UserProfile.tsx
@@ -9,7 +9,7 @@ import { Textarea } from "./ui/textarea";
import React, { useState, useEffect } from 'react';
import UpdateAvatar from './UpdateAvatar';
import {localizeTime} from "../lib/localizeTime";
-
+import Loader from "./ui/loader";
interface SessionData {
[key: string]: any;
}
@@ -95,7 +95,7 @@ export default function ProfilePage() {
}
if (!userData) {
- return (
Loading profile data...
);
+ return (
);
}
return (
diff --git a/src/components/ui/loader.jsx b/src/components/ui/loader.jsx
new file mode 100644
index 0000000..a71771c
--- /dev/null
+++ b/src/components/ui/loader.jsx
@@ -0,0 +1,80 @@
+import React, { useEffect } from 'react';
+
+const Loader = () => {
+ // CSS styles object
+ const styles = {
+ container: {
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: '100vh',
+ width: '100%',
+ },
+ loader: {
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: '16px',
+ },
+ dot: {
+ width: '12px',
+ height: '12px',
+ margin: '0 4px',
+ backgroundColor: '#6d9e37',
+ borderRadius: '50%',
+ display: 'inline-block',
+ animation: 'bounce 1.4s infinite ease-in-out both',
+ },
+ dot1: {
+ animationDelay: '-0.32s',
+ },
+ dot2: {
+ animationDelay: '-0.16s',
+ },
+ text: {
+ color: '#6d9e37',
+ fontSize: '1rem',
+ fontWeight: '500',
+ },
+ // Keyframes as a string to be injected
+ keyframes: `
+ @keyframes bounce {
+ 0%, 80%, 100% {
+ transform: scale(0);
+ }
+ 40% {
+ transform: scale(1.0);
+ }
+ }
+ `,
+ };
+
+ useEffect(() => {
+ // Only run on client-side where document is available
+ if (typeof document !== 'undefined') {
+ const styleSheet = document.styleSheets[0];
+ try {
+ styleSheet.insertRule(styles.keyframes, styleSheet.cssRules.length);
+ } catch (e) {
+ // Fallback for browsers that might not support this
+ const styleElement = document.createElement('style');
+ styleElement.innerHTML = styles.keyframes;
+ document.head.appendChild(styleElement);
+ }
+ }
+ }, []); // Empty dependency array means this runs once on mount
+
+ return (
+
+ );
+};
+
+export default Loader;
\ No newline at end of file
diff --git a/src/lib/InvoicePDF.jsx b/src/lib/InvoicePDF.jsx
new file mode 100644
index 0000000..29b2386
--- /dev/null
+++ b/src/lib/InvoicePDF.jsx
@@ -0,0 +1,187 @@
+import React from 'react';
+import { Page, Text, View, Document, StyleSheet } from '@react-pdf/renderer';
+
+// Create styles
+const styles = StyleSheet.create({
+ page: {
+ flexDirection: 'column',
+ backgroundColor: '#FFFFFF',
+ padding: 40
+ },
+ header: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ marginBottom: 20,
+ borderBottomWidth: 2,
+ borderBottomColor: '#6d9e37',
+ paddingBottom: 10
+ },
+ title: {
+ fontSize: 24,
+ fontWeight: 'bold',
+ color: '#6d9e37'
+ },
+ section: {
+ marginBottom: 20
+ },
+ row: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ marginBottom: 5
+ },
+ label: {
+ fontSize: 12,
+ fontWeight: 'bold'
+ },
+ value: {
+ fontSize: 12
+ },
+ divider: {
+ borderBottomWidth: 1,
+ borderBottomColor: '#EEEEEE',
+ marginVertical: 10
+ },
+ tableHeader: {
+ flexDirection: 'row',
+ backgroundColor: '#F5F5F5',
+ padding: 5,
+ marginBottom: 5
+ },
+ tableRow: {
+ flexDirection: 'row',
+ padding: 5,
+ borderBottomWidth: 1,
+ borderBottomColor: '#EEEEEE'
+ },
+ col1: {
+ width: '40%'
+ },
+ col2: {
+ width: '30%',
+ textAlign: 'right'
+ },
+ col3: {
+ width: '30%',
+ textAlign: 'right'
+ },
+ total: {
+ flexDirection: 'row',
+ justifyContent: 'flex-end',
+ marginTop: 10
+ },
+ totalText: {
+ fontSize: 14,
+ fontWeight: 'bold'
+ },
+ footer: {
+ position: 'absolute',
+ bottom: 30,
+ left: 40,
+ right: 40,
+ textAlign: 'center',
+ fontSize: 10,
+ color: '#999999'
+ },
+ status: {
+ padding: 3,
+ borderRadius: 3,
+ fontSize: 10,
+ fontWeight: 'bold'
+ }
+});
+
+const InvoicePDF = ({ data }) => {
+ const statusColor = data.status === 'completed' ? '#10B981' : '#EF4444';
+
+ return (
+
+
+ {/* Header */}
+
+
+ INVOICE
+ Invoice #: {data.billing_id}
+ Date: {new Date(data.created_at).toLocaleDateString()}
+
+
+ Your Company
+ 123 Business Street
+ City, Country
+ contact@yourcompany.com
+
+
+
+ {/* Bill To */}
+
+
+
+ BILL TO:
+ {data.user}
+
+
+ STATUS:
+
+ {data.status.toUpperCase()}
+
+
+
+
+
+
+
+ {/* Items Table */}
+
+
+ DESCRIPTION
+ TENURE
+ AMOUNT
+
+
+ {data.service}
+ {data.tenure}
+
+ {new Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency: 'USD'
+ }).format(parseFloat(data.amount))}
+
+
+
+
+
+
+ {/* Total */}
+
+
+
+ SUBTOTAL:
+
+ {new Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency: 'USD'
+ }).format(parseFloat(data.amount))}
+
+
+
+ TOTAL:
+
+ {new Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency: 'USD'
+ }).format(parseFloat(data.amount))}
+
+
+
+
+
+ {/* Footer */}
+
+ Thank you for your business!
+ Please make payments payable to Your Company
+
+
+
+ );
+};
+
+export default InvoicePDF;
\ No newline at end of file
diff --git a/src/pages/manager/selling-list.astro b/src/pages/manager/selling-list.astro
new file mode 100644
index 0000000..308c327
--- /dev/null
+++ b/src/pages/manager/selling-list.astro
@@ -0,0 +1,7 @@
+---
+import Layout from "../../layouts/Layout.astro";
+import AllSellingList from "../../components/Manager/AllSellingList"
+---
+
+
+
\ No newline at end of file
diff --git a/src/pages/topic/[id].astro b/src/pages/topic/[id].astro
index 2801400..e6baf1c 100644
--- a/src/pages/topic/[id].astro
+++ b/src/pages/topic/[id].astro
@@ -19,7 +19,7 @@ try {
const data = await response.json();
topic = data.data[0]; // Assuming single result
- console.log('Single Topic:', topic);
+ // console.log('Single Topic:', topic);
} catch (error) {
console.error('Error fetching single topic:', error);
}
@@ -28,7 +28,7 @@ export async function getStaticPaths() {
const TOPIC_API_URL = 'https://host-api.cs1.hz.siliconpin.com/v1/topics/';
try {
- const response = await fetch(`${TOPIC_API_URL}?query=get-all-topics`, {
+ const response = await fetch(`${TOPIC_API_URL}?query=get-all-topics-for-slug`, {
method: 'GET',
credentials: 'include',
});
diff --git a/src/pages/topic/index.astro b/src/pages/topic/index.astro
index 97d10f2..a6e78fc 100644
--- a/src/pages/topic/index.astro
+++ b/src/pages/topic/index.astro
@@ -6,7 +6,7 @@ const TOPIC_API_URL = 'https://host-api.cs1.hz.siliconpin.com/v1/topics/';
let topics = [];
try {
- const response = await fetch(`${TOPIC_API_URL}?query=get-all-topics`, {
+ const response = await fetch(`${TOPIC_API_URL}?query=get-all-topics-for-slug`, {
method: 'GET',
credentials: 'include',
});
@@ -16,13 +16,13 @@ try {
}
const data = await response.json();
+ // console.log('Topic Data', data)
topics = data.data || [];
- // console.log('Topic Data', data);
} catch (error) {
console.error('An error occurred', error);
}
---
-
+
diff --git a/yarn.lock b/yarn.lock
index 5a0198d..35afb45 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -213,7 +213,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.25.9"
-"@babel/runtime@^7.14.6", "@babel/runtime@^7.17.2":
+"@babel/runtime@^7.14.6", "@babel/runtime@^7.17.2", "@babel/runtime@^7.20.13":
version "7.27.0"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz"
integrity sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==
@@ -650,6 +650,144 @@
resolved "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz"
integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==
+"@react-pdf/fns@3.1.2":
+ version "3.1.2"
+ resolved "https://registry.npmjs.org/@react-pdf/fns/-/fns-3.1.2.tgz"
+ integrity sha512-qTKGUf0iAMGg2+OsUcp9ffKnKi41RukM/zYIWMDJ4hRVYSr89Q7e3wSDW/Koqx3ea3Uy/z3h2y3wPX6Bdfxk6g==
+
+"@react-pdf/font@^4.0.2":
+ version "4.0.2"
+ resolved "https://registry.npmjs.org/@react-pdf/font/-/font-4.0.2.tgz"
+ integrity sha512-/dAWu7Y2RD1RxarDZ9SkYPHgBYOhmcDnet4W/qN/m8k+A2Hr3ja54GymSR7GGxWBtxjKtNauVKrTa9LS1n8WUw==
+ dependencies:
+ "@react-pdf/pdfkit" "^4.0.3"
+ "@react-pdf/types" "^2.9.0"
+ fontkit "^2.0.2"
+ is-url "^1.2.4"
+
+"@react-pdf/image@^3.0.3":
+ version "3.0.3"
+ resolved "https://registry.npmjs.org/@react-pdf/image/-/image-3.0.3.tgz"
+ integrity sha512-lvP5ryzYM3wpbO9bvqLZYwEr5XBDX9jcaRICvtnoRqdJOo7PRrMnmB4MMScyb+Xw10mGeIubZAAomNAG5ONQZQ==
+ dependencies:
+ "@react-pdf/png-js" "^3.0.0"
+ jay-peg "^1.1.1"
+
+"@react-pdf/layout@^4.4.0":
+ version "4.4.0"
+ resolved "https://registry.npmjs.org/@react-pdf/layout/-/layout-4.4.0.tgz"
+ integrity sha512-Aq+Cc6JYausWLoks2FvHe3PwK9cTuvksB2uJ0AnkKJEUtQbvCq8eCRb1bjbbwIji9OzFRTTzZij7LzkpKHjIeA==
+ dependencies:
+ "@react-pdf/fns" "3.1.2"
+ "@react-pdf/image" "^3.0.3"
+ "@react-pdf/primitives" "^4.1.1"
+ "@react-pdf/stylesheet" "^6.1.0"
+ "@react-pdf/textkit" "^6.0.0"
+ "@react-pdf/types" "^2.9.0"
+ emoji-regex "^10.3.0"
+ queue "^6.0.1"
+ yoga-layout "^3.2.1"
+
+"@react-pdf/pdfkit@^4.0.3":
+ version "4.0.3"
+ resolved "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-4.0.3.tgz"
+ integrity sha512-k+Lsuq8vTwWsCqTp+CCB4+2N+sOTFrzwGA7aw3H9ix/PDWR9QksbmNg0YkzGbLAPI6CeawmiLHcf4trZ5ecLPQ==
+ dependencies:
+ "@babel/runtime" "^7.20.13"
+ "@react-pdf/png-js" "^3.0.0"
+ browserify-zlib "^0.2.0"
+ crypto-js "^4.2.0"
+ fontkit "^2.0.2"
+ jay-peg "^1.1.1"
+ linebreak "^1.1.0"
+ vite-compatible-readable-stream "^3.6.1"
+
+"@react-pdf/png-js@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-3.0.0.tgz"
+ integrity sha512-eSJnEItZ37WPt6Qv5pncQDxLJRK15eaRwPT+gZoujP548CodenOVp49GST8XJvKMFt9YqIBzGBV/j9AgrOQzVA==
+ dependencies:
+ browserify-zlib "^0.2.0"
+
+"@react-pdf/primitives@^4.1.1":
+ version "4.1.1"
+ resolved "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-4.1.1.tgz"
+ integrity sha512-IuhxYls1luJb7NUWy6q5avb1XrNaVj9bTNI40U9qGRuS6n7Hje/8H8Qi99Z9UKFV74bBP3DOf3L1wV2qZVgVrQ==
+
+"@react-pdf/reconciler@^1.1.4":
+ version "1.1.4"
+ resolved "https://registry.npmjs.org/@react-pdf/reconciler/-/reconciler-1.1.4.tgz"
+ integrity sha512-oTQDiR/t4Z/Guxac88IavpU2UgN7eR0RMI9DRKvKnvPz2DUasGjXfChAdMqDNmJJxxV26mMy9xQOUV2UU5/okg==
+ dependencies:
+ object-assign "^4.1.1"
+ scheduler "0.25.0-rc-603e6108-20241029"
+
+"@react-pdf/render@^4.3.0":
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/@react-pdf/render/-/render-4.3.0.tgz"
+ integrity sha512-MdWfWaqO6d7SZD75TZ2z5L35V+cHpyA43YNRlJNG0RJ7/MeVGDQv12y/BXOJgonZKkeEGdzM3EpAt9/g4E22WA==
+ dependencies:
+ "@babel/runtime" "^7.20.13"
+ "@react-pdf/fns" "3.1.2"
+ "@react-pdf/primitives" "^4.1.1"
+ "@react-pdf/textkit" "^6.0.0"
+ "@react-pdf/types" "^2.9.0"
+ abs-svg-path "^0.1.1"
+ color-string "^1.9.1"
+ normalize-svg-path "^1.1.0"
+ parse-svg-path "^0.1.2"
+ svg-arc-to-cubic-bezier "^3.2.0"
+
+"@react-pdf/renderer@^4.3.0":
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/@react-pdf/renderer/-/renderer-4.3.0.tgz"
+ integrity sha512-28gpA69fU9ZQrDzmd5xMJa1bDf8t0PT3ApUKBl2PUpoE/x4JlvCB5X66nMXrfFrgF2EZrA72zWQAkvbg7TE8zw==
+ dependencies:
+ "@babel/runtime" "^7.20.13"
+ "@react-pdf/fns" "3.1.2"
+ "@react-pdf/font" "^4.0.2"
+ "@react-pdf/layout" "^4.4.0"
+ "@react-pdf/pdfkit" "^4.0.3"
+ "@react-pdf/primitives" "^4.1.1"
+ "@react-pdf/reconciler" "^1.1.4"
+ "@react-pdf/render" "^4.3.0"
+ "@react-pdf/types" "^2.9.0"
+ events "^3.3.0"
+ object-assign "^4.1.1"
+ prop-types "^15.6.2"
+ queue "^6.0.1"
+
+"@react-pdf/stylesheet@^6.1.0":
+ version "6.1.0"
+ resolved "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-6.1.0.tgz"
+ integrity sha512-BGZ2sYNUp38VJUegjva/jsri3iiRGnVNjWI+G9dTwAvLNOmwFvSJzqaCsEnqQ/DW5mrTBk/577FhDY7pv6AidA==
+ dependencies:
+ "@react-pdf/fns" "3.1.2"
+ "@react-pdf/types" "^2.9.0"
+ color-string "^1.9.1"
+ hsl-to-hex "^1.0.0"
+ media-engine "^1.0.3"
+ postcss-value-parser "^4.1.0"
+
+"@react-pdf/textkit@^6.0.0":
+ version "6.0.0"
+ resolved "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-6.0.0.tgz"
+ integrity sha512-fDt19KWaJRK/n2AaFoVm31hgGmpygmTV7LsHGJNGZkgzXcFyLsx+XUl63DTDPH3iqxj3xUX128t104GtOz8tTw==
+ dependencies:
+ "@react-pdf/fns" "3.1.2"
+ bidi-js "^1.0.2"
+ hyphen "^1.6.4"
+ unicode-properties "^1.4.1"
+
+"@react-pdf/types@^2.9.0":
+ version "2.9.0"
+ resolved "https://registry.npmjs.org/@react-pdf/types/-/types-2.9.0.tgz"
+ integrity sha512-ckj80vZLlvl9oYrQ4tovEaqKWP3O06Eb1D48/jQWbdwz1Yh7Y9v1cEmwlP8ET+a1Whp8xfdM0xduMexkuPANCQ==
+ dependencies:
+ "@react-pdf/font" "^4.0.2"
+ "@react-pdf/primitives" "^4.1.1"
+ "@react-pdf/stylesheet" "^6.1.0"
+
"@rollup/pluginutils@^5.1.4":
version "5.1.4"
resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz"
@@ -739,6 +877,13 @@
resolved "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz"
integrity sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==
+"@swc/helpers@^0.5.12":
+ version "0.5.17"
+ resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz"
+ integrity sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==
+ dependencies:
+ tslib "^2.8.0"
+
"@types/babel__core@^7.20.5":
version "7.20.5"
resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz"
@@ -951,6 +1096,11 @@
resolved "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz"
integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==
+abs-svg-path@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz"
+ integrity sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==
+
acorn@^8.14.1:
version "8.14.1"
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz"
@@ -1135,16 +1285,28 @@ base-64@^1.0.0:
resolved "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz"
integrity sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==
-base64-js@^1.3.1:
+base64-js@^1.1.2, base64-js@^1.3.0, base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+base64-js@0.0.8:
+ version "0.0.8"
+ resolved "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz"
+ integrity sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==
+
bcp-47-match@^2.0.0:
version "2.0.3"
resolved "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz"
integrity sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==
+bidi-js@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz"
+ integrity sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==
+ dependencies:
+ require-from-string "^2.0.2"
+
binary-extensions@^2.0.0:
version "2.3.0"
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
@@ -1199,11 +1361,25 @@ braces@^3.0.3, braces@~3.0.2:
dependencies:
fill-range "^7.1.1"
+brotli@^1.3.2:
+ version "1.3.3"
+ resolved "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz"
+ integrity sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==
+ dependencies:
+ base64-js "^1.1.2"
+
browser-or-node@^2.1.1:
version "2.1.1"
resolved "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz"
integrity sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==
+browserify-zlib@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz"
+ integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==
+ dependencies:
+ pako "~1.0.5"
+
browserslist@^4.24.0, browserslist@^4.24.4, "browserslist@>= 4.21.0":
version "4.24.4"
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz"
@@ -1359,6 +1535,11 @@ clone@^1.0.2:
resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz"
integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
+clone@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz"
+ integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==
+
clsx@^2.1.1:
version "2.1.1"
resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz"
@@ -1388,7 +1569,7 @@ color-name@^1.0.0, color-name@~1.1.4:
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-color-string@^1.9.0:
+color-string@^1.9.0, color-string@^1.9.1:
version "1.9.1"
resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz"
integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
@@ -1460,6 +1641,11 @@ crossws@^0.3.3:
dependencies:
uncrypto "^0.1.3"
+crypto-js@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz"
+ integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
+
css-selector-parser@^1.0.0:
version "1.4.1"
resolved "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-1.4.1.tgz"
@@ -1569,6 +1755,11 @@ devlop@^1.0.0, devlop@^1.1.0:
dependencies:
dequal "^2.0.0"
+dfa@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz"
+ integrity sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==
+
didyoumean@^1.2.2:
version "1.2.2"
resolved "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz"
@@ -1734,6 +1925,11 @@ eventemitter3@^5.0.1:
resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz"
integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
+events@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz"
+ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
execa@^7.0.0:
version "7.2.0"
resolved "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz"
@@ -1754,6 +1950,11 @@ extend@^3.0.0:
resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
+fast-deep-equal@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
fast-glob@^3.3.2:
version "3.3.3"
resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz"
@@ -1809,6 +2010,21 @@ flattie@^1.1.1:
resolved "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz"
integrity sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==
+fontkit@^2.0.2:
+ version "2.0.4"
+ resolved "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz"
+ integrity sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==
+ dependencies:
+ "@swc/helpers" "^0.5.12"
+ brotli "^1.3.2"
+ clone "^2.1.2"
+ dfa "^1.2.0"
+ fast-deep-equal "^3.1.3"
+ restructure "^3.0.0"
+ tiny-inflate "^1.0.3"
+ unicode-properties "^1.4.0"
+ unicode-trie "^2.0.0"
+
for-each@^0.3.5:
version "0.3.5"
resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz"
@@ -2312,6 +2528,18 @@ hastscript@^9.0.0:
property-information "^7.0.0"
space-separated-tokens "^2.0.0"
+hsl-to-hex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/hsl-to-hex/-/hsl-to-hex-1.0.0.tgz"
+ integrity sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==
+ dependencies:
+ hsl-to-rgb-for-reals "^1.1.0"
+
+hsl-to-rgb-for-reals@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/hsl-to-rgb-for-reals/-/hsl-to-rgb-for-reals-1.1.1.tgz"
+ integrity sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==
+
html-escaper@3.0.3:
version "3.0.3"
resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz"
@@ -2342,6 +2570,11 @@ human-signals@^4.3.0:
resolved "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz"
integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==
+hyphen@^1.6.4:
+ version "1.10.6"
+ resolved "https://registry.npmjs.org/hyphen/-/hyphen-1.10.6.tgz"
+ integrity sha512-fXHXcGFTXOvZTSkPJuGOQf5Lv5T/R2itiiCVPg9LxAje5D00O0pP83yJShFq5V89Ly//Gt6acj7z8pbBr34stw==
+
ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz"
@@ -2352,7 +2585,7 @@ import-meta-resolve@^4.1.0:
resolved "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz"
integrity sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==
-inherits@^2.0.3, inherits@^2.0.4:
+inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -2518,6 +2751,11 @@ is-unicode-supported@^1.1.0:
resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz"
integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==
+is-url@^1.2.4:
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz"
+ integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==
+
is-wsl@^3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz"
@@ -2539,6 +2777,13 @@ jackspeak@^3.1.2:
optionalDependencies:
"@pkgjs/parseargs" "^0.11.0"
+jay-peg@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/jay-peg/-/jay-peg-1.1.1.tgz"
+ integrity sha512-D62KEuBxz/ip2gQKOEhk/mx14o7eiFRaU+VNNSP4MOiIkwb/D6B3G1Mfas7C/Fit8EsSV2/IWjZElx/Gs6A4ww==
+ dependencies:
+ restructure "^3.0.0"
+
jiti@^1.21.6, jiti@>=1.21.0:
version "1.21.7"
resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz"
@@ -2590,6 +2835,14 @@ lilconfig@^3.0.0, lilconfig@^3.1.3:
resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz"
integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==
+linebreak@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz"
+ integrity sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==
+ dependencies:
+ base64-js "0.0.8"
+ unicode-trie "^2.0.0"
+
lines-and-columns@^1.1.6:
version "1.2.4"
resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz"
@@ -3005,6 +3258,11 @@ mdast-util-to-string@^4.0.0:
dependencies:
"@types/mdast" "^4.0.0"
+media-engine@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz"
+ integrity sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg==
+
merge-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz"
@@ -3712,6 +3970,13 @@ normalize-range@^0.1.2:
resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz"
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
+normalize-svg-path@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz"
+ integrity sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==
+ dependencies:
+ svg-arc-to-cubic-bezier "^3.0.0"
+
not@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/not/-/not-0.1.0.tgz"
@@ -3818,6 +4083,16 @@ package-manager-detector@^1.0.0:
resolved "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.1.0.tgz"
integrity sha512-Y8f9qUlBzW8qauJjd/eu6jlpJZsuPJm2ZAV0cDVd420o4EdpH5RPdoCv+60/TdJflGatr4sDfpAL6ArWZbM5tA==
+pako@^0.2.5:
+ version "0.2.9"
+ resolved "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz"
+ integrity sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==
+
+pako@~1.0.5:
+ version "1.0.11"
+ resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz"
+ integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
+
parse-entities@^4.0.0:
version "4.0.2"
resolved "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz"
@@ -3848,6 +4123,11 @@ parse-numeric-range@^1.3.0:
resolved "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz"
integrity sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==
+parse-svg-path@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz"
+ integrity sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==
+
parse5@^6.0.0:
version "6.0.1"
resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz"
@@ -3967,7 +4247,7 @@ postcss-selector-parser@^6.1.1, postcss-selector-parser@^6.1.2:
cssesc "^3.0.0"
util-deprecate "^1.0.2"
-postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
+postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
version "4.2.0"
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
@@ -3994,7 +4274,7 @@ prompts@^2.4.2:
kleur "^3.0.3"
sisteransi "^1.0.5"
-prop-types@^15.0.0, prop-types@^15.8.1:
+prop-types@^15.0.0, prop-types@^15.6.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@@ -4033,6 +4313,13 @@ queue-microtask@^1.2.2:
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+queue@^6.0.1:
+ version "6.0.2"
+ resolved "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz"
+ integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==
+ dependencies:
+ inherits "~2.0.3"
+
radix3@^1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz"
@@ -4463,6 +4750,11 @@ remark-stringify@^11.0.0:
mdast-util-to-markdown "^2.0.0"
unified "^11.0.0"
+require-from-string@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz"
+ integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+
resolve@^1.1.7, resolve@^1.22.8:
version "1.22.10"
resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz"
@@ -4480,6 +4772,11 @@ restore-cursor@^4.0.0:
onetime "^5.1.0"
signal-exit "^3.0.2"
+restructure@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz"
+ integrity sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==
+
retext-latin@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz"
@@ -4588,6 +4885,11 @@ scheduler@^0.25.0:
resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz"
integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==
+scheduler@0.25.0-rc-603e6108-20241029:
+ version "0.25.0-rc-603e6108-20241029"
+ resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0-rc-603e6108-20241029.tgz"
+ integrity sha512-pFwF6H1XrSdYYNLfOcGlM28/j8CGLu8IvdrxqhjWULe2bPcKiKW4CV+OWqR/9fT52mywx65l7ysNkjLKBda7eA==
+
semver@^6.3.1:
version "6.3.1"
resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
@@ -4871,6 +5173,11 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+svg-arc-to-cubic-bezier@^3.0.0, svg-arc-to-cubic-bezier@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz"
+ integrity sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==
+
tailwind-merge@^3.0.2:
version "3.0.2"
resolved "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.0.2.tgz"
@@ -4930,6 +5237,11 @@ through2@^4.0.2:
dependencies:
readable-stream "3"
+tiny-inflate@^1.0.0, tiny-inflate@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz"
+ integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==
+
tinyexec@^0.3.2:
version "0.3.2"
resolved "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz"
@@ -4970,7 +5282,7 @@ tsconfck@^3.1.5:
resolved "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.5.tgz"
integrity sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg==
-tslib@^2.0.0, tslib@^2.1.0:
+tslib@^2.0.0, tslib@^2.1.0, tslib@^2.8.0:
version "2.8.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
@@ -5010,6 +5322,22 @@ uncrypto@^0.1.3:
resolved "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz"
integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==
+unicode-properties@^1.4.0, unicode-properties@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz"
+ integrity sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==
+ dependencies:
+ base64-js "^1.3.0"
+ unicode-trie "^2.0.0"
+
+unicode-trie@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz"
+ integrity sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==
+ dependencies:
+ pako "^0.2.5"
+ tiny-inflate "^1.0.0"
+
unified@^10.0.0, unified@~10.1.1:
version "10.1.2"
resolved "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz"
@@ -5296,6 +5624,15 @@ vfile@^6.0.0, vfile@^6.0.3:
"@types/unist" "^3.0.0"
vfile-message "^4.0.0"
+vite-compatible-readable-stream@^3.6.1:
+ version "3.6.1"
+ resolved "https://registry.npmjs.org/vite-compatible-readable-stream/-/vite-compatible-readable-stream-3.6.1.tgz"
+ integrity sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==
+ dependencies:
+ inherits "^2.0.3"
+ string_decoder "^1.1.1"
+ util-deprecate "^1.0.1"
+
"vite@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", "vite@^4.2.0 || ^5.0.0 || ^6.0.0", vite@^6.2.0, vite@^6.2.1:
version "6.2.2"
resolved "https://registry.npmjs.org/vite/-/vite-6.2.2.tgz"
@@ -5447,6 +5784,11 @@ yoctocolors@^2.1.1:
resolved "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz"
integrity sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==
+yoga-layout@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz"
+ integrity sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==
+
zod-to-json-schema@^3.24.3:
version "3.24.4"
resolved "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.4.tgz"