* Revert #10366: Undoing then redo fix differently * Re-implement defaulting to first day in the month * Update Embed.tsx and DateOverrideInputDialog
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { shallow } from "zustand/shallow";
|
||||
|
||||
import type { Dayjs } from "@calcom/dayjs";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { default as DatePickerComponent } from "@calcom/features/calendars/DatePicker";
|
||||
import { useNonEmptyScheduleDays } from "@calcom/features/schedules";
|
||||
@@ -23,8 +24,13 @@ export const DatePicker = () => {
|
||||
return (
|
||||
<DatePickerComponent
|
||||
isLoading={schedule.isLoading}
|
||||
onChange={(date) => setSelectedDate(date ? date.format("YYYY-MM-DD") : date)}
|
||||
onMonthChange={(date) => setMonth(date.format("YYYY-MM"))}
|
||||
onChange={(date: Dayjs | null) => {
|
||||
setSelectedDate(date === null ? date : date.format("YYYY-MM-DD"));
|
||||
}}
|
||||
onMonthChange={(date: Dayjs) => {
|
||||
setMonth(date.format("YYYY-MM"));
|
||||
setSelectedDate(date.format("YYYY-MM-DD"));
|
||||
}}
|
||||
includedDates={nonEmptyScheduleDays}
|
||||
locale={i18n.language}
|
||||
browsingDate={month ? dayjs(month) : undefined}
|
||||
|
||||
@@ -154,14 +154,19 @@ export const useBookerStore = create<BookerStore>((set, get) => ({
|
||||
},
|
||||
selectedDate: getQueryParam("date") || null,
|
||||
setSelectedDate: (selectedDate: string | null) => {
|
||||
// unset selected date
|
||||
if (!selectedDate) {
|
||||
removeQueryParam("date");
|
||||
return;
|
||||
}
|
||||
|
||||
const currentSelection = dayjs(get().selectedDate);
|
||||
const newSelection = dayjs(selectedDate);
|
||||
set({ selectedDate });
|
||||
updateQueryParam("date", selectedDate ?? "");
|
||||
|
||||
// Setting month make sure small calendar in fullscreen layouts also updates.
|
||||
// If selectedDate is null, prevents setting month to Invalid-Date
|
||||
if (selectedDate && newSelection.month() !== currentSelection.month()) {
|
||||
if (newSelection.month() !== currentSelection.month()) {
|
||||
set({ month: newSelection.format("YYYY-MM") });
|
||||
updateQueryParam("month", newSelection.format("YYYY-MM"));
|
||||
}
|
||||
@@ -194,6 +199,7 @@ export const useBookerStore = create<BookerStore>((set, get) => ({
|
||||
setMonth: (month: string | null) => {
|
||||
set({ month, selectedTimeslot: null });
|
||||
updateQueryParam("month", month ?? "");
|
||||
get().setSelectedDate(null);
|
||||
},
|
||||
isTeamEvent: false,
|
||||
seatedEventData: {
|
||||
|
||||
@@ -30,7 +30,7 @@ export type DatePickerProps = {
|
||||
/** Defaults to [], which dates are not bookable. Array of valid dates like: ["2022-04-23", "2022-04-24"] */
|
||||
excludedDates?: string[];
|
||||
/** defaults to all, which dates are bookable (inverse of excludedDates) */
|
||||
includedDates?: string[] | null;
|
||||
includedDates?: string[];
|
||||
/** allows adding classes to the container */
|
||||
className?: string;
|
||||
/** Shows a small loading spinner next to the month name */
|
||||
@@ -100,6 +100,40 @@ const NoAvailabilityOverlay = ({
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes care of selecting a valid date in the month if the selected date is not available in the month
|
||||
*/
|
||||
const useHandleInitialDateSelection = ({
|
||||
daysToRenderForTheMonth,
|
||||
selected,
|
||||
onChange,
|
||||
}: {
|
||||
daysToRenderForTheMonth: { day: Dayjs | null; disabled: boolean }[];
|
||||
selected: Dayjs | Dayjs[] | null | undefined;
|
||||
onChange: (date: Dayjs | null) => void;
|
||||
}) => {
|
||||
// Let's not do something for now in case of multiple selected dates as behaviour is unclear and it's not needed at the moment
|
||||
if (selected instanceof Array) {
|
||||
return;
|
||||
}
|
||||
const firstAvailableDateOfTheMonth = daysToRenderForTheMonth.find((day) => !day.disabled)?.day;
|
||||
|
||||
const isSelectedDateAvailable = selected
|
||||
? daysToRenderForTheMonth.some(({ day, disabled }) => {
|
||||
if (day && yyyymmdd(day) === yyyymmdd(selected) && !disabled) return true;
|
||||
})
|
||||
: false;
|
||||
|
||||
if (!isSelectedDateAvailable && firstAvailableDateOfTheMonth) {
|
||||
// If selected date not available in the month, select the first available date of the month
|
||||
onChange(firstAvailableDateOfTheMonth);
|
||||
}
|
||||
|
||||
if (!firstAvailableDateOfTheMonth) {
|
||||
onChange(null);
|
||||
}
|
||||
};
|
||||
|
||||
const Days = ({
|
||||
minDate = dayjs.utc(),
|
||||
excludedDates = [],
|
||||
@@ -121,7 +155,7 @@ const Days = ({
|
||||
// Create placeholder elements for empty days in first week
|
||||
const weekdayOfFirst = browsingDate.date(1).day();
|
||||
const currentDate = minDate.utcOffset(browsingDate.utcOffset());
|
||||
const availableDates = (includedDates: string[] | undefined | null) => {
|
||||
const availableDates = (includedDates: string[] | undefined) => {
|
||||
const dates = [];
|
||||
const lastDateOfMonth = browsingDate.date(daysInMonth(browsingDate));
|
||||
for (
|
||||
@@ -148,21 +182,6 @@ const Days = ({
|
||||
days.push(date);
|
||||
}
|
||||
|
||||
const daysToRenderForTheMonth = days.map((day) => {
|
||||
if (!day) return { day: null, disabled: true };
|
||||
return {
|
||||
day: day,
|
||||
disabled:
|
||||
(includedDates && !includedDates.includes(yyyymmdd(day))) || excludedDates.includes(yyyymmdd(day)),
|
||||
};
|
||||
});
|
||||
|
||||
useHandleInitialDateSelection({
|
||||
daysToRenderForTheMonth,
|
||||
selected,
|
||||
onChange: props.onChange,
|
||||
});
|
||||
|
||||
const [selectedDatesAndTimes] = useBookerStore((state) => [state.selectedDatesAndTimes], shallow);
|
||||
|
||||
const isActive = (day: dayjs.Dayjs) => {
|
||||
@@ -190,6 +209,21 @@ const Days = ({
|
||||
return false;
|
||||
};
|
||||
|
||||
const daysToRenderForTheMonth = days.map((day) => {
|
||||
if (!day) return { day: null, disabled: true };
|
||||
return {
|
||||
day: day,
|
||||
disabled:
|
||||
(includedDates && !includedDates.includes(yyyymmdd(day))) || excludedDates.includes(yyyymmdd(day)),
|
||||
};
|
||||
});
|
||||
|
||||
useHandleInitialDateSelection({
|
||||
daysToRenderForTheMonth,
|
||||
selected,
|
||||
onChange: props.onChange,
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{daysToRenderForTheMonth.map(({ day, disabled }, idx) => (
|
||||
@@ -305,41 +339,4 @@ const DatePicker = ({
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes care of selecting a valid date in the month if the selected date is not available in the month
|
||||
*/
|
||||
const useHandleInitialDateSelection = ({
|
||||
daysToRenderForTheMonth,
|
||||
selected,
|
||||
onChange,
|
||||
}: {
|
||||
daysToRenderForTheMonth: { day: Dayjs | null; disabled: boolean }[];
|
||||
selected: Dayjs | Dayjs[] | null | undefined;
|
||||
onChange: (date: Dayjs | null) => void;
|
||||
}) => {
|
||||
// Let's not do something for now in case of multiple selected dates as behaviour is unclear and it's not needed at the moment
|
||||
if (selected instanceof Array) {
|
||||
return;
|
||||
}
|
||||
const firstAvailableDateOfTheMonth = daysToRenderForTheMonth.find((day) => !day.disabled)?.day;
|
||||
|
||||
const isSelectedDateAvailable = selected
|
||||
? daysToRenderForTheMonth.some(({ day, disabled }) => {
|
||||
if (day && yyyymmdd(day) === yyyymmdd(selected) && !disabled) return true;
|
||||
})
|
||||
: false;
|
||||
|
||||
if (firstAvailableDateOfTheMonth) {
|
||||
// If selected date not available in the month, select the first available date of the month
|
||||
if (!isSelectedDateAvailable) {
|
||||
onChange(firstAvailableDateOfTheMonth);
|
||||
}
|
||||
} else {
|
||||
// No date is available and if we were asked to select something inform that it couldn't be selected. This would actually help in not showing the timeslots section(with No Time Available) when no date in the month is available
|
||||
if (selected) {
|
||||
onChange(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default DatePicker;
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { ControlProps } from "react-select";
|
||||
import { components } from "react-select";
|
||||
import { shallow } from "zustand/shallow";
|
||||
|
||||
import type { Dayjs } from "@calcom/dayjs";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { AvailableTimes } from "@calcom/features/bookings";
|
||||
import { useBookerStore, useInitializeBookerStore } from "@calcom/features/bookings/Booker/store";
|
||||
@@ -223,21 +224,27 @@ const EmailEmbed = ({ eventType, username }: { eventType?: EventType; username:
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<div className="mb-[9px] font-medium">
|
||||
<div className="text-default text-sm">{t("select_date")}</div>
|
||||
<DatePicker
|
||||
isLoading={schedule.isLoading}
|
||||
onChange={(date) => setSelectedDate(date ? date.format("YYYY-MM-DD") : date)}
|
||||
onMonthChange={(date) => {
|
||||
setMonth(date.format("YYYY-MM"));
|
||||
setSelectedDate(date.format("YYYY-MM-DD"));
|
||||
}}
|
||||
includedDates={nonEmptyScheduleDays}
|
||||
locale={i18n.language}
|
||||
browsingDate={month ? dayjs(month) : undefined}
|
||||
selected={dayjs(selectedDate)}
|
||||
weekStart={weekdayToWeekIndex(event?.data?.users?.[0]?.weekStart)}
|
||||
eventSlug={eventType?.slug}
|
||||
/>
|
||||
<Collapsible open>
|
||||
<CollapsibleContent>
|
||||
<div className="text-default text-sm">{t("select_date")}</div>
|
||||
<DatePicker
|
||||
isLoading={schedule.isLoading}
|
||||
onChange={(date: Dayjs | null) => {
|
||||
setSelectedDate(date === null ? date : date.format("YYYY-MM-DD"));
|
||||
}}
|
||||
onMonthChange={(date: Dayjs) => {
|
||||
setMonth(date.format("YYYY-MM"));
|
||||
setSelectedDate(date.format("YYYY-MM-DD"));
|
||||
}}
|
||||
includedDates={nonEmptyScheduleDays}
|
||||
locale={i18n.language}
|
||||
browsingDate={month ? dayjs(month) : undefined}
|
||||
selected={dayjs(selectedDate)}
|
||||
weekStart={weekdayToWeekIndex(event?.data?.users?.[0]?.weekStart)}
|
||||
eventSlug={eventType?.slug}
|
||||
/>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
</div>
|
||||
{selectedDate ? (
|
||||
<div className="mt-[9px] font-medium ">
|
||||
|
||||
@@ -51,11 +51,7 @@ const DateOverrideForm = ({
|
||||
|
||||
const [selectedDates, setSelectedDates] = useState<Dayjs[]>(value ? [dayjs.utc(value[0].start)] : []);
|
||||
|
||||
const onDateChange = (newDate: Dayjs | null) => {
|
||||
// If no date is selected, do nothing
|
||||
if (!newDate) {
|
||||
return;
|
||||
}
|
||||
const onDateChange = (newDate: Dayjs) => {
|
||||
// If clicking on a selected date unselect it
|
||||
if (selectedDates.some((date) => yyyymmdd(date) === yyyymmdd(newDate))) {
|
||||
setSelectedDates(selectedDates.filter((date) => yyyymmdd(date) !== yyyymmdd(newDate)));
|
||||
@@ -154,7 +150,9 @@ const DateOverrideForm = ({
|
||||
excludedDates={excludedDates}
|
||||
weekStart={0}
|
||||
selected={selectedDates}
|
||||
onChange={(day) => onDateChange(day)}
|
||||
onChange={(day) => {
|
||||
if (day) onDateChange(day);
|
||||
}}
|
||||
onMonthChange={(newMonth) => {
|
||||
setBrowsingDate(newMonth);
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user