UI/UX Specification: Standardizing Customer Table View Columns & Adding Membership Tiers
Last Updated: 16/07/2026
Type: UI/UX Layout Specification — Customer Management
System: Saleor CMS — Customers > Customers List View
Severity: 🔴 High — Critical for operations, admins must immediately identify user membership tiers and access structured columns without view state loss
Feedback Screenshot:
1. Identified Issues
In the CMS Customers list screen:
- No Persistent Table View: Toggling table columns does not persist. Reloading/Navigating away resets the selected columns, losing the default view.
- Missing "Membership Tier" Column: There is no column showing whether a user is
Silver,Gold,Platinum, orDiamond. This is the single most important parameter for membership administration. - Column Overcrowding & Width Issues: Text is clipped (e.g. name column) while empty columns consume space.
2. Solution Specifications
2.1 Default Table View Columns
We establish a standardized default view containing exactly the following columns in order. This view must be set as the default database/localStorage configuration so that it loads instantly for all admins:
| Order | Column Name (VN) | JSON Key | Width | Content Format |
|---|---|---|---|---|
| 1 | STT | index | 60px | Static row count (see cms-table-pagination-standard.md) |
| 2 | Họ và Tên | fullName | 180px | Bold string (e.g., Nguyen Van A) |
| 3 | Hạng thành viên | membershipTier | 120px | [NEW] Tier Badge (Silver/Gold/Plat/Dia) |
| 4 | Số điện thoại | phone | 130px | Standard numeric string |
| 5 | email | 200px | Standard email string | |
| 6 | Mã thành viên | membershipCode | 130px | Unique member ID code (e.g. GL-DEMO-001) |
| 7 | Mã giới thiệu | referralCode | 120px | Auto-generated code (see auto-referral-code-generation.md) |
| 8 | Trạng thái | status | 100px | Status Badge (Verified / Registered) |
| 9 | Thao tác | actions | 100px | Action button popover (Edit details, View transaction history) |
2.2 Membership Tier Column Styles
Render the tier column with distinct background colors corresponding to the brand tiers:
🥈 SILVER → Background: #E0E0E0, Text: #424242
🥇 GOLD → Background: #FFF9C4, Text: #F57F17
💎 PLATINUM → Background: #E1F5FE, Text: #0288D1
💎 DIAMOND → Background: #ECE0FD, Text: #6200EA
2.3 Persistent Column Settings (View State Storage)
To prevent column selections from resetting:
- Client-side Storage: Save the list of active column IDs in the browser's
localStorageunder the keycms_customer_table_columns. - Initialization: On component mount, check
localStorage. If empty, load the standard default list (detailed in Section 2.1).
3. Code Implementation Spec (React / Saleor Dashboard)
// Inside CustomerListTable.tsx
import React, { useEffect, useState } from 'react';
const DEFAULT_COLUMNS = [
'index',
'fullName',
'membershipTier', // ✅ NEW column
'phone',
'email',
'membershipCode',
'referralCode',
'status',
'actions'
];
export const CustomerListTable = () => {
const [selectedColumns, setSelectedColumns] = useState<string[]>([]);
// Load configuration on mount
useEffect(() => {
const savedCols = localStorage.getItem('cms_customer_table_columns');
if (savedCols) {
try {
setSelectedColumns(JSON.parse(savedCols));
} catch {
setSelectedColumns(DEFAULT_COLUMNS);
}
} else {
setSelectedColumns(DEFAULT_COLUMNS);
}
}, []);
// Save configuration when columns are modified
const handleColumnToggle = (columnId: string) => {
const updated = selectedColumns.includes(columnId)
? selectedColumns.filter(c => c !== columnId)
: [...selectedColumns, columnId];
setSelectedColumns(updated);
localStorage.setItem('cms_customer_table_columns', JSON.stringify(updated));
};
return (
<Table>
<TableHeader>
{selectedColumns.includes('index') && <TableCell style={{ width: 60 }}>STT</TableCell>}
{selectedColumns.includes('fullName') && <TableCell style={{ width: 180 }}>Họ và Tên</TableCell>}
{selectedColumns.includes('membershipTier') && <TableCell style={{ width: 120 }}>Hạng</TableCell>}
{/* ...other headers */}
</TableHeader>
<TableBody>
{customers.map((user, idx) => (
<TableRow key={user.id}>
{selectedColumns.includes('index') && <TableCell>{idx + 1}</TableCell>}
{selectedColumns.includes('fullName') && <TableCell>{user.fullName}</TableCell>}
{selectedColumns.includes('membershipTier') && (
<TableCell>
<TierBadge tier={user.membershipTier} /> {/* Render colored badges */}
</TableCell>
)}
{/* ...other cells */}
</TableRow>
))}
</TableBody>
</Table>
);
};
Technical Checklist
- Add the Hạng thành viên (membershipTier) property to the Customer API response payload from the backend.
- Add the
membershipTierheader descriptor block inCustomerListTable.tsx. - Implement the
TierBadgestyled component with specific colors for Silver, Gold, Platinum, and Diamond. - Implement
localStoragehooks in the table container component to load and save column configuration. - Set
DEFAULT_COLUMNSarray to match the order described in Section 2.1. - Adjust table layout widths to prevent name truncation and hide unused/empty columns by default.
- Test view persistence:
- Open the customer list, toggle off the "Email" column.
- F5 / Refresh the browser page.
- Verify that the "Email" column remains hidden and the layout does not reset.