Tighten Users filters and admin-only header badges.
Match sticky headers to sidebar glass, drop the Users role column, and show compact owner/admin badges only where needed. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
6c52ce1247
commit
722933dda9
@@ -33,7 +33,7 @@ import accessStyles from '../components/ChangeUserAccessModal.module.css'
|
||||
import styles from './CustomersPage.module.css'
|
||||
|
||||
const PAGE_SIZE = 24
|
||||
const COLUMN_COUNT = 7
|
||||
const COLUMN_COUNT = 6
|
||||
|
||||
function formatDate(value: string, locale: 'en' | 'fa') {
|
||||
const d = new Date(value)
|
||||
@@ -54,13 +54,11 @@ function formatTransactionTotal(total: number | null | undefined) {
|
||||
return formatIrtPrice(total)
|
||||
}
|
||||
|
||||
function accessBadgeKey(user: BusinessCustomerListItem): BusinessMessageKey {
|
||||
/** Badge under name — owner / admin only. */
|
||||
function adminBadgeKey(user: BusinessCustomerListItem): BusinessMessageKey | null {
|
||||
if (user.isBusinessOwner) return 'customers.access.badge.owner'
|
||||
if (user.teamRole === 'admin') return 'customers.access.badge.admin'
|
||||
if (user.teamRole === 'editor') return 'customers.access.badge.editor'
|
||||
if (user.teamRole === 'viewer') return 'customers.access.badge.viewer'
|
||||
if (user.businessMemberId) return 'customers.access.badge.manager'
|
||||
return 'customers.access.customer'
|
||||
return null
|
||||
}
|
||||
|
||||
function teamRoleMessageKey(teamRole: string): BusinessMessageKey {
|
||||
@@ -322,41 +320,40 @@ export function CustomersPage() {
|
||||
|
||||
<div className={filterStyles.filtersPanel}>
|
||||
<form className={filterStyles.filtersGrid} onSubmit={(e) => { e.preventDefault(); applyFilters() }}>
|
||||
<div className={filterStyles.filtersInputs}>
|
||||
<div className={`${filterStyles.field} ${filterStyles.fieldCol3}`}>
|
||||
<select
|
||||
id="filter-customer-access"
|
||||
value={draftAccess}
|
||||
onChange={(e) => handleAccessFilterChange(e.target.value as CustomerAccessFilter)}
|
||||
aria-label={t('customers.filter.access')}
|
||||
disabled={loading}
|
||||
>
|
||||
<option value="all">{t('customers.filter.access.all')}</option>
|
||||
<option value="customers">{t('customers.filter.access.customers')}</option>
|
||||
<option value="managers">{t('customers.filter.access.managers')}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={`${filterStyles.field} ${filterStyles.fieldCol3}`}>
|
||||
<input
|
||||
id="filter-customer-name"
|
||||
value={draftName}
|
||||
onChange={(e) => setDraftName(e.target.value)}
|
||||
placeholder={t('customers.filter.name')}
|
||||
aria-label={t('customers.filter.name')}
|
||||
/>
|
||||
</div>
|
||||
<div className={`${filterStyles.field} ${styles.filterCellNarrow}`}>
|
||||
<input
|
||||
id="filter-customer-cell"
|
||||
value={draftCell}
|
||||
onChange={(e) => setDraftCell(e.target.value)}
|
||||
placeholder={t('customers.filter.cell')}
|
||||
aria-label={t('customers.filter.cell')}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
<div className={`${filterStyles.field} ${filterStyles.fieldCol3}`}>
|
||||
<input
|
||||
id="filter-customer-name"
|
||||
value={draftName}
|
||||
onChange={(e) => setDraftName(e.target.value)}
|
||||
placeholder={t('customers.filter.name')}
|
||||
aria-label={t('customers.filter.name')}
|
||||
/>
|
||||
</div>
|
||||
<div className={filterStyles.filterActions}>
|
||||
<div className={`${filterStyles.field} ${filterStyles.fieldCol2}`}>
|
||||
<input
|
||||
id="filter-customer-cell"
|
||||
value={draftCell}
|
||||
onChange={(e) => setDraftCell(e.target.value)}
|
||||
placeholder={t('customers.filter.cell')}
|
||||
aria-label={t('customers.filter.cell')}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
<div className={`${filterStyles.field} ${filterStyles.fieldCol2}`}>
|
||||
<select
|
||||
id="filter-customer-access"
|
||||
value={draftAccess}
|
||||
onChange={(e) => handleAccessFilterChange(e.target.value as CustomerAccessFilter)}
|
||||
aria-label={t('customers.filter.access')}
|
||||
disabled={loading}
|
||||
>
|
||||
<option value="all">{t('customers.filter.access.all')}</option>
|
||||
<option value="customers">{t('customers.filter.access.customers')}</option>
|
||||
<option value="managers">{t('customers.filter.access.managers')}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={filterStyles.filterSpacerCol4} aria-hidden="true" />
|
||||
<div className={`${filterStyles.filterActions} ${filterStyles.filterActionsCol1}`}>
|
||||
<button
|
||||
type="submit"
|
||||
className={`${filterStyles.iconActionBtn} ${filterStyles.iconActionBtnPrimary}`}
|
||||
@@ -408,7 +405,6 @@ export function CustomersPage() {
|
||||
>
|
||||
<colgroup>
|
||||
<col className={styles.colName} />
|
||||
<col className={styles.colRole} />
|
||||
<col className={styles.colCell} />
|
||||
<col className={styles.colOrders} />
|
||||
<col className={styles.colTransactions} />
|
||||
@@ -418,7 +414,6 @@ export function CustomersPage() {
|
||||
<thead>
|
||||
<tr>
|
||||
<th className={styles.th}>{t('customers.col.name')}</th>
|
||||
<th className={styles.th}>{t('customers.col.role')}</th>
|
||||
<th className={styles.th}>{t('customers.col.cell')}</th>
|
||||
<th className={styles.th}>{t('customers.col.orders')}</th>
|
||||
<th className={styles.th}>{t('customers.col.transactions')}</th>
|
||||
@@ -447,7 +442,7 @@ export function CustomersPage() {
|
||||
data?.items?.map((customer) => {
|
||||
const name = displayName(customer)
|
||||
const nameLocale = textLocaleAttrs(name)
|
||||
const badgeKey = accessBadgeKey(customer)
|
||||
const badgeKey = adminBadgeKey(customer)
|
||||
const accessLocked = accessChangeDisabledReason(customer)
|
||||
return (
|
||||
<tr
|
||||
@@ -468,13 +463,13 @@ export function CustomersPage() {
|
||||
>
|
||||
{name}
|
||||
</div>
|
||||
{badgeKey ? (
|
||||
<span className={accessStyles.roleBadge}>{t(badgeKey)}</span>
|
||||
) : null}
|
||||
{!customer.isEnabled && (
|
||||
<div className={styles.statusDisabled}>{t('customers.disabled')}</div>
|
||||
)}
|
||||
</td>
|
||||
<td className={styles.td}>
|
||||
<span className={accessStyles.roleBadge}>{t(badgeKey)}</span>
|
||||
</td>
|
||||
<td className={styles.td}>{formatCellForDisplay(customer.cellNumber)}</td>
|
||||
<td className={styles.td}>
|
||||
{customer.orderCount == null || customer.orderCount === 0 ? (
|
||||
|
||||
Reference in New Issue
Block a user