11import { useState } from 'react' ;
22import { X , Scissors } from 'lucide-react' ;
33import { useEscapeKey } from '@/hooks/use-escape-key' ;
4+ import { SearchableSelect } from '@/components/ui/searchable-select' ;
45
56type OrderItem = {
67 id : number ;
@@ -14,6 +15,12 @@ type OrderItem = {
1415 addons : { addon : { name : string } | null } [ ] ;
1516} ;
1617
18+ type DiningTable = {
19+ id : number ;
20+ name : string ;
21+ dining_area : { name : string } | null ;
22+ } ;
23+
1724type SplitItem = {
1825 order_item_id : number ;
1926 quantity : number ;
@@ -23,19 +30,21 @@ type Props = {
2330 orderId : number ;
2431 orderNumber : string ;
2532 items : OrderItem [ ] ;
33+ tables ?: DiningTable [ ] ;
2634 onClose : ( ) => void ;
27- onSplit : ( items : SplitItem [ ] ) => Promise < void > ;
35+ onSplit : ( items : SplitItem [ ] , diningTableId : number | null ) => Promise < void > ;
2836 loading ?: boolean ;
2937} ;
3038
31- export function OrderSplitModal ( { orderId, orderNumber, items, onClose, onSplit, loading } : Props ) {
39+ export function OrderSplitModal ( { orderId, orderNumber, items, tables = [ ] , onClose, onSplit, loading } : Props ) {
3240 useEscapeKey ( onClose ) ;
3341
3442 const activeItems = items . filter ( ( i ) => i . status !== 'cancelled' ) ;
3543 const [ selected , setSelected ] = useState < Record < number , boolean > > ( { } ) ;
3644 const [ quantities , setQuantities ] = useState < Record < number , number > > ( ( ) =>
3745 Object . fromEntries ( activeItems . map ( ( i ) => [ i . id , parseFloat ( String ( i . quantity ) ) ] ) )
3846 ) ;
47+ const [ diningTableId , setDiningTableId ] = useState < number | null > ( null ) ;
3948 const [ submitting , setSubmitting ] = useState ( false ) ;
4049 const [ error , setError ] = useState < string | null > ( null ) ;
4150
@@ -46,7 +55,7 @@ export function OrderSplitModal({ orderId, orderNumber, items, onClose, onSplit,
4655 }
4756
4857 function setQty ( id : number , val : number , max : number ) {
49- setQuantities ( ( prev ) => ( { ...prev , [ id ] : Math . max ( 0.01 , Math . min ( val , max ) ) } ) ) ;
58+ setQuantities ( ( prev ) => ( { ...prev , [ id ] : Math . max ( 1 , Math . min ( Math . floor ( val ) , max ) ) } ) ) ;
5059 }
5160
5261 async function handleSubmit ( ) {
@@ -59,7 +68,7 @@ export function OrderSplitModal({ orderId, orderNumber, items, onClose, onSplit,
5968 setSubmitting ( true ) ;
6069 setError ( null ) ;
6170 try {
62- await onSplit ( splitItems ) ;
71+ await onSplit ( splitItems , diningTableId ) ;
6372 } catch ( e : any ) {
6473 setError ( e ?. message ?? 'Split failed.' ) ;
6574 } finally {
@@ -85,8 +94,29 @@ export function OrderSplitModal({ orderId, orderNumber, items, onClose, onSplit,
8594 </ div >
8695
8796 { /* Content */ }
88- < div className = "flex-1 overflow-y-auto p-4 space-y-2" >
89- < p className = "text-xs text-muted-foreground mb-3" > Select items to move into a new order. The original order keeps the remaining items.</ p >
97+ < div className = "flex-1 overflow-y-auto p-4 space-y-3" >
98+ < p className = "text-xs text-muted-foreground" > Select items to move into a new order. The original order keeps the remaining items.</ p >
99+
100+ { /* Table selector for new order */ }
101+ { tables . length > 0 && (
102+ < div className = "rounded-lg border border-border dark:border-stone-700 p-3 space-y-1.5" >
103+ < label className = "text-xs font-semibold text-foreground" > Table for new order</ label >
104+ < SearchableSelect
105+ value = { diningTableId ?? '' }
106+ placeholder = "Same as original order"
107+ onChange = { ( e ) => setDiningTableId ( e . target . value ? Number ( e . target . value ) : null ) }
108+ >
109+ < option value = "" > Same as original order</ option >
110+ { tables . map ( ( t ) => (
111+ < option key = { t . id } value = { t . id } >
112+ { t . dining_area ? `${ t . dining_area . name } - ` : '' } { t . name }
113+ </ option >
114+ ) ) }
115+ </ SearchableSelect >
116+ </ div >
117+ ) }
118+
119+ { /* Items */ }
90120 { activeItems . map ( ( item ) => {
91121 const max = parseFloat ( String ( item . quantity ) ) ;
92122 const isSelected = ! ! selected [ item . id ] ;
@@ -121,7 +151,7 @@ export function OrderSplitModal({ orderId, orderNumber, items, onClose, onSplit,
121151 < span className = "text-xs text-muted-foreground" > Qty to split:</ span >
122152 < input
123153 type = "number"
124- min = "0.01 "
154+ min = "1 "
125155 max = { max }
126156 step = "1"
127157 value = { quantities [ item . id ] }
@@ -143,20 +173,20 @@ export function OrderSplitModal({ orderId, orderNumber, items, onClose, onSplit,
143173 < div className = "border-t border-border dark:border-stone-800 px-4 py-3 flex flex-col gap-2" >
144174 { error && < p className = "text-xs text-red-500" > { error } </ p > }
145175 < div className = "flex items-center justify-between gap-3" >
146- < span className = "text-xs text-muted-foreground" > { selectedCount } item{ selectedCount !== 1 ? 's' : '' } selected</ span >
147- < div className = "flex gap-2" >
148- < button type = "button" onClick = { onClose } className = "rounded-lg border border-border px-3 py-1.5 text-xs font-semibold hover:bg-muted dark:border-stone-700" >
149- Cancel
150- </ button >
151- < button
152- type = "button"
153- onClick = { handleSubmit }
154- disabled = { selectedCount === 0 || submitting }
155- className = "rounded-lg bg-primary px-3 py-1.5 text-xs font-bold text-white disabled:opacity-50 hover:opacity-90"
156- >
157- { submitting ? 'Splitting...' : 'Split Order' }
158- </ button >
159- </ div >
176+ < span className = "text-xs text-muted-foreground" > { selectedCount } item{ selectedCount !== 1 ? 's' : '' } selected</ span >
177+ < div className = "flex gap-2" >
178+ < button type = "button" onClick = { onClose } className = "rounded-lg border border-border px-3 py-1.5 text-xs font-semibold hover:bg-muted dark:border-stone-700" >
179+ Cancel
180+ </ button >
181+ < button
182+ type = "button"
183+ onClick = { handleSubmit }
184+ disabled = { selectedCount === 0 || submitting }
185+ className = "rounded-lg bg-primary px-3 py-1.5 text-xs font-bold text-white disabled:opacity-50 hover:opacity-90"
186+ >
187+ { submitting ? 'Splitting...' : 'Split Order' }
188+ </ button >
189+ </ div >
160190 </ div >
161191 </ div >
162192 </ div >
0 commit comments