@mohasinac/appkit 3.2.20 → 3.3.0
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/checkout/actions.d.ts +2 -0
- package/dist/_internal/server/features/checkout/actions.js +239 -190
- package/dist/_internal/server/functions/scheduled.d.ts +2 -1
- package/dist/_internal/server/functions/scheduled.js +9 -1
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +8 -11
- package/dist/_internal/server/jobs/core/emiInstallmentReminder.d.ts +8 -0
- package/dist/_internal/server/jobs/core/emiInstallmentReminder.js +78 -0
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.d.ts +2 -2
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +15 -10
- package/dist/_internal/server/jobs/handlers/emiInstallmentReminder.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/emiInstallmentReminder.js +2 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
- package/dist/_internal/server/jobs/handlers/index.js +2 -0
- package/dist/_internal/server/providers/index.d.ts +4 -4
- package/dist/_internal/server/providers/index.js +4 -4
- package/dist/_internal/server/providers/payment/razorpay-mock.d.ts +3 -2
- package/dist/_internal/server/providers/payment/razorpay-mock.js +3 -1
- package/dist/_internal/server/providers/resolve.d.ts +10 -13
- package/dist/_internal/server/providers/resolve.js +9 -15
- package/dist/_internal/shared/actions/action-registry.js +28 -0
- package/dist/_internal/shared/checkout/rules/_defaults.js +1 -0
- package/dist/_internal/shared/checkout/rules/_registry.js +4 -0
- package/dist/_internal/shared/checkout/rules/art.rule.d.ts +9 -0
- package/dist/_internal/shared/checkout/rules/art.rule.js +5 -0
- package/dist/_internal/shared/checkout/rules/auction.rule.js +1 -0
- package/dist/_internal/shared/checkout/rules/classified.rule.js +1 -0
- package/dist/_internal/shared/checkout/rules/index.d.ts +2 -0
- package/dist/_internal/shared/checkout/rules/index.js +2 -0
- package/dist/_internal/shared/checkout/rules/stickers.rule.d.ts +9 -0
- package/dist/_internal/shared/checkout/rules/stickers.rule.js +5 -0
- package/dist/_internal/shared/checkout/rules/types.d.ts +6 -0
- package/dist/_internal/shared/features/checkout/config.d.ts +16 -1
- package/dist/_internal/shared/features/checkout/config.js +16 -1
- package/dist/_internal/shared/features/emi/schedule.d.ts +63 -0
- package/dist/_internal/shared/features/emi/schedule.js +62 -0
- package/dist/_internal/shared/fees/calculator.d.ts +53 -0
- package/dist/_internal/shared/fees/calculator.js +40 -0
- package/dist/_internal/shared/listing-types/_registry.d.ts +22 -66
- package/dist/_internal/shared/listing-types/_registry.js +19 -2
- package/dist/_internal/shared/listing-types/art/config.d.ts +15 -0
- package/dist/_internal/shared/listing-types/art/config.js +14 -0
- package/dist/_internal/shared/listing-types/art/ctas.d.ts +1 -0
- package/dist/_internal/shared/listing-types/art/ctas.js +3 -0
- package/dist/_internal/shared/listing-types/art/og.d.ts +1 -0
- package/dist/_internal/shared/listing-types/art/og.js +1 -0
- package/dist/_internal/shared/listing-types/art/schema.d.ts +2 -0
- package/dist/_internal/shared/listing-types/art/schema.js +3 -0
- package/dist/_internal/shared/listing-types/art/seed-factory.d.ts +1 -0
- package/dist/_internal/shared/listing-types/art/seed-factory.js +1 -0
- package/dist/_internal/shared/listing-types/auction/config.d.ts +8 -0
- package/dist/_internal/shared/listing-types/auction/config.js +6 -0
- package/dist/_internal/shared/listing-types/capabilities.js +17 -0
- package/dist/_internal/shared/listing-types/classified/config.d.ts +8 -0
- package/dist/_internal/shared/listing-types/classified/config.js +6 -0
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +8 -0
- package/dist/_internal/shared/listing-types/digital-code/config.js +6 -0
- package/dist/_internal/shared/listing-types/live/config.d.ts +8 -0
- package/dist/_internal/shared/listing-types/live/config.js +6 -0
- package/dist/_internal/shared/listing-types/pre-order/config.d.ts +8 -0
- package/dist/_internal/shared/listing-types/pre-order/config.js +6 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +8 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.js +6 -0
- package/dist/_internal/shared/listing-types/standard/config.d.ts +8 -0
- package/dist/_internal/shared/listing-types/standard/config.js +6 -0
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +15 -0
- package/dist/_internal/shared/listing-types/stickers/config.js +14 -0
- package/dist/_internal/shared/listing-types/stickers/ctas.d.ts +1 -0
- package/dist/_internal/shared/listing-types/stickers/ctas.js +3 -0
- package/dist/_internal/shared/listing-types/stickers/og.d.ts +1 -0
- package/dist/_internal/shared/listing-types/stickers/og.js +1 -0
- package/dist/_internal/shared/listing-types/stickers/schema.d.ts +2 -0
- package/dist/_internal/shared/listing-types/stickers/schema.js +3 -0
- package/dist/_internal/shared/listing-types/stickers/seed-factory.d.ts +1 -0
- package/dist/_internal/shared/listing-types/stickers/seed-factory.js +1 -0
- package/dist/client.d.ts +7 -2
- package/dist/client.js +4 -2
- package/dist/constants/field-names.d.ts +2 -6
- package/dist/constants/field-names.js +2 -6
- package/dist/contracts/index.d.ts +4 -2
- package/dist/contracts/index.js +6 -0
- package/dist/contracts/payment.d.ts +14 -9
- package/dist/contracts/payment.js +11 -1
- package/dist/contracts/shipping.d.ts +14 -9
- package/dist/contracts/shipping.js +11 -1
- package/dist/features/about/components/PublicProfileView.js +3 -6
- package/dist/features/admin/components/AdminAddressBookView.d.ts +11 -0
- package/dist/features/admin/components/AdminAddressBookView.js +30 -0
- package/dist/features/admin/components/AdminArtView.d.ts +3 -0
- package/dist/features/admin/components/AdminArtView.js +45 -0
- package/dist/features/admin/components/AdminSiteConfigGuideView.js +1 -1
- package/dist/features/admin/components/AdminSiteSettingsView.js +14 -9
- package/dist/features/admin/components/AdminStickersView.d.ts +3 -0
- package/dist/features/admin/components/AdminStickersView.js +45 -0
- package/dist/features/admin/components/index.d.ts +6 -0
- package/dist/features/admin/components/index.js +4 -0
- package/dist/features/admin/schemas/firestore.d.ts +19 -11
- package/dist/features/admin/schemas/firestore.js +12 -2
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +3 -2
- package/dist/features/auth/hooks/useAuth.js +35 -9
- package/dist/features/auth/schemas/firestore.d.ts +2 -6
- package/dist/features/cart/schemas/firestore.d.ts +3 -2
- package/dist/features/consultation/schemas/index.d.ts +2 -2
- package/dist/features/loyalty/schemas/index.d.ts +6 -6
- package/dist/features/orders/repository/orders.repository.d.ts +20 -2
- package/dist/features/orders/repository/orders.repository.js +34 -5
- package/dist/features/orders/schemas/firestore.d.ts +33 -7
- package/dist/features/orders/schemas/firestore.js +1 -1
- package/dist/features/orders/schemas/index.d.ts +176 -31
- package/dist/features/orders/schemas/index.js +20 -6
- package/dist/features/orders/types/index.d.ts +3 -3
- package/dist/features/payments/repository/payout.repository.js +2 -2
- package/dist/features/payments/schemas/firestore.d.ts +3 -3
- package/dist/features/payments/schemas/firestore.js +2 -2
- package/dist/features/payments/schemas/index.d.ts +5 -5
- package/dist/features/payments/schemas/index.js +2 -2
- package/dist/features/products/api/[id]/route.js +4 -1
- package/dist/features/products/api/route.js +4 -1
- package/dist/features/products/components/CompareOverlay.js +7 -9
- package/dist/features/products/components/ProductDetailPageView.d.ts +3 -1
- package/dist/features/products/components/ProductDetailPageView.js +2 -2
- package/dist/features/products/components/ProductForm.js +18 -7
- package/dist/features/products/components/ProductGrid.js +7 -12
- package/dist/features/products/components/ShowGroupSection.js +3 -5
- package/dist/features/products/components/SublistingCarouselSection.js +3 -6
- package/dist/features/products/constants/listing-tabs.d.ts +32 -0
- package/dist/features/products/constants/listing-tabs.js +8 -0
- package/dist/features/products/index.d.ts +1 -1
- package/dist/features/products/index.js +3 -1
- package/dist/features/products/schemas/firestore.d.ts +20 -1
- package/dist/features/products/schemas/firestore.js +2 -0
- package/dist/features/products/schemas/index.d.ts +48 -0
- package/dist/features/products/schemas/index.js +9 -0
- package/dist/features/products/schemas/product-features.d.ts +1 -1
- package/dist/features/products/types/index.d.ts +5 -3
- package/dist/features/products/utils/listing-type.d.ts +6 -0
- package/dist/features/products/utils/listing-type.js +3 -0
- package/dist/features/reviews/api/[id]/route.js +5 -4
- package/dist/features/seller/actions/seller-actions.d.ts +29 -14
- package/dist/features/seller/actions/seller-actions.js +101 -27
- package/dist/features/seller/components/SellerArtView.d.ts +7 -0
- package/dist/features/seller/components/SellerArtView.js +114 -0
- package/dist/features/seller/components/SellerOrdersView.js +38 -1
- package/dist/features/seller/components/SellerProductShell.d.ts +5 -1
- package/dist/features/seller/components/SellerProductShell.js +69 -59
- package/dist/features/seller/components/SellerShippingView.js +6 -25
- package/dist/features/seller/components/SellerStickersView.d.ts +7 -0
- package/dist/features/seller/components/SellerStickersView.js +114 -0
- package/dist/features/seller/components/index.d.ts +4 -0
- package/dist/features/seller/components/index.js +2 -0
- package/dist/features/seller/messages/en.json +1 -1
- package/dist/features/seller/schemas/index.d.ts +7 -7
- package/dist/features/seller/schemas/index.js +1 -1
- package/dist/features/seller/types/index.d.ts +1 -1
- package/dist/features/stores/components/StoreDetailLayoutView.js +18 -2
- package/dist/features/stores/schemas/firestore.d.ts +7 -1
- package/dist/features/stores/schemas/index.d.ts +19 -16
- package/dist/features/stores/schemas/index.js +1 -1
- package/dist/index.d.ts +21 -36
- package/dist/index.js +27 -39
- package/dist/next/routing/route-map.d.ts +22 -0
- package/dist/next/routing/route-map.js +10 -0
- package/dist/providers/payment-manual/index.d.ts +40 -0
- package/dist/providers/payment-manual/index.js +91 -0
- package/dist/providers/payment-razorpay/index.d.ts +4 -2
- package/dist/providers/payment-razorpay/index.js +4 -1
- package/dist/providers/shipping-manual/index.d.ts +22 -0
- package/dist/providers/shipping-manual/index.js +47 -0
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +5 -3
- package/dist/schemas/registry.d.ts +129 -70
- package/dist/schemas/registry.js +0 -4
- package/dist/security/pii-encrypt.js +0 -7
- package/dist/security/pii-redact.js +0 -1
- package/dist/seed/conversations-seed-data.js +2 -2
- package/dist/seed/faq-seed-data.js +7 -7
- package/dist/seed/grouped-listings-seed-data.d.ts +2 -0
- package/dist/seed/index.d.ts +2 -0
- package/dist/seed/index.js +2 -0
- package/dist/seed/manifest.js +20 -16
- package/dist/seed/payouts-seed-data.js +5 -5
- package/dist/seed/products-art-seed-data.d.ts +11 -0
- package/dist/seed/products-art-seed-data.js +125 -0
- package/dist/seed/products-preorders-seed-data.d.ts +2 -0
- package/dist/seed/products-stickers-seed-data.d.ts +11 -0
- package/dist/seed/products-stickers-seed-data.js +125 -0
- package/dist/seed/site-settings-seed-data.js +13 -4
- package/dist/seed/stores-seed-data.js +11 -11
- package/dist/server.d.ts +7 -15
- package/dist/server.js +17 -42
- package/package.json +1 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EMI (installment) eligibility + schedule computation — pure functions,
|
|
3
|
+
* no I/O. Consumed by checkout (buyer-facing quote + order creation) and by
|
|
4
|
+
* the seller/admin installment-collection UI (schedule display).
|
|
5
|
+
*
|
|
6
|
+
* Eligibility: a per-seller checkout group qualifies for EMI when the
|
|
7
|
+
* site-wide flag, the seller's own opt-in, AND the subtotal threshold are
|
|
8
|
+
* all satisfied — matching the existing COD deposit pattern of gating on
|
|
9
|
+
* `siteSettings.payment.codEnabled`.
|
|
10
|
+
*
|
|
11
|
+
* Schedule: the buyer pays `tokenPercent`% up front (the "token"), then the
|
|
12
|
+
* remaining principal plus a surcharge (the buyer's cost for spreading
|
|
13
|
+
* payment across `tenureMonths`, split between platform and seller per
|
|
14
|
+
* `surchargeSellerSharePercent`) across equal monthly installments, each
|
|
15
|
+
* due on `billingDay` (1–10) of the month, starting the month after
|
|
16
|
+
* purchase. All money amounts are in paise (integer).
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* `settings.enabled` is the site-wide toggle (`siteSettings.emi.enabled`).
|
|
20
|
+
* `sellerEmiEnabled` is the seller's own opt-in (`StoreDocument.emiEnabled`).
|
|
21
|
+
* Both must be true, in addition to the subtotal threshold.
|
|
22
|
+
*/
|
|
23
|
+
export function checkEmiEligibility(sellerSubtotal, sellerEmiEnabled, settings) {
|
|
24
|
+
if (!settings.enabled)
|
|
25
|
+
return { eligible: false, reason: "site_disabled" };
|
|
26
|
+
if (!sellerEmiEnabled)
|
|
27
|
+
return { eligible: false, reason: "seller_disabled" };
|
|
28
|
+
if (sellerSubtotal <= settings.minOrderValueInPaise)
|
|
29
|
+
return { eligible: false, reason: "below_minimum" };
|
|
30
|
+
return { eligible: true };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* `purchaseDate` defaults to now; the first installment always falls in the
|
|
34
|
+
* calendar month AFTER purchase, regardless of which day of the current
|
|
35
|
+
* month the purchase happens on.
|
|
36
|
+
*/
|
|
37
|
+
export function computeEmiSchedule(sellerSubtotal, tenureMonths, settings, purchaseDate = new Date()) {
|
|
38
|
+
const tokenAmount = Math.round(sellerSubtotal * (settings.tokenPercent / 100));
|
|
39
|
+
const principalRemaining = sellerSubtotal - tokenAmount;
|
|
40
|
+
const surchargeAmount = Math.round(principalRemaining * (settings.surchargePercentPerMonth / 100) * tenureMonths);
|
|
41
|
+
const surchargeSellerShare = Math.round(surchargeAmount * (settings.surchargeSellerSharePercent / 100));
|
|
42
|
+
const surchargePlatformShare = surchargeAmount - surchargeSellerShare;
|
|
43
|
+
const totalToInstall = principalRemaining + surchargeAmount;
|
|
44
|
+
const baseInstallment = Math.floor(totalToInstall / tenureMonths);
|
|
45
|
+
const remainder = totalToInstall - baseInstallment * tenureMonths;
|
|
46
|
+
const billingDay = Math.min(Math.max(settings.billingDay, 1), 10);
|
|
47
|
+
const installments = [];
|
|
48
|
+
for (let i = 1; i <= tenureMonths; i++) {
|
|
49
|
+
const dueDate = new Date(Date.UTC(purchaseDate.getUTCFullYear(), purchaseDate.getUTCMonth() + i, billingDay));
|
|
50
|
+
// Last installment absorbs the rounding remainder so the sum is exact.
|
|
51
|
+
const amount = i === tenureMonths ? baseInstallment + remainder : baseInstallment;
|
|
52
|
+
installments.push({ index: i, dueDate, amount });
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
tokenAmount,
|
|
56
|
+
surchargeAmount,
|
|
57
|
+
surchargeSellerShare,
|
|
58
|
+
surchargePlatformShare,
|
|
59
|
+
installments,
|
|
60
|
+
remainingBalance: totalToInstall,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared fee calculator — single source of truth for platform commission,
|
|
3
|
+
* gateway fee, GST, and COD handling fee math. Replaces the ~5 duplicated
|
|
4
|
+
* (and in the payout case, inconsistent) formulas that used to live
|
|
5
|
+
* separately in checkout actions, refund actions, and the two payout
|
|
6
|
+
* eligibility jobs.
|
|
7
|
+
*
|
|
8
|
+
* Two distinct fee shapes:
|
|
9
|
+
* - `computeCheckoutFees` — what the BUYER pays on top of the subtotal
|
|
10
|
+
* (platform fee + GST on that fee). The gateway fee is absorbed by the
|
|
11
|
+
* platform, never passed through to the buyer.
|
|
12
|
+
* - `computePayoutDeduction` — what's deducted from the SELLER's payout
|
|
13
|
+
* (platform fee + gateway fee + GST on the platform fee).
|
|
14
|
+
*
|
|
15
|
+
* All money amounts are in paise (integer).
|
|
16
|
+
*/
|
|
17
|
+
export interface FeeCommissionRates {
|
|
18
|
+
platformFeePercent: number;
|
|
19
|
+
gstPercent: number;
|
|
20
|
+
/** Rupee floor (not paise) — matches the existing `minimumTransactionFee` doc convention. */
|
|
21
|
+
minimumTransactionFee?: number;
|
|
22
|
+
gatewayFeePercent?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface CheckoutFees {
|
|
25
|
+
/** Platform commission in paise. */
|
|
26
|
+
platformFee: number;
|
|
27
|
+
/** GST on the platform fee, in paise. */
|
|
28
|
+
gstOnFee: number;
|
|
29
|
+
/** platformFee + gstOnFee, floored at minimumTransactionFee. */
|
|
30
|
+
totalFee: number;
|
|
31
|
+
}
|
|
32
|
+
export declare function computeCheckoutFees(subtotal: number, commissions: FeeCommissionRates): CheckoutFees;
|
|
33
|
+
export interface PayoutDeduction {
|
|
34
|
+
/** Platform commission in paise. */
|
|
35
|
+
platformFee: number;
|
|
36
|
+
/** Payment gateway cost, absorbed by the platform from the seller's share, in paise. */
|
|
37
|
+
gatewayFee: number;
|
|
38
|
+
/** GST on the platform fee, in paise. */
|
|
39
|
+
gstOnFee: number;
|
|
40
|
+
/** platformFee + gatewayFee + gstOnFee. */
|
|
41
|
+
totalDeduction: number;
|
|
42
|
+
/** grossAmount - totalDeduction, floored at 0. */
|
|
43
|
+
netAmount: number;
|
|
44
|
+
}
|
|
45
|
+
export declare function computePayoutDeduction(grossAmount: number, commissions: FeeCommissionRates): PayoutDeduction;
|
|
46
|
+
export interface CodHandlingFeeRates {
|
|
47
|
+
/** Optional so existing `siteSettings` documents saved before this field existed don't produce NaN — falls back to ₹200 (20000 paise). */
|
|
48
|
+
codHandlingFeeMinInPaise?: number;
|
|
49
|
+
/** Optional for the same reason — falls back to 10%. */
|
|
50
|
+
codHandlingFeePercent?: number;
|
|
51
|
+
}
|
|
52
|
+
/** COD handling fee charged to the buyer: max(fixed floor, subtotal × percent). */
|
|
53
|
+
export declare function computeCodHandlingFee(subtotal: number, rates: CodHandlingFeeRates): number;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared fee calculator — single source of truth for platform commission,
|
|
3
|
+
* gateway fee, GST, and COD handling fee math. Replaces the ~5 duplicated
|
|
4
|
+
* (and in the payout case, inconsistent) formulas that used to live
|
|
5
|
+
* separately in checkout actions, refund actions, and the two payout
|
|
6
|
+
* eligibility jobs.
|
|
7
|
+
*
|
|
8
|
+
* Two distinct fee shapes:
|
|
9
|
+
* - `computeCheckoutFees` — what the BUYER pays on top of the subtotal
|
|
10
|
+
* (platform fee + GST on that fee). The gateway fee is absorbed by the
|
|
11
|
+
* platform, never passed through to the buyer.
|
|
12
|
+
* - `computePayoutDeduction` — what's deducted from the SELLER's payout
|
|
13
|
+
* (platform fee + gateway fee + GST on the platform fee).
|
|
14
|
+
*
|
|
15
|
+
* All money amounts are in paise (integer).
|
|
16
|
+
*/
|
|
17
|
+
export function computeCheckoutFees(subtotal, commissions) {
|
|
18
|
+
const platformFee = Math.round(subtotal * (commissions.platformFeePercent / 100));
|
|
19
|
+
const gstOnFee = Math.round(platformFee * (commissions.gstPercent / 100));
|
|
20
|
+
const minimumTransactionFeeInPaise = Math.round((commissions.minimumTransactionFee ?? 0) * 100);
|
|
21
|
+
const totalFee = Math.max(platformFee + gstOnFee, minimumTransactionFeeInPaise);
|
|
22
|
+
return { platformFee, gstOnFee, totalFee };
|
|
23
|
+
}
|
|
24
|
+
export function computePayoutDeduction(grossAmount, commissions) {
|
|
25
|
+
const platformFee = Math.round(grossAmount * (commissions.platformFeePercent / 100));
|
|
26
|
+
const gatewayFee = Math.round(grossAmount * ((commissions.gatewayFeePercent ?? 0) / 100));
|
|
27
|
+
const gstOnFee = Math.round(platformFee * (commissions.gstPercent / 100));
|
|
28
|
+
const totalDeduction = platformFee + gatewayFee + gstOnFee;
|
|
29
|
+
const netAmount = Math.max(0, grossAmount - totalDeduction);
|
|
30
|
+
return { platformFee, gatewayFee, gstOnFee, totalDeduction, netAmount };
|
|
31
|
+
}
|
|
32
|
+
const DEFAULT_COD_HANDLING_FEE_MIN_IN_PAISE = 20000;
|
|
33
|
+
const DEFAULT_COD_HANDLING_FEE_PERCENT = 10;
|
|
34
|
+
/** COD handling fee charged to the buyer: max(fixed floor, subtotal × percent). */
|
|
35
|
+
export function computeCodHandlingFee(subtotal, rates) {
|
|
36
|
+
const minInPaise = rates.codHandlingFeeMinInPaise ?? DEFAULT_COD_HANDLING_FEE_MIN_IN_PAISE;
|
|
37
|
+
const percent = rates.codHandlingFeePercent ?? DEFAULT_COD_HANDLING_FEE_PERCENT;
|
|
38
|
+
const percentFee = Math.round(subtotal * (percent / 100));
|
|
39
|
+
return Math.max(minInPaise, percentFee);
|
|
40
|
+
}
|
|
@@ -14,71 +14,27 @@ export interface ListingTypePlugin {
|
|
|
14
14
|
listingType: ListingType;
|
|
15
15
|
slugPrefix: string;
|
|
16
16
|
cartLine: "single-product" | "blocked" | "bundle-expand";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
};
|
|
24
|
-
readonly auction: {
|
|
25
|
-
listingType: "auction";
|
|
26
|
-
slugPrefix: string;
|
|
27
|
-
cartLine: "blocked";
|
|
28
|
-
};
|
|
29
|
-
readonly "pre-order": {
|
|
30
|
-
listingType: "pre-order";
|
|
31
|
-
slugPrefix: string;
|
|
32
|
-
cartLine: "single-product";
|
|
33
|
-
};
|
|
34
|
-
readonly "prize-draw": {
|
|
35
|
-
listingType: "prize-draw";
|
|
36
|
-
slugPrefix: string;
|
|
37
|
-
cartLine: "single-product";
|
|
38
|
-
};
|
|
39
|
-
readonly classified: {
|
|
40
|
-
listingType: "classified";
|
|
41
|
-
slugPrefix: string;
|
|
42
|
-
cartLine: "blocked";
|
|
17
|
+
/** Public detail-page href builder — replaces the ad-hoc per-type href pickers duplicated across card/link components. */
|
|
18
|
+
detailRoute: (idOrSlug: string) => string;
|
|
19
|
+
/** Card-grid badge shown for time-sensitive/action-required types (auction/pre-order); undefined = no badge. */
|
|
20
|
+
badge?: {
|
|
21
|
+
label: string;
|
|
22
|
+
className: string;
|
|
43
23
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
listingType: "auction";
|
|
61
|
-
slugPrefix: string;
|
|
62
|
-
cartLine: "blocked";
|
|
63
|
-
} | {
|
|
64
|
-
listingType: "pre-order";
|
|
65
|
-
slugPrefix: string;
|
|
66
|
-
cartLine: "single-product";
|
|
67
|
-
} | {
|
|
68
|
-
listingType: "prize-draw";
|
|
69
|
-
slugPrefix: string;
|
|
70
|
-
cartLine: "single-product";
|
|
71
|
-
} | {
|
|
72
|
-
listingType: "classified";
|
|
73
|
-
slugPrefix: string;
|
|
74
|
-
cartLine: "blocked";
|
|
75
|
-
} | {
|
|
76
|
-
listingType: "digital-code";
|
|
77
|
-
slugPrefix: string;
|
|
78
|
-
cartLine: "single-product";
|
|
79
|
-
} | {
|
|
80
|
-
listingType: "live";
|
|
81
|
-
slugPrefix: string;
|
|
82
|
-
cartLine: "single-product";
|
|
83
|
-
};
|
|
24
|
+
/** Seller create/edit form price-field label. */
|
|
25
|
+
priceLabel: string;
|
|
26
|
+
/** Human label for the listing type (breadcrumbs/titles). */
|
|
27
|
+
typeLabel: string;
|
|
28
|
+
/** Whether the seller create/edit form shows a Stock Quantity field. */
|
|
29
|
+
showsStockQuantity: boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare const LISTING_TYPE_REGISTRY: Record<ListingType, ListingTypePlugin>;
|
|
32
|
+
export declare function pluginFor(type: ListingType): ListingTypePlugin;
|
|
33
|
+
/**
|
|
34
|
+
* Infer a listing type from a product slug/id by matching its registered
|
|
35
|
+
* `slugPrefix` — replaces ad-hoc `id.startsWith("auction-")` chains in
|
|
36
|
+
* contexts (guest carts, unauthenticated payloads) that don't carry an
|
|
37
|
+
* explicit `listingType` field. Falls back to "standard" when no prefix matches.
|
|
38
|
+
*/
|
|
39
|
+
export declare function detectListingTypeFromSlug(slug: string): ListingType;
|
|
84
40
|
export { LISTING_TYPE_CAPABILITIES };
|
|
@@ -16,9 +16,13 @@ import * as prizeDraw from "./prize-draw/config";
|
|
|
16
16
|
import * as classified from "./classified/config";
|
|
17
17
|
import * as digitalCode from "./digital-code/config";
|
|
18
18
|
import * as live from "./live/config";
|
|
19
|
+
// EMI/art-stickers session — printed-only physical-goods types.
|
|
20
|
+
import * as art from "./art/config";
|
|
21
|
+
import * as stickers from "./stickers/config";
|
|
19
22
|
import { LISTING_TYPE_CAPABILITIES } from "./capabilities";
|
|
20
23
|
// SB-UNI-D — bundle entry removed; bundles are a categoryType, not a listingType.
|
|
21
24
|
// SB-UNI-F 2026-05-13 — classified / digital-code / live added.
|
|
25
|
+
// EMI/art-stickers session — art / stickers added.
|
|
22
26
|
export const LISTING_TYPE_REGISTRY = {
|
|
23
27
|
standard: standard.config,
|
|
24
28
|
auction: auction.config,
|
|
@@ -27,12 +31,25 @@ export const LISTING_TYPE_REGISTRY = {
|
|
|
27
31
|
classified: classified.config,
|
|
28
32
|
"digital-code": digitalCode.config,
|
|
29
33
|
live: live.config,
|
|
34
|
+
art: art.config,
|
|
35
|
+
stickers: stickers.config,
|
|
30
36
|
};
|
|
31
|
-
// Returns undefined for "bundle" — bundles are CategoryDocument, not in this registry.
|
|
32
|
-
// Callers must null-check: `pluginFor(lt) ?? fallbackBehavior`.
|
|
33
37
|
export function pluginFor(type) {
|
|
34
38
|
return LISTING_TYPE_REGISTRY[type];
|
|
35
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Infer a listing type from a product slug/id by matching its registered
|
|
42
|
+
* `slugPrefix` — replaces ad-hoc `id.startsWith("auction-")` chains in
|
|
43
|
+
* contexts (guest carts, unauthenticated payloads) that don't carry an
|
|
44
|
+
* explicit `listingType` field. Falls back to "standard" when no prefix matches.
|
|
45
|
+
*/
|
|
46
|
+
export function detectListingTypeFromSlug(slug) {
|
|
47
|
+
for (const plugin of Object.values(LISTING_TYPE_REGISTRY)) {
|
|
48
|
+
if (plugin.slugPrefix && slug.startsWith(plugin.slugPrefix))
|
|
49
|
+
return plugin.listingType;
|
|
50
|
+
}
|
|
51
|
+
return "standard";
|
|
52
|
+
}
|
|
36
53
|
// Re-export the capability map so consumers can pull both surfaces from
|
|
37
54
|
// the same module path.
|
|
38
55
|
export { LISTING_TYPE_CAPABILITIES };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const LISTING_TYPE: "art";
|
|
2
|
+
export declare const capability: import("../capabilities").ListingTypeCapability;
|
|
3
|
+
export declare const config: {
|
|
4
|
+
listingType: "art";
|
|
5
|
+
slugPrefix: string;
|
|
6
|
+
cartLine: "single-product";
|
|
7
|
+
detailRoute: (idOrSlug: string) => string;
|
|
8
|
+
badge: {
|
|
9
|
+
label: string;
|
|
10
|
+
className: string;
|
|
11
|
+
} | undefined;
|
|
12
|
+
priceLabel: string;
|
|
13
|
+
typeLabel: string;
|
|
14
|
+
showsStockQuantity: boolean;
|
|
15
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
|
|
2
|
+
import { ROUTES } from "../../../../next/routing/route-map";
|
|
3
|
+
export const LISTING_TYPE = "art";
|
|
4
|
+
export const capability = LISTING_TYPE_CAPABILITIES.art;
|
|
5
|
+
export const config = {
|
|
6
|
+
listingType: LISTING_TYPE,
|
|
7
|
+
slugPrefix: "art-",
|
|
8
|
+
cartLine: "single-product",
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(idOrSlug)),
|
|
10
|
+
badge: undefined,
|
|
11
|
+
priceLabel: "Price (₹)",
|
|
12
|
+
typeLabel: "Art Print",
|
|
13
|
+
showsStockQuantity: true,
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ctas: readonly string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,4 +4,12 @@ export declare const config: {
|
|
|
4
4
|
listingType: "auction";
|
|
5
5
|
slugPrefix: string;
|
|
6
6
|
cartLine: "blocked";
|
|
7
|
+
detailRoute: (idOrSlug: string) => string;
|
|
8
|
+
badge: {
|
|
9
|
+
label: string;
|
|
10
|
+
className: string;
|
|
11
|
+
};
|
|
12
|
+
priceLabel: string;
|
|
13
|
+
typeLabel: string;
|
|
14
|
+
showsStockQuantity: boolean;
|
|
7
15
|
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
|
|
2
|
+
import { ROUTES } from "../../../../next/routing/route-map";
|
|
2
3
|
export const LISTING_TYPE = "auction";
|
|
3
4
|
export const capability = LISTING_TYPE_CAPABILITIES.auction;
|
|
4
5
|
export const config = {
|
|
5
6
|
listingType: LISTING_TYPE,
|
|
6
7
|
slugPrefix: "auction-",
|
|
7
8
|
cartLine: "blocked",
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.AUCTION_DETAIL(idOrSlug)),
|
|
10
|
+
badge: { label: "Auction", className: "bg-warning-surface text-white" },
|
|
11
|
+
priceLabel: "Suggested Retail Price (₹)",
|
|
12
|
+
typeLabel: "Auction",
|
|
13
|
+
showsStockQuantity: false,
|
|
8
14
|
};
|
|
@@ -68,6 +68,23 @@ export const LISTING_TYPE_CAPABILITIES = {
|
|
|
68
68
|
requiresJurisdictionCheck: true,
|
|
69
69
|
hasInstantFulfillment: false,
|
|
70
70
|
},
|
|
71
|
+
// Art/stickers session — printed-only physical goods, standard-like checkout.
|
|
72
|
+
art: {
|
|
73
|
+
canAddToCart: true,
|
|
74
|
+
canBid: false,
|
|
75
|
+
supportsShipping: true,
|
|
76
|
+
requiresVendorVerified: false,
|
|
77
|
+
requiresJurisdictionCheck: false,
|
|
78
|
+
hasInstantFulfillment: false,
|
|
79
|
+
},
|
|
80
|
+
stickers: {
|
|
81
|
+
canAddToCart: true,
|
|
82
|
+
canBid: false,
|
|
83
|
+
supportsShipping: true,
|
|
84
|
+
requiresVendorVerified: false,
|
|
85
|
+
requiresJurisdictionCheck: false,
|
|
86
|
+
hasInstantFulfillment: false,
|
|
87
|
+
},
|
|
71
88
|
};
|
|
72
89
|
export function capabilityFor(type) {
|
|
73
90
|
return LISTING_TYPE_CAPABILITIES[type];
|
|
@@ -4,4 +4,12 @@ export declare const config: {
|
|
|
4
4
|
listingType: "classified";
|
|
5
5
|
slugPrefix: string;
|
|
6
6
|
cartLine: "blocked";
|
|
7
|
+
detailRoute: (idOrSlug: string) => string;
|
|
8
|
+
badge: {
|
|
9
|
+
label: string;
|
|
10
|
+
className: string;
|
|
11
|
+
} | undefined;
|
|
12
|
+
priceLabel: string;
|
|
13
|
+
typeLabel: string;
|
|
14
|
+
showsStockQuantity: boolean;
|
|
7
15
|
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
|
|
2
|
+
import { ROUTES } from "../../../../next/routing/route-map";
|
|
2
3
|
export const LISTING_TYPE = "classified";
|
|
3
4
|
export const capability = LISTING_TYPE_CAPABILITIES.classified;
|
|
4
5
|
export const config = {
|
|
5
6
|
listingType: LISTING_TYPE,
|
|
6
7
|
slugPrefix: "classified-",
|
|
7
8
|
cartLine: "blocked",
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(idOrSlug)),
|
|
10
|
+
badge: undefined,
|
|
11
|
+
priceLabel: "Asking Price (₹)",
|
|
12
|
+
typeLabel: "Classified",
|
|
13
|
+
showsStockQuantity: true,
|
|
8
14
|
};
|
|
@@ -4,4 +4,12 @@ export declare const config: {
|
|
|
4
4
|
listingType: "digital-code";
|
|
5
5
|
slugPrefix: string;
|
|
6
6
|
cartLine: "single-product";
|
|
7
|
+
detailRoute: (idOrSlug: string) => string;
|
|
8
|
+
badge: {
|
|
9
|
+
label: string;
|
|
10
|
+
className: string;
|
|
11
|
+
} | undefined;
|
|
12
|
+
priceLabel: string;
|
|
13
|
+
typeLabel: string;
|
|
14
|
+
showsStockQuantity: boolean;
|
|
7
15
|
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
|
|
2
|
+
import { ROUTES } from "../../../../next/routing/route-map";
|
|
2
3
|
export const LISTING_TYPE = "digital-code";
|
|
3
4
|
export const capability = LISTING_TYPE_CAPABILITIES["digital-code"];
|
|
4
5
|
export const config = {
|
|
5
6
|
listingType: LISTING_TYPE,
|
|
6
7
|
slugPrefix: "digitalcode-",
|
|
7
8
|
cartLine: "single-product",
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(idOrSlug)),
|
|
10
|
+
badge: undefined,
|
|
11
|
+
priceLabel: "Price per Code (₹)",
|
|
12
|
+
typeLabel: "Digital Code",
|
|
13
|
+
showsStockQuantity: false,
|
|
8
14
|
};
|
|
@@ -4,4 +4,12 @@ export declare const config: {
|
|
|
4
4
|
listingType: "live";
|
|
5
5
|
slugPrefix: string;
|
|
6
6
|
cartLine: "single-product";
|
|
7
|
+
detailRoute: (idOrSlug: string) => string;
|
|
8
|
+
badge: {
|
|
9
|
+
label: string;
|
|
10
|
+
className: string;
|
|
11
|
+
} | undefined;
|
|
12
|
+
priceLabel: string;
|
|
13
|
+
typeLabel: string;
|
|
14
|
+
showsStockQuantity: boolean;
|
|
7
15
|
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
|
|
2
|
+
import { ROUTES } from "../../../../next/routing/route-map";
|
|
2
3
|
export const LISTING_TYPE = "live";
|
|
3
4
|
export const capability = LISTING_TYPE_CAPABILITIES.live;
|
|
4
5
|
export const config = {
|
|
5
6
|
listingType: LISTING_TYPE,
|
|
6
7
|
slugPrefix: "live-",
|
|
7
8
|
cartLine: "single-product",
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(idOrSlug)),
|
|
10
|
+
badge: undefined,
|
|
11
|
+
priceLabel: "Price (₹)",
|
|
12
|
+
typeLabel: "Live Item",
|
|
13
|
+
showsStockQuantity: true,
|
|
8
14
|
};
|
|
@@ -4,4 +4,12 @@ export declare const config: {
|
|
|
4
4
|
listingType: "pre-order";
|
|
5
5
|
slugPrefix: string;
|
|
6
6
|
cartLine: "single-product";
|
|
7
|
+
detailRoute: (idOrSlug: string) => string;
|
|
8
|
+
badge: {
|
|
9
|
+
label: string;
|
|
10
|
+
className: string;
|
|
11
|
+
};
|
|
12
|
+
priceLabel: string;
|
|
13
|
+
typeLabel: string;
|
|
14
|
+
showsStockQuantity: boolean;
|
|
7
15
|
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
|
|
2
|
+
import { ROUTES } from "../../../../next/routing/route-map";
|
|
2
3
|
export const LISTING_TYPE = "pre-order";
|
|
3
4
|
export const capability = LISTING_TYPE_CAPABILITIES["pre-order"];
|
|
4
5
|
export const config = {
|
|
5
6
|
listingType: LISTING_TYPE,
|
|
6
7
|
slugPrefix: "preorder-",
|
|
7
8
|
cartLine: "single-product",
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.PRE_ORDER_DETAIL(idOrSlug)),
|
|
10
|
+
badge: { label: "Pre-Order", className: "bg-info-surface text-white" },
|
|
11
|
+
priceLabel: "Pre-Order Price (₹)",
|
|
12
|
+
typeLabel: "Pre-Order",
|
|
13
|
+
showsStockQuantity: false,
|
|
8
14
|
};
|
|
@@ -4,4 +4,12 @@ export declare const config: {
|
|
|
4
4
|
listingType: "prize-draw";
|
|
5
5
|
slugPrefix: string;
|
|
6
6
|
cartLine: "single-product";
|
|
7
|
+
detailRoute: (idOrSlug: string) => string;
|
|
8
|
+
badge: {
|
|
9
|
+
label: string;
|
|
10
|
+
className: string;
|
|
11
|
+
} | undefined;
|
|
12
|
+
priceLabel: string;
|
|
13
|
+
typeLabel: string;
|
|
14
|
+
showsStockQuantity: boolean;
|
|
7
15
|
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
|
|
2
|
+
import { ROUTES } from "../../../../next/routing/route-map";
|
|
2
3
|
export const LISTING_TYPE = "prize-draw";
|
|
3
4
|
export const capability = LISTING_TYPE_CAPABILITIES["prize-draw"];
|
|
4
5
|
export const config = {
|
|
5
6
|
listingType: LISTING_TYPE,
|
|
6
7
|
slugPrefix: "prizedraw-",
|
|
7
8
|
cartLine: "single-product",
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(idOrSlug)),
|
|
10
|
+
badge: undefined,
|
|
11
|
+
priceLabel: "Price (₹)",
|
|
12
|
+
typeLabel: "Prize Draw",
|
|
13
|
+
showsStockQuantity: false,
|
|
8
14
|
};
|
|
@@ -4,4 +4,12 @@ export declare const config: {
|
|
|
4
4
|
listingType: "standard";
|
|
5
5
|
slugPrefix: string;
|
|
6
6
|
cartLine: "single-product";
|
|
7
|
+
detailRoute: (idOrSlug: string) => string;
|
|
8
|
+
badge: {
|
|
9
|
+
label: string;
|
|
10
|
+
className: string;
|
|
11
|
+
} | undefined;
|
|
12
|
+
priceLabel: string;
|
|
13
|
+
typeLabel: string;
|
|
14
|
+
showsStockQuantity: boolean;
|
|
7
15
|
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
|
|
2
|
+
import { ROUTES } from "../../../../next/routing/route-map";
|
|
2
3
|
export const LISTING_TYPE = "standard";
|
|
3
4
|
export const capability = LISTING_TYPE_CAPABILITIES.standard;
|
|
4
5
|
export const config = {
|
|
5
6
|
listingType: LISTING_TYPE,
|
|
6
7
|
slugPrefix: "product-",
|
|
7
8
|
cartLine: "single-product",
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(idOrSlug)),
|
|
10
|
+
badge: undefined,
|
|
11
|
+
priceLabel: "Price (₹)",
|
|
12
|
+
typeLabel: "Product",
|
|
13
|
+
showsStockQuantity: true,
|
|
8
14
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const LISTING_TYPE: "stickers";
|
|
2
|
+
export declare const capability: import("../capabilities").ListingTypeCapability;
|
|
3
|
+
export declare const config: {
|
|
4
|
+
listingType: "stickers";
|
|
5
|
+
slugPrefix: string;
|
|
6
|
+
cartLine: "single-product";
|
|
7
|
+
detailRoute: (idOrSlug: string) => string;
|
|
8
|
+
badge: {
|
|
9
|
+
label: string;
|
|
10
|
+
className: string;
|
|
11
|
+
} | undefined;
|
|
12
|
+
priceLabel: string;
|
|
13
|
+
typeLabel: string;
|
|
14
|
+
showsStockQuantity: boolean;
|
|
15
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
|
|
2
|
+
import { ROUTES } from "../../../../next/routing/route-map";
|
|
3
|
+
export const LISTING_TYPE = "stickers";
|
|
4
|
+
export const capability = LISTING_TYPE_CAPABILITIES.stickers;
|
|
5
|
+
export const config = {
|
|
6
|
+
listingType: LISTING_TYPE,
|
|
7
|
+
slugPrefix: "sticker-",
|
|
8
|
+
cartLine: "single-product",
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(idOrSlug)),
|
|
10
|
+
badge: undefined,
|
|
11
|
+
priceLabel: "Price (₹)",
|
|
12
|
+
typeLabel: "Stickers",
|
|
13
|
+
showsStockQuantity: true,
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ctas: readonly string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|