feat(customers): Add responsive table for orders on desktop
Improved Orders section with proper responsive design: Desktop (≥768px): ✅ Clean table layout ✅ Columns: Order | Date | Status | Items | Total ✅ Hover effect on rows ✅ Click row to view order ✅ Compact, scannable format ✅ Right-aligned numbers ✅ Status badges Mobile (<768px): ✅ Card layout (existing) ✅ Full order details ✅ Touch-friendly ✅ Status badges ✅ Tap to view order Table Structure: ┌─────────┬────────────┬──────────┬───────┬──────────┐ │ Order │ Date │ Status │ Items │ Total │ ├─────────┼────────────┼──────────┼───────┼──────────┤ │ #360 │ 18/11/2025 │ ●complete│ 12 │ Rp1.5jt │ │ #359 │ 18/11/2025 │ ●pending │ 2 │ Rp129k │ │ #358 │ 18/11/2025 │ ●on-hold │ 1 │ Rp129k │ └─────────┴────────────┴──────────┴───────┴──────────┘ Benefits: ✅ Desktop: Compact, professional table ✅ Mobile: Rich card details ✅ Consistent with PROJECT_SOP.md patterns ✅ Better use of desktop space ✅ Easy to scan multiple orders ✅ Click/tap anywhere on row/card Technical: - Desktop: table - Mobile: cards - Cursor pointer on table rows - Hover effects on both - Status badge colors (green/blue/yellow/gray) Result: Orders section now has proper responsive layout!
This commit is contained in:
@@ -201,40 +201,90 @@ export default function CustomerDetail() {
|
||||
<p className="text-sm mt-1">{__('This customer hasn\'t placed any orders')}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
{orders.map((order: any) => (
|
||||
<Link
|
||||
key={order.id}
|
||||
to={`/orders/${order.id}`}
|
||||
className="block p-4 rounded-lg border border-border hover:bg-accent/50 transition-colors"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="font-medium">#{order.number}</span>
|
||||
<span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${
|
||||
order.status === 'completed' ? 'bg-green-100 text-green-800' :
|
||||
order.status === 'processing' ? 'bg-blue-100 text-blue-800' :
|
||||
order.status === 'pending' ? 'bg-yellow-100 text-yellow-800' :
|
||||
'bg-gray-100 text-gray-800'
|
||||
}`}>
|
||||
{order.status}
|
||||
</span>
|
||||
<>
|
||||
{/* Desktop: Table */}
|
||||
<div className="hidden md:block overflow-hidden rounded-lg border">
|
||||
<table className="w-full">
|
||||
<thead className="bg-muted/50">
|
||||
<tr className="border-b">
|
||||
<th className="text-left p-3 font-medium">{__('Order')}</th>
|
||||
<th className="text-left p-3 font-medium">{__('Date')}</th>
|
||||
<th className="text-left p-3 font-medium">{__('Status')}</th>
|
||||
<th className="text-right p-3 font-medium">{__('Items')}</th>
|
||||
<th className="text-right p-3 font-medium">{__('Total')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{orders.map((order: any) => (
|
||||
<tr
|
||||
key={order.id}
|
||||
onClick={() => navigate(`/orders/${order.id}`)}
|
||||
className="border-b hover:bg-muted/30 last:border-0 cursor-pointer"
|
||||
>
|
||||
<td className="p-3">
|
||||
<span className="font-medium">#{order.number}</span>
|
||||
</td>
|
||||
<td className="p-3 text-sm text-muted-foreground">
|
||||
{order.date ? new Date(order.date).toLocaleDateString('id-ID') : '-'}
|
||||
</td>
|
||||
<td className="p-3">
|
||||
<span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${
|
||||
order.status === 'completed' ? 'bg-green-100 text-green-800' :
|
||||
order.status === 'processing' ? 'bg-blue-100 text-blue-800' :
|
||||
order.status === 'pending' ? 'bg-yellow-100 text-yellow-800' :
|
||||
'bg-gray-100 text-gray-800'
|
||||
}`}>
|
||||
{order.status}
|
||||
</span>
|
||||
</td>
|
||||
<td className="p-3 text-right text-sm">
|
||||
{order.items_count || 0}
|
||||
</td>
|
||||
<td className="p-3 text-right font-medium">
|
||||
{formatMoney(parseFloat(order.total || '0'))}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{/* Mobile: Cards */}
|
||||
<div className="md:hidden space-y-2">
|
||||
{orders.map((order: any) => (
|
||||
<Link
|
||||
key={order.id}
|
||||
to={`/orders/${order.id}`}
|
||||
className="block p-4 rounded-lg border border-border hover:bg-accent/50 transition-colors"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="font-medium">#{order.number}</span>
|
||||
<span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${
|
||||
order.status === 'completed' ? 'bg-green-100 text-green-800' :
|
||||
order.status === 'processing' ? 'bg-blue-100 text-blue-800' :
|
||||
order.status === 'pending' ? 'bg-yellow-100 text-yellow-800' :
|
||||
'bg-gray-100 text-gray-800'
|
||||
}`}>
|
||||
{order.status}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-sm text-muted-foreground mt-1">
|
||||
{order.date ? new Date(order.date).toLocaleDateString('id-ID') : '-'}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm text-muted-foreground mt-1">
|
||||
{order.date ? new Date(order.date).toLocaleDateString('id-ID') : '-'}
|
||||
<div className="text-right">
|
||||
<div className="font-bold">{formatMoney(parseFloat(order.total || '0'))}</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{order.items_count || 0} {__('items')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="font-bold">{formatMoney(parseFloat(order.total || '0'))}</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{order.items_count || 0} {__('items')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
</FormSection>
|
||||
|
||||
Reference in New Issue
Block a user