frontend fully integreated with the backend
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
import { api } from '@/lib/api'
|
||||
import type {
|
||||
PaginatedResponse,
|
||||
ItemSummaryResponse,
|
||||
ItemDetailResponse,
|
||||
CategoryResponse,
|
||||
BrandResponse,
|
||||
UomResponse,
|
||||
SyncSource,
|
||||
} from '@/types/api'
|
||||
|
||||
import type { PageParams } from './master'
|
||||
|
||||
// ─── Items ────────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface ItemListParams extends PageParams {
|
||||
categoryId?: string
|
||||
brandId?: string
|
||||
search?: string
|
||||
}
|
||||
|
||||
export interface ItemBody {
|
||||
sku: string
|
||||
name: string
|
||||
description?: string | null
|
||||
categoryId: string
|
||||
subCategoryId?: string | null
|
||||
brandId?: string | null
|
||||
baseUomId: string
|
||||
salePrice: number
|
||||
syncSource?: SyncSource
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export const items = {
|
||||
list: (params?: ItemListParams) =>
|
||||
api.get<PaginatedResponse<ItemSummaryResponse>>('/items', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<ItemDetailResponse>(`/items/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: ItemBody) =>
|
||||
api.post<ItemDetailResponse>('/items', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<ItemBody>) =>
|
||||
api.put<ItemDetailResponse>(`/items/${id}`, body).then(r => r.data),
|
||||
|
||||
remove: (id: string) =>
|
||||
api.delete(`/items/${id}`),
|
||||
}
|
||||
|
||||
// ─── Categories ───────────────────────────────────────────────────────────────
|
||||
|
||||
export interface CategoryBody {
|
||||
name: string
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export interface SubCategoryBody {
|
||||
name: string
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export const categories = {
|
||||
list: () =>
|
||||
api.get<CategoryResponse[]>('/categories').then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<CategoryResponse>(`/categories/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: CategoryBody) =>
|
||||
api.post<CategoryResponse>('/categories', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<CategoryBody>) =>
|
||||
api.put<CategoryResponse>(`/categories/${id}`, body).then(r => r.data),
|
||||
|
||||
createSubCategory: (categoryId: string, body: SubCategoryBody) =>
|
||||
api.post(`/categories/${categoryId}/sub-categories`, body).then(r => r.data),
|
||||
|
||||
updateSubCategory: (categoryId: string, subId: string, body: Partial<SubCategoryBody>) =>
|
||||
api.put(`/categories/${categoryId}/sub-categories/${subId}`, body).then(r => r.data),
|
||||
}
|
||||
|
||||
// ─── Brands ───────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface BrandBody {
|
||||
name: string
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export const brands = {
|
||||
list: (params?: PageParams) =>
|
||||
api.get<PaginatedResponse<BrandResponse>>('/brands', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<BrandResponse>(`/brands/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: BrandBody) =>
|
||||
api.post<BrandResponse>('/brands', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<BrandBody>) =>
|
||||
api.put<BrandResponse>(`/brands/${id}`, body).then(r => r.data),
|
||||
}
|
||||
|
||||
// ─── UOMs ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface UomBody {
|
||||
name: string
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export interface UomConversionBody {
|
||||
toUomId: string
|
||||
factor: number
|
||||
}
|
||||
|
||||
export const uoms = {
|
||||
list: () =>
|
||||
api.get<UomResponse[]>('/uoms').then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<UomResponse>(`/uoms/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: UomBody) =>
|
||||
api.post<UomResponse>('/uoms', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<UomBody>) =>
|
||||
api.put<UomResponse>(`/uoms/${id}`, body).then(r => r.data),
|
||||
|
||||
addConversion: (id: string, body: UomConversionBody) =>
|
||||
api.post(`/uoms/${id}/conversions`, body).then(r => r.data),
|
||||
|
||||
removeConversion: (id: string, conversionId: string) =>
|
||||
api.delete(`/uoms/${id}/conversions/${conversionId}`),
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { api } from '@/lib/api'
|
||||
import type {
|
||||
PaginatedResponse,
|
||||
DriverProfileResponse,
|
||||
DriverComplianceConfigResponse,
|
||||
} from '@/types/api'
|
||||
|
||||
import type { PageParams } from './master'
|
||||
|
||||
// ─── Driver Profiles ──────────────────────────────────────────────────────────
|
||||
|
||||
export interface DriverProfileBody {
|
||||
userId: string
|
||||
licenseNumber: string
|
||||
licenseExpiry: string
|
||||
medicalClearanceExpiry: string
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export const drivers = {
|
||||
list: (params?: PageParams) =>
|
||||
api.get<PaginatedResponse<DriverProfileResponse>>('/driver-profiles', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<DriverProfileResponse>(`/driver-profiles/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: DriverProfileBody) =>
|
||||
api.post<DriverProfileResponse>('/driver-profiles', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<DriverProfileBody>) =>
|
||||
api.put<DriverProfileResponse>(`/driver-profiles/${id}`, body).then(r => r.data),
|
||||
}
|
||||
|
||||
// ─── Compliance Config ────────────────────────────────────────────────────────
|
||||
|
||||
export interface ComplianceConfigBody {
|
||||
enforceLicenseExpiry: boolean
|
||||
enforceMedicalClearance: boolean
|
||||
}
|
||||
|
||||
export const compliance = {
|
||||
get: () =>
|
||||
api.get<DriverComplianceConfigResponse>('/driver-profiles/compliance').then(r => r.data),
|
||||
|
||||
update: (body: ComplianceConfigBody) =>
|
||||
api.put<DriverComplianceConfigResponse>('/driver-profiles/compliance', body).then(r => r.data),
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
export { regions, routes, vehicles, warehouses } from './master'
|
||||
export { items, categories, brands, uoms } from './catalogue'
|
||||
export { priceLists, schemes } from './pricing'
|
||||
export { stores } from './stores'
|
||||
export { suppliers } from './suppliers'
|
||||
export { users, roles, permissions } from './users'
|
||||
export { drivers, compliance } from './drivers'
|
||||
export { purchaseOrders, grn } from './procurement'
|
||||
export { rides, loadingSheets, deliveryTasks } from './operations'
|
||||
export { stock } from './stock'
|
||||
export { sales, orders, payments } from './sales'
|
||||
export { getPaginatedItems } from './paginated'
|
||||
|
||||
export type { PageParams } from './master'
|
||||
export { getApiError } from '@/lib/api'
|
||||
@@ -0,0 +1,186 @@
|
||||
import { api } from '@/lib/api'
|
||||
import type {
|
||||
PaginatedResponse,
|
||||
RegionResponse,
|
||||
RouteResponse,
|
||||
VehicleResponse,
|
||||
WarehouseResponse,
|
||||
VehicleType,
|
||||
WarehouseType,
|
||||
} from '@/types/api'
|
||||
|
||||
const VEHICLE_TYPE_CODES: Record<VehicleType, number> = {
|
||||
Car: 0,
|
||||
Truck: 1,
|
||||
Van: 2,
|
||||
Motorcycle: 3,
|
||||
Bicycle: 4,
|
||||
}
|
||||
|
||||
const VEHICLE_TYPE_VALUES = ['Car', 'Truck', 'Van', 'Motorcycle', 'Bicycle'] as const
|
||||
|
||||
function normalizeVehicleType(type: VehicleType | number): VehicleType {
|
||||
if (typeof type === 'number') {
|
||||
return VEHICLE_TYPE_VALUES[type] ?? 'Car'
|
||||
}
|
||||
|
||||
return type
|
||||
}
|
||||
|
||||
function normalizeVehicle(
|
||||
vehicle: VehicleResponse | (Omit<VehicleResponse, 'type'> & { type: VehicleType | number })
|
||||
): VehicleResponse {
|
||||
return {
|
||||
...vehicle,
|
||||
type: normalizeVehicleType(vehicle.type),
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeVehicleListResponse(
|
||||
response: PaginatedResponse<VehicleResponse> | (Omit<VehicleResponse, 'type'> & { type: VehicleType | number })[],
|
||||
params?: VehicleListParams
|
||||
): PaginatedResponse<VehicleResponse> {
|
||||
if (Array.isArray(response)) {
|
||||
const page = params?.page ?? 1
|
||||
const pageSize = params?.pageSize ?? (response.length || 1)
|
||||
const start = (page - 1) * pageSize
|
||||
const items = response.slice(start, start + pageSize).map(normalizeVehicle)
|
||||
|
||||
return {
|
||||
page,
|
||||
pageSize,
|
||||
total: response.length,
|
||||
items,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...response,
|
||||
items: response.items.map(normalizeVehicle),
|
||||
}
|
||||
}
|
||||
|
||||
function serializeVehicleBody(body: VehicleBody | Partial<VehicleBody>) {
|
||||
return {
|
||||
...body,
|
||||
...(body.type ? { type: VEHICLE_TYPE_CODES[body.type] } : {}),
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Pagination ───────────────────────────────────────────────────────────────
|
||||
|
||||
export interface PageParams {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
}
|
||||
|
||||
// ─── Regions ──────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface RegionBody {
|
||||
name: string
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export const regions = {
|
||||
list: (params?: PageParams) =>
|
||||
api.get<PaginatedResponse<RegionResponse>>('/regions', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<RegionResponse>(`/regions/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: RegionBody) =>
|
||||
api.post<RegionResponse>('/regions', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<RegionBody>) =>
|
||||
api.put<RegionResponse>(`/regions/${id}`, body).then(r => r.data),
|
||||
|
||||
remove: (id: string) =>
|
||||
api.delete(`/regions/${id}`),
|
||||
}
|
||||
|
||||
// ─── Routes ───────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface RouteBody {
|
||||
regionId: string
|
||||
routeName: string
|
||||
startPoint: string
|
||||
endPoint: string
|
||||
length: number
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export const routes = {
|
||||
list: (params?: PageParams & { regionId?: string }) =>
|
||||
api.get<PaginatedResponse<RouteResponse>>('/routes', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<RouteResponse>(`/routes/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: RouteBody) =>
|
||||
api.post<RouteResponse>('/routes', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<RouteBody>) =>
|
||||
api.put<RouteResponse>(`/routes/${id}`, body).then(r => r.data),
|
||||
|
||||
remove: (id: string) =>
|
||||
api.delete(`/routes/${id}`),
|
||||
}
|
||||
|
||||
// ─── Vehicles ─────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface VehicleBody {
|
||||
regNumber: string
|
||||
numberPlate: string
|
||||
type: VehicleType
|
||||
}
|
||||
|
||||
export interface VehicleListParams extends PageParams {
|
||||
available?: boolean
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export const vehicles = {
|
||||
list: (params?: VehicleListParams) =>
|
||||
api.get<PaginatedResponse<VehicleResponse> | VehicleResponse[]>('/vehicles', { params }).then(r =>
|
||||
normalizeVehicleListResponse(r.data, params)
|
||||
),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<VehicleResponse>(`/vehicles/${id}`).then(r => normalizeVehicle(r.data)),
|
||||
|
||||
create: (body: VehicleBody) =>
|
||||
api.post<VehicleResponse>('/vehicles', serializeVehicleBody(body)).then(r => normalizeVehicle(r.data)),
|
||||
|
||||
update: (id: string, body: Partial<VehicleBody>) =>
|
||||
api.put<VehicleResponse>(`/vehicles/${id}`, serializeVehicleBody(body)).then(r => normalizeVehicle(r.data)),
|
||||
|
||||
remove: (id: string) =>
|
||||
api.delete(`/vehicles/${id}`),
|
||||
}
|
||||
|
||||
// ─── Warehouses ───────────────────────────────────────────────────────────────
|
||||
|
||||
export interface WarehouseBody {
|
||||
name: string
|
||||
location: string
|
||||
type: WarehouseType
|
||||
vehicleId?: string | null
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export const warehouses = {
|
||||
list: (params?: PageParams) =>
|
||||
api.get<PaginatedResponse<WarehouseResponse>>('/warehouses', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<WarehouseResponse>(`/warehouses/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: WarehouseBody) =>
|
||||
api.post<WarehouseResponse>('/warehouses', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<WarehouseBody>) =>
|
||||
api.put<WarehouseResponse>(`/warehouses/${id}`, body).then(r => r.data),
|
||||
|
||||
remove: (id: string) =>
|
||||
api.delete(`/warehouses/${id}`),
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
import { api } from '@/lib/api'
|
||||
import type {
|
||||
PaginatedResponse,
|
||||
RideResponse,
|
||||
CancelRequestResponse,
|
||||
LoadingSheetResponse,
|
||||
DeliveryTaskResponse,
|
||||
RideType,
|
||||
RideStatus,
|
||||
CancelRequestType,
|
||||
CancelRequestStatus,
|
||||
LoadingSheetStatus,
|
||||
DeliveryTaskStatus,
|
||||
} from '@/types/api'
|
||||
|
||||
import type { PageParams } from './master'
|
||||
|
||||
// ─── Rides ────────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface RideBody {
|
||||
rideType: RideType
|
||||
vehicleId: string
|
||||
driverProfileId: string
|
||||
routeId: string
|
||||
sourceWarehouseId: string
|
||||
meterstart: number
|
||||
}
|
||||
|
||||
export interface RideListParams extends PageParams {
|
||||
status?: RideStatus
|
||||
rideType?: RideType
|
||||
driverProfileId?: string
|
||||
vehicleId?: string
|
||||
}
|
||||
|
||||
export interface CancelRequestBody {
|
||||
typeCode: CancelRequestType
|
||||
reason: string
|
||||
}
|
||||
|
||||
export interface CancelRequestReviewBody {
|
||||
status: CancelRequestStatus
|
||||
}
|
||||
|
||||
export const rides = {
|
||||
list: (params?: RideListParams) =>
|
||||
api.get<PaginatedResponse<RideResponse>>('/rides', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<RideResponse>(`/rides/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: RideBody) =>
|
||||
api.post<RideResponse>('/rides', body).then(r => r.data),
|
||||
|
||||
activate: (id: string) =>
|
||||
api.patch<RideResponse>(`/rides/${id}/activate`).then(r => r.data),
|
||||
|
||||
close: (id: string, meterend: number) =>
|
||||
api.patch<RideResponse>(`/rides/${id}/close`, { meterend }).then(r => r.data),
|
||||
|
||||
cancelRequests: {
|
||||
list: (rideId: string) =>
|
||||
api.get<CancelRequestResponse[]>(`/rides/${rideId}/cancel-requests`).then(r => r.data),
|
||||
|
||||
create: (rideId: string, body: CancelRequestBody) =>
|
||||
api.post<CancelRequestResponse>(`/rides/${rideId}/cancel-requests`, body).then(r => r.data),
|
||||
|
||||
review: (rideId: string, requestId: string, body: CancelRequestReviewBody) =>
|
||||
api.patch<CancelRequestResponse>(`/rides/${rideId}/cancel-requests/${requestId}`, body).then(r => r.data),
|
||||
},
|
||||
}
|
||||
|
||||
// ─── Loading Sheets ───────────────────────────────────────────────────────────
|
||||
|
||||
export interface LoadingSheetItemBody {
|
||||
itemId: string
|
||||
quantityDispatched: number
|
||||
}
|
||||
|
||||
export interface LoadingSheetBody {
|
||||
rideId: string
|
||||
sourceWarehouseId: string
|
||||
items: LoadingSheetItemBody[]
|
||||
}
|
||||
|
||||
export interface LoadingSheetReceiptItemBody {
|
||||
itemId: string
|
||||
quantityReceived: number
|
||||
}
|
||||
|
||||
export interface LoadingSheetListParams extends PageParams {
|
||||
rideId?: string
|
||||
status?: LoadingSheetStatus
|
||||
}
|
||||
|
||||
export const loadingSheets = {
|
||||
list: (params?: LoadingSheetListParams) =>
|
||||
api.get<PaginatedResponse<LoadingSheetResponse>>('/loading-sheets', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<LoadingSheetResponse>(`/loading-sheets/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: LoadingSheetBody) =>
|
||||
api.post<LoadingSheetResponse>('/loading-sheets', body).then(r => r.data),
|
||||
|
||||
confirmDispatch: (id: string) =>
|
||||
api.patch<LoadingSheetResponse>(`/loading-sheets/${id}/dispatch`).then(r => r.data),
|
||||
|
||||
confirmReceipt: (id: string, items: LoadingSheetReceiptItemBody[]) =>
|
||||
api.patch<LoadingSheetResponse>(`/loading-sheets/${id}/receipt`, { items }).then(r => r.data),
|
||||
|
||||
resolve: (id: string) =>
|
||||
api.patch<LoadingSheetResponse>(`/loading-sheets/${id}/resolve`).then(r => r.data),
|
||||
}
|
||||
|
||||
// ─── Delivery Tasks ───────────────────────────────────────────────────────────
|
||||
|
||||
export interface DeliveryTaskListParams extends PageParams {
|
||||
rideId?: string
|
||||
status?: DeliveryTaskStatus
|
||||
storeId?: string
|
||||
}
|
||||
|
||||
export const deliveryTasks = {
|
||||
listByRide: (rideId: string, params?: Omit<DeliveryTaskListParams, 'rideId'>) =>
|
||||
api.get<PaginatedResponse<DeliveryTaskResponse>>(`/rides/${rideId}/delivery-tasks`, { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<DeliveryTaskResponse>(`/delivery-tasks/${id}`).then(r => r.data),
|
||||
|
||||
updateStatus: (id: string, status: DeliveryTaskStatus, note?: string) =>
|
||||
api.patch<DeliveryTaskResponse>(`/delivery-tasks/${id}/status`, { status, note }).then(r => r.data),
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export function getPaginatedItems<T>(value: T[] | { items?: T[] } | null | undefined): T[] {
|
||||
if (Array.isArray(value)) return value
|
||||
return Array.isArray(value?.items) ? value.items : []
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import { api } from '@/lib/api'
|
||||
import type {
|
||||
PaginatedResponse,
|
||||
PriceListResponse,
|
||||
SchemeResponse,
|
||||
SchemeRuleType,
|
||||
} from '@/types/api'
|
||||
|
||||
import type { PageParams } from './master'
|
||||
|
||||
// ─── Price Lists ──────────────────────────────────────────────────────────────
|
||||
|
||||
export interface PriceListItemBody {
|
||||
itemId: string
|
||||
price: number
|
||||
minPrice?: number | null
|
||||
}
|
||||
|
||||
export interface PriceListBody {
|
||||
name: string
|
||||
regionId?: string | null
|
||||
effectiveFrom: string
|
||||
effectiveTo: string
|
||||
isActive?: boolean
|
||||
items: PriceListItemBody[]
|
||||
}
|
||||
|
||||
export interface PriceListListParams extends PageParams {
|
||||
regionId?: string
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export const priceLists = {
|
||||
list: (params?: PriceListListParams) =>
|
||||
api.get<PaginatedResponse<PriceListResponse>>('/price-lists', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<PriceListResponse>(`/price-lists/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: PriceListBody) =>
|
||||
api.post<PriceListResponse>('/price-lists', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<PriceListBody>) =>
|
||||
api.put<PriceListResponse>(`/price-lists/${id}`, body).then(r => r.data),
|
||||
}
|
||||
|
||||
// ─── Schemes ──────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface BundleComponentBody {
|
||||
itemId: string
|
||||
qty: number
|
||||
}
|
||||
|
||||
export interface SchemeBody {
|
||||
name: string
|
||||
ruleType: SchemeRuleType
|
||||
ruleConfig?: string | null
|
||||
triggerItemId?: string | null
|
||||
triggerQty?: number
|
||||
freeItemId?: string | null
|
||||
freeQty?: number
|
||||
bundleComponents?: BundleComponentBody[]
|
||||
regionId?: string | null
|
||||
eligibleSegment?: string | null
|
||||
dateRangeFrom: string
|
||||
dateRangeTo: string
|
||||
agentLimitExempt?: boolean
|
||||
baselineExpectedSales?: number
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export interface SchemeListParams extends PageParams {
|
||||
regionId?: string
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export const schemes = {
|
||||
list: (params?: SchemeListParams) =>
|
||||
api.get<PaginatedResponse<SchemeResponse>>('/schemes', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<SchemeResponse>(`/schemes/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: SchemeBody) =>
|
||||
api.post<SchemeResponse>('/schemes', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<SchemeBody>) =>
|
||||
api.put<SchemeResponse>(`/schemes/${id}`, body).then(r => r.data),
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { api } from '@/lib/api'
|
||||
import type {
|
||||
PaginatedResponse,
|
||||
PurchaseOrderResponse,
|
||||
GrnResponse,
|
||||
PurchaseOrderStatus,
|
||||
} from '@/types/api'
|
||||
|
||||
import type { PageParams } from './master'
|
||||
|
||||
// ─── Purchase Orders ──────────────────────────────────────────────────────────
|
||||
|
||||
export interface PurchaseOrderItemBody {
|
||||
itemId: string
|
||||
quantity: number
|
||||
unitCost: number
|
||||
}
|
||||
|
||||
export interface PurchaseOrderBody {
|
||||
supplierId: string
|
||||
items: PurchaseOrderItemBody[]
|
||||
}
|
||||
|
||||
export interface PurchaseOrderListParams extends PageParams {
|
||||
supplierId?: string
|
||||
status?: PurchaseOrderStatus
|
||||
}
|
||||
|
||||
export const purchaseOrders = {
|
||||
list: (params?: PurchaseOrderListParams) =>
|
||||
api.get<PaginatedResponse<PurchaseOrderResponse>>('/purchase-orders', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<PurchaseOrderResponse>(`/purchase-orders/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: PurchaseOrderBody) =>
|
||||
api.post<PurchaseOrderResponse>('/purchase-orders', body).then(r => r.data),
|
||||
|
||||
cancel: (id: string, cancelReason: string) =>
|
||||
api.patch<PurchaseOrderResponse>(`/purchase-orders/${id}/cancel`, { cancelReason }).then(r => r.data),
|
||||
}
|
||||
|
||||
// ─── Goods Receipts (GRN) ─────────────────────────────────────────────────────
|
||||
|
||||
export interface GrnItemBody {
|
||||
purchaseOrderItemId: string
|
||||
acceptedQuantity: number
|
||||
rejectedQuantity: number
|
||||
}
|
||||
|
||||
export interface GrnBody {
|
||||
purchaseOrderId: string
|
||||
warehouseId: string
|
||||
receivedAt: string
|
||||
items: GrnItemBody[]
|
||||
}
|
||||
|
||||
export const grn = {
|
||||
list: (params?: PageParams & { purchaseOrderId?: string }) =>
|
||||
api.get<PaginatedResponse<GrnResponse>>('/goods-receipts', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<GrnResponse>(`/goods-receipts/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: GrnBody) =>
|
||||
api.post<GrnResponse>('/goods-receipts', body).then(r => r.data),
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import { api } from '@/lib/api'
|
||||
import type {
|
||||
PaginatedResponse,
|
||||
SaleResponse,
|
||||
OrderResponse,
|
||||
PaymentResponse,
|
||||
SaleStatus,
|
||||
OrderStatus,
|
||||
PaymentStatus,
|
||||
PaymentMethod,
|
||||
} from '@/types/api'
|
||||
|
||||
import type { PageParams } from './master'
|
||||
|
||||
// ─── Sales ────────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface SaleItemBody {
|
||||
itemId: string
|
||||
quantity: number
|
||||
unitPrice: number
|
||||
}
|
||||
|
||||
export interface SaleBody {
|
||||
storeId: string
|
||||
rideId?: string | null
|
||||
fulfillImmediately?: boolean
|
||||
items: SaleItemBody[]
|
||||
}
|
||||
|
||||
export interface SaleListParams extends PageParams {
|
||||
storeId?: string
|
||||
status?: SaleStatus
|
||||
paymentStatus?: PaymentStatus
|
||||
rideId?: string
|
||||
from?: string
|
||||
to?: string
|
||||
}
|
||||
|
||||
export const sales = {
|
||||
list: (params?: SaleListParams) =>
|
||||
api.get<PaginatedResponse<SaleResponse>>('/sales', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<SaleResponse>(`/sales/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: SaleBody) =>
|
||||
api.post<SaleResponse>('/sales', body).then(r => r.data),
|
||||
|
||||
cancel: (id: string) =>
|
||||
api.patch<SaleResponse>(`/sales/${id}/cancel`).then(r => r.data),
|
||||
}
|
||||
|
||||
// ─── Orders ───────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface OrderListParams extends PageParams {
|
||||
storeId?: string
|
||||
status?: OrderStatus
|
||||
from?: string
|
||||
to?: string
|
||||
}
|
||||
|
||||
export const orders = {
|
||||
list: (params?: OrderListParams) =>
|
||||
api.get<PaginatedResponse<OrderResponse>>('/orders', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<OrderResponse>(`/orders/${id}`).then(r => r.data),
|
||||
}
|
||||
|
||||
// ─── Payments ─────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface PaymentBody {
|
||||
saleId: string
|
||||
storeId: string
|
||||
amount: number
|
||||
method: PaymentMethod
|
||||
collectedAt: string
|
||||
}
|
||||
|
||||
export interface PaymentListParams extends PageParams {
|
||||
storeId?: string
|
||||
saleId?: string
|
||||
method?: PaymentMethod
|
||||
from?: string
|
||||
to?: string
|
||||
}
|
||||
|
||||
export const payments = {
|
||||
list: (params?: PaymentListParams) =>
|
||||
api.get<PaginatedResponse<PaymentResponse>>('/payments', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<PaymentResponse>(`/payments/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: PaymentBody) =>
|
||||
api.post<PaymentResponse>('/payments', body).then(r => r.data),
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { api } from '@/lib/api'
|
||||
import type {
|
||||
PaginatedResponse,
|
||||
StockBalanceResponse,
|
||||
StockMovementResponse,
|
||||
LocationType,
|
||||
MovementType,
|
||||
} from '@/types/api'
|
||||
|
||||
import type { PageParams } from './master'
|
||||
|
||||
export interface StockBalanceParams extends PageParams {
|
||||
locationId?: string
|
||||
locationType?: LocationType
|
||||
itemId?: string
|
||||
}
|
||||
|
||||
export interface StockMovementParams extends PageParams {
|
||||
itemId?: string
|
||||
locationId?: string
|
||||
type?: MovementType
|
||||
from?: string
|
||||
to?: string
|
||||
}
|
||||
|
||||
export const stock = {
|
||||
balances: (params?: StockBalanceParams) =>
|
||||
api.get<PaginatedResponse<StockBalanceResponse>>('/stock/balances', { params }).then(r => r.data),
|
||||
|
||||
movements: (params?: StockMovementParams) =>
|
||||
api.get<PaginatedResponse<StockMovementResponse>>('/stock/movements', { params }).then(r => r.data),
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import { api } from '@/lib/api'
|
||||
import type {
|
||||
PaginatedResponse,
|
||||
StoreResponse,
|
||||
KycDocumentResponse,
|
||||
OutstandingBalanceResponse,
|
||||
StoreDashboardResponse,
|
||||
KycStatus,
|
||||
} from '@/types/api'
|
||||
|
||||
import type { PageParams } from './master'
|
||||
|
||||
// ─── Stores ───────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface StoreBody {
|
||||
routeId: string
|
||||
ownerName: string
|
||||
storeName: string
|
||||
storeAddress: string
|
||||
latitude: number
|
||||
longitude: number
|
||||
oneTimeAmount?: number
|
||||
creditLimit?: number
|
||||
segment?: string | null
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export interface StoreListParams extends PageParams {
|
||||
routeId?: string
|
||||
kycStatus?: KycStatus
|
||||
search?: string
|
||||
}
|
||||
|
||||
export const stores = {
|
||||
list: (params?: StoreListParams) =>
|
||||
api.get<PaginatedResponse<StoreResponse>>('/stores', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<StoreResponse>(`/stores/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: StoreBody) =>
|
||||
api.post<StoreResponse>('/stores', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<StoreBody>) =>
|
||||
api.put<StoreResponse>(`/stores/${id}`, body).then(r => r.data),
|
||||
|
||||
outstandingBalance: (id: string) =>
|
||||
api.get<OutstandingBalanceResponse>(`/stores/${id}/outstanding-balance`).then(r => r.data),
|
||||
|
||||
dashboard: (id: string, period?: string) =>
|
||||
api.get<StoreDashboardResponse>(`/stores/${id}/dashboard`, { params: { period } }).then(r => r.data),
|
||||
|
||||
kycDocuments: (id: string) =>
|
||||
api.get<KycDocumentResponse[]>(`/stores/${id}/kyc-documents`).then(r => r.data),
|
||||
|
||||
uploadKycDocument: (id: string, documentType: string, fileReference: string) =>
|
||||
api.post<KycDocumentResponse>(`/stores/${id}/kyc-documents`, { documentType, fileReference }).then(r => r.data),
|
||||
|
||||
updateKycStatus: (id: string, kycStatus: KycStatus) =>
|
||||
api.patch<StoreResponse>(`/stores/${id}/kyc-status`, { kycStatus }).then(r => r.data),
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { api } from '@/lib/api'
|
||||
import type { PaginatedResponse, SupplierResponse } from '@/types/api'
|
||||
import type { PageParams } from './master'
|
||||
|
||||
export interface SupplierBody {
|
||||
name: string
|
||||
contactInfo?: string | null
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export const suppliers = {
|
||||
list: (params?: PageParams) =>
|
||||
api.get<PaginatedResponse<SupplierResponse>>('/suppliers', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<SupplierResponse>(`/suppliers/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: SupplierBody) =>
|
||||
api.post<SupplierResponse>('/suppliers', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<SupplierBody>) =>
|
||||
api.put<SupplierResponse>(`/suppliers/${id}`, body).then(r => r.data),
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import { api } from '@/lib/api'
|
||||
import type {
|
||||
PaginatedResponse,
|
||||
UserResponse,
|
||||
RoleResponse,
|
||||
PermissionResponse,
|
||||
} from '@/types/api'
|
||||
|
||||
import type { PageParams } from './master'
|
||||
|
||||
// ─── Users ────────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface UserBody {
|
||||
username: string
|
||||
fullName: string
|
||||
roleId: string
|
||||
reportsToUserId?: string | null
|
||||
password?: string
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export interface UserListParams extends PageParams {
|
||||
roleId?: string
|
||||
search?: string
|
||||
}
|
||||
|
||||
export const users = {
|
||||
list: (params?: UserListParams) =>
|
||||
api.get<PaginatedResponse<UserResponse>>('/users', { params }).then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<UserResponse>(`/users/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: UserBody) =>
|
||||
api.post<UserResponse>('/users', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<UserBody>) =>
|
||||
api.put<UserResponse>(`/users/${id}`, body).then(r => r.data),
|
||||
}
|
||||
|
||||
// ─── Roles ────────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface RoleBody {
|
||||
name: string
|
||||
level: number
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export interface RoleWithPermissions extends RoleResponse {
|
||||
permissions: PermissionResponse[]
|
||||
}
|
||||
|
||||
export const roles = {
|
||||
list: () =>
|
||||
api.get<RoleResponse[]>('/roles').then(r => r.data),
|
||||
|
||||
get: (id: string) =>
|
||||
api.get<RoleWithPermissions>(`/roles/${id}`).then(r => r.data),
|
||||
|
||||
create: (body: RoleBody) =>
|
||||
api.post<RoleResponse>('/roles', body).then(r => r.data),
|
||||
|
||||
update: (id: string, body: Partial<RoleBody>) =>
|
||||
api.put<RoleResponse>(`/roles/${id}`, body).then(r => r.data),
|
||||
|
||||
assignPermissions: (id: string, permissionIds: string[]) =>
|
||||
api.put(`/roles/${id}/permissions`, { permissionIds }).then(r => r.data),
|
||||
}
|
||||
|
||||
// ─── Permissions ──────────────────────────────────────────────────────────────
|
||||
|
||||
export const permissions = {
|
||||
list: () =>
|
||||
api.get<PermissionResponse[]>('/permissions').then(r => r.data),
|
||||
}
|
||||
Reference in New Issue
Block a user