From f97b49cbdfe218bfaa6c03fad61734c3b7148f17 Mon Sep 17 00:00:00 2001 From: t0is Date: Wed, 9 Jul 2025 15:35:23 +0200 Subject: [PATCH] vite cfg fix, floorplan --- .../Api/StockPositionController.php | 4 +- .../Controllers/Api/StockRackController.php | 7 ++ package.json | 3 +- resources/js/Components/RackModalDetails.tsx | 56 ++++++++----- .../Components/modals/EditStockSections.tsx | 2 +- resources/js/Layouts/AppLayout.tsx | 13 +++ resources/js/Pages/FloorPlan.tsx | 68 +++++++++++++++- routes/api.php | 4 +- vite.config.ts | 80 ++++++++++++------- 9 files changed, 181 insertions(+), 56 deletions(-) diff --git a/app/Http/Controllers/Api/StockPositionController.php b/app/Http/Controllers/Api/StockPositionController.php index 8b62f49..b4b2a81 100644 --- a/app/Http/Controllers/Api/StockPositionController.php +++ b/app/Http/Controllers/Api/StockPositionController.php @@ -72,13 +72,13 @@ class StockPositionController extends Controller } - public function getPosition(Request $request) + public function getPosition(Request $request, int $id) { // 1) Eager‐load the real relationships $position = StockPosition::with([ 'sections.entries.physicalItem', 'shelf.rack.line.room', - ])->findOrFail(2); + ])->findOrFail($id); // 2) Compute the storage address string $position->storage_address = $position->storageAddress(); diff --git a/app/Http/Controllers/Api/StockRackController.php b/app/Http/Controllers/Api/StockRackController.php index 40eda46..9f4da42 100644 --- a/app/Http/Controllers/Api/StockRackController.php +++ b/app/Http/Controllers/Api/StockRackController.php @@ -22,6 +22,13 @@ class StockRackController extends Controller return response()->json($rack, 201); } + public function show(Request $request, int $id) + { + $rack = StockRack::with(['line', 'shelves.positions.sections'])->findOrFail($id); + + return response()->json($rack, 201); + } + public function update(Request $request, StockRack $rack) { $data = $request->validate([ diff --git a/package.json b/package.json index 13593ff..0aa67a9 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "type": "module", "scripts": { "build": "vite build", - "dev": "vite" + "dev": "vite", + "dev:android": "EMULATOR=1 vite --host 0.0.0.0" }, "devDependencies": { "@capacitor/cli": "^7.4.1", diff --git a/resources/js/Components/RackModalDetails.tsx b/resources/js/Components/RackModalDetails.tsx index eb14a18..e5c2113 100644 --- a/resources/js/Components/RackModalDetails.tsx +++ b/resources/js/Components/RackModalDetails.tsx @@ -1,40 +1,56 @@ // components/RackDetails.tsx import React from 'react'; -import {StockRack} from '@/types'; +import {StockRack, StockPosition} from '@/types'; interface RackDetailsProps { rack: StockRack | null; + onPositionClick: (posId: number) => void; } -export default function RackModalDetails({ rack }: RackDetailsProps) { +export default function RackModalDetails({rack, onPositionClick}: RackDetailsProps) { + return (
{rack.shelves?.map((shelf) => ( -
+
{/* Shelf label */}
Shelf {shelf.shelf_symbol}
{/* Positions container */} -
- {shelf.positions.map((position) => ( -
- {/* Position label */} -
Pos {position.position_symbol}
+
+ {shelf.positions.length > 0 ? ( + shelf.positions.map((position) => ( +
onPositionClick(position.position_id)} + > + {/* Position label */} +
Pos {position.position_symbol}
- {/* Sections grid */} -
- {position.sections.map((section) => ( -
- {section.section_symbol} -
- ))} + {/* Sections grid */} +
+ {position.sections.map((section) => ( + +
{ + e.stopPropagation(); + onPositionClick(position.position_id); + }} + > + Sec {section.section_symbol} +
+ ))} +
-
- ))} + )) + ) : ( +
No + positions
+ )}
))} diff --git a/resources/js/Components/modals/EditStockSections.tsx b/resources/js/Components/modals/EditStockSections.tsx index 63d29f5..4b2eb9f 100644 --- a/resources/js/Components/modals/EditStockSections.tsx +++ b/resources/js/Components/modals/EditStockSections.tsx @@ -6,7 +6,7 @@ import { StockPosition, StockSection } from "@/types" interface Props { onClose: () => void - selectedPosition: () => StockPosition + selectedPosition: StockPosition } interface EditableSection { diff --git a/resources/js/Layouts/AppLayout.tsx b/resources/js/Layouts/AppLayout.tsx index b402ad5..47f47e3 100644 --- a/resources/js/Layouts/AppLayout.tsx +++ b/resources/js/Layouts/AppLayout.tsx @@ -90,6 +90,12 @@ export default function AppLayout({ > PDA + + Floor plan +
@@ -323,6 +329,13 @@ export default function AppLayout({ > PDA + + + Floor plan +
{/* */} diff --git a/resources/js/Pages/FloorPlan.tsx b/resources/js/Pages/FloorPlan.tsx index f068778..cf27bcd 100644 --- a/resources/js/Pages/FloorPlan.tsx +++ b/resources/js/Pages/FloorPlan.tsx @@ -3,12 +3,41 @@ import AppLayout from '@/Layouts/AppLayout'; import { Stage, Layer, Rect, Image as KonvaImage, Text, Transformer } from 'react-konva'; import useImage from 'use-image'; import axios from 'axios'; -import {StockRoom, LayoutItem, LayoutLine, StockRack, StockLine} from '@/types'; +import {StockRoom, LayoutItem, LayoutLine, StockRack, StockLine, StockPosition} from '@/types'; import RackModalDetails from "@/Components/RackModalDetails"; +import EditStockSections from '@/Components/modals/EditStockSections'; const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''); export default function FloorPlan() { + + // at the top of FloorPlan() + const [showEditSectionsModal, setShowEditSectionsModal] = useState(false); + const [selectedPositionForEditing, setSelectedPositionForEditing] = useState(null); + + // fire this when RackModalDetails tells us “user clicked a position” + const handleOpenSections = async (posId: number) => { + try { + console.log(posId); + // 1️⃣ pull down the fresh position (with capacity & sections) + const { data: freshPos } = await axios.get( + `/api/stockPositions/${posId}`, + { withCredentials: true } + ); + // 2️⃣ stash it & open the modal + setSelectedPositionForEditing(freshPos); + setShowEditSectionsModal(true); + } catch (err) { + console.error(err); + alert('Could not load position details. Please try again.'); + } + }; + +// pass this into EditStockSections so that onClose we go back to RackModalDetails + const handleCloseSections = () => { + setShowEditSectionsModal(false); + }; + // Rooms & selected room const [rooms, setRooms] = useState([]); const [selectedRoom, setSelectedRoom] = useState(null); @@ -55,6 +84,27 @@ export default function FloorPlan() { .catch(console.error); }, []); + useEffect(() => { + if (!showEditSectionsModal && selectedRoom) { + loadLayout(selectedRoom.room_id); + } + }, [showEditSectionsModal, selectedRoom]); + + useEffect(() => { + if (!showEditSectionsModal && editModal.visible && editModal.type === 'rack' && editModal.item_obj) { + // grab the just-saved rack by its ID: + axios.get(`/api/stock-racks/${(editModal.item_obj as StockRack).rack_id}`, { + withCredentials: true + }) + .then(({ data: freshRack }) => { + setEditModal(m => ({ ...m, item_obj: freshRack })); + }) + .catch(err => { + console.error('Could not refresh rack details:', err); + }); + } + }, [showEditSectionsModal, editModal.visible]); + // Load a room's layout (or show create modal) const loadLayout = async (roomId: number) => { try { @@ -451,7 +501,7 @@ export default function FloorPlan() { {/* Edit Modal */} {editModal.visible && (
-
+

Edit {editModal.type}

Shelves & Sections

- +
)}
@@ -482,6 +532,18 @@ export default function FloorPlan() {
)} + {/* === Sections Editor Nested Modal === */} + {showEditSectionsModal && selectedPositionForEditing && ( +
+
+ +
+
+ )} + {/* Create Layout Modal */} {showCreateModal && (
diff --git a/routes/api.php b/routes/api.php index 300a701..90c0cb9 100644 --- a/routes/api.php +++ b/routes/api.php @@ -126,13 +126,14 @@ Route::get('/stockStatusList', [StockEntryController::class, 'getStatusList']); - Route::get('/pdaView/getStockPosition', [StockPositionController::class, 'getPosition']); + Route::get('/pdaView/getStockPosition/{id}', [StockPositionController::class, 'getPosition']); Route::post('/pdaView/moveStockSection', [StockSectionController::class, 'movePosition']); Route::post('/pdaView/changeCount', [StockSectionController::class, 'changeCount']); Route::put('/stockPositions/{id}', [StockPositionController::class, 'update']); + Route::get('/stockPositions/{id}', [StockPositionController::class, 'getPosition']); Route::get('/stockSections/{id}', [StockSectionController::class, 'getSection']); Route::post('/stockSections', [StockSectionController::class, 'store']); Route::put('/stockSections/{id}', [StockSectionController::class, 'update']); @@ -153,6 +154,7 @@ Route::get('/stockStatusList', [StockEntryController::class, 'getStatusList']); Route::delete ('/stock-lines/{line}', [StockLineController::class, 'destroy']); // Racks + Route::get ('/stock-racks/{rack}', [StockRackController::class, 'show']); Route::post ('/stock-racks', [StockRackController::class, 'store']); Route::put ('/stock-racks/{rack}', [StockRackController::class, 'update']); Route::delete ('/stock-racks/{rack}', [StockRackController::class, 'destroy']); diff --git a/vite.config.ts b/vite.config.ts index 36dc296..d600915 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,30 +1,54 @@ -import { defineConfig } from 'vite'; -import laravel from 'laravel-vite-plugin'; -import react from '@vitejs/plugin-react'; +// vite.config.ts +import { defineConfig } from 'vite' +import laravel from 'laravel-vite-plugin' +import react from '@vitejs/plugin-react' -export default defineConfig({ - plugins: [ - laravel({ - input: 'resources/js/app.tsx', - refresh: true, - }), - react(), - ], - base: './', - resolve: { alias: { '@': '/resources/js' } }, - build: { - outDir: 'public/spa', - emptyOutDir: true, - }, - server: { - host: '0.0.0.0', - port: 5173, - strictPort: true, - // Allow cross‐origin requests from your Laravel app: - cors: true, - hmr: { - host: '10.0.2.2', - port: 5173, +export default defineConfig(({ command }) => { + const isDev = command === 'serve' + const isBuild = command === 'build' + // set EMULATOR=1 in your npm script when you want to work on the Android build + const isEmulator = !!process.env.EMULATOR + + return { + // for web‐dev we load from “/”, for the Capacitor build we need “./” + base: isBuild ? './' : '/', + + plugins: [ + laravel({ + input: 'resources/js/app.tsx', + refresh: true, + }), + react(), + ], + + resolve: { + alias: { + '@': '/resources/js', + }, }, - }, -}); + + // only spin up a dev server when running `vite` or `npm run dev` + ...(isDev && { + server: { + // if you do `--host`, Vite will override this to 0.0.0.0 + host: isEmulator ? '0.0.0.0' : 'localhost', + port: 5173, + strictPort: true, + cors: true, + hmr: { + // emulator needs 10.0.2.2, browser just localhost + host: isEmulator ? '10.0.2.2' : 'localhost', + port: 5173, + }, + }, + }), + + // only emit your Capacitor build when running `vite build` or `npm run build` + ...(isBuild && { + build: { + outDir: 'public/spa', + emptyOutDir: true, + }, + }), + } +})