general fixes and ordering display overhaul
This commit is contained in:
@@ -81,6 +81,80 @@ function SplitModal({ item, onConfirm, onClose }) {
|
||||
)
|
||||
}
|
||||
|
||||
// ─── Item action modal (long-press) ──────────────────────────────────────────
|
||||
|
||||
function ItemActionModal({ target, onOrderAgain, onSplit, onClose }) {
|
||||
const { items, singleStacked, multiSelect } = target
|
||||
const label = multiSelect
|
||||
? `${items.length} αντικείμενα επιλεγμένα`
|
||||
: items[0]?.product?.name || `#${items[0]?.product_id}`
|
||||
|
||||
return (
|
||||
<div className="modal-overlay" onClick={onClose}>
|
||||
<div className="modal-sheet" onClick={e => e.stopPropagation()} style={{ gap: 0 }}>
|
||||
<div className="modal-handle" />
|
||||
<p style={{ textAlign: 'center', color: 'var(--muted)', fontSize: 13, margin: '0 0 16px' }}>{label}</p>
|
||||
|
||||
<button
|
||||
onClick={onOrderAgain}
|
||||
style={{
|
||||
width: '100%', display: 'flex', alignItems: 'center', gap: 14,
|
||||
padding: '16px 4px', background: 'none', border: 'none',
|
||||
borderBottom: singleStacked && !multiSelect ? '1px solid var(--border)' : 'none',
|
||||
cursor: 'pointer', textAlign: 'left',
|
||||
}}
|
||||
>
|
||||
<span style={{
|
||||
width: 38, height: 38, borderRadius: 10, flexShrink: 0,
|
||||
background: 'rgba(245,158,11,0.15)',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
}}>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M1 4v6h6M23 20v-6h-6" stroke="#f59e0b" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
<path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4-4.64 4.36A9 9 0 0 1 3.51 15" stroke="#f59e0b" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
</span>
|
||||
<div>
|
||||
<div style={{ fontSize: 15, fontWeight: 600, color: '#f59e0b' }}>Παραγγελία ξανά</div>
|
||||
<div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 1 }}>Προσθήκη στο νέο καλάθι</div>
|
||||
</div>
|
||||
<span style={{ marginLeft: 'auto', color: 'var(--muted)', fontSize: 18 }}>›</span>
|
||||
</button>
|
||||
|
||||
{singleStacked && !multiSelect && (
|
||||
<button
|
||||
onClick={onSplit}
|
||||
style={{
|
||||
width: '100%', display: 'flex', alignItems: 'center', gap: 14,
|
||||
padding: '16px 4px', background: 'none', border: 'none',
|
||||
cursor: 'pointer', textAlign: 'left',
|
||||
}}
|
||||
>
|
||||
<span style={{
|
||||
width: 38, height: 38, borderRadius: 10, flexShrink: 0,
|
||||
background: 'rgba(96,165,250,0.15)',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
}}>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M16 3h5v5M4 20L21 3M21 16v5h-5M15 15l6 6M4 4l5 5" stroke="#60a5fa" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
</span>
|
||||
<div>
|
||||
<div style={{ fontSize: 15, fontWeight: 600, color: '#60a5fa' }}>Διαχωρισμός</div>
|
||||
<div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 1 }}>Χώρισμα σε δύο γραμμές</div>
|
||||
</div>
|
||||
<span style={{ marginLeft: 'auto', color: 'var(--muted)', fontSize: 18 }}>›</span>
|
||||
</button>
|
||||
)}
|
||||
|
||||
<button className="btn btn--secondary" style={{ width: '100%', marginTop: 12 }} onClick={onClose}>
|
||||
Άκυρο
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ─── Actions top sheet ────────────────────────────────────────────────────────
|
||||
|
||||
function ActionsSheet({ order, tableId, onClose, onTransfer, onMerge, onSetFlags, onAssignWaiter, onPrintSynopsis }) {
|
||||
@@ -429,6 +503,7 @@ export default function TableDetailPage() {
|
||||
const [allWaiters, setAllWaiters] = useState([])
|
||||
const [actionDataLoading, setActionDataLoading] = useState(false)
|
||||
const [splitItem, setSplitItem] = useState(null)
|
||||
const [itemActionTarget, setItemActionTarget] = useState(null) // { items: [...], singleStacked: bool }
|
||||
|
||||
const scrollRef = useRef(null)
|
||||
|
||||
@@ -800,7 +875,15 @@ export default function TableDetailPage() {
|
||||
selectable={canInteract && !paying}
|
||||
selectedIds={selectedIds}
|
||||
onToggle={toggleItem}
|
||||
onLongPressItem={(item) => { setSplitItem(item) }}
|
||||
onLongPressItem={(item) => {
|
||||
// If multiple items are selected, order-again all selected items
|
||||
if (selectedIds.length > 1) {
|
||||
const items = activeItems.filter(i => selectedIds.includes(i.id))
|
||||
setItemActionTarget({ items, singleStacked: false, multiSelect: true })
|
||||
} else {
|
||||
setItemActionTarget({ items: [item], singleStacked: item.quantity > 1, multiSelect: false })
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Floating controls row — only visible when items are selected */}
|
||||
@@ -937,6 +1020,32 @@ export default function TableDetailPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Item action modal (long-press) */}
|
||||
{itemActionTarget && (
|
||||
<ItemActionModal
|
||||
target={itemActionTarget}
|
||||
onOrderAgain={() => {
|
||||
const items = itemActionTarget.items
|
||||
sessionStorage.setItem('orderAgainItems', JSON.stringify(
|
||||
items.map(it => ({
|
||||
product_id: it.product_id,
|
||||
quantity: it.quantity,
|
||||
selected_options: (() => { try { return JSON.parse(it.selected_options || '[]') } catch { return [] } })(),
|
||||
removed_ingredients: (() => { try { return JSON.parse(it.removed_ingredients || '[]') } catch { return [] } })(),
|
||||
notes: it.notes || '',
|
||||
}))
|
||||
))
|
||||
setItemActionTarget(null)
|
||||
navigate(`/tables/${tableId}/add`)
|
||||
}}
|
||||
onSplit={() => {
|
||||
setSplitItem(itemActionTarget.items[0])
|
||||
setItemActionTarget(null)
|
||||
}}
|
||||
onClose={() => setItemActionTarget(null)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Split stepper modal */}
|
||||
{splitItem && (
|
||||
<SplitModal
|
||||
|
||||
Reference in New Issue
Block a user