store user login

This commit is contained in:
2026-08-25 18:00:16 +05:30
parent 1dc582ba07
commit 517a99d577
62 changed files with 8059 additions and 650 deletions

View File

@@ -14,7 +14,8 @@ import { insightsApi, type DateRange, type OrderQuery } from '@/api/insights';
import { productsApi } from '@/api/products';
import { posUsersApi, staffApi } from '@/api/people';
import { stockApi, type StockRequestQuery } from '@/api/stock';
import { tenantsApi } from '@/api/tenants';
import { tenantsApi, utilsApi, type TenantListQuery } from '@/api/tenants';
import { customersApi, type CustomerQuery } from '@/api/customers';
import { queryKeys } from './keys';
import { LIVE_REFETCH_MS } from './interval';
@@ -46,10 +47,33 @@ const stable = {
/* ── Tenants ─────────────────────────────────────────────────────────────── */
export function useTenants() {
export function useTenants(query: TenantListQuery = {}) {
return useQuery({
queryKey: queryKeys.tenants.list(),
queryFn: () => tenantsApi.listAll(),
queryKey: queryKeys.tenants.list({ ...query }),
queryFn: () => tenantsApi.listAll(query),
...stable,
});
}
/**
* The approval queue.
*
* Its own hook rather than a filter over `useTenants`, because it is a
* different endpoint: `getalltenants` cannot see an unapproved tenant at all.
*/
export function useTenantsByApproval(status: 'pending' | 'Active' | 'InActive', keyword?: string) {
return useQuery({
queryKey: queryKeys.tenants.approval(status, keyword ?? ''),
queryFn: () => tenantsApi.byApproval(status, keyword),
...stable,
});
}
/** The business-category master, for onboarding. */
export function useAppCategories() {
return useQuery({
queryKey: queryKeys.tenants.appCategories(),
queryFn: () => utilsApi.appCategories(),
...stable,
});
}
@@ -103,6 +127,37 @@ export function useProductCategories(tenantid: number | undefined) {
});
}
/**
* The tenant's categories as they are actually used.
*
* Prefer this over `useProductCategories`, which reads a master table missing
* rows for live categoryids and hardcoded to `moduleid = 2`.
*/
export function useTenantCategories(tenantid: number | undefined) {
return useQuery({
queryKey: queryKeys.products.tenantCategories(tenantid ?? 0),
queryFn: () => productsApi.tenantCategories(tenantid as number),
enabled: typeof tenantid === 'number' && tenantid > 0,
...stable,
});
}
/**
* One global-catalogue row, for the product drawer.
*
* Not retried: the common failure is that a re-scrape retired the source row,
* and asking three more times does not bring it back.
*/
export function useCatalogueProduct(brand: string | undefined, sku: string | undefined) {
return useQuery({
queryKey: queryKeys.catalogue.product(brand ?? '', sku ?? ''),
queryFn: () => catalogueApi.product(brand as string, sku as string),
enabled: Boolean(brand) && Boolean(sku),
retry: false,
...stable,
});
}
export function useLocationProducts(
tenantid: number | undefined,
locationid: number | undefined,
@@ -267,6 +322,21 @@ export function useDeliveries(query: OrderQuery | undefined) {
/* ── People ──────────────────────────────────────────────────────────────── */
/** The back-office directory. Role names arrive resolved; never map ids here. */
/**
* The branch's customers.
*
* Page size is always sent — see `customersApi`. Left off, the backend returns
* an empty list rather than an error, which reads as "no customers".
*/
export function useCustomers(query: CustomerQuery | undefined) {
return useQuery({
queryKey: queryKeys.customers.list({ ...query }),
queryFn: () => customersApi.list(query as CustomerQuery),
enabled: Boolean(query?.tenantid),
...live,
});
}
export function useStaff(tenantid: number | undefined) {
return useQuery({
queryKey: queryKeys.people.staff(tenantid ?? 0),

View File

@@ -10,7 +10,11 @@
export const queryKeys = {
tenants: {
all: ['tenants'] as const,
list: () => [...queryKeys.tenants.all, 'list'] as const,
list: (params: Record<string, unknown> = {}) =>
[...queryKeys.tenants.all, 'list', params] as const,
appCategories: () => [...queryKeys.tenants.all, 'appCategories'] as const,
approval: (status: string, keyword: string) =>
[...queryKeys.tenants.all, 'approval', status, keyword] as const,
locations: (tenantid: number) =>
[...queryKeys.tenants.all, 'locations', tenantid] as const,
search: (keyword: string) => [...queryKeys.tenants.all, 'search', keyword] as const,
@@ -23,6 +27,8 @@ export const queryKeys = {
brands: () => [...queryKeys.catalogue.all, 'brands'] as const,
importedRefs: (tenantid: number) =>
[...queryKeys.catalogue.all, 'imported', tenantid] as const,
product: (brand: string, sku: string) =>
[...queryKeys.catalogue.all, 'product', brand, sku] as const,
},
products: {
@@ -34,6 +40,8 @@ export const queryKeys = {
subCategories: (tenantid: number, categoryid: number) =>
[...queryKeys.products.all, 'subcategories', tenantid, categoryid] as const,
count: (tenantid: number) => [...queryKeys.products.all, 'count', tenantid] as const,
tenantCategories: (tenantid: number) =>
[...queryKeys.products.all, 'tenantcategories', tenantid] as const,
},
insights: {
@@ -67,6 +75,12 @@ export const queryKeys = {
[...queryKeys.people.all, 'shifts', tenantid, locationid] as const,
},
customers: {
all: ['customers'] as const,
list: (params: Record<string, unknown>) =>
[...queryKeys.customers.all, 'list', params] as const,
},
stock: {
all: ['stock'] as const,
requests: (params: Record<string, unknown>) =>