From 36f518afca3a1714406cb4d41b01f5a6cd133593 Mon Sep 17 00:00:00 2001 From: mzerone Date: Thu, 1 Aug 2024 00:41:35 +0200 Subject: [PATCH 01/14] add create user in settings. --- src/pages/(admin)/BatchCreateUser.tsx | 236 ++++++++++++++++++++++++++ src/pages/api/make_user.ts | 110 ++++++++++++ src/pages/settings.tsx | 6 +- src/utils/permissions.ts | 2 +- 4 files changed, 351 insertions(+), 3 deletions(-) create mode 100644 src/pages/(admin)/BatchCreateUser.tsx create mode 100644 src/pages/api/make_user.ts diff --git a/src/pages/(admin)/BatchCreateUser.tsx b/src/pages/(admin)/BatchCreateUser.tsx new file mode 100644 index 00000000..d470c2e8 --- /dev/null +++ b/src/pages/(admin)/BatchCreateUser.tsx @@ -0,0 +1,236 @@ +import Button from "@/components/Low/Button"; +import useUsers from "@/hooks/useUsers"; +import { Type as UserType, User } from "@/interfaces/user"; +import axios from "axios"; +import { uniqBy } from "lodash"; +import { useEffect, useState } from "react"; +import { toast } from "react-toastify"; +import { useFilePicker } from "use-file-picker"; +import readXlsxFile from "read-excel-file"; +import Modal from "@/components/Modal"; +import { BsQuestionCircleFill } from "react-icons/bs"; +import { PermissionType } from "@/interfaces/permissions"; +const EMAIL_REGEX = new RegExp( + /^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*$/ +); + +type Type = Exclude + +const USER_TYPE_LABELS: {[key in Type]: string} = { + student: "Student", + teacher: "Teacher", + corporate: "Corporate", +}; + +const USER_TYPE_PERMISSIONS: { + [key in Type]: { perm: PermissionType | undefined; list: Type[] }; +} = { + student: { + perm: "createCodeStudent", + list: [], + }, + teacher: { + perm: "createCodeTeacher", + list: [], + }, + corporate: { + perm: "createCodeCorporate", + list: ["student", "teacher"], + }, +}; + +export default function BatchCreateUser({ user }: { user: User }) { + const [infos, setInfos] = useState< + { email: string; name: string; passport_id:string, type: Type, demographicInformation: { + country: string, + passport_id:string, + phone: string + } }[] + >([]); + const [isLoading, setIsLoading] = useState(false); + const [type, setType] = useState("student"); + const [showHelp, setShowHelp] = useState(false); + + const { users } = useUsers(); + + const { openFilePicker, filesContent, clear } = useFilePicker({ + accept: ".xlsx", + multiple: false, + readAs: "ArrayBuffer", + }); + + + useEffect(() => { + if (filesContent.length > 0) { + const file = filesContent[0]; + readXlsxFile(file.content).then((rows) => { + try { + const information = uniqBy( + rows + .map((row) => { + const [ + firstName, + lastName, + country, + passport_id, + email, + phone + ] = row as string[]; + return EMAIL_REGEX.test(email.toString().trim()) + ? { + email: email.toString().trim().toLowerCase(), + name: `${firstName ?? ""} ${lastName ?? ""}`.trim().toLowerCase(), + type: type, + passport_id: passport_id?.toString().trim() || undefined, + demographicInformation: { + country: country, + passport_id: passport_id?.toString().trim() || undefined, + phone, + } + } + : undefined; + }) + .filter((x) => !!x) as typeof infos, + (x) => x.email + ); + + if (information.length === 0) { + toast.error( + "Please upload an Excel file containing user information, one per line! All already registered e-mails have also been ignored!" + ); + return clear(); + } + + setInfos(information); + } catch { + toast.error( + "Please upload an Excel file containing user information, one per line! All already registered e-mails have also been ignored!" + ); + return clear(); + } + }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [filesContent]); + + const makeUsers = async () => { + const newUsers = infos.filter( + (x) => !users.map((u) => u.email).includes(x.email) + ); + const confirmed = confirm( + `You are about to add ${newUsers.length}, are you sure you want to continue?` + ) + if (!confirmed) + return; + + if (newUsers.length > 0) + { + setIsLoading(true); + Promise.all(newUsers.map((user) => { + return axios.post("/api/make_user", user) + })).finally(() => { + return clear(); + }) + } + setIsLoading(false); + setInfos([]); + }; + + + return ( + <> + setShowHelp(false)} + title="Excel File Format" + > +
+ Please upload an Excel file with the following format: + + + + + + + + + + + +
+ First Name + + Last Name + Country + Passport/National ID + E-mail + Phone Number +
+ + Notes: +
    +
  • - All incorrect e-mails will be ignored;
  • +
  • - All already registered e-mails will be ignored;
  • +
  • + - You may have a header row with the format above, however, it + is not necessary; +
  • +
  • + - All of the e-mails in the file will receive an e-mail to join + EnCoach with the role selected below. +
  • +
+
+
+
+
+
+ +
setShowHelp(true)} + > + +
+
+ + + {user && ( + + )} + +
+ + ); +} diff --git a/src/pages/api/make_user.ts b/src/pages/api/make_user.ts new file mode 100644 index 00000000..2abd5c90 --- /dev/null +++ b/src/pages/api/make_user.ts @@ -0,0 +1,110 @@ +import type { NextApiRequest, NextApiResponse } from "next"; +import { app } from "@/firebase"; +import { + getFirestore, + setDoc, + doc, + query, + collection, + where, + getDocs, + getDoc, + deleteDoc, +} from "firebase/firestore"; +import { withIronSessionApiRoute } from "iron-session/next"; +import { sessionOptions } from "@/lib/session"; +import {v4} from "uuid"; +import {Group} from "@/interfaces/user"; +import {createUserWithEmailAndPassword, getAuth} from "firebase/auth"; + +const DEFAULT_DESIRED_LEVELS = { + reading: 9, + listening: 9, + writing: 9, + speaking: 9, +}; + +const DEFAULT_LEVELS = { + reading: 0, + listening: 0, + writing: 0, + speaking: 0, +}; + +const auth = getAuth(app); +const db = getFirestore(app); + +export default withIronSessionApiRoute(handler, sessionOptions); + +async function handler(req: NextApiRequest, res: NextApiResponse) { + + if (req.method === "POST") return post(req, res); + + return res.status(404).json({ ok: false }); +} + +async function post(req: NextApiRequest, res: NextApiResponse) { + if (!req.session.user) { + return res + .status(401) + .json({ ok: false, reason: "You must be logged in to make user!" }); + } + + const { email, passport_id, type } = req.body as { + email: string; + passport_id: string; + type: string + }; + createUserWithEmailAndPassword(auth, email.toLowerCase(), passport_id) + .then(async (userCredentials) => { + const userId = userCredentials.user.uid; + + const user = { + ...req.body, + bio: "", + type: type, + focus: "academic", + status: "paymentDue", + + desiredLevels: DEFAULT_DESIRED_LEVELS, + levels: DEFAULT_LEVELS, + isFirstLogin: false, + }; + await setDoc(doc(db, "users", userId), user); + if (type === "corporate") { + const defaultTeachersGroup: Group = { + admin: userId, + id: v4(), + name: "Teachers", + participants: [], + disableEditing: true, + }; + + const defaultStudentsGroup: Group = { + admin: userId, + id: v4(), + name: "Students", + participants: [], + disableEditing: true, + }; + + const defaultCorporateGroup: Group = { + admin: userId, + id: v4(), + name: "Corporate", + participants: [], + disableEditing: true, + }; + + + await setDoc(doc(db, "groups", defaultTeachersGroup.id), defaultTeachersGroup); + await setDoc(doc(db, "groups", defaultStudentsGroup.id), defaultStudentsGroup); + await setDoc(doc(db, "groups", defaultCorporateGroup.id), defaultCorporateGroup); + } + res.status(200).json({ ok: true }); + }) + .catch((error) => { + console.log(error); + res.status(401).json({error}); + }); +} diff --git a/src/pages/settings.tsx b/src/pages/settings.tsx index 3886d13e..e3488cd9 100644 --- a/src/pages/settings.tsx +++ b/src/pages/settings.tsx @@ -13,6 +13,7 @@ import Lists from "./(admin)/Lists"; import BatchCodeGenerator from "./(admin)/BatchCodeGenerator"; import {shouldRedirectHome} from "@/utils/navigation.disabled"; import ExamGenerator from "./(admin)/ExamGenerator"; +import BatchCreateUser from "./(admin)/BatchCreateUser"; export const getServerSideProps = withIronSessionSsr(({req, res}) => { const user = req.session.user; @@ -59,10 +60,11 @@ export default function Admin() {
+ {user.type !== "teacher" && ( <> - - + + )}
diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index daa309a3..65d7d17c 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -42,4 +42,4 @@ export function getTypesOfUser(types: Type[]) { return userTypes.filter((userType) => { return !types.includes(userType); }) -} \ No newline at end of file +} From 4e30eda06f1a8a3bf16bf075c881919ddc49725c Mon Sep 17 00:00:00 2001 From: mzerone Date: Sat, 3 Aug 2024 01:37:41 +0200 Subject: [PATCH 02/14] make user verified by default. --- src/pages/api/make_user.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/api/make_user.ts b/src/pages/api/make_user.ts index 2abd5c90..5a30cf55 100644 --- a/src/pages/api/make_user.ts +++ b/src/pages/api/make_user.ts @@ -65,10 +65,10 @@ async function post(req: NextApiRequest, res: NextApiResponse) { type: type, focus: "academic", status: "paymentDue", - desiredLevels: DEFAULT_DESIRED_LEVELS, levels: DEFAULT_LEVELS, isFirstLogin: false, + isVerified: true }; await setDoc(doc(db, "users", userId), user); if (type === "corporate") { From 309dfba583e59f810e3fb05b6739d15f80251f0c Mon Sep 17 00:00:00 2001 From: Carlos Mesquita Date: Mon, 5 Aug 2024 10:41:11 +0100 Subject: [PATCH 03/14] Fixed the training content view --- package-lock.json | 643 ++++++++++++++---- package.json | 4 +- src/components/Dropdown.tsx | 4 +- src/components/InfiniteCarousel.tsx | 168 +++++ src/components/Sidebar.tsx | 3 + src/components/StatGridItem.tsx | 45 +- .../TrainingContent/TrainingScore.tsx | 2 +- src/pages/training/[id]/index.tsx | 209 +++--- src/pages/training/index.tsx | 2 +- src/styles/globals.css | 29 +- yarn.lock | 81 +-- 11 files changed, 906 insertions(+), 284 deletions(-) create mode 100644 src/components/InfiniteCarousel.tsx diff --git a/package-lock.json b/package-lock.json index 8bbc1cb6..b7c22f81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@beam-australia/react-env": "^3.1.1", "@dnd-kit/core": "^6.1.0", + "@firebase/util": "^1.9.7", "@headlessui/react": "^1.7.13", "@mdi/js": "^7.1.96", "@mdi/react": "^1.6.1", @@ -22,6 +23,7 @@ "@types/node": "18.13.0", "@types/react": "18.0.27", "@types/react-dom": "18.0.10", + "@use-gesture/react": "^10.3.1", "axios": "^1.3.5", "bcrypt": "^5.1.1", "chart.js": "^4.2.1", @@ -64,14 +66,12 @@ "react-phone-number-input": "^3.3.6", "react-player": "^2.12.0", "react-select": "^5.7.5", - "react-slick": "^0.30.2", "react-string-replace": "^1.1.0", "react-toastify": "^9.1.2", "react-tooltip": "^5.27.1", "react-xarrows": "^2.0.2", "read-excel-file": "^5.7.1", "short-unique-id": "5.0.2", - "slick-carousel": "^1.8.1", "stripe": "^13.10.0", "swr": "^2.1.3", "tailwind-scrollbar-hide": "^1.1.7", @@ -91,7 +91,6 @@ "@types/qrcode": "^1.5.5", "@types/react-csv": "^1.1.10", "@types/react-datepicker": "^4.15.1", - "@types/react-slick": "^0.23.13", "@types/uuid": "^9.0.1", "@types/wavesurfer.js": "^6.0.6", "@wixc3/react-board": "^2.2.0", @@ -772,11 +771,27 @@ "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/analytics-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/analytics-types": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.0.tgz", "integrity": "sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw==" }, + "node_modules/@firebase/analytics/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/app": { "version": "0.9.7", "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.7.tgz", @@ -819,6 +834,14 @@ "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/app-check-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/app-check-interop-types": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.2.0.tgz", @@ -829,6 +852,14 @@ "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.0.tgz", "integrity": "sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ==" }, + "node_modules/@firebase/app-check/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/app-compat": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.7.tgz", @@ -841,11 +872,27 @@ "tslib": "^2.1.0" } }, + "node_modules/@firebase/app-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/app-types": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==" }, + "node_modules/@firebase/app/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/auth": { "version": "0.22.0", "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.22.0.tgz", @@ -877,6 +924,14 @@ "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/auth-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/auth-interop-types": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz", @@ -891,6 +946,14 @@ "@firebase/util": "1.x" } }, + "node_modules/@firebase/auth/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/component": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz", @@ -900,6 +963,14 @@ "tslib": "^2.1.0" } }, + "node_modules/@firebase/component/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/database": { "version": "0.14.4", "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.14.4.tgz", @@ -926,6 +997,14 @@ "tslib": "^2.1.0" } }, + "node_modules/@firebase/database-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/database-types": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.10.4.tgz", @@ -935,6 +1014,22 @@ "@firebase/util": "1.9.3" } }, + "node_modules/@firebase/database-types/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/firestore": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-3.10.0.tgz", @@ -971,6 +1066,14 @@ "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/firestore-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/firestore-types": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.5.1.tgz", @@ -980,6 +1083,14 @@ "@firebase/util": "1.x" } }, + "node_modules/@firebase/firestore/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/functions": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.9.4.tgz", @@ -1012,11 +1123,27 @@ "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/functions-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/functions-types": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.0.tgz", "integrity": "sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw==" }, + "node_modules/@firebase/functions/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/installations": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.4.tgz", @@ -1046,6 +1173,14 @@ "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/installations-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/installations-types": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.0.tgz", @@ -1054,6 +1189,14 @@ "@firebase/app-types": "0.x" } }, + "node_modules/@firebase/installations/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/logger": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", @@ -1092,11 +1235,27 @@ "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/messaging-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/messaging-interop-types": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz", "integrity": "sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ==" }, + "node_modules/@firebase/messaging/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/performance": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.4.tgz", @@ -1128,11 +1287,27 @@ "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/performance-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/performance-types": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.0.tgz", "integrity": "sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA==" }, + "node_modules/@firebase/performance/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/remote-config": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.4.tgz", @@ -1164,11 +1339,27 @@ "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/remote-config-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/remote-config-types": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz", "integrity": "sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA==" }, + "node_modules/@firebase/remote-config/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/storage": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.11.2.tgz", @@ -1198,6 +1389,14 @@ "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/storage-compat/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/storage-types": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.0.tgz", @@ -1207,7 +1406,7 @@ "@firebase/util": "1.x" } }, - "node_modules/@firebase/util": { + "node_modules/@firebase/storage/node_modules/@firebase/util": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", @@ -1215,6 +1414,14 @@ "tslib": "^2.1.0" } }, + "node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/webchannel-wrapper": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.9.0.tgz", @@ -2642,15 +2849,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-slick": { - "version": "0.23.13", - "resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.13.tgz", - "integrity": "sha512-bNZfDhe/L8t5OQzIyhrRhBr/61pfBcWaYJoq6UDqFtv5LMwfg4NsVDD2J8N01JqdAdxLjOt66OZEp6PX+dGs/A==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -2794,6 +2992,22 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@use-gesture/core": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz", + "integrity": "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==" + }, + "node_modules/@use-gesture/react": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz", + "integrity": "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==", + "dependencies": { + "@use-gesture/core": "10.3.1" + }, + "peerDependencies": { + "react": ">= 16.8.0" + } + }, "node_modules/@wixc3/board-core": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@wixc3/board-core/-/board-core-2.2.0.tgz", @@ -4106,11 +4320,6 @@ "node": ">=10.13.0" } }, - "node_modules/enquire.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz", - "integrity": "sha512-/KujNpO+PT63F7Hlpu4h3pE3TokKRHN26JYmQpPyjkRD/N57R7bPDNojMXdi7uveAKjYB7yQnartCxZnFWr0Xw==" - }, "node_modules/ent": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.1.tgz", @@ -5115,6 +5324,14 @@ "@google-cloud/storage": "^6.9.5" } }, + "node_modules/firebase/node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -6629,14 +6846,6 @@ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, - "node_modules/json2mq": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", - "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", - "dependencies": { - "string-convert": "^0.2.0" - } - }, "node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", @@ -6859,11 +7068,6 @@ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" - }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -8492,22 +8696,6 @@ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, - "node_modules/react-slick": { - "version": "0.30.2", - "resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.30.2.tgz", - "integrity": "sha512-XvQJi7mRHuiU3b9irsqS9SGIgftIfdV5/tNcURTb5LdIokRA5kIIx3l4rlq2XYHfxcSntXapoRg/GxaVOM1yfg==", - "dependencies": { - "classnames": "^2.2.5", - "enquire.js": "^2.1.6", - "json2mq": "^0.2.0", - "lodash.debounce": "^4.0.8", - "resize-observer-polyfill": "^1.5.0" - }, - "peerDependencies": { - "react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-string-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/react-string-replace/-/react-string-replace-1.1.0.tgz", @@ -8677,11 +8865,6 @@ "lodash": "^4.17.21" } }, - "node_modules/resize-observer-polyfill": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", - "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" - }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -8929,14 +9112,6 @@ "node": ">=8" } }, - "node_modules/slick-carousel": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/slick-carousel/-/slick-carousel-1.8.1.tgz", - "integrity": "sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==", - "peerDependencies": { - "jquery": ">=1.8.0" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -8987,11 +9162,6 @@ "safe-buffer": "~5.2.0" } }, - "node_modules/string-convert": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", - "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -10531,6 +10701,16 @@ "@firebase/logger": "0.4.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/analytics-compat": { @@ -10543,6 +10723,16 @@ "@firebase/component": "0.6.4", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/analytics-types": { @@ -10560,6 +10750,16 @@ "@firebase/util": "1.9.3", "idb": "7.0.1", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/app-check": { @@ -10571,6 +10771,16 @@ "@firebase/logger": "0.4.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/app-check-compat": { @@ -10584,6 +10794,16 @@ "@firebase/logger": "0.4.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/app-check-interop-types": { @@ -10606,6 +10826,16 @@ "@firebase/logger": "0.4.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/app-types": { @@ -10623,6 +10853,16 @@ "@firebase/util": "1.9.3", "node-fetch": "2.6.7", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/auth-compat": { @@ -10636,6 +10876,16 @@ "@firebase/util": "1.9.3", "node-fetch": "2.6.7", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/auth-interop-types": { @@ -10655,6 +10905,16 @@ "requires": { "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/database": { @@ -10668,6 +10928,16 @@ "@firebase/util": "1.9.3", "faye-websocket": "0.11.4", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/database-compat": { @@ -10681,6 +10951,16 @@ "@firebase/logger": "0.4.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/database-types": { @@ -10690,6 +10970,16 @@ "requires": { "@firebase/app-types": "0.9.0", "@firebase/util": "1.9.3" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/firestore": { @@ -10705,6 +10995,16 @@ "@grpc/proto-loader": "^0.6.13", "node-fetch": "2.6.7", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/firestore-compat": { @@ -10717,6 +11017,16 @@ "@firebase/firestore-types": "2.5.1", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/firestore-types": { @@ -10736,6 +11046,16 @@ "@firebase/util": "1.9.3", "node-fetch": "2.6.7", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/functions-compat": { @@ -10748,6 +11068,16 @@ "@firebase/functions-types": "0.6.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/functions-types": { @@ -10764,6 +11094,16 @@ "@firebase/util": "1.9.3", "idb": "7.0.1", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/installations-compat": { @@ -10776,6 +11116,16 @@ "@firebase/installations-types": "0.5.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/installations-types": { @@ -10802,6 +11152,16 @@ "@firebase/util": "1.9.3", "idb": "7.0.1", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/messaging-compat": { @@ -10813,6 +11173,16 @@ "@firebase/messaging": "0.12.4", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/messaging-interop-types": { @@ -10830,6 +11200,16 @@ "@firebase/logger": "0.4.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/performance-compat": { @@ -10843,6 +11223,16 @@ "@firebase/performance-types": "0.2.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/performance-types": { @@ -10860,6 +11250,16 @@ "@firebase/logger": "0.4.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/remote-config-compat": { @@ -10873,6 +11273,16 @@ "@firebase/remote-config-types": "0.3.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/remote-config-types": { @@ -10889,6 +11299,16 @@ "@firebase/util": "1.9.3", "node-fetch": "2.6.7", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/storage-compat": { @@ -10901,6 +11321,16 @@ "@firebase/storage-types": "0.8.0", "@firebase/util": "1.9.3", "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "@firebase/storage-types": { @@ -10909,9 +11339,9 @@ "integrity": "sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==" }, "@firebase/util": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", - "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", "requires": { "tslib": "^2.1.0" } @@ -12063,15 +12493,6 @@ "@types/react": "*" } }, - "@types/react-slick": { - "version": "0.23.13", - "resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.13.tgz", - "integrity": "sha512-bNZfDhe/L8t5OQzIyhrRhBr/61pfBcWaYJoq6UDqFtv5LMwfg4NsVDD2J8N01JqdAdxLjOt66OZEp6PX+dGs/A==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, "@types/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -12167,6 +12588,19 @@ "eslint-visitor-keys": "^3.3.0" } }, + "@use-gesture/core": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz", + "integrity": "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==" + }, + "@use-gesture/react": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz", + "integrity": "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==", + "requires": { + "@use-gesture/core": "10.3.1" + } + }, "@wixc3/board-core": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@wixc3/board-core/-/board-core-2.2.0.tgz", @@ -13155,11 +13589,6 @@ "tapable": "^2.2.0" } }, - "enquire.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz", - "integrity": "sha512-/KujNpO+PT63F7Hlpu4h3pE3TokKRHN26JYmQpPyjkRD/N57R7bPDNojMXdi7uveAKjYB7yQnartCxZnFWr0Xw==" - }, "ent": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.1.tgz", @@ -13899,6 +14328,16 @@ "@firebase/storage": "0.11.2", "@firebase/storage-compat": "0.3.2", "@firebase/util": "1.9.3" + }, + "dependencies": { + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + } } }, "firebase-admin": { @@ -14988,14 +15427,6 @@ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, - "json2mq": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", - "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", - "requires": { - "string-convert": "^0.2.0" - } - }, "json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", @@ -15187,11 +15618,6 @@ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" - }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -16351,18 +16777,6 @@ } } }, - "react-slick": { - "version": "0.30.2", - "resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.30.2.tgz", - "integrity": "sha512-XvQJi7mRHuiU3b9irsqS9SGIgftIfdV5/tNcURTb5LdIokRA5kIIx3l4rlq2XYHfxcSntXapoRg/GxaVOM1yfg==", - "requires": { - "classnames": "^2.2.5", - "enquire.js": "^2.1.6", - "json2mq": "^0.2.0", - "lodash.debounce": "^4.0.8", - "resize-observer-polyfill": "^1.5.0" - } - }, "react-string-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/react-string-replace/-/react-string-replace-1.1.0.tgz", @@ -16486,11 +16900,6 @@ "lodash": "^4.17.21" } }, - "resize-observer-polyfill": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", - "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" - }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -16656,11 +17065,6 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, - "slick-carousel": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/slick-carousel/-/slick-carousel-1.8.1.tgz", - "integrity": "sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==" - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -16702,11 +17106,6 @@ "safe-buffer": "~5.2.0" } }, - "string-convert": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", - "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" - }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", diff --git a/package.json b/package.json index e47b874a..edebc0e7 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@types/node": "18.13.0", "@types/react": "18.0.27", "@types/react-dom": "18.0.10", + "@use-gesture/react": "^10.3.1", "axios": "^1.3.5", "bcrypt": "^5.1.1", "chart.js": "^4.2.1", @@ -67,14 +68,12 @@ "react-phone-number-input": "^3.3.6", "react-player": "^2.12.0", "react-select": "^5.7.5", - "react-slick": "^0.30.2", "react-string-replace": "^1.1.0", "react-toastify": "^9.1.2", "react-tooltip": "^5.27.1", "react-xarrows": "^2.0.2", "read-excel-file": "^5.7.1", "short-unique-id": "5.0.2", - "slick-carousel": "^1.8.1", "stripe": "^13.10.0", "swr": "^2.1.3", "tailwind-scrollbar-hide": "^1.1.7", @@ -94,7 +93,6 @@ "@types/qrcode": "^1.5.5", "@types/react-csv": "^1.1.10", "@types/react-datepicker": "^4.15.1", - "@types/react-slick": "^0.23.13", "@types/uuid": "^9.0.1", "@types/wavesurfer.js": "^6.0.6", "@wixc3/react-board": "^2.2.0", diff --git a/src/components/Dropdown.tsx b/src/components/Dropdown.tsx index 596706ce..61054e6b 100644 --- a/src/components/Dropdown.tsx +++ b/src/components/Dropdown.tsx @@ -2,7 +2,7 @@ import React, { useState, ReactNode, useRef, useEffect } from 'react'; import { animated, useSpring } from '@react-spring/web'; interface DropdownProps { - title: string; + title: ReactNode; open?: boolean; className?: string; contentWrapperClassName?: string; @@ -81,4 +81,4 @@ const Dropdown: React.FC = ({ ); }; -export default Dropdown; \ No newline at end of file +export default Dropdown; diff --git a/src/components/InfiniteCarousel.tsx b/src/components/InfiniteCarousel.tsx new file mode 100644 index 00000000..bdc4657f --- /dev/null +++ b/src/components/InfiniteCarousel.tsx @@ -0,0 +1,168 @@ +import React, { useRef, useEffect, useState, useCallback, ReactNode } from 'react'; +import { useSpring, animated } from '@react-spring/web'; +import { useDrag } from '@use-gesture/react'; +import clsx from 'clsx'; + +interface InfiniteCarouselProps { + children: React.ReactNode; + height: string; + speed?: number; + gap?: number; + overlay?: ReactNode; + overlayFunc?: (index: number) => void; + overlayClassName?: string; +} + +const InfiniteCarousel: React.FC = ({ + children, + height, + speed = 20000, + gap = 16, + overlay = undefined, + overlayFunc = undefined, + overlayClassName = "" +}) => { + const containerRef = useRef(null); + const [containerWidth, setContainerWidth] = useState(0); + const itemCount = React.Children.count(children); + const [isDragging, setIsDragging] = useState(false); + const [itemWidth, setItemWidth] = useState(0); + const [isInfinite, setIsInfinite] = useState(true); + const dragStartX = useRef(0); + + useEffect(() => { + const handleResize = () => { + if (containerRef.current) { + const containerWidth = containerRef.current.clientWidth; + setContainerWidth(containerWidth); + + const firstChild = containerRef.current.firstElementChild?.firstElementChild as HTMLElement; + if (firstChild) { + const childWidth = firstChild.offsetWidth; + setItemWidth(childWidth); + + const totalContentWidth = (childWidth + gap) * itemCount - gap; + setIsInfinite(totalContentWidth > containerWidth); + } + } + }; + + handleResize(); + window.addEventListener('resize', handleResize); + + return () => { + window.removeEventListener('resize', handleResize); + }; + }, [gap, itemCount]); + + const totalWidth = (itemWidth + gap) * itemCount; + + const [{ x }, api] = useSpring(() => ({ + from: { x: 0 }, + to: { x: -totalWidth }, + config: { duration: speed }, + loop: true, + })); + + const startAnimation = useCallback(() => { + if (isInfinite) { + api.start({ + from: { x: x.get() }, + to: { x: x.get() - totalWidth }, + config: { duration: speed }, + loop: true, + }); + } else { + api.stop(); + api.start({ x: 0, immediate: true }); + } + }, [api, x, totalWidth, speed, isInfinite]); + + useEffect(() => { + if (containerWidth > 0 && !isDragging) { + startAnimation(); + } + }, [containerWidth, isDragging, startAnimation]); + + const bind = useDrag(({ down, movement: [mx], first }) => { + if (!isInfinite) return; + if (first) { + setIsDragging(true); + api.stop(); + dragStartX.current = x.get(); + } + if (down) { + let newX = dragStartX.current + mx; + newX = ((newX % totalWidth) + totalWidth) % totalWidth; + if (newX > 0) newX -= totalWidth; + api.start({ x: newX, immediate: true }); + } else { + setIsDragging(false); + startAnimation(); + } + }, { + filterTaps: true, + from: () => [x.get(), 0], + }); + + return ( +
+ `translate3d(${x}px, 0, 0)`) + : 'none', + gap: `${gap}px`, + width: 'fit-content', + }} + > + {React.Children.map(children, (child, i) => ( +
+ {overlay !== undefined && overlayFunc !== undefined && ( +
overlayFunc(i)}> + {overlay} +
+ )} +
+ {child} +
+
+ ))} + {isInfinite && React.Children.map(children, (child, i) => ( +
+ {overlay !== undefined && overlayFunc !== undefined && ( +
overlayFunc(i)}> + {overlay} +
+ )} +
+ {child} +
+
+ ))} +
+
+ ); +}; + +export default InfiniteCarousel; \ No newline at end of file diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 15852575..47eded75 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -175,6 +175,9 @@ export default function Sidebar({path, navDisabled = false, focusMode = false, u {checkAccess(user, getTypesOfUser(["agent"]), "viewRecords") && (