dispatch page

This commit is contained in:
2026-06-12 14:45:06 +05:30
parent d8c1517239
commit 5378f2df1f
34 changed files with 4451 additions and 1744 deletions

View File

@@ -46,12 +46,17 @@ import {
getUserById,
createUser,
updateUser,
assignRiderToOrders,
CreateUserInput,
createTenantUser,
createTenantLocation,
CreateTenantInput,
CreateTenantLocationInput,
} from './fiestaApi';
export const fiestaKeys = {
orderSummary: (tenantid: number, fromdate: string, todate: string) =>
['fiesta', 'orderSummary', tenantid, fromdate, todate] as const,
orderSummary: (tenantid: number, fromdate: string, todate: string, locationid?: number) =>
['fiesta', 'orderSummary', tenantid, fromdate, todate, locationid ?? 0] as const,
locationSummary: (tenantid: number) => ['fiesta', 'locationSummary', tenantid] as const,
orderInsight: (tenantid: number) => ['fiesta', 'orderInsight', tenantid] as const,
orders: (params: Record<string, unknown>) => ['fiesta', 'orders', params] as const,
@@ -60,7 +65,9 @@ export const fiestaKeys = {
deliveryInsight: (tenantid: number) => ['fiesta', 'deliveryInsight', tenantid] as const,
riders: (params: Record<string, unknown>) => ['fiesta', 'riders', params] as const,
riderShifts: (applocationid: number) => ['fiesta', 'riderShifts', applocationid] as const,
tenantLocations: (tenantid: number) => ['fiesta', 'tenantLocations', tenantid] as const,
// v2: bumped when test-row filtering was added to getTenantLocations so any
// warm cache holding the old unfiltered (duplicated/junk) rows is bypassed.
tenantLocations: (tenantid: number) => ['fiesta', 'tenantLocations', 'v2', tenantid] as const,
allTenants: (params: Record<string, unknown>) => ['fiesta', 'allTenants', params] as const,
tenantCustomers: (params: Record<string, unknown>) => ['fiesta', 'tenantCustomers', params] as const,
stockStatement: (params: Record<string, unknown>) => ['fiesta', 'stockStatement', params] as const,
@@ -79,10 +86,10 @@ export const fiestaKeys = {
};
// ── Orders ──────────────────────────────────────────────────────────────────
export function useFiestaOrderSummary(tenantid: number = FIESTA_TENANT_ID, fromdate: string, todate: string) {
export function useFiestaOrderSummary(tenantid: number = FIESTA_TENANT_ID, fromdate: string, todate: string, locationid?: number) {
return useQuery({
queryKey: fiestaKeys.orderSummary(tenantid, fromdate, todate),
queryFn: () => getOrderSummary(tenantid, fromdate, todate),
queryKey: fiestaKeys.orderSummary(tenantid, fromdate, todate, locationid),
queryFn: () => getOrderSummary(tenantid, fromdate, todate, locationid),
enabled: Boolean(tenantid && fromdate && todate),
});
}
@@ -108,6 +115,9 @@ export function useFiestaOrders(opts: {
status: string;
fromdate: string;
todate: string;
locationid?: number;
applocationid?: number;
keyword?: string;
pageno?: number;
pagesize?: number;
}) {
@@ -118,10 +128,61 @@ export function useFiestaOrders(opts: {
});
}
/**
* Fetches orders across all statuses for a given date range by firing one
* request per status in parallel and merging the results. This is needed
* because the /orders/getorders API requires an explicit status param and
* returns an empty array when status is blank or 'all'.
*/
export function useFiestaAllOrders(opts: {
tenantid: number;
fromdate: string;
todate: string;
locationid?: number;
applocationid?: number;
keyword?: string;
}) {
return useQuery({
queryKey: ['fiesta', 'allOrders', opts],
queryFn: async () => {
const statuses = ['created', 'pending', 'processing', 'delivered', 'cancelled'];
const results = await Promise.all(
statuses.map(status =>
getOrders({
tenantid: opts.tenantid,
status,
fromdate: opts.fromdate,
todate: opts.todate,
locationid: opts.locationid,
applocationid: opts.applocationid,
keyword: opts.keyword,
pagesize: 100,
}).catch(() => [] as Row[])
)
);
// Merge and deduplicate by orderid/orderheaderid
const merged: Row[] = [];
const seen = new Set<string>();
for (const list of results) {
for (const row of list) {
const id = String(row.orderid || row.orderheaderid || Math.random());
if (!seen.has(id)) {
seen.add(id);
merged.push(row);
}
}
}
return merged;
},
enabled: Boolean(opts.tenantid && opts.fromdate && opts.todate),
});
}
// ── Deliveries ────────────────────────────────────────────────────────────────
export function useFiestaDeliverySummary(opts: {
tenantid: number;
applocationid?: number;
locationid?: number;
fromdate: string;
todate: string;
}) {
@@ -132,7 +193,17 @@ export function useFiestaDeliverySummary(opts: {
});
}
export function useFiestaDeliveries(opts: { tenantid: number; fromdate: string; todate: string }) {
export function useFiestaDeliveries(opts: {
tenantid: number;
fromdate: string;
todate: string;
status?: string;
locationid?: number;
applocationid?: number;
keyword?: string;
pageno?: number;
pagesize?: number;
}) {
return useQuery({
queryKey: fiestaKeys.deliveries(opts),
queryFn: () => getDeliveries(opts),
@@ -148,8 +219,28 @@ export function useFiestaDeliveryInsight(tenantid: number = FIESTA_TENANT_ID) {
});
}
/**
* Bulk-assign one rider to many orders (the Orders board's multi-select assign).
* Fires one updatedelivery per row in parallel, tolerates partial failure, and
* refreshes the orders + deliveries lists on completion.
*/
export function useFiestaAssignRider() {
const qc = useQueryClient();
return useMutation({
mutationFn: (input: { userid: number; orders: Row[] }) => assignRiderToOrders(input.userid, input.orders),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['fiesta', 'orders'] });
qc.invalidateQueries({ queryKey: ['fiesta', 'orderSummary'] });
// Refresh the Deliveries board AND its KPI summary so a freshly-assigned
// order shows up on the deliveries page immediately (table + count cards).
qc.invalidateQueries({ queryKey: ['fiesta', 'deliveries'] });
qc.invalidateQueries({ queryKey: ['fiesta', 'deliverySummary'] });
},
});
}
// ── Partners / Riders ─────────────────────────────────────────────────────────
export function useFiestaRiders(opts: { applocationid?: number; tenantid: number }) {
export function useFiestaRiders(opts: { applocationid?: number; tenantid: number; partnerid?: number }) {
return useQuery({
queryKey: fiestaKeys.riders(opts),
queryFn: () => getRiders(opts),
@@ -409,6 +500,28 @@ export function useFiestaUpdateUser() {
});
}
/** Create a new tenant and admin user, then refresh tenants list on success. */
export function useFiestaCreateTenant() {
const qc = useQueryClient();
return useMutation({
mutationFn: (input: CreateTenantInput) => createTenantUser(input),
onSuccess: () => qc.invalidateQueries({ queryKey: ['fiesta', 'allTenants'] }),
});
}
/** Create a new tenant location, then refresh tenant locations list on success. */
export function useFiestaCreateLocation() {
const qc = useQueryClient();
return useMutation({
mutationFn: (input: CreateTenantLocationInput) => createTenantLocation(input),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['fiesta', 'tenantLocations'] });
qc.invalidateQueries({ queryKey: ['fiesta', 'locationSummary'] });
},
});
}
// ── Auth ──────────────────────────────────────────────────────────────────────
/**
* Verify login credentials against the Fiesta web-login endpoint. A mutation