feat: update current time indicator on page refocus (#27503)
Add updateCurrentTimeOnFocus prop to Calendar component that enables the current time indicator to update when the page is refocused. This helps users see the accurate current time after switching tabs. Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com>
This commit is contained in:
co-authored by
Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Peer Richelsen
parent
d743c92479
commit
4b7ea0c98f
@@ -1,14 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { useMemo, useEffect } from "react";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { useTimePreferences } from "@calcom/features/bookings/lib";
|
||||
import { Calendar } from "@calcom/web/modules/calendars/weeklyview/components/Calendar";
|
||||
import type { CalendarEvent } from "@calcom/features/calendars/weeklyview/types/events";
|
||||
import { useGetTheme } from "@calcom/lib/hooks/useTheme";
|
||||
import { Calendar } from "@calcom/web/modules/calendars/weeklyview/components/Calendar";
|
||||
import { useBanners } from "@calcom/web/modules/shell/banners/useBanners";
|
||||
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useBookingDetailsSheetStore } from "../store/bookingDetailsSheetStore";
|
||||
import type { BookingOutput } from "../types";
|
||||
|
||||
@@ -101,6 +99,7 @@ export function BookingCalendarView({
|
||||
}}
|
||||
showTimezone
|
||||
hideHeader
|
||||
updateCurrentTimeOnFocus
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import React, { useEffect, useMemo, useRef } from "react";
|
||||
|
||||
import {
|
||||
CalendarStoreContext,
|
||||
createCalendarStore,
|
||||
useCalendarStore,
|
||||
} from "@calcom/features/calendars/weeklyview/state/store";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
|
||||
import { CalendarStoreContext, createCalendarStore, useCalendarStore } from "@calcom/features/calendars/weeklyview/state/store";
|
||||
import type React from "react";
|
||||
import { useEffect, useMemo, useRef } from "react";
|
||||
import "@calcom/features/calendars/weeklyview/styles/styles.css";
|
||||
import type { CalendarComponentProps } from "@calcom/features/calendars/weeklyview/types/state";
|
||||
import { getDaysBetweenDates, getHoursToDisplay } from "@calcom/features/calendars/weeklyview/utils";
|
||||
import { DateValues } from "./DateValues";
|
||||
import { CurrentTime } from "./currentTime";
|
||||
import { DateValues } from "./DateValues";
|
||||
import { AvailableCellsForDay, EmptyCell } from "./event/Empty";
|
||||
import { EventList } from "./event/EventList";
|
||||
import { SchedulerColumns } from "./grid";
|
||||
@@ -35,6 +38,7 @@ function CalendarInner(props: CalendarComponentProps) {
|
||||
const showBorder = useCalendarStore((state) => state.showBorder ?? true);
|
||||
const borderColor = useCalendarStore((state) => state.borderColor ?? "default");
|
||||
const scrollToCurrentTime = useCalendarStore((state) => state.scrollToCurrentTime ?? true);
|
||||
const updateCurrentTimeOnFocus = useCalendarStore((state) => state.updateCurrentTimeOnFocus ?? false);
|
||||
|
||||
const days = useMemo(() => getDaysBetweenDates(startDate, endDate), [startDate, endDate]);
|
||||
|
||||
@@ -75,7 +79,11 @@ function CalendarInner(props: CalendarComponentProps) {
|
||||
borderColor={borderColor}
|
||||
/>
|
||||
<div className="relative flex flex-auto">
|
||||
<CurrentTime timezone={timezone} scrollToCurrentTime={scrollToCurrentTime} />
|
||||
<CurrentTime
|
||||
timezone={timezone}
|
||||
scrollToCurrentTime={scrollToCurrentTime}
|
||||
updateOnFocus={updateCurrentTimeOnFocus}
|
||||
/>
|
||||
<div
|
||||
className={classNames(
|
||||
"bg-default dark:bg-cal-muted ring-muted sticky left-0 z-10 w-16 flex-none ring-1",
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { useTimePreferences } from "@calcom/features/bookings/lib";
|
||||
|
||||
import { useCalendarStore } from "@calcom/features/calendars/weeklyview/state/store";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
function calculateMinutesFromStart(startHour: number, currentHour: number, currentMinute: number) {
|
||||
const startMinute = startHour * 60;
|
||||
@@ -14,9 +12,11 @@ function calculateMinutesFromStart(startHour: number, currentHour: number, curre
|
||||
export function CurrentTime({
|
||||
timezone,
|
||||
scrollToCurrentTime = true,
|
||||
updateOnFocus = false,
|
||||
}: {
|
||||
timezone: string;
|
||||
scrollToCurrentTime?: boolean;
|
||||
updateOnFocus?: boolean;
|
||||
}) {
|
||||
const { timeFormat } = useTimePreferences();
|
||||
const currentTimeRef = useRef<HTMLDivElement>(null);
|
||||
@@ -27,29 +27,44 @@ export function CurrentTime({
|
||||
endHour: state.endHour || 23,
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
// Set the container scroll position based on the current time.
|
||||
|
||||
const currentDateTime = dayjs().tz(timezone); // Get current date and time in the specified timezone
|
||||
|
||||
const updateCurrentTimePosition = useCallback(() => {
|
||||
const currentDateTime = dayjs().tz(timezone);
|
||||
const currentHour = currentDateTime.hour();
|
||||
const currentMinute = currentDateTime.minute();
|
||||
|
||||
if (currentHour > endHour || currentHour < startHour) {
|
||||
setCurrentTimePos(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const minutesFromStart = calculateMinutesFromStart(startHour, currentHour, currentMinute);
|
||||
setCurrentTimePos(minutesFromStart);
|
||||
}, [timezone, startHour, endHour]);
|
||||
|
||||
useEffect(() => {
|
||||
updateCurrentTimePosition();
|
||||
|
||||
if (!scrollToCurrentTime || !currentTimeRef.current || scrolledIntoView) return;
|
||||
// Within a small timeout so element has time to render.
|
||||
setTimeout(() => {
|
||||
// Doesn't seem to cause any issue. Put it under condition if needed
|
||||
currentTimeRef?.current?.scrollIntoView({ block: "center" });
|
||||
setScrolledIntoView(true);
|
||||
}, 100);
|
||||
}, [startHour, endHour, scrolledIntoView, timezone, scrollToCurrentTime]);
|
||||
}, [updateCurrentTimePosition, scrolledIntoView, scrollToCurrentTime]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!updateOnFocus) return;
|
||||
|
||||
const handleVisibilityChange = () => {
|
||||
if (document.visibilityState === "visible") {
|
||||
updateCurrentTimePosition();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||
return () => {
|
||||
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
||||
};
|
||||
}, [updateOnFocus, updateCurrentTimePosition]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { IFromUser, IToUser } from "@calcom/features/availability/lib/getUserAvailability";
|
||||
import type { TimeRange } from "@calcom/types/schedule";
|
||||
|
||||
import type { BorderColor } from "./common";
|
||||
import type { CalendarEvent } from "./events";
|
||||
|
||||
@@ -158,6 +157,11 @@ export type CalendarState = {
|
||||
* Selected booking UID to highlight the corresponding event
|
||||
*/
|
||||
selectedBookingUid?: string | null;
|
||||
/**
|
||||
* Update the current time indicator when the page is refocused
|
||||
* @default false
|
||||
*/
|
||||
updateCurrentTimeOnFocus?: boolean;
|
||||
};
|
||||
|
||||
export type CalendarComponentProps = CalendarPublicActions & CalendarState & { isPending?: boolean };
|
||||
|
||||
Reference in New Issue
Block a user