@@ -6,54 +6,26 @@ import {
66 useDeleteAisle ,
77 useUpdateAisle ,
88 getAisleTypesOptions ,
9+ useUpdateStore ,
910} from '@/hooks/use-stores'
1011import { Button } from '@/components/ui/button'
1112import { Card , CardContent , CardHeader , CardTitle } from '@/components/ui/card'
12- import { Badge } from '@/components/ui/badge'
13- import {
14- Table ,
15- TableBody ,
16- TableCell ,
17- TableHead ,
18- TableHeader ,
19- TableRow ,
20- } from '@/components/ui/table'
2113import {
2214 Select ,
2315 SelectContent ,
2416 SelectItem ,
2517 SelectTrigger ,
2618 SelectValue ,
2719} from '@/components/ui/select'
28- import {
29- ArrowLeft ,
30- Plus ,
31- Trash2 ,
32- Move ,
33- Maximize2 ,
34- Pencil ,
35- Save ,
36- } from 'lucide-react'
20+ import { ArrowLeft , Trash2 , Move , Maximize2 , Pencil , Save } from 'lucide-react'
3721import { useSuspenseQuery } from '@tanstack/react-query'
3822import { cn } from '@/lib/utils'
3923import { useState , useRef , useEffect } from 'react'
24+ import type { ResponseType } from '@/lib/api'
4025
4126type Tool = 'draw' | 'move' | 'resize' | 'delete'
4227
43- type AisleType =
44- | 'OBSTACLE'
45- | 'FREEZER'
46- | 'DRINKS'
47- | 'PANTRY'
48- | 'SWEETS'
49- | 'CHEESE'
50- | 'MEAT'
51- | 'DAIRY'
52- | 'FRIDGE'
53- | 'FRUIT'
54- | 'VEGETABLES'
55- | 'BAKERY'
56- | 'OTHER'
28+ type AisleType = ResponseType < '/api/resources/aisle-types' , 'get' , 200 > [ number ]
5729
5830interface Aisle {
5931 id : string
@@ -119,6 +91,7 @@ function AislesPage() {
11991 const createAisle = useCreateAisle ( )
12092 const deleteAisle = useDeleteAisle ( )
12193 const updateAisle = useUpdateAisle ( )
94+ const updateStore = useUpdateStore ( )
12295
12396 // Drawing state
12497 const [ activeTool , setActiveTool ] = useState < Tool | null > ( null )
@@ -128,6 +101,25 @@ function AislesPage() {
128101 const [ modifiedAisles , setModifiedAisles ] = useState <
129102 Map < string , ModifiedAisle >
130103 > ( new Map ( ) )
104+
105+ const [ selectedPoint , setSelectedPoint ] = useState <
106+ 'entrance' | 'exit' | null
107+ > ( null )
108+ const [ localEntranceCoords , setLocalEntranceCoords ] = useState < {
109+ x : number
110+ y : number
111+ } > ( {
112+ x : store . entranceX ,
113+ y : store . entranceY ,
114+ } )
115+ const [ localExitCoords , setLocalExitCoords ] = useState < {
116+ x : number
117+ y : number
118+ } > ( {
119+ x : store . exitX ,
120+ y : store . exitY ,
121+ } )
122+
131123 const [ deletedAisles , setDeletedAisles ] = useState < Set < string > > ( new Set ( ) )
132124 const [ newAisles , setNewAisles ] = useState < ModifiedAisle [ ] > ( [ ] )
133125
@@ -153,17 +145,13 @@ function AislesPage() {
153145 } , [ aisles ] )
154146
155147 const hasModifications =
156- modifiedAisles . size > 0 || deletedAisles . size > 0 || newAisles . length > 0
157-
158- const handleCreateAisle = ( ) => {
159- createAisle . mutate ( { slug } )
160- }
161-
162- const handleDeleteAisle = ( aisleId : string ) => {
163- if ( confirm ( 'Are you sure you want to delete this aisle?' ) ) {
164- deleteAisle . mutate ( { slug, aisleId } )
165- }
166- }
148+ modifiedAisles . size > 0 ||
149+ deletedAisles . size > 0 ||
150+ newAisles . length > 0 ||
151+ store . entranceX !== localEntranceCoords . x ||
152+ store . entranceY !== localEntranceCoords . y ||
153+ store . exitX !== localExitCoords . x ||
154+ store . exitY !== localExitCoords . y
167155
168156 const getGridCoordinates = (
169157 clientX : number ,
@@ -238,6 +226,19 @@ function AislesPage() {
238226 }
239227 } else if ( activeTool === 'move' ) {
240228 const aisle = findAisleAtPosition ( coords . x , coords . y )
229+ if (
230+ coords . x === localEntranceCoords . x &&
231+ coords . y === localEntranceCoords . y
232+ ) {
233+ setSelectedPoint ( 'entrance' )
234+ setDragStart ( coords )
235+ return
236+ }
237+ if ( coords . x === localExitCoords . x && coords . y === localExitCoords . y ) {
238+ setSelectedPoint ( 'exit' )
239+ setDragStart ( coords )
240+ return
241+ }
241242 if ( aisle ) {
242243 setSelectedAisleId ( aisle . id )
243244 setDragStart ( coords )
@@ -337,6 +338,16 @@ function AislesPage() {
337338 )
338339 setDragStart ( coords )
339340 }
341+ } else if ( activeTool === 'move' && selectedPoint && dragStart ) {
342+ const newCoords = getGridCoordinates ( e . clientX , e . clientY )
343+ if ( newCoords ) {
344+ if ( selectedPoint === 'entrance' ) {
345+ setLocalEntranceCoords ( newCoords )
346+ }
347+ if ( selectedPoint === 'exit' ) {
348+ setLocalExitCoords ( newCoords )
349+ }
350+ }
340351 }
341352 }
342353
@@ -391,6 +402,7 @@ function AislesPage() {
391402 setSelectedAisleId ( null )
392403 setDragStart ( null )
393404 setResizeHandle ( null )
405+ setSelectedPoint ( null )
394406 }
395407
396408 const handleSaveChanges = async ( ) => {
@@ -429,6 +441,14 @@ function AislesPage() {
429441 await deleteAisle . mutateAsync ( { slug, aisleId } )
430442 }
431443
444+ await updateStore . mutateAsync ( {
445+ slug,
446+ entranceX : localEntranceCoords . x ,
447+ entranceY : localEntranceCoords . y ,
448+ exitX : localExitCoords . x ,
449+ exitY : localExitCoords . y ,
450+ } )
451+
432452 // Clear modifications
433453 setModifiedAisles ( new Map ( ) )
434454 setDeletedAisles ( new Set ( ) )
@@ -445,6 +465,9 @@ function AislesPage() {
445465 setDeletedAisles ( new Set ( ) )
446466 setNewAisles ( [ ] )
447467 setActiveTool ( null )
468+ setSelectedPoint ( null )
469+ setLocalEntranceCoords ( { x : store . entranceX , y : store . entranceY } )
470+ setLocalExitCoords ( { x : store . exitX , y : store . exitY } )
448471 }
449472
450473 const getPreviewRectangle = ( ) => {
@@ -470,59 +493,6 @@ function AislesPage() {
470493 </ Button >
471494 </ div >
472495
473- < Card className = "mb-6" >
474- < CardHeader className = "flex flex-row items-center justify-between" >
475- < CardTitle > Aisles - { store ?. name } </ CardTitle >
476- < Button onClick = { handleCreateAisle } disabled = { createAisle . isPending } >
477- < Plus className = "mr-2 h-4 w-4" />
478- { createAisle . isPending ? 'Creating...' : 'New Aisle' }
479- </ Button >
480- </ CardHeader >
481- < CardContent >
482- < Table >
483- < TableHeader >
484- < TableRow >
485- < TableHead > Type</ TableHead >
486- < TableHead > Position (X, Y)</ TableHead >
487- < TableHead > Size (W × H)</ TableHead >
488- < TableHead > Actions</ TableHead >
489- </ TableRow >
490- </ TableHeader >
491- < TableBody >
492- { aisles ?. map ( ( aisle ) => (
493- < TableRow key = { aisle . id } >
494- < TableCell >
495- < Badge
496- variant = {
497- aisle . type === 'OBSTACLE' ? 'destructive' : 'secondary'
498- }
499- >
500- { aisle . type }
501- </ Badge >
502- </ TableCell >
503- < TableCell >
504- ({ aisle . gridX } , { aisle . gridY } )
505- </ TableCell >
506- < TableCell >
507- { aisle . width } × { aisle . height }
508- </ TableCell >
509- < TableCell >
510- < Button
511- variant = "ghost"
512- size = "sm"
513- onClick = { ( ) => handleDeleteAisle ( aisle . id ) }
514- disabled = { deleteAisle . isPending }
515- >
516- < Trash2 className = "h-4 w-4 text-red-500" />
517- </ Button >
518- </ TableCell >
519- </ TableRow >
520- ) ) }
521- </ TableBody >
522- </ Table >
523- </ CardContent >
524- </ Card >
525-
526496 { /* Grid Visualization with Drawing Tools */ }
527497 < Card >
528498 < CardHeader className = "flex flex-row items-center justify-between" >
@@ -628,7 +598,7 @@ function AislesPage() {
628598 < div className = "relative bg-gray-100 p-4 rounded-lg overflow-auto" >
629599 < div
630600 ref = { gridRef }
631- className = "grid bg-[#434343] cursor-crosshair"
601+ className = "grid bg-[#434343] cursor-crosshair w-fit "
632602 style = { {
633603 gridTemplateColumns : 'repeat(64, 10px)' ,
634604 gridTemplateRows : 'repeat(64, 10px)' ,
@@ -676,6 +646,44 @@ function AislesPage() {
676646 </ div >
677647 ) ) }
678648
649+ { /* Entrance */ }
650+
651+ < div
652+ id = "store-entrance"
653+ className = { cn (
654+ 'bg-green-400' ,
655+ activeTool === 'move' && 'cursor-move' ,
656+ activeTool === 'resize' && 'cursor-not-allowed' ,
657+ activeTool === 'delete' && 'cursor-not-allowed' ,
658+ ) }
659+ style = { {
660+ gridColumnStart : localEntranceCoords . x + 1 ,
661+ gridColumnEnd : localEntranceCoords . x + 1 ,
662+ gridRowStart : localEntranceCoords . y + 1 ,
663+ gridRowEnd : localEntranceCoords . y + 1 ,
664+ } }
665+ >
666+ Enter
667+ </ div >
668+ { /* Exit */ }
669+ < div
670+ id = "store-exit"
671+ className = { cn (
672+ 'bg-red-400' ,
673+ activeTool === 'move' && 'cursor-move' ,
674+ activeTool === 'resize' && 'cursor-not-allowed' ,
675+ activeTool === 'delete' && 'cursor-not-allowed' ,
676+ ) }
677+ style = { {
678+ gridColumnStart : localExitCoords . x + 1 ,
679+ gridColumnEnd : localExitCoords . x + 1 ,
680+ gridRowStart : localExitCoords . y + 1 ,
681+ gridRowEnd : localExitCoords . y + 1 ,
682+ } }
683+ >
684+ Exit
685+ </ div >
686+
679687 { /* Draw preview */ }
680688 { preview && (
681689 < div
0 commit comments