fix: Time Buttons Should be Scroll not the Whole Right Side (#11412)

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
This commit is contained in:
Augusto Miranda Galego 2023-09-19 22:01:26 +02:00 committed by GitHub
parent eccab37607
commit 405a4cc850
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 69 deletions

View File

@ -316,7 +316,7 @@ const BookerComponent = ({
className={classNames( className={classNames(
"border-subtle rtl:border-default flex h-full w-full flex-col overflow-x-auto px-5 py-3 pb-0 rtl:border-r ltr:md:border-l", "border-subtle rtl:border-default flex h-full w-full flex-col overflow-x-auto px-5 py-3 pb-0 rtl:border-r ltr:md:border-l",
layout === BookerLayouts.MONTH_VIEW && layout === BookerLayouts.MONTH_VIEW &&
"scroll-bar h-full overflow-auto md:w-[var(--booker-timeslots-width)]", "h-full overflow-hidden md:w-[var(--booker-timeslots-width)]",
layout !== BookerLayouts.MONTH_VIEW && "sticky top-0" layout !== BookerLayouts.MONTH_VIEW && "sticky top-0"
)} )}
ref={timeslotsRef} ref={timeslotsRef}

View File

@ -10,6 +10,7 @@ import useMediaQuery from "@calcom/lib/hooks/useMediaQuery";
import { BookerLayouts } from "@calcom/prisma/zod-utils"; import { BookerLayouts } from "@calcom/prisma/zod-utils";
import { trpc } from "@calcom/trpc"; import { trpc } from "@calcom/trpc";
import { AvailableTimesHeader } from "../../components/AvailableTimesHeader";
import { useBookerStore } from "../store"; import { useBookerStore } from "../store";
import { useEvent, useScheduleForEvent } from "../utils/event"; import { useEvent, useScheduleForEvent } from "../utils/event";
@ -100,33 +101,47 @@ export const AvailableTimeSlots = ({
}, [containerRef, schedule.isLoading, isEmbed, isMobile]); }, [containerRef, schedule.isLoading, isEmbed, isMobile]);
return ( return (
<div <>
ref={containerRef} <div className="flex">
className={classNames( {schedule.isLoading
limitHeight && "flex-grow md:h-[400px]", ? // Shows exact amount of days as skeleton.
!limitHeight && "flex h-full w-full flex-row gap-4" Array.from({ length: 1 + (extraDays ?? 0) }).map((_, i) => <AvailableTimesSkeleton key={i} />)
)}> : slotsPerDay.length > 0 &&
{schedule.isLoading slotsPerDay.map((slots) => (
? // Shows exact amount of days as skeleton. <AvailableTimesHeader
Array.from({ length: 1 + (extraDays ?? 0) }).map((_, i) => <AvailableTimesSkeleton key={i} />) key={slots.date}
: slotsPerDay.length > 0 && date={dayjs(slots.date)}
slotsPerDay.map((slots) => ( showTimeFormatToggle={!isColumnView}
<AvailableTimes availableMonth={
className="w-full" dayjs(selectedDate).format("MM") !== dayjs(slots.date).format("MM")
key={slots.date} ? dayjs(slots.date).format("MMM")
showTimeFormatToggle={!isColumnView} : undefined
onTimeSelect={onTimeSelect} }
date={dayjs(slots.date)} />
slots={slots.slots} ))}
seatsPerTimeSlot={seatsPerTimeSlot} </div>
showAvailableSeatsCount={showAvailableSeatsCount} <div
availableMonth={ ref={containerRef}
dayjs(selectedDate).format("MM") !== dayjs(slots.date).format("MM") className={classNames(
? dayjs(slots.date).format("MMM") limitHeight && "scroll-bar flex-grow overflow-auto md:h-[400px]",
: undefined !limitHeight && "flex h-full w-full flex-row gap-4"
} )}>
/> {schedule.isLoading
))} ? // Shows exact amount of days as skeleton.
</div> Array.from({ length: 1 + (extraDays ?? 0) }).map((_, i) => <AvailableTimesSkeleton key={i} />)
: slotsPerDay.length > 0 &&
slotsPerDay.map((slots) => (
<AvailableTimes
className="scroll-bar w-full overflow-auto"
key={slots.date}
showTimeFormatToggle={!isColumnView}
onTimeSelect={onTimeSelect}
slots={slots.slots}
seatsPerTimeSlot={seatsPerTimeSlot}
showAvailableSeatsCount={showAvailableSeatsCount}
/>
))}
</div>
</>
); );
}; };

View File

@ -1,22 +1,16 @@
import { CalendarX2 } from "lucide-react"; import { CalendarX2 } from "lucide-react";
import { shallow } from "zustand/shallow";
import type { Dayjs } from "@calcom/dayjs";
import dayjs from "@calcom/dayjs"; import dayjs from "@calcom/dayjs";
import type { Slots } from "@calcom/features/schedules"; import type { Slots } from "@calcom/features/schedules";
import { classNames } from "@calcom/lib"; import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { nameOfDay } from "@calcom/lib/weekday";
import { BookerLayouts } from "@calcom/prisma/zod-utils";
import { Button, SkeletonText } from "@calcom/ui"; import { Button, SkeletonText } from "@calcom/ui";
import { useBookerStore } from "../Booker/store"; import { useBookerStore } from "../Booker/store";
import { useTimePreferences } from "../lib"; import { useTimePreferences } from "../lib";
import { SeatsAvailabilityText } from "./SeatsAvailabilityText"; import { SeatsAvailabilityText } from "./SeatsAvailabilityText";
import { TimeFormatToggle } from "./TimeFormatToggle";
type AvailableTimesProps = { type AvailableTimesProps = {
date: Dayjs;
slots: Slots[string]; slots: Slots[string];
onTimeSelect: ( onTimeSelect: (
time: string, time: string,
@ -28,58 +22,25 @@ type AvailableTimesProps = {
showAvailableSeatsCount?: boolean | null; showAvailableSeatsCount?: boolean | null;
showTimeFormatToggle?: boolean; showTimeFormatToggle?: boolean;
className?: string; className?: string;
availableMonth?: string | undefined;
selectedSlots?: string[]; selectedSlots?: string[];
}; };
export const AvailableTimes = ({ export const AvailableTimes = ({
date,
slots, slots,
onTimeSelect, onTimeSelect,
seatsPerTimeSlot, seatsPerTimeSlot,
showAvailableSeatsCount, showAvailableSeatsCount,
showTimeFormatToggle = true, showTimeFormatToggle = true,
className, className,
availableMonth,
selectedSlots, selectedSlots,
}: AvailableTimesProps) => { }: AvailableTimesProps) => {
const { t, i18n } = useLocale(); const { t, i18n } = useLocale();
const [timeFormat, timezone] = useTimePreferences((state) => [state.timeFormat, state.timezone]); const [timeFormat, timezone] = useTimePreferences((state) => [state.timeFormat, state.timezone]);
const bookingData = useBookerStore((state) => state.bookingData); const bookingData = useBookerStore((state) => state.bookingData);
const hasTimeSlots = !!seatsPerTimeSlot; const hasTimeSlots = !!seatsPerTimeSlot;
const [layout] = useBookerStore((state) => [state.layout], shallow);
const isColumnView = layout === BookerLayouts.COLUMN_VIEW;
const isMonthView = layout === BookerLayouts.MONTH_VIEW;
const isToday = dayjs().isSame(date, "day");
return ( return (
<div className={classNames("text-default flex flex-col", className)}> <div className={classNames("text-default flex flex-col", className)}>
<header className="bg-default before:bg-default dark:bg-muted dark:before:bg-muted mb-3 flex w-full flex-row items-center font-medium">
<span
className={classNames(
isColumnView && "w-full text-center",
isColumnView ? "text-subtle text-xs uppercase" : "text-emphasis font-semibold"
)}>
<span className={classNames(isToday && "!text-default")}>
{nameOfDay(i18n.language, Number(date.format("d")), "short")}
</span>
<span
className={classNames(
isColumnView && isToday && "bg-brand-default text-brand ml-2",
"inline-flex items-center justify-center rounded-3xl px-1 pt-0.5 font-medium",
isMonthView ? "text-default text-sm" : "text-xs"
)}>
{date.format("DD")}
{availableMonth && `, ${availableMonth}`}
</span>
</span>
{showTimeFormatToggle && (
<div className="ml-auto rtl:mr-auto">
<TimeFormatToggle />
</div>
)}
</header>
<div className="h-full pb-4"> <div className="h-full pb-4">
{!slots.length && ( {!slots.length && (
<div className="bg-subtle border-subtle flex h-full flex-col items-center rounded-md border p-6 dark:bg-transparent"> <div className="bg-subtle border-subtle flex h-full flex-col items-center rounded-md border p-6 dark:bg-transparent">

View File

@ -0,0 +1,60 @@
import { shallow } from "zustand/shallow";
import type { Dayjs } from "@calcom/dayjs";
import dayjs from "@calcom/dayjs";
import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { nameOfDay } from "@calcom/lib/weekday";
import { BookerLayouts } from "@calcom/prisma/zod-utils";
import { useBookerStore } from "../Booker/store";
import { TimeFormatToggle } from "./TimeFormatToggle";
type AvailableTimesHeaderProps = {
date: Dayjs;
showTimeFormatToggle?: boolean;
availableMonth?: string | undefined;
};
export const AvailableTimesHeader = ({
date,
showTimeFormatToggle = true,
availableMonth,
}: AvailableTimesHeaderProps) => {
const { t, i18n } = useLocale();
const [layout] = useBookerStore((state) => [state.layout], shallow);
const isColumnView = layout === BookerLayouts.COLUMN_VIEW;
const isMonthView = layout === BookerLayouts.MONTH_VIEW;
const isToday = dayjs().isSame(date, "day");
return (
<header className="bg-default before:bg-default dark:bg-muted dark:before:bg-muted mb-3 flex w-full flex-row items-center font-medium">
<span
className={classNames(
isColumnView && "w-full text-center",
isColumnView ? "text-subtle text-xs uppercase" : "text-emphasis font-semibold"
)}>
<span className={classNames(isToday && "!text-default")}>
{nameOfDay(i18n.language, Number(date.format("d")), "short")}
</span>
<span
className={classNames(
isColumnView && isToday && "bg-brand-default text-brand ml-2",
"inline-flex items-center justify-center rounded-3xl px-1 pt-0.5 font-medium",
isMonthView ? "text-default text-sm" : "text-xs"
)}>
{date.format("DD")}
{availableMonth && `, ${availableMonth}`}
</span>
</span>
{showTimeFormatToggle && (
<div className="ml-auto rtl:mr-auto">
<TimeFormatToggle />
</div>
)}
</header>
);
};

View File

@ -6,3 +6,4 @@ export {
EventTitle, EventTitle,
} from "./components/event-meta"; } from "./components/event-meta";
export { AvailableTimes, AvailableTimesSkeleton } from "./components/AvailableTimes"; export { AvailableTimes, AvailableTimesSkeleton } from "./components/AvailableTimes";
export { AvailableTimesHeader } from "./components/AvailableTimesHeader";

View File

@ -10,6 +10,7 @@ import { shallow } from "zustand/shallow";
import type { Dayjs } from "@calcom/dayjs"; import type { Dayjs } from "@calcom/dayjs";
import dayjs from "@calcom/dayjs"; import dayjs from "@calcom/dayjs";
import { AvailableTimesHeader } from "@calcom/features/bookings";
import { AvailableTimes } from "@calcom/features/bookings"; import { AvailableTimes } from "@calcom/features/bookings";
import { useBookerStore, useInitializeBookerStore } from "@calcom/features/bookings/Booker/store"; import { useBookerStore, useInitializeBookerStore } from "@calcom/features/bookings/Booker/store";
import { useEvent, useScheduleForEvent } from "@calcom/features/bookings/Booker/utils/event"; import { useEvent, useScheduleForEvent } from "@calcom/features/bookings/Booker/utils/event";
@ -248,9 +249,9 @@ const EmailEmbed = ({ eventType, username }: { eventType?: EventType; username:
<div className="mt-[9px] font-medium "> <div className="mt-[9px] font-medium ">
{selectedDate ? ( {selectedDate ? (
<div className="flex h-full w-full flex-row gap-4"> <div className="flex h-full w-full flex-row gap-4">
<AvailableTimesHeader date={dayjs(selectedDate)} />
<AvailableTimes <AvailableTimes
className="w-full" className="w-full"
date={dayjs(selectedDate)}
selectedSlots={ selectedSlots={
eventType.slug && eventType.slug &&
selectedDatesAndTimes && selectedDatesAndTimes &&