From 0b56f3fa473abd25b0b33422fd6db299792ccd02 Mon Sep 17 00:00:00 2001 From: "riho.takagi" Date: Wed, 25 Sep 2024 13:55:04 -0400 Subject: [PATCH 1/2] Support for the Timestamp type in firebase. --- booking-app/components/src/client/utils/serverDate.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/booking-app/components/src/client/utils/serverDate.ts b/booking-app/components/src/client/utils/serverDate.ts index c4651a57..9e7e1072 100644 --- a/booking-app/components/src/client/utils/serverDate.ts +++ b/booking-app/components/src/client/utils/serverDate.ts @@ -22,8 +22,8 @@ export const serverFormatDate = ( ): string => { if (!input) return ""; try { - const date = new Date(input); - + const timestamp = parseTimestamp(input); + const date = new Date(timestamp.toDate()); const zonedDate = toZonedTime(date, timeZone); const formattedResult = format(zonedDate, "yyyy-MM-dd hh:mm a", { From f2f9c7494f25459db71977551ab5390caffb3e63 Mon Sep 17 00:00:00 2001 From: lucia <51058748+lucia-gomez@users.noreply.github.com> Date: Wed, 25 Sep 2024 14:29:22 -0400 Subject: [PATCH 2/2] more calendar drag and drop --- .../booking/components/CalendarEventBlock.tsx | 72 ++++++++++--------- .../components/CalendarVerticalResource.tsx | 32 ++++++++- 2 files changed, 69 insertions(+), 35 deletions(-) diff --git a/booking-app/components/src/client/routes/booking/components/CalendarEventBlock.tsx b/booking-app/components/src/client/routes/booking/components/CalendarEventBlock.tsx index f9786b11..92ca0fbf 100644 --- a/booking-app/components/src/client/routes/booking/components/CalendarEventBlock.tsx +++ b/booking-app/components/src/client/routes/booking/components/CalendarEventBlock.tsx @@ -1,6 +1,5 @@ import { Box, IconButton } from "@mui/material"; -import { BookingStatusLabel } from "../../../../types"; import { Close } from "@mui/icons-material"; import { EventContentArg } from "@fullcalendar/core"; import React from "react"; @@ -11,28 +10,31 @@ export const UNKNOWN_BLOCK_TITLE = "Unavailable"; interface Props { bgcolor: string; - isFirst: boolean; - isLast: boolean; - isNew: boolean; + isnew: boolean; + numrooms: number; } -const Block = styled(Box)( - ({ theme, bgcolor, isFirst, isLast, isNew }) => ({ - backgroundColor: bgcolor || theme.palette.primary.main, - border: `2px solid ${bgcolor || theme.palette.primary.main}`, - borderRadius: "4px", - outline: "none", - height: "100%", - width: isNew && !isLast ? "105%" : "100%", - overflowX: "hidden", - cursor: bgcolor ? "unset" : "pointer", - padding: "2px 4px", - position: "relative", - zIndex: isNew ? 99 : 2, - borderTopLeftRadius: isNew && !isFirst ? 0 : 4, - borderBottomLeftRadius: isNew && !isFirst ? 0 : 4, - }) -); +const Block = styled(Box)(({ theme, bgcolor, isnew, numrooms }) => ({ + backgroundColor: bgcolor || theme.palette.primary.main, + border: `2px solid ${bgcolor || theme.palette.primary.main}`, + borderRadius: "4px", + outline: "none", + height: "100%", + width: isnew + ? `calc((100% + 2px) * ${numrooms} + ${numrooms - 1}px)` + : "100%", + overflowX: "hidden", + cursor: bgcolor ? "unset" : "pointer", + padding: "2px 4px", + position: "relative", + zIndex: isnew ? 99 : 2, +})); + +const Empty = styled(Box)` + width: "100%"; + height: "100%"; + position: relative; +`; const CloseButton = styled(IconButton)(({ theme }) => ({ position: "absolute", @@ -52,8 +54,9 @@ export default function CalendarEventBlock(eventInfo: EventContentArg) { ? eventInfo.event.url.split(":") : ["0", "0"]; const index = Number(params[0]); - const maxIndex = Number(params[1]); - const isLast = index === maxIndex; + const numRooms = Number(params[1]); + + const isLast = index === numRooms - 1; const isOneColumn = index === 0 && isLast; const backgroundColor = () => { @@ -63,17 +66,22 @@ export default function CalendarEventBlock(eventInfo: EventContentArg) { return "rgba(72, 196, 77, 1)"; }; - const hideTitle = isNew && index !== 0 && !isOneColumn; + if (isNew && index !== 0) { + return ( + + {isNew && isLast && ( + + + + )} + + ); + } return ( - - {!hideTitle && {title}} - {isNew && isLast && ( + + {title} + {isNew && isOneColumn && ( diff --git a/booking-app/components/src/client/routes/booking/components/CalendarVerticalResource.tsx b/booking-app/components/src/client/routes/booking/components/CalendarVerticalResource.tsx index 9853a86a..6a509743 100644 --- a/booking-app/components/src/client/routes/booking/components/CalendarVerticalResource.tsx +++ b/booking-app/components/src/client/routes/booking/components/CalendarVerticalResource.tsx @@ -1,10 +1,16 @@ import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; -import { CalendarApi, DateSelectArg, EventClickArg } from "@fullcalendar/core"; +import { + CalendarApi, + DateSelectArg, + EventClickArg, + EventDropArg, +} from "@fullcalendar/core"; import { CalendarEvent, RoomSetting } from "../../../../types"; import CalendarEventBlock, { NEW_TITLE_TAG } from "./CalendarEventBlock"; import React, { useContext, useEffect, useMemo, useRef } from "react"; import { BookingContext } from "../bookingProvider"; +import { EventResizeDoneArg } from "fullcalendar"; import FullCalendar from "@fullcalendar/react"; import googleCalendarPlugin from "@fullcalendar/google-calendar"; import interactionPlugin from "@fullcalendar/interaction"; // for selectable @@ -117,7 +123,10 @@ export default function CalendarVerticalResource({ resourceId: room.roomId + "", title: NEW_TITLE_TAG, overlap: true, - url: `${index}:${rooms.length - 1}`, // some hackiness to let us render multiple events visually as one big block + durationEditable: true, + startEditable: true, + groupId: "new", + url: `${index}:${rooms.length}`, // some hackiness to let us render multiple events visually as one big block })); }, [bookingCalendarInfo, rooms]); @@ -164,12 +173,26 @@ export default function CalendarVerticalResource({ return el.overlap; }; + // clicking on created event should delete it const handleEventClick = (info: EventClickArg) => { if (info.event.title.includes(NEW_TITLE_TAG)) { setBookingCalendarInfo(null); } }; + // if change event duration via dragging edges or drag event block to move + const handleEventEdit = (info: EventResizeDoneArg | EventDropArg) => { + setBookingCalendarInfo({ + startStr: info.event.startStr, + start: info.event.start, + endStr: info.event.endStr, + end: info.event.end, + allDay: false, + jsEvent: info.jsEvent, + view: info.view, + }); + }; + // for editing an existing reservation const existingCalEventsFiltered = useMemo(() => { if (!isEdit || calendarEventId == null || calendarEventId.length === 0) @@ -185,7 +208,8 @@ export default function CalendarVerticalResource({ return ( - Select spaces to view their availability and choose a time slot + Select spaces to view their availability, then click and drag to + choose a time slot ); @@ -214,6 +238,8 @@ export default function CalendarVerticalResource({ info.jsEvent.preventDefault(); handleEventClick(info); }} + eventResize={handleEventEdit} + eventDrop={handleEventEdit} headerToolbar={false} slotMinTime="09:00:00" slotMaxTime="21:00:00"