Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Provide event rescheduling option before the event end time #15150

Merged
merged 12 commits into from
Jun 28, 2024
28 changes: 17 additions & 11 deletions apps/web/modules/bookings/views/bookings-single-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ export default function Success(props: PageProps) {
function getTitle(): string {
const titleSuffix = props.recurringBookings ? "_recurring" : "";
const titlePrefix = isRoundRobin ? "round_robin_" : "";
if (isCancelled) {
if (isCancelled || isBookingInPast) {
return "";
}
if (needsConfirmation) {
Expand Down Expand Up @@ -340,6 +340,8 @@ export default function Success(props: PageProps) {

const providerName = guessEventLocationType(location)?.label;
const rescheduleProviderName = guessEventLocationType(rescheduleLocation)?.label;
const isBookingInPast = new Date(bookingInfo.endTime) < new Date();
const isReschedulable = !isCancelled && !isBookingInPast;

const bookingCancelledEventProps = {
booking: bookingInfo,
Expand Down Expand Up @@ -412,7 +414,7 @@ export default function Success(props: PageProps) {
imageSrc={`${bookingInfo.user.avatarUrl}`}
/>
)}
{giphyImage && !needsConfirmation && !isCancelled && (
{giphyImage && !needsConfirmation && isReschedulable && (
// eslint-disable-next-line @next/next/no-img-element
<img src={giphyImage} className="w-full rounded-lg" alt="Gif from Giphy" />
)}
Expand All @@ -421,32 +423,36 @@ export default function Success(props: PageProps) {
"mx-auto flex h-12 w-12 items-center justify-center rounded-full",
isRoundRobin &&
"border-cal-bg dark:border-cal-bg-muted absolute bottom-0 right-0 z-10 h-12 w-12 border-8",
!giphyImage && !isCancelled && !needsConfirmation ? "bg-success" : "",
!giphyImage && !isCancelled && needsConfirmation ? "bg-subtle" : "",
isCancelled ? "bg-error" : ""
!giphyImage && isReschedulable && !needsConfirmation ? "bg-success" : "",
!giphyImage && isReschedulable && needsConfirmation ? "bg-subtle" : "",
isCancelled || isBookingInPast ? "bg-error" : ""
)}>
{!giphyImage && !needsConfirmation && !isCancelled && (
{!giphyImage && !needsConfirmation && isReschedulable && (
<Icon name="check" className="h-5 w-5 text-green-600 dark:text-green-400" />
)}
{needsConfirmation && !isCancelled && (
{needsConfirmation && isReschedulable && (
<Icon name="calendar" className="text-emphasis h-5 w-5" />
)}
{isCancelled && <Icon name="x" className="h-5 w-5 text-red-600 dark:text-red-200" />}
{(isCancelled || isBookingInPast) && (
<Icon name="x" className="h-5 w-5 text-red-600 dark:text-red-200" />
)}
</div>
</div>
<div className="mb-8 mt-6 text-center last:mb-0">
<h3
className="text-emphasis text-2xl font-semibold leading-6"
data-testid={isCancelled ? "cancelled-headline" : ""}
id="modal-headline">
{needsConfirmation && !isCancelled
{needsConfirmation && isReschedulable
? props.recurringBookings
? t("booking_submitted_recurring")
: t("booking_submitted")
: isCancelled
? seatReferenceUid
? t("no_longer_attending")
: t("event_cancelled")
: isBookingInPast
? t("event_expired")
: props.recurringBookings
? t("meeting_is_scheduled_recurring")
: t("meeting_is_scheduled")}
Expand Down Expand Up @@ -650,7 +656,7 @@ export default function Success(props: PageProps) {
)}
{!requiresLoginToUpdate &&
(!needsConfirmation || !userIsOwner) &&
!isCancelled &&
isReschedulable &&
(!isCancellationMode ? (
<>
<hr className="border-subtle mb-8" />
Expand Down Expand Up @@ -708,7 +714,7 @@ export default function Success(props: PageProps) {
{userIsOwner &&
!needsConfirmation &&
!isCancellationMode &&
!isCancelled &&
isReschedulable &&
!!calculatedDuration && (
<>
<hr className="border-subtle mt-8" />
Expand Down
2 changes: 2 additions & 0 deletions apps/web/public/static/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -2481,5 +2481,7 @@
"USER_PENDING_MEMBER_OF_THE_ORG": "User is a pending member of the organization",
"USER_ALREADY_INVITED_OR_MEMBER": "User is already invited or a member",
"USER_MEMBER_OF_OTHER_ORGANIZATION": "User is member of an organization that this team is not a part of.",
"rescheduling_not_possible": "Rescheduling is not possible as the event has expired",
"event_expired": "This event is expired",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
27 changes: 24 additions & 3 deletions packages/features/calendars/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,16 @@ const NoAvailabilityOverlay = ({
);
};

const ReschedulingNotPossibleOverlay = () => {
const { t } = useLocale();

return (
<div className="bg-muted border-subtle absolute left-1/2 top-40 -mt-10 w-2/3 -translate-x-1/2 -translate-y-1/2 transform break-all rounded-md border p-8 shadow-sm">
<h4 className="text-emphasis font-medium">{t("rescheduling_not_possible")}</h4>
</div>
);
};

const Days = ({
minDate,
excludedDates = [],
Expand All @@ -141,6 +151,7 @@ const Days = ({
eventSlug,
slots,
customClassName,
isBookingInPast,
...props
}: Omit<DatePickerProps, "locale" | "className" | "weekStart"> & {
DayComponent?: React.FC<React.ComponentProps<typeof Day>>;
Expand All @@ -153,6 +164,7 @@ const Days = ({
datePickerDateActive?: string;
};
scrollToTimeSlots?: () => void;
isBookingInPast: boolean;
}) => {
// Create placeholder elements for empty days in first week
const weekdayOfFirst = browsingDate.date(1).day();
Expand Down Expand Up @@ -279,7 +291,9 @@ const Days = ({
</div>
))}

{!props.isPending && includedDates && includedDates?.length === 0 && (
{isBookingInPast && <ReschedulingNotPossibleOverlay />}

{!props.isPending && !isBookingInPast && includedDates && includedDates?.length === 0 && (
<NoAvailabilityOverlay month={month} nextMonthButton={nextMonthButton} />
)}
</>
Expand All @@ -294,6 +308,7 @@ const DatePicker = ({
onMonthChange,
slots,
customClassNames,
includedDates,
...passThroughProps
}: DatePickerProps &
Partial<React.ComponentProps<typeof Days>> & {
Expand All @@ -308,6 +323,8 @@ const DatePicker = ({
}) => {
const browsingDate = passThroughProps.browsingDate || dayjs().startOf("month");
const { i18n } = useLocale();
const bookingData = useBookerStore((state) => state.bookingData);
const isBookingInPast = bookingData ? new Date(bookingData.endTime) < new Date() : false;

const changeMonth = (newMonth: number) => {
if (onMonthChange) {
Expand Down Expand Up @@ -357,11 +374,13 @@ const DatePicker = ({
<Button
className={classNames(
`group p-1 opacity-70 transition hover:opacity-100 rtl:rotate-180`,
isBookingInPast && `disabled:text-bookinglighter hover:bg-background hover:opacity-70`,
`${customClassNames?.datePickerToggle}`
)}
onClick={() => changeMonth(+1)}
data-testid="incrementMonth"
color="minimal"
disabled={isBookingInPast}
variant="icon"
StartIcon="chevron-right"
/>
Expand All @@ -387,12 +406,14 @@ const DatePicker = ({
datePickerDateActive: customClassNames?.datePickerDatesActive,
}}
weekStart={weekStart}
selected={selected}
selected={!isBookingInPast ? selected : null}
{...passThroughProps}
browsingDate={browsingDate}
month={month}
nextMonthButton={() => changeMonth(+1)}
slots={slots}
slots={!isBookingInPast ? slots : {}}
includedDates={!isBookingInPast ? includedDates : []}
isBookingInPast={isBookingInPast}
/>
</div>
</div>
Expand Down
Loading