diff --git a/media_commons_booking_app/src/client/routes/admin/components/BookingActions.tsx b/media_commons_booking_app/src/client/routes/admin/components/BookingActions.tsx index bd9acaf9..b1e682f0 100644 --- a/media_commons_booking_app/src/client/routes/admin/components/BookingActions.tsx +++ b/media_commons_booking_app/src/client/routes/admin/components/BookingActions.tsx @@ -1,10 +1,10 @@ -import { Booking, BookingStatusLabel } from '../../../../types'; import React, { useContext, useMemo, useState } from 'react'; +import { BookingStatusLabel } from '../../../../types'; import { DatabaseContext } from '../../components/Provider'; import Loading from '../../../utils/Loading'; import { serverFunctions } from '../../../utils/serverFunctions'; -import useBookingStatus from '../hooks/getBookingStatus'; +import { useLocation } from 'react-router'; interface Props { calendarEventId: string; @@ -15,6 +15,9 @@ export default function BookingActions({ status, calendarEventId }: Props) { const [loading, setLoading] = useState(false); const { reloadBookings, reloadBookingStatuses } = useContext(DatabaseContext); + const location = useLocation(); + const isAdminPage = useMemo(() => location.pathname === '/admin', [location]); + const reload = async () => { await Promise.all([reloadBookings(), reloadBookingStatuses()]); }; @@ -33,9 +36,6 @@ export default function BookingActions({ status, calendarEventId }: Props) { } finally { setLoading(false); } - // await action(); - // await reload(); - // setLoading(false); }} > {text} @@ -43,25 +43,47 @@ export default function BookingActions({ status, calendarEventId }: Props) { ); if (loading) { - return ; + return ( + + + + ); } - return ( + const paBtns = ( <> - {status === BookingStatusLabel.PRE_APPROVED && - ActionButton('Second Approve', () => - serverFunctions.approveBooking(calendarEventId) - )} - {status === BookingStatusLabel.REQUESTED && - ActionButton('First Approve', () => - serverFunctions.approveBooking(calendarEventId) - )} - {ActionButton('Reject', () => serverFunctions.reject(calendarEventId))} - {ActionButton('Cancel', () => serverFunctions.cancel(calendarEventId))} {status !== BookingStatusLabel.CHECKED_IN && ActionButton('Check In', () => serverFunctions.checkin(calendarEventId) )} + {status !== BookingStatusLabel.NO_SHOW && + ActionButton('No Show', () => serverFunctions.noShow(calendarEventId))} ); + + if (!isAdminPage) { + return ( + +
{paBtns}
+ + ); + } + + return ( + +
+ {status === BookingStatusLabel.PRE_APPROVED && + ActionButton('2nd Approve', () => + serverFunctions.approveBooking(calendarEventId) + )} + {status === BookingStatusLabel.REQUESTED && + ActionButton('1st Approve', () => + serverFunctions.approveBooking(calendarEventId) + )} + {ActionButton('Reject', () => serverFunctions.reject(calendarEventId))} + {ActionButton('Cancel', () => serverFunctions.cancel(calendarEventId))} + {paBtns} +
+ + ); } diff --git a/media_commons_booking_app/src/client/routes/admin/components/Bookings.tsx b/media_commons_booking_app/src/client/routes/admin/components/Bookings.tsx index 8384b2b5..e7e3e8e9 100644 --- a/media_commons_booking_app/src/client/routes/admin/components/Bookings.tsx +++ b/media_commons_booking_app/src/client/routes/admin/components/Bookings.tsx @@ -66,17 +66,12 @@ export const Bookings: React.FC = ({ {filteredBookings.map((booking, index) => { const status = getBookingStatus(booking, bookingStatuses); return ( - + {!isUserView && ( - - - + )} {status} {booking.roomId} @@ -120,11 +115,9 @@ export const Bookings: React.FC = ({ {booking.sponsorFirstName} {booking.sponsorLastName} {booking.sponsorEmail} - - {booking.reservationTitle} - + {booking.title} - {booking.reservationDescription} + {booking.description} {booking.expectedAttendance} diff --git a/media_commons_booking_app/src/client/routes/admin/components/Liaisons.tsx b/media_commons_booking_app/src/client/routes/admin/components/Liaisons.tsx index cb943d13..1dd381e1 100644 --- a/media_commons_booking_app/src/client/routes/admin/components/Liaisons.tsx +++ b/media_commons_booking_app/src/client/routes/admin/components/Liaisons.tsx @@ -1,9 +1,9 @@ import React, { useContext, useMemo, useState } from 'react'; +import { TableNames, getLiaisonTableName } from '../../../../policy'; import { DatabaseContext } from '../../components/Provider'; import EmailListTable from '../../components/EmailListTable'; import Loading from '../../../utils/Loading'; -import { TableNames } from '../../../../policy'; import { formatDate } from '../../../utils/date'; // This is a wrapper for google.script.run that lets us use promises. import { serverFunctions } from '../../../utils/serverFunctions'; @@ -26,7 +26,7 @@ const AddLiaisonForm = ({ liaisonEmails, reloadLiaisonEmails }) => { setLoading(true); try { - await serverFunctions.appendRowActive(TableNames.LIAISONS, [ + await serverFunctions.appendRowActive(getLiaisonTableName(), [ email, department, new Date().toString(), @@ -37,6 +37,7 @@ const AddLiaisonForm = ({ liaisonEmails, reloadLiaisonEmails }) => { alert('Failed to add user'); } finally { setLoading(false); + setEmail(''); } }; @@ -56,6 +57,7 @@ const AddLiaisonForm = ({ liaisonEmails, reloadLiaisonEmails }) => { onChange={(e) => { setEmail(e.target.value); }} + value={email} className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="name@nyu.edu" required @@ -113,7 +115,7 @@ export const Liaisons = () => { reloadLiaisonEmails={reloadLiaisonUsers} /> { const bookingStatusMatch = bookingStatuses.filter( - (row) => row.calendarEventId === booking.calendarEventId + (row) => row.calendarId === booking.calendarId )[0]; if (bookingStatusMatch === undefined) return BookingStatusLabel.UNKNOWN; if (bookingStatusMatch.checkedInAt !== '') { return BookingStatusLabel.CHECKED_IN; + } else if (bookingStatusMatch.noShowedAt !== '') { + return BookingStatusLabel.NO_SHOW; } else if (bookingStatusMatch.canceledAt !== '') { return BookingStatusLabel.CANCELED; } else if (bookingStatusMatch.rejectedAt !== '') { diff --git a/media_commons_booking_app/src/client/routes/booking/approval_email.html b/media_commons_booking_app/src/client/routes/booking/approval_email.html index 5b9c882e..625466f1 100644 --- a/media_commons_booking_app/src/client/routes/booking/approval_email.html +++ b/media_commons_booking_app/src/client/routes/booking/approval_email.html @@ -116,11 +116,11 @@

Room Reservation Request

Reservation Title: - +

Reservation Description: - +

Expected Attendance: diff --git a/media_commons_booking_app/src/client/routes/booking/bookingProvider.tsx b/media_commons_booking_app/src/client/routes/booking/bookingProvider.tsx index ddaee013..59977a29 100644 --- a/media_commons_booking_app/src/client/routes/booking/bookingProvider.tsx +++ b/media_commons_booking_app/src/client/routes/booking/bookingProvider.tsx @@ -14,32 +14,26 @@ import { serverFunctions } from '../../utils/serverFunctions'; export interface BookingContextType { bookingCalendarInfo: DateSelectArg | undefined; - canBookFullTime: boolean; department: Department | undefined; isBanned: boolean; isSafetyTrained: boolean; - isThesis_PLACEHOLDER: boolean; role: Role | undefined; selectedRooms: RoomSetting[]; setBookingCalendarInfo: (x: DateSelectArg) => void; setDepartment: (x: Department) => void; - setIsThesis: (x: boolean) => void; setRole: (x: Role) => void; setSelectedRooms: (x: RoomSetting[]) => void; } export const BookingContext = createContext({ bookingCalendarInfo: undefined, - canBookFullTime: false, department: undefined, isBanned: false, isSafetyTrained: true, - isThesis_PLACEHOLDER: false, role: undefined, selectedRooms: [], setBookingCalendarInfo: (x: DateSelectArg) => {}, setDepartment: (x: Department) => {}, - setIsThesis: (x: boolean) => {}, setRole: (x: Role) => {}, setSelectedRooms: (x: RoomSetting[]) => {}, }); @@ -52,15 +46,9 @@ export function BookingProvider({ children }) { useState(); const [department, setDepartment] = useState(); const [isSafetyTrained, setIsSafetyTrained] = useState(true); - const [isThesis_PLACEHOLDER, setIsThesis] = useState(false); const [role, setRole] = useState(); const [selectedRooms, setSelectedRooms] = useState([]); - const canBookFullTime = useMemo( - () => isThesis_PLACEHOLDER || role !== 'Student', - [isThesis_PLACEHOLDER, role] - ); - const isBanned = useMemo(() => { if (!userEmail) return false; return bannedUsers @@ -90,16 +78,13 @@ export function BookingProvider({ children }) { { const [bookingTimeEvent, setBookingTimeEvent] = useState(); @@ -114,7 +112,6 @@ export const Calendars = ({ allRooms={allRooms} bookingTimeEvent={bookingTimeEvent} setBookingTimeEvent={setBookingTimeEvent} - canBookFullTime={canBookFullTime} isOverlap={isOverlap} key={i} /> diff --git a/media_commons_booking_app/src/client/routes/booking/components/FormInput.tsx b/media_commons_booking_app/src/client/routes/booking/components/FormInput.tsx index 068aaa2d..47febc80 100644 --- a/media_commons_booking_app/src/client/routes/booking/components/FormInput.tsx +++ b/media_commons_booking_app/src/client/routes/booking/components/FormInput.tsx @@ -51,8 +51,6 @@ const FormInput = ({ handleParentSubmit }) => { const [showTextbox, setShowTextbox] = useState(false); const roomNumber = selectedRooms.map((room) => room.roomId); - console.log(selectedRooms); - const maxCapacity = selectedRooms.reduce((sum, room) => { return sum + parseInt(room.capacity); }, 0); @@ -79,7 +77,6 @@ const FormInput = ({ handleParentSubmit }) => { const onSubmit: SubmitHandler = (data) => { const dumpMediaServices = data.mediaServices || []; - //@ts-ignore data.mediaServices = Array.isArray(dumpMediaServices) ? dumpMediaServices.join(', ') : dumpMediaServices; @@ -95,15 +92,7 @@ const FormInput = ({ handleParentSubmit }) => { }; return ( -

{ - // e.preventDefault(); - // const values = Object.values(data); - // handleParentSubmit(values, data); - //}} - onSubmit={handleSubmit(onSubmit)} - > + {userEmail == null && (
- {watch('mediaServices') !== undefined && ( -
- +

+ {errors.mediaServicesDetails && ( + + )} + 0, + })} + /> +
+ )}
{ htmlFor="chartFieldForSecurity" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white" > - ChartField for Campus Safety + ChartField for Security
{ +export const MultipleCalendars = ({ allRooms, handleSetDate }) => { const [calendarRefs, setCalendarRefs] = useState([]); const [loading, setLoading] = useState(true); const [checkedRoomIds, setCheckedRoomIds] = useState([]); @@ -122,7 +118,6 @@ export const MultipleCalendars = ({ allRooms={allRooms} selectedRooms={checkedRooms} handleSetDate={handleSubmit} - canBookFullTime={canBookFullTime} />
)} diff --git a/media_commons_booking_app/src/client/routes/booking/components/RoomCalendar.tsx b/media_commons_booking_app/src/client/routes/booking/components/RoomCalendar.tsx index 36efe7ce..67eeb1ef 100644 --- a/media_commons_booking_app/src/client/routes/booking/components/RoomCalendar.tsx +++ b/media_commons_booking_app/src/client/routes/booking/components/RoomCalendar.tsx @@ -1,6 +1,6 @@ +import { BookingStatusLabel, CalendarEvent } from '../../../../types'; import React, { useEffect, useRef, useState } from 'react'; -import { CalendarEvent } from '../../../../types'; import FullCalendar from '@fullcalendar/react'; import dayGridPlugin from '@fullcalendar/daygrid'; import googleCalendarPlugin from '@fullcalendar/google-calendar'; @@ -16,7 +16,6 @@ export const RoomCalendar = ({ allRooms, bookingTimeEvent, setBookingTimeEvent, - canBookFullTime, isOverlap, }) => { const [events, setEvents] = useState([]); @@ -80,16 +79,6 @@ export const RoomCalendar = ({ setBookingTimeEvent(selectInfo); }; const handleSelectAllow = (selectInfo) => { - console.log('selectInfo', selectInfo); - // only enrolledThesis user can book over 4 hours - if ( - !canBookFullTime && - selectInfo.end.getTime() / 1000 - selectInfo.start.getTime() / 1000 > - 60 * 60 * 4 - ) { - return false; - } - console.log('isOverlap', !isOverlap(selectInfo)); return !isOverlap(selectInfo); }; @@ -149,17 +138,19 @@ export const RoomCalendar = ({ } } // Change the background color of the event depending on its title - if (info.event.title.includes('REQUESTED')) { + if (info.event.title.includes(BookingStatusLabel.REQUESTED)) { info.el.style.backgroundColor = '#d60000'; - } else if (info.event.title.includes('PRE-APPROVED')) { + } else if ( + info.event.title.includes(BookingStatusLabel.PRE_APPROVED) + ) { info.el.style.backgroundColor = '#f6c026'; - } else if (info.event.title.includes('APPROVED')) { + } else if (info.event.title.includes(BookingStatusLabel.APPROVED)) { info.el.style.backgroundColor = '#33b679'; - } else if (info.event.title.includes('CONFIRMED')) { - info.el.style.backgroundColor = '#0b8043'; - } else if (info.event.title.includes('REJECTED')) { + } else if (info.event.title.includes(BookingStatusLabel.REJECTED)) { + info.el.style.display = 'none'; + } else if (info.event.title.includes(BookingStatusLabel.CANCELED)) { info.el.style.display = 'none'; - } else if (info.event.title.includes('CANCELLED')) { + } else if (info.event.title.includes(BookingStatusLabel.NO_SHOW)) { info.el.style.display = 'none'; } }} diff --git a/media_commons_booking_app/src/client/routes/booking/formPages/SelectRoomPage.tsx b/media_commons_booking_app/src/client/routes/booking/formPages/SelectRoomPage.tsx index 1fcf4700..f26a22fd 100644 --- a/media_commons_booking_app/src/client/routes/booking/formPages/SelectRoomPage.tsx +++ b/media_commons_booking_app/src/client/routes/booking/formPages/SelectRoomPage.tsx @@ -12,7 +12,6 @@ export default function SelectRoomPage() { const navigate = useNavigate(); const { roomSettings, userEmail } = useContext(DatabaseContext); const { - canBookFullTime, isBanned, isSafetyTrained, selectedRooms, @@ -50,7 +49,6 @@ export default function SelectRoomPage() { key="calendars" allRooms={roomSettings} handleSetDate={handleSetDate} - canBookFullTime={canBookFullTime} />
); diff --git a/media_commons_booking_app/src/client/routes/booking/formPages/UserRolePage.tsx b/media_commons_booking_app/src/client/routes/booking/formPages/UserRolePage.tsx index cfeabdbc..27a57fd7 100644 --- a/media_commons_booking_app/src/client/routes/booking/formPages/UserRolePage.tsx +++ b/media_commons_booking_app/src/client/routes/booking/formPages/UserRolePage.tsx @@ -5,14 +5,8 @@ import { BookingContext } from '../bookingProvider'; import { useNavigate } from 'react-router-dom'; export default function UserRolePage() { - const { - isThesis_PLACEHOLDER, - role, - department, - setDepartment, - setIsThesis, - setRole, - } = useContext(BookingContext); + const { role, department, setDepartment, setRole } = + useContext(BookingContext); const navigate = useNavigate(); @@ -70,23 +64,6 @@ export default function UserRolePage() { ))}
- {role === 'Student' && ( -
- setIsThesis(e.target.checked)} - className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600" - /> - -
- )}