fix: polish planning layout selectors
This commit is contained in:
parent
62bceabc66
commit
c3f3b8e218
@ -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(
|
||||
|
||||
@ -8387,6 +8387,10 @@ export default function NonIntegratedDetailClient({
|
||||
>({});
|
||||
const [planningLayoutBrandPickerSkuId, setPlanningLayoutBrandPickerSkuId] =
|
||||
useState<string | null>(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<keyof NonIntegratedSampleMeasurementRow, "skuId">,
|
||||
@ -17691,7 +17716,7 @@ export default function NonIntegratedDetailClient({
|
||||
)}
|
||||
</div>
|
||||
{isReadOnly ? null : (
|
||||
<>
|
||||
<div className="relative ml-auto h-6 w-10 shrink-0">
|
||||
<input
|
||||
type="text"
|
||||
aria-label={`企划布局${label}`}
|
||||
@ -17715,20 +17740,16 @@ export default function NonIntegratedDetailClient({
|
||||
event.preventDefault();
|
||||
addPlanningLayoutListValue(row.skuId, field);
|
||||
}}
|
||||
placeholder="?"
|
||||
className="h-6 w-10 shrink-0 rounded-apple-sm border border-apple-separator bg-apple-bg-primary px-1 text-center text-xs text-apple-label-primary outline-none placeholder:text-apple-label-tertiary"
|
||||
placeholder=""
|
||||
className="h-6 w-full rounded-apple-sm border border-apple-separator bg-apple-bg-primary px-1 pr-3 text-center text-xs text-apple-label-primary outline-none placeholder:text-apple-label-tertiary"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={`添加${label}`}
|
||||
title={`添加${label}`}
|
||||
data-testid={`planning-layout-${field}-add-${row.skuId}`}
|
||||
onClick={() => addPlanningLayoutListValue(row.skuId, field)}
|
||||
className="inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-apple-sm bg-black text-white transition-opacity hover:opacity-80"
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute right-1 top-1/2 -translate-y-1/2 text-[9px] leading-none text-apple-label-tertiary"
|
||||
>
|
||||
<Plus className="h-3 w-3" />
|
||||
</button>
|
||||
</>
|
||||
⌄
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<datalist id={listId}>
|
||||
@ -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 (
|
||||
<div className="w-max" style={{ minWidth }}>
|
||||
@ -17789,23 +17815,42 @@ export default function NonIntegratedDetailClient({
|
||||
)}
|
||||
</div>
|
||||
{isReadOnly ? null : (
|
||||
<div className="relative">
|
||||
<div className="relative ml-auto">
|
||||
<button
|
||||
type="button"
|
||||
aria-label="选择适配品牌"
|
||||
aria-expanded={pickerOpen}
|
||||
aria-controls={pickerOpen ? pickerDropdownId : undefined}
|
||||
data-testid={`planning-layout-brands-picker-${row.skuId}`}
|
||||
onClick={() =>
|
||||
onClick={(event) => {
|
||||
const buttonRect =
|
||||
event.currentTarget.getBoundingClientRect();
|
||||
setPlanningLayoutBrandPickerSkuId((current) =>
|
||||
current === row.skuId ? null : row.skuId,
|
||||
)
|
||||
}
|
||||
);
|
||||
setPlanningLayoutBrandPickerPosition((current) =>
|
||||
current?.skuId === row.skuId
|
||||
? null
|
||||
: {
|
||||
skuId: row.skuId,
|
||||
left: buttonRect.right - 148,
|
||||
top: buttonRect.bottom + 6,
|
||||
},
|
||||
);
|
||||
}}
|
||||
className="inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-apple-sm bg-black text-[10px] text-white transition-opacity hover:opacity-80"
|
||||
>
|
||||
✓
|
||||
</button>
|
||||
{pickerOpen ? (
|
||||
<div className="absolute right-0 top-[calc(100%+6px)] z-20 min-w-[148px] rounded-apple-lg border border-apple-separator bg-apple-bg-primary p-2 shadow-apple-md">
|
||||
{pickerOpen && pickerPosition ? (
|
||||
<div
|
||||
id={pickerDropdownId}
|
||||
className="fixed z-50 min-w-[148px] rounded-apple-lg border border-apple-separator bg-apple-bg-primary p-2 shadow-apple-md"
|
||||
style={{
|
||||
left: Math.max(8, pickerPosition.left),
|
||||
top: pickerPosition.top,
|
||||
}}
|
||||
>
|
||||
<div className="space-y-1.5">
|
||||
{options.map((brand) => {
|
||||
const checked = selectedValues.includes(brand);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user