@@ -60,7 +86,7 @@ function Pagination({
totalRecords,
currPage,
onNextPage,
- onPrevPage
+ onPrevPage,
}: {
totalRecords: number;
currPage: number;
@@ -68,16 +94,19 @@ function Pagination({
onPrevPage: any;
}) {
const firstRecordOnPage = getFirstRecordOnPage(currPage);
- const lastRecordOnPage = getLastRecordOnPage(
- firstRecordOnPage,
- totalRecords
- );
+ const lastRecordOnPage = getLastRecordOnPage(firstRecordOnPage, totalRecords);
if (!isValidPage(firstRecordOnPage, totalRecords)) {
return null;
}
- const arrows = getArrows(firstRecordOnPage, totalRecords, currPage, onNextPage, onPrevPage);
+ const arrows = getArrows(
+ firstRecordOnPage,
+ totalRecords,
+ currPage,
+ onNextPage,
+ onPrevPage
+ );
return (
@@ -86,7 +115,12 @@ function Pagination({
{arrows.map(({ symbol, disabled, onClick }, index) => (
-
+
))}
diff --git a/components/molecules/Pagination/PaginationHooks.ts b/components/molecules/Pagination/PaginationHooks.ts
new file mode 100644
index 00000000..efbdee09
--- /dev/null
+++ b/components/molecules/Pagination/PaginationHooks.ts
@@ -0,0 +1,65 @@
+import { CollectionPath } from "@lib/types/db";
+import { getTotalRecords } from "db/firebase/getSize";
+import { useEffect, useState } from "react";
+
+export function usePaginatedData
(
+ fetchPage: (
+ page: number,
+ paginationReferences: Map
+ ) => Promise<{ data: T[]; paginationInfo: any }>,
+ type: CollectionPath
+) {
+ const [paginationReferences, setPaginationReferences] = useState<
+ Map
+ >(new Map());
+ const [currPage, setCurrPage] = useState(1);
+ const [data, setData] = useState([]);
+ const [totalRecords, setTotalRecords] = useState(0);
+ const [refreshKey, setRefreshKey] = useState(0);
+
+ const fetchTotalRecords = async () => {
+ try {
+ const numRecords = await getTotalRecords(type);
+ if (numRecords) {
+ setTotalRecords(numRecords);
+ }
+ } catch (error) {
+ console.error("Error fetching records.");
+ }
+ };
+
+ const updatePaginationReferences = async (paginationInfo: any) => {
+ setPaginationReferences((prev) => {
+ const newRefs = new Map(prev);
+ newRefs.set(currPage, paginationInfo);
+ return newRefs;
+ });
+ };
+
+ const fetchPageData = async () => {
+ const newPageData = await fetchPage(currPage, paginationReferences);
+ setData(newPageData.data);
+ updatePaginationReferences(newPageData.paginationInfo);
+ };
+
+ useEffect(() => {
+ fetchPageData();
+ fetchTotalRecords();
+ }, [currPage]);
+
+ useEffect(() => {
+ setCurrPage(1);
+ fetchPageData();
+ fetchTotalRecords();
+ }, [refreshKey]);
+
+ return {
+ data,
+ totalRecords,
+ currPage,
+ setCurrPage,
+ onNextPage: () => setCurrPage((prev) => prev + 1),
+ onPrevPage: () => setCurrPage((prev) => prev - 1),
+ refresh: () => setRefreshKey((prev) => prev + 1),
+ };
+}
diff --git a/web/components/resources/FAQ.tsx b/components/resources/FAQ.tsx
similarity index 100%
rename from web/components/resources/FAQ.tsx
rename to components/resources/FAQ.tsx
diff --git a/web/components/resources/Links.tsx b/components/resources/Links.tsx
similarity index 100%
rename from web/components/resources/Links.tsx
rename to components/resources/Links.tsx
diff --git a/web/components/resources/Research.tsx b/components/resources/Research.tsx
similarity index 100%
rename from web/components/resources/Research.tsx
rename to components/resources/Research.tsx
diff --git a/web/components/settings/LiabilityWaver.tsx b/components/settings/LiabilityWaver.tsx
similarity index 100%
rename from web/components/settings/LiabilityWaver.tsx
rename to components/settings/LiabilityWaver.tsx
diff --git a/web/components/tables/BabiesTable.tsx b/components/tables/BabiesTable.tsx
similarity index 100%
rename from web/components/tables/BabiesTable.tsx
rename to components/tables/BabiesTable.tsx
diff --git a/web/components/tables/CaretakerTable.tsx b/components/tables/CaretakerTable.tsx
similarity index 100%
rename from web/components/tables/CaretakerTable.tsx
rename to components/tables/CaretakerTable.tsx
diff --git a/components/tables/PaginatedTable.tsx b/components/tables/PaginatedTable.tsx
new file mode 100644
index 00000000..21ed76b6
--- /dev/null
+++ b/components/tables/PaginatedTable.tsx
@@ -0,0 +1,35 @@
+import React from "react";
+import Pagination from "@components/molecules/Pagination/Pagination";
+import CaretakerTable from "@components/tables/CaretakerTable";
+import BabiesTable from "@components/tables/BabiesTable";
+import { BABIES_TAB, CAREGIVERS_TAB } from "@lib/utils/consts";
+
+export default function PaginatedTable({
+ type,
+ tableProps,
+ paginatedProps,
+ onNextPage,
+ onPrevPage,
+}: any) {
+ return (
+
+
+ {type == BABIES_TAB ? (
+
+ ) : type == CAREGIVERS_TAB ? (
+
+ ) : (
+ <>>
+ )}
+
+
+
+ );
+}
diff --git a/web/db/actions/Login.ts b/db/actions/Login.ts
similarity index 100%
rename from web/db/actions/Login.ts
rename to db/actions/Login.ts
diff --git a/web/db/actions/SignUp.ts b/db/actions/SignUp.ts
similarity index 100%
rename from web/db/actions/SignUp.ts
rename to db/actions/SignUp.ts
diff --git a/web/db/actions/admin/Baby.ts b/db/actions/admin/Baby.ts
similarity index 77%
rename from web/db/actions/admin/Baby.ts
rename to db/actions/admin/Baby.ts
index 3135499c..20366834 100644
--- a/web/db/actions/admin/Baby.ts
+++ b/db/actions/admin/Baby.ts
@@ -14,19 +14,37 @@ import {
import { Baby } from "@lib/types/baby";
import { db } from "db/firebase";
-import { PaginationInfoType, PaginationReferencesType } from "@lib/types/common";
+import {
+ PaginationInfoType,
+ PaginationReferencesType,
+} from "@lib/types/common";
import { BABIES_COLLECTION_PATH, CAREGIVERS_COLLECTION_PATH } from "db/consts";
import { getQueryConstraintsFromPagination } from "@lib/utils/pagination";
import getBabiesFromBabyDocs from "@lib/utils/baby";
-import { FailedToAddError, FailedToDeleteError, FailedToEditError, FailedToFetchError } from "@lib/exceptions/DatabaseExceptions";
-import { addBabyToCaretaker, removeBabyFromCaretaker } from "../shared/babyCaregiver";
+import {
+ FailedToAddError,
+ FailedToDeleteError,
+ FailedToEditError,
+ FailedToFetchError,
+} from "@lib/exceptions/DatabaseExceptions";
+import {
+ addBabyToCaretaker,
+ removeBabyFromCaretaker,
+} from "../shared/babyCaregiver";
const path = BABIES_COLLECTION_PATH;
const caregiverPath = CAREGIVERS_COLLECTION_PATH;
const docType = "baby";
-export async function getBabyPage(pageNumber: number, paginationReferences: PaginationReferencesType) {
- const constraints = getQueryConstraintsFromPagination(path, pageNumber, paginationReferences);
+export async function getBabyPage(
+ pageNumber: number,
+ paginationReferences: PaginationReferencesType
+) {
+ const constraints = getQueryConstraintsFromPagination(
+ path,
+ pageNumber,
+ paginationReferences
+ );
const itemsRef = query(collection(db, path), ...constraints);
try {
@@ -43,7 +61,9 @@ export async function getBabyPage(pageNumber: number, paginationReferences: Pagi
}
export const addNewChild = async (child: Baby) => {
- let caretakerRef = child.caretakerID ? doc(db, caregiverPath, child.caretakerID) : null;
+ const caretakerRef = child.caretakerID
+ ? doc(db, caregiverPath, child.caretakerID)
+ : null;
let newBaby = null;
try {
newBaby = await addDoc(collection(db, path), {
@@ -61,10 +81,7 @@ export const addNewChild = async (child: Baby) => {
return newBaby;
};
-export async function updateBaby(
- uid: string,
- baby: any
-) {
+export async function updateBaby(uid: string, baby: any) {
const babyDoc = doc(db, path, uid);
try {
await updateDoc(babyDoc, baby);
@@ -99,7 +116,6 @@ export const deleteBaby = async (baby: any) => {
}
removeBabyFromCaretaker(caretakerID, babyRef);
-
};
// If before this code is deployed, new babies are added, just call and run this function
@@ -107,20 +123,22 @@ export const deleteBaby = async (baby: any) => {
// This sets it to 0 if there exist caregivers without baby counts
// Can delete this function once this PR is merged into main
async function resetBabyCountForCaregiversWithoutCount() {
- const caregiversCollection = collection(db, 'caregivers');
+ const caregiversCollection = collection(db, "caregivers");
const batch = writeBatch(db);
try {
const snapshot = await getDocs(caregiversCollection);
- snapshot.forEach(doc => {
+ snapshot.forEach((doc) => {
const caregiverRef = doc.ref;
if (!doc.data().babyCount) {
batch.set(caregiverRef, { babyCount: 0, babies: [] }, { merge: true });
}
});
await batch.commit();
- console.log("Caregiver documents updated to have babyCount set to 0 where it was missing.");
+ console.log(
+ "Caregiver documents updated to have babyCount set to 0 where it was missing."
+ );
} catch (error) {
console.error("Error updating caregiver documents: ", error);
}
-}
\ No newline at end of file
+}
diff --git a/web/db/actions/admin/Caregiver.ts b/db/actions/admin/Caregiver.ts
similarity index 78%
rename from web/db/actions/admin/Caregiver.ts
rename to db/actions/admin/Caregiver.ts
index 084fe381..d91d1495 100644
--- a/web/db/actions/admin/Caregiver.ts
+++ b/db/actions/admin/Caregiver.ts
@@ -11,12 +11,21 @@ import {
import { db } from "db/firebase";
-import { PaginationInfoType, PaginationReferencesType } from "@lib/types/common";
+import {
+ PaginationInfoType,
+ PaginationReferencesType,
+} from "@lib/types/common";
import { getQueryConstraintsFromPagination } from "@lib/utils/pagination";
import { CAREGIVERS_COLLECTION_PATH } from "db/consts";
import getCaregiversFromCaregiverDocs from "@lib/utils/caregiver";
import { Caregiver } from "@lib/types/users";
-import { FailedToAddError, FailedToDeleteError, FailedToEditError, FailedToFetchError, GenericDatabaseErrorException } from "@lib/exceptions/DatabaseExceptions";
+import {
+ FailedToAddError,
+ FailedToDeleteError,
+ FailedToEditError,
+ FailedToFetchError,
+ GenericDatabaseErrorException,
+} from "@lib/exceptions/DatabaseExceptions";
import { removeCaretakerFromBabies } from "../shared/babyCaregiver";
const docType = "caregiver";
@@ -48,8 +57,15 @@ export const addNewCaregiver = async (caregiver: Caregiver) => {
}
};
-export async function getCaregiverPage(pageNumber: number, paginationReferences: PaginationReferencesType) {
- const constraints = getQueryConstraintsFromPagination(path, pageNumber, paginationReferences);
+export async function getCaregiverPage(
+ pageNumber: number,
+ paginationReferences: PaginationReferencesType
+) {
+ const constraints = getQueryConstraintsFromPagination(
+ path,
+ pageNumber,
+ paginationReferences
+ );
try {
const itemsRef = query(collection(db, path), ...constraints);
const caregiverDocs = await getDocs(itemsRef);
@@ -64,10 +80,7 @@ export async function getCaregiverPage(pageNumber: number, paginationReferences:
}
}
-export async function updateCaregiver(
- uid: string,
- caregiver: any
-) {
+export async function updateCaregiver(uid: string, caregiver: any) {
const caregiverDoc = doc(db, path, uid);
try {
await updateDoc(caregiverDoc, caregiver as Partial);
@@ -77,7 +90,7 @@ export async function updateCaregiver(
}
export const deleteCaretaker = async (caretaker: Caregiver) => {
- const caretakerID = caretaker.id;
+ const caretakerID = caretaker.id;
try {
await removeCaretakerFromBabies(caretaker.babies);
@@ -86,4 +99,3 @@ export const deleteCaretaker = async (caretaker: Caregiver) => {
throw new FailedToDeleteError(docType);
}
};
-
diff --git a/web/db/actions/caregiver/Photo.ts b/db/actions/caregiver/Photo.ts
similarity index 100%
rename from web/db/actions/caregiver/Photo.ts
rename to db/actions/caregiver/Photo.ts
diff --git a/web/db/actions/shared/Caregiver.ts b/db/actions/shared/Caregiver.ts
similarity index 100%
rename from web/db/actions/shared/Caregiver.ts
rename to db/actions/shared/Caregiver.ts
diff --git a/web/db/actions/shared/babyCaregiver.ts b/db/actions/shared/babyCaregiver.ts
similarity index 61%
rename from web/db/actions/shared/babyCaregiver.ts
rename to db/actions/shared/babyCaregiver.ts
index dc6c3231..cb6a3e2a 100644
--- a/web/db/actions/shared/babyCaregiver.ts
+++ b/db/actions/shared/babyCaregiver.ts
@@ -1,17 +1,26 @@
-import { arrayRemove, arrayUnion, DocumentData, DocumentReference, increment } from "firebase/firestore";
+import {
+ arrayRemove,
+ arrayUnion,
+ DocumentData,
+ DocumentReference,
+ increment,
+} from "firebase/firestore";
import { updateCaregiver } from "../admin/Caregiver";
import { updateBaby } from "../admin/Baby";
-export async function addBabyToCaretaker (caretakerID: string, babyRef: any) {
+export async function addBabyToCaretaker(caretakerID: string, babyRef: any) {
if (!caretakerID) return;
const updates = {
babies: arrayUnion(babyRef),
babyCount: increment(1),
};
updateCaregiver(caretakerID, updates);
-};
+}
-export async function removeBabyFromCaretaker(caretakerID: string, babyRef: any) {
+export async function removeBabyFromCaretaker(
+ caretakerID: string,
+ babyRef: any
+) {
if (!caretakerID) return;
const updates = {
@@ -22,7 +31,9 @@ export async function removeBabyFromCaretaker(caretakerID: string, babyRef: any)
await updateCaregiver(caretakerID, updates);
}
-export async function removeCaretakerFromBabies(babiesToRemove: DocumentReference[]) {
+export async function removeCaretakerFromBabies(
+ babiesToRemove: DocumentReference[]
+) {
const updatePromises = babiesToRemove.map(async (babyRef) => {
return updateBaby(babyRef.id, {
caretaker: null,
@@ -31,4 +42,4 @@ export async function removeCaretakerFromBabies(babiesToRemove: DocumentReferenc
});
await Promise.all(updatePromises);
-}
\ No newline at end of file
+}
diff --git a/db/consts.ts b/db/consts.ts
new file mode 100644
index 00000000..cf418198
--- /dev/null
+++ b/db/consts.ts
@@ -0,0 +1,11 @@
+import { CollectionPath } from "@lib/types/db";
+
+export const BABIES_COLLECTION_PATH = "babies";
+export const CAREGIVERS_COLLECTION_PATH = "caregivers";
+
+export const PAGINATION_PAGE_SIZE = 5;
+
+export const COLLECTION_ORDER_KEYS: Record = {
+ [BABIES_COLLECTION_PATH]: "firstName",
+ [CAREGIVERS_COLLECTION_PATH]: "babyCount",
+};
diff --git a/web/db/firebase/admin/config.ts b/db/firebase/admin/config.ts
similarity index 100%
rename from web/db/firebase/admin/config.ts
rename to db/firebase/admin/config.ts
diff --git a/web/db/firebase/admin/index.ts b/db/firebase/admin/index.ts
similarity index 100%
rename from web/db/firebase/admin/index.ts
rename to db/firebase/admin/index.ts
diff --git a/web/db/firebase/getDoc.ts b/db/firebase/getDoc.ts
similarity index 100%
rename from web/db/firebase/getDoc.ts
rename to db/firebase/getDoc.ts
diff --git a/web/db/firebase/getSize.ts b/db/firebase/getSize.ts
similarity index 77%
rename from web/db/firebase/getSize.ts
rename to db/firebase/getSize.ts
index d92c393d..28143c8e 100644
--- a/web/db/firebase/getSize.ts
+++ b/db/firebase/getSize.ts
@@ -1,10 +1,12 @@
import { collection } from "firebase/firestore";
import { db } from ".";
import { getCountFromServer } from "@firebase/firestore";
-import { GenericDatabaseErrorException, PathNotFoundError } from "@lib/exceptions/DatabaseExceptions";
+import {
+ GenericDatabaseErrorException,
+ PathNotFoundError,
+} from "@lib/exceptions/DatabaseExceptions";
import { CollectionPath } from "@lib/types/db";
-
export async function getTotalRecords(path: CollectionPath) {
try {
const coll = collection(db, path);
@@ -12,8 +14,8 @@ export async function getTotalRecords(path: CollectionPath) {
return snapshot.data().count;
} catch (e) {
if (e instanceof Error && e.message.includes("path")) {
- throw new PathNotFoundError(path);
+ throw new PathNotFoundError(path);
}
throw new GenericDatabaseErrorException();
}
-}
\ No newline at end of file
+}
diff --git a/web/db/firebase/index.ts b/db/firebase/index.ts
similarity index 100%
rename from web/db/firebase/index.ts
rename to db/firebase/index.ts
diff --git a/web/deploy.sh b/deploy.sh
old mode 100755
new mode 100644
similarity index 100%
rename from web/deploy.sh
rename to deploy.sh
diff --git a/web/lib/SideBarItems.ts b/lib/SideBarItems.ts
similarity index 100%
rename from web/lib/SideBarItems.ts
rename to lib/SideBarItems.ts
diff --git a/web/lib/contexts/userContext.tsx b/lib/contexts/userContext.tsx
similarity index 100%
rename from web/lib/contexts/userContext.tsx
rename to lib/contexts/userContext.tsx
diff --git a/web/lib/exceptions/DatabaseExceptions.ts b/lib/exceptions/DatabaseExceptions.ts
similarity index 100%
rename from web/lib/exceptions/DatabaseExceptions.ts
rename to lib/exceptions/DatabaseExceptions.ts
diff --git a/web/lib/hooks/useMap.ts b/lib/hooks/useMap.ts
similarity index 100%
rename from web/lib/hooks/useMap.ts
rename to lib/hooks/useMap.ts
diff --git a/web/lib/types/baby.ts b/lib/types/baby.ts
similarity index 100%
rename from web/lib/types/baby.ts
rename to lib/types/baby.ts
diff --git a/web/lib/types/common.ts b/lib/types/common.ts
similarity index 64%
rename from web/lib/types/common.ts
rename to lib/types/common.ts
index a8320399..de5d9aaf 100644
--- a/web/lib/types/common.ts
+++ b/lib/types/common.ts
@@ -1,4 +1,8 @@
-import { DocumentData, QueryDocumentSnapshot, Timestamp } from "firebase/firestore";
+import {
+ DocumentData,
+ QueryDocumentSnapshot,
+ Timestamp,
+} from "firebase/firestore";
import { BABIES_TAB, CAREGIVERS_TAB } from "@lib/utils/consts";
export interface User {
@@ -22,10 +26,13 @@ export type AuthFormValues = {
};
export interface PaginationInfoType {
- pageNumber: number,
- startAfter: QueryDocumentSnapshot
+ pageNumber: number;
+ startAfter: QueryDocumentSnapshot;
}
-export type PaginationReferencesType = Map>;
+export type PaginationReferencesType = Map<
+ number,
+ QueryDocumentSnapshot
+>;
-export type TabType = typeof BABIES_TAB | typeof CAREGIVERS_TAB;
\ No newline at end of file
+export type TabType = typeof BABIES_TAB | typeof CAREGIVERS_TAB;
diff --git a/lib/types/db.ts b/lib/types/db.ts
new file mode 100644
index 00000000..9ad09790
--- /dev/null
+++ b/lib/types/db.ts
@@ -0,0 +1,8 @@
+import { BABIES_COLLECTION_PATH, CAREGIVERS_COLLECTION_PATH } from "db/consts";
+import { DocumentData, QuerySnapshot } from "firebase/firestore";
+
+export type CollectionPath =
+ | typeof BABIES_COLLECTION_PATH
+ | typeof CAREGIVERS_COLLECTION_PATH;
+
+export type FBDocs = QuerySnapshot;
diff --git a/web/lib/types/items.ts b/lib/types/items.ts
similarity index 100%
rename from web/lib/types/items.ts
rename to lib/types/items.ts
diff --git a/web/lib/types/users.ts b/lib/types/users.ts
similarity index 100%
rename from web/lib/types/users.ts
rename to lib/types/users.ts
diff --git a/lib/utils/baby.ts b/lib/utils/baby.ts
new file mode 100644
index 00000000..d9e4d272
--- /dev/null
+++ b/lib/utils/baby.ts
@@ -0,0 +1,29 @@
+import { encrypt } from "./encryption";
+import { Baby } from "@lib/types/baby";
+import { FBDocs } from "@lib/types/db";
+
+export default async function getBabiesFromBabyDocs(babyDocs: FBDocs) {
+ const babies = await Promise.all(
+ babyDocs?.docs.map((babyDoc) => {
+ const data = babyDoc.data() as Baby;
+
+ const { iv, content } = encrypt(babyDoc.id);
+
+ return {
+ id: babyDoc.id,
+ firstName: data.firstName,
+ lastName: data.lastName,
+ name: data?.firstName ?? "" + " " + data?.lastName ?? "",
+ motherName: data?.motherName || null,
+ birthday: data?.dob,
+ sex: data?.sex || null,
+ babyBook: `/admin/book/${content}?iv=${iv}`,
+ hospitalName: data?.hospitalName,
+ caretakerID: data?.caretakerID,
+ caretakerName: data?.caretakerName,
+ };
+ })
+ );
+
+ return babies;
+}
diff --git a/lib/utils/caregiver.ts b/lib/utils/caregiver.ts
new file mode 100644
index 00000000..0ef76312
--- /dev/null
+++ b/lib/utils/caregiver.ts
@@ -0,0 +1,35 @@
+import { getDoc } from "firebase/firestore";
+import { formatPhoneNumber } from "./contactInfo";
+import { FBDocs } from "@lib/types/db";
+
+export default async function getCaregiversFromCaregiverDocs(
+ caregiverDocs: FBDocs
+) {
+ // TODO update for multiple children
+ const caregivers = await Promise.all(
+ caregiverDocs?.docs.map(async (doc) => {
+ const data = doc.data();
+ const children = data.babies;
+ return {
+ id: doc.id,
+ name: data.firstName + " " + data.lastName,
+ email: data.email || "N/A",
+ phone:
+ (data.phoneNumber && formatPhoneNumber(data.phoneNumber)) || "N/A",
+ registeredDate: data.createdAt
+ ? data.createdAt.toDate().toLocaleDateString()
+ : null,
+ assigned: children && children.length > 0 ? true : false,
+ address: `${data.address}, ${
+ data.apartment ? `${data.apartment}, ` : ""
+ }${data.city}, ${data.state}`,
+ prefferedCommunication: data.prefferedCommunication || "N/A",
+ babies: children,
+ houseHoldInfo: `${data.numAdults} adults, ${data.numChildren} children`,
+ // liabilityWaiver: data.signedWaivers?.at(-1).id || null,
+ liabilityWaiver: "",
+ };
+ })
+ );
+ return caregivers;
+}
diff --git a/web/lib/utils/consts.ts b/lib/utils/consts.ts
similarity index 100%
rename from web/lib/utils/consts.ts
rename to lib/utils/consts.ts
diff --git a/web/lib/utils/contactInfo.ts b/lib/utils/contactInfo.ts
similarity index 100%
rename from web/lib/utils/contactInfo.ts
rename to lib/utils/contactInfo.ts
diff --git a/web/lib/utils/date.ts b/lib/utils/date.ts
similarity index 100%
rename from web/lib/utils/date.ts
rename to lib/utils/date.ts
diff --git a/web/lib/utils/encryption.ts b/lib/utils/encryption.ts
similarity index 100%
rename from web/lib/utils/encryption.ts
rename to lib/utils/encryption.ts
diff --git a/lib/utils/keyboardScroll.ts b/lib/utils/keyboardScroll.ts
new file mode 100644
index 00000000..d0f05489
--- /dev/null
+++ b/lib/utils/keyboardScroll.ts
@@ -0,0 +1,9 @@
+import { FocusEvent } from "react";
+
+export default function keyboardScroll(e: FocusEvent) {
+ e.target.scrollIntoView({
+ behavior: "smooth",
+ block: "center",
+ inline: "center",
+ });
+}
diff --git a/lib/utils/pagination.ts b/lib/utils/pagination.ts
new file mode 100644
index 00000000..2f3f9b2d
--- /dev/null
+++ b/lib/utils/pagination.ts
@@ -0,0 +1,28 @@
+import { CollectionPath } from "@lib/types/db";
+import { COLLECTION_ORDER_KEYS, PAGINATION_PAGE_SIZE } from "db/consts";
+import {
+ limit,
+ orderBy,
+ QueryConstraint,
+ startAfter,
+} from "firebase/firestore";
+
+export function getQueryConstraintsFromPagination(
+ path: CollectionPath,
+ pageNumber: number,
+ paginationReferences: Map
+): QueryConstraint[] {
+ const constraints: QueryConstraint[] = [
+ orderBy(COLLECTION_ORDER_KEYS[path]),
+ limit(PAGINATION_PAGE_SIZE),
+ ];
+
+ if (pageNumber != 1 && paginationReferences) {
+ const prevPage = paginationReferences.get(pageNumber - 1);
+ if (prevPage?.startAfter) {
+ constraints.push(startAfter(prevPage.startAfter));
+ }
+ }
+
+ return constraints;
+}
diff --git a/web/next-env.d.ts b/next-env.d.ts
similarity index 100%
rename from web/next-env.d.ts
rename to next-env.d.ts
diff --git a/web/next.config.js b/next.config.js
similarity index 100%
rename from web/next.config.js
rename to next.config.js
diff --git a/web/package-lock.json b/package-lock.json
similarity index 90%
rename from web/package-lock.json
rename to package-lock.json
index a04f5e85..c28e8276 100644
--- a/web/package-lock.json
+++ b/package-lock.json
@@ -13,7 +13,9 @@
"firebase": "^9.23.0",
"firebase-admin": "^11.2.0",
"firebase-functions": "^4.0.2",
+ "husky": "^9.1.6",
"jszip": "^3.10.1",
+ "lint-staged": "^15.2.10",
"markdown-it": "^12.3.2",
"next": "^12.3.4",
"nextjs-progressbar": "^0.0.14",
@@ -1376,6 +1378,186 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/@next/swc-android-arm-eabi": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.4.tgz",
+ "integrity": "sha512-cM42Cw6V4Bz/2+j/xIzO8nK/Q3Ly+VSlZJTa1vHzsocJRYz8KT6MrreXaci2++SIZCF1rVRCDgAg5PpqRibdIA==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-android-arm64": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.4.tgz",
+ "integrity": "sha512-5jf0dTBjL+rabWjGj3eghpLUxCukRhBcEJgwLedewEA/LJk2HyqCvGIwj5rH+iwmq1llCWbOky2dO3pVljrapg==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.4.tgz",
+ "integrity": "sha512-DqsSTd3FRjQUR6ao0E1e2OlOcrF5br+uegcEGPVonKYJpcr0MJrtYmPxd4v5T6UCJZ+XzydF7eQo5wdGvSZAyA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.4.tgz",
+ "integrity": "sha512-PPF7tbWD4k0dJ2EcUSnOsaOJ5rhT3rlEt/3LhZUGiYNL8KvoqczFrETlUx0cUYaXe11dRA3F80Hpt727QIwByQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-freebsd-x64": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.4.tgz",
+ "integrity": "sha512-KM9JXRXi/U2PUM928z7l4tnfQ9u8bTco/jb939pdFUHqc28V43Ohd31MmZD1QzEK4aFlMRaIBQOWQZh4D/E5lQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm-gnueabihf": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.4.tgz",
+ "integrity": "sha512-3zqD3pO+z5CZyxtKDTnOJ2XgFFRUBciOox6EWkoZvJfc9zcidNAQxuwonUeNts6Xbm8Wtm5YGIRC0x+12YH7kw==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.4.tgz",
+ "integrity": "sha512-kiX0vgJGMZVv+oo1QuObaYulXNvdH/IINmvdZnVzMO/jic/B8EEIGlZ8Bgvw8LCjH3zNVPO3mGrdMvnEEPEhKA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.4.tgz",
+ "integrity": "sha512-EETZPa1juczrKLWk5okoW2hv7D7WvonU+Cf2CgsSoxgsYbUCZ1voOpL4JZTOb6IbKMDo6ja+SbY0vzXZBUMvkQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.4.tgz",
+ "integrity": "sha512-4csPbRbfZbuWOk3ATyWcvVFdD9/Rsdq5YHKvRuEni68OCLkfy4f+4I9OBpyK1SKJ00Cih16NJbHE+k+ljPPpag==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.4.tgz",
+ "integrity": "sha512-YeBmI+63Ro75SUiL/QXEVXQ19T++58aI/IINOyhpsRL1LKdyfK/35iilraZEFz9bLQrwy1LYAR5lK200A9Gjbg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.4.tgz",
+ "integrity": "sha512-Sd0qFUJv8Tj0PukAYbCCDbmXcMkbIuhnTeHm9m4ZGjCf6kt7E/RMs55Pd3R5ePjOkN7dJEuxYBehawTR/aPDSQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "12.3.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.4.tgz",
+ "integrity": "sha512-rt/vv/vg/ZGGkrkKcuJ0LyliRdbskQU+91bje+PgoYmxTZf/tYs6IfbmgudBJk6gH3QnjHWbkphDdRQrseRefQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
"node_modules/@next/swc-win32-x64-msvc": {
"version": "12.3.4",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.4.tgz",
@@ -2083,6 +2265,21 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
+ "node_modules/ansi-escapes": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz",
+ "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==",
+ "license": "MIT",
+ "dependencies": {
+ "environment": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/ansi-regex": {
"version": "5.0.1",
"license": "MIT",
@@ -2647,6 +2844,87 @@
"version": "2.3.2",
"license": "MIT"
},
+ "node_modules/cli-cursor": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
+ "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-truncate": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz",
+ "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==",
+ "license": "MIT",
+ "dependencies": {
+ "slice-ansi": "^5.0.0",
+ "string-width": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-truncate/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/cli-truncate/node_modules/emoji-regex": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
+ "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
+ "license": "MIT"
+ },
+ "node_modules/cli-truncate/node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-truncate/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
"node_modules/cliui": {
"version": "7.0.4",
"license": "ISC",
@@ -2679,6 +2957,12 @@
"version": "1.1.4",
"license": "MIT"
},
+ "node_modules/colorette": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+ "license": "MIT"
+ },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -2690,6 +2974,15 @@
"node": ">= 0.8"
}
},
+ "node_modules/commander": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/compressible": {
"version": "2.0.18",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
@@ -2792,7 +3085,6 @@
},
"node_modules/cross-spawn": {
"version": "7.0.3",
- "dev": true,
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
@@ -2803,12 +3095,6 @@
"node": ">= 8"
}
},
- "node_modules/crypto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
- "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==",
- "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in."
- },
"node_modules/css-select": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
@@ -2869,10 +3155,12 @@
}
},
"node_modules/debug": {
- "version": "4.3.4",
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
- "ms": "2.1.2"
+ "ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
@@ -2883,10 +3171,6 @@
}
}
},
- "node_modules/debug/node_modules/ms": {
- "version": "2.1.2",
- "license": "MIT"
- },
"node_modules/deep-is": {
"version": "0.1.4",
"devOptional": true,
@@ -3139,6 +3423,18 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
+ "node_modules/environment": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz",
+ "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -4043,6 +4339,41 @@
"version": "4.0.7",
"license": "MIT"
},
+ "node_modules/execa": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
+ "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^8.0.1",
+ "human-signals": "^5.0.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^4.1.0",
+ "strip-final-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=16.17"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/execa/node_modules/is-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/express": {
"version": "4.21.0",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz",
@@ -4534,6 +4865,18 @@
"node": "6.* || 8.* || >= 10.*"
}
},
+ "node_modules/get-east-asian-width": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz",
+ "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/get-intrinsic": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
@@ -4553,6 +4896,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/get-stream": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
+ "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/get-symbol-description": {
"version": "1.0.0",
"dev": true,
@@ -5210,14 +5565,38 @@
"node": ">= 6"
}
},
- "node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
+ "node_modules/human-signals": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
+ "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=16.17.0"
+ }
+ },
+ "node_modules/husky": {
+ "version": "9.1.6",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz",
+ "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==",
+ "license": "MIT",
+ "bin": {
+ "husky": "bin.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/typicode"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
"engines": {
"node": ">=0.10.0"
}
@@ -5538,7 +5917,6 @@
},
"node_modules/isexe": {
"version": "2.0.0",
- "dev": true,
"license": "ISC"
},
"node_modules/isstream": {
@@ -5968,6 +6346,171 @@
"uc.micro": "^1.0.1"
}
},
+ "node_modules/lint-staged": {
+ "version": "15.2.10",
+ "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz",
+ "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "~5.3.0",
+ "commander": "~12.1.0",
+ "debug": "~4.3.6",
+ "execa": "~8.0.1",
+ "lilconfig": "~3.1.2",
+ "listr2": "~8.2.4",
+ "micromatch": "~4.0.8",
+ "pidtree": "~0.6.0",
+ "string-argv": "~0.3.2",
+ "yaml": "~2.5.0"
+ },
+ "bin": {
+ "lint-staged": "bin/lint-staged.js"
+ },
+ "engines": {
+ "node": ">=18.12.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/lint-staged"
+ }
+ },
+ "node_modules/lint-staged/node_modules/chalk": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/lint-staged/node_modules/lilconfig": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
+ "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
+ "node_modules/lint-staged/node_modules/yaml": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz",
+ "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==",
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/listr2": {
+ "version": "8.2.5",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz",
+ "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cli-truncate": "^4.0.0",
+ "colorette": "^2.0.20",
+ "eventemitter3": "^5.0.1",
+ "log-update": "^6.1.0",
+ "rfdc": "^1.4.1",
+ "wrap-ansi": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/listr2/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/listr2/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/listr2/node_modules/emoji-regex": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
+ "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
+ "license": "MIT"
+ },
+ "node_modules/listr2/node_modules/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+ "license": "MIT"
+ },
+ "node_modules/listr2/node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/listr2/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/listr2/node_modules/wrap-ansi": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
+ "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -6058,6 +6601,135 @@
"resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
"integrity": "sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ=="
},
+ "node_modules/log-update": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz",
+ "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-escapes": "^7.0.0",
+ "cli-cursor": "^5.0.0",
+ "slice-ansi": "^7.1.0",
+ "strip-ansi": "^7.1.0",
+ "wrap-ansi": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/emoji-regex": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
+ "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
+ "license": "MIT"
+ },
+ "node_modules/log-update/node_modules/is-fullwidth-code-point": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz",
+ "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==",
+ "license": "MIT",
+ "dependencies": {
+ "get-east-asian-width": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/node_modules/slice-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz",
+ "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "is-fullwidth-code-point": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/wrap-ansi": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
+ "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/long": {
"version": "4.0.0",
"license": "Apache-2.0"
@@ -6158,6 +6830,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "license": "MIT"
+ },
"node_modules/merge2": {
"version": "1.4.1",
"license": "MIT",
@@ -6218,6 +6896,30 @@
"node": ">= 0.6"
}
},
+ "node_modules/mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mimic-function": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
+ "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"dev": true,
@@ -6412,6 +7114,33 @@
"node": ">=0.10.0"
}
},
+ "node_modules/npm-run-path": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
+ "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/npm-run-path/node_modules/path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/nprogress": {
"version": "0.2.0",
"license": "MIT"
@@ -6560,6 +7289,21 @@
"wrappy": "1"
}
},
+ "node_modules/onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/open-graph": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/open-graph/-/open-graph-0.2.6.tgz",
@@ -6679,7 +7423,6 @@
},
"node_modules/path-key": {
"version": "3.1.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -6725,6 +7468,18 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/pidtree": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
+ "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
+ "license": "MIT",
+ "bin": {
+ "pidtree": "bin/pidtree.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/pify": {
"version": "2.3.0",
"license": "MIT",
@@ -7386,6 +8141,37 @@
"node": ">=4"
}
},
+ "node_modules/restore-cursor": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
+ "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^7.0.0",
+ "signal-exit": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/restore-cursor/node_modules/onetime": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
+ "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-function": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/retry": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
@@ -7418,6 +8204,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/rfdc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+ "license": "MIT"
+ },
"node_modules/rimraf": {
"version": "3.0.2",
"dev": true,
@@ -7611,7 +8403,6 @@
},
"node_modules/shebang-command": {
"version": "2.0.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
@@ -7622,7 +8413,6 @@
},
"node_modules/shebang-regex": {
"version": "3.0.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -7646,6 +8436,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
@@ -7656,6 +8458,46 @@
"node": ">=8"
}
},
+ "node_modules/slice-ansi": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
+ "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.0.0",
+ "is-fullwidth-code-point": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
+ "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -7733,6 +8575,15 @@
"safe-buffer": "~5.2.0"
}
},
+ "node_modules/string-argv": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
+ "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6.19"
+ }
+ },
"node_modules/string-width": {
"version": "4.2.3",
"license": "MIT",
@@ -7811,6 +8662,18 @@
"node": ">=4"
}
},
+ "node_modules/strip-final-newline": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+ "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"devOptional": true,
@@ -8334,7 +9197,6 @@
},
"node_modules/which": {
"version": "2.0.2",
- "dev": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
diff --git a/web/package.json b/package.json
similarity index 86%
rename from web/package.json
rename to package.json
index b25e3f1b..d329d215 100644
--- a/web/package.json
+++ b/package.json
@@ -6,7 +6,8 @@
"build": "next build",
"start": "next start",
"lint": "next lint",
- "format": "prettier --write ."
+ "format": "prettier --write .",
+ "prepare": "husky"
},
"dependencies": {
"@firebase/firestore": "^3.7.2",
@@ -16,7 +17,9 @@
"firebase": "^9.23.0",
"firebase-admin": "^11.2.0",
"firebase-functions": "^4.0.2",
+ "husky": "^9.1.6",
"jszip": "^3.10.1",
+ "lint-staged": "^15.2.10",
"markdown-it": "^12.3.2",
"next": "^12.3.4",
"nextjs-progressbar": "^0.0.14",
@@ -53,5 +56,9 @@
"postcss": "^8.4.16",
"prettier": "^3.3.3",
"typescript": "^5.5.4"
+ },
+ "lint-staged": {
+ "*.{js,jsx,ts,tsx}": "eslint --cache --fix",
+ "*.{js,jsx,ts,tsx,json,css,md}": "prettier --write"
}
}
diff --git a/web/pages/_app.tsx b/pages/_app.tsx
similarity index 100%
rename from web/pages/_app.tsx
rename to pages/_app.tsx
diff --git a/web/pages/_document.tsx b/pages/_document.tsx
similarity index 100%
rename from web/pages/_document.tsx
rename to pages/_document.tsx
diff --git a/web/pages/admin/babies.tsx b/pages/admin/babies.tsx
similarity index 100%
rename from web/pages/admin/babies.tsx
rename to pages/admin/babies.tsx
diff --git a/web/pages/admin/book/[babyId].tsx b/pages/admin/book/[babyId].tsx
similarity index 100%
rename from web/pages/admin/book/[babyId].tsx
rename to pages/admin/book/[babyId].tsx
diff --git a/web/pages/admin/caregivers.tsx b/pages/admin/caregivers.tsx
similarity index 100%
rename from web/pages/admin/caregivers.tsx
rename to pages/admin/caregivers.tsx
diff --git a/web/pages/admin/index.tsx b/pages/admin/index.tsx
similarity index 100%
rename from web/pages/admin/index.tsx
rename to pages/admin/index.tsx
diff --git a/web/pages/admin/item-requests.tsx b/pages/admin/item-requests.tsx
similarity index 100%
rename from web/pages/admin/item-requests.tsx
rename to pages/admin/item-requests.tsx
diff --git a/web/pages/admin/resource-library.tsx b/pages/admin/resource-library.tsx
similarity index 100%
rename from web/pages/admin/resource-library.tsx
rename to pages/admin/resource-library.tsx
diff --git a/web/pages/admin/settings.tsx b/pages/admin/settings.tsx
similarity index 100%
rename from web/pages/admin/settings.tsx
rename to pages/admin/settings.tsx
diff --git a/web/pages/admin/waivers/[id].tsx b/pages/admin/waivers/[id].tsx
similarity index 100%
rename from web/pages/admin/waivers/[id].tsx
rename to pages/admin/waivers/[id].tsx
diff --git a/web/pages/admin/waivers/index.tsx b/pages/admin/waivers/index.tsx
similarity index 100%
rename from web/pages/admin/waivers/index.tsx
rename to pages/admin/waivers/index.tsx
diff --git a/web/pages/api/download-album.ts b/pages/api/download-album.ts
similarity index 100%
rename from web/pages/api/download-album.ts
rename to pages/api/download-album.ts
diff --git a/web/pages/api/download.ts b/pages/api/download.ts
similarity index 100%
rename from web/pages/api/download.ts
rename to pages/api/download.ts
diff --git a/web/pages/caregiver/book/[babyId].tsx b/pages/caregiver/book/[babyId].tsx
similarity index 100%
rename from web/pages/caregiver/book/[babyId].tsx
rename to pages/caregiver/book/[babyId].tsx
diff --git a/web/pages/caregiver/book/index.tsx b/pages/caregiver/book/index.tsx
similarity index 100%
rename from web/pages/caregiver/book/index.tsx
rename to pages/caregiver/book/index.tsx
diff --git a/web/pages/caregiver/onboarding.tsx b/pages/caregiver/onboarding.tsx
similarity index 100%
rename from web/pages/caregiver/onboarding.tsx
rename to pages/caregiver/onboarding.tsx
diff --git a/web/pages/login.tsx b/pages/login.tsx
similarity index 100%
rename from web/pages/login.tsx
rename to pages/login.tsx
diff --git a/web/pages/signup.tsx b/pages/signup.tsx
similarity index 100%
rename from web/pages/signup.tsx
rename to pages/signup.tsx
diff --git a/web/postcss.config.js b/postcss.config.js
similarity index 100%
rename from web/postcss.config.js
rename to postcss.config.js
diff --git a/web/public/GoogleImage.png b/public/GoogleImage.png
similarity index 100%
rename from web/public/GoogleImage.png
rename to public/GoogleImage.png
diff --git a/web/public/MBBLogo.svg b/public/MBBLogo.svg
similarity index 100%
rename from web/public/MBBLogo.svg
rename to public/MBBLogo.svg
diff --git a/web/public/admin_portal_gradient.png b/public/admin_portal_gradient.png
similarity index 100%
rename from web/public/admin_portal_gradient.png
rename to public/admin_portal_gradient.png
diff --git a/web/public/book.png b/public/book.png
old mode 100755
new mode 100644
similarity index 100%
rename from web/public/book.png
rename to public/book.png
diff --git a/web/public/book.svg b/public/book.svg
similarity index 100%
rename from web/public/book.svg
rename to public/book.svg
diff --git a/web/public/caretakers_icon.png b/public/caretakers_icon.png
similarity index 100%
rename from web/public/caretakers_icon.png
rename to public/caretakers_icon.png
diff --git a/web/public/children_and_baby_books_icon.png b/public/children_and_baby_books_icon.png
similarity index 100%
rename from web/public/children_and_baby_books_icon.png
rename to public/children_and_baby_books_icon.png
diff --git a/web/public/dots.png b/public/dots.png
similarity index 100%
rename from web/public/dots.png
rename to public/dots.png
diff --git a/web/public/favicon.ico b/public/favicon.ico
similarity index 100%
rename from web/public/favicon.ico
rename to public/favicon.ico
diff --git a/web/public/item_requests_icon.png b/public/item_requests_icon.png
similarity index 100%
rename from web/public/item_requests_icon.png
rename to public/item_requests_icon.png
diff --git a/web/public/left_heart.png b/public/left_heart.png
similarity index 100%
rename from web/public/left_heart.png
rename to public/left_heart.png
diff --git a/web/public/resource_library_icon.png b/public/resource_library_icon.png
similarity index 100%
rename from web/public/resource_library_icon.png
rename to public/resource_library_icon.png
diff --git a/web/public/right_heart.png b/public/right_heart.png
similarity index 100%
rename from web/public/right_heart.png
rename to public/right_heart.png
diff --git a/web/public/settings_icon.png b/public/settings_icon.png
similarity index 100%
rename from web/public/settings_icon.png
rename to public/settings_icon.png
diff --git a/web/public/trashcan.png b/public/trashcan.png
similarity index 100%
rename from web/public/trashcan.png
rename to public/trashcan.png
diff --git a/web/public/vercel.svg b/public/vercel.svg
similarity index 100%
rename from web/public/vercel.svg
rename to public/vercel.svg
diff --git a/web/public/warning.svg b/public/warning.svg
similarity index 100%
rename from web/public/warning.svg
rename to public/warning.svg
diff --git a/web/public/x.svg b/public/x.svg
similarity index 100%
rename from web/public/x.svg
rename to public/x.svg
diff --git a/web/styles/globals.css b/styles/globals.css
similarity index 100%
rename from web/styles/globals.css
rename to styles/globals.css
diff --git a/web/tailwind.config.js b/tailwind.config.js
similarity index 100%
rename from web/tailwind.config.js
rename to tailwind.config.js
diff --git a/web/tsconfig.json b/tsconfig.json
similarity index 100%
rename from web/tsconfig.json
rename to tsconfig.json
diff --git a/web/.gitignore b/web/.gitignore
deleted file mode 100644
index 88b6f0d9..00000000
--- a/web/.gitignore
+++ /dev/null
@@ -1,37 +0,0 @@
-# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
-
-# dependencies
-/node_modules
-/.pnp
-.pnp.js
-
-# testing
-/coverage
-
-# next.js
-/.next/
-/out/
-
-# production
-/build
-
-# misc
-.DS_Store
-*.pem
-
-# debug
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# local env files
-.env.local
-.env.development.local
-.env.test.local
-.env.production.local
-
-# vercel
-.vercel
-
-# typescript
-*.tsbuildinfo
diff --git a/web/README.md b/web/README.md
deleted file mode 100644
index c87e0421..00000000
--- a/web/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
-
-## Getting Started
-
-First, run the development server:
-
-```bash
-npm run dev
-# or
-yarn dev
-```
-
-Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
-
-You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
-
-[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
-
-The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
-
-## Learn More
-
-To learn more about Next.js, take a look at the following resources:
-
-- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
-- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
-
-You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
-
-## Deploy on Vercel
-
-The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
-
-Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/web/components/molecules/Pagination/PaginationHooks.ts b/web/components/molecules/Pagination/PaginationHooks.ts
deleted file mode 100644
index 5b788742..00000000
--- a/web/components/molecules/Pagination/PaginationHooks.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { CollectionPath } from "@lib/types/db";
-import { getTotalRecords } from "db/firebase/getSize";
-import { useEffect, useState } from "react";
-
-export function usePaginatedData(fetchPage: (page: number, paginationReferences: Map) => Promise<{ data: T[], paginationInfo: any }>, type: CollectionPath) {
- const [paginationReferences, setPaginationReferences] = useState