feat: persist customer product and shop favorites through the live API
Replace mall fixture favorites with customer-scoped endpoints, and send signed-out shoppers back to the page they left after sign-in. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
94a64ec712
commit
6c1357ec4d
@@ -13,6 +13,8 @@ import type {
|
||||
CouponTemplate,
|
||||
CouponTemplateInput,
|
||||
Currency,
|
||||
Favorite,
|
||||
FavoriteKind,
|
||||
FlashSaleItem,
|
||||
FlashSaleItemInput,
|
||||
FlashSaleSession,
|
||||
@@ -126,6 +128,13 @@ export interface ConvertResult {
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface FavoriteListQuery {
|
||||
kind: FavoriteKind;
|
||||
target_id?: string;
|
||||
page?: number;
|
||||
per_page?: number;
|
||||
}
|
||||
|
||||
type Query = Record<string, string | number | boolean | undefined>;
|
||||
|
||||
async function request<T>(
|
||||
@@ -212,6 +221,11 @@ export interface ApiClient {
|
||||
updateAddress(id: string, address: AddressInput): Promise<AddressBookEntry>;
|
||||
deleteAddress(id: string): Promise<AddressBookEntry[]>;
|
||||
setDefaultAddress(id: string): Promise<AddressBookEntry>;
|
||||
listFavorites(q: FavoriteListQuery): Promise<Paged<Favorite>>;
|
||||
addProductFavorite(productId: string): Promise<Favorite>;
|
||||
removeProductFavorite(productId: string): Promise<void>;
|
||||
addShopFavorite(shopId: string): Promise<Favorite>;
|
||||
removeShopFavorite(shopId: string): Promise<void>;
|
||||
/** Public: coupons a shopper could claim from this shop right now. */
|
||||
listShopCouponTemplates(shopId: string): Promise<CouponTemplate[]>;
|
||||
listMyCoupons(): Promise<Coupon[]>;
|
||||
@@ -328,6 +342,11 @@ export function createApi(opts: ApiClientOptions): ApiClient {
|
||||
updateAddress: (id, address) => r("PUT", `/addresses/${id}`, address),
|
||||
deleteAddress: (id) => r("DELETE", `/addresses/${id}`),
|
||||
setDefaultAddress: (id) => r("POST", `/addresses/${id}/default`),
|
||||
listFavorites: (q) => r("GET", "/favorites", undefined, { ...q }),
|
||||
addProductFavorite: (productId) => r("PUT", `/favorites/products/${productId}`),
|
||||
removeProductFavorite: (productId) => r("DELETE", `/favorites/products/${productId}`),
|
||||
addShopFavorite: (shopId) => r("PUT", `/favorites/shops/${shopId}`),
|
||||
removeShopFavorite: (shopId) => r("DELETE", `/favorites/shops/${shopId}`),
|
||||
listShopCouponTemplates: (shopId) => r("GET", `/shops/${shopId}/coupon-templates`),
|
||||
listMyCoupons: () => r("GET", "/me/coupons"),
|
||||
claimCoupon: (templateId) => r("POST", "/me/coupons", { template_id: templateId }),
|
||||
|
||||
@@ -567,6 +567,37 @@ export interface ShopProfile {
|
||||
score_speed: number | null;
|
||||
}
|
||||
|
||||
/** Current public product card data nested in a product favorite. */
|
||||
export interface FavoriteProductSummary {
|
||||
id: string;
|
||||
shop_id: string;
|
||||
slug: string;
|
||||
name: LocalizedText;
|
||||
image: string | null;
|
||||
price_minor: number | null;
|
||||
currency: string | null;
|
||||
}
|
||||
|
||||
export type FavoriteKind = "product" | "shop";
|
||||
|
||||
export interface ProductFavorite {
|
||||
kind: "product";
|
||||
id: string;
|
||||
user_id: string;
|
||||
created_at: string;
|
||||
product: FavoriteProductSummary;
|
||||
}
|
||||
|
||||
export interface ShopFavorite {
|
||||
kind: "shop";
|
||||
id: string;
|
||||
user_id: string;
|
||||
created_at: string;
|
||||
shop: ShopProfile;
|
||||
}
|
||||
|
||||
export type Favorite = ProductFavorite | ShopFavorite;
|
||||
|
||||
export interface ShopProfileInput {
|
||||
logo?: string | null;
|
||||
banner?: string | null;
|
||||
|
||||
Reference in New Issue
Block a user