Files
calendar/packages/features/calendars/weeklyview/components/DateValues/index.tsx
T
Eunjae LeeandGitHub 3986d61f40 feat(bookings): improve bookings redesign (#25251)
* use booking.uid instead of booking.id for url param

* show timezone on calendar

* fix type

* restore horizontal tab and remove header and subtitle

* clean up sidebar items

* fix event propagation from attendees

* fetch all statuses except for cancelled on calendar view

* clean up styles of the badges on BookingListItem

* fix useMediaQuery

* add close button to the header

* add assignment reason to the details sheet

* use separator row

* use ToggleGroup for the top bookings tab

* move ViewToggleButton

* resize the action button

* remove wrong prop

* fix type error

* fix type error

* hide view toggle button on mobile (and fix the breakpoint)

* remove unused e2e tests

* fix e2e tests

* hide toggle button when feature flag is off

* update skeleton

* improve attendees on booking list item and slide over

* improve attendee dropdown

* fix type error

* move query to containers

* select attendee email

* infinite fetching for calendar view

* update styles

* fix compatibility

* fix: add backward compatibility for status field in getAllUserBookings

* increase calendar height

* fix type error

* support Member filter only for admin / owners

* add debug log (TEMP)

* add event border color

* show Reject / Accept buttons on BookingDetailsSheet

* move description section to the top

* update When section

* update style of Who section

* add CancelBookingDialog WIP

* fix CancelBookingDialog

* increase clickable area

* add schedule info section WIP

* fix flaky reject button

* fixing reschedule info WIP

* add fromReschedule index to Booking

* improve rescheduled information

* improve reassignment

* fix type error

* fix unit test

* respect user's weekStart value on the booking calendar view

* update debug log

* improve payment section

* clean up

* fix log message

* reposition filters on list view

* fix bookings controller api2 e2e test

* clean up file by extracting logic into custom hooks

* rename files

* merge BookingCalendar into its container

* extract logic into separate hook files

* remove redundant logic

* rearrange items on calendar view

* add WeekPicker

* extract filter button

* responsive header on list view

* horizontal scroll for ToggleGroup WIP

* fix type error

* fix cancelling recurring event

* address feedback

* fix e2e tests

* fix unit test

* fix e2e tests

* make hover style more visible for ToggleGroup

* fix margin on CancelBookingDialog

* update styles on the slide over (mostly font weight)

* update style of CancelBookingDialog

* update styles

* update margin top for the header

* refactor getBookingDetails handler

* fix gap in who section

* auto-filter the current user on the calendar view

* calculate calendar height considering top banners

* improve booking details sheet interaction without overlay

* update calendar event styles

* update reject dialog style

* put uid first in the query params

* fix class name

* memoize functions in useMediaQuery

* query attendee with id instead of email

* update margins

* replace TRPCError with ErrorWithCode

* move calculation outside loop

* remove dead code
2025-12-10 13:40:04 +00:00

116 lines
3.9 KiB
TypeScript

import React from "react";
import dayjs from "@calcom/dayjs";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import classNames from "@calcom/ui/classNames";
import { useCalendarStore } from "../../state/store";
import type { BorderColor } from "../../types/common";
type Props = {
showBorder: boolean;
borderColor: BorderColor;
days: dayjs.Dayjs[];
containerNavRef: React.RefObject<HTMLDivElement>;
};
export function DateValues({ showBorder, borderColor, days, containerNavRef }: Props) {
const { i18n } = useLocale();
const timezone = useCalendarStore((state) => state.timezone);
const showTimezone = useCalendarStore((state) => state.showTimezone ?? false);
const formatDate = (date: dayjs.Dayjs): string => {
return new Intl.DateTimeFormat(i18n.language, { weekday: "short" }).format(date.toDate());
};
const getTimezoneDisplay = () => {
if (!showTimezone || !timezone) return null;
try {
const timeRaw = dayjs().tz(timezone);
const utcOffsetInMinutes = timeRaw.utcOffset();
// Convert offset to decimal hours
const offsetInHours = Math.abs(utcOffsetInMinutes / 60);
const sign = utcOffsetInMinutes < 0 ? "-" : "+";
// If offset is 0, just return "GMT"
if (utcOffsetInMinutes === 0) {
return "GMT";
}
// Format as decimal (e.g., 1.5 for 1:30, 1 for 1:00)
const offsetFormatted = `${sign}${offsetInHours}`;
return `GMT ${offsetFormatted}`;
} catch {
// Fallback to showing the timezone name if formatting fails
return timezone.split("/").pop()?.replace(/_/g, " ") || timezone;
}
};
return (
<div
ref={containerNavRef}
className={classNames(
"bg-default dark:bg-cal-muted top-(--calendar-dates-sticky-offset,0px) z-80 sticky flex-none border-b",
borderColor === "subtle" ? "border-b-subtle" : "border-b-default",
showBorder && (borderColor === "subtle" ? "border-r-subtle border-r" : "border-r-default border-r")
)}>
<div className="text-subtle flex leading-6 sm:hidden" data-dayslength={days.length}>
{days.map((day) => {
const isToday = dayjs().isSame(day, "day");
return (
<button
key={day.toString()}
type="button"
className="flex flex-1 flex-col items-center pb-3 pt-2">
{day.format("dd")}{" "}
<span
className={classNames(
"text-emphasis mt-1 flex h-8 w-8 items-center justify-center font-medium",
isToday && "bg-inverted text-inverted rounded-sm"
)}>
{day.format("D")}
</span>
</button>
);
})}
</div>
<div className="text-subtle -mr-px hidden auto-cols-fr leading-6 sm:flex">
<div
className={classNames(
"col-end-1 flex w-16 items-center justify-center",
showBorder &&
(borderColor === "subtle" ? "border-l-subtle border-l" : "border-l-default border-l")
)}>
{showTimezone && timezone && (
<span className="text-muted text-xs font-medium">{getTimezoneDisplay()}</span>
)}
</div>
{days.map((day) => {
const isToday = dayjs().isSame(day, "day");
return (
<div
key={day.toString()}
className={classNames(
"flex flex-1 items-center justify-center py-3 text-xs font-medium uppercase",
isToday && "text-default"
)}>
<span>
{formatDate(day)}{" "}
<span
className={classNames(
"items-center justify-center p-1",
isToday && "bg-brand-default text-brand ml-1 rounded-md"
)}>
{day.format("DD")}
</span>
</span>
</div>
);
})}
</div>
</div>
);
}