Add customer/manager access UI and tighten customers filters.

Business and super-admin can set Customer vs Manager roles (Admin only for super-admin), and the customers page drops clutter while filtering by all/customers/managers.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-10 21:31:28 +03:30
co-authored by Cursor
parent 404c008ced
commit f622e6d605
28 changed files with 1280 additions and 241 deletions
@@ -17,6 +17,10 @@ export interface BusinessCustomerListItem extends BusinessCustomer {
orderCount?: number | null
/** Placeholder until orders stats API exists */
totalTransactionsIrt?: number | null
/** Present when this customer is also staff/owner on the business. */
businessMemberId?: string | null
isBusinessOwner?: boolean
teamRole?: string | null
}
export interface CustomersListResponse {
@@ -26,11 +30,14 @@ export interface CustomersListResponse {
pageSize: number
}
export type CustomerAccessFilter = 'all' | 'customers' | 'managers'
export interface ListCustomersParams {
page?: number
pageSize?: number
name?: string
cellNumber?: string
access?: CustomerAccessFilter
}
function businessPath(suffix = '') {
@@ -50,6 +57,7 @@ export async function listCustomers(
if (params.pageSize !== undefined) q.set('pageSize', String(params.pageSize))
if (params.name) q.set('name', params.name)
if (params.cellNumber) q.set('cellNumber', params.cellNumber)
if (params.access) q.set('access', params.access)
const query = q.toString()
const path = `${businessPath()}${query ? `?${query}` : ''}`
+44
View File
@@ -0,0 +1,44 @@
import { apiRequest } from '../lib/api'
import { getActiveBusinessId } from '../lib/businessContext'
export type BusinessAccess = 'customer' | 'staff'
export interface AssignBusinessAccessPayload {
userId: string
access: BusinessAccess
roleSlug?: string
}
export interface AssignBusinessAccessResult {
message: string
access: BusinessAccess
member: {
id: string | number
userId: string | number
isOwner: boolean
teamRole: string | null
} | null
}
function teamPath(suffix = '') {
const businessId = getActiveBusinessId()
if (!businessId) {
throw new Error('No active business selected. Please sign in again.')
}
return `/businesses/${businessId}/team${suffix}`
}
/** Set customer vs manager (admin/editor/viewer) for a user on this business. */
export async function assignBusinessAccess(payload: AssignBusinessAccessPayload) {
return apiRequest<AssignBusinessAccessResult>(teamPath('/access'), {
method: 'PATCH',
auth: true,
body: {
userId: String(payload.userId),
access: payload.access,
...(payload.access === 'staff' && payload.roleSlug
? { roleSlug: payload.roleSlug }
: {}),
},
})
}