"use client"; import type { OptInFeatureConfig } from "@calcom/features/feature-opt-in/config"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Button } from "@coss/ui/components/button"; import { Checkbox } from "@coss/ui/components/checkbox"; import { Dialog, DialogClose, DialogDescription, DialogFooter, DialogHeader, DialogPanel, DialogPopup, DialogTitle, } from "@coss/ui/components/dialog"; import { Label } from "@coss/ui/components/label"; import { Menu, MenuCheckboxItem, MenuPopup, MenuSeparator, MenuTrigger } from "@coss/ui/components/menu"; import { toastManager } from "@coss/ui/components/toast"; import { BuildingIcon, ChevronDownIcon, UserIcon, UsersIcon } from "lucide-react"; import { useRouter } from "next/navigation"; import type { ReactElement } from "react"; import { useState } from "react"; import { FeatureOptInSuccessDialog } from "./FeatureOptInSuccessDialog"; type UserRoleContext = { isOrgAdmin: boolean; orgId: number | null; adminTeamIds: number[]; adminTeamNames: { id: number; name: string }[]; }; export type FeatureOptInMutations = { setUserState: (params: { slug: string; state: "enabled" }) => Promise; setTeamState: (params: { teamId: number; slug: string; state: "enabled" }) => Promise; setOrganizationState: (params: { slug: string; state: "enabled" }) => Promise; setUserAutoOptIn: (params: { autoOptIn: boolean }) => Promise; setTeamAutoOptIn: (params: { teamId: number; autoOptIn: boolean }) => Promise; setOrganizationAutoOptIn: (params: { autoOptIn: boolean }) => Promise; invalidateQueries: () => void; }; type FeatureOptInTrackingData = { enableFor: "user" | "organization" | "teams"; teamCount?: number; autoOptIn: boolean; }; interface FeatureOptInConfirmDialogProps { isOpen: boolean; onClose: () => void; onDismissBanner: () => void; onOptInSuccess?: () => void; featureConfig: OptInFeatureConfig; userRoleContext: UserRoleContext; mutations: FeatureOptInMutations; onTrackFeatureEnabled?: (data: FeatureOptInTrackingData) => void; } export function FeatureOptInConfirmDialog({ isOpen, onClose, onDismissBanner, onOptInSuccess, featureConfig, userRoleContext, mutations, onTrackFeatureEnabled, }: FeatureOptInConfirmDialogProps): ReactElement { const { t } = useLocale(); const router = useRouter(); const { isOrgAdmin, orgId, adminTeamIds, adminTeamNames } = userRoleContext; const hasAdminTeams = adminTeamIds.length > 0; const canEnableForOrg = isOrgAdmin && orgId !== null; const canEnableForTeams = hasAdminTeams; const showSelector = canEnableForOrg || canEnableForTeams; const [enableForUser, setEnableForUser] = useState(true); const [enableForOrg, setEnableForOrg] = useState(false); const [selectedTeamIds, setSelectedTeamIds] = useState([]); const [autoOptIn, setAutoOptIn] = useState(false); const [isSuccess, setIsSuccess] = useState(false); const [shouldInvalidate, setShouldInvalidate] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const hasTeamsSelected = selectedTeamIds.length > 0; const hasAnySelection = enableForUser || enableForOrg || hasTeamsSelected; const getSelectedText = (): string => { const parts: string[] = []; if (enableForUser) parts.push(t("just_for_me")); if (enableForOrg) parts.push(t("entire_organization")); if (hasTeamsSelected) { const teamNames = adminTeamNames .filter((team) => selectedTeamIds.includes(team.id)) .map((team) => team.name); parts.push(...teamNames); } return parts.length > 0 ? parts.join(", ") : t("select"); }; const handleUserChange = (checked: boolean): void => { setEnableForUser(checked); if (checked) { setEnableForOrg(false); setSelectedTeamIds([]); } }; const handleOrgChange = (checked: boolean): void => { setEnableForOrg(checked); if (checked) { setEnableForUser(false); setSelectedTeamIds([]); } }; const handleTeamChange = (teamId: number, checked: boolean): void => { if (checked) { setSelectedTeamIds((prev) => [...prev, teamId]); setEnableForUser(false); setEnableForOrg(false); } else { setSelectedTeamIds((prev) => prev.filter((id) => id !== teamId)); } }; const getAutoOptInText = (): string => { if (enableForOrg) { return t("auto_opt_in_future_features_org"); } if (hasTeamsSelected) { return t("auto_opt_in_future_features_teams"); } return t("auto_opt_in_future_features_user"); }; const handleConfirm = async (): Promise => { setIsSubmitting(true); try { const promises: Promise[] = []; if (enableForOrg && orgId) { promises.push(mutations.setOrganizationState({ slug: featureConfig.slug, state: "enabled" })); if (autoOptIn) { promises.push(mutations.setOrganizationAutoOptIn({ autoOptIn: true })); } } if (hasTeamsSelected) { selectedTeamIds.forEach((teamId) => { promises.push(mutations.setTeamState({ teamId, slug: featureConfig.slug, state: "enabled" })); if (autoOptIn) { promises.push(mutations.setTeamAutoOptIn({ teamId, autoOptIn: true })); } }); } if (enableForUser) { promises.push(mutations.setUserState({ slug: featureConfig.slug, state: "enabled" })); if (autoOptIn) { promises.push(mutations.setUserAutoOptIn({ autoOptIn: true })); } } await Promise.all(promises); const enableFor = enableForOrg ? "organization" : hasTeamsSelected ? "teams" : "user"; onTrackFeatureEnabled?.({ enableFor, teamCount: hasTeamsSelected ? selectedTeamIds.length : undefined, autoOptIn, }); setIsSuccess(true); setShouldInvalidate(true); onOptInSuccess?.(); } catch (_error) { toastManager.add({ title: t("error_enabling_feature"), type: "error" }); } finally { setIsSubmitting(false); } }; const getSettingsRedirectPath = (): string => { if (enableForOrg) { return "/settings/organizations/features"; } if (hasTeamsSelected && selectedTeamIds.length > 0) { return `/settings/teams/${selectedTeamIds[0]}/features`; } return "/settings/my-account/features"; }; const handleViewSettings = (): void => { resetAndClose(); router.push(getSettingsRedirectPath()); }; const handleDismiss = (): void => { resetAndClose(); }; const resetAndClose = (): void => { if (shouldInvalidate) { mutations.invalidateQueries(); setShouldInvalidate(false); } setIsSuccess(false); setEnableForUser(true); setEnableForOrg(false); setSelectedTeamIds([]); setAutoOptIn(false); onClose(); }; if (isSuccess) { return ( ); } return ( {t(featureConfig.i18n.name)} {t(featureConfig.i18n.description)}
{showSelector && (
}> {getSelectedText()} handleUserChange(checked)}> {t("just_for_me")} {canEnableForOrg && ( <> handleOrgChange(checked)}> {t("entire_organization")} )} {canEnableForTeams && adminTeamNames.length > 0 && ( <> {adminTeamNames.map((team) => ( handleTeamChange(team.id, checked)}> {team.name} ))} )}
)}
} onClick={resetAndClose} disabled={isSubmitting}> {t("cancel")}
); } export default FeatureOptInConfirmDialog;