diff --git a/booking-app/app/api/approve/route.ts b/booking-app/app/api/approve/route.ts index 297b6d3f..73204525 100644 --- a/booking-app/app/api/approve/route.ts +++ b/booking-app/app/api/approve/route.ts @@ -3,11 +3,10 @@ import { NextRequest, NextResponse } from "next/server"; import { serverApproveBooking } from "@/components/src/server/admin"; export async function POST(req: NextRequest) { - const { id } = await req.json(); + const { id, email } = await req.json(); try { - console.log("id", id); - await serverApproveBooking(id); + await serverApproveBooking(id, email); return NextResponse.json( { message: "Approved successfully" }, { status: 200 }, diff --git a/booking-app/app/decline/page.tsx b/booking-app/app/decline/page.tsx index 957715e0..a2e17f85 100644 --- a/booking-app/app/decline/page.tsx +++ b/booking-app/app/decline/page.tsx @@ -1,10 +1,12 @@ "use client"; - -import React, { Suspense, useState } from "react"; - -import { Button } from "@mui/material"; -import { useSearchParams } from "next/navigation"; +import { + DatabaseContext, + DatabaseProvider, +} from "@/components/src/client/routes/components/Provider"; import { decline } from "@/components/src/server/db"; +import { Button, TextField } from "@mui/material"; +import { useSearchParams } from "next/navigation"; +import React, { Suspense, useContext, useState } from "react"; const DeclinePageContent: React.FC = () => { const searchParams = useSearchParams(); @@ -12,19 +14,24 @@ const DeclinePageContent: React.FC = () => { const [loading, setLoading] = useState(false); const [declined, setDeclined] = useState(false); const [error, setError] = useState(null); + const [reason, setReason] = useState(""); + const { userEmail } = useContext(DatabaseContext); const handleDecline = async () => { - if (paramCalendarEventId) { + if (paramCalendarEventId && reason.trim()) { setLoading(true); setError(null); try { - await decline(paramCalendarEventId); + await decline(paramCalendarEventId, userEmail, reason); setDeclined(true); } catch (err) { setError("Failed to decline booking."); + console.log(err); } finally { setLoading(false); } + } else { + setError("Please provide a reason for declining."); } }; @@ -34,9 +41,20 @@ const DeclinePageContent: React.FC = () => { {paramCalendarEventId ? (

Event ID: {paramCalendarEventId}

+ setReason(e.target.value)} + style={{ marginBottom: 16 }} + required + />
}> - - + + Loading...}> + + + ); export default DeclinePage; diff --git a/booking-app/components/src/server/db.ts b/booking-app/components/src/server/db.ts index ac299854..966c3374 100644 --- a/booking-app/components/src/server/db.ts +++ b/booking-app/components/src/server/db.ts @@ -1,20 +1,20 @@ import { - BookingFormDetails, - BookingStatusLabel, - PolicySettings, -} from "../types"; + clientFetchAllDataFromCollection, + clientGetDataByCalendarEventId, + clientUpdateDataInFirestore, +} from "@/lib/firebase/firebase"; +import { Timestamp, where } from "@firebase/firestore"; import { TableNames, clientGetFinalApproverEmail, getCancelCcEmail, } from "../policy"; -import { Timestamp, where } from "@firebase/firestore"; -import { approvalUrl, declineUrl, getBookingToolDeployUrl } from "./ui"; import { - clientFetchAllDataFromCollection, - clientGetDataByCalendarEventId, - clientUpdateDataInFirestore, -} from "@/lib/firebase/firebase"; + BookingFormDetails, + BookingStatusLabel, + PolicySettings, +} from "../types"; +import { approvalUrl, declineUrl, getBookingToolDeployUrl } from "./ui"; import { clientUpdateDataByCalendarEventId } from "@/lib/firebase/client/clientDb"; import { roundTimeUp } from "../client/utils/date"; @@ -69,9 +69,10 @@ export const getOldSafetyTrainingEmails = () => { //return combinedValues; }; -export const decline = async (id: string) => { +export const decline = async (id: string, email: string, reason?: string) => { clientUpdateDataByCalendarEventId(TableNames.BOOKING_STATUS, id, { declinedAt: Timestamp.now(), + declinedBy: email, }); const doc = await clientGetDataByCalendarEventId( @@ -80,8 +81,15 @@ export const decline = async (id: string) => { ); //@ts-ignore const guestEmail = doc ? doc.email : null; - const headerMessage = - "Your reservation request for Media Commons has been declined. For detailed reasons regarding this decision, please contact us at mediacommons.reservations@nyu.edu."; + let headerMessage = + "Your reservation request for Media Commons has been declined."; + + if (reason) { + headerMessage += ` Reason: ${reason}`; + } else { + headerMessage += + " For detailed reasons regarding this decision, please contact us at mediacommons.reservations@nyu.edu."; + } clientSendBookingDetailEmail( id, guestEmail, @@ -102,9 +110,10 @@ export const decline = async (id: string) => { } ); }; -export const cancel = async (id: string) => { +export const cancel = async (id: string, email: string) => { clientUpdateDataByCalendarEventId(TableNames.BOOKING_STATUS, id, { canceledAt: Timestamp.now(), + canceledBy: email, }); const doc = await clientGetDataByCalendarEventId( TableNames.BOOKING_STATUS, @@ -156,9 +165,10 @@ export const updatePolicySettingData = async (updatedData: object) => { console.log("No policy settings docs found"); } }; -export const checkin = async (id: string) => { +export const checkin = async (id: string, email: string) => { clientUpdateDataByCalendarEventId(TableNames.BOOKING_STATUS, id, { checkedInAt: Timestamp.now(), + checkedInBy: email, }); const doc = await clientGetDataByCalendarEventId( TableNames.BOOKING_STATUS, @@ -190,10 +200,11 @@ export const checkin = async (id: string) => { ); }; -export const checkOut = async (id: string) => { +export const checkOut = async (id: string, email: string) => { const checkoutDate = roundTimeUp(); clientUpdateDataByCalendarEventId(TableNames.BOOKING_STATUS, id, { checkedOutAt: Timestamp.now(), + checkedOutBy: email, }); clientUpdateDataByCalendarEventId(TableNames.BOOKING, id, { endDate: Timestamp.fromDate(checkoutDate), @@ -234,9 +245,10 @@ export const checkOut = async (id: string) => { ); }; -export const noShow = async (id: string) => { +export const noShow = async (id: string, email: string) => { clientUpdateDataByCalendarEventId(TableNames.BOOKING_STATUS, id, { noShowedAt: Timestamp.now(), + noShowedBy: email, }); const doc = await clientGetDataByCalendarEventId( TableNames.BOOKING_STATUS, @@ -324,12 +336,12 @@ export const clientSendConfirmationEmail = async ( clientSendBookingDetailEmail(calendarEventId, email, headerMessage, status); }; -export const clientApproveBooking = async (id: string) => { +export const clientApproveBooking = async (id: string, email: string) => { const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/approve`, { method: "POST", headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ id: id }), + body: JSON.stringify({ id: id, email: email }), }); };