From 31f35a4656bc0524382c6b91de45e46e82ff9396 Mon Sep 17 00:00:00 2001 From: "riho.takagi" Date: Tue, 8 Oct 2024 12:59:15 -0400 Subject: [PATCH] Record email when someone change status --- booking-app/app/approve/page.tsx | 19 +++++++---- .../admin/components/BookingActions.tsx | 32 +++++++++---------- booking-app/components/src/server/admin.ts | 26 ++++++++------- 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/booking-app/app/approve/page.tsx b/booking-app/app/approve/page.tsx index beff1943..11d7f5ec 100644 --- a/booking-app/app/approve/page.tsx +++ b/booking-app/app/approve/page.tsx @@ -1,10 +1,14 @@ "use client"; -import React, { Suspense, useState } from "react"; +import React, { Suspense, useContext, useState } from "react"; +import { + DatabaseContext, + DatabaseProvider, +} from "@/components/src/client/routes/components/Provider"; +import { clientApproveBooking } from "@/components/src/server/db"; import { Button } from "@mui/material"; import { useSearchParams } from "next/navigation"; -import { clientApproveBooking } from "@/components/src/server/db"; const ApprovePageContent: React.FC = () => { const searchParams = useSearchParams(); @@ -12,13 +16,14 @@ const ApprovePageContent: React.FC = () => { const [loading, setLoading] = useState(false); const [approved, setApproved] = useState(false); const [error, setError] = useState(null); + const { userEmail } = useContext(DatabaseContext); const handleApprove = async () => { if (paramCalendarEventId) { setLoading(true); setError(null); try { - await clientApproveBooking(paramCalendarEventId); + await clientApproveBooking(paramCalendarEventId, userEmail); setApproved(true); } catch (err) { setError("Failed to approve booking."); @@ -55,9 +60,11 @@ const ApprovePageContent: React.FC = () => { }; const ApprovePage: React.FC = () => ( - Loading...}> - - + + Loading...}> + + + ); export default ApprovePage; diff --git a/booking-app/components/src/client/routes/admin/components/BookingActions.tsx b/booking-app/components/src/client/routes/admin/components/BookingActions.tsx index 10437974..3358f92a 100644 --- a/booking-app/components/src/client/routes/admin/components/BookingActions.tsx +++ b/booking-app/components/src/client/routes/admin/components/BookingActions.tsx @@ -1,6 +1,3 @@ -import { BookingStatusLabel, PageContextLevel } from "../../../../types"; -import { IconButton, MenuItem, Select } from "@mui/material"; -import React, { useContext, useMemo, useState } from "react"; import { cancel, checkOut, @@ -9,16 +6,19 @@ import { decline, noShow, } from "@/components/src/server/db"; +import { IconButton, MenuItem, Select } from "@mui/material"; +import { useContext, useMemo, useState } from "react"; +import { BookingStatusLabel, PageContextLevel } from "../../../../types"; -import AlertToast from "../../components/AlertToast"; -import { BookingContext } from "../../booking/bookingProvider"; +import { Timestamp } from "@firebase/firestore"; import Check from "@mui/icons-material/Check"; +import { useRouter } from "next/navigation"; +import { BookingContext } from "../../booking/bookingProvider"; +import AlertToast from "../../components/AlertToast"; import ConfirmDialog from "../../components/ConfirmDialog"; -import { DatabaseContext } from "../../components/Provider"; import Loading from "../../components/Loading"; -import { Timestamp } from "@firebase/firestore"; +import { DatabaseContext } from "../../components/Provider"; import useExistingBooking from "../hooks/useExistingBooking"; -import { useRouter } from "next/navigation"; interface Props { calendarEventId: string; @@ -65,7 +65,7 @@ export default function BookingActions({ const [date, setDate] = useState(new Date()); const router = useRouter(); const loadExistingBookingData = useExistingBooking(); - + const { userEmail } = useContext(DatabaseContext); const reload = async () => { await Promise.all([reloadBookings(), reloadBookingStatuses()]); }; @@ -109,44 +109,44 @@ export default function BookingActions({ const actions: { [key in Actions]: ActionDefinition } = { [Actions.CANCEL]: { action: async () => { - await cancel(calendarEventId); + await cancel(calendarEventId, userEmail); }, optimisticNextStatus: BookingStatusLabel.CANCELED, confirmation: true, }, [Actions.NO_SHOW]: { action: async () => { - await noShow(calendarEventId); + await noShow(calendarEventId, userEmail); }, optimisticNextStatus: BookingStatusLabel.NO_SHOW, }, [Actions.CHECK_IN]: { action: async () => { - await checkin(calendarEventId); + await checkin(calendarEventId, userEmail); }, optimisticNextStatus: BookingStatusLabel.CHECKED_IN, }, [Actions.CHECK_OUT]: { action: async () => { - await checkOut(calendarEventId); + await checkOut(calendarEventId, userEmail); }, optimisticNextStatus: BookingStatusLabel.CHECKED_OUT, }, [Actions.FIRST_APPROVE]: { action: async () => { - await clientApproveBooking(calendarEventId); + await clientApproveBooking(calendarEventId, userEmail); }, optimisticNextStatus: BookingStatusLabel.PENDING, }, [Actions.FINAL_APPROVE]: { action: async () => { - await clientApproveBooking(calendarEventId); + await clientApproveBooking(calendarEventId, userEmail); }, optimisticNextStatus: BookingStatusLabel.APPROVED, }, [Actions.DECLINE]: { action: async () => { - await decline(calendarEventId); + await decline(calendarEventId, userEmail); }, optimisticNextStatus: BookingStatusLabel.DECLINED, confirmation: true, diff --git a/booking-app/components/src/server/admin.ts b/booking-app/components/src/server/admin.ts index ef068696..4d92d1a1 100644 --- a/booking-app/components/src/server/admin.ts +++ b/booking-app/components/src/server/admin.ts @@ -1,10 +1,3 @@ -import { - BookingFormDetails, - BookingStatus, - BookingStatusLabel, - PolicySettings, - RoomSetting, -} from "../types"; import { Constraint, serverDeleteData, @@ -14,6 +7,12 @@ import { serverUpdateInFirestore, } from "@/lib/firebase/server/adminDb"; import { TableNames, getApprovalCcEmail } from "../policy"; +import { + BookingFormDetails, + BookingStatus, + BookingStatusLabel, + RoomSetting, +} from "../types"; import { approvalUrl, declineUrl, getBookingToolDeployUrl } from "./ui"; import { Timestamp } from "firebase-admin/firestore"; @@ -72,15 +71,17 @@ export const serverDeleteDataByCalendarEventId = async ( }; // from server -const serverFirstApprove = (id: string) => { +const serverFirstApprove = (id: string, email?: string) => { serverUpdateDataByCalendarEventId(TableNames.BOOKING_STATUS, id, { firstApprovedAt: Timestamp.now(), + firstApprovedBy: email, }); }; -const serverFinalApprove = (id: string) => { +const serverFinalApprove = (id: string, email?: string) => { serverUpdateDataByCalendarEventId(TableNames.BOOKING_STATUS, id, { finalApprovedAt: Timestamp.now(), + finalApprovedBy: email, }); }; @@ -92,7 +93,7 @@ export const serverApproveInstantBooking = (id: string) => { }; // both first approve and second approve flows hit here -export const serverApproveBooking = async (id: string) => { +export const serverApproveBooking = async (id: string, email: string) => { const bookingStatus = await serverGetDataByCalendarEventId( TableNames.BOOKING_STATUS, id @@ -106,10 +107,11 @@ export const serverApproveBooking = async (id: string) => { // if already first approved, then this is a second approve if (firstApproveDateRange !== null) { - serverFinalApprove(id); + serverFinalApprove(id, email); await serverApproveEvent(id); } else { - serverFirstApprove(id); + console.log("email", email); + serverFirstApprove(id, email); const response = await fetch( `${process.env.NEXT_PUBLIC_BASE_URL}/api/calendarEvents`,