Cleanup pass 2

This commit is contained in:
adilallo
2026-05-22 13:30:47 -06:00
parent b7c804bac8
commit 753220f97b
76 changed files with 1338 additions and 1020 deletions
@@ -28,6 +28,7 @@ import {
import CustomMethodCardModalBody from "./CustomMethodCardModalBody";
import MethodCardCustomizeModalHeader from "./MethodCardCustomizeModalHeader";
import { buildCustomRuleModalKebabMenu } from "./customRuleModalKebabMenu";
import { useDiscardCustomizeConfirm } from "../hooks/useDiscardCustomizeConfirm";
import {
communicationPresetFor,
conflictManagementPresetFor,
@@ -52,7 +53,6 @@ import {
} from "../../../../lib/create/coreValueChipFacet";
import {
captureMethodCardCustomizeSnapshot,
confirmDiscardMethodCardCustomizeSession,
isMethodCardCustomizeSessionDirty,
type MethodCardCustomizeSnapshot,
type MethodCardHeaderDraft,
@@ -171,6 +171,8 @@ export function FinalReviewChipEditModal({
const tModal = useTranslation(
"create.reviewAndComplete.finalReview.chipEditModal",
);
const { confirmDiscard, confirmDirtyCustomizeCancel, confirmDialog } =
useDiscardCustomizeConfirm();
const [draft, setDraft] = useState<Draft | null>(null);
const [modalEditUnlocked, setModalEditUnlocked] = useState(false);
@@ -342,32 +344,30 @@ export function FinalReviewChipEditModal({
onClose();
}, [onClose]);
const handleModalClose = useCallback(() => {
const handleModalClose = useCallback(async () => {
if (
target &&
target.groupKey === "coreValues" &&
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
coreCustomizeSnapshotRef.current,
draft?.groupKey === "coreValues" ? draft.value : null,
null,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
if (
target &&
isMethodFacetGroup(target.groupKey) &&
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
customizeSnapshotRef.current,
methodDetailDraftForCustomizeSession(draft),
draftFieldBlocks,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -380,17 +380,17 @@ export function FinalReviewChipEditModal({
}
finalizeModalClose();
}, [
confirmDiscard,
customizeHeaderDraft,
draft,
draftFieldBlocks,
finalizeModalClose,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
replaceState,
target,
]);
const handleCancelCustomize = useCallback(() => {
const handleCancelCustomize = useCallback(async () => {
if (!modalEditUnlocked || !target) {
return;
}
@@ -404,13 +404,12 @@ export function FinalReviewChipEditModal({
}
if (
draft?.groupKey === "coreValues" &&
isMethodCardCustomizeSessionDirty(
!(await confirmDirtyCustomizeCancel(
snap,
draft.value,
null,
customizeHeaderDraft,
) &&
!window.confirm(modalKebabMenu.discardUnsavedCustomizeChanges)
))
) {
return;
}
@@ -435,13 +434,12 @@ export function FinalReviewChipEditModal({
return;
}
if (
isMethodCardCustomizeSessionDirty(
!(await confirmDirtyCustomizeCancel(
snap,
methodDetailDraftForCustomizeSession(draft),
draftFieldBlocks,
customizeHeaderDraft,
) &&
!window.confirm(modalKebabMenu.discardUnsavedCustomizeChanges)
))
) {
return;
}
@@ -451,11 +449,11 @@ export function FinalReviewChipEditModal({
customizeSnapshotRef.current = null;
setCustomizeHeaderDraft(null);
}, [
confirmDirtyCustomizeCancel,
customizeHeaderDraft,
draft,
draftFieldBlocks,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
target,
]);
@@ -565,7 +563,7 @@ export function FinalReviewChipEditModal({
tCm,
]);
const handleRemoveSelectedFromModal = useCallback(() => {
const handleRemoveSelectedFromModal = useCallback(async () => {
if (!target || !isMethodFacetGroup(target.groupKey)) {
return;
}
@@ -575,14 +573,13 @@ export function FinalReviewChipEditModal({
}
onInteract?.();
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
customizeSnapshotRef.current,
methodDetailDraftForCustomizeSession(draft),
draftFieldBlocks,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -597,32 +594,31 @@ export function FinalReviewChipEditModal({
}));
finalizeModalClose();
}, [
confirmDiscard,
customizeHeaderDraft,
draft,
draftFieldBlocks,
finalizeModalClose,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
onInteract,
replaceState,
selectionIdsForTarget,
target,
]);
const handleRemoveCoreValueFromModal = useCallback(() => {
const handleRemoveCoreValueFromModal = useCallback(async () => {
if (!target || target.groupKey !== "coreValues") {
return;
}
onInteract?.();
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
coreCustomizeSnapshotRef.current,
draft?.groupKey === "coreValues" ? draft.value : null,
null,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -634,17 +630,17 @@ export function FinalReviewChipEditModal({
}));
finalizeModalClose();
}, [
confirmDiscard,
customizeHeaderDraft,
draft,
finalizeModalClose,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
onInteract,
replaceState,
target,
]);
const handleDuplicateCoreValue = useCallback(() => {
const handleDuplicateCoreValue = useCallback(async () => {
if (
!target ||
target.groupKey !== "coreValues" ||
@@ -659,14 +655,13 @@ export function FinalReviewChipEditModal({
return;
}
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
coreCustomizeSnapshotRef.current,
draft.value,
null,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -711,10 +706,10 @@ export function FinalReviewChipEditModal({
chipLabel: outcome.newLabel,
});
}, [
confirmDiscard,
customizeHeaderDraft,
draft,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
modalKebabMenu.duplicateTitleSuffix,
onEditTargetChange,
onInteract,
@@ -1015,6 +1010,7 @@ export function FinalReviewChipEditModal({
: showMethodModalPrimary;
return (
<>
<Create
isOpen={isOpen}
onClose={handleModalClose}
@@ -1184,6 +1180,8 @@ export function FinalReviewChipEditModal({
))}
</div>
</Create>
{confirmDialog}
</>
);
}
+2 -7
View File
@@ -31,7 +31,7 @@ export function useCreateFlowExit({
user: { id: string; email: string } | null;
/** When save fails, surface the server message in the create shell banner (no leave confirm). */
setDraftSaveBannerMessage?: (_message: string | null) => void;
/** When exit would discard unsaved work, return true to proceed. Defaults to `window.confirm`. */
/** When exit would discard unsaved work, return true to proceed. Defaults to denying leave. */
confirmLeave?: () => Promise<boolean>;
}): (_options?: { saveDraft?: boolean }) => Promise<void> {
return useCallback(
@@ -41,12 +41,7 @@ export function useCreateFlowExit({
const saveDraft = options?.saveDraft ?? false;
if (!saveDraft) {
const confirmFn =
confirmLeave ??
(async () => {
if (typeof window === "undefined") return true;
return window.confirm(messages.create.topNav.leaveConfirmLoss);
});
const confirmFn = confirmLeave ?? (async () => false);
const confirmed = await confirmFn();
if (!confirmed) return;
}
@@ -0,0 +1,78 @@
"use client";
import { useCallback } from "react";
import messages from "../../../../messages/en/index";
import { useAsyncConfirm } from "../../../hooks/useAsyncConfirm";
import type { CustomMethodCardFieldBlock } from "../../../../lib/create/customMethodCardFieldBlocks";
import {
confirmDiscardMethodCardCustomizeSession,
isMethodCardCustomizeSessionDirty,
type MethodCardCustomizeSnapshot,
type MethodCardHeaderDraft,
} from "../../../../lib/create/methodCardCustomizeSession";
const copy = messages.create.customRule.modalKebabMenu;
const confirmOptions = {
title: copy.discardUnsavedCustomizeChangesTitle,
description: copy.discardUnsavedCustomizeChangesDescription,
proceedText: copy.discardUnsavedCustomizeChangesProceed,
cancelText: copy.discardUnsavedCustomizeChangesCancel,
};
/**
* Create-flow confirm for exiting customize mode with unsaved edits.
*
* @returns Async helpers plus `confirmDialog` to render once in the screen JSX.
*/
export function useDiscardCustomizeConfirm() {
const { requestConfirm, confirmDialog } = useAsyncConfirm();
const runConfirm = useCallback(
() => requestConfirm(confirmOptions),
[requestConfirm],
);
const confirmDiscard = useCallback(
async <TDraft,>(
modalEditUnlocked: boolean,
snapshot: MethodCardCustomizeSnapshot<TDraft> | null,
pendingDraft: TDraft | null,
draftFieldBlocks: CustomMethodCardFieldBlock[] | null,
headerDraft: MethodCardHeaderDraft | null,
) =>
confirmDiscardMethodCardCustomizeSession(
modalEditUnlocked,
snapshot,
pendingDraft,
draftFieldBlocks,
headerDraft,
runConfirm,
),
[runConfirm],
);
const confirmDirtyCustomizeCancel = useCallback(
async <TDraft,>(
snapshot: MethodCardCustomizeSnapshot<TDraft>,
pendingDraft: TDraft | null,
draftFieldBlocks: CustomMethodCardFieldBlock[] | null,
headerDraft: MethodCardHeaderDraft | null,
) => {
if (
!isMethodCardCustomizeSessionDirty(
snapshot,
pendingDraft,
draftFieldBlocks,
headerDraft,
)
) {
return true;
}
return runConfirm();
},
[runConfirm],
);
return { confirmDiscard, confirmDirtyCustomizeCancel, confirmDialog };
}
@@ -19,6 +19,7 @@ import { useState, useCallback, useMemo, useRef } from "react";
import { useMessages } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import { useCreateFlowMdUp } from "../../hooks/useCreateFlowMdUp";
import { useDiscardCustomizeConfirm } from "../../hooks/useDiscardCustomizeConfirm";
import { useMethodCardDeckOrdering } from "../../hooks/useMethodCardDeckOrdering";
import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup";
import CardStack from "../../../../components/cards/CardStack";
@@ -53,8 +54,6 @@ import { buildCustomRuleModalKebabMenu } from "../../components/customRuleModalK
import { methodCardMetaWithCustomizeHeader } from "../../../../../lib/create/methodCardCustomizeMetaPatch";
import {
captureMethodCardCustomizeSnapshot,
confirmDiscardMethodCardCustomizeSession,
isMethodCardCustomizeSessionDirty,
type MethodCardCustomizeSnapshot,
type MethodCardHeaderDraft,
} from "../../../../../lib/create/methodCardCustomizeSession";
@@ -65,6 +64,8 @@ export function CommunicationMethodsScreen() {
const comm = m.create.customRule.communication;
const modalKebabMenu = m.create.customRule.modalKebabMenu;
const mdUp = useCreateFlowMdUp();
const { confirmDiscard, confirmDirtyCustomizeCancel, confirmDialog } =
useDiscardCustomizeConfirm();
const { state, updateState, replaceState, markCreateFlowInteraction } =
useCreateFlow();
const pendingEphemeralDuplicateIdRef = useRef<string | null>(null);
@@ -201,16 +202,15 @@ export function CommunicationMethodsScreen() {
],
);
const handleCreateModalClose = useCallback(() => {
const handleCreateModalClose = useCallback(async () => {
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
customizeSnapshotRef.current,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -241,15 +241,15 @@ export function CommunicationMethodsScreen() {
setDraftFieldBlocks(null);
setCustomizeHeaderDraft(null);
}, [
confirmDiscard,
customizeHeaderDraft,
draftFieldBlocks,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
replaceState,
]);
const handleCancelCustomize = useCallback(() => {
const handleCancelCustomize = useCallback(async () => {
if (!modalEditUnlocked) {
return;
}
@@ -262,13 +262,12 @@ export function CommunicationMethodsScreen() {
return;
}
if (
isMethodCardCustomizeSessionDirty(
!(await confirmDirtyCustomizeCancel(
snap,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
) &&
!window.confirm(modalKebabMenu.discardUnsavedCustomizeChanges)
))
) {
return;
}
@@ -278,27 +277,26 @@ export function CommunicationMethodsScreen() {
customizeSnapshotRef.current = null;
setCustomizeHeaderDraft(null);
}, [
confirmDirtyCustomizeCancel,
customizeHeaderDraft,
draftFieldBlocks,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
]);
const handleRemoveSelectedFromModal = useCallback(() => {
const handleRemoveSelectedFromModal = useCallback(async () => {
if (!pendingCardId || !selectedIds.includes(pendingCardId)) {
return;
}
markCreateFlowInteraction();
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
customizeSnapshotRef.current,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -310,14 +308,14 @@ export function CommunicationMethodsScreen() {
pendingCardId,
),
);
handleCreateModalClose();
await handleCreateModalClose();
}, [
confirmDiscard,
customizeHeaderDraft,
draftFieldBlocks,
handleCreateModalClose,
markCreateFlowInteraction,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
pendingCardId,
selectedIds,
@@ -829,6 +827,7 @@ export function CommunicationMethodsScreen() {
uploadCreateFlowFile(file, "customMethodAttachment")
}
/>
{confirmDialog}
</>
);
}
@@ -16,6 +16,7 @@ import { useState, useCallback, useMemo, useRef } from "react";
import { useMessages } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import { useCreateFlowMdUp } from "../../hooks/useCreateFlowMdUp";
import { useDiscardCustomizeConfirm } from "../../hooks/useDiscardCustomizeConfirm";
import { useMethodCardDeckOrdering } from "../../hooks/useMethodCardDeckOrdering";
import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup";
import CardStack from "../../../../components/cards/CardStack";
@@ -50,8 +51,6 @@ import { buildCustomRuleModalKebabMenu } from "../../components/customRuleModalK
import { methodCardMetaWithCustomizeHeader } from "../../../../../lib/create/methodCardCustomizeMetaPatch";
import {
captureMethodCardCustomizeSnapshot,
confirmDiscardMethodCardCustomizeSession,
isMethodCardCustomizeSessionDirty,
type MethodCardCustomizeSnapshot,
type MethodCardHeaderDraft,
} from "../../../../../lib/create/methodCardCustomizeSession";
@@ -62,6 +61,8 @@ export function ConflictManagementScreen() {
const cm = m.create.customRule.conflictManagement;
const modalKebabMenu = m.create.customRule.modalKebabMenu;
const mdUp = useCreateFlowMdUp();
const { confirmDiscard, confirmDirtyCustomizeCancel, confirmDialog } =
useDiscardCustomizeConfirm();
const { state, updateState, replaceState, markCreateFlowInteraction } =
useCreateFlow();
const pendingEphemeralDuplicateIdRef = useRef<string | null>(null);
@@ -202,16 +203,15 @@ export function ConflictManagementScreen() {
],
);
const handleCreateModalClose = useCallback(() => {
const handleCreateModalClose = useCallback(async () => {
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
customizeSnapshotRef.current,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -242,15 +242,15 @@ export function ConflictManagementScreen() {
setDraftFieldBlocks(null);
setCustomizeHeaderDraft(null);
}, [
confirmDiscard,
customizeHeaderDraft,
draftFieldBlocks,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
replaceState,
]);
const handleCancelCustomize = useCallback(() => {
const handleCancelCustomize = useCallback(async () => {
if (!modalEditUnlocked) {
return;
}
@@ -263,13 +263,12 @@ export function ConflictManagementScreen() {
return;
}
if (
isMethodCardCustomizeSessionDirty(
!(await confirmDirtyCustomizeCancel(
snap,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
) &&
!window.confirm(modalKebabMenu.discardUnsavedCustomizeChanges)
))
) {
return;
}
@@ -279,27 +278,26 @@ export function ConflictManagementScreen() {
customizeSnapshotRef.current = null;
setCustomizeHeaderDraft(null);
}, [
confirmDirtyCustomizeCancel,
customizeHeaderDraft,
draftFieldBlocks,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
]);
const handleRemoveSelectedFromModal = useCallback(() => {
const handleRemoveSelectedFromModal = useCallback(async () => {
if (!pendingCardId || !selectedIds.includes(pendingCardId)) {
return;
}
markCreateFlowInteraction();
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
customizeSnapshotRef.current,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -311,14 +309,14 @@ export function ConflictManagementScreen() {
pendingCardId,
),
);
handleCreateModalClose();
await handleCreateModalClose();
}, [
confirmDiscard,
customizeHeaderDraft,
draftFieldBlocks,
handleCreateModalClose,
markCreateFlowInteraction,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
pendingCardId,
selectedIds,
@@ -828,6 +826,7 @@ export function ConflictManagementScreen() {
uploadCreateFlowFile(file, "customMethodAttachment")
}
/>
{confirmDialog}
</>
);
}
@@ -17,6 +17,7 @@ import { useState, useCallback, useMemo, useRef } from "react";
import { useMessages } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import { useCreateFlowMdUp } from "../../hooks/useCreateFlowMdUp";
import { useDiscardCustomizeConfirm } from "../../hooks/useDiscardCustomizeConfirm";
import { useMethodCardDeckOrdering } from "../../hooks/useMethodCardDeckOrdering";
import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup";
import CardStack from "../../../../components/cards/CardStack";
@@ -51,8 +52,6 @@ import { buildCustomRuleModalKebabMenu } from "../../components/customRuleModalK
import { methodCardMetaWithCustomizeHeader } from "../../../../../lib/create/methodCardCustomizeMetaPatch";
import {
captureMethodCardCustomizeSnapshot,
confirmDiscardMethodCardCustomizeSession,
isMethodCardCustomizeSessionDirty,
type MethodCardCustomizeSnapshot,
type MethodCardHeaderDraft,
} from "../../../../../lib/create/methodCardCustomizeSession";
@@ -63,6 +62,8 @@ export function MembershipMethodsScreen() {
const mem = m.create.customRule.membership;
const modalKebabMenu = m.create.customRule.modalKebabMenu;
const mdUp = useCreateFlowMdUp();
const { confirmDiscard, confirmDirtyCustomizeCancel, confirmDialog } =
useDiscardCustomizeConfirm();
const { state, updateState, replaceState, markCreateFlowInteraction } =
useCreateFlow();
const pendingEphemeralDuplicateIdRef = useRef<string | null>(null);
@@ -199,16 +200,15 @@ export function MembershipMethodsScreen() {
],
);
const handleCreateModalClose = useCallback(() => {
const handleCreateModalClose = useCallback(async () => {
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
customizeSnapshotRef.current,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -239,15 +239,15 @@ export function MembershipMethodsScreen() {
setDraftFieldBlocks(null);
setCustomizeHeaderDraft(null);
}, [
confirmDiscard,
customizeHeaderDraft,
draftFieldBlocks,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
replaceState,
]);
const handleCancelCustomize = useCallback(() => {
const handleCancelCustomize = useCallback(async () => {
if (!modalEditUnlocked) {
return;
}
@@ -260,13 +260,12 @@ export function MembershipMethodsScreen() {
return;
}
if (
isMethodCardCustomizeSessionDirty(
!(await confirmDirtyCustomizeCancel(
snap,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
) &&
!window.confirm(modalKebabMenu.discardUnsavedCustomizeChanges)
))
) {
return;
}
@@ -276,27 +275,26 @@ export function MembershipMethodsScreen() {
customizeSnapshotRef.current = null;
setCustomizeHeaderDraft(null);
}, [
confirmDirtyCustomizeCancel,
customizeHeaderDraft,
draftFieldBlocks,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
]);
const handleRemoveSelectedFromModal = useCallback(() => {
const handleRemoveSelectedFromModal = useCallback(async () => {
if (!pendingCardId || !selectedIds.includes(pendingCardId)) {
return;
}
markCreateFlowInteraction();
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
customizeSnapshotRef.current,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -304,14 +302,14 @@ export function MembershipMethodsScreen() {
updateState(
removeMethodCardFromFacetSelection(state, "membership", pendingCardId),
);
handleCreateModalClose();
await handleCreateModalClose();
}, [
confirmDiscard,
customizeHeaderDraft,
draftFieldBlocks,
handleCreateModalClose,
markCreateFlowInteraction,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
pendingCardId,
selectedIds,
@@ -821,6 +819,7 @@ export function MembershipMethodsScreen() {
uploadCreateFlowFile(file, "customMethodAttachment")
}
/>
{confirmDialog}
</>
);
}
@@ -26,6 +26,7 @@ import type { InfoMessageBoxItem } from "../../../../components/controls/InfoMes
import { useMessages } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import { useCreateFlowMdUp } from "../../hooks/useCreateFlowMdUp";
import { useDiscardCustomizeConfirm } from "../../hooks/useDiscardCustomizeConfirm";
import { useMethodCardDeckOrdering } from "../../hooks/useMethodCardDeckOrdering";
import { CreateFlowTwoColumnSelectShell } from "../../components/CreateFlowTwoColumnSelectShell";
import { DecisionApproachEditFields } from "../../components/methodEditFields";
@@ -52,8 +53,6 @@ import { buildCustomRuleModalKebabMenu } from "../../components/customRuleModalK
import { methodCardMetaWithCustomizeHeader } from "../../../../../lib/create/methodCardCustomizeMetaPatch";
import {
captureMethodCardCustomizeSnapshot,
confirmDiscardMethodCardCustomizeSession,
isMethodCardCustomizeSessionDirty,
type MethodCardCustomizeSnapshot,
type MethodCardHeaderDraft,
} from "../../../../../lib/create/methodCardCustomizeSession";
@@ -64,6 +63,8 @@ export function DecisionApproachesScreen() {
const da = m.create.customRule.decisionApproaches;
const modalKebabMenu = m.create.customRule.modalKebabMenu;
const mdUp = useCreateFlowMdUp();
const { confirmDiscard, confirmDirtyCustomizeCancel, confirmDialog } =
useDiscardCustomizeConfirm();
const { state, updateState, replaceState, markCreateFlowInteraction } =
useCreateFlow();
const pendingEphemeralDuplicateIdRef = useRef<string | null>(null);
@@ -216,16 +217,15 @@ export function DecisionApproachesScreen() {
],
);
const handleCreateModalClose = useCallback(() => {
const handleCreateModalClose = useCallback(async () => {
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
customizeSnapshotRef.current,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -256,15 +256,15 @@ export function DecisionApproachesScreen() {
setDraftFieldBlocks(null);
setCustomizeHeaderDraft(null);
}, [
confirmDiscard,
customizeHeaderDraft,
draftFieldBlocks,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
replaceState,
]);
const handleCancelCustomize = useCallback(() => {
const handleCancelCustomize = useCallback(async () => {
if (!modalEditUnlocked) {
return;
}
@@ -277,13 +277,12 @@ export function DecisionApproachesScreen() {
return;
}
if (
isMethodCardCustomizeSessionDirty(
!(await confirmDirtyCustomizeCancel(
snap,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
) &&
!window.confirm(modalKebabMenu.discardUnsavedCustomizeChanges)
))
) {
return;
}
@@ -293,27 +292,26 @@ export function DecisionApproachesScreen() {
customizeSnapshotRef.current = null;
setCustomizeHeaderDraft(null);
}, [
confirmDirtyCustomizeCancel,
customizeHeaderDraft,
draftFieldBlocks,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
]);
const handleRemoveSelectedFromModal = useCallback(() => {
const handleRemoveSelectedFromModal = useCallback(async () => {
if (!pendingCardId || !selectedIds.includes(pendingCardId)) {
return;
}
markCreateFlowInteraction();
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
customizeSnapshotRef.current,
pendingDraft,
draftFieldBlocks,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -325,14 +323,14 @@ export function DecisionApproachesScreen() {
pendingCardId,
),
);
handleCreateModalClose();
await handleCreateModalClose();
}, [
confirmDiscard,
customizeHeaderDraft,
draftFieldBlocks,
handleCreateModalClose,
markCreateFlowInteraction,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
pendingDraft,
pendingCardId,
selectedIds,
@@ -867,6 +865,7 @@ export function DecisionApproachesScreen() {
uploadCreateFlowFile(file, "customMethodAttachment")
}
/>
{confirmDialog}
</>
);
}
@@ -8,6 +8,7 @@ import ContentLockup from "../../../../components/type/ContentLockup";
import { useMessages } from "../../../../contexts/MessagesContext";
import { buildCoreValueChipOptionsFromDraft } from "../../../../../lib/create/coreValueChipOptionsFromDraft";
import { useCreateFlow } from "../../context/CreateFlowContext";
import { useDiscardCustomizeConfirm } from "../../hooks/useDiscardCustomizeConfirm";
import type {
CommunityStructureChipSnapshotRow,
CoreValueDetailEntry,
@@ -19,7 +20,6 @@ import MethodCardCustomizeModalHeader from "../../components/MethodCardCustomize
import { buildCustomRuleModalKebabMenu } from "../../components/customRuleModalKebabMenu";
import {
captureMethodCardCustomizeSnapshot,
confirmDiscardMethodCardCustomizeSession,
isMethodCardCustomizeSessionDirty,
type MethodCardCustomizeSnapshot,
type MethodCardHeaderDraft,
@@ -101,6 +101,8 @@ export function CoreValuesSelectScreen() {
[cv.values],
);
const { confirmDiscard, confirmDirtyCustomizeCancel, confirmDialog } =
useDiscardCustomizeConfirm();
const { markCreateFlowInteraction, updateState, replaceState, state } =
useCreateFlow();
@@ -239,7 +241,7 @@ export function CoreValuesSelectScreen() {
setModalEditUnlocked(true);
}, [activeModalChipId, coreValueOptions, draft, markCreateFlowInteraction]);
const handleCancelCustomize = useCallback(() => {
const handleCancelCustomize = useCallback(async () => {
if (!modalEditUnlocked) return;
const snap = coreCustomizeSnapshotRef.current;
if (!snap) {
@@ -247,18 +249,22 @@ export function CoreValuesSelectScreen() {
return;
}
if (
isMethodCardCustomizeSessionDirty(snap, draft, null, customizeHeaderDraft) &&
!window.confirm(modalKebabMenu.discardUnsavedCustomizeChanges)
!(await confirmDirtyCustomizeCancel(
snap,
draft,
null,
customizeHeaderDraft,
))
) {
return;
}
setDraft(structuredClone(snap.pendingDraft));
resetCustomizeSession();
}, [
confirmDirtyCustomizeCancel,
customizeHeaderDraft,
draft,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
resetCustomizeSession,
]);
@@ -271,17 +277,16 @@ export function CoreValuesSelectScreen() {
);
}, [activeModalChipId, customizeHeaderDraft, coreValueOptions]);
const handleDuplicateCoreChip = useCallback(() => {
const handleDuplicateCoreChip = useCallback(async () => {
if (!activeModalChipId || !modalSession) return;
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
coreCustomizeSnapshotRef.current,
draft,
null,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -317,11 +322,11 @@ export function CoreValuesSelectScreen() {
);
}, [
activeModalChipId,
confirmDiscard,
customizeHeaderDraft,
draft,
markCreateFlowInteraction,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
modalKebabMenu.duplicateTitleSuffix,
modalSession,
openModal,
@@ -329,16 +334,15 @@ export function CoreValuesSelectScreen() {
resetCustomizeSession,
]);
const handleRemoveFromKebab = useCallback(() => {
const handleRemoveFromKebab = useCallback(async () => {
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
coreCustomizeSnapshotRef.current,
draft,
null,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -382,30 +386,27 @@ export function CoreValuesSelectScreen() {
finalizeModalDismiss();
}, [
activeModalChipId,
confirmDiscard,
coreValueOptions,
customizeHeaderDraft,
draft,
finalizeModalDismiss,
markCreateFlowInteraction,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
modalSession,
persistCoreValues,
replaceState,
modalSession,
persistCoreValues,
]);
const handleModalDismiss = useCallback(() => {
const handleModalDismiss = useCallback(async () => {
if (
!confirmDiscardMethodCardCustomizeSession(
!(await confirmDiscard(
modalEditUnlocked,
coreCustomizeSnapshotRef.current,
draft,
null,
customizeHeaderDraft,
modalKebabMenu.discardUnsavedCustomizeChanges,
)
))
) {
return;
}
@@ -435,12 +436,12 @@ export function CoreValuesSelectScreen() {
finalizeModalDismiss();
}, [
activeModalChipId,
confirmDiscard,
coreValueOptions,
customizeHeaderDraft,
draft,
finalizeModalDismiss,
modalEditUnlocked,
modalKebabMenu.discardUnsavedCustomizeChanges,
modalSession,
persistCoreValues,
replaceState,
@@ -645,6 +646,7 @@ export function CoreValuesSelectScreen() {
const detailModal = cv.detailModal;
return (
<>
<CreateFlowTwoColumnSelectShell
lgVerticalAlign="start"
header={
@@ -724,5 +726,7 @@ export function CoreValuesSelectScreen() {
</Create>
)}
</CreateFlowTwoColumnSelectShell>
{confirmDialog}
</>
);
}