fix: make delete confirmation consistent across schedules (#26300)

* add delete dialog

* add types
This commit is contained in:
Manas Kenge
2026-01-02 10:54:40 +00:00
committed by GitHub
parent 9d5983d32d
commit 8bc710eb6e
2 changed files with 36 additions and 10 deletions
+2 -1
View File
@@ -121,8 +121,9 @@ test.describe("Availability", () => {
await test.step("Can delete a schedule", async () => {
await page.getByTestId("go-back-button").click();
await page.locator('[data-testid="schedules"] > li').nth(1).getByTestId("schedule-more").click();
await page.locator('[data-testid="delete-schedule"]').click()
await submitAndWaitForResponse(page, "/api/trpc/availability/schedule.delete?batch=1", {
action: () => page.locator('[data-testid="delete-schedule"]').click(),
action: () => page.locator('[data-testid="dialog-confirmation"]').click(),
});
await expect(page.locator('[data-testid="schedules"] > li').nth(1)).toHaveCount(0, { timeout: 0 });
});
@@ -1,12 +1,13 @@
"use client";
import Link from "next/link";
import { Fragment } from "react";
import { Fragment, useState } from "react";
import { availabilityAsString } from "@calcom/lib/availability";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { sortAvailabilityStrings } from "@calcom/lib/weekstart";
import type { RouterOutputs } from "@calcom/trpc/react";
import { Dialog } from "@calcom/features/components/controlled-dialog";
import { Badge } from "@calcom/ui/components/badge";
import { Button } from "@calcom/ui/components/button";
import {
@@ -16,6 +17,7 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from "@calcom/ui/components/dropdown";
import { ConfirmationDialogContent } from "@calcom/ui/components/dialog";
import { Icon } from "@calcom/ui/components/icon";
import { showToast } from "@calcom/ui/components/toast";
@@ -41,6 +43,9 @@ export function ScheduleListItem({
redirectUrl: string;
}) {
const { t, i18n } = useLocale();
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
type AvailabilityItem = (typeof schedule.availability)[number];
return (
<li key={schedule.id}>
@@ -57,17 +62,24 @@ export function ScheduleListItem({
</div>
<p className="text-subtle mt-1">
{schedule.availability
.filter((availability) => !!availability.days.length)
.map((availability) =>
.filter(
(availability: AvailabilityItem) => !!availability.days.length
)
.map((availability: AvailabilityItem) =>
availabilityAsString(availability, {
locale: i18n.language,
hour12: displayOptions?.hour12,
})
)
// sort the availability strings as per user's weekstart (settings)
.sort(sortAvailabilityStrings(i18n.language, displayOptions?.weekStart))
.map((availabilityString, index) => (
<Fragment key={index}>
.sort(
sortAvailabilityStrings(
i18n.language,
displayOptions?.weekStart
)
)
.map((availabilityString: string) => (
<Fragment key={availabilityString}>
{availabilityString}
<br />
</Fragment>
@@ -131,9 +143,7 @@ export function ScheduleListItem({
if (!isDeletable) {
showToast(t("requires_at_least_one_schedule"), "error");
} else {
deleteFunction({
scheduleId: schedule.id,
});
setIsDeleteDialogOpen(true);
}
}}>
{t("delete")}
@@ -141,6 +151,21 @@ export function ScheduleListItem({
</DropdownMenuItem>
</DropdownMenuContent>
</Dropdown>
<Dialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
<ConfirmationDialogContent
variety="danger"
title={t("delete_schedule")}
confirmBtnText={t("delete")}
loadingText={t("delete")}
onConfirm={(e) => {
e.preventDefault();
deleteFunction({
scheduleId: schedule.id,
});
}}>
{t("delete_schedule_description")}
</ConfirmationDialogContent>
</Dialog>
</div>
</li>
);