diff --git a/.DS_Store b/.DS_Store
index 7862d48..a31408c 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/.env b/.env
index 8197906..6fb4820 100644
--- a/.env
+++ b/.env
@@ -1,6 +1,9 @@
#Backend Options
-BACKEND_PORT=3000
+BACKEND_PORT=3001
+BACKEND_TEST_PORT=4001
+DATABASE_PORT=1111
+DATABASE_TEST_PORT=2222
DATABASE_USER="pim_user"
DATABASE_PASSWORD="pim_password"
DATABASE_NAME="pim"
diff --git a/.gitignore b/.gitignore
index b9bcc7c..ff979e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
pg_data
node_modules
.DS_Store
-frontend/.DS_Store
-.vscode
\ No newline at end of file
+frontend/.DS_Store
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..cf8ccce
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,7 @@
+{
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true
+ },
+ "eslint.validate": ["javascript, typescript, vue, html, css, scss, json, markdown"],
+ "css.lint.unknownAtRules": "ignore"
+}
\ No newline at end of file
diff --git a/backend/.env b/backend/.env
index 1dbad59..7ca4859 100644
--- a/backend/.env
+++ b/backend/.env
@@ -1,4 +1,8 @@
#Backend Options
-BACKEND_PORT=3000
+BACKEND_PORT=3001
+BACKEND_TEST_PORT=4001
+DATABASE_PORT=1111
+DATABASE_TEST_PORT=2222
DATABASE_URL=postgres://pim_user:pim_password@database:5432/pim
+DATABASE_TEST_URL=postgres://pim_user:pim_password@database-test:5432/pim
JWT_SECRET=oIAea3K2KQ7xXVuyq7pmFFVVBMp86UiT
\ No newline at end of file
diff --git a/backend/controllers/AuthController.js b/backend/controllers/AuthController.js
index 9c39a1c..14d0487 100644
--- a/backend/controllers/AuthController.js
+++ b/backend/controllers/AuthController.js
@@ -7,7 +7,7 @@ const db = require('../database');
// This middleware will be used to sign the token after a vendor logs in
const signToken = async (req, res, next) => {
if (res.locals.vendor === undefined) {
- return res.status(401).json({message: 'Unauthorized'});
+ return res.status(401).json({message: 'Unauthorized: Vendor'});
}
// Sign the token with JWT_SECRET
@@ -23,17 +23,22 @@ const verifyToken = async (req, res, next) => {
// Retrieve the token from the cookie
const token = req.cookies.auth;
+ if (!token) {
+ return res.status(403).json({ message: 'No token provided' });
+ }
+
// Verify the token with JWT_SECRET
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
- res.status(401).json({message: 'Unauthorized'});
+ console.log(err);
+ res.status(401).json({message: 'Unauthorized: vendor1'});
} else {
// Update cookie data from database
db.oneOrNone('SELECT * FROM vendors WHERE vendor_id = $1', [decoded.vendor_id], (result, err) => {
if (err) {
res.status(500).json({message: 'Internal Server Error'});
} else if (result === null) {
- res.status(401).json({message: 'Unauthorized'});
+ res.status(401).json({message: 'Unauthorized: Vendor2'});
}
res.locals.vendor = result;
@@ -50,7 +55,7 @@ const verifyToken = async (req, res, next) => {
// This middleware will be used to sign the token after an admin logs in
const signAdminToken = async (req, res, next) => {
if (res.locals.admin === undefined) {
- return res.status(401).json({message: 'Unauthorized'});
+ return res.status(401).json({message: 'Unauthorized: Admin'});
}
// Sign the token with JWT_SECRET
@@ -69,7 +74,7 @@ const verifyAdminToken = async (req, res, next) => {
// Verify the token with JWT_SECRET
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
- return res.status(401).json({message: 'Unauthorized'});
+ return res.status(401).json({message: 'Unauthorized: Admin'});
} else {
// Keep the cookie up to date with the database
db.oneOrNone('SELECT * FROM admins WHERE admin_id = $1', [decoded.admin_id], (result, err) => {
@@ -77,7 +82,7 @@ const verifyAdminToken = async (req, res, next) => {
console.log(err);
return res.status(500).json({message: 'Internal Server Error'});
} else if (result === undefined) {
- return res.status(401).json({message: 'Unauthorized'});
+ return res.status(401).json({message: 'Unauthorized: Admin.'});
}
console.log(result);
diff --git a/backend/controllers/VendorController.js b/backend/controllers/VendorController.js
index 67cb0dd..1bab7ef 100644
--- a/backend/controllers/VendorController.js
+++ b/backend/controllers/VendorController.js
@@ -26,8 +26,16 @@ const getVendor = async (req, res, next) => {
// Middleware to verify the password of the vendor
const authenticateVendor = async (req, res, next) => {
try {
+
const vendor = res.locals.data;
- const match = await bcrypt.compare(req.body.password, vendor.password);
+ const email = req.body.email;
+ const password = req.body.password;
+
+ if (email === undefined || password === undefined) {
+ res.status(401).json({message: 'Missing email or password'});
+ return;
+ }
+ const match = await bcrypt.compare(password, vendor.password);
// If passwords match, pass vendor object without password
if (match) {
@@ -97,7 +105,10 @@ const createVendor = async (req, res, next) => {
// Checks if the required fields are present
if (!password || !email || !name) {
console.log(req.body);
- return res.status(400).json({error: 'Missing required fields'});
+ return res.status(400).json({
+ error: 'Missing required fields',
+ data: req.body,
+ });
}
// Hashes the password using bcrypt
@@ -107,7 +118,7 @@ const createVendor = async (req, res, next) => {
passwordHash = await hash(password, salt);
} catch (err) {
console.log(err);
- res.status(495).json({error: err});
+ res.status(495).json({error: "Error hashing password"});
return;
}
@@ -134,7 +145,7 @@ const createVendor = async (req, res, next) => {
// Other internal error
console.log(err);
- res.status(500).json({error: err});
+ res.status(500).json({error: "Internal Server Error"});
return;
}
diff --git a/backend/database.js b/backend/database.js
index 9ca244f..174688b 100644
--- a/backend/database.js
+++ b/backend/database.js
@@ -1,12 +1,24 @@
// Import the pg-promise library and initialize it
const pgp = require('pg-promise')();
-// Connect to the database using the environment variable DATABASE_URL
-if (process.env.DATABASE_URL === undefined) {
- throw new Error('DATABASE_URL environment variable not set');
+let db;
+
+if (process.env.NODE_ENV === undefined) {
+ throw new Error('NODE_ENV environment variable not set');
+}
+if (process.env.DATABASE_URL === undefined || process.env.DATABASE_TEST_URL === undefined) {
+ throw new Error('DATABASE_URL or DATABASE_TEST_URL environment variable not set');
}
-const db = pgp(process.env.DATABASE_URL);
+// Connect to the database using the environment variable DATABASE_URL
+if (process.env.NODE_ENV === 'test') {
+ console.log('Connecting to database using url: ' + process.env.DATABASE_TEST_URL);
+ db = pgp(process.env.DATABASE_TEST_URL);
+}
+else {
+ console.log('Connecting to database using url: ' + process.env.DATABASE_URL);
+ db = pgp(process.env.DATABASE_URL);
+}
/*
The database object above represents a connection to our database. However,
diff --git a/backend/index.js b/backend/index.js
index 3b52c27..5e79bf3 100644
--- a/backend/index.js
+++ b/backend/index.js
@@ -38,6 +38,26 @@ app.get('/', (req, res) => {
res.status(202).send('Hello World!');
});
+app.get('/api/health', (req, res) => {
+ db.one('SELECT 1 AS value')
+ .then(() => {
+ res.status(200).json({
+ status: 'success',
+ message: 'Database connection is healthy',
+ });
+ })
+ .catch(error => {
+ console.error('Database connection error:', error);
+ res.status(503).json({
+ status: 'error',
+ message: 'Database connection is unhealthy',
+ error: error.message,
+ });
+ });
+});
+
+
+
/*
The backend should be listening on port 3000 within its container,
but the container's port 3000 is mapped externally to 3001.
@@ -45,6 +65,17 @@ but the container's port 3000 is mapped externally to 3001.
TL;DR the backend is running on port 3001 on the host machine.
*/
-app.listen(process.env.BACKEND_PORT, () => {
- console.log(`PIM backend app listening on port ${process.env.BACKEND_PORT}`);
-});
+if (process.env.NODE_ENV === 'test') {
+ app.listen(process.env.BACKEND_TEST_PORT, () => {
+ console.log(`PIM backend app listening on port ${process.env.BACKEND_TEST_PORT}`);
+ });
+ // export app to import into test files
+ module.exports = app;
+ return;
+}
+else if (process.env.NODE_ENV === 'dev') {
+ app.listen( process.env.BACKEND_PORT, () => {
+ console.log(`PIM backend app listening on port ${process.env.BACKEND_PORT}`);
+ });
+ return;
+}
diff --git a/docker-compose-test.yaml b/docker-compose-test.yaml
new file mode 100644
index 0000000..8380549
--- /dev/null
+++ b/docker-compose-test.yaml
@@ -0,0 +1,49 @@
+version: "3"
+services:
+ backend-test:
+ image: node:alpine3.17
+ container_name: backend-test
+ working_dir: /app
+ command: npm run dev
+ ports:
+ - "${BACKEND_TEST_PORT}:4000"
+ volumes:
+ - ./backend:/app
+ environment:
+ - NODE_ENV=test
+ depends_on:
+ database-test:
+ condition: service_healthy
+
+ # PostgreSQL
+ database-test:
+ hostname: database-test
+ image: postgres:latest
+ container_name: postgres-test
+ ports:
+ - "${DATABASE_TEST_PORT}:5432"
+ environment:
+ POSTGRES_DB: ${DATABASE_NAME}
+ POSTGRES_USER: ${DATABASE_USER}
+ POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ volumes:
+ - ./sql-scripts:/docker-entrypoint-initdb.d # Mount directory for initial SQL files
+
+
+ # React.js Frontend
+ frontend-test:
+ image: node:alpine3.17
+ container_name: frontend-test
+ working_dir: /app
+ command: npm run test
+ volumes:
+ - ./frontend:/app
+ ports:
+ - "4000:4000"
+ depends_on:
+ - backend-test
diff --git a/docker-compose.yaml b/docker-compose.yaml
index e0cc8db..4de2041 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -7,11 +7,11 @@ services:
working_dir: /app
command: npm run dev
ports:
- - "3001:3000"
+ - "${BACKEND_PORT}:3001"
volumes:
- ./backend:/app
environment:
- - NODE_ENV=development
+ - NODE_ENV=dev
depends_on:
- database
@@ -21,7 +21,7 @@ services:
image: postgres:latest
container_name: postgres
ports:
- - "5432:5432"
+ - "${DATABASE_PORT}:5432"
environment:
POSTGRES_DB: ${DATABASE_NAME}
POSTGRES_USER: ${DATABASE_USER}
diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.cjs
similarity index 100%
rename from frontend/.eslintrc.js
rename to frontend/.eslintrc.cjs
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index eebdd78..63c3dfe 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -18,6 +18,10 @@
"@testing-library/user-event": "^13.5.0",
"axios": "^1.6.0",
"babel-plugin-macros": "^3.1.0",
+ "chai": "^4.3.4",
+ "js-cookie": "^3.0.5",
+ "jwt-decode": "^4.0.0",
+ "mocha": "^9.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router": "^6.17.0",
@@ -4782,6 +4786,11 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@ungap/promise-all-settled": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
+ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q=="
+ },
"node_modules/@ungap/structured-clone": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
@@ -5090,6 +5099,14 @@
"ajv": "^6.9.1"
}
},
+ "node_modules/ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/ansi-escapes": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
@@ -5322,6 +5339,14 @@
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
},
+ "node_modules/assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/ast-types-flow": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
@@ -5861,6 +5886,11 @@
"resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
"integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow=="
},
+ "node_modules/browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
+ },
"node_modules/browserslist": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
@@ -6011,6 +6041,23 @@
"node": ">=4"
}
},
+ "node_modules/chai": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz",
+ "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==",
+ "dependencies": {
+ "assertion-error": "^1.1.0",
+ "check-error": "^1.0.3",
+ "deep-eql": "^4.1.3",
+ "get-func-name": "^2.0.2",
+ "loupe": "^2.3.6",
+ "pathval": "^1.1.1",
+ "type-detect": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -6032,6 +6079,17 @@
"node": ">=10"
}
},
+ "node_modules/check-error": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
+ "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
+ "dependencies": {
+ "get-func-name": "^2.0.2"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/check-types": {
"version": "11.2.3",
"resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz",
@@ -6771,6 +6829,17 @@
}
}
},
+ "node_modules/decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/decimal.js": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
@@ -6781,6 +6850,17 @@
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
"integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA=="
},
+ "node_modules/deep-eql": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
+ "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
+ "dependencies": {
+ "type-detect": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/deep-equal": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz",
@@ -6950,6 +7030,14 @@
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
},
+ "node_modules/diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
"node_modules/diff-sequences": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz",
@@ -8368,6 +8456,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
"node_modules/flat-cache": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
@@ -8695,6 +8791,14 @@
"node": "6.* || 8.* || >= 10.*"
}
},
+ "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-intrinsic": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
@@ -8880,6 +8984,14 @@
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="
},
+ "node_modules/growl": {
+ "version": "1.10.5",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
+ "engines": {
+ "node": ">=4.x"
+ }
+ },
"node_modules/gzip-size": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
@@ -9762,6 +9874,17 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
},
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-weakmap": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
@@ -11902,6 +12025,14 @@
"jiti": "bin/jiti.js"
}
},
+ "node_modules/js-cookie": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
+ "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -12066,6 +12197,14 @@
"node": ">=4.0"
}
},
+ "node_modules/jwt-decode": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
+ "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -12218,6 +12357,85 @@
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
"integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ=="
},
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-symbols/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/log-symbols/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/log-symbols/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -12229,6 +12447,14 @@
"loose-envify": "cli.js"
}
},
+ "node_modules/loupe": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
+ "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==",
+ "dependencies": {
+ "get-func-name": "^2.0.1"
+ }
+ },
"node_modules/lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
@@ -12452,6 +12678,191 @@
"mkdirp": "bin/cmd.js"
}
},
+ "node_modules/mocha": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz",
+ "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==",
+ "dependencies": {
+ "@ungap/promise-all-settled": "1.1.2",
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.3",
+ "debug": "4.3.3",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "7.2.0",
+ "growl": "1.10.5",
+ "he": "1.2.0",
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "4.2.1",
+ "ms": "2.1.3",
+ "nanoid": "3.3.1",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "which": "2.0.2",
+ "workerpool": "6.2.0",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "bin": {
+ "_mocha": "bin/_mocha",
+ "mocha": "bin/mocha"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mochajs"
+ }
+ },
+ "node_modules/mocha/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+ },
+ "node_modules/mocha/node_modules/debug": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+ "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/mocha/node_modules/debug/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/mocha/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/mocha/node_modules/glob/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/mocha/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mocha/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/mocha/node_modules/minimatch": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz",
+ "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/mocha/node_modules/nanoid": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
+ "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/mocha/node_modules/serialize-javascript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/mocha/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/mocha/node_modules/yargs-parser": {
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -12977,6 +13388,14 @@
"node": ">=8"
}
},
+ "node_modules/pathval": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
+ "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -17761,6 +18180,11 @@
"workbox-core": "6.6.0"
}
},
+ "node_modules/workerpool": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz",
+ "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A=="
+ },
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@@ -17899,6 +18323,28 @@
"node": ">=10"
}
},
+ "node_modules/yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "dependencies": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-unparser/node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 8fa73fb..dcf038e 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,7 @@
{
"name": "pim-frontend",
"version": "0.1.0",
+ "type": "module",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.4.2",
@@ -13,6 +14,10 @@
"@testing-library/user-event": "^13.5.0",
"axios": "^1.6.0",
"babel-plugin-macros": "^3.1.0",
+ "chai": "^4.3.4",
+ "js-cookie": "^3.0.5",
+ "jwt-decode": "^4.0.0",
+ "mocha": "^9.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router": "^6.17.0",
@@ -27,7 +32,7 @@
"prestart": "npm i",
"start": "react-scripts start",
"build": "react-scripts build",
- "test": "react-scripts test",
+ "test": "mocha 'src/tests/**/*.test.js'",
"eject": "react-scripts eject"
},
"eslintConfig": {
diff --git a/frontend/src/.DS_Store b/frontend/src/.DS_Store
index 27ba0c6..b73e692 100644
Binary files a/frontend/src/.DS_Store and b/frontend/src/.DS_Store differ
diff --git a/frontend/src/assets/Indigenous_Marketplace_Vendor_Policy_Handbook_2023_June (1).pdf b/frontend/src/assets/Indigenous_Marketplace_Vendor_Policy_Handbook_2023_June (1).pdf
new file mode 100644
index 0000000..a7e9525
Binary files /dev/null and b/frontend/src/assets/Indigenous_Marketplace_Vendor_Policy_Handbook_2023_June (1).pdf differ
diff --git a/frontend/src/components/messagemodal.jsx b/frontend/src/components/messagemodal.jsx
new file mode 100644
index 0000000..50045ba
--- /dev/null
+++ b/frontend/src/components/messagemodal.jsx
@@ -0,0 +1,34 @@
+import React, {useState} from 'react';
+import PropTypes from 'prop-types';
+
+
+function MessageModal({closeModal, vendor}) { // added vendor object so we can send message to vendor
+ const [message, setMessage] = useState('');
+ function handleSubmit() {
+ console.log(`Posting message(${message}) to ${vendor.name}`);
+ console.log('... As long as someone finishes my code');
+ closeModal(false);
+ }
+ // changed the code a little bit, easier to use react state and functions than form
+ return (
+
+
+ Send A Message To {vendor.name}
+
+
+
+
+ handleSubmit()}>Send
+ closeModal(false)}>Cancel
+
+
+
+ );
+}
+
+export default MessageModal;
+
+MessageModal.propTypes = {
+ closeModal: PropTypes.func.isRequired,
+ vendor: PropTypes.object.isRequired,
+};
diff --git a/frontend/src/components/modal.jsx b/frontend/src/components/modal.jsx
index d89f9e7..1355214 100644
--- a/frontend/src/components/modal.jsx
+++ b/frontend/src/components/modal.jsx
@@ -1,15 +1,21 @@
import React from 'react';
-
-export default function Modal() {
- const [show, setShow] = useState(false);
+import PropTypes from 'prop-types';
+export default function Modal({setModal, message}) {
const toggleModal = () => {
- setShow(!show);
+ setModal(false);
};
return (
<>
- {show && Modal }
- Show Modal
+ Modal
+ {message}
+ Close
>
+
);
}
+
+Modal.propTypes = {
+ message: PropTypes.string,
+ setModal: PropTypes.func,
+};
diff --git a/frontend/src/components/pdf.js b/frontend/src/components/pdf.js
new file mode 100644
index 0000000..3b0de63
--- /dev/null
+++ b/frontend/src/components/pdf.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import {Page, Text, View, Document, StyleSheet} from '@react-pdf/renderer';
+
+const styles = StyleSheet.create({
+ page: {
+ flexDirection: 'row',
+ backgroundColor: '#E4E4E4',
+ },
+ section: {
+ margin: 10,
+ padding: 10,
+ flexGrow: 1,
+ },
+});
+
+const MyDocument = () => (
+
+
+
+ Section #1
+
+
+ Section #2
+
+
+
+);
+export default MyDocument;
diff --git a/frontend/src/config.js b/frontend/src/config.js
index 0eac2e3..c2895fb 100644
--- a/frontend/src/config.js
+++ b/frontend/src/config.js
@@ -1,5 +1,5 @@
const config = {
- environment: 'dev',
+ environment: 'prod',
baseUrl: 'http://localhost:3001/api',
};
diff --git a/frontend/src/index.jsx b/frontend/src/index.jsx
index 3e99fe6..468c58a 100644
--- a/frontend/src/index.jsx
+++ b/frontend/src/index.jsx
@@ -1,13 +1,12 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import reportWebVitals from './reportWebVitals.js';
-import {createBrowserRouter, Navigate, RouterProvider} from 'react-router-dom';
+import {createBrowserRouter, RouterProvider} from 'react-router-dom';
// Import CSS for this page
import './App.css';
// Import Pages
-import Vendor from './routes/vendor.jsx';
import Event from './routes/event.jsx';
import Events from './routes/events.jsx';
import Profile from './routes/profile.jsx';
@@ -32,6 +31,8 @@ import VendorsService from './services/Vendors/VendorsService.js';
import {handleLoginVendor} from './services/handleLogin.js';
import {handleRegister} from './services/handleRegister.js';
+import HttpClient from './services/HttpClient.js';
+
// Import configuration variables
import config from './config.js';
@@ -48,9 +49,12 @@ if (config.environment == 'dev') {
// Load base url for the backend
const baseUrl = config.baseUrl;
+ // Create HttpClient
+ const httpClient = new HttpClient(baseUrl);
+
// Initilize Services
- const eventsService = new EventsService(baseUrl);
- const vendorsService = new VendorsService(baseUrl);
+ const eventsService = new EventsService(httpClient);
+ const vendorsService = new VendorsService(httpClient);
eventService = eventsService;
vendorService = vendorsService;
@@ -63,7 +67,7 @@ const router = createBrowserRouter([
children: [
{
path: '/vendors/:vendorId',
- element: ,
+ element: ,
},
{
path: '/login',
@@ -78,10 +82,6 @@ const router = createBrowserRouter([
path: '/reset_password',
element: ,
},
- {
- path: '/profile',
- element: ,
- },
{
path: '/events/:eventId',
element: ,
@@ -106,7 +106,7 @@ const router = createBrowserRouter([
const root = ReactDOM.createRoot(document.getElementById('root'));
export default root.render(
-
+
,
);
// If you want to start measuring performance in your app, pass a function
diff --git a/frontend/src/objects/Event.js b/frontend/src/objects/Event.js
index 188897a..26dff80 100644
--- a/frontend/src/objects/Event.js
+++ b/frontend/src/objects/Event.js
@@ -1,7 +1,7 @@
/*
Storage mechanism for a vendor object
*/
-class Event {
+export default class Event {
constructor(eventId, name, location, startTime, endTime, description, vendorCapacity) {
this.eventId = eventId;
this.name = name;
@@ -17,5 +17,3 @@ class Event {
return JSON.stringify(this);
}
}
-
-module.exports = Event;
diff --git a/frontend/src/objects/Permission.js b/frontend/src/objects/Permission.js
new file mode 100644
index 0000000..79e1e4b
--- /dev/null
+++ b/frontend/src/objects/Permission.js
@@ -0,0 +1,9 @@
+/*
+Permission enum
+*/
+const Permission = {
+ Admin: 'admin',
+ Vendor: 'vendor',
+};
+
+export default Permission;
diff --git a/frontend/src/objects/User.js b/frontend/src/objects/User.js
new file mode 100644
index 0000000..31957b5
--- /dev/null
+++ b/frontend/src/objects/User.js
@@ -0,0 +1,41 @@
+// import Permission from './Permission.js';
+import Cookies from 'js-cookie';
+import {jwtDecode} from 'jwt-decode';
+
+/*
+Storage mechanism for the currently logged-in user.
+*/
+export default class User {
+ constructor(id, name, email, isadmin, phone_number=null, website=null) {
+ this.id = id;
+ this.name = name;
+ this.email = email;
+ this.isadmin = isadmin;
+ this.phone_number = phone_number;
+ this.website = website;
+ }
+
+ // isAdmin() {
+ // return this.permission === Permission.Admin;
+ // }
+
+ // isVendor() {
+ // return this.permission === Permission.Vendor;
+ // }
+
+ static createFromCookie() {
+ if (Cookies.get('auth_pim') != undefined) {
+ const cookie = Cookies.get('auth_pim');
+ const decode = jwtDecode(cookie);
+
+ return User(decode.admin_id, decode.name, decode.email, true, null, null);
+ } else if ( Cookies.get('auth') != undefined ) {
+ const cookie = Cookies.get('auth');
+ const decode = jwtDecode(cookie);
+
+ return User(decode.vendor_id, decode.name, decode.email, false, decode.phone_number, decode.website);
+ } else {
+ return undefined;
+ }
+ }
+}
diff --git a/frontend/src/objects/Vendor.js b/frontend/src/objects/Vendor.js
index f542932..0cb6f8f 100644
--- a/frontend/src/objects/Vendor.js
+++ b/frontend/src/objects/Vendor.js
@@ -1,7 +1,7 @@
/*
Storage mechanism for a vendor object
*/
-class Vendor {
+export default class Vendor {
/*
id: int - database id assigned to this vendor
name: string - name of the vendor
@@ -32,5 +32,3 @@ class Vendor {
return JSON.stringify(this);
}
}
-
-module.exports = Vendor;
diff --git a/frontend/src/routes/event.jsx b/frontend/src/routes/event.jsx
index 3a16822..50c9ddb 100644
--- a/frontend/src/routes/event.jsx
+++ b/frontend/src/routes/event.jsx
@@ -1,18 +1,18 @@
-import React, { useEffect, useState, useContext } from 'react';
-import { useNavigate, useParams } from 'react-router-dom';
+import React, {useEffect, useState, useContext} from 'react';
+import {useNavigate, useParams} from 'react-router-dom';
import PropTypes from 'prop-types';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faCaretDown, faAnglesLeft } from '@fortawesome/free-solid-svg-icons';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
+import {faCaretDown, faAnglesLeft} from '@fortawesome/free-solid-svg-icons';
import logo from '../assets/PIM_logo_white.png';
import bLogo from '../assets/PIM_logo_black.png';
-import {Context} from '../services/context.jsx'
+import {Context} from '../services/context.jsx';
-export default function Event({ eventService }) {
+export default function Event({eventService}) {
const [event, setEvent] = useState(null);
const [about, setAbout] = useState(false);
const navigate = useNavigate();
- const { eventId } = useParams();
- const { user, setMessage, setBad } = useContext(Context);
+ const {eventId} = useParams();
+ const {user, setMessage, setBad} = useContext(Context);
useEffect(() => {
if (!user) {
@@ -21,11 +21,11 @@ export default function Event({ eventService }) {
navigate('/');
}
const fetchEvent = async () => {
- console.log('Event id', eventId)
+ console.log('Event id', eventId);
const eventData = await eventService.getEventById(parseInt(eventId.slice(1)));
if (!eventData) {
- setMessage("Event not found")
- setBad(true)
+ setMessage('Event not found');
+ setBad(true);
navigate('/events');
} else {
setEvent(eventData);
@@ -39,7 +39,7 @@ export default function Event({ eventService }) {
return Event Not Found
;
}
- const { name, location, date, startTime, endTime, description } = event;
+ const {name, location, date, startTime, endTime, description} = event;
const vendorImages = [logo, bLogo, logo, bLogo, logo, bLogo, logo, bLogo, logo, bLogo, logo, bLogo];
const toggleVendor = () => {
@@ -83,7 +83,7 @@ export default function Event({ eventService }) {
}
Event.propTypes = {
- eventsService: PropTypes.shape({
+ eventService: PropTypes.shape({
getEventById: PropTypes.func.isRequired,
}).isRequired,
};
diff --git a/frontend/src/routes/events.jsx b/frontend/src/routes/events.jsx
index 89eaf7d..c1c09af 100644
--- a/frontend/src/routes/events.jsx
+++ b/frontend/src/routes/events.jsx
@@ -1,13 +1,13 @@
-import React, { useContext } from 'react';
-import { useState, useEffect } from 'react';
+import React, {useContext, useState, useEffect} from 'react';
import PropTypes from 'prop-types';
-import { Context } from '../services/context';
-import { Link } from 'react-router-dom';
+import {Context} from '../services/context';
+import {Link} from 'react-router-dom';
-export default function Events({ eventService }) {
+export default function Events({eventService}) {
const [events, setEvents] = useState([]);
const [error, setError] = useState('');
- const { user } = useContext(Context);
+ const {user} = useContext(Context);
+ const [modal, setModal] = useState(false);
useEffect(() => {
const fetchEvents = async () => {
@@ -28,9 +28,14 @@ export default function Events({ eventService }) {
fetchEvents();
}, [eventService]);
+ const closeModal = () => {
+ setModal(false);
+ };
+
const handleAddEvent = () => {
console.log('add event called, but I am not implemented :(((');
// eventsService.createEvent(); this needs implementation
+ setModal(true);
};
const handleEditEvent = () => {
@@ -50,9 +55,9 @@ export default function Events({ eventService }) {
{event.location}
{user && user.isadmin && handleEditEvent()} className='hover:bg-blue absolute right-0 text-sm text-grey-5 px-1 rounded-md bg-white border-2'>Edit }
-
+
View Event Details
-
+
);
@@ -66,17 +71,38 @@ export default function Events({ eventService }) {
}
return (
- // display in a single column
{user && user.isadmin &&
handleAddEvent()}>Add Event }
+ {modal && (
+
+
+
{
+ closeModal();
+ }} className='bg-blue text-white p-5'>Close Edit
+
+ )}
Events
{
events && (Array.isArray(events) ? events.map((event, i) => (
-
{eventDisplay(event)}
+ {eventDisplay(event)}
)) : eventDisplay(events))
}
@@ -85,8 +111,7 @@ export default function Events({ eventService }) {
}
Events.propTypes = {
- eventsService: PropTypes.shape({
+ eventService: PropTypes.shape({
getAllEvents: PropTypes.func.isRequired,
- createEvent: PropTypes.func.isRequired,
}).isRequired,
};
diff --git a/frontend/src/routes/handbook.jsx b/frontend/src/routes/handbook.jsx
deleted file mode 100644
index e69de29..0000000
diff --git a/frontend/src/routes/login.jsx b/frontend/src/routes/login.jsx
index 0fcb377..790bc99 100644
--- a/frontend/src/routes/login.jsx
+++ b/frontend/src/routes/login.jsx
@@ -1,26 +1,38 @@
-import React, { useState } from 'react';
+import React, {useState} from 'react';
import logo from './../assets/PIM_logo_black.png';
-import { Link, useNavigate } from 'react-router-dom';
-import { useContext } from 'react';
-import { Context } from '../services/context';
+import {Link, useNavigate} from 'react-router-dom';
+import {useContext} from 'react';
+import {Context} from '../services/context';
import PropTypes from 'prop-types';
+import User from '../objects/User';
-
-export default function Login({ loginService }) {
+export default function Login({loginService}) {
const [email, setEmail] = useState('');
const [pass, setPass] = useState('');
const navigate = useNavigate();
- const { setMessage, setBad, setUser } = useContext(Context);
+ const {setMessage, setBad, setUser} = useContext(Context);
async function handleLogin() {
- const data = { email: email, password: pass };
- if (await loginService(data)) {
- setBad(false);
- setUser({ email: email, password: pass, id: 2, isadmin: true }); // dummy user object for develepment
- setMessage('Logged in succesfully');
- navigate('/events');
- console.log('Logged in!');
+ const data = {email: email, password: pass};
+ const loginResponse = await loginService(data);
+
+ console.log(loginResponse);
+
+ if (loginResponse != undefined) {
+ if (loginResponse.status == 200) {
+ setUser(User.createFromCookie());
+ setBad(false);
+ setMessage('Logged in succesfully');
+ navigate('/events');
+ console.log('Logged in!');
+ } else if (loginResponse.status == 401) {
+ setBad(true);
+ setMessage('Bad Request. Check username and password.');
+ } else if (loginResponse.status == 500) {
+ setBad(true);
+ setMessage('Server experienced an error processing this request. Please try again.');
+ }
} else {
setBad(true);
setMessage('Failed to login');
diff --git a/frontend/src/routes/profile.jsx b/frontend/src/routes/profile.jsx
index 80c1018..21a1c70 100644
--- a/frontend/src/routes/profile.jsx
+++ b/frontend/src/routes/profile.jsx
@@ -1,31 +1,55 @@
-import React, {useEffect} from 'react';
-import {useState} from 'react';
+import React, {useEffect, useContext, useState} from 'react';
import handbook from './../assets/Handbook.png';
-import {Link, useNavigate} from 'react-router-dom';
+import {useNavigate, useParams} from 'react-router-dom';
import PropTypes from 'prop-types';
-import Modal from '../components/modal';
+import {Context} from '../services/context';
+import Modal from '../components/modal.jsx';
-export default function Profile({VendorService}) {
+export default function Profile({vendorService}) {
const navigate = useNavigate();
- // const [vendorId] = useState(useParams().vendorId);
- const [vendor] = useState(VendorService.getVendorById(1));
+ const {user, setMessage, setBad} = useContext(Context);
+ const [modal, setModal] = useState(false);
+ const {vendorId} = useParams();
+ const id = parseInt(vendorId.slice(1));
+ const [vendor] = useState(vendorService.getVendorById(id));
+
useEffect(() => {
if (!user) {
setMessage('Please log in');
setBad(true);
navigate('/');
+ } else if (user.isadmin) {
+ setMessage('What should an admin see?');
}
}, [navigate, user]);
- // Can test using specific id number
+ function handleEdit() {
+ setModal(true);
+ }
+ const [showEditModal, setEditModal] = useState(false);
+ const setEditModalHandler = () =>{
+ setEditModal(true);
+ };
+ const setEditModalHandlerClose = () =>{
+ setEditModal(false);
+ };
+ const [showModal, setShowModal] = useState(false);
+ const setShowModalHandler = () => {
+ setShowModal(true);
+ };
+ const setShowModalHandlerClose = () => {
+ setShowModal(false);
+ };
return (
-
{vendor.name}
+
{
+ setEditModalHandler();
+ }}>Edit
@@ -43,17 +67,216 @@ export default function Profile({VendorService}) {
Violations
-
+
{
+ setShowModalHandler();
+ }}>
+
+
+
Policy Handbook
+ {
+ showEditModal && (
+
+
+
+ {
+ setEditModalHandlerClose();
+ }} className='bg-blue text-white p-5'>Close Edit
+
+
+ )
+ }
+ {
+ showModal && (
+
+
+
+
+
Mission Statement:
+ Portland Indigenous Marketplace supports indigenous artists and
+ entrepreneurs by providing barrier-free, culturally respectful spaces that
+ encourage cultural resilience and economic sustainability by promoting
+ public education through cultural arts
+
Introduction:
+
+ The nonprofit Portland Indigenous Marketplace and their
+ Indigenous Marketplace programming together with vendors and event
+ staff have compiled this Vendor Policy Handbook to better communicate all
+ rules and expectations from vendors that are part of the Indigenous
+ Marketplace programming.
+
+ By following the rules and policies outlined in this Vendor Policy Handbook
+ you help keep the Indigenous Marketplace community a supportive, viable
+ and enjoyable environment for the entire community. As an approved
+ Indigenous Marketplace vendor, you are responsible for informing yourself
+ and your staff about following all applicable marketplace rules, policies and
+ regulations set forth in this Vendor Handbook as well as local, tribal, state
+ and federal policies, rules and guidelines. All vendors are asked to comply
+ with the rules and policies outlined by the Vendor Policy Committee to
+ remain a vendor in good standing.
+ This is a live document and this organization’s serving Board, Executive
+ Director, and the Vendor Policy Committee reserve the right to modify the
+ policies of the Indigenous Marketplace as circumstances warrant. Vendors
+ will receive advance warning, and a revised copy of the rules as soon as
+ changes are incorporated into the rules.
+ Questions or concerns can be sent to info@indigenousmarketplace.org
+ or 503-901-3881
+ Portland Indigenous Marketplace:Vendor Policy Handbook
+
+
Indigenous Marketplace Vendor Policies:
+
+ 1. a. Vendors agree to donate one raffle item to the organization per
+ marketplace day that they participate in as a vendor. The item
+ donated should be a true representation of the vendor's talent/booth
+ with a value of at least $20. Upon review donation could qualify for a
+ maximum of 2 days raffle donation.
+ b. In Nov/Dec of each year every approved vendor will be asked to
+ donate a Silent Auction item with a value of a minimum of $50.
+ This donation will be needed to participate as an approved
+ Indigenous Marketplace vendor into the following of each year.
+
+
+ 2. Vendors agree that all products are made or designed by the Vendor.
+ Used or flea-market goods, manufactured items, or commercialbrand merchandise are not permitted for sale at the Indigenous
+ Marketplace events. Buying products from another vendor,
+ wholesaler, store or other operation and then selling those products
+ un-altered or not personalized is prohibited at Indigenous
+ marketplaces events. Vendors may only sell products for which they
+ have been approved, per their application the Exception Process
+ Exhibit 3 (upon approval each vendor may have 1 approved item that they did
+ not make or design if the Vendor Policy Committee finds that the item integrates
+ into the vendors booth).
+
+ 3. Attendance tracking begins with the first scheduled market day.
+ Vendors agree to cancel a market date by notifying staff at least 48
+ hours in advance. Notice must be given by calling the general PIM
+ number 503-901-3881 or directly contacting the appropriate staff
+ member via phone or email. Vendors are allowed 2 excused absences
+ per market year. In addition, 2 emergency cancellations are permitted
+ without proper notice.
+
+
+ 4. Vendors agree to set up by the start time of the Indigenous
+ marketplace events and stay for the duration of marketplace hours. If
+ vendor is running late or if a need to leave before the marketplace
+ ends arises, vendors agree to communicate with staff before initiating
+ any pack up. In such case during breakdown, the utmost care must be
+ taken to ensure the safety of our customers and fellow vendors. Staff
+ reserves the right to ask vendor to cover table until the end of planned
+ marketplace hours.
+
+
+ 5. Vendor space at the Indigenous Marketplace events will only be
+ shared with other approved Indigenous Marketplace vendors. Any
+ family or friends with the intent to vend will need to complete a
+ vendor application and be approved before vending. (Family, friends
+ and staff are welcomed in your space if they are there to support not sell their
+ own products)
+
+
+ 6. Vendors agree when using canopies/tents they must have four
+ grounded and weighted corners. A minimum of 20 pounds of weight
+ is required to hold down and to secure EACH canopy leg. Weights will
+ be inspected periodically to ensure proper weights are attached to
+ your canopies. **Each vendor is responsible for damages incurred
+ due to fly-aways of their display, canopy or inventory** PIM staff
+ strongly encourage set ups that can be stabilized when winds pick up.
+ PIM is not responsible for any personal losses or damages.
+
+
+ 7. Vendors agree not to drive any motorized vehicle in the marketplace
+ area during marketplace hours. If late arrivals or early pack ups
+ occur, you will not be able to drive your vehicle into the marketplace
+ area to unload or load but carts and equipment may be available for
+ loading/unloading needs.
+
+
+ 8. Before leaving the market, all vendors must clean their booth spaces
+ and ensure that all litter, broken equipment, produce, and other
+ product debris is removed.
+
+
+ 9. While imitation is the sincerest form of flattery, please respect your
+ fellow vendors’ ideas and concepts and refrain from copying them.
+
+
+ 10. Vendors agree to engage in respectful communications with staff, community members, and volunteers.
+ Complaints concerning policies 1-10 must be submitted by completing the
+ Indigenous Marketplace Complaint Form in hardcopy (Exhibit 1) or digital
+ form to PIM staff within 24-48hrs of the marketplace day that the alleged
+ violation is observed. The complaint will then be given to the Vendor Policy
+ Committee for review. The complaint must clearly identify the alleged
+ person of interest, either through vendor name, business name or booth
+ location on the day of the infraction, plus provide the staff with written
+ evidence as to the nature of the alleged violation.
+
+
What happens when a policy complaint occurs?
+
When a complaint is brought forward by community, vendors,
+ volunteers or staff the Vendor Policy Committee will review complaint. If
+ the complaint is found valid the vendor of interest will receive a notice of
+ the appropriate level of accountability.
+ 1. First infraction. A warning will be issued (exhibit 3) to vendor
+ in writing/email and recorded in file/history of vendor.
+ 2. Second infraction. A face to face or zoom meeting will be
+ needed with staff and Vendor Policy Committee before
+ returning to in person events. This infraction will be recorded in
+ writing/email to the vendor and recorded in file/history of
+ vendor (exhibit 3).
+ 3. A plan of separation for the Indigenous Marketplace
+ programming and the Vendor. For severe infractions including
+ but not limited to violence and hate the plan of separation may
+ be permanent. This plan of separation will be shared in
+ writing/email to the vendor and recorded in file/history of
+ vendor (exhibit 2).
+ Portland Indigenous Marketplace:Vendor Policy Handbook
+ 4. Extreme Exceptions: Staff and the Vendor Policy Committee
+ hold the right for severe violations that include but not limited
+ to violence and hate to recommend the plan of separation to be
+ activated with the first validated infraction with written
+ reasoning (exhibit 2) of being extreme to be reviewed by the
+ Board of Directors of the Portland Indigenous Marketplace.
+ This Extreme Exception will be shared in writing/email to the
+ vendor and recorded in file/history of vendor (exhibit 2).
+ Portland Indigenous Marketplace is committed to providing access, equal
+ opportunity and reasonable accommodation for individuals with
+ disabilities, medical needs and other barriers in its services, programs, and
+ activities. To request reasonable accommodations through contact below.
+ info@indigenousmarketplace.org
+ or
503-901-3881
+ Thank you for being a part of the Indigenous Marketplace community!
+
+
+
+
{
+ setShowModalHandlerClose();
+ }} className='bg-blue text-white p-5'>Close Handbook
+
+
+ )
+ }
);
}
Profile.propTypes = {
- VendorService: PropTypes.func.isRequired,
+ vendorService: PropTypes.shape({
+ getVendorById: PropTypes.func.isRequired,
+ }).isRequired,
};
diff --git a/frontend/src/routes/register.jsx b/frontend/src/routes/register.jsx
index a038166..c25929b 100644
--- a/frontend/src/routes/register.jsx
+++ b/frontend/src/routes/register.jsx
@@ -1,7 +1,5 @@
-// import axios from "axios"
import React from 'react';
import {useState} from 'react';
-// import { redirect} from "react-router"
import logo from './../assets/PIM_logo_black.png';
import {Link, useNavigate} from 'react-router-dom';
import {Context} from '../services/context';
diff --git a/frontend/src/routes/vendor.jsx b/frontend/src/routes/vendor.jsx
deleted file mode 100644
index 6a477b3..0000000
--- a/frontend/src/routes/vendor.jsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import React from 'react';
-import {useState} from 'react';
-import {useParams} from 'react-router';
-export default function Vendor() {
- const [vendorId] = useState(useParams().vendorId);
- return (
- You are on the vendor {vendorId} route
-
- );
-}
diff --git a/frontend/src/routes/vendors.jsx b/frontend/src/routes/vendors.jsx
index 6d743f3..6a63447 100644
--- a/frontend/src/routes/vendors.jsx
+++ b/frontend/src/routes/vendors.jsx
@@ -1,26 +1,34 @@
-import React, { useContext, useEffect } from 'react';
-import { useState } from 'react';
+import React, {useContext, useEffect} from 'react';
+import {useState} from 'react';
import PropTypes from 'prop-types';
-import { useNavigate } from 'react-router-dom';
-import { Context } from '../services/context';
+import MessageModal from '../components/messagemodal.jsx'; // changed case of MessageModal, this is convention
+import {useNavigate} from 'react-router-dom';
+import {Context} from '../services/context';
// import {Link} from 'react-router-dom';
// import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
// import {faArrowRight} from '@fortawesome/free-solid-svg-icons';
-function VendorButton({ content, onClick }) {
+import User from '../objects/User.js';
+
+function VendorButton({content, onClick}) {
return (
- {content}
+ {content} // changed the way this onclick works, wasnt working before
);
}
-export default function Vendors({ VendorService }) {
- const [vendors, setVendors] = useState([]);
- const [error, setError] = useState('');
+export default function Vendors({vendorService}) {
+ const [vendors, setVendors] = useState(vendorService.getVendors());
+ const [vendor, setVendor] = useState({});
+ const [openModal, setOpenModal] = useState(false);
+ const [error, setError] = useState(false);
+ const navigate = useNavigate();
+ const {setMessage, setBad} = useContext(Context);
+ const [user, setUser] = useState(User.createFromCookie());
useEffect(() => {
const fetchVendors = async () => {
try {
- const fetchedVendors = await VendorService.getVendors();
+ const fetchedVendors = await vendorService.getVendors();
if (fetchedVendors.length === 0) {
console.error('No vendors found');
} else {
@@ -28,16 +36,28 @@ export default function Vendors({ VendorService }) {
setError('');
}
} catch (error) {
+ setError(true);
console.error('Error fetching vendors:', error);
setError('Failed to fetch vendors.');
}
};
fetchVendors();
- }, [VendorService]);
+ setUser(User.createFromCookie());
+ if (user != undefined) {
+ setMessage('Please log in');
+ setBad(true);
+ navigate('/');
+ }
+ }, [vendorService, user]);
const handleSearch = (vendor) => {
- vendor ? setVendors(VendorService.getVendorByName(vendor)) : setVendors(VendorService.getVendors());
+ vendor ? setVendors(vendorService.getVendorByName(vendor)) : setVendors(vendorService.getVendors());
+ };
+
+ const handleMessage = (vendor) => {
+ setVendor(vendor);
+ setOpenModal(true);
};
const vendorDisplay = (vendor) => (
@@ -45,7 +65,7 @@ export default function Vendors({ VendorService }) {
{vendor.name}
setMessage('please write my code')} content='Invite' />
- setMessage('please write my code')} content='Message' />
+ handleMessage(vendor)} content='Message' />
navigate(`/vendors/:${vendor.id}`)} content='View' />
setMessage('please write my code')} content='Promote' />
@@ -70,13 +90,17 @@ export default function Vendors({ VendorService }) {
)) : vendorDisplay(vendors))
}
+ {openModal && }
);
}
Vendors.propTypes = {
- VendorService: PropTypes.func.isRequired,
+ vendorService: PropTypes.shape({
+ getVendors: PropTypes.func.isRequired,
+ getVendorByName: PropTypes.func.isRequired,
+ }).isRequired,
};
VendorButton.propTypes = {
diff --git a/frontend/src/services/Events/EventsRepository.js b/frontend/src/services/Events/EventsRepository.js
index ee9c193..aa3bc54 100644
--- a/frontend/src/services/Events/EventsRepository.js
+++ b/frontend/src/services/Events/EventsRepository.js
@@ -1,13 +1,11 @@
-import axios from 'axios';
-
export default class EventsRepository {
- constructor(baseUrl) {
- this.baseUrl = baseUrl;
+ constructor(httpClient) {
+ this.httpClient = httpClient;
}
async getAllEvents() {
try {
- const response = await axios.get(`${this.baseUrl}/events`);
+ const response = await this.httpClient.axiosInstance.get('/events');
return response.data;
} catch (error) {
console.error('Error fetching events:', error);
@@ -17,7 +15,7 @@ export default class EventsRepository {
async getEventById(eventId) {
try {
- const response = await axios.get(`${this.baseUrl}/events/${eventId}`);
+ const response = await this.httpClient.axiosInstance.get(`/events/${eventId}`);
return response.data;
} catch (error) {
console.error(`Error fetching event with ID ${eventId}:`, error);
@@ -27,7 +25,7 @@ export default class EventsRepository {
async createEvent(eventData) {
try {
- const response = await axios.post(`${this.baseUrl}/events`, eventData);
+ const response = await this.httpClient.axiosInstance.post('/events', eventData);
return response.data;
} catch (error) {
console.error('Error creating event:', error);
@@ -37,7 +35,7 @@ export default class EventsRepository {
async updateEvent(eventId, eventData) {
try {
- const response = await axios.put(`${this.baseUrl}/events/${eventId}`, eventData);
+ const response = await this.httpClient.axiosInstance.put(`/events/${eventId}`, eventData);
return response.data;
} catch (error) {
console.error(`Error updating event with ID ${eventId}:`, error);
@@ -47,7 +45,7 @@ export default class EventsRepository {
async deleteEvent(eventId) {
try {
- const response = await axios.delete(`${this.baseUrl}/events/${eventId}`);
+ const response = await this.httpClient.axiosInstance.delete(`/events/${eventId}`);
return response.data;
} catch (error) {
console.error(`Error deleting event with ID ${eventId}:`, error);
diff --git a/frontend/src/services/Events/EventsService.js b/frontend/src/services/Events/EventsService.js
index 39672b1..82da5d1 100644
--- a/frontend/src/services/Events/EventsService.js
+++ b/frontend/src/services/Events/EventsService.js
@@ -1,9 +1,9 @@
-import EventsRepository from './EventsRepository';
-import Event from '../../objects/Event';
+import EventsRepository from './EventsRepository.js';
+import Event from '../../objects/Event.js';
export default class EventsService {
- constructor(baseUrl) {
- this.eventsRepository = new EventsRepository(baseUrl);
+ constructor(httpClient) {
+ this.eventsRepository = new EventsRepository(httpClient);
}
async getAllEvents() {
diff --git a/frontend/src/services/HttpClient.js b/frontend/src/services/HttpClient.js
new file mode 100644
index 0000000..0fd5fd6
--- /dev/null
+++ b/frontend/src/services/HttpClient.js
@@ -0,0 +1,17 @@
+import axios from 'axios';
+
+class HttpClient {
+ constructor(baseURL) {
+ this.axiosInstance = axios.create({
+ baseURL: baseURL,
+ });
+ this.cookie = '';
+ }
+
+ setCookie(cookie) {
+ this.cookie = cookie;
+ this.axiosInstance.defaults.headers.common['Cookie'] = cookie;
+ }
+}
+
+export default HttpClient;
diff --git a/frontend/src/services/MockServices/MockEventService.js b/frontend/src/services/MockServices/MockEventService.js
index 5d77c76..d049a57 100644
--- a/frontend/src/services/MockServices/MockEventService.js
+++ b/frontend/src/services/MockServices/MockEventService.js
@@ -1,4 +1,4 @@
-import Event from '../../objects/Event';
+import Event from '../../objects/Event.js';
export default class MockEventService {
static mockEvents = [];
diff --git a/frontend/src/services/Vendors/VendorsRepository.js b/frontend/src/services/Vendors/VendorsRepository.js
index fa37f46..1203375 100644
--- a/frontend/src/services/Vendors/VendorsRepository.js
+++ b/frontend/src/services/Vendors/VendorsRepository.js
@@ -1,67 +1,86 @@
-import axios from 'axios';
-
export default class VendorsRepository {
- constructor(baseUrl) {
- this.baseUrl = baseUrl;
+ constructor(httpClient) {
+ this.httpClient = httpClient;
}
async getAllVendors() {
try {
- const response = await axios.get(`${this.baseUrl}/vendors`);
+ const response = await this.httpClient.axiosInstance.get('/vendors');
return response.data;
} catch (error) {
- console.error('Error fetching vendors:', error);
- throw error;
+ console.error('Error fetching vendors');
+ return undefined;
}
}
async getVendorById(vendorId) {
try {
- const response = await axios.get(`${this.baseUrl}/vendors/${vendorId}`);
+ const response = await this.httpClient.axiosInstance.get(`/vendors/${vendorId}`);
return response.data;
} catch (error) {
- console.error(`Error fetching vendor with ID ${vendorId}:`, error);
- throw error;
+ console.error(`Error fetching vendor with ID ${vendorId}:`);
+ return undefined;
}
}
async authenticateVendor(vendorData) {
try {
- const response = await axios.post(`${this.baseUrl}/vendors/login`, vendorData);
- return response.data;
+ const response = await this.httpClient.axiosInstance.post('vendors/login', vendorData);
+ this.httpClient.setCookie(response.headers['set-cookie'][0]);
+ return response;
} catch (error) {
- console.error('Error logging in vendor:', error);
- throw error;
+ console.error('Error logging in vendor:');
+ return undefined;
}
}
async createVendor(vendorData) {
try {
- const response = await axios.post(`${this.baseUrl}/vendors`, vendorData);
+ const response = await this.httpClient.axiosInstance.post('/vendors', vendorData);
+ return response.data;
+ } catch (error) {
+ console.error('Error creating vendor:');
+ return undefined;
+ }
+ }
+
+ async updateSelfVendor(vendorData) {
+ try {
+ const response = await this.httpClient.axiosInstance.put('/vendors', vendorData);
return response.data;
} catch (error) {
- console.error('Error creating vendor:', error);
- throw error;
+ console.error('Error updating vendor:');
+ return undefined;
}
}
async updateVendor(vendorId, vendorData) {
try {
- const response = await axios.put(`${this.baseUrl}/vendors/${vendorId}`, vendorData);
+ const response = await this.httpClient.axiosInstance.put(`/vendors/${vendorId}`, vendorData);
return response.data;
} catch (error) {
- console.error(`Error updating vendor with ID ${vendorId}:`, error);
- throw error;
+ console.error(`Error updating vendor with ID ${vendorId}:`);
+ return undefined;
}
}
async deleteVendor(vendorId) {
try {
- const response = await axios.delete(`${this.baseUrl}/vendors/${vendorId}`);
+ const response = await this.httpClient.axiosInstance.delete(`/vendors/${vendorId}`);
+ return response.data;
+ } catch (error) {
+ console.error(`Error deleting vendor with ID ${vendorId}:`);
+ return undefined;
+ }
+ }
+
+ async logout() {
+ try {
+ const response = await this.httpClient.axiosInstance.post('/logout');
return response.data;
} catch (error) {
- console.error(`Error deleting vendor with ID ${vendorId}:`, error);
- throw error;
+ console.error('Error logging out:');
+ return undefined;
}
}
}
diff --git a/frontend/src/services/Vendors/VendorsService.js b/frontend/src/services/Vendors/VendorsService.js
index 69ed796..5d8ba16 100644
--- a/frontend/src/services/Vendors/VendorsService.js
+++ b/frontend/src/services/Vendors/VendorsService.js
@@ -1,19 +1,23 @@
-import VendorsRepository from './VendorsRepository';
-import Vendor from '../../objects/Vendor';
+import VendorsRepository from './VendorsRepository.js';
+import Vendor from '../../objects/Vendor.js';
export default class VendorsService {
- constructor(baseUrl) {
- this.vendorsRepository = new VendorsRepository(baseUrl);
+ constructor(httpClient) {
+ this.vendorsRepository = new VendorsRepository(httpClient);
}
async getVendors() {
const vendorsData = await this.vendorsRepository.getAllVendors();
+ if (vendorsData == undefined) {
+ return undefined;
+ }
+
return vendorsData.map((data) => new Vendor(
- data.vendorId,
+ data.vendor_id,
data.name,
data.email,
data.website,
- data.phoneNumber,
+ data.phone_number,
data.image,
));
}
@@ -21,11 +25,11 @@ export default class VendorsService {
async getVendorById(vendorId) {
const vendorData = await this.vendorsRepository.getVendorById(vendorId);
return new Vendor(
- vendorData.vendorId,
+ vendorData.vendor_id,
vendorData.name,
vendorData.email,
vendorData.website,
- vendorData.phoneNumber,
+ vendorData.phone_number,
vendorData.image,
);
}
@@ -35,14 +39,15 @@ export default class VendorsService {
email: vendor.email,
password: vendor.password,
};
- return await this.vendorsRepository.authenticateVendor(vendorData);
+ const response = await this.vendorsRepository.authenticateVendor(vendorData);
+ return response;
}
- async createVendor(vendor) {
+ async createVendor(vendor, password) {
const vendorData = {
name: vendor.name,
email: vendor.email,
- password: vendor.password,
+ password: password,
website: vendor.website,
phoneNumber: vendor.phoneNumber,
image: vendor.image,
@@ -50,6 +55,16 @@ export default class VendorsService {
return await this.vendorsRepository.createVendor(vendorData);
}
+ async updateSelfVendor(vendor) {
+ const vendorData = {
+ name: vendor.name,
+ email: vendor.email,
+ website: vendor.website,
+ phone_number: vendor.phoneNumber,
+ };
+ return await this.vendorsRepository.updateSelfVendor(vendorData);
+ }
+
async updateVendor(vendor) {
const vendorData = {
name: vendor.name,
@@ -64,4 +79,8 @@ export default class VendorsService {
async deleteVendor(vendorId) {
return await this.vendorsRepository.deleteVendor(vendorId);
}
+
+ async logout() {
+ return await this.vendorsRepository.logout();
+ }
}
diff --git a/frontend/src/services/handleLogin.js b/frontend/src/services/handleLogin.js
index f3196e1..c377e03 100644
--- a/frontend/src/services/handleLogin.js
+++ b/frontend/src/services/handleLogin.js
@@ -1,11 +1,16 @@
import axios from 'axios';
-import config from '../config';
+import config from '../config.js';
+
export async function handleLoginVendor(data) {
const server = axios.create({
baseURL: config.baseUrl,
});
- let response;
- await server.post('/vendors/login', data).then((res) => response = res).catch((err) => console.log('error:', err));
- console.log('response:', response);
- return response;
+
+ try {
+ const res = await server.post('/vendors/login', data);
+ return res;
+ } catch ( e ) {
+ console.log(e);
+ return e.response;
+ }
}
diff --git a/frontend/src/services/handleRegister.js b/frontend/src/services/handleRegister.js
index 08a364d..7634e3b 100644
--- a/frontend/src/services/handleRegister.js
+++ b/frontend/src/services/handleRegister.js
@@ -1,5 +1,5 @@
import axios from 'axios';
-import config from '../config';
+import config from '../config.js';
// function that returns a boolean, true if the registration was successful, false otherwise.
export async function handleRegister(data) {
const server = axios.create({
diff --git a/frontend/src/tests/integration/vendor.test.js b/frontend/src/tests/integration/vendor.test.js
new file mode 100644
index 0000000..2e52486
--- /dev/null
+++ b/frontend/src/tests/integration/vendor.test.js
@@ -0,0 +1,107 @@
+import {expect} from 'chai';
+import VendorsService from '../../services/Vendors/VendorsService.js';
+import Vendor from '../../objects/Vendor.js';
+import axios from 'axios';
+import HttpClient from '../../services/HttpClient.js';
+
+describe('Vendors Service', function() {
+ this.timeout(10000); // Set timeout for all tests in this describe block
+ const httpClient = new HttpClient('http://backend-test:4001/api');
+ const vendorService = new VendorsService(httpClient);
+
+ // Use async/await with the before hook
+ before(async function() {
+ await waitForService('http://backend-test:4001/api/health', 100000, 5000);
+ });
+
+ describe('Add Vendor', function() {
+ it('should add a vendor', async function() {
+ const vendor = new Vendor(
+ 1, 'John Smith', 'John.smith@gmail.com',
+ 'www.johnsmith.com', '123-456-7890', 'https://www.kasandbox.org/programming-images/avatars/spunky-sam.png');
+ const password = 'password';
+ try {
+ const res = await vendorService.createVendor(vendor, password);
+ expect(res.status).to.equal('success');
+ } catch (error) {
+ // Handle errors or failed assertions
+ console.error('Test failed', error);
+ throw error; // Rethrow to make the test fail
+ }
+ });
+ });
+
+ describe('Get Vendors', function() {
+ it('should get all vendors', async function() {
+ try {
+ const vendors = await vendorService.getVendors();
+ expect(vendors.length).to.be.at.least(1);
+ } catch (error) {
+ console.error('Test failed', error);
+ throw error;
+ }
+ });
+ });
+
+ describe('Get Vendor By ID', function() {
+ it('should get a vendor by ID', async function() {
+ const vendorId = 1;
+ try {
+ const vendor = await vendorService.getVendorById(vendorId);
+ expect(vendor.id).to.equal(vendorId);
+ } catch (error) {
+ console.error('Test failed', error);
+ throw error;
+ }
+ });
+ });
+
+ describe('Authenticate Vendor', function() {
+ it('should authenticate a vendor', async function() {
+ const email = 'John.smith@gmail.com';
+ const password = 'password';
+ try {
+ const response = await vendorService.authenticateVendor({email, password});
+ expect(response.status).to.equal(200);
+ } catch (error) {
+ console.error('Test failed', error);
+ throw error;
+ }
+ });
+ });
+
+ describe('Update Vendor', function() {
+ it('should update a vendor', async function() {
+ const vendor = new Vendor(
+ 1, 'Jane Doe', 'John.smith@gmail.com',
+ 'www.johnsmith.com', '123-456-7890', 'https://www.kasandbox.org/programming-images/avatars/spunky-sam.png');
+ try {
+ const res = await vendorService.updateSelfVendor(vendor);
+ expect(res.status).to.equal('success');
+ } catch (error) {
+ console.error('Test failed', error);
+ throw error;
+ }
+ });
+ });
+});
+
+// Function to wait for the backend service to be ready
+async function waitForService(url, timeout = 5000, interval = 1000) {
+ console.log(`Waiting for service at ${url} to be ready...`);
+ const startTime = Date.now();
+
+ while (true) {
+ try {
+ await axios.get(url);
+ console.log(`Service at ${url} is ready.`);
+ break; // Exit loop if request succeeds
+ } catch (error) {
+ console.log(`Service at ${url} is not ready yet: ${error.message}`);
+ if (Date.now() - startTime > timeout) {
+ throw new Error(`Service at ${url} did not become ready in time: ${error.message}`);
+ }
+ await new Promise((resolve) => setTimeout(resolve, interval)); // Wait before next attempt
+ }
+ }
+}
diff --git a/package-lock.json b/package-lock.json
index b140292..651eff3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,1834 @@
{
+<<<<<<< HEAD
"name": "f23-PortlandIndigenousMarketplace",
"lockfileVersion": 3,
"requires": true,
"packages": {}
+=======
+ "requires": true,
+ "lockfileVersion": 1,
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.23.9",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
+ "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
+ "requires": {
+ "regenerator-runtime": "^0.14.0"
+ }
+ },
+ "@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "requires": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA=="
+ },
+ "emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+ },
+ "string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "requires": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ }
+ },
+ "string-width-cjs": {
+ "version": "npm:string-width@4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "requires": {
+ "ansi-regex": "^6.0.1"
+ }
+ },
+ "strip-ansi-cjs": {
+ "version": "npm:strip-ansi@6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+ }
+ }
+ }
+ }
+ },
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+ "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "requires": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="
+ },
+ "@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw=="
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.22",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz",
+ "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==",
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "@mapbox/node-pre-gyp": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
+ "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
+ "requires": {
+ "detect-libc": "^2.0.0",
+ "https-proxy-agent": "^5.0.0",
+ "make-dir": "^3.1.0",
+ "node-fetch": "^2.6.7",
+ "nopt": "^5.0.0",
+ "npmlog": "^5.0.1",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.11"
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "optional": true
+ },
+ "@popperjs/core": {
+ "version": "2.11.8",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
+ "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
+ },
+ "@react-pdf/fns": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-2.1.0.tgz",
+ "integrity": "sha512-EZAvv96Ec0zxwvpL5jyVHY22FlzTQcrQn7WFzknx1BsaeF5P74m1SV2UnIfyFxrottw0H4f3n5XJjMgrR5yTYg==",
+ "requires": {
+ "@babel/runtime": "^7.20.13"
+ }
+ },
+ "@react-pdf/font": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@react-pdf/font/-/font-2.4.2.tgz",
+ "integrity": "sha512-p4bDluB99/Rdhy8ynPND4k335RT2bhCuV6jzwqqZkKOKZ2lG2VjE7/DJyKdFMLE+dbPuM5MDX5dDp0FQbtQT/w==",
+ "requires": {
+ "@babel/runtime": "^7.20.13",
+ "@react-pdf/types": "^2.4.0",
+ "cross-fetch": "^3.1.5",
+ "fontkit": "^2.0.2",
+ "is-url": "^1.2.4"
+ }
+ },
+ "@react-pdf/image": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@react-pdf/image/-/image-2.3.1.tgz",
+ "integrity": "sha512-wfnbw0AGFRHIyx6I/LbHfYwD/OW8JM1ItR2H6pdY80SclgiM+jS2tOu7LOwoqCbXr9X6ReyhqqZPBLUa+hSLmA==",
+ "requires": {
+ "@babel/runtime": "^7.20.13",
+ "@react-pdf/png-js": "^2.3.0",
+ "cross-fetch": "^3.1.5",
+ "jpeg-exif": "^1.1.4"
+ }
+ },
+ "@react-pdf/layout": {
+ "version": "3.10.3",
+ "resolved": "https://registry.npmjs.org/@react-pdf/layout/-/layout-3.10.3.tgz",
+ "integrity": "sha512-JT6wfbBh5an7YmD0VIG8A/PLmj2kMzjnS874kxK+5WOaEQOx8oEw+OEMqk67jK413JIPYLR4+BdjplI7iwOsUQ==",
+ "requires": {
+ "@babel/runtime": "^7.20.13",
+ "@react-pdf/fns": "2.1.0",
+ "@react-pdf/image": "^2.3.1",
+ "@react-pdf/pdfkit": "^3.1.2",
+ "@react-pdf/primitives": "^3.1.1",
+ "@react-pdf/stylesheet": "^4.2.2",
+ "@react-pdf/textkit": "^4.3.0",
+ "@react-pdf/types": "^2.4.0",
+ "cross-fetch": "^3.1.5",
+ "emoji-regex": "^10.3.0",
+ "queue": "^6.0.1",
+ "yoga-layout": "^2.0.1"
+ },
+ "dependencies": {
+ "emoji-regex": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
+ "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw=="
+ }
+ }
+ },
+ "@react-pdf/pdfkit": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-3.1.2.tgz",
+ "integrity": "sha512-/u8uT/LE7C67maMQHQdV20wwwD1jG0yLfSJ0PJEJG/bn2GvIWy5aaNLlHTMdHXLzkr2NdgEZcevI/2WEfQxUjQ==",
+ "requires": {
+ "@babel/runtime": "^7.20.13",
+ "@react-pdf/png-js": "^2.3.0",
+ "browserify-zlib": "^0.2.0",
+ "crypto-js": "^4.2.0",
+ "fontkit": "^2.0.2",
+ "jpeg-exif": "^1.1.4",
+ "vite-compatible-readable-stream": "^3.6.1"
+ }
+ },
+ "@react-pdf/png-js": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-2.3.0.tgz",
+ "integrity": "sha512-+HLW7JZ09P8isxFq3hJJ9ppdCyQWLErfekkQHKNdpxoVW9S3tokJmaKofTvhAy6XA4Yd1QlN9en0iJ8V5mDdQA==",
+ "requires": {
+ "browserify-zlib": "^0.2.0"
+ }
+ },
+ "@react-pdf/primitives": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-3.1.1.tgz",
+ "integrity": "sha512-miwjxLwTnO3IjoqkTVeTI+9CdyDggwekmSLhVCw+a/7FoQc+gF3J2dSKwsHvAcVFM0gvU8mzCeTofgw0zPDq0w=="
+ },
+ "@react-pdf/render": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/@react-pdf/render/-/render-3.4.1.tgz",
+ "integrity": "sha512-wLs9L20OWv6Dz0QTWeTtX+ZyxGHYWD1VFWcbvOC3vYq9caA81QisMn5T4Tfzn5HaxRz5VBFy+pQ8dFR54n86Wg==",
+ "requires": {
+ "@babel/runtime": "^7.20.13",
+ "@react-pdf/fns": "2.1.0",
+ "@react-pdf/primitives": "^3.1.1",
+ "@react-pdf/textkit": "^4.3.0",
+ "@react-pdf/types": "^2.4.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": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/@react-pdf/renderer/-/renderer-3.3.4.tgz",
+ "integrity": "sha512-Y8tOGOeSZ/alYlvmngK90EbYJItcsE0D2yY2E9Nt+6K7oLPwgw8CY6D2zaPYNHvzyJWRGbIuML8noK/CY2zRug==",
+ "requires": {
+ "@babel/runtime": "^7.20.13",
+ "@react-pdf/font": "^2.4.2",
+ "@react-pdf/layout": "^3.10.3",
+ "@react-pdf/pdfkit": "^3.1.2",
+ "@react-pdf/primitives": "^3.1.1",
+ "@react-pdf/render": "^3.4.1",
+ "@react-pdf/types": "^2.4.0",
+ "events": "^3.3.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2",
+ "queue": "^6.0.1",
+ "scheduler": "^0.17.0"
+ }
+ },
+ "@react-pdf/stylesheet": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-4.2.2.tgz",
+ "integrity": "sha512-2VRjp2oIXrSqYZebEMfIiFfbHeuVag8hrY2APAfCsQptvSpc6JHv/2OK1o07zxS6AkUDSyjlH6MUbEcIkwhdIA==",
+ "requires": {
+ "@babel/runtime": "^7.20.13",
+ "@react-pdf/fns": "2.1.0",
+ "@react-pdf/types": "^2.4.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": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-4.3.0.tgz",
+ "integrity": "sha512-A0bbHFxLYOh2lEFKbtgefmxlJEVbCX5dRhaI5ORwgHJNpbFOCTQyowq3h9gWXO9sSWl5GQdTTYAO35wp4oS2NQ==",
+ "requires": {
+ "@babel/runtime": "^7.20.13",
+ "@react-pdf/fns": "2.1.0",
+ "hyphen": "^1.6.4",
+ "unicode-properties": "^1.4.1"
+ }
+ },
+ "@react-pdf/types": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/@react-pdf/types/-/types-2.4.0.tgz",
+ "integrity": "sha512-vq+xghyedWYtVvTmKl+pwoKgHzCtWzful1YJ2vqR4w0/lhtq4RK473jLUrhgzrGgE+xnpHiNW8AkGov6bnQmkg=="
+ },
+ "@swc/helpers": {
+ "version": "0.4.36",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.36.tgz",
+ "integrity": "sha512-5lxnyLEYFskErRPenYItLRSge5DjrJngYKdVjRSrWfza9G6KkgHEXi0vUZiyUeMU5JfXH1YnvXZzSp8ul88o2Q==",
+ "requires": {
+ "legacy-swc-helpers": "npm:@swc/helpers@=0.4.14",
+ "tslib": "^2.4.0"
+ }
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "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=="
+ },
+ "agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "requires": {
+ "debug": "4"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+ },
+ "ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="
+ },
+ "any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
+ },
+ "anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "aproba": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
+ },
+ "are-we-there-yet": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
+ "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^3.6.0"
+ }
+ },
+ "arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+ },
+ "binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "brotli": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz",
+ "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==",
+ "requires": {
+ "base64-js": "^1.1.2"
+ }
+ },
+ "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==",
+ "requires": {
+ "pako": "~1.0.5"
+ },
+ "dependencies": {
+ "pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
+ }
+ }
+ },
+ "camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="
+ },
+ "canvas": {
+ "version": "2.11.2",
+ "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz",
+ "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==",
+ "requires": {
+ "@mapbox/node-pre-gyp": "^1.0.0",
+ "nan": "^2.17.0",
+ "simple-get": "^3.0.3"
+ }
+ },
+ "chart.js": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz",
+ "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w=="
+ },
+ "chartjs-plugin-datalabels": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz",
+ "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw=="
+ },
+ "chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "requires": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "fsevents": "~2.3.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
+ "chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
+ },
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
+ },
+ "clsx": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
+ "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg=="
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "requires": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "color-support": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="
+ },
+ "commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
+ },
+ "cross-fetch": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz",
+ "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==",
+ "requires": {
+ "node-fetch": "^2.6.12"
+ }
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "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=="
+ },
+ "cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
+ },
+ "custom-event-polyfill": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz",
+ "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w=="
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "decompress-response": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
+ "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
+ "requires": {
+ "mimic-response": "^2.0.0"
+ }
+ },
+ "deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
+ },
+ "dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="
+ },
+ "detect-autofill": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/detect-autofill/-/detect-autofill-1.1.4.tgz",
+ "integrity": "sha512-utCBQwCR/beSnADQmBC7C4tTueBBkYCl6WSpfGUkYKO/+MzPxqYGj6G4MvHzcKmH1gCTK+VunX2vaagvkRXPvA==",
+ "requires": {
+ "custom-event-polyfill": "^1.0.7"
+ }
+ },
+ "detect-libc": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz",
+ "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="
+ },
+ "dfa": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
+ "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q=="
+ },
+ "didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
+ },
+ "dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
+ },
+ "eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="
+ },
+ "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=="
+ },
+ "fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
+ "fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "fontkit": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.2.tgz",
+ "integrity": "sha512-jc4k5Yr8iov8QfS6u8w2CnHWVmbOGtdBtOXMze5Y+QD966Rx6PEVWXSEGwXlsDlKtu1G12cJjcsybnqhSk/+LA==",
+ "requires": {
+ "@swc/helpers": "^0.4.2",
+ "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"
+ }
+ },
+ "foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "dependencies": {
+ "signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="
+ }
+ }
+ },
+ "fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "requires": {
+ "minipass": "^3.0.0"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ },
+ "fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+ },
+ "gauge": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
+ "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
+ "requires": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.2",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.1",
+ "object-assign": "^4.1.1",
+ "signal-exit": "^3.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.2"
+ }
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "requires": {
+ "is-glob": "^4.0.3"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
+ },
+ "hasown": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
+ "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
+ "requires": {
+ "function-bind": "^1.1.2"
+ }
+ },
+ "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==",
+ "requires": {
+ "hsl-to-rgb-for-reals": "^1.1.0"
+ }
+ },
+ "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=="
+ },
+ "https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "requires": {
+ "agent-base": "6",
+ "debug": "4"
+ }
+ },
+ "hyphen": {
+ "version": "1.10.4",
+ "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.10.4.tgz",
+ "integrity": "sha512-SejXzIpv9gOVdDWXd4suM1fdF1k2dxZGvuTdkOVLoazYfK7O4DykIQbdrvuyG+EaTNlXAGhMndtKrhykgbt0gg=="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-core-module": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+ "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "requires": {
+ "hasown": "^2.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+ },
+ "is-url": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
+ "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "jackspeak": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "requires": {
+ "@isaacs/cliui": "^8.0.2",
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "jiti": {
+ "version": "1.21.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
+ "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q=="
+ },
+ "jpeg-exif": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/jpeg-exif/-/jpeg-exif-1.1.4.tgz",
+ "integrity": "sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ=="
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "legacy-swc-helpers": {
+ "version": "npm:@swc/helpers@0.4.14",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz",
+ "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==",
+ "requires": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "lilconfig": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
+ "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ=="
+ },
+ "lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "make-cancellable-promise": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/make-cancellable-promise/-/make-cancellable-promise-1.3.2.tgz",
+ "integrity": "sha512-GCXh3bq/WuMbS+Ky4JBPW1hYTOU+znU+Q5m9Pu+pI8EoUqIHk9+tviOKC6/qhHh8C4/As3tzJ69IF32kdz85ww=="
+ },
+ "make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "requires": {
+ "semver": "^6.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
+ }
+ }
+ },
+ "make-event-props": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.6.2.tgz",
+ "integrity": "sha512-iDwf7mA03WPiR8QxvcVHmVWEPfMY1RZXerDVNCRYW7dUr2ppH3J58Rwb39/WG39yTZdRSxr3x+2v22tvI0VEvA=="
+ },
+ "media-engine": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz",
+ "integrity": "sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg=="
+ },
+ "merge-refs": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-1.2.2.tgz",
+ "integrity": "sha512-RwcT7GsQR3KbuLw1rRuodq4Nt547BKEBkliZ0qqsrpyNne9bGTFtsFIsIpx82huWhcl3kOlOlH4H0xkPk/DqVw=="
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "mimic-response": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
+ "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA=="
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="
+ },
+ "minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "requires": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "requires": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "nan": {
+ "version": "2.18.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz",
+ "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w=="
+ },
+ "nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="
+ },
+ "node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ }
+ },
+ "nopt": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+ "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+ "requires": {
+ "abbrev": "1"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+ },
+ "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==",
+ "requires": {
+ "svg-arc-to-cubic-bezier": "^3.0.0"
+ }
+ },
+ "npmlog": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
+ "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
+ "requires": {
+ "are-we-there-yet": "^2.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^3.0.0",
+ "set-blocking": "^2.0.0"
+ }
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+ },
+ "object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "pako": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="
+ },
+ "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=="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "path-scurry": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
+ "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+ "requires": {
+ "lru-cache": "^9.1.1 || ^10.0.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
+ "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q=="
+ }
+ }
+ },
+ "path2d-polyfill": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz",
+ "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA=="
+ },
+ "pdfjs-dist": {
+ "version": "3.11.174",
+ "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz",
+ "integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==",
+ "requires": {
+ "canvas": "^2.11.2",
+ "path2d-polyfill": "^2.0.1"
+ }
+ },
+ "perfect-scrollbar": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz",
+ "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g=="
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="
+ },
+ "pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg=="
+ },
+ "postcss": {
+ "version": "8.4.35",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
+ "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==",
+ "requires": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ }
+ },
+ "postcss-import": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz",
+ "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==",
+ "requires": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ }
+ },
+ "postcss-js": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
+ "requires": {
+ "camelcase-css": "^2.0.1"
+ }
+ },
+ "postcss-load-config": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz",
+ "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==",
+ "requires": {
+ "lilconfig": "^2.0.5",
+ "yaml": "^1.10.2"
+ }
+ },
+ "postcss-nested": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz",
+ "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==",
+ "requires": {
+ "postcss-selector-parser": "^6.0.10"
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "6.0.15",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz",
+ "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==",
+ "requires": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+ },
+ "prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "queue": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
+ "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
+ "requires": {
+ "inherits": "~2.0.3"
+ }
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="
+ },
+ "quick-lru": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
+ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="
+ },
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "react-pdf": {
+ "version": "7.7.0",
+ "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-7.7.0.tgz",
+ "integrity": "sha512-704ObLnRDm5lixL4e6NXNLaincBHGNLo+NGdbO3rEXE963NlNzwLxFpmKcbdXHAMQL4rYJQWb1L0w5IL6y8Osw==",
+ "requires": {
+ "clsx": "^2.0.0",
+ "dequal": "^2.0.3",
+ "make-cancellable-promise": "^1.3.1",
+ "make-event-props": "^1.6.0",
+ "merge-refs": "^1.2.1",
+ "pdfjs-dist": "3.11.174",
+ "prop-types": "^15.6.2",
+ "tiny-invariant": "^1.0.0",
+ "warning": "^4.0.0"
+ }
+ },
+ "read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "requires": {
+ "pify": "^2.3.0"
+ }
+ },
+ "readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
+ },
+ "resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "requires": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "restructure": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.0.tgz",
+ "integrity": "sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw=="
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ },
+ "scheduler": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.17.0.tgz",
+ "integrity": "sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1"
+ }
+ },
+ "semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
+ },
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
+ "simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
+ },
+ "simple-get": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
+ "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
+ "requires": {
+ "decompress-response": "^4.2.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "requires": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "requires": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "sucrase": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
+ "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+ "requires": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "^10.3.10",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "requires": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ }
+ },
+ "minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
+ }
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
+ },
+ "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=="
+ },
+ "tailwindcss": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.0.tgz",
+ "integrity": "sha512-hOXlFx+YcklJ8kXiCAfk/FMyr4Pm9ck477G0m/us2344Vuj355IpoEDB5UmGAsSpTBmr+4ZhjzW04JuFXkb/fw==",
+ "requires": {
+ "arg": "^5.0.2",
+ "chokidar": "^3.5.3",
+ "color-name": "^1.1.4",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.2.12",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.17.2",
+ "lilconfig": "^2.0.6",
+ "micromatch": "^4.0.5",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.0.0",
+ "postcss": "^8.0.9",
+ "postcss-import": "^14.1.0",
+ "postcss-js": "^4.0.0",
+ "postcss-load-config": "^3.1.4",
+ "postcss-nested": "6.0.0",
+ "postcss-selector-parser": "^6.0.11",
+ "postcss-value-parser": "^4.2.0",
+ "quick-lru": "^5.1.1",
+ "resolve": "^1.22.1",
+ "sucrase": "^3.29.0"
+ }
+ },
+ "tar": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
+ "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
+ "requires": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ }
+ },
+ "thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "requires": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "requires": {
+ "thenify": ">= 3.1.0 < 4"
+ }
+ },
+ "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=="
+ },
+ "tiny-invariant": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz",
+ "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw=="
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
+ "ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
+ },
+ "tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+ },
+ "tw-elements": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/tw-elements/-/tw-elements-1.1.0.tgz",
+ "integrity": "sha512-IUr9YW2l99oTVZxuVjQg6rpuCpo6VZqbaKGYmZUNVVsoSVU/ljPpkJAY2Pn/morlXwKPhP9MTPNQMlWosqHL4w==",
+ "requires": {
+ "@popperjs/core": "^2.6.0",
+ "chart.js": "^3.7.1",
+ "chartjs-plugin-datalabels": "^2.0.0",
+ "deepmerge": "^4.2.2",
+ "detect-autofill": "^1.1.3",
+ "perfect-scrollbar": "^1.5.5",
+ "tailwindcss": "3.3.0"
+ }
+ },
+ "unicode-properties": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz",
+ "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==",
+ "requires": {
+ "base64-js": "^1.3.0",
+ "unicode-trie": "^2.0.0"
+ }
+ },
+ "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==",
+ "requires": {
+ "pako": "^0.2.5",
+ "tiny-inflate": "^1.0.0"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "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==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "warning": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
+ "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
+ "requires": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "requires": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "wide-align": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+ "requires": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "requires": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA=="
+ },
+ "emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+ },
+ "string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "requires": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "requires": {
+ "ansi-regex": "^6.0.1"
+ }
+ }
+ }
+ },
+ "wrap-ansi-cjs": {
+ "version": "npm:wrap-ansi@7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
+ "yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="
+ },
+ "yoga-layout": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-2.0.1.tgz",
+ "integrity": "sha512-tT/oChyDXelLo2A+UVnlW9GU7CsvFMaEnd9kVFsaiCQonFAXd3xrHhkLYu+suwwosrAEQ746xBU+HvYtm1Zs2Q=="
+ }
+ }
+>>>>>>> main
}
diff --git a/sql-scripts/init.sql b/sql-scripts/init.sql
index c4474f4..b85945a 100644
--- a/sql-scripts/init.sql
+++ b/sql-scripts/init.sql
@@ -1,7 +1,7 @@
-- Create the tables
-- Admins table
-CREATE TABLE Admins (
+CREATE TABLE IF NOT EXISTS Admins (
admin_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(320) UNIQUE NOT NULL,
@@ -9,7 +9,7 @@ CREATE TABLE Admins (
);
-- Vendors table
-CREATE TABLE Vendors (
+CREATE TABLE IF NOT EXISTS Vendors (
vendor_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
phone_number VARCHAR(31),
@@ -19,7 +19,7 @@ CREATE TABLE Vendors (
);
-- Events table
-CREATE TABLE Events (
+CREATE TABLE IF NOT EXISTS Events (
event_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
location VARCHAR(255),
@@ -30,14 +30,14 @@ CREATE TABLE Events (
);
-- Violations table
-CREATE TABLE Violation (
+CREATE TABLE IF NOT EXISTS Violation (
violation_id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT
);
-- Violations_to_Vendors table
-CREATE TABLE VendorViolations (
+CREATE TABLE IF NOT EXISTS VendorViolations (
violation_id INT REFERENCES Violation(violation_id),
vendor_id INT REFERENCES Vendors(vendor_id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
@@ -45,7 +45,7 @@ CREATE TABLE VendorViolations (
);
-- Event_Requests table
-CREATE TABLE EventRequests (
+CREATE TABLE IF NOT EXISTS EventRequests (
request_id SERIAL PRIMARY KEY,
vendor_id INT REFERENCES Vendors(vendor_id),
event_id INT REFERENCES Events(event_id),