Stage M7
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
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),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user