From e267e3c2b29be3ce5fe2e6755cf1b7a0a413ab47 Mon Sep 17 00:00:00 2001 From: dwindown Date: Thu, 20 Nov 2025 10:14:39 +0700 Subject: [PATCH] feat: Standardize table UI across Orders and Products modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Issue:** - Orders and Products had inconsistent table styling - Orders: px-3 py-2, no hover, no header bg - Products: p-3, hover effect, header bg **Solution:** 1. Added comprehensive Table/List UI Standards to PROJECT_SOP.md 2. Updated Orders table to match Products standard **Changes to PROJECT_SOP.md:** - Added "Table/List UI Standards" section - Defined required classes for all table elements - Specified padding: p-3 (NOT px-3 py-2) - Specified header: bg-muted/50 + font-medium - Specified rows: hover:bg-muted/30 - Added empty state and mobile card patterns **Changes to Orders/index.tsx:** - Container: border-border bg-card → border (match Products) - Header: border-b → bg-muted/50 + border-b - Header cells: px-3 py-2 → p-3 font-medium text-left - Body rows: Added hover:bg-muted/30 - Body cells: px-3 py-2 → p-3 - Empty state: px-3 py-12 → p-8 text-muted-foreground **Result:** ✅ Consistent padding across all modules (p-3) ✅ Consistent header styling (bg-muted/50 + font-medium) ✅ Consistent hover effects (hover:bg-muted/30) ✅ Consistent container styling (overflow-hidden) ✅ Documented standard for future modules --- PROJECT_SOP.md | 75 +++++++++++++++++++++++++++ admin-spa/src/routes/Orders/index.tsx | 42 +++++++-------- 2 files changed, 96 insertions(+), 21 deletions(-) diff --git a/PROJECT_SOP.md b/PROJECT_SOP.md index 13f842f..206aefa 100644 --- a/PROJECT_SOP.md +++ b/PROJECT_SOP.md @@ -260,6 +260,81 @@ When updating an existing module to follow this pattern: ``` +#### Table/List UI Standards + +All CRUD list pages MUST follow these consistent UI patterns: + +**Table Structure:** +```tsx +
+ + + + + + {/* ... more columns */} + + + + + + {/* ... more cells */} + + +
{/* Checkbox */}{__('Column')}
{/* Cell content */}
+
+``` + +**Required Classes:** + +| Element | Classes | Purpose | +|---------|---------|---------| +| **Container** | `rounded-lg border overflow-hidden` | Rounded corners, border, hide overflow | +| **Table** | `w-full` | Full width | +| **Header Row** | `bg-muted/50` + `border-b` | Light background, bottom border | +| **Header Cell** | `p-3 font-medium text-left` | Padding, bold, left-aligned | +| **Body Row** | `border-b hover:bg-muted/30 last:border-0` | Border, hover effect, remove last border | +| **Body Cell** | `p-3` | Consistent padding (NOT `px-3 py-2`) | +| **Checkbox Column** | `w-12 p-3` | Fixed width for checkbox | +| **Actions Column** | `text-right p-3` or `text-center p-3` | Right/center aligned | + +**Empty State Pattern:** +```tsx + + + + {primaryMessage} + {helperText &&

{helperText}

} + + +``` + +**Mobile Card Pattern:** +```tsx +
+ {items.map(item => ( + + {/* Card content */} + + ))} +
+``` + +**Rules:** +1. ✅ **Always use `p-3`** for table cells (NOT `px-3 py-2`) +2. ✅ **Always add `hover:bg-muted/30`** to body rows +3. ✅ **Always use `bg-muted/50`** for table headers +4. ✅ **Always use `font-medium`** for header cells +5. ✅ **Always use `last:border-0`** to remove last row border +6. ✅ **Always use `overflow-hidden`** on table container +7. ❌ **Never mix padding styles** between modules +8. ❌ **Never omit hover effects** on interactive rows + +**Responsive Behavior:** +- Desktop: Show table with `hidden md:block` +- Mobile: Show cards with `md:hidden` +- Both views must support same actions (select, edit, delete) + #### Variable Product Handling in Order Forms When adding products to orders, variable products MUST follow the Tokopedia/Shopee pattern: diff --git a/admin-spa/src/routes/Orders/index.tsx b/admin-spa/src/routes/Orders/index.tsx index 99de455..cc9569d 100644 --- a/admin-spa/src/routes/Orders/index.tsx +++ b/admin-spa/src/routes/Orders/index.tsx @@ -392,11 +392,11 @@ export default function Orders() { {/* Desktop: Table */} -
+
- - - + + - - - - - - - + + + + + + + {filteredOrders.map((row) => ( - - + - - - - + - - + - @@ -455,7 +455,7 @@ export default function Orders() { {filteredOrders.length === 0 && ( -
+
{__('Order')}{__('Date')}{__('Customer')}{__('Items')}{__('Status')}{__('Total')}{__('Actions')}{__('Order')}{__('Date')}{__('Customer')}{__('Items')}{__('Status')}{__('Total')}{__('Actions')}
+
toggleRow(row.id)} aria-label={__('Select order')} /> + #{row.number} + {formatRelativeOrDate(row.date_ts)} {row.customer || '—'} + {row.customer || '—'} + {formatMoney(row.total, { currency: row.currency || store.currency, symbol: row.currency_symbol || store.symbol, @@ -446,7 +446,7 @@ export default function Orders() { decimals: store.decimals, })} + {__('Open')} {__('Edit')}
+
{__('No orders found')}