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:
dwindown
2025-11-21 00:51:31 +07:00
parent 82a42bf9c2
commit bc4b64fd2f

View File

@@ -201,40 +201,90 @@ export default function CustomerDetail() {
<p className="text-sm mt-1">{__('This customer hasn\'t placed any orders')}</p> <p className="text-sm mt-1">{__('This customer hasn\'t placed any orders')}</p>
</div> </div>
) : ( ) : (
<div className="space-y-2"> <>
{orders.map((order: any) => ( {/* Desktop: Table */}
<Link <div className="hidden md:block overflow-hidden rounded-lg border">
key={order.id} <table className="w-full">
to={`/orders/${order.id}`} <thead className="bg-muted/50">
className="block p-4 rounded-lg border border-border hover:bg-accent/50 transition-colors" <tr className="border-b">
> <th className="text-left p-3 font-medium">{__('Order')}</th>
<div className="flex items-center justify-between"> <th className="text-left p-3 font-medium">{__('Date')}</th>
<div className="flex-1"> <th className="text-left p-3 font-medium">{__('Status')}</th>
<div className="flex items-center gap-3"> <th className="text-right p-3 font-medium">{__('Items')}</th>
<span className="font-medium">#{order.number}</span> <th className="text-right p-3 font-medium">{__('Total')}</th>
<span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${ </tr>
order.status === 'completed' ? 'bg-green-100 text-green-800' : </thead>
order.status === 'processing' ? 'bg-blue-100 text-blue-800' : <tbody>
order.status === 'pending' ? 'bg-yellow-100 text-yellow-800' : {orders.map((order: any) => (
'bg-gray-100 text-gray-800' <tr
}`}> key={order.id}
{order.status} onClick={() => navigate(`/orders/${order.id}`)}
</span> 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>
<div className="text-sm text-muted-foreground mt-1"> <div className="text-right">
{order.date ? new Date(order.date).toLocaleDateString('id-ID') : '-'} <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> </div>
<div className="text-right"> </Link>
<div className="font-bold">{formatMoney(parseFloat(order.total || '0'))}</div> ))}
<div className="text-sm text-muted-foreground"> </div>
{order.items_count || 0} {__('items')} </>
</div>
</div>
</div>
</Link>
))}
</div>
)} )}
</Card> </Card>
</FormSection> </FormSection>