CRM & Clients Flow¶
This page describes how Workbench AI handles client records, CRM views, and appointments.
Screens & views¶
Clients screen (/clients)¶
File: src/pages/Clients.tsx
Responsibilities:
- Main clients list and CRM entry point.
- Provides:
- Stats summary (total clients, revenue, VIPs, etc.).
- Filters for segmentation.
- Table of clients with inline actions.
- Details modal with client profile + orders.
Key components:
ClientStatsCards– high-level metrics:- Total clients.
- Total revenue.
- Average order value.
- Active clients (last 30 days).
- New clients (last 30 days).
- VIP clients.
ClientFilters– segmentation controls (search, has email, address, spend, orders, recency, activity status).ClientsTable– tabular list of clients.ClientDetailsModal– view/edit a client and see related orders.ClientForm– create/edit form.
CRM view (/clients/crm)¶
File: src/pages/clients/CRM.tsx
Currently a simple placeholder that:
- Uses
DashboardLayoutwith a title and description. - Intended future home for higher-level CRM tooling (pipelines, tags, campaigns).
For now, most CRM behavior lives on /clients and in the associated stats/filters rather than this page.
Appointments & calendar (/clients/appointments)¶
File: src/pages/clients/AppointmentsCalendar.tsx
Currently a placeholder page that:
- Uses
DashboardLayoutwith a title and description. - Declares scope for: consultations, fittings, pickups, reminders, and availability.
Appointments are not yet fully implemented in the codebase; when they are, this page should be updated to describe the actual data model and flows.
Appointments status
As of this documentation pass, appointments are conceptual. There is no appointments table or concrete implementation yet. This page documents the intent; update it when appointments ship.
Clients data & operations¶
useClients hook¶
File: src/hooks/useClients.ts
Exposes the core client operations:
fetchClients(filters?)– list clients for the current tenant.createClient(input)– create a new client (with plan-limit checks).updateClient(input)– update existing client data.deleteClient(id)– delete a client.getClientStats(id)– per-client stats (total spent, order count, last order date).fetchClientStats()– aggregate stats for the tenant.
Clients table¶
Migration: supabase/migrations/20250114000000_create_clients_table.sql
- Table:
clients - Fields (subset):
idtenant_id– tenant/company owner.first_name,last_name.email(nullable).phone.address(nullable).notes(nullable).date_of_birth(nullable).preferred_contact_method(nullable) – e.g. phone, email, SMS.created_at,updated_at.
- Indexes for efficient lookup by tenant, name, email, and phone.
- RLS is enabled to restrict access by tenant.
Fetching & filtering clients¶
fetchClients(filters) builds a Supabase query like:
- Base:
from('clients').select('*').eq('tenant_id', tenantId)
- Search:
- If
filters.searchis set, applies case-insensitive search across: first_name,last_name,email,phone.
- If
- Boolean filters:
has_email– include only clients with/non-with email.has_address– include only clients with/non-with address.
- Preferred contact:
preferred_contact_method = filters.preferred_contact.
- Created date range:
created_at >= filters.created_date_from.created_at <= filters.created_date_to.
- Sorting:
- Name (alphabetical), date created, or default.
After the base query, it derives stats per client using RPCs:
get_client_total_spent(client_id_param).get_client_order_count(client_id_param).get_client_last_order_date(client_id_param).
These stats are attached to each client as:
total_spent– aggregate order revenue.order_count– number of orders.last_order_date– date of last order.
Client-side filters are then applied using these stats:
- Money spent range.
- Order count range.
- Last order date range.
- Activity status:
active– ordered in last 30 days.inactive– no orders in last 30 days or never ordered.new– client created in last 30 days.vip–total_spent > $1000ororder_count > 10.
Creating & updating clients¶
-
createClient(input):- Checks current client count for the tenant.
- Loads subscription plan info from
subscriptions. - Uses
getPlanLimits(plan_name, subscription)to enforce plan-specific client limits. - Inserts a row into
clientswith tenant-scoped data. - Normalizes optional fields to
nullwhen absent.
-
updateClient(input):- Updates
clientsrow, normalizing optional fields.
- Updates
-
deleteClient(id):- Deletes the client row.
- Downstream effects (e.g. orders referencing this client) are governed by DB constraints and should be handled with care.
Stats aggregation¶
fetchClientStats() summarizes CRM health:
- Queries all
clientsfor the tenant. - Queries all
ordersfor the tenant. - Computes:
total_clients– count of clients.total_revenue– sum oforders.price.average_order_value.active_clients_30d– clients with orders in last 30 days.new_clients_30d– clients created in last 30 days.vip_clients– clients over thresholds for spend or order count.
These metrics feed ClientStatsCards on the /clients page.
Tables & relationships¶
Key tables:
-
clients- Master CRM record for each customer.
- Linked to
orders.client_id.
-
orders- Used to derive client stats (revenue, order count, recency).
- See Orders Flow for details.
-
RPC functions
get_client_total_spent– sum of order totals per client.get_client_order_count– count of orders per client.get_client_last_order_date– latest order date per client.
There is no dedicated appointments table yet; when it exists, update this doc to include its schema and how it links to clients and orders.
Flow diagram¶
flowchart LR
U[User] --> CLI[/Clients screen/]
CLI --> HOOK[useClients]
HOOK --> C[(clients)]
HOOK --> O[(orders)]
subgraph Stats
RPC1[get_client_total_spent]
RPC2[get_client_order_count]
RPC3[get_client_last_order_date]
end
O --> RPC1
O --> RPC2
O --> RPC3
click CLI "../architecture/frontend/" "Clients page & components"
click HOOK "../architecture/frontend/" "useClients hook"
click C "../architecture/supabase/" "Clients table"
click O "./orders.md" "Orders flow & data model"
Narrative:
- User opens
/clients. useClientsfetchesclientsrows for the tenant.- For each client, RPCs compute spending and order-based stats using
orders. - Filters and stats are applied client-side to segment customers.
- UI surfaces insights (VIPs, inactive clients, new clients) for follow-up.
Related docs¶
- Orders Flow – orders & revenue used in client stats.
- Supabase Architecture – clients and orders schema.
- Frontend Architecture – route map and providers.
- Auth Flow – tenant scoping for data access.