@mohasinac/appkit 2.7.17 → 2.7.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/server/features/bundles/actions.d.ts +15 -0
- package/dist/_internal/server/features/bundles/actions.js +48 -0
- package/dist/_internal/server/features/bundles/index.d.ts +1 -0
- package/dist/_internal/server/features/bundles/index.js +1 -0
- package/dist/_internal/server/features/checkout/actions.d.ts +4 -0
- package/dist/_internal/server/features/checkout/actions.js +23 -12
- package/dist/_internal/server/features/payments/data.d.ts +5 -3
- package/dist/_internal/server/features/payments/data.js +13 -8
- package/dist/_internal/server/features/payments/index.d.ts +1 -1
- package/dist/_internal/server/features/payments/index.js +1 -1
- package/dist/_internal/server/features/seo/manifest.js +9 -3
- package/dist/_internal/shared/features/categories/bundle-config.d.ts +24 -0
- package/dist/_internal/shared/features/categories/bundle-config.js +28 -0
- package/dist/_internal/shared/features/categories/bundle-copy.d.ts +7 -0
- package/dist/_internal/shared/features/categories/bundle-copy.js +9 -0
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +69 -19
- package/dist/_internal/shared/features/categories/bundle-schemas.js +20 -2
- package/dist/_internal/shared/features/checkout/config.d.ts +1 -1
- package/dist/_internal/shared/features/checkout/config.js +1 -1
- package/dist/_internal/shared/features/payments/config.d.ts +2 -1
- package/dist/_internal/shared/features/payments/config.js +2 -1
- package/dist/_internal/shared/features/products/schema.d.ts +8 -8
- package/dist/constants/field-names.d.ts +8 -1
- package/dist/constants/field-names.js +9 -2
- package/dist/constants/table-keys.d.ts +3 -0
- package/dist/constants/table-keys.js +3 -0
- package/dist/features/admin/components/AdminSiteSettingsView.js +17 -15
- package/dist/features/admin/components/DashboardStats.js +20 -12
- package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +18 -2
- package/dist/features/admin/components/analytics/AdminStatCard.d.ts +7 -1
- package/dist/features/admin/components/analytics/AdminStatCard.js +13 -2
- package/dist/features/admin/schemas/firestore.d.ts +39 -4
- package/dist/features/admin/schemas/firestore.js +14 -1
- package/dist/features/categories/components/BundleBuyNowCta.d.ts +3 -1
- package/dist/features/categories/components/BundleBuyNowCta.js +3 -3
- package/dist/features/categories/components/BundleDynamicRuleEditor.d.ts +1 -1
- package/dist/features/categories/components/BundleDynamicRuleEditor.js +2 -1
- package/dist/features/categories/components/BundlesListView.d.ts +4 -1
- package/dist/features/categories/components/BundlesListView.js +2 -2
- package/dist/features/categories/components/CategoryBundlesListing.d.ts +4 -1
- package/dist/features/categories/components/CategoryBundlesListing.js +9 -8
- package/dist/features/categories/schemas/firestore.d.ts +29 -1
- package/dist/features/checkout/actions/checkout-actions.d.ts +11 -0
- package/dist/features/checkout/actions/checkout-actions.js +26 -0
- package/dist/features/filters/FilterFacetSection.d.ts +6 -1
- package/dist/features/filters/FilterFacetSection.js +25 -2
- package/dist/features/homepage/components/FeaturedBundlesSection.d.ts +4 -1
- package/dist/features/homepage/components/FeaturedBundlesSection.js +9 -8
- package/dist/features/orders/actions/refund-actions.js +10 -7
- package/dist/features/orders/schemas/firestore.d.ts +16 -13
- package/dist/features/orders/schemas/firestore.js +6 -5
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +1 -1
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +2 -1
- package/dist/features/products/components/AuctionsIndexListing.js +2 -1
- package/dist/features/products/components/ProductDetailPageView.js +3 -1
- package/dist/features/products/components/ProductDetailView.d.ts +3 -1
- package/dist/features/products/components/ProductDetailView.js +2 -2
- package/dist/features/products/components/ProductFilters.d.ts +10 -4
- package/dist/features/products/components/ProductFilters.js +20 -16
- package/dist/features/products/components/ProductGrid.js +2 -2
- package/dist/features/products/components/ProductsIndexListing.js +2 -1
- package/dist/features/products/constants/action-defs.d.ts +64 -22
- package/dist/features/products/constants/action-defs.js +101 -64
- package/dist/features/products/constants/product-features.constants.js +5 -1
- package/dist/features/products/schemas/index.d.ts +2 -2
- package/dist/features/products/schemas/product-features.d.ts +1 -1
- package/dist/features/products/schemas/product-features.validators.d.ts +10 -10
- package/dist/features/products/schemas/product-features.validators.js +4 -0
- package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
- package/dist/features/seller/components/analytics/SellerAnalyticsStats.js +10 -4
- package/dist/features/stores/components/StoreBundlesPageView.d.ts +4 -1
- package/dist/features/stores/components/StoreBundlesPageView.js +2 -2
- package/dist/features/stores/components/StoresIndexListing.js +2 -1
- package/dist/providers/db-firebase/admin-app-lite.js +8 -2
- package/dist/providers/db-firebase/admin.js +8 -2
- package/dist/seed/addresses-seed-data.js +24 -7
- package/dist/seed/cart-seed-data.d.ts +10 -10
- package/dist/seed/cart-seed-data.js +39 -2
- package/dist/seed/grouped-listings-seed-data.js +47 -0
- package/dist/seed/orders-seed-data.js +150 -0
- package/dist/seed/products-standard-seed-data.js +42 -0
- package/dist/seed/site-settings-seed-data.js +14 -4
- package/dist/seed/users-seed-data.js +1 -1
- package/dist/seed/wishlists-seed-data.js +7 -0
- package/dist/server-entry.d.ts +2 -1
- package/dist/server-entry.js +2 -1
- package/dist/server.d.ts +2 -1
- package/dist/server.js +3 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/SideDrawer.style.css +49 -11
- package/package.json +1 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle server actions — appkit internal.
|
|
3
|
+
*
|
|
4
|
+
* `addBundleToCartAction` is the shared business logic called by the
|
|
5
|
+
* consumer's `"use server"` wrapper. The consumer is responsible for:
|
|
6
|
+
* 1. Resolving the authenticated userId (throw AuthError when unauthenticated
|
|
7
|
+
* so BundleBuyNowCta's isAuthError guard shows the login modal).
|
|
8
|
+
* 2. Calling redirect(ROUTES.PUBLIC.CHECKOUT) after this returns.
|
|
9
|
+
*
|
|
10
|
+
* Bundles are categoryType:"bundle" rows — they bypass the regular
|
|
11
|
+
* addItemToCart capability gate and write directly to cartRepository with
|
|
12
|
+
* bundleCategorySlug + bundleProductIds so checkout's bundle-expansion
|
|
13
|
+
* helpers can fan out stock decrements to member products.
|
|
14
|
+
*/
|
|
15
|
+
export declare function addBundleToCartAction(userId: string, bundleSlug: string): Promise<void>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle server actions — appkit internal.
|
|
3
|
+
*
|
|
4
|
+
* `addBundleToCartAction` is the shared business logic called by the
|
|
5
|
+
* consumer's `"use server"` wrapper. The consumer is responsible for:
|
|
6
|
+
* 1. Resolving the authenticated userId (throw AuthError when unauthenticated
|
|
7
|
+
* so BundleBuyNowCta's isAuthError guard shows the login modal).
|
|
8
|
+
* 2. Calling redirect(ROUTES.PUBLIC.CHECKOUT) after this returns.
|
|
9
|
+
*
|
|
10
|
+
* Bundles are categoryType:"bundle" rows — they bypass the regular
|
|
11
|
+
* addItemToCart capability gate and write directly to cartRepository with
|
|
12
|
+
* bundleCategorySlug + bundleProductIds so checkout's bundle-expansion
|
|
13
|
+
* helpers can fan out stock decrements to member products.
|
|
14
|
+
*/
|
|
15
|
+
import { NotFoundError, ValidationError } from "../../../../errors";
|
|
16
|
+
import { categoriesRepository } from "../../../../repositories";
|
|
17
|
+
import { cartRepository } from "../../../../features/cart/repository/cart.repository";
|
|
18
|
+
import { getDefaultCurrency } from "../../../../core/baseline-resolver";
|
|
19
|
+
export async function addBundleToCartAction(userId, bundleSlug) {
|
|
20
|
+
if (!userId)
|
|
21
|
+
throw new ValidationError("User id is required");
|
|
22
|
+
if (!bundleSlug)
|
|
23
|
+
throw new ValidationError("Bundle slug is required");
|
|
24
|
+
const bundle = await categoriesRepository.findBySlugAndType(bundleSlug, "bundle");
|
|
25
|
+
if (!bundle)
|
|
26
|
+
throw new NotFoundError("Bundle not found");
|
|
27
|
+
if (!bundle.isActive)
|
|
28
|
+
throw new ValidationError("Bundle is not available");
|
|
29
|
+
if (bundle.bundleStockStatus === "out_of_stock") {
|
|
30
|
+
throw new ValidationError("Bundle is currently out of stock");
|
|
31
|
+
}
|
|
32
|
+
if (!bundle.bundlePriceInPaise || bundle.bundlePriceInPaise < 1) {
|
|
33
|
+
throw new ValidationError("Bundle price is not configured");
|
|
34
|
+
}
|
|
35
|
+
await cartRepository.addItem(userId, {
|
|
36
|
+
productId: bundle.id,
|
|
37
|
+
productTitle: bundle.name,
|
|
38
|
+
productImage: bundle.display?.coverImage ?? "",
|
|
39
|
+
price: bundle.bundlePriceInPaise,
|
|
40
|
+
currency: getDefaultCurrency(),
|
|
41
|
+
quantity: 1,
|
|
42
|
+
storeId: bundle.createdByStoreId ?? "",
|
|
43
|
+
storeName: bundle.createdByStoreName ?? "",
|
|
44
|
+
listingType: "standard",
|
|
45
|
+
bundleCategorySlug: bundle.slug,
|
|
46
|
+
bundleProductIds: bundle.bundleProductIds ?? [],
|
|
47
|
+
});
|
|
48
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { getBundleForDetail, listBundleMembers, listFeaturedBundles, type BundleDataOptions, } from "./data";
|
|
2
2
|
export { buildBundleMetadata, type BundleMetadataOptions } from "./metadata";
|
|
3
3
|
export { renderBundleOg, renderBundleOgImage, type BundleOgData, } from "./og";
|
|
4
|
+
export { addBundleToCartAction } from "./actions";
|
|
@@ -2,3 +2,4 @@ export { getBundleForDetail, listBundleMembers, listFeaturedBundles, } from "./d
|
|
|
2
2
|
export { buildBundleMetadata } from "./metadata";
|
|
3
3
|
// S-SBUNI-4 2026-05-13 — bundle OG renderer.
|
|
4
4
|
export { renderBundleOg, renderBundleOgImage, } from "./og";
|
|
5
|
+
export { addBundleToCartAction } from "./actions";
|
|
@@ -16,6 +16,10 @@ export interface CreateCheckoutOrderInput {
|
|
|
16
16
|
paymentMethod: CheckoutPaymentMethod;
|
|
17
17
|
notes?: string;
|
|
18
18
|
excludedProductIds?: string[];
|
|
19
|
+
/** When true this is an admin test order — OTP consent is pre-granted and the order is created paid/processing. */
|
|
20
|
+
adminBypass?: boolean;
|
|
21
|
+
/** UID of the admin who triggered the bypass. Set when adminBypass is true. */
|
|
22
|
+
adminBypassBy?: string;
|
|
19
23
|
}
|
|
20
24
|
/**
|
|
21
25
|
* Place order(s) from the user's cart in a single Firestore transaction.
|
|
@@ -76,7 +76,7 @@ function emitOrderPlacedNotifications(args) {
|
|
|
76
76
|
* auth + rate-limiting before calling this and supply the resolved user fields.
|
|
77
77
|
*/
|
|
78
78
|
export async function createCheckoutOrderAction(input) {
|
|
79
|
-
const { userId: uid, userName, userEmail, addressId, paymentMethod, notes, excludedProductIds = [], } = input;
|
|
79
|
+
const { userId: uid, userName, userEmail, addressId, paymentMethod, notes, excludedProductIds = [], adminBypass = false, adminBypassBy, } = input;
|
|
80
80
|
const siteSettings = await siteSettingsRepository.getSingleton();
|
|
81
81
|
const commissions = siteSettings?.commissions ?? CHECKOUT_DEFAULT_COMMISSIONS;
|
|
82
82
|
const cart = await unitOfWork.carts.getOrCreate(uid);
|
|
@@ -147,7 +147,7 @@ export async function createCheckoutOrderAction(input) {
|
|
|
147
147
|
const reason = !otpData ? "otp_not_verified" : "consent_expired";
|
|
148
148
|
throw Object.assign(new ApiError(403, "Order verification required. Please complete OTP verification before placing this order."), { _failReason: reason });
|
|
149
149
|
}
|
|
150
|
-
const emailOtpUsed = otpData.verifiedVia !== "sms";
|
|
150
|
+
const emailOtpUsed = otpData.verifiedVia !== "sms" && otpData.verifiedVia !== "admin_bypass";
|
|
151
151
|
// SB-UNI-5 2026-05-13 — bundle-aware stock fan-out. Build the unique
|
|
152
152
|
// product-id set across the whole cart (regular items + each bundle's
|
|
153
153
|
// members) and fetch each one ONCE. Validation walks per cart-line and
|
|
@@ -249,6 +249,11 @@ export async function createCheckoutOrderAction(input) {
|
|
|
249
249
|
}
|
|
250
250
|
const appliedCoupons = cart.appliedCoupons ?? [];
|
|
251
251
|
const orderGroups = splitCartIntoOrderGroups(available);
|
|
252
|
+
// Admin-bypass orders are immediately paid and processing; generate a shared
|
|
253
|
+
// transaction reference for all orders in this checkout batch.
|
|
254
|
+
const adminBatchId = adminBypass
|
|
255
|
+
? `ADMIN-${Date.now().toString(36).toUpperCase()}-${Math.random().toString(36).slice(2, 6).toUpperCase()}`
|
|
256
|
+
: undefined;
|
|
252
257
|
const orderIds = [];
|
|
253
258
|
let total = 0;
|
|
254
259
|
const emailsToSend = [];
|
|
@@ -389,14 +394,16 @@ export async function createCheckoutOrderAction(input) {
|
|
|
389
394
|
items: orderItems,
|
|
390
395
|
orderType,
|
|
391
396
|
offerId: firstItem.offerId ?? undefined,
|
|
392
|
-
status: OrderStatusValues.PENDING,
|
|
393
|
-
paymentStatus: PaymentStatusValues.PENDING,
|
|
394
|
-
paymentMethod,
|
|
397
|
+
status: adminBypass ? OrderStatusValues.PROCESSING : OrderStatusValues.PENDING,
|
|
398
|
+
paymentStatus: adminBypass ? PaymentStatusValues.PAID : PaymentStatusValues.PENDING,
|
|
399
|
+
paymentMethod: adminBypass ? PaymentMethodValues.ADMIN_BYPASS : paymentMethod,
|
|
400
|
+
paymentId: adminBatchId,
|
|
401
|
+
adminBypassBy: adminBypassBy,
|
|
395
402
|
shippingAddress,
|
|
396
403
|
notes,
|
|
397
404
|
shippingFee: shippingFee > 0 ? shippingFee : undefined,
|
|
398
|
-
depositAmount,
|
|
399
|
-
codRemainingAmount,
|
|
405
|
+
depositAmount: adminBypass ? undefined : depositAmount,
|
|
406
|
+
codRemainingAmount: adminBypass ? undefined : codRemainingAmount,
|
|
400
407
|
couponCode: appliedDiscounts[0]?.code,
|
|
401
408
|
couponDiscount: couponDiscount > 0 ? couponDiscount : undefined,
|
|
402
409
|
appliedDiscounts: appliedDiscounts.length > 0 ? appliedDiscounts : undefined,
|
|
@@ -429,7 +436,7 @@ export async function createCheckoutOrderAction(input) {
|
|
|
429
436
|
buyerName: userName,
|
|
430
437
|
storeOwnerId,
|
|
431
438
|
productLabel: orderItems.length > 1 ? `${orderItems.length} items` : firstItem.productTitle,
|
|
432
|
-
paid:
|
|
439
|
+
paid: adminBypass,
|
|
433
440
|
});
|
|
434
441
|
}
|
|
435
442
|
if (couponUsageAccumulator.size > 0) {
|
|
@@ -487,7 +494,8 @@ export async function attachPaymentAction(input) {
|
|
|
487
494
|
export async function verifyAndPlaceRazorpayOrderAction(input) {
|
|
488
495
|
const { userId: uid, userName, userEmail, razorpay_order_id, razorpay_payment_id, razorpay_signature, addressId, notes, } = input;
|
|
489
496
|
const siteSettings = await siteSettingsRepository.getSingleton();
|
|
490
|
-
const
|
|
497
|
+
const platformFeePercent = siteSettings?.commissions?.platformFeePercent ?? 5;
|
|
498
|
+
const gstPercent = siteSettings?.commissions?.gstPercent ?? 18;
|
|
491
499
|
const commissions = siteSettings?.commissions ?? CHECKOUT_DEFAULT_COMMISSIONS;
|
|
492
500
|
const isValid = await verifyPaymentSignatureWithKeys({
|
|
493
501
|
razorpay_order_id,
|
|
@@ -596,8 +604,9 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
|
|
|
596
604
|
const unit = isBundle ? item.price : product.price;
|
|
597
605
|
return sum + unit * item.quantity;
|
|
598
606
|
}, 0);
|
|
599
|
-
const expectedPlatformFee = Math.round(cartSubtotalRs * (
|
|
600
|
-
const
|
|
607
|
+
const expectedPlatformFee = Math.round(cartSubtotalRs * (platformFeePercent / 100) * 100) / 100;
|
|
608
|
+
const expectedGstOnFee = Math.round(expectedPlatformFee * (gstPercent / 100) * 100) / 100;
|
|
609
|
+
const expectedPaymentAmountRs = cartSubtotalRs + expectedPlatformFee + expectedGstOnFee;
|
|
601
610
|
const rzpOrderRecord = await fetchRazorpayOrder(razorpay_order_id);
|
|
602
611
|
const paidAmountRs = paiseToRupees(rzpOrderRecord.amount);
|
|
603
612
|
if (paidAmountRs < expectedPaymentAmountRs - 1) {
|
|
@@ -684,7 +693,9 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
|
|
|
684
693
|
}
|
|
685
694
|
}
|
|
686
695
|
couponDiscount = Math.min(couponDiscount, groupTotal);
|
|
687
|
-
const
|
|
696
|
+
const rawPlatformFee = Math.round(groupTotal * (platformFeePercent / 100) * 100) / 100;
|
|
697
|
+
const gstOnFee = Math.round(rawPlatformFee * (gstPercent / 100) * 100) / 100;
|
|
698
|
+
const platformFee = rawPlatformFee + gstOnFee;
|
|
688
699
|
const orderTotal = Math.max(0, groupTotal - couponDiscount) + shippingFee;
|
|
689
700
|
total += orderTotal;
|
|
690
701
|
// S-SBUNI-RULES 2026-05-13 — order-item decoration via rule registry.
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export interface ResolvedPaymentFee {
|
|
2
2
|
baseAmount: number;
|
|
3
3
|
platformFee: number;
|
|
4
|
+
gstOnFee: number;
|
|
4
5
|
totalAmount: number;
|
|
5
6
|
}
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Inflates the cart total by our platform fee + GST on that fee.
|
|
9
|
+
* platformFeePercent = siteSettings.commissions.platformFeePercent (our cut %).
|
|
10
|
+
* gstPercent = siteSettings.commissions.gstPercent (18% GST on our fee, not on full order).
|
|
11
|
+
* minimumTransactionFee = per-gateway-transaction floor in rupees.
|
|
10
12
|
*/
|
|
11
13
|
export declare function resolvePaymentFee(baseAmount: number): Promise<ResolvedPaymentFee>;
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { siteSettingsRepository } from "../../../../repositories";
|
|
2
|
-
import {
|
|
2
|
+
import { PAYMENTS_DEFAULT_PLATFORM_FEE_PERCENT, PAYMENTS_DEFAULT_GST_PERCENT, } from "../../../shared/features/payments/config";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Inflates the cart total by our platform fee + GST on that fee.
|
|
5
|
+
* platformFeePercent = siteSettings.commissions.platformFeePercent (our cut %).
|
|
6
|
+
* gstPercent = siteSettings.commissions.gstPercent (18% GST on our fee, not on full order).
|
|
7
|
+
* minimumTransactionFee = per-gateway-transaction floor in rupees.
|
|
7
8
|
*/
|
|
8
9
|
export async function resolvePaymentFee(baseAmount) {
|
|
9
10
|
const siteSettings = await siteSettingsRepository.getSingleton();
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
11
|
+
const platformFeePercent = siteSettings?.commissions?.platformFeePercent ?? PAYMENTS_DEFAULT_PLATFORM_FEE_PERCENT;
|
|
12
|
+
const gstPercent = siteSettings?.commissions?.gstPercent ?? PAYMENTS_DEFAULT_GST_PERCENT;
|
|
13
|
+
const minimumTransactionFee = Math.max(0, siteSettings?.commissions?.minimumTransactionFee ?? 0);
|
|
14
|
+
const platformFee = Math.round(baseAmount * (platformFeePercent / 100) * 100) / 100;
|
|
15
|
+
const gstOnFee = Math.round(platformFee * (gstPercent / 100) * 100) / 100;
|
|
16
|
+
const rawTotal = baseAmount + platformFee + gstOnFee;
|
|
17
|
+
const totalAmount = Math.max(rawTotal, baseAmount + minimumTransactionFee);
|
|
18
|
+
return { baseAmount, platformFee, gstOnFee, totalAmount };
|
|
14
19
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { createPaymentIntentAction, verifyPaymentSignatureAction, type CreatePaymentIntentInput, type CreatePaymentIntentResult, type VerifyPaymentSignatureInput, } from "./actions";
|
|
2
2
|
export { resolvePaymentFee, type ResolvedPaymentFee } from "./data";
|
|
3
|
-
export {
|
|
3
|
+
export { PAYMENTS_DEFAULT_PLATFORM_FEE_PERCENT, PAYMENTS_DEFAULT_GST_PERCENT, PAYMENTS_RECEIPT_PREFIX, } from "../../../shared/features/payments/config";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { createPaymentIntentAction, verifyPaymentSignatureAction, } from "./actions";
|
|
2
2
|
export { resolvePaymentFee } from "./data";
|
|
3
|
-
export {
|
|
3
|
+
export { PAYMENTS_DEFAULT_PLATFORM_FEE_PERCENT, PAYMENTS_DEFAULT_GST_PERCENT, PAYMENTS_RECEIPT_PREFIX, } from "../../../shared/features/payments/config";
|
|
@@ -15,9 +15,15 @@ export function buildManifest({ name, shortName, description }) {
|
|
|
15
15
|
prefer_related_applications: false,
|
|
16
16
|
icons: [
|
|
17
17
|
{
|
|
18
|
-
src: "/favicon.
|
|
19
|
-
sizes: "
|
|
20
|
-
type: "image/
|
|
18
|
+
src: "/favicon/android-chrome-192x192.png",
|
|
19
|
+
sizes: "192x192",
|
|
20
|
+
type: "image/png",
|
|
21
|
+
purpose: "any maskable",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
src: "/favicon/android-chrome-512x512.png",
|
|
25
|
+
sizes: "512x512",
|
|
26
|
+
type: "image/png",
|
|
21
27
|
purpose: "any maskable",
|
|
22
28
|
},
|
|
23
29
|
],
|
|
@@ -15,3 +15,27 @@ export declare const BUNDLE_MAX_PER_USER_DEFAULT: 3;
|
|
|
15
15
|
export declare const BUNDLES_PAGE_SIZE: 24;
|
|
16
16
|
/** Cap on homepage featured-bundles strip. */
|
|
17
17
|
export declare const BUNDLES_FEATURED_LIMIT: 12;
|
|
18
|
+
/**
|
|
19
|
+
* Listing types that may be added to a bundle.
|
|
20
|
+
* - standard — regular product
|
|
21
|
+
* - pre-order — pre-order product
|
|
22
|
+
* - prize-draw — added as N draws/entries (see BundleItemDetail.drawCount)
|
|
23
|
+
*
|
|
24
|
+
* Auctions and bundles themselves are never eligible.
|
|
25
|
+
*/
|
|
26
|
+
export declare const BUNDLE_ELIGIBLE_LISTING_TYPES: readonly ["standard", "pre-order", "prize-draw"];
|
|
27
|
+
export type BundleEligibleListingType = (typeof BUNDLE_ELIGIBLE_LISTING_TYPES)[number];
|
|
28
|
+
/**
|
|
29
|
+
* "special" — explicitly curated admin bundle. Only special bundles write
|
|
30
|
+
* reverse `partOfBundleIds` pointers on member products and are displayed in
|
|
31
|
+
* the "Bundled" badge on product cards / detail pages.
|
|
32
|
+
*
|
|
33
|
+
* "brand" — auto-generated collection driven by a dynamic brand query rule.
|
|
34
|
+
* Does NOT update `partOfBundleIds` on products; treated as a discovery
|
|
35
|
+
* surface, not a priced product grouping.
|
|
36
|
+
*/
|
|
37
|
+
export declare const BUNDLE_KIND_SPECIAL: "special";
|
|
38
|
+
export declare const BUNDLE_KIND_BRAND: "brand";
|
|
39
|
+
export type BundleKind = typeof BUNDLE_KIND_SPECIAL | typeof BUNDLE_KIND_BRAND;
|
|
40
|
+
/** Max draw entries a prize-draw item contributes when added to a bundle. */
|
|
41
|
+
export declare const BUNDLE_DRAW_COUNT_MAX: 500;
|
|
@@ -15,3 +15,31 @@ export const BUNDLE_MAX_PER_USER_DEFAULT = 3;
|
|
|
15
15
|
export const BUNDLES_PAGE_SIZE = 24;
|
|
16
16
|
/** Cap on homepage featured-bundles strip. */
|
|
17
17
|
export const BUNDLES_FEATURED_LIMIT = 12;
|
|
18
|
+
// ── Bundle eligibility ───────────────────────────────────────────────────────
|
|
19
|
+
/**
|
|
20
|
+
* Listing types that may be added to a bundle.
|
|
21
|
+
* - standard — regular product
|
|
22
|
+
* - pre-order — pre-order product
|
|
23
|
+
* - prize-draw — added as N draws/entries (see BundleItemDetail.drawCount)
|
|
24
|
+
*
|
|
25
|
+
* Auctions and bundles themselves are never eligible.
|
|
26
|
+
*/
|
|
27
|
+
export const BUNDLE_ELIGIBLE_LISTING_TYPES = [
|
|
28
|
+
"standard",
|
|
29
|
+
"pre-order",
|
|
30
|
+
"prize-draw",
|
|
31
|
+
];
|
|
32
|
+
// ── Bundle kinds ─────────────────────────────────────────────────────────────
|
|
33
|
+
/**
|
|
34
|
+
* "special" — explicitly curated admin bundle. Only special bundles write
|
|
35
|
+
* reverse `partOfBundleIds` pointers on member products and are displayed in
|
|
36
|
+
* the "Bundled" badge on product cards / detail pages.
|
|
37
|
+
*
|
|
38
|
+
* "brand" — auto-generated collection driven by a dynamic brand query rule.
|
|
39
|
+
* Does NOT update `partOfBundleIds` on products; treated as a discovery
|
|
40
|
+
* surface, not a priced product grouping.
|
|
41
|
+
*/
|
|
42
|
+
export const BUNDLE_KIND_SPECIAL = "special";
|
|
43
|
+
export const BUNDLE_KIND_BRAND = "brand";
|
|
44
|
+
/** Max draw entries a prize-draw item contributes when added to a bundle. */
|
|
45
|
+
export const BUNDLE_DRAW_COUNT_MAX = 500;
|
|
@@ -86,6 +86,13 @@ export declare const BUNDLE_COPY: {
|
|
|
86
86
|
readonly ruleTypeLabel: "Bundle members source";
|
|
87
87
|
readonly ruleTypeStatic: "Hand-picked products";
|
|
88
88
|
readonly ruleTypeDynamic: "Dynamic query (auto-resolves)";
|
|
89
|
+
readonly bundleKindLabel: "Bundle kind";
|
|
90
|
+
readonly bundleKindHint: "Special bundles show the 'Bundled' badge on product cards and update member product metadata. Brand bundles are discovery collections only.";
|
|
91
|
+
readonly bundleKindSpecial: "Special bundle";
|
|
92
|
+
readonly bundleKindBrand: "Brand collection";
|
|
93
|
+
readonly drawCountLabel: "Draw entries included";
|
|
94
|
+
readonly drawCountHint: "How many raffle entries the buyer receives for this prize-draw when purchasing the bundle.";
|
|
95
|
+
readonly drawCountPlaceholder: "e.g. 5";
|
|
89
96
|
readonly dynamic: {
|
|
90
97
|
readonly title: "Dynamic query rule";
|
|
91
98
|
readonly hint: "onProductStockChange resolves bundleProductIds; bundleQueryResolvedAt tracks the last refresh.";
|
|
@@ -96,6 +96,15 @@ export const BUNDLE_COPY = {
|
|
|
96
96
|
ruleTypeLabel: "Bundle members source",
|
|
97
97
|
ruleTypeStatic: "Hand-picked products",
|
|
98
98
|
ruleTypeDynamic: "Dynamic query (auto-resolves)",
|
|
99
|
+
// Bundle kind
|
|
100
|
+
bundleKindLabel: "Bundle kind",
|
|
101
|
+
bundleKindHint: "Special bundles show the 'Bundled' badge on product cards and update member product metadata. Brand bundles are discovery collections only.",
|
|
102
|
+
bundleKindSpecial: "Special bundle",
|
|
103
|
+
bundleKindBrand: "Brand collection",
|
|
104
|
+
// Prize-draw draw count
|
|
105
|
+
drawCountLabel: "Draw entries included",
|
|
106
|
+
drawCountHint: "How many raffle entries the buyer receives for this prize-draw when purchasing the bundle.",
|
|
107
|
+
drawCountPlaceholder: "e.g. 5",
|
|
99
108
|
dynamic: {
|
|
100
109
|
title: "Dynamic query rule",
|
|
101
110
|
hint: "onProductStockChange resolves bundleProductIds; bundleQueryResolvedAt tracks the last refresh.",
|
|
@@ -23,15 +23,16 @@ export declare const bundleQueryRuleSchema: z.ZodDiscriminatedUnion<"type", [z.Z
|
|
|
23
23
|
categorySlug: z.ZodOptional<z.ZodString>;
|
|
24
24
|
brandSlug: z.ZodOptional<z.ZodString>;
|
|
25
25
|
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
26
|
-
|
|
26
|
+
/** Eligible listing types for a dynamic bundle rule. */
|
|
27
|
+
listingType: z.ZodOptional<z.ZodEnum<["standard", "pre-order", "prize-draw"]>>;
|
|
27
28
|
}, "strip", z.ZodTypeAny, {
|
|
28
29
|
tags?: string[] | undefined;
|
|
29
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
30
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
30
31
|
categorySlug?: string | undefined;
|
|
31
32
|
brandSlug?: string | undefined;
|
|
32
33
|
}, {
|
|
33
34
|
tags?: string[] | undefined;
|
|
34
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
35
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
35
36
|
categorySlug?: string | undefined;
|
|
36
37
|
brandSlug?: string | undefined;
|
|
37
38
|
}>;
|
|
@@ -40,7 +41,7 @@ export declare const bundleQueryRuleSchema: z.ZodDiscriminatedUnion<"type", [z.Z
|
|
|
40
41
|
}, "strip", z.ZodTypeAny, {
|
|
41
42
|
filter: {
|
|
42
43
|
tags?: string[] | undefined;
|
|
43
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
44
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
44
45
|
categorySlug?: string | undefined;
|
|
45
46
|
brandSlug?: string | undefined;
|
|
46
47
|
};
|
|
@@ -50,7 +51,7 @@ export declare const bundleQueryRuleSchema: z.ZodDiscriminatedUnion<"type", [z.Z
|
|
|
50
51
|
}, {
|
|
51
52
|
filter: {
|
|
52
53
|
tags?: string[] | undefined;
|
|
53
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
54
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
54
55
|
categorySlug?: string | undefined;
|
|
55
56
|
brandSlug?: string | undefined;
|
|
56
57
|
};
|
|
@@ -75,6 +76,11 @@ export declare const bundleCreateSchema: z.ZodObject<{
|
|
|
75
76
|
name: z.ZodString;
|
|
76
77
|
slug: z.ZodOptional<z.ZodString>;
|
|
77
78
|
description: z.ZodOptional<z.ZodString>;
|
|
79
|
+
/**
|
|
80
|
+
* "special" — curated bundle; updates partOfBundleIds on member products.
|
|
81
|
+
* "brand" — brand discovery collection; does not touch product reverse pointers.
|
|
82
|
+
*/
|
|
83
|
+
bundleKind: z.ZodEnum<["special", "brand"]>;
|
|
78
84
|
bundlePriceInPaise: z.ZodNumber;
|
|
79
85
|
bundleQueryRule: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
80
86
|
type: z.ZodLiteral<"static">;
|
|
@@ -91,15 +97,16 @@ export declare const bundleCreateSchema: z.ZodObject<{
|
|
|
91
97
|
categorySlug: z.ZodOptional<z.ZodString>;
|
|
92
98
|
brandSlug: z.ZodOptional<z.ZodString>;
|
|
93
99
|
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
94
|
-
|
|
100
|
+
/** Eligible listing types for a dynamic bundle rule. */
|
|
101
|
+
listingType: z.ZodOptional<z.ZodEnum<["standard", "pre-order", "prize-draw"]>>;
|
|
95
102
|
}, "strip", z.ZodTypeAny, {
|
|
96
103
|
tags?: string[] | undefined;
|
|
97
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
104
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
98
105
|
categorySlug?: string | undefined;
|
|
99
106
|
brandSlug?: string | undefined;
|
|
100
107
|
}, {
|
|
101
108
|
tags?: string[] | undefined;
|
|
102
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
109
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
103
110
|
categorySlug?: string | undefined;
|
|
104
111
|
brandSlug?: string | undefined;
|
|
105
112
|
}>;
|
|
@@ -108,7 +115,7 @@ export declare const bundleCreateSchema: z.ZodObject<{
|
|
|
108
115
|
}, "strip", z.ZodTypeAny, {
|
|
109
116
|
filter: {
|
|
110
117
|
tags?: string[] | undefined;
|
|
111
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
118
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
112
119
|
categorySlug?: string | undefined;
|
|
113
120
|
brandSlug?: string | undefined;
|
|
114
121
|
};
|
|
@@ -118,7 +125,7 @@ export declare const bundleCreateSchema: z.ZodObject<{
|
|
|
118
125
|
}, {
|
|
119
126
|
filter: {
|
|
120
127
|
tags?: string[] | undefined;
|
|
121
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
128
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
122
129
|
categorySlug?: string | undefined;
|
|
123
130
|
brandSlug?: string | undefined;
|
|
124
131
|
};
|
|
@@ -127,6 +134,17 @@ export declare const bundleCreateSchema: z.ZodObject<{
|
|
|
127
134
|
orderBy?: "price-asc" | "price-desc" | "createdAt-desc" | undefined;
|
|
128
135
|
}>]>;
|
|
129
136
|
bundleProductIds: z.ZodArray<z.ZodString, "many">;
|
|
137
|
+
/** Richer per-member metadata (draw counts for prize-draws). */
|
|
138
|
+
bundleItemDetails: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
139
|
+
productId: z.ZodString;
|
|
140
|
+
drawCount: z.ZodOptional<z.ZodNumber>;
|
|
141
|
+
}, "strip", z.ZodTypeAny, {
|
|
142
|
+
productId: string;
|
|
143
|
+
drawCount?: number | undefined;
|
|
144
|
+
}, {
|
|
145
|
+
productId: string;
|
|
146
|
+
drawCount?: number | undefined;
|
|
147
|
+
}>, "many">>;
|
|
130
148
|
display: z.ZodOptional<z.ZodObject<{
|
|
131
149
|
coverImage: z.ZodOptional<z.ZodString>;
|
|
132
150
|
icon: z.ZodOptional<z.ZodString>;
|
|
@@ -144,6 +162,7 @@ export declare const bundleCreateSchema: z.ZodObject<{
|
|
|
144
162
|
}, "strip", z.ZodTypeAny, {
|
|
145
163
|
name: string;
|
|
146
164
|
bundleProductIds: string[];
|
|
165
|
+
bundleKind: "brand" | "special";
|
|
147
166
|
bundlePriceInPaise: number;
|
|
148
167
|
bundleQueryRule: {
|
|
149
168
|
type: "static";
|
|
@@ -151,7 +170,7 @@ export declare const bundleCreateSchema: z.ZodObject<{
|
|
|
151
170
|
} | {
|
|
152
171
|
filter: {
|
|
153
172
|
tags?: string[] | undefined;
|
|
154
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
173
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
155
174
|
categorySlug?: string | undefined;
|
|
156
175
|
brandSlug?: string | undefined;
|
|
157
176
|
};
|
|
@@ -167,9 +186,14 @@ export declare const bundleCreateSchema: z.ZodObject<{
|
|
|
167
186
|
isActive?: boolean | undefined;
|
|
168
187
|
description?: string | undefined;
|
|
169
188
|
slug?: string | undefined;
|
|
189
|
+
bundleItemDetails?: {
|
|
190
|
+
productId: string;
|
|
191
|
+
drawCount?: number | undefined;
|
|
192
|
+
}[] | undefined;
|
|
170
193
|
}, {
|
|
171
194
|
name: string;
|
|
172
195
|
bundleProductIds: string[];
|
|
196
|
+
bundleKind: "brand" | "special";
|
|
173
197
|
bundlePriceInPaise: number;
|
|
174
198
|
bundleQueryRule: {
|
|
175
199
|
type: "static";
|
|
@@ -177,7 +201,7 @@ export declare const bundleCreateSchema: z.ZodObject<{
|
|
|
177
201
|
} | {
|
|
178
202
|
filter: {
|
|
179
203
|
tags?: string[] | undefined;
|
|
180
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
204
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
181
205
|
categorySlug?: string | undefined;
|
|
182
206
|
brandSlug?: string | undefined;
|
|
183
207
|
};
|
|
@@ -193,10 +217,15 @@ export declare const bundleCreateSchema: z.ZodObject<{
|
|
|
193
217
|
isActive?: boolean | undefined;
|
|
194
218
|
description?: string | undefined;
|
|
195
219
|
slug?: string | undefined;
|
|
220
|
+
bundleItemDetails?: {
|
|
221
|
+
productId: string;
|
|
222
|
+
drawCount?: number | undefined;
|
|
223
|
+
}[] | undefined;
|
|
196
224
|
}>;
|
|
197
225
|
export declare const bundleUpdateSchema: z.ZodObject<{
|
|
198
226
|
name: z.ZodOptional<z.ZodString>;
|
|
199
227
|
description: z.ZodOptional<z.ZodString>;
|
|
228
|
+
bundleKind: z.ZodOptional<z.ZodEnum<["special", "brand"]>>;
|
|
200
229
|
bundlePriceInPaise: z.ZodOptional<z.ZodNumber>;
|
|
201
230
|
bundleQueryRule: z.ZodOptional<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
202
231
|
type: z.ZodLiteral<"static">;
|
|
@@ -213,15 +242,16 @@ export declare const bundleUpdateSchema: z.ZodObject<{
|
|
|
213
242
|
categorySlug: z.ZodOptional<z.ZodString>;
|
|
214
243
|
brandSlug: z.ZodOptional<z.ZodString>;
|
|
215
244
|
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
216
|
-
|
|
245
|
+
/** Eligible listing types for a dynamic bundle rule. */
|
|
246
|
+
listingType: z.ZodOptional<z.ZodEnum<["standard", "pre-order", "prize-draw"]>>;
|
|
217
247
|
}, "strip", z.ZodTypeAny, {
|
|
218
248
|
tags?: string[] | undefined;
|
|
219
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
249
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
220
250
|
categorySlug?: string | undefined;
|
|
221
251
|
brandSlug?: string | undefined;
|
|
222
252
|
}, {
|
|
223
253
|
tags?: string[] | undefined;
|
|
224
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
254
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
225
255
|
categorySlug?: string | undefined;
|
|
226
256
|
brandSlug?: string | undefined;
|
|
227
257
|
}>;
|
|
@@ -230,7 +260,7 @@ export declare const bundleUpdateSchema: z.ZodObject<{
|
|
|
230
260
|
}, "strip", z.ZodTypeAny, {
|
|
231
261
|
filter: {
|
|
232
262
|
tags?: string[] | undefined;
|
|
233
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
263
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
234
264
|
categorySlug?: string | undefined;
|
|
235
265
|
brandSlug?: string | undefined;
|
|
236
266
|
};
|
|
@@ -240,7 +270,7 @@ export declare const bundleUpdateSchema: z.ZodObject<{
|
|
|
240
270
|
}, {
|
|
241
271
|
filter: {
|
|
242
272
|
tags?: string[] | undefined;
|
|
243
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
273
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
244
274
|
categorySlug?: string | undefined;
|
|
245
275
|
brandSlug?: string | undefined;
|
|
246
276
|
};
|
|
@@ -249,6 +279,16 @@ export declare const bundleUpdateSchema: z.ZodObject<{
|
|
|
249
279
|
orderBy?: "price-asc" | "price-desc" | "createdAt-desc" | undefined;
|
|
250
280
|
}>]>>;
|
|
251
281
|
bundleProductIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
282
|
+
bundleItemDetails: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
283
|
+
productId: z.ZodString;
|
|
284
|
+
drawCount: z.ZodOptional<z.ZodNumber>;
|
|
285
|
+
}, "strip", z.ZodTypeAny, {
|
|
286
|
+
productId: string;
|
|
287
|
+
drawCount?: number | undefined;
|
|
288
|
+
}, {
|
|
289
|
+
productId: string;
|
|
290
|
+
drawCount?: number | undefined;
|
|
291
|
+
}>, "many">>;
|
|
252
292
|
display: z.ZodOptional<z.ZodObject<{
|
|
253
293
|
coverImage: z.ZodOptional<z.ZodString>;
|
|
254
294
|
icon: z.ZodOptional<z.ZodString>;
|
|
@@ -273,6 +313,7 @@ export declare const bundleUpdateSchema: z.ZodObject<{
|
|
|
273
313
|
isActive?: boolean | undefined;
|
|
274
314
|
description?: string | undefined;
|
|
275
315
|
bundleProductIds?: string[] | undefined;
|
|
316
|
+
bundleKind?: "brand" | "special" | undefined;
|
|
276
317
|
bundlePriceInPaise?: number | undefined;
|
|
277
318
|
bundleQueryRule?: {
|
|
278
319
|
type: "static";
|
|
@@ -280,7 +321,7 @@ export declare const bundleUpdateSchema: z.ZodObject<{
|
|
|
280
321
|
} | {
|
|
281
322
|
filter: {
|
|
282
323
|
tags?: string[] | undefined;
|
|
283
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
324
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
284
325
|
categorySlug?: string | undefined;
|
|
285
326
|
brandSlug?: string | undefined;
|
|
286
327
|
};
|
|
@@ -288,6 +329,10 @@ export declare const bundleUpdateSchema: z.ZodObject<{
|
|
|
288
329
|
limit: number;
|
|
289
330
|
orderBy?: "price-asc" | "price-desc" | "createdAt-desc" | undefined;
|
|
290
331
|
} | undefined;
|
|
332
|
+
bundleItemDetails?: {
|
|
333
|
+
productId: string;
|
|
334
|
+
drawCount?: number | undefined;
|
|
335
|
+
}[] | undefined;
|
|
291
336
|
}, {
|
|
292
337
|
name?: string | undefined;
|
|
293
338
|
display?: {
|
|
@@ -298,6 +343,7 @@ export declare const bundleUpdateSchema: z.ZodObject<{
|
|
|
298
343
|
isActive?: boolean | undefined;
|
|
299
344
|
description?: string | undefined;
|
|
300
345
|
bundleProductIds?: string[] | undefined;
|
|
346
|
+
bundleKind?: "brand" | "special" | undefined;
|
|
301
347
|
bundlePriceInPaise?: number | undefined;
|
|
302
348
|
bundleQueryRule?: {
|
|
303
349
|
type: "static";
|
|
@@ -305,7 +351,7 @@ export declare const bundleUpdateSchema: z.ZodObject<{
|
|
|
305
351
|
} | {
|
|
306
352
|
filter: {
|
|
307
353
|
tags?: string[] | undefined;
|
|
308
|
-
listingType?: "standard" | "pre-order" | undefined;
|
|
354
|
+
listingType?: "standard" | "pre-order" | "prize-draw" | undefined;
|
|
309
355
|
categorySlug?: string | undefined;
|
|
310
356
|
brandSlug?: string | undefined;
|
|
311
357
|
};
|
|
@@ -313,6 +359,10 @@ export declare const bundleUpdateSchema: z.ZodObject<{
|
|
|
313
359
|
limit: number;
|
|
314
360
|
orderBy?: "price-asc" | "price-desc" | "createdAt-desc" | undefined;
|
|
315
361
|
} | undefined;
|
|
362
|
+
bundleItemDetails?: {
|
|
363
|
+
productId: string;
|
|
364
|
+
drawCount?: number | undefined;
|
|
365
|
+
}[] | undefined;
|
|
316
366
|
}>;
|
|
317
367
|
export type BundleCreateBody = z.infer<typeof bundleCreateSchema>;
|
|
318
368
|
export type BundleUpdateBody = z.infer<typeof bundleUpdateSchema>;
|