From 879bcf45b5697fcbb32e4ab2bc5a232036847605 Mon Sep 17 00:00:00 2001 From: evermake Date: Fri, 1 Nov 2024 18:38:27 +0500 Subject: [PATCH 1/2] feat(room-booking): scroll to a date from search param --- .../routes/_with_menu/room-booking.index.tsx | 16 +++++++++ .../room-booking/timeline/BookingTimeline.vue | 13 +++----- .../room-booking/timeline/RoomBookingPage.tsx | 33 +++++++++++++++++-- 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/app/routes/_with_menu/room-booking.index.tsx b/src/app/routes/_with_menu/room-booking.index.tsx index 80ca63e..592a471 100644 --- a/src/app/routes/_with_menu/room-booking.index.tsx +++ b/src/app/routes/_with_menu/room-booking.index.tsx @@ -4,6 +4,10 @@ import { RoomBookingPage } from "@/components/room-booking/timeline/RoomBookingP import { createFileRoute } from "@tanstack/react-router"; import { Helmet } from "react-helmet-async"; +type RoomBookingSearch = { + d?: number; +}; + export const Route = createFileRoute("/_with_menu/room-booking/")({ component: () => ( <> @@ -20,4 +24,16 @@ export const Route = createFileRoute("/_with_menu/room-booking/")({ ), + validateSearch: (search): RoomBookingSearch => { + const unix = + typeof search.d === "number" + ? search.d + : typeof search.d === "string" + ? Number.parseInt(search.d) + : NaN; + if (!Number.isNaN(unix) && unix > Date.UTC(0)) { + return { d: unix }; + } + return {}; + }, }); diff --git a/src/components/room-booking/timeline/BookingTimeline.vue b/src/components/room-booking/timeline/BookingTimeline.vue index e9af992..2eccb91 100644 --- a/src/components/room-booking/timeline/BookingTimeline.vue +++ b/src/components/room-booking/timeline/BookingTimeline.vue @@ -8,14 +8,7 @@ import { } from "@/lib/utils/dates.ts"; import { useMediaQuery, useNow } from "@vueuse/core"; import type { MaybeRef } from "vue"; -import { - computed, - onMounted, - ref, - shallowRef, - unref, - watch, -} from "vue"; /* ========================================================================== */ +import { computed, onMounted, ref, shallowRef, unref, watch } from "vue"; /* ========================================================================== */ /* ================================ Options ================================= */ @@ -40,6 +33,8 @@ const emit = defineEmits<{ bookingClick: [booking: Booking]; }>(); +defineExpose({ scrollTo }); + /* ========================================================================== */ /* =============================== Constants ================================ */ /* ========================================================================== */ @@ -959,7 +954,7 @@ function handleBookingClick(event: MouseEvent) { /* =============================== Scrolling ================================ */ /* ========================================================================== */ -type ScrollToOptions = { +export type ScrollToOptions = { /** Date to scroll to. */ to: Date; /** Behavior of scroll. */ diff --git a/src/components/room-booking/timeline/RoomBookingPage.tsx b/src/components/room-booking/timeline/RoomBookingPage.tsx index fd4dab4..2927127 100644 --- a/src/components/room-booking/timeline/RoomBookingPage.tsx +++ b/src/components/room-booking/timeline/RoomBookingPage.tsx @@ -3,17 +3,45 @@ import { $roomBooking } from "@/api/room-booking"; import { AuthWall } from "@/components/common/AuthWall.tsx"; import { BookingModal } from "@/components/room-booking/timeline/BookingModal.tsx"; import { T } from "@/lib/utils/dates.ts"; -import { lazy, Suspense, useState } from "react"; -import type { Booking, Slot } from "./BookingTimeline.vue"; +import { lazy, Suspense, useEffect, useRef, useState } from "react"; +import type { Booking, ScrollToOptions, Slot } from "./BookingTimeline.vue"; +import { getRouteApi } from "@tanstack/react-router"; const BookingTimeline = lazy( () => import("@/components/room-booking/timeline/BookingTimeline.tsx"), ); +type TimelineRef = { + __veauryVueRef__: { + scrollTo: (options: ScrollToOptions) => void; + }; +}; + +const routeApi = getRouteApi("/_with_menu/room-booking/"); + export function RoomBookingPage() { + const search = routeApi.useSearch(); const [modalOpen, setModalOpen] = useState(false); const [newBookingSlot, setNewBookingSlot] = useState(); const [bookingDetails, setBookingDetails] = useState(); + const timelineRef = useRef(null); + const [timelineLoaded, setTimelineLoaded] = useState(false); + + const setTimelineRef = (x: TimelineRef) => { + timelineRef.current = x; + setTimelineLoaded(true); + }; + + useEffect(() => { + if (timelineLoaded && search.d) { + timelineRef.current?.__veauryVueRef__.scrollTo({ + to: new Date(search.d), + behavior: "smooth", + offsetMs: T.Min * 20, + position: "left", + }); + } + }, [timelineLoaded, search.d]); const { me } = useMe(); @@ -68,6 +96,7 @@ export function RoomBookingPage() { setNewBookingSlot(undefined); setModalOpen(true); }} + ref={setTimelineRef} /> From b65aeade787cc78701fb62bb41c762449336d201 Mon Sep 17 00:00:00 2001 From: Artem Bulgakov Date: Tue, 19 Nov 2024 05:31:49 +0300 Subject: [PATCH 2/2] chore(room-booking): add button to show booking on timeline --- src/components/room-booking/list/BookingsListPage.tsx | 11 +++++++++++ .../room-booking/timeline/RoomBookingPage.tsx | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/components/room-booking/list/BookingsListPage.tsx b/src/components/room-booking/list/BookingsListPage.tsx index 915d319..491a41a 100644 --- a/src/components/room-booking/list/BookingsListPage.tsx +++ b/src/components/room-booking/list/BookingsListPage.tsx @@ -5,6 +5,7 @@ import Tooltip from "@/components/common/Tooltip.tsx"; import { DeleteBookingModal } from "@/components/room-booking/list/DeleteBookingModal.tsx"; import { clockTime, durationFormatted, msBetween } from "@/lib/utils/dates.ts"; import { useQueryClient } from "@tanstack/react-query"; +import { Link } from "@tanstack/react-router"; import clsx from "clsx"; import React, { useMemo, useState } from "react"; @@ -106,6 +107,16 @@ export function BookingCard({ isPending ? "visible" : "invisible", )} > + + + + + +