From 67c5b34bf5c90537ea6893e352bf380e540eef64 Mon Sep 17 00:00:00 2001 From: Donkie Date: Sat, 23 Nov 2024 22:42:47 +0100 Subject: [PATCH] Final touches on locations page --- client/package-lock.json | 41 +++++- client/package.json | 4 +- .../pages/locations/components/location.tsx | 46 +++++-- .../components/locationContainer.tsx | 44 +++++-- .../pages/locations/components/spoolCard.tsx | 120 +++++++++++++++--- .../pages/locations/components/spoolList.tsx | 45 +++---- client/src/pages/locations/dnd.ts | 29 +++++ client/src/pages/locations/functions.ts | 97 ++++++++++---- client/src/pages/locations/itemTypes.ts | 4 - client/src/pages/locations/locations.css | 8 ++ 10 files changed, 339 insertions(+), 99 deletions(-) create mode 100644 client/src/pages/locations/dnd.ts delete mode 100644 client/src/pages/locations/itemTypes.ts diff --git a/client/package-lock.json b/client/package-lock.json index 273f467..faf8f1e 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -37,10 +37,12 @@ "react-router-dom": "^6.28.0", "react-to-print": "^2.15.1", "uuid": "^11.0.3", - "vite-plugin-svgr": "^4.3.0" + "vite-plugin-svgr": "^4.3.0", + "zustand": "^5.0.1" }, "devDependencies": { "@refinedev/cli": "^2.16.39", + "@simbathesailor/use-what-changed": "^2.0.0", "@types/node": "^22.9.1", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", @@ -2643,6 +2645,15 @@ "win32" ] }, + "node_modules/@simbathesailor/use-what-changed": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@simbathesailor/use-what-changed/-/use-what-changed-2.0.0.tgz", + "integrity": "sha512-ulBNrPSvfho9UN6zS2fii3AsdEcp2fMaKeqUZZeCNPaZbB6aXyTUhpEN9atjMAbu/eyK3AY8L4SYJUG62Ekocw==", + "dev": true, + "peerDependencies": { + "react": ">=16" + } + }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -10320,6 +10331,34 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zustand": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.1.tgz", + "integrity": "sha512-pRET7Lao2z+n5R/HduXMio35TncTlSW68WsYBq2Lg1ASspsNGjpwLAsij3RpouyV6+kHMwwwzP0bZPD70/Jx/w==", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + }, "node_modules/zwitch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", diff --git a/client/package.json b/client/package.json index d333a91..119fc09 100644 --- a/client/package.json +++ b/client/package.json @@ -36,10 +36,12 @@ "react-router-dom": "^6.28.0", "react-to-print": "^2.15.1", "uuid": "^11.0.3", - "vite-plugin-svgr": "^4.3.0" + "vite-plugin-svgr": "^4.3.0", + "zustand": "^5.0.1" }, "devDependencies": { "@refinedev/cli": "^2.16.39", + "@simbathesailor/use-what-changed": "^2.0.0", "@types/node": "^22.9.1", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", diff --git a/client/src/pages/locations/components/location.tsx b/client/src/pages/locations/components/location.tsx index 926a713..eebd526 100644 --- a/client/src/pages/locations/components/location.tsx +++ b/client/src/pages/locations/components/location.tsx @@ -4,15 +4,11 @@ import { useRef, useState } from "react"; import { useDrag, useDrop } from "react-dnd"; import { DeleteOutlined } from "@ant-design/icons"; +import { useUpdate } from "@refinedev/core"; import { ISpool } from "../../spools/model"; -import { ItemTypes } from "../itemTypes"; +import { DragItem, ItemTypes, SpoolDragItem } from "../dnd"; import { SpoolList } from "./spoolList"; -interface DragItem { - index: number; - title: string; -} - export function Location({ index, title, @@ -36,10 +32,24 @@ export function Location({ }) { const [editTitle, setEditTitle] = useState(false); const [newTitle, setNewTitle] = useState(title); + const { mutate: updateSpool } = useUpdate({ + resource: "spool", + mutationMode: "optimistic", + successNotification: false, + }); + + const moveSpoolLocation = (spool_id: number, location: string) => { + updateSpool({ + id: spool_id, + values: { + location: location, + }, + }); + }; const ref = useRef(null); const [{ handlerId }, drop] = useDrop({ - accept: ItemTypes.CONTAINER, + accept: [ItemTypes.CONTAINER, ItemTypes.SPOOL], collect(monitor) { return { handlerId: monitor.getHandlerId(), @@ -49,6 +59,21 @@ export function Location({ if (!ref.current) { return null; } + + if ("spool" in item) { + // Only allow dropping spools on the container if it's empty. + if (spools.length > 0) { + return null; + } + + const spoolitem = item as SpoolDragItem; + if (spoolitem.spool.location !== title) { + moveSpoolLocation(spoolitem.spool.id, title); + spoolitem.spool.location = title; + } + return null; + } + const dragIndex = item.index; const hoverIndex = index; @@ -127,12 +152,7 @@ export function Location({ )} {showDelete &&