Skip to main content

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:

  1. No Persistent Table View: Toggling table columns does not persist. Reloading/Navigating away resets the selected columns, losing the default view.
  2. Missing "Membership Tier" Column: There is no column showing whether a user is Silver, Gold, Platinum, or Diamond. This is the single most important parameter for membership administration.
  3. 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:

OrderColumn Name (VN)JSON KeyWidthContent Format
1STTindex60pxStatic row count (see cms-table-pagination-standard.md)
2Họ và TênfullName180pxBold string (e.g., Nguyen Van A)
3Hạng thành viênmembershipTier120px[NEW] Tier Badge (Silver/Gold/Plat/Dia)
4Số điện thoạiphone130pxStandard numeric string
5Emailemail200pxStandard email string
6Mã thành viênmembershipCode130pxUnique member ID code (e.g. GL-DEMO-001)
7Mã giới thiệureferralCode120pxAuto-generated code (see auto-referral-code-generation.md)
8Trạng tháistatus100pxStatus Badge (Verified / Registered)
9Thao tácactions100pxAction 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 localStorage under the key cms_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 membershipTier header descriptor block in CustomerListTable.tsx.
  • Implement the TierBadge styled component with specific colors for Silver, Gold, Platinum, and Diamond.
  • Implement localStorage hooks in the table container component to load and save column configuration.
  • Set DEFAULT_COLUMNS array 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.