vite cfg fix, floorplan
This commit is contained in:
parent
2b9391f5e9
commit
f97b49cbdf
@ -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
|
// 1) Eager‐load the real relationships
|
||||||
$position = StockPosition::with([
|
$position = StockPosition::with([
|
||||||
'sections.entries.physicalItem',
|
'sections.entries.physicalItem',
|
||||||
'shelf.rack.line.room',
|
'shelf.rack.line.room',
|
||||||
])->findOrFail(2);
|
])->findOrFail($id);
|
||||||
|
|
||||||
// 2) Compute the storage address string
|
// 2) Compute the storage address string
|
||||||
$position->storage_address = $position->storageAddress();
|
$position->storage_address = $position->storageAddress();
|
||||||
|
@ -22,6 +22,13 @@ class StockRackController extends Controller
|
|||||||
return response()->json($rack, 201);
|
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)
|
public function update(Request $request, StockRack $rack)
|
||||||
{
|
{
|
||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"dev": "vite"
|
"dev": "vite",
|
||||||
|
"dev:android": "EMULATOR=1 vite --host 0.0.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@capacitor/cli": "^7.4.1",
|
"@capacitor/cli": "^7.4.1",
|
||||||
|
@ -1,40 +1,56 @@
|
|||||||
// components/RackDetails.tsx
|
// components/RackDetails.tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {StockRack} from '@/types';
|
import {StockRack, StockPosition} from '@/types';
|
||||||
|
|
||||||
interface RackDetailsProps {
|
interface RackDetailsProps {
|
||||||
rack: StockRack | null;
|
rack: StockRack | null;
|
||||||
|
onPositionClick: (posId: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RackModalDetails({ rack }: RackDetailsProps) {
|
export default function RackModalDetails({rack, onPositionClick}: RackDetailsProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="overflow-auto p-4">
|
<div className="overflow-auto p-4">
|
||||||
<div className="flex flex-col space-y-4">
|
<div className="flex flex-col space-y-4">
|
||||||
{rack.shelves?.map((shelf) => (
|
{rack.shelves?.map((shelf) => (
|
||||||
<div key={shelf.shelf_symbol} className="flex items-start space-x-4">
|
<div key={shelf.shelf_symbol} className="flex items-start space-x-4 flex-col">
|
||||||
{/* Shelf label */}
|
{/* Shelf label */}
|
||||||
<div className="font-bold">Shelf {shelf.shelf_symbol}</div>
|
<div className="font-bold">Shelf {shelf.shelf_symbol}</div>
|
||||||
|
|
||||||
{/* Positions container */}
|
{/* Positions container */}
|
||||||
<div className="flex space-x-4">
|
<div className="flex space-x-4 border border-white dark:border-gray-700 h-max min-h-40 w-full">
|
||||||
{shelf.positions.map((position) => (
|
{shelf.positions.length > 0 ? (
|
||||||
<div key={position.position_symbol} className="border rounded-lg p-3">
|
shelf.positions.map((position) => (
|
||||||
{/* Position label */}
|
<div
|
||||||
<div className="font-semibold mb-2">Pos {position.position_symbol}</div>
|
key={position.position_symbol}
|
||||||
|
className="border rounded-lg p-3 w-full cursor-pointer"
|
||||||
|
onClick={() => onPositionClick(position.position_id)}
|
||||||
|
>
|
||||||
|
{/* Position label */}
|
||||||
|
<div className="font-semibold mb-2">Pos {position.position_symbol}</div>
|
||||||
|
|
||||||
{/* Sections grid */}
|
{/* Sections grid */}
|
||||||
<div className="grid grid-cols-3 gap-2">
|
<div className="grid grid-cols-1 gap-2">
|
||||||
{position.sections.map((section) => (
|
{position.sections.map((section) => (
|
||||||
<div
|
|
||||||
key={section.section_symbol}
|
<div
|
||||||
className="border rounded p-1 text-sm text-center"
|
key={section.section_symbol}
|
||||||
>
|
className="border rounded p-1 text-center bg-primary font-bold cursor-pointer"
|
||||||
{section.section_symbol}
|
onClick={(e) => {
|
||||||
</div>
|
e.stopPropagation();
|
||||||
))}
|
onPositionClick(position.position_id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Sec {section.section_symbol}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))
|
||||||
))}
|
) : (
|
||||||
|
<div className="border rounded-lg p-3 w-full flex items-center justify-center">No
|
||||||
|
positions</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
@ -6,7 +6,7 @@ import { StockPosition, StockSection } from "@/types"
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
selectedPosition: () => StockPosition
|
selectedPosition: StockPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EditableSection {
|
interface EditableSection {
|
||||||
|
@ -90,6 +90,12 @@ export default function AppLayout({
|
|||||||
>
|
>
|
||||||
PDA
|
PDA
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
<NavLink
|
||||||
|
href={route('floorPlan')}
|
||||||
|
active={route().current('floorPlan')}
|
||||||
|
>
|
||||||
|
Floor plan
|
||||||
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -323,6 +329,13 @@ export default function AppLayout({
|
|||||||
>
|
>
|
||||||
PDA
|
PDA
|
||||||
</ResponsiveNavLink>
|
</ResponsiveNavLink>
|
||||||
|
|
||||||
|
<ResponsiveNavLink
|
||||||
|
href={route('floorPlan')}
|
||||||
|
active={route().current('floorPlan')}
|
||||||
|
>
|
||||||
|
Floor plan
|
||||||
|
</ResponsiveNavLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <!-- Responsive Settings Options --> */}
|
{/* <!-- Responsive Settings Options --> */}
|
||||||
|
@ -3,12 +3,41 @@ import AppLayout from '@/Layouts/AppLayout';
|
|||||||
import { Stage, Layer, Rect, Image as KonvaImage, Text, Transformer } from 'react-konva';
|
import { Stage, Layer, Rect, Image as KonvaImage, Text, Transformer } from 'react-konva';
|
||||||
import useImage from 'use-image';
|
import useImage from 'use-image';
|
||||||
import axios from 'axios';
|
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 RackModalDetails from "@/Components/RackModalDetails";
|
||||||
|
import EditStockSections from '@/Components/modals/EditStockSections';
|
||||||
|
|
||||||
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
||||||
|
|
||||||
export default function FloorPlan() {
|
export default function FloorPlan() {
|
||||||
|
|
||||||
|
// at the top of FloorPlan()
|
||||||
|
const [showEditSectionsModal, setShowEditSectionsModal] = useState(false);
|
||||||
|
const [selectedPositionForEditing, setSelectedPositionForEditing] = useState<StockPosition | null>(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<StockPosition>(
|
||||||
|
`/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
|
// Rooms & selected room
|
||||||
const [rooms, setRooms] = useState<StockRoom[]>([]);
|
const [rooms, setRooms] = useState<StockRoom[]>([]);
|
||||||
const [selectedRoom, setSelectedRoom] = useState<StockRoom | null>(null);
|
const [selectedRoom, setSelectedRoom] = useState<StockRoom | null>(null);
|
||||||
@ -55,6 +84,27 @@ export default function FloorPlan() {
|
|||||||
.catch(console.error);
|
.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<StockRack>(`/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)
|
// Load a room's layout (or show create modal)
|
||||||
const loadLayout = async (roomId: number) => {
|
const loadLayout = async (roomId: number) => {
|
||||||
try {
|
try {
|
||||||
@ -451,7 +501,7 @@ export default function FloorPlan() {
|
|||||||
{/* Edit Modal */}
|
{/* Edit Modal */}
|
||||||
{editModal.visible && (
|
{editModal.visible && (
|
||||||
<div className="modal modal-open">
|
<div className="modal modal-open">
|
||||||
<div className="modal-box">
|
<div className="modal-box max-w-[50%]">
|
||||||
<h3 className="font-bold text-lg">Edit {editModal.type}</h3>
|
<h3 className="font-bold text-lg">Edit {editModal.type}</h3>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@ -470,7 +520,7 @@ export default function FloorPlan() {
|
|||||||
{editModal.type === 'rack' && (
|
{editModal.type === 'rack' && (
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<h4 className="font-bold mb-2">Shelves & Sections</h4>
|
<h4 className="font-bold mb-2">Shelves & Sections</h4>
|
||||||
<RackModalDetails rack={editModal.item_obj} />
|
<RackModalDetails rack={editModal.item_obj} onPositionClick={handleOpenSections} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="modal-action">
|
<div className="modal-action">
|
||||||
@ -482,6 +532,18 @@ export default function FloorPlan() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* === Sections Editor Nested Modal === */}
|
||||||
|
{showEditSectionsModal && selectedPositionForEditing && (
|
||||||
|
<div className="modal modal-open">
|
||||||
|
<div className="modal-box max-w-[50%]">
|
||||||
|
<EditStockSections
|
||||||
|
selectedPosition={selectedPositionForEditing}
|
||||||
|
onClose={handleCloseSections}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Create Layout Modal */}
|
{/* Create Layout Modal */}
|
||||||
{showCreateModal && (
|
{showCreateModal && (
|
||||||
<div className="modal modal-open">
|
<div className="modal modal-open">
|
||||||
|
@ -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/moveStockSection', [StockSectionController::class, 'movePosition']);
|
||||||
Route::post('/pdaView/changeCount', [StockSectionController::class, 'changeCount']);
|
Route::post('/pdaView/changeCount', [StockSectionController::class, 'changeCount']);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Route::put('/stockPositions/{id}', [StockPositionController::class, 'update']);
|
Route::put('/stockPositions/{id}', [StockPositionController::class, 'update']);
|
||||||
|
Route::get('/stockPositions/{id}', [StockPositionController::class, 'getPosition']);
|
||||||
Route::get('/stockSections/{id}', [StockSectionController::class, 'getSection']);
|
Route::get('/stockSections/{id}', [StockSectionController::class, 'getSection']);
|
||||||
Route::post('/stockSections', [StockSectionController::class, 'store']);
|
Route::post('/stockSections', [StockSectionController::class, 'store']);
|
||||||
Route::put('/stockSections/{id}', [StockSectionController::class, 'update']);
|
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']);
|
Route::delete ('/stock-lines/{line}', [StockLineController::class, 'destroy']);
|
||||||
|
|
||||||
// Racks
|
// Racks
|
||||||
|
Route::get ('/stock-racks/{rack}', [StockRackController::class, 'show']);
|
||||||
Route::post ('/stock-racks', [StockRackController::class, 'store']);
|
Route::post ('/stock-racks', [StockRackController::class, 'store']);
|
||||||
Route::put ('/stock-racks/{rack}', [StockRackController::class, 'update']);
|
Route::put ('/stock-racks/{rack}', [StockRackController::class, 'update']);
|
||||||
Route::delete ('/stock-racks/{rack}', [StockRackController::class, 'destroy']);
|
Route::delete ('/stock-racks/{rack}', [StockRackController::class, 'destroy']);
|
||||||
|
@ -1,30 +1,54 @@
|
|||||||
import { defineConfig } from 'vite';
|
// vite.config.ts
|
||||||
import laravel from 'laravel-vite-plugin';
|
import { defineConfig } from 'vite'
|
||||||
import react from '@vitejs/plugin-react';
|
import laravel from 'laravel-vite-plugin'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig(({ command }) => {
|
||||||
plugins: [
|
const isDev = command === 'serve'
|
||||||
laravel({
|
const isBuild = command === 'build'
|
||||||
input: 'resources/js/app.tsx',
|
// set EMULATOR=1 in your npm script when you want to work on the Android build
|
||||||
refresh: true,
|
const isEmulator = !!process.env.EMULATOR
|
||||||
}),
|
|
||||||
react(),
|
return {
|
||||||
],
|
// for web‐dev we load from “/”, for the Capacitor build we need “./”
|
||||||
base: './',
|
base: isBuild ? './' : '/',
|
||||||
resolve: { alias: { '@': '/resources/js' } },
|
|
||||||
build: {
|
plugins: [
|
||||||
outDir: 'public/spa',
|
laravel({
|
||||||
emptyOutDir: true,
|
input: 'resources/js/app.tsx',
|
||||||
},
|
refresh: true,
|
||||||
server: {
|
}),
|
||||||
host: '0.0.0.0',
|
react(),
|
||||||
port: 5173,
|
],
|
||||||
strictPort: true,
|
|
||||||
// Allow cross‐origin requests from your Laravel app:
|
resolve: {
|
||||||
cors: true,
|
alias: {
|
||||||
hmr: {
|
'@': '/resources/js',
|
||||||
host: '10.0.2.2',
|
},
|
||||||
port: 5173,
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
});
|
// 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,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user