fix(ui): Ensure Customer module UI/UX consistency with SOP

Aligned Customers module with Products/Coupons patterns per PROJECT_SOP.md

Issues Found & Fixed:
 Missing 'New' submenu tab (violated SOP CRUD pattern)
 FAB showing on index page (should be 'none' - submenu handles New)
 No mobile search bar (inconsistent with Products/Coupons)
 Duplicate coupons entry in navigation

Changes Made:

1. NavigationRegistry.php:
 Added 'New' submenu tab to customers navigation
 Removed duplicate coupons navigation entry
 Now matches Products/Coupons pattern: [All customers | New]

2. Customers/index.tsx:
 Changed FAB from 'customers' to 'none' (submenu handles New per SOP)
 Added mobile search bar (md:hidden) matching Products/Coupons
 Desktop toolbar already correct (hidden md:block)

Verified SOP Compliance:

 Submenu Tabs Pattern:
   - Products: [All products | New | Categories | Tags | Attributes]
   - Coupons: [All coupons | New]
   - Customers: [All customers | New] ← NOW CONSISTENT

 Toolbar Structure (Desktop):
   - Left: Bulk Actions (Delete when selected, Refresh always)
   - Right: Search input
   - NO 'New' button (handled by submenu)

 Mobile Pattern:
   - Search bar at top (md:hidden)
   - Toolbar hidden on mobile
   - Cards instead of table

 Table Styling (matches SOP standards):
   - Container: rounded-lg border overflow-hidden
   - Table: w-full
   - Header: bg-muted/50 + border-b
   - Header cells: p-3 font-medium text-left
   - Body rows: border-b hover:bg-muted/30 last:border-0
   - Body cells: p-3

 Button Styling:
   - Delete: bg-red-600 text-white hover:bg-red-700
   - Refresh: border hover:bg-accent
   - All: inline-flex items-center gap-2

Result: Customer module now 100% consistent with Products/Coupons
following PROJECT_SOP.md CRUD Module Pattern standards
This commit is contained in:
dwindown
2025-11-20 23:15:29 +07:00
parent 921c1b6f80
commit fe63e08239
2 changed files with 21 additions and 13 deletions

View File

@@ -23,8 +23,8 @@ export default function CustomersIndex() {
const [search, setSearch] = useState(''); const [search, setSearch] = useState('');
const [selectedIds, setSelectedIds] = useState<number[]>([]); const [selectedIds, setSelectedIds] = useState<number[]>([]);
// FAB config for "New Customer" button // FAB config - 'none' because submenu has 'New' tab (per SOP)
useFABConfig('customers'); useFABConfig('none');
// Fetch customers // Fetch customers
const customersQuery = useQuery({ const customersQuery = useQuery({
@@ -99,7 +99,24 @@ export default function CustomersIndex() {
return ( return (
<div className="space-y-4"> <div className="space-y-4">
{/* Toolbar */} {/* Mobile: Search */}
<div className="md:hidden">
<div className="relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
<Input
type="search"
placeholder={__('Search customers...')}
value={search}
onChange={(e) => {
setSearch(e.target.value);
setPage(1);
}}
className="pl-9"
/>
</div>
</div>
{/* Desktop: Toolbar */}
<div className="hidden md:block rounded-lg border border-border p-4 bg-card"> <div className="hidden md:block rounded-lg border border-border p-4 bg-card">
<div className="flex flex-col lg:flex-row lg:justify-between lg:items-center gap-3"> <div className="flex flex-col lg:flex-row lg:justify-between lg:items-center gap-3">
{/* Left: Bulk Actions */} {/* Left: Bulk Actions */}

View File

@@ -153,16 +153,7 @@ class NavigationRegistry {
'icon' => 'users', 'icon' => 'users',
'children' => [ 'children' => [
['label' => __('All customers', 'woonoow'), 'mode' => 'spa', 'path' => '/customers'], ['label' => __('All customers', 'woonoow'), 'mode' => 'spa', 'path' => '/customers'],
], ['label' => __('New', 'woonoow'), 'mode' => 'spa', 'path' => '/customers/new'],
],
[
'key' => 'coupons',
'label' => __('Coupons', 'woonoow'),
'path' => '/coupons',
'icon' => 'tag',
'children' => [
['label' => __('All coupons', 'woonoow'), 'mode' => 'spa', 'path' => '/coupons'],
['label' => __('New', 'woonoow'), 'mode' => 'spa', 'path' => '/coupons/new'],
], ],
], ],
[ [