fix: keep dialog state by decoupling it from list (#24914)

Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
This commit is contained in:
Rodrigo EhlersandUdit Takkar authored and GitHub committed 2025-11-06 13:37:26 +05:30
1 parent c741d8133e
commit c6ab6b3d13
4 files changed
+94 -61

No files matched your search

@@ -1,6 +1,6 @@
import { _generateMetadata } from "app/_utils";
import OutOfOfficeEntriesList from "@calcom/features/settings/outOfOffice/OutOfOfficeEntriesList";
import OutOfOfficeView from "~/settings/my-account/out-of-office-view";
export const generateMetadata = async () =>
await _generateMetadata(
@@ -12,7 +12,7 @@ export const generateMetadata = async () =>
);
const Page = () => {
return <OutOfOfficeEntriesList />;
return <OutOfOfficeView />;
};
export default Page;
@@ -0,0 +1,56 @@
"use client";
import { useEffect, useState } from "react";
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
import OutOfOfficeEntriesList from "@calcom/features/settings/outOfOffice/OutOfOfficeEntriesList";
import { CreateOrEditOutOfOfficeEntryModal } from "@calcom/features/settings/outOfOffice/CreateOrEditOutOfOfficeModal";
import type { BookingRedirectForm } from "@calcom/features/settings/outOfOffice/CreateOrEditOutOfOfficeModal";
export default function OutOfOfficeView() {
const [openModal, setOpenModal] = useState(false);
const [currentlyEditingOutOfOfficeEntry, setCurrentlyEditingOutOfOfficeEntry] =
useState<BookingRedirectForm | null>(null);
const params = useCompatSearchParams();
const openModalOnStart = !!params?.get("om");
useEffect(() => {
if (openModalOnStart) {
setOpenModal(true);
}
}, [openModalOnStart]);
const handleOpenCreateDialog = () => {
setCurrentlyEditingOutOfOfficeEntry(null);
setOpenModal(true);
};
const handleOpenEditDialog = (entry: BookingRedirectForm) => {
setCurrentlyEditingOutOfOfficeEntry(entry);
setOpenModal(true);
};
const handleCloseModal = () => {
setOpenModal(false);
setCurrentlyEditingOutOfOfficeEntry(null);
};
return (
<>
<OutOfOfficeEntriesList
onOpenCreateDialog={handleOpenCreateDialog}
onOpenEditDialog={handleOpenEditDialog}
/>
{openModal && (
<CreateOrEditOutOfOfficeEntryModal
openModal={openModal}
closeModal={handleCloseModal}
currentlyEditingOutOfOfficeEntry={currentlyEditingOutOfOfficeEntry}
/>
)}
</>
);
}
@@ -1,7 +1,5 @@
"use client";
import { useState, useEffect } from "react";
import { checkAdminOrOwner } from "@calcom/features/auth/lib/checkAdminOrOwner";
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -10,14 +8,15 @@ import useMeQuery from "@calcom/trpc/react/hooks/useMeQuery";
import type { ButtonProps } from "@calcom/ui/components/button";
import { Button } from "@calcom/ui/components/button";
import { CreateOrEditOutOfOfficeEntryModal } from "./CreateOrEditOutOfOfficeModal";
import { OutOfOfficeTab } from "./OutOfOfficeToggleGroup";
const CreateNewOutOfOfficeEntry = ({
const CreateNewOutOfOfficeEntryButton = ({
size,
onClick,
...rest
}: {
size?: ButtonProps["size"];
onClick: () => void;
"data-testid"?: string;
}) => {
const { t } = useLocale();
@@ -27,39 +26,20 @@ const CreateNewOutOfOfficeEntry = ({
const hasTeamOOOAdminAccess = isOrgAdminOrOwner || me?.data?.isTeamAdminOrOwner;
const params = useCompatSearchParams();
const openModalOnStart = !!params?.get("om");
useEffect(() => {
if (openModalOnStart) {
setOpenModal(true);
}
}, [openModalOnStart]);
const [openModal, setOpenModal] = useState(false);
const selectedTab = params?.get("type") ?? OutOfOfficeTab.MINE;
return (
<>
<Button
color="primary"
size={size ?? "base"}
className="flex items-center justify-between px-4"
StartIcon="plus"
onClick={() => setOpenModal(true)}
data-testid={rest["data-testid"]}
disabled={selectedTab === OutOfOfficeTab.TEAM && !hasTeamOOOAdminAccess}>
{t("add")}
</Button>
{openModal && (
<CreateOrEditOutOfOfficeEntryModal
openModal={openModal}
closeModal={() => {
setOpenModal(false);
}}
currentlyEditingOutOfOfficeEntry={null}
/>
)}
</>
<Button
color="primary"
size={size ?? "base"}
className="flex items-center justify-between px-4"
StartIcon="plus"
onClick={onClick}
data-testid={rest["data-testid"]}
disabled={selectedTab === OutOfOfficeTab.TEAM && !hasTeamOOOAdminAccess}>
{t("add")}
</Button>
);
};
export default CreateNewOutOfOfficeEntry;
export default CreateNewOutOfOfficeEntryButton;
@@ -38,7 +38,6 @@ import { showToast } from "@calcom/ui/components/toast";
import { Tooltip } from "@calcom/ui/components/tooltip";
import CreateNewOutOfOfficeEntryButton from "./CreateNewOutOfOfficeEntryButton";
import { CreateOrEditOutOfOfficeEntryModal } from "./CreateOrEditOutOfOfficeModal";
import type { BookingRedirectForm } from "./CreateOrEditOutOfOfficeModal";
import { OutOfOfficeTab, OutOfOfficeToggleGroup } from "./OutOfOfficeToggleGroup";
@@ -63,7 +62,13 @@ interface OutOfOfficeEntry {
canEditAndDelete: boolean;
}
export default function OutOfOfficeEntriesList() {
export default function OutOfOfficeEntriesList({
onOpenCreateDialog,
onOpenEditDialog,
}: {
onOpenCreateDialog: () => void;
onOpenEditDialog: (entry: BookingRedirectForm) => void;
}) {
const { t } = useLocale();
const pathname = usePathname();
@@ -76,27 +81,29 @@ export default function OutOfOfficeEntriesList() {
CTA={
<div className="flex gap-2">
<OutOfOfficeToggleGroup />
<CreateNewOutOfOfficeEntryButton data-testid="add_entry_ooo" />
<CreateNewOutOfOfficeEntryButton data-testid="add_entry_ooo" onClick={onOpenCreateDialog} />
</div>
}>
<DataTableProvider tableIdentifier={pathname} useSegments={useSegments}>
<OutOfOfficeEntriesListContent />
<OutOfOfficeEntriesListContent
onOpenCreateDialog={onOpenCreateDialog}
onOpenEditDialog={onOpenEditDialog}
/>
</DataTableProvider>
</SettingsHeader>
);
}
function OutOfOfficeEntriesListContent() {
function OutOfOfficeEntriesListContent({
onOpenCreateDialog,
onOpenEditDialog,
}: {
onOpenCreateDialog: () => void;
onOpenEditDialog: (entry: BookingRedirectForm) => void;
}) {
const { t } = useLocale();
const tableContainerRef = useRef<HTMLDivElement>(null);
const [deletedEntry, setDeletedEntry] = useState(0);
const [currentlyEditingOutOfOfficeEntry, setCurrentlyEditingOutOfOfficeEntry] =
useState<BookingRedirectForm | null>(null);
const [openModal, setOpenModal] = useState(false);
const editOutOfOfficeEntry = (entry: BookingRedirectForm) => {
setCurrentlyEditingOutOfOfficeEntry(entry);
setOpenModal(true);
};
const { searchTerm } = useDataTable();
const searchParams = useCompatSearchParams();
@@ -288,7 +295,7 @@ function OutOfOfficeEntriesListContent() {
forUserAvatar: item.user?.avatarUrl,
toUserName: item.toUser?.name || item.toUser?.username,
};
editOutOfOfficeEntry(outOfOfficeEntryData);
onOpenEditDialog(outOfOfficeEntryData);
}}
disabled={isPending || isFetching || !item.canEditAndDelete}
/>
@@ -324,7 +331,7 @@ function OutOfOfficeEntriesListContent() {
},
}),
];
}, [selectedTab, isPending, isFetching]);
}, [selectedTab, isPending, isFetching, onOpenEditDialog, t]);
const table = useReactTable({
data: flatData,
@@ -385,7 +392,7 @@ function OutOfOfficeEntriesListContent() {
? t("ooo_team_empty_description")
: t("ooo_empty_description")
}
buttonRaw={<CreateNewOutOfOfficeEntryButton size="sm" />}
buttonRaw={<CreateNewOutOfOfficeEntryButton size="sm" onClick={onOpenCreateDialog} />}
customIcon={
<div className="mt-4 h-[102px]">
<div className="flex h-full flex-col items-center justify-center p-2 md:mt-0 md:p-0">
@@ -410,16 +417,6 @@ function OutOfOfficeEntriesListContent() {
/>
}
/>
{openModal && (
<CreateOrEditOutOfOfficeEntryModal
openModal={openModal}
closeModal={() => {
setOpenModal(false);
setCurrentlyEditingOutOfOfficeEntry(null);
}}
currentlyEditingOutOfOfficeEntry={currentlyEditingOutOfOfficeEntry}
/>
)}
</>
);
}