refine: Polish mobile Orders UI based on feedback
Addressed all three feedback points from user testing. 1. OrderCard Layout Improvements Problem: Card felt too dense, cramped spacing Changes: - Increased icon size: 10x10 → 12x12 - Increased icon padding: w-10 h-10 → w-12 h-12 - Rounded corners: rounded-lg → rounded-xl - Added shadow-sm for depth - Increased gap between elements: gap-3 → gap-4 - Added space-y-2 for vertical rhythm - Made order number bolder: font-semibold → font-bold - Increased order number size: text-base → text-lg - Made customer name font-medium (was muted) - Made total amount bolder and colored: font-semibold → font-bold text-primary - Increased total size: text-base → text-lg - Better status badge: px-2 py-0.5 → px-2.5 py-1, font-medium → font-semibold - Larger checkbox: default → w-5 h-5 - Centered chevron vertically: mt-2 → self-center Result: More breathing room, better hierarchy, easier to scan 2. FilterBottomSheet Z-Index & Padding Problem: Bottom sheet covered by FAB and bottom nav Changes: - Increased backdrop z-index: z-40 → z-[60] - Increased sheet z-index: z-50 → z-[70] (above FAB z-50) - Made sheet flexbox: added flex flex-col - Made content scrollable: added flex-1 overflow-y-auto - Added bottom padding: pb-24 (space for bottom nav) Result: Sheet now covers FAB, content scrolls, bottom nav visible 3. Contextual Headers for Order Pages Problem: Order Detail, New, Edit pages are actionable but had no headers Solution: Added contextual headers to all three pages Order Detail: - Header: "Order #337" - Actions: [Invoice] [Edit] buttons - Shows order number dynamically - Hides in print mode New Order: - Header: "New Order" - No actions (form has submit) Edit Order: - Header: "Edit Order #337" - No actions (form has submit) - Shows order number dynamically Implementation: - Import usePageHeader - useEffect to set/clear header - Order Detail: Custom action buttons - New/Edit: Simple title only Files Modified: - routes/Orders/components/OrderCard.tsx - routes/Orders/components/FilterBottomSheet.tsx - routes/Orders/Detail.tsx - routes/Orders/New.tsx - routes/Orders/Edit.tsx Result: ✅ Cards feel spacious and scannable ✅ Filter sheet properly layered ✅ Order pages have contextual headers ✅ Consistent mobile UX across all order flows ✅ Professional, polished feel! 🎯
This commit is contained in:
@@ -29,9 +29,9 @@ export function OrderCard({ order, selected, onSelect, currencyConfig }: OrderCa
|
||||
return (
|
||||
<Link
|
||||
to={`/orders/${order.id}`}
|
||||
className="block bg-card border border-border rounded-lg p-4 hover:bg-accent/50 transition-colors active:scale-[0.98] active:transition-transform"
|
||||
className="block bg-card border border-border rounded-xl p-4 hover:bg-accent/50 transition-colors active:scale-[0.98] active:transition-transform shadow-sm"
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex items-start gap-4">
|
||||
{/* Checkbox */}
|
||||
{onSelect && (
|
||||
<div
|
||||
@@ -40,48 +40,49 @@ export function OrderCard({ order, selected, onSelect, currencyConfig }: OrderCa
|
||||
e.stopPropagation();
|
||||
onSelect(order.id);
|
||||
}}
|
||||
className="pt-1"
|
||||
className="pt-0.5"
|
||||
>
|
||||
<Checkbox
|
||||
checked={selected}
|
||||
aria-label={__('Select order')}
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Icon */}
|
||||
<div className="flex-shrink-0 w-10 h-10 rounded-lg bg-primary/10 text-primary flex items-center justify-center">
|
||||
<Package className="w-5 h-5" />
|
||||
<div className="flex-shrink-0 w-12 h-12 rounded-xl bg-primary/10 text-primary flex items-center justify-center">
|
||||
<Package className="w-6 h-6" />
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex-1 min-w-0 space-y-2">
|
||||
{/* Order Number & Status */}
|
||||
<div className="flex items-center justify-between gap-2 mb-1">
|
||||
<h3 className="font-semibold text-base">#{order.number}</h3>
|
||||
<span className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium capitalize ${statusClass}`}>
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<h3 className="font-bold text-lg leading-tight">#{order.number}</h3>
|
||||
<span className={`inline-flex items-center px-2.5 py-1 rounded-md text-xs font-semibold capitalize whitespace-nowrap ${statusClass}`}>
|
||||
{order.status || 'unknown'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Customer */}
|
||||
<div className="text-sm text-muted-foreground mb-2">
|
||||
<div className="text-sm font-medium text-foreground">
|
||||
{order.customer || __('Guest')}
|
||||
</div>
|
||||
|
||||
{/* Items Brief */}
|
||||
{order.items_brief && (
|
||||
<div className="text-sm text-muted-foreground mb-2 truncate">
|
||||
<div className="text-sm text-muted-foreground truncate">
|
||||
{order.items_count} {order.items_count === 1 ? __('item') : __('items')} · {order.items_brief}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Date & Total */}
|
||||
<div className="flex items-center justify-between gap-2 mt-2">
|
||||
<div className="flex items-center justify-between gap-3 pt-1">
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{formatRelativeOrDate(order.date_ts)}
|
||||
</span>
|
||||
<span className="font-semibold text-base tabular-nums">
|
||||
<span className="font-bold text-lg tabular-nums text-primary">
|
||||
{formatMoney(order.total, {
|
||||
currency: order.currency || currencyConfig.currency,
|
||||
symbol: order.currency_symbol || currencyConfig.symbol,
|
||||
@@ -95,7 +96,7 @@ export function OrderCard({ order, selected, onSelect, currencyConfig }: OrderCa
|
||||
</div>
|
||||
|
||||
{/* Chevron */}
|
||||
<ChevronRight className="w-5 h-5 text-muted-foreground flex-shrink-0 mt-2" />
|
||||
<ChevronRight className="w-5 h-5 text-muted-foreground flex-shrink-0 self-center" />
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user