Replace all `any` types with proper types across 36 files:
- TanStack Router search params: `{} as Record<string, unknown>`
- API response pagination: proper typed interface
- DataTable column casts: remove unnecessary `as any`
- Function params and event handlers: use specific types
- Remove unused imports and variables in POS components
Frontend lint now passes with 0 errors and 0 warnings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
164 lines
4.6 KiB
TypeScript
164 lines
4.6 KiB
TypeScript
import { queryOptions } from '@tanstack/react-query'
|
|
import { api } from '@/lib/api-client'
|
|
|
|
// --- Types ---
|
|
|
|
export interface Transaction {
|
|
id: string
|
|
locationId: string | null
|
|
transactionNumber: string
|
|
accountId: string | null
|
|
repairTicketId: string | null
|
|
repairBatchId: string | null
|
|
transactionType: string
|
|
status: string
|
|
subtotal: string
|
|
discountTotal: string
|
|
taxTotal: string
|
|
total: string
|
|
paymentMethod: string | null
|
|
amountTendered: string | null
|
|
changeGiven: string | null
|
|
checkNumber: string | null
|
|
roundingAdjustment: string
|
|
taxExempt: boolean
|
|
taxExemptReason: string | null
|
|
processedBy: string
|
|
drawerSessionId: string | null
|
|
notes: string | null
|
|
completedAt: string | null
|
|
createdAt: string
|
|
updatedAt: string
|
|
lineItems?: TransactionLineItem[]
|
|
}
|
|
|
|
export interface TransactionLineItem {
|
|
id: string
|
|
transactionId: string
|
|
productId: string | null
|
|
inventoryUnitId: string | null
|
|
description: string
|
|
qty: number
|
|
unitPrice: string
|
|
discountAmount: string
|
|
discountReason: string | null
|
|
taxRate: string
|
|
taxAmount: string
|
|
lineTotal: string
|
|
createdAt: string
|
|
}
|
|
|
|
export interface DrawerSession {
|
|
id: string
|
|
locationId: string | null
|
|
openedBy: string
|
|
closedBy: string | null
|
|
openingBalance: string
|
|
closingBalance: string | null
|
|
expectedBalance: string | null
|
|
overShort: string | null
|
|
denominations: Record<string, number> | null
|
|
status: string
|
|
notes: string | null
|
|
openedAt: string
|
|
closedAt: string | null
|
|
}
|
|
|
|
export interface Discount {
|
|
id: string
|
|
name: string
|
|
discountType: string
|
|
discountValue: string
|
|
appliesTo: string
|
|
requiresApprovalAbove: string | null
|
|
isActive: boolean
|
|
}
|
|
|
|
export interface Product {
|
|
id: string
|
|
name: string
|
|
sku: string | null
|
|
upc: string | null
|
|
description: string | null
|
|
price: string | null
|
|
costPrice: string | null
|
|
qtyOnHand: number | null
|
|
taxCategory: string
|
|
isSerialized: boolean
|
|
isActive: boolean
|
|
}
|
|
|
|
// --- Query Keys ---
|
|
|
|
export const posKeys = {
|
|
transaction: (id: string) => ['pos', 'transaction', id] as const,
|
|
drawer: (locationId: string) => ['pos', 'drawer', locationId] as const,
|
|
products: (search: string) => ['pos', 'products', search] as const,
|
|
discounts: ['pos', 'discounts'] as const,
|
|
}
|
|
|
|
// --- Query Options ---
|
|
|
|
export function transactionOptions(id: string | null) {
|
|
return queryOptions({
|
|
queryKey: posKeys.transaction(id ?? ''),
|
|
queryFn: () => api.get<Transaction>(`/v1/transactions/${id}`),
|
|
enabled: !!id,
|
|
})
|
|
}
|
|
|
|
export function currentDrawerOptions(locationId: string | null) {
|
|
return queryOptions({
|
|
queryKey: posKeys.drawer(locationId ?? ''),
|
|
queryFn: () => api.get<DrawerSession>('/v1/drawer/current', { locationId }),
|
|
enabled: !!locationId,
|
|
retry: false,
|
|
})
|
|
}
|
|
|
|
export function productSearchOptions(search: string) {
|
|
return queryOptions({
|
|
queryKey: posKeys.products(search),
|
|
queryFn: () => api.get<{ data: Product[]; pagination: { page: number; limit: number; total: number; totalPages: number } }>('/v1/products', { q: search, limit: 24, isActive: true }),
|
|
enabled: search.length >= 1,
|
|
})
|
|
}
|
|
|
|
export function discountListOptions() {
|
|
return queryOptions({
|
|
queryKey: posKeys.discounts,
|
|
queryFn: () => api.get<Discount[]>('/v1/discounts/all'),
|
|
})
|
|
}
|
|
|
|
// --- Mutations ---
|
|
|
|
export const posMutations = {
|
|
createTransaction: (data: { transactionType: string; locationId?: string }) =>
|
|
api.post<Transaction>('/v1/transactions', data),
|
|
|
|
addLineItem: (txnId: string, data: { productId?: string; inventoryUnitId?: string; description: string; qty: number; unitPrice: number }) =>
|
|
api.post<TransactionLineItem>(`/v1/transactions/${txnId}/line-items`, data),
|
|
|
|
removeLineItem: (txnId: string, lineItemId: string) =>
|
|
api.del<TransactionLineItem>(`/v1/transactions/${txnId}/line-items/${lineItemId}`),
|
|
|
|
applyDiscount: (txnId: string, data: { discountId?: string; amount: number; reason: string; lineItemId?: string }) =>
|
|
api.post<Transaction>(`/v1/transactions/${txnId}/discounts`, data),
|
|
|
|
complete: (txnId: string, data: { paymentMethod: string; amountTendered?: number; checkNumber?: string }) =>
|
|
api.post<Transaction>(`/v1/transactions/${txnId}/complete`, data),
|
|
|
|
void: (txnId: string) =>
|
|
api.post<Transaction>(`/v1/transactions/${txnId}/void`, {}),
|
|
|
|
openDrawer: (data: { locationId?: string; openingBalance: number }) =>
|
|
api.post<DrawerSession>('/v1/drawer/open', data),
|
|
|
|
closeDrawer: (id: string, data: { closingBalance: number; denominations?: Record<string, number>; notes?: string }) =>
|
|
api.post<DrawerSession>(`/v1/drawer/${id}/close`, data),
|
|
|
|
lookupUpc: (upc: string) =>
|
|
api.get<Product>(`/v1/products/lookup/upc/${upc}`),
|
|
}
|