diff --git a/booking-app/components/src/client/routes/components/Provider.tsx b/booking-app/components/src/client/routes/components/Provider.tsx index d348345c..508699d6 100644 --- a/booking-app/components/src/client/routes/components/Provider.tsx +++ b/booking-app/components/src/client/routes/components/Provider.tsx @@ -7,6 +7,7 @@ import { Booking, BookingType, DepartmentType, + Filters, OperationHours, PaUser, PagePermission, @@ -28,7 +29,6 @@ import { Timestamp } from "firebase-admin/firestore"; export interface DatabaseContextType { adminUsers: AdminUser[]; bannedUsers: Ban[]; - futureBookings: Booking[]; allBookings: Booking[]; bookingsLoading: boolean; liaisonUsers: Approver[]; @@ -44,6 +44,7 @@ export interface DatabaseContextType { userEmail: string | undefined; netId: string | undefined; userApiData: UserApiData | undefined; + loadMoreEnabled?: boolean; reloadAdminUsers: () => Promise; reloadApproverUsers: () => Promise; reloadBannedUsers: () => Promise; @@ -54,13 +55,15 @@ export interface DatabaseContextType { reloadBookingTypes: () => Promise; reloadSafetyTrainedUsers: () => Promise; setUserEmail: (x: string) => void; - fetchAllBookings: () => Promise; + fetchAllBookings: (clicked: boolean) => Promise; + setFilters: (x: Filters) => void; + setLoadMoreEnabled: (x: boolean) => void; + setLastItem: (x: any) => void; } export const DatabaseContext = createContext({ adminUsers: [], bannedUsers: [], - futureBookings: [], allBookings: [], bookingsLoading: true, liaisonUsers: [], @@ -76,17 +79,21 @@ export const DatabaseContext = createContext({ userEmail: undefined, netId: undefined, userApiData: undefined, - reloadAdminUsers: async () => {}, - reloadApproverUsers: async () => {}, - reloadBannedUsers: async () => {}, - reloadFutureBookings: async () => {}, - reloadDepartmentNames: async () => {}, - reloadOperationHours: async () => {}, - reloadPaUsers: async () => {}, - reloadBookingTypes: async () => {}, - reloadSafetyTrainedUsers: async () => {}, - setUserEmail: (x: string) => {}, - fetchAllBookings: async () => {}, + loadMoreEnabled: true, + reloadAdminUsers: async () => { }, + reloadApproverUsers: async () => { }, + reloadBannedUsers: async () => { }, + reloadFutureBookings: async () => { }, + reloadDepartmentNames: async () => { }, + reloadOperationHours: async () => { }, + reloadPaUsers: async () => { }, + reloadBookingTypes: async () => { }, + reloadSafetyTrainedUsers: async () => { }, + setUserEmail: (x: string) => { }, + fetchAllBookings: async () => { }, + setFilters: (x: Filters) => { }, + setLoadMoreEnabled: (x: boolean) => { }, + setLastItem: (x: any) => { }, }); export const DatabaseProvider = ({ @@ -95,7 +102,7 @@ export const DatabaseProvider = ({ children: React.ReactNode; }) => { const [bannedUsers, setBannedUsers] = useState([]); - const [futureBookings, setFutureBookings] = useState([]); + // const [futureBookings, setFutureBookings] = useState([]); const [bookingsLoading, setBookingsLoading] = useState(true); const [allBookings, setAllBookings] = useState([]); const [adminUsers, setAdminUsers] = useState([]); @@ -107,6 +114,8 @@ export const DatabaseProvider = ({ const [policySettings, setPolicySettings] = useState({ finalApproverEmail: "", }); + const [loadMoreEnabled, setLoadMoreEnabled] = useState(true); + const [roomSettings, setRoomSettings] = useState([]); const [safetyTrainedUsers, setSafetyTrainedUsers] = useState< SafetyTraining[] @@ -116,8 +125,9 @@ export const DatabaseProvider = ({ const [userApiData, setUserApiData] = useState( undefined ); - const [lastItem, setLastItem] = useState(null); - const LIMIT = 3; + const [lastItem, setLastItem] = useState(null); + const [filters, setFilters] = useState({ dateRange: "", sortField: "startDate" }); + const LIMIT = 10; const { user } = useAuth(); const netId = useMemo(() => userEmail?.split("@")[0], [userEmail]); @@ -165,6 +175,10 @@ export const DatabaseProvider = ({ JSON.stringify(equipmentUsers), ]); + useEffect(() => { + console.log(allBookings.length); + }, [allBookings]); + useEffect(() => { if (!bookingsLoading) { fetchSafetyTrainedUsers(); @@ -173,10 +187,14 @@ export const DatabaseProvider = ({ fetchDepartmentNames(); fetchSettings(); } else { - fetchFutureBookings(); + // fetchBookings(); } }, [bookingsLoading, user]); + useEffect(() => { + fetchBookings(); + }, [filters]); + useEffect(() => { fetchActiveUserEmail(); fetchAdminUsers(); @@ -184,15 +202,6 @@ export const DatabaseProvider = ({ fetchRoomSettings(); }, [user]); - useEffect(() => { - if ( - pagePermission === PagePermission.ADMIN || - pagePermission === PagePermission.LIAISON || - pagePermission === PagePermission.PA - ) - fetchBookings(); - }, [pagePermission]); - const fetchActiveUserEmail = () => { if (!user) return; setUserEmail(user.email); @@ -201,20 +210,42 @@ export const DatabaseProvider = ({ const fetchFutureBookings = async () => { fetchAllFutureBooking() .then((fetchedData) => { - setFutureBookings(fetchedData as Booking[]); + // setFutureBookings(fetchedData as Booking[]); setBookingsLoading(false); }) .catch((error) => console.error("Error fetching data:", error)); }; - const fetchBookings = async () => { + const fetchBookings = async (clicked = false) => { try { + + if (filters.dateRange === "") { + return; + } + const bookingsResponse: Booking[] = await fetchAllBookings( + pagePermission, LIMIT, + filters, lastItem ); - setLastItem(bookingsResponse[bookingsResponse.length - 1].requestedAt); - setAllBookings((oldBookings) => [...oldBookings, ...bookingsResponse]); + + + + if (clicked && bookingsResponse.length === 0) { + setLoadMoreEnabled(false); + return; + } + + if (clicked) { + setLastItem(bookingsResponse[bookingsResponse.length - 1]); + setAllBookings((oldBookings) => [...oldBookings, ...bookingsResponse]); + } else { + setLastItem(bookingsResponse[bookingsResponse.length - 1]); + setAllBookings(bookingsResponse); + } + setBookingsLoading(false); + } catch (error) { console.error("Error fetching data:", error); } @@ -418,7 +449,6 @@ export const DatabaseProvider = ({ value={{ adminUsers, bannedUsers, - futureBookings, allBookings, liaisonUsers, equipmentUsers, @@ -434,6 +464,7 @@ export const DatabaseProvider = ({ netId, bookingsLoading, userApiData, + loadMoreEnabled, reloadAdminUsers: fetchAdminUsers, reloadApproverUsers: fetchApproverUsers, reloadBannedUsers: fetchBannedUsers, @@ -445,6 +476,9 @@ export const DatabaseProvider = ({ reloadSafetyTrainedUsers: fetchSafetyTrainedUsers, setUserEmail, fetchAllBookings: fetchBookings, + setFilters: setFilters, + setLoadMoreEnabled, + setLastItem, }} > {children} diff --git a/booking-app/components/src/client/routes/components/bookingTable/BookingTableFilters.tsx b/booking-app/components/src/client/routes/components/bookingTable/BookingTableFilters.tsx index 4c7a373a..b2d89e00 100644 --- a/booking-app/components/src/client/routes/components/bookingTable/BookingTableFilters.tsx +++ b/booking-app/components/src/client/routes/components/bookingTable/BookingTableFilters.tsx @@ -4,8 +4,9 @@ import { Box } from "@mui/material"; import { DateRangeFilter } from "./hooks/getDateFilter"; import Dropdown from "../../booking/components/Dropdown"; import FilterList from "@mui/icons-material/FilterList"; -import React from "react"; +import React, { useContext } from "react"; import StatusChip from "./StatusChip"; +import { DatabaseContext } from "../Provider"; interface Props { allowedStatuses: BookingStatusLabel[]; @@ -24,6 +25,7 @@ export default function BookingTableFilters({ selectedDateRange, setSelectedDateRange, }: Props) { + const { setLoadMoreEnabled, setLastItem } = useContext(DatabaseContext); const handleChipClick = (status: BookingStatusLabel) => { setSelectedStatuses((prev: BookingStatusLabel[]) => { if (prev.includes(status)) { @@ -39,6 +41,8 @@ export default function BookingTableFilters({ ) => { if (newFilter != null) { setSelectedDateRange(newFilter); + setLoadMoreEnabled(true); + setLastItem(null); } }; @@ -46,7 +50,7 @@ export default function BookingTableFilters({ handleDateRangeFilterClick(null, x)} - options={["Today", "This Week", "All"]} + options={["Today", "This Week", "All Future", "Past 24 hours", "Past Week", "Past Month", "Past 6 Months", "All Past"]} placeholder={"Today"} sx={{ width: "125px", mr: 1 }} /> diff --git a/booking-app/components/src/client/routes/components/bookingTable/Bookings.tsx b/booking-app/components/src/client/routes/components/bookingTable/Bookings.tsx index d9145fcf..3eb94699 100644 --- a/booking-app/components/src/client/routes/components/bookingTable/Bookings.tsx +++ b/booking-app/components/src/client/routes/components/bookingTable/Bookings.tsx @@ -31,22 +31,25 @@ export const Bookings: React.FC = ({ pageContext, calendarEventId, }) => { - const { futureBookings, bookingsLoading, reloadFutureBookings, fetchAllBookings, allBookings } = + const { bookingsLoading, setLastItem, fetchAllBookings, allBookings, loadMoreEnabled } = useContext(DatabaseContext); const allowedStatuses = useAllowedStatuses(pageContext); const [modalData, setModalData] = useState(null); const [statusFilters, setStatusFilters] = useState([]); const [selectedDateRange, setSelectedDateRange] = useState( - calendarEventId ? "All" : "Today" + calendarEventId ? "All Future" : "Today" ); const [orderBy, setOrderBy] = useState("startDate"); - const [order, setOrder] = useState("asc"); + const [order, setOrder] = useState("desc"); const isUserView = pageContext === PageContextLevel.USER; useEffect(() => { - reloadFutureBookings(); + // reloadFutureBookings(); + return ()=>{ + setLastItem(null); + } }, []); const filteredRows = useBookingFilters({ @@ -103,7 +106,7 @@ export const Bookings: React.FC = ({ }, [pageContext, statusFilters, allowedStatuses, selectedDateRange]); const bottomSection = useMemo(() => { - if (bookingsLoading && futureBookings.length === 0) { + if (bookingsLoading && allBookings.length === 0) { return ( @@ -206,35 +209,10 @@ export const Bookings: React.FC = ({ closeModal={() => setModalData(null)} /> )} - {!isUserView && ( - - - Previous Bookings - - - {allBookings.map((row: BookingRow) => ( - - ))} -
- - - -
- )} + {loadMoreEnabled && + ( + + )} ); }; diff --git a/booking-app/components/src/client/routes/components/bookingTable/hooks/getDateFilter.ts b/booking-app/components/src/client/routes/components/bookingTable/hooks/getDateFilter.ts index 439c514e..2bcfd1bf 100644 --- a/booking-app/components/src/client/routes/components/bookingTable/hooks/getDateFilter.ts +++ b/booking-app/components/src/client/routes/components/bookingTable/hooks/getDateFilter.ts @@ -1,6 +1,6 @@ import { Booking } from "@/components/src/types"; -export type DateRangeFilter = "Today" | "This Week" | "All"; +export type DateRangeFilter = "Today" | "This Week" | "All Future" | "Past 24 hours" | "Past Week" | "Past Month" | "Past 6 Months" | "All Past"; export const DATE_FILTERS: Record boolean> = { Today: (row) => { @@ -12,6 +12,7 @@ export const DATE_FILTERS: Record boolean> = { date.getDate() === today.getDate() ); }, + "This Week": (row) => { const today = new Date(); let dayOfWeek = today.getDay(); @@ -34,5 +35,55 @@ export const DATE_FILTERS: Record boolean> = { const date = row.startDate.toDate(); return date >= startOfWeek && date <= endOfWeek; }, - All: (row) => true, + + "All Future": (row) => { + const today = new Date(); + return row.startDate.toDate() >= today; + }, + + "Past 24 hours": (row) => { + const today = new Date(); + const date = row.startDate.toDate(); + const diff = today.getTime() - date.getTime(); + + // Check that the date is within the past 24 hours and not in the future + return diff >= 0 && diff < 24 * 60 * 60 * 1000; + }, + + "Past Week": (row) => { + const today = new Date(); + today.setHours(0, 0, 0, 0); // Reset today to midnight + + const date = row.startDate.toDate(); + const diff = today.getTime() - date.getTime(); + + // Check that the date is within the past 7 days and not in the future + return diff >= 0 && diff < 7 * 24 * 60 * 60 * 1000; + }, + + "Past Month": (row) => { + const today = new Date(); + const date = row.startDate.toDate(); + const diff = today.getTime() - date.getTime(); + + // Check that the date is within the past 30 days and not in the future + return diff >= 0 && diff < 30 * 24 * 60 * 60 * 1000; + }, + + "Past 6 Months": (row) => { + const today = new Date(); + const date = row.startDate.toDate(); + const diff = today.getTime() - date.getTime(); + + // Check that the date is within the past 6 months and not in the future + return diff >= 0 && diff < 6 * 30 * 24 * 60 * 60 * 1000; + }, + + "All Past": (row) => { + const today = new Date(); + const date = row.startDate.toDate(); + + // Check that the date is in the past (not in the future) + return today.getTime() - date.getTime() >= 0; + }, }; diff --git a/booking-app/components/src/client/routes/components/bookingTable/hooks/useBookingFilters.ts b/booking-app/components/src/client/routes/components/bookingTable/hooks/useBookingFilters.ts index 9bdc772f..305c20df 100644 --- a/booking-app/components/src/client/routes/components/bookingTable/hooks/useBookingFilters.ts +++ b/booking-app/components/src/client/routes/components/bookingTable/hooks/useBookingFilters.ts @@ -21,145 +21,243 @@ interface Props { selectedStatusFilters: BookingStatusLabel[]; } -export function useBookingFilters(props: Props): BookingRow[] { - const { - pageContext, - columnOrderBy, - columnOrder, - selectedDateRange, - selectedStatusFilters, - } = props; - const { futureBookings, liaisonUsers, userEmail } = useContext(DatabaseContext); - const allowedStatuses = useAllowedStatuses(pageContext); - const [currentTime, setCurrentTime] = useState(new Date()); - - useEffect(() => { - const interval = setInterval(() => { - setCurrentTime(new Date()); - }, 60000); // Update every minute - - return () => clearInterval(interval); - }, []); - - const rows: BookingRow[] = useMemo( - () => - futureBookings.map((booking) => ({ - ...booking, - status: getBookingStatus(booking), - })), - [futureBookings] - ); - - const filteredRows = useMemo(() => { - const filter = new BookingFilter({ +function getDateRangeFromDateSelection(selectedDateRange: DateRangeFilter) { + switch (selectedDateRange) { + case "Today": { + // return an array of the start and end of the day + const today = new Date(); + const startOfDay = new Date(today); + startOfDay.setHours(0, 0, 0, 0); + const endOfDay = new Date(today); + endOfDay.setHours(23, 59, 59, 999); + return [startOfDay, endOfDay]; + } + case "This Week": { + // return an array of the start and end of the week + const today = new Date(); + let dayOfWeek = today.getDay(); + if (dayOfWeek === 0) { + // sunday as last day of week + dayOfWeek = 7; + } + + // Calculate the start of the week (Monday) + const startOfWeek = new Date(today); + startOfWeek.setDate(today.getDate() - (dayOfWeek - 1)); + startOfWeek.setHours(0, 0, 0, 0); + + // Calculate the end of the week (Sunday) + const endOfWeek = new Date(today); + endOfWeek.setDate(today.getDate() + (7 - dayOfWeek)); + endOfWeek.setHours(23, 59, 59, 999); + return [startOfWeek, endOfWeek]; + } + case "All Future": { + // return an array of the start of today and the end of time + const today = new Date(); + const startOfToday = new Date(today); + startOfToday.setHours(0, 0, 0, 0); + return [startOfToday, null]; + } + case "Past 24 hours": { + // return an array of the start and end of the past 24 hours + const today = new Date(); + const startOfPast24Hours = new Date(today); + startOfPast24Hours.setHours(today.getHours() - 24); + return [startOfPast24Hours, today]; + } + case "Past Week": { + // return an array of the start and end of the past week + const today = new Date(); + today.setHours(0, 0, 0, 0); // Reset today to midnight + + const startOfPastWeek = new Date(today); + startOfPastWeek.setDate(today.getDate() - 7); + return [startOfPastWeek, today]; + } + case "Past Month": + { + // return an array of the start and end of the past month + const today = new Date(); + today.setHours(0, 0, 0, 0); // Reset today to midnight + + const startOfPastMonth = new Date(today); + startOfPastMonth.setMonth(today.getMonth() - 1); + return [startOfPastMonth, today]; + } + case "Past 6 Months": { + // return an array of the start and end of the past 6 months + const today = new Date(); + today.setHours(0, 0, 0, 0); // Reset today to midnight + + const startOfPast6Months = new Date(today); + startOfPast6Months.setMonth(today.getMonth() - 6); + return [startOfPast6Months, today]; + } + case "All Past": { + // return an array of the start of time and the end of today + const today = new Date(); + const endOfToday = new Date(today); + endOfToday.setHours(23, 59, 59, 999); + return [null, endOfToday]; + } + default: + return "Today"; + } +} + + export function useBookingFilters(props: Props): BookingRow[] { + const { + pageContext, + columnOrderBy, + columnOrder, + selectedDateRange, + selectedStatusFilters, + } = props; + const { liaisonUsers, userEmail, allBookings, setFilters } = useContext(DatabaseContext); + const allowedStatuses = useAllowedStatuses(pageContext); + const [currentTime, setCurrentTime] = useState(new Date()); + + useEffect(() => { + const interval = setInterval(() => { + setCurrentTime(new Date()); + }, 60000); // Update every minute + + return () => clearInterval(interval); + }, []); + + useEffect(() => { + console.log("selectedDateRange",getDateRangeFromDateSelection(selectedDateRange)); + setFilters({ + dateRange: getDateRangeFromDateSelection(selectedDateRange), + sortField: "startDate", + }); + }, [selectedDateRange]); + + const rows: BookingRow[] = useMemo( + () => { + /* return futureBookings.map((booking) => ({ + ...booking, + status: getBookingStatus(booking), + }))} */ + return allBookings.map((booking) => ({ + ...booking, + status: getBookingStatus(booking), + })) + }, + [allBookings] + ); + + const filteredRows = useMemo(() => { + const filter = new BookingFilter({ + rows, + allowedStatuses, + pageContext, + }); + + return filter + // .filterSelectedDateRange(selectedDateRange) + .filterElapsedTime(currentTime) + .filterPageContext(userEmail, liaisonUsers) + .filterAllowedStatuses() + .filterStatusChips(selectedStatusFilters) + .sortByColumn(columnOrderBy, columnOrder) + .getRows(); + }, [ rows, - allowedStatuses, + columnOrderBy, + columnOrder, + currentTime, pageContext, - }); - - return filter - .filterSelectedDateRange(selectedDateRange) - .filterElapsedTime(currentTime) - .filterPageContext(userEmail, liaisonUsers) - .filterAllowedStatuses() - .filterStatusChips(selectedStatusFilters) - .sortByColumn(columnOrderBy, columnOrder) - .getRows(); - }, [ - rows, - columnOrderBy, - columnOrder, - currentTime, - pageContext, - selectedDateRange, - selectedStatusFilters, - ]); - - return filteredRows; -} + // selectedDateRange, + selectedStatusFilters, + ]); -class BookingFilter { - rows: BookingRow[]; - allowedStatuses: BookingStatusLabel[]; - pageContext: PageContextLevel; + return filteredRows; + } - constructor(obj: { + class BookingFilter { rows: BookingRow[]; allowedStatuses: BookingStatusLabel[]; pageContext: PageContextLevel; - }) { - this.rows = obj.rows; - this.allowedStatuses = obj.allowedStatuses; - this.pageContext = obj.pageContext; - } - // filter if endTime has passed and status should be hidden - // checks once per minute - filterElapsedTime(currentTime: Date) { - this.rows = this.rows.filter( - (row) => - !( - BOOKING_TABLE_HIDE_STATUS_TIME_ELAPSED.includes(row.status) && - row.endDate.toDate() < currentTime - ) - ); - return this; - } - - filterPageContext(userEmail: string, liaisonUsers: Approver[]) { - if (this.pageContext === PageContextLevel.USER) { - this.rows = this.rows.filter((row) => row.email === userEmail); + constructor(obj: { + rows: BookingRow[]; + allowedStatuses: BookingStatusLabel[]; + pageContext: PageContextLevel; + }) { + this.rows = obj.rows; + this.allowedStatuses = obj.allowedStatuses; + this.pageContext = obj.pageContext; } - if (this.pageContext === PageContextLevel.LIAISON) { - const liaisonMatches = liaisonUsers.filter( - (user) => user.email === userEmail + + // filter if endTime has passed and status should be hidden + // checks once per minute + filterElapsedTime(currentTime: Date) { + this.rows = this.rows.filter( + (row) => + !( + BOOKING_TABLE_HIDE_STATUS_TIME_ELAPSED.includes(row.status) && + row.endDate.toDate() < currentTime + ) ); - if (liaisonMatches.length > 0) { - const liaisonDepartments = liaisonMatches.map( - (user) => user.department - ); - this.rows = this.rows.filter((row) => - liaisonDepartments.includes(row.department) + return this; + } + + filterPageContext(userEmail: string, liaisonUsers: Approver[]) { + if (this.pageContext === PageContextLevel.USER) { + this.rows = this.rows.filter((row) => row.email === userEmail); + } + if (this.pageContext === PageContextLevel.LIAISON) { + const liaisonMatches = liaisonUsers.filter( + (user) => user.email === userEmail ); + if (liaisonMatches.length > 0) { + const liaisonDepartments = liaisonMatches.map( + (user) => user.department + ); + this.rows = this.rows.filter((row) => + liaisonDepartments.includes(row.department) + ); + } } + return this; } - return this; - } - filterAllowedStatuses() { - this.rows = this.rows.filter((row) => - this.allowedStatuses.includes(row.status) - ); - return this; - } - - filterSelectedDateRange(selectedDateRange: DateRangeFilter) { - if (this.pageContext >= PageContextLevel.PA) { - this.rows = this.rows.filter(DATE_FILTERS[selectedDateRange]); - } - return this; - } - - filterStatusChips(selectedStatusFilters: BookingStatusLabel[]) { - if (selectedStatusFilters.length > 0) { + filterAllowedStatuses() { this.rows = this.rows.filter((row) => - selectedStatusFilters.includes(row.status) + this.allowedStatuses.includes(row.status) ); + return this; } - return this; - } - sortByColumn(orderBy: keyof BookingRow, order: ColumnSortOrder) { - const comparator = COMPARATORS[orderBy]; - const coeff = order === "asc" ? 1 : -1; - if (comparator != null) { - this.rows.sort((a, b) => coeff * comparator(a, b)); + filterSelectedDateRange(selectedDateRange: DateRangeFilter) { + if (this.pageContext >= PageContextLevel.PA) { + this.rows = this.rows.filter(DATE_FILTERS[selectedDateRange]); + } + return this; } - return this; - } + filterStatusChips(selectedStatusFilters: BookingStatusLabel[]) { + if (selectedStatusFilters.length > 0) { + this.rows = this.rows.filter((row) => + selectedStatusFilters.includes(row.status) + ); + } + return this; + } + + sortByColumn(orderBy: keyof BookingRow, order: ColumnSortOrder) { + const comparator = COMPARATORS[orderBy]; + const coeff = order === "asc" ? 1 : -1; + if (comparator != null) { + this.rows.sort((a, b) => coeff * comparator(a, b)); + } - getRows() { - return this.rows; + return this; + } + + getRows() { + return this.rows; + } } -} diff --git a/booking-app/components/src/server/db.ts b/booking-app/components/src/server/db.ts index 819f6348..fab41d3f 100644 --- a/booking-app/components/src/server/db.ts +++ b/booking-app/components/src/server/db.ts @@ -3,7 +3,9 @@ import { BookingFormDetails, BookingStatusLabel, Days, + Filters, OperationHours, + PagePermission, } from "../types"; import { @@ -36,15 +38,27 @@ export const fetchAllFutureBooking = async (): Promise => { }; export const fetchAllBookings = async ( + pagePermission:PagePermission, limit: number, + filters: Filters, last: any ): Promise => { - return getPaginatedData( - TableNames.BOOKING, - limit, - "requestedAt", - last - ); + if(pagePermission === PagePermission.ADMIN || pagePermission === PagePermission.LIAISON || pagePermission === PagePermission.PA) + { + return getPaginatedData( + TableNames.BOOKING, + limit, + filters, + last + ); + } else { + return getPaginatedData( + TableNames.BOOKING, + limit, + filters, + last + ); + } }; export const getOldSafetyTrainingEmails = () => { diff --git a/booking-app/components/src/types.ts b/booking-app/components/src/types.ts index 258ca767..6e27abb0 100644 --- a/booking-app/components/src/types.ts +++ b/booking-app/components/src/types.ts @@ -285,3 +285,8 @@ export interface UserApiData { dept_name?: string; preferred_first_name?: string; } + +export type Filters = { + dateRange: string | Date[]; + sortField: string; +}; \ No newline at end of file diff --git a/booking-app/lib/firebase/firebase.ts b/booking-app/lib/firebase/firebase.ts index d777eb13..54e79fd5 100644 --- a/booking-app/lib/firebase/firebase.ts +++ b/booking-app/lib/firebase/firebase.ts @@ -19,6 +19,7 @@ import { } from "@firebase/firestore"; import { getDb } from "./firebaseClient"; +import { Filters } from "@/components/src/types"; export type AdminUserData = { email: string; @@ -86,29 +87,45 @@ export const clientFetchAllDataFromCollectionWithLimitAndOffset = async ( export const getPaginatedData = async ( collectionName, itemsPerPage = 10, - orderByField = 'requestedAt', - lastVisible = null + filters: Filters, + lastVisible = null, ) : Promise => { try { const db = getDb(); // Create reference to collection const colRef = collection(db, collectionName); + console.log(filters) + const queryParams = []; + if (filters.dateRange && filters.dateRange.length === 2) { + if(filters.dateRange[0]){ + queryParams.push(where("startDate", ">=", filters.dateRange[0])); + } + + if(filters.dateRange[1]){ + queryParams.push(where("startDate", "<=", filters.dateRange[1])); + } + } + console.log(queryParams) // Build query let q = query( colRef, - orderBy(orderByField, 'desc'), + ...queryParams, + orderBy(filters.sortField, 'desc'), + orderBy("__name__", 'desc'), limit(itemsPerPage) ); // If we have a last visible item, start after it + console.log(lastVisible) if (lastVisible) { - console.log(lastVisible); q = query( colRef, - orderBy(orderByField, 'desc'), - startAfter(lastVisible), + ...queryParams, + orderBy(filters.sortField, 'desc'), + orderBy("__name__", 'desc'), + startAfter(lastVisible[filters.sortField], lastVisible.id), limit(itemsPerPage) ); }