fix(grid): prevent split collision by including source in overlap check
Server action: remove 'other.id === entryId' exclusion from the split overlap scan so the source item's own footprint is treated as occupied, forcing the split to find a different position. UI: disable the split button via findEmptySpot check when no room exists for the split stack, preventing a failed action.
This commit is contained in:
parent
256e5bd68a
commit
d88fe04b56
3 changed files with 7 additions and 3 deletions
|
|
@ -737,7 +737,7 @@ export async function splitGridStack(
|
||||||
|
|
||||||
let overlaps = false;
|
let overlaps = false;
|
||||||
for (const other of existing) {
|
for (const other of existing) {
|
||||||
if (other.id === entryId || other.id == null) continue;
|
if (other.id == null) continue;
|
||||||
const otherRes = other.resource as Resource;
|
const otherRes = other.resource as Resource;
|
||||||
if (!otherRes || typeof otherRes === "number") continue;
|
if (!otherRes || typeof otherRes === "number") continue;
|
||||||
const otherRotated = other.rotated ?? false;
|
const otherRotated = other.rotated ?? false;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {
|
||||||
LayoutGridIcon,
|
LayoutGridIcon,
|
||||||
ListIcon,
|
ListIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { GridItem, getItemFootprint, getGridOccupancy } from "@/lib/logistics";
|
import { GridItem, getItemFootprint, getGridOccupancy, findEmptySpot } from "@/lib/logistics";
|
||||||
import { Resource } from "@/payload-types";
|
import { Resource } from "@/payload-types";
|
||||||
import { cn, pluralize } from "@/lib/utils";
|
import { cn, pluralize } from "@/lib/utils";
|
||||||
|
|
||||||
|
|
@ -41,6 +41,9 @@ export function GridToolbar({
|
||||||
const occupancy = getGridOccupancy(storedResources, gridWidth, gridHeight);
|
const occupancy = getGridOccupancy(storedResources, gridWidth, gridHeight);
|
||||||
const res = selectedItem ? (selectedItem.resource as Resource) : null;
|
const res = selectedItem ? (selectedItem.resource as Resource) : null;
|
||||||
const fp = res ? getItemFootprint(res, selectedItem!.rotated) : null;
|
const fp = res ? getItemFootprint(res, selectedItem!.rotated) : null;
|
||||||
|
const canSplit = selectedItem && res && fp
|
||||||
|
? findEmptySpot(storedResources, fp.width, fp.height, gridWidth, gridHeight) !== null
|
||||||
|
: false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
|
|
@ -94,6 +97,7 @@ export function GridToolbar({
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
disabled={!canSplit}
|
||||||
onClick={() => onSplit(selectedItem.id, Math.floor(selectedItem.amount / 2))}
|
onClick={() => onSplit(selectedItem.id, Math.floor(selectedItem.amount / 2))}
|
||||||
>
|
>
|
||||||
<ScissorsIcon className="size-3.5" />
|
<ScissorsIcon className="size-3.5" />
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ export function StructureCard({ structure }: StructureCardProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={`/logistics/structures/${structure.id}`}>
|
<Link href={`/logistics/structures/${structure.id}`}>
|
||||||
<Item variant="outline" className="cursor-pointer group transition-all duration-200 hover:scale-[1.01] hover:[box-shadow:inset_0_2px_8px_rgba(255,255,255,0.12)]">
|
<Item variant="outline" className="cursor-pointer group transition-all duration-200 hover:scale-[1.01] hover:[box-shadow:inset_0_2px_8px_rgba(255,255,255,0.33)]">
|
||||||
<ItemHeader>
|
<ItemHeader>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<ItemMedia variant="icon">
|
<ItemMedia variant="icon">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue