From c3f3b8e2188ec73af26d690695f6eda146305f14 Mon Sep 17 00:00:00 2001 From: WuYongJie Date: Wed, 13 May 2026 09:50:17 +0800 Subject: [PATCH] fix: polish planning layout selectors --- .../NonIntegratedDetailClient.test.tsx | 12 ++- .../NonIntegratedDetailClient.tsx | 83 ++++++++++++++----- 2 files changed, 74 insertions(+), 21 deletions(-) diff --git a/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedDetailClient.test.tsx b/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedDetailClient.test.tsx index d46d5b70..627e3df1 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedDetailClient.test.tsx +++ b/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedDetailClient.test.tsx @@ -2830,7 +2830,10 @@ describe("NonIntegratedDetailClient", () => { screen.getByTestId( "planning-layout-spaces-draft-sku-planning-layout-fields-1", ), - ).toHaveAttribute("placeholder", "?"); + ).toHaveAttribute("placeholder", ""); + expect( + screen.queryByTestId("planning-layout-spaces-add-sku-planning-layout-fields-1"), + ).not.toBeInTheDocument(); fireEvent.change( screen.getByTestId( "planning-layout-categories-draft-sku-planning-layout-fields-1", @@ -2850,7 +2853,12 @@ describe("NonIntegratedDetailClient", () => { screen.getByTestId( "planning-layout-categories-draft-sku-planning-layout-fields-1", ), - ).toHaveAttribute("placeholder", "?"); + ).toHaveAttribute("placeholder", ""); + expect( + screen.queryByTestId( + "planning-layout-categories-add-sku-planning-layout-fields-1", + ), + ).not.toBeInTheDocument(); await waitFor(() => { const savedProduct = getNonIntegratedProductById( diff --git a/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedDetailClient.tsx b/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedDetailClient.tsx index 61c0d99b..0655abe4 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedDetailClient.tsx +++ b/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedDetailClient.tsx @@ -8387,6 +8387,10 @@ export default function NonIntegratedDetailClient({ >({}); const [planningLayoutBrandPickerSkuId, setPlanningLayoutBrandPickerSkuId] = useState(null); + const [ + planningLayoutBrandPickerPosition, + setPlanningLayoutBrandPickerPosition, + ] = useState<{ skuId: string; left: number; top: number } | null>(null); const [productLimitRows, setProductLimitRows] = useState< NonIntegratedProductLimitRow[] >(existingProduct?.productLimitRows ?? []); @@ -8579,6 +8583,22 @@ export default function NonIntegratedDetailClient({ onDocumentWorkspaceStateChange, ]); + useEffect(() => { + if (!planningLayoutBrandPickerSkuId) return; + + const handleWindowChange = () => { + closePlanningLayoutBrandPicker(); + }; + + window.addEventListener("resize", handleWindowChange); + window.addEventListener("scroll", handleWindowChange, true); + + return () => { + window.removeEventListener("resize", handleWindowChange); + window.removeEventListener("scroll", handleWindowChange, true); + }; + }, [planningLayoutBrandPickerSkuId]); + useEffect(() => { if (typeof fetch !== "function") { return; @@ -12509,6 +12529,11 @@ export default function NonIntegratedDetailClient({ }); } + function closePlanningLayoutBrandPicker() { + setPlanningLayoutBrandPickerSkuId(null); + setPlanningLayoutBrandPickerPosition(null); + } + function updateSampleMeasurementRow( skuId: string, key: Exclude, @@ -17691,7 +17716,7 @@ export default function NonIntegratedDetailClient({ )} {isReadOnly ? null : ( - <> +
- - + ⌄ + +
)} @@ -17752,6 +17773,11 @@ export default function NonIntegratedDetailClient({ }) => { const selectedValues = getUniqueNonEmptyStrings(values); const pickerOpen = planningLayoutBrandPickerSkuId === row.skuId; + const pickerDropdownId = `planning-layout-brands-dropdown-${row.skuId}`; + const pickerPosition = + pickerOpen && planningLayoutBrandPickerPosition?.skuId === row.skuId + ? planningLayoutBrandPickerPosition + : null; return (
@@ -17789,23 +17815,42 @@ export default function NonIntegratedDetailClient({ )}
{isReadOnly ? null : ( -
+
- {pickerOpen ? ( -
+ {pickerOpen && pickerPosition ? ( +
{options.map((brand) => { const checked = selectedValues.includes(brand);