From c6ab6b3d1335dbad15d57ac8dd2d13c184796b37 Mon Sep 17 00:00:00 2001 From: Rodrigo Ehlers Date: Thu, 6 Nov 2025 09:07:26 +0100 Subject: [PATCH] fix: keep dialog state by decoupling it from list (#24914) Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> --- .../my-account/out-of-office/page.tsx | 4 +- .../my-account/out-of-office-view.tsx | 56 +++++++++++++++++++ .../CreateNewOutOfOfficeEntryButton.tsx | 48 +++++----------- .../outOfOffice/OutOfOfficeEntriesList.tsx | 47 ++++++++-------- 4 files changed, 94 insertions(+), 61 deletions(-) create mode 100644 apps/web/modules/settings/my-account/out-of-office-view.tsx diff --git a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/my-account/out-of-office/page.tsx b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/my-account/out-of-office/page.tsx index c80a4bec3c..716eb37ac9 100644 --- a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/my-account/out-of-office/page.tsx +++ b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/my-account/out-of-office/page.tsx @@ -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 ; + return ; }; export default Page; diff --git a/apps/web/modules/settings/my-account/out-of-office-view.tsx b/apps/web/modules/settings/my-account/out-of-office-view.tsx new file mode 100644 index 0000000000..223d96e841 --- /dev/null +++ b/apps/web/modules/settings/my-account/out-of-office-view.tsx @@ -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(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 ( + <> + + {openModal && ( + + )} + + ); +} + diff --git a/packages/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton.tsx b/packages/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton.tsx index 8642cc2419..aeaa8c9cc4 100644 --- a/packages/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton.tsx +++ b/packages/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton.tsx @@ -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 ( - <> - - {openModal && ( - { - setOpenModal(false); - }} - currentlyEditingOutOfOfficeEntry={null} - /> - )} - + ); }; -export default CreateNewOutOfOfficeEntry; +export default CreateNewOutOfOfficeEntryButton; diff --git a/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx b/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx index 6b09200e13..d62c62b218 100644 --- a/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx +++ b/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx @@ -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={
- +
}> - + ); } -function OutOfOfficeEntriesListContent() { +function OutOfOfficeEntriesListContent({ + onOpenCreateDialog, + onOpenEditDialog, +}: { + onOpenCreateDialog: () => void; + onOpenEditDialog: (entry: BookingRedirectForm) => void; +}) { const { t } = useLocale(); const tableContainerRef = useRef(null); const [deletedEntry, setDeletedEntry] = useState(0); - const [currentlyEditingOutOfOfficeEntry, setCurrentlyEditingOutOfOfficeEntry] = - useState(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={} + buttonRaw={} customIcon={
@@ -410,16 +417,6 @@ function OutOfOfficeEntriesListContent() { /> } /> - {openModal && ( - { - setOpenModal(false); - setCurrentlyEditingOutOfOfficeEntry(null); - }} - currentlyEditingOutOfOfficeEntry={currentlyEditingOutOfOfficeEntry} - /> - )} ); }