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:
dwindown
2025-11-08 13:35:24 +07:00
parent e0a236fc64
commit c62fbd9436
6 changed files with 73 additions and 20 deletions

View File

@@ -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>
);