71 lines
2.5 KiB
TypeScript
71 lines
2.5 KiB
TypeScript
import type { AdminDiscount, OffsetPaginated } from '@sport/types';
|
|
|
|
import type { HttpClient } from '../http-client';
|
|
|
|
export interface DiscountListParams {
|
|
page?: number;
|
|
perPage?: number;
|
|
q?: string;
|
|
trigger?: 'AUTOMATIC' | 'CODE';
|
|
}
|
|
|
|
/**
|
|
* A discount as the admin form submits it.
|
|
*
|
|
* Deliberately not `DiscountInput` from `@sport/validation`: that is the type
|
|
* *after* parsing, with defaults already applied, so using it here would force
|
|
* every caller to supply fields the schema is perfectly happy to fill in.
|
|
*/
|
|
export interface DiscountPayload {
|
|
code?: string | null;
|
|
trigger: 'AUTOMATIC' | 'CODE';
|
|
type: 'PERCENTAGE' | 'FIXED_AMOUNT';
|
|
scope?: 'ORDER' | 'PRODUCT';
|
|
value: number;
|
|
translations: Record<string, { name: string; description?: string | null }>;
|
|
minSubtotalAmount?: number | null;
|
|
startsAt?: string | null;
|
|
endsAt?: string | null;
|
|
isActive?: boolean;
|
|
usageLimit?: number | null;
|
|
stackable?: boolean;
|
|
priority?: number;
|
|
productIds?: string[];
|
|
collectionIds?: string[];
|
|
}
|
|
|
|
/**
|
|
* Promotions and coupons, which are one resource.
|
|
*
|
|
* There is no `coupons` resource next to this one, and that is the point: a
|
|
* coupon is a promotion that needs a code typed (ADR-0020). Two client
|
|
* resources would reintroduce the split the data model exists to avoid.
|
|
*/
|
|
export interface PromotionsAdminResource {
|
|
list(params?: DiscountListParams): Promise<OffsetPaginated<AdminDiscount>>;
|
|
getById(id: string): Promise<AdminDiscount>;
|
|
create(payload: DiscountPayload): Promise<AdminDiscount>;
|
|
update(id: string, payload: DiscountPayload): Promise<AdminDiscount>;
|
|
remove(id: string): Promise<void>;
|
|
}
|
|
|
|
export function createPromotionsAdminResource(http: HttpClient): PromotionsAdminResource {
|
|
// Never cached. An operator who just switched a promotion off must see it
|
|
// off — a stale list here is a discount they believe they stopped giving.
|
|
const uncached = { cache: 'no-store' } as const;
|
|
|
|
return {
|
|
list: (params = {}) =>
|
|
http.get<OffsetPaginated<AdminDiscount>>('/admin/discounts', {
|
|
...uncached,
|
|
query: { ...params },
|
|
}),
|
|
getById: (id) =>
|
|
http.get<AdminDiscount>(`/admin/discounts/${encodeURIComponent(id)}`, uncached),
|
|
create: (payload) => http.post<AdminDiscount>('/admin/discounts', payload, uncached),
|
|
update: (id, payload) =>
|
|
http.patch<AdminDiscount>(`/admin/discounts/${encodeURIComponent(id)}`, payload, uncached),
|
|
remove: (id) => http.delete<void>(`/admin/discounts/${encodeURIComponent(id)}`, uncached),
|
|
};
|
|
}
|