@mohasinac/appkit 2.6.1 → 2.6.2
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/client/features/layout/DashboardLayoutClient.d.ts +38 -0
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +75 -0
- package/dist/_internal/client/features/layout/RoleGuard.d.ts +15 -0
- package/dist/_internal/client/features/layout/RoleGuard.js +25 -0
- package/dist/_internal/client/features/layout/index.d.ts +5 -0
- package/dist/_internal/client/features/layout/index.js +4 -0
- package/dist/_internal/server/features/brands/actions.d.ts +3 -3
- package/dist/_internal/server/features/brands/actions.js +72 -5
- package/dist/_internal/server/features/brands/data.d.ts +8 -8
- package/dist/_internal/server/features/brands/data.js +10 -11
- package/dist/_internal/server/features/brands/service.d.ts +2 -2
- package/dist/_internal/server/features/brands/service.js +5 -5
- package/dist/_internal/server/features/categories/og.d.ts +33 -0
- package/dist/_internal/server/features/categories/og.js +75 -0
- package/dist/_internal/server/features/checkout/actions.d.ts +24 -0
- package/dist/_internal/server/features/checkout/actions.js +442 -13
- package/dist/_internal/server/features/checkout/index.d.ts +1 -1
- package/dist/_internal/server/features/checkout/index.js +1 -1
- package/dist/_internal/server/features/checkout/prize-bundle-gates.d.ts +59 -0
- package/dist/_internal/server/features/checkout/prize-bundle-gates.js +99 -0
- package/dist/_internal/server/features/grouped/data.js +12 -5
- package/dist/_internal/server/features/homepage/data.d.ts +1 -1
- package/dist/_internal/server/features/homepage/data.js +2 -2
- package/dist/_internal/server/features/media/contextGuards.d.ts +52 -0
- package/dist/_internal/server/features/media/contextGuards.js +198 -0
- package/dist/_internal/server/features/orders/adapters.js +12 -0
- package/dist/_internal/server/features/products/data.d.ts +1 -1
- package/dist/_internal/server/features/sublisting-categories/data.d.ts +1 -1
- package/dist/_internal/server/features/sublisting-categories/data.js +2 -2
- package/dist/_internal/server/jobs/handlers/assignSpinPrize.d.ts +24 -0
- package/dist/_internal/server/jobs/handlers/assignSpinPrize.js +86 -0
- package/dist/_internal/server/jobs/handlers/bundleStockSync.d.ts +18 -0
- package/dist/_internal/server/jobs/handlers/bundleStockSync.js +80 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +8 -0
- package/dist/_internal/server/jobs/handlers/index.js +13 -0
- package/dist/_internal/server/jobs/handlers/listingProcessor.js +13 -3
- package/dist/_internal/server/jobs/handlers/onProductStockChange.d.ts +17 -0
- package/dist/_internal/server/jobs/handlers/onProductStockChange.js +136 -0
- package/dist/_internal/server/jobs/handlers/onProductWrite.js +17 -1
- package/dist/_internal/server/jobs/handlers/prizeRevealClose.d.ts +9 -0
- package/dist/_internal/server/jobs/handlers/prizeRevealClose.js +29 -0
- package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.d.ts +10 -0
- package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.js +58 -0
- package/dist/_internal/server/jobs/handlers/prizeRevealOpen.d.ts +10 -0
- package/dist/_internal/server/jobs/handlers/prizeRevealOpen.js +65 -0
- package/dist/_internal/server/jobs/handlers/prizeRevealReminder.d.ts +9 -0
- package/dist/_internal/server/jobs/handlers/prizeRevealReminder.js +45 -0
- package/dist/_internal/server/jobs/handlers/triggerEventRaffle.d.ts +30 -0
- package/dist/_internal/server/jobs/handlers/triggerEventRaffle.js +94 -0
- package/dist/_internal/shared/features/brands/schema.d.ts +3 -3
- package/dist/_internal/shared/features/cart/schema.d.ts +8 -8
- package/dist/_internal/shared/features/cart/schema.js +1 -1
- package/dist/_internal/shared/features/categories/bundle-config.d.ts +17 -0
- package/dist/_internal/shared/features/categories/bundle-config.js +17 -0
- package/dist/_internal/shared/features/layout/config.d.ts +35 -0
- package/dist/_internal/shared/features/layout/config.js +58 -0
- package/dist/_internal/shared/features/layout/index.d.ts +3 -0
- package/dist/_internal/shared/features/layout/index.js +2 -0
- package/dist/_internal/shared/features/layout/types.d.ts +137 -0
- package/dist/_internal/shared/features/layout/types.js +13 -0
- package/dist/_internal/shared/features/products/types.d.ts +1 -1
- package/dist/_internal/shared/listing-types/_registry.d.ts +57 -0
- package/dist/_internal/shared/listing-types/_registry.js +28 -0
- package/dist/_internal/shared/listing-types/auction/config.d.ts +7 -0
- package/dist/_internal/shared/listing-types/auction/config.js +8 -0
- package/dist/_internal/shared/listing-types/auction/ctas.d.ts +1 -0
- package/dist/_internal/shared/listing-types/auction/ctas.js +2 -0
- package/dist/_internal/shared/listing-types/auction/og.d.ts +1 -0
- package/dist/_internal/shared/listing-types/auction/og.js +1 -0
- package/dist/_internal/shared/listing-types/auction/schema.d.ts +1 -0
- package/dist/_internal/shared/listing-types/auction/schema.js +1 -0
- package/dist/_internal/shared/listing-types/auction/seed-factory.d.ts +1 -0
- package/dist/_internal/shared/listing-types/auction/seed-factory.js +1 -0
- package/dist/_internal/shared/listing-types/capabilities.d.ts +41 -0
- package/dist/_internal/shared/listing-types/capabilities.js +75 -0
- package/dist/_internal/shared/listing-types/pre-order/config.d.ts +7 -0
- package/dist/_internal/shared/listing-types/pre-order/config.js +8 -0
- package/dist/_internal/shared/listing-types/pre-order/ctas.d.ts +1 -0
- package/dist/_internal/shared/listing-types/pre-order/ctas.js +2 -0
- package/dist/_internal/shared/listing-types/pre-order/og.d.ts +1 -0
- package/dist/_internal/shared/listing-types/pre-order/og.js +1 -0
- package/dist/_internal/shared/listing-types/pre-order/schema.d.ts +1 -0
- package/dist/_internal/shared/listing-types/pre-order/schema.js +1 -0
- package/dist/_internal/shared/listing-types/pre-order/seed-factory.d.ts +1 -0
- package/dist/_internal/shared/listing-types/pre-order/seed-factory.js +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +7 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.js +8 -0
- package/dist/_internal/shared/listing-types/prize-draw/ctas.d.ts +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/ctas.js +2 -0
- package/dist/_internal/shared/listing-types/prize-draw/og.d.ts +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/og.js +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/schema.d.ts +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/schema.js +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/seed-factory.d.ts +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/seed-factory.js +1 -0
- package/dist/_internal/shared/listing-types/standard/config.d.ts +7 -0
- package/dist/_internal/shared/listing-types/standard/config.js +8 -0
- package/dist/_internal/shared/listing-types/standard/ctas.d.ts +1 -0
- package/dist/_internal/shared/listing-types/standard/ctas.js +3 -0
- package/dist/_internal/shared/listing-types/standard/og.d.ts +1 -0
- package/dist/_internal/shared/listing-types/standard/og.js +1 -0
- package/dist/_internal/shared/listing-types/standard/schema.d.ts +1 -0
- package/dist/_internal/shared/listing-types/standard/schema.js +1 -0
- package/dist/_internal/shared/listing-types/standard/seed-factory.d.ts +1 -0
- package/dist/_internal/shared/listing-types/standard/seed-factory.js +1 -0
- package/dist/_internal/shared/media/limits.d.ts +33 -0
- package/dist/_internal/shared/media/limits.js +97 -0
- package/dist/_internal/shared/schema-versions.d.ts +76 -0
- package/dist/_internal/shared/schema-versions.js +82 -0
- package/dist/client.d.ts +9 -0
- package/dist/client.js +7 -0
- package/dist/constants/api-endpoints.d.ts +6 -3
- package/dist/constants/api-endpoints.js +2 -1
- package/dist/errors/messages.d.ts +1 -1
- package/dist/errors/messages.js +1 -1
- package/dist/features/account/migrations.d.ts +2 -0
- package/dist/features/account/migrations.js +10 -0
- package/dist/features/admin/components/AdminMediaView.js +1 -1
- package/dist/features/admin/components/AdminProductsView.js +7 -3
- package/dist/features/admin/migrations.d.ts +2 -0
- package/dist/features/admin/migrations.js +10 -0
- package/dist/features/admin/types/product.types.d.ts +1 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +1 -1
- package/dist/features/auctions/migrations.d.ts +2 -0
- package/dist/features/auctions/migrations.js +10 -0
- package/dist/features/auctions/schemas/index.d.ts +3 -3
- package/dist/features/auctions/schemas/index.js +1 -1
- package/dist/features/auth/migrations.d.ts +2 -0
- package/dist/features/auth/migrations.js +10 -0
- package/dist/features/blog/migrations.d.ts +2 -0
- package/dist/features/blog/migrations.js +10 -0
- package/dist/features/brands/migrations.d.ts +2 -0
- package/dist/features/brands/migrations.js +10 -0
- package/dist/features/bundles/components/BundlesByCategoryListing.d.ts +6 -0
- package/dist/features/bundles/components/BundlesByCategoryListing.js +50 -0
- package/dist/features/bundles/components/index.d.ts +2 -0
- package/dist/features/bundles/components/index.js +1 -0
- package/dist/features/bundles/migrations.d.ts +2 -0
- package/dist/features/bundles/migrations.js +10 -0
- package/dist/features/bundles/schemas/index.d.ts +1 -0
- package/dist/features/bundles/schemas/index.js +1 -0
- package/dist/features/bundles/schemas/zod.d.ts +377 -0
- package/dist/features/bundles/schemas/zod.js +71 -0
- package/dist/features/cart/migrations.d.ts +2 -0
- package/dist/features/cart/migrations.js +10 -0
- package/dist/features/cart/schemas/firestore.d.ts +2 -2
- package/dist/features/categories/components/BrandDetailPageView.js +35 -4
- package/dist/features/categories/components/BrandDetailTabs.d.ts +5 -1
- package/dist/features/categories/components/BrandDetailTabs.js +22 -8
- package/dist/features/categories/components/CategoryBundlesListing.d.ts +6 -0
- package/dist/features/categories/components/CategoryBundlesListing.js +74 -0
- package/dist/features/categories/components/CategoryDetailPageView.js +29 -4
- package/dist/features/categories/components/CategoryDetailTabs.d.ts +5 -1
- package/dist/features/categories/components/CategoryDetailTabs.js +22 -8
- package/dist/features/categories/migrations.d.ts +2 -0
- package/dist/features/categories/migrations.js +10 -0
- package/dist/features/categories/repository/categories.repository.d.ts +29 -0
- package/dist/features/categories/repository/categories.repository.js +83 -0
- package/dist/features/categories/schemas/firestore.d.ts +59 -2
- package/dist/features/categories/schemas/firestore.js +6 -0
- package/dist/features/categories/types/index.d.ts +11 -3
- package/dist/features/events/migrations.d.ts +2 -0
- package/dist/features/events/migrations.js +10 -0
- package/dist/features/faq/migrations.d.ts +2 -0
- package/dist/features/faq/migrations.js +10 -0
- package/dist/features/grouped/migrations.d.ts +2 -0
- package/dist/features/grouped/migrations.js +10 -0
- package/dist/features/grouped/schemas/firestore.d.ts +29 -10
- package/dist/features/grouped/schemas/firestore.js +10 -5
- package/dist/features/history/migrations.d.ts +2 -0
- package/dist/features/history/migrations.js +10 -0
- package/dist/features/homepage/hooks/useFeaturedAuctions.js +2 -2
- package/dist/features/homepage/hooks/useFeaturedPreOrders.js +2 -2
- package/dist/features/homepage/lib/section-renderer.js +5 -3
- package/dist/features/media/AvatarUpload.js +6 -28
- package/dist/features/media/hooks/useMedia.d.ts +31 -15
- package/dist/features/media/hooks/useMedia.js +48 -13
- package/dist/features/media/upload/ImageUpload.js +1 -1
- package/dist/features/media/upload/MediaUploadField.js +1 -1
- package/dist/features/messages/migrations.d.ts +2 -0
- package/dist/features/messages/migrations.js +10 -0
- package/dist/features/orders/components/OrdersList.js +10 -1
- package/dist/features/orders/migrations.d.ts +2 -0
- package/dist/features/orders/migrations.js +10 -0
- package/dist/features/orders/repository/orders.repository.d.ts +16 -0
- package/dist/features/orders/repository/orders.repository.js +49 -0
- package/dist/features/orders/schemas/firestore.d.ts +8 -0
- package/dist/features/orders/types/index.d.ts +12 -0
- package/dist/features/orders/utils/order-splitter.d.ts +2 -2
- package/dist/features/orders/utils/order-splitter.js +5 -0
- package/dist/features/payments/migrations.d.ts +2 -0
- package/dist/features/payments/migrations.js +10 -0
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +4 -1
- package/dist/features/products/actions/product-actions.d.ts +1 -1
- package/dist/features/products/api/[id]/route.js +34 -0
- package/dist/features/products/api/route.js +1 -19
- package/dist/features/products/components/CompareOverlay.d.ts +1 -1
- package/dist/features/products/components/MarketplacePrizeDrawCard.d.ts +24 -0
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +102 -0
- package/dist/features/products/components/PrizeDrawCollage.d.ts +32 -0
- package/dist/features/products/components/PrizeDrawCollage.js +22 -0
- package/dist/features/products/components/PrizeDrawDetailPageView.d.ts +27 -0
- package/dist/features/products/components/PrizeDrawDetailPageView.js +118 -0
- package/dist/features/products/components/PrizeDrawEntryActions.d.ts +19 -0
- package/dist/features/products/components/PrizeDrawEntryActions.js +48 -0
- package/dist/features/products/components/PrizeDrawItemsEditor.d.ts +13 -0
- package/dist/features/products/components/PrizeDrawItemsEditor.js +97 -0
- package/dist/features/products/components/PrizeDrawsIndexListing.d.ts +8 -0
- package/dist/features/products/components/PrizeDrawsIndexListing.js +128 -0
- package/dist/features/products/components/PrizeDrawsListingView.d.ts +15 -0
- package/dist/features/products/components/PrizeDrawsListingView.js +49 -0
- package/dist/features/products/components/PrizeRevealModal.d.ts +34 -0
- package/dist/features/products/components/PrizeRevealModal.js +124 -0
- package/dist/features/products/components/ProductDetailPageView.js +13 -1
- package/dist/features/products/components/ProductForm.js +35 -2
- package/dist/features/products/components/ProductGrid.js +3 -1
- package/dist/features/products/components/index.d.ts +16 -0
- package/dist/features/products/components/index.js +8 -0
- package/dist/features/products/constants/listing-tabs.d.ts +113 -0
- package/dist/features/products/constants/listing-tabs.js +43 -0
- package/dist/features/products/index.d.ts +1 -0
- package/dist/features/products/index.js +1 -0
- package/dist/features/products/migrations.d.ts +2 -0
- package/dist/features/products/migrations.js +10 -0
- package/dist/features/products/repository/products.repository.d.ts +11 -7
- package/dist/features/products/repository/products.repository.js +49 -24
- package/dist/features/products/schemas/firestore.d.ts +3 -3
- package/dist/features/products/schemas/firestore.js +2 -2
- package/dist/features/products/schemas/index.d.ts +5 -5
- package/dist/features/products/schemas/index.js +3 -1
- package/dist/features/products/schemas/product-features.validators.d.ts +6 -6
- package/dist/features/products/types/index.d.ts +17 -1
- package/dist/features/products/utils/listing-type.d.ts +7 -4
- package/dist/features/products/utils/listing-type.js +8 -4
- package/dist/features/promotions/actions/coupon-actions.d.ts +1 -1
- package/dist/features/promotions/hooks/useCouponValidate.d.ts +1 -1
- package/dist/features/promotions/migrations.d.ts +2 -0
- package/dist/features/promotions/migrations.js +10 -0
- package/dist/features/promotions/repository/coupons.repository.d.ts +1 -1
- package/dist/features/promotions/schemas/index.d.ts +2 -2
- package/dist/features/reviews/migrations.d.ts +2 -0
- package/dist/features/reviews/migrations.js +10 -0
- package/dist/features/scams/migrations.d.ts +2 -0
- package/dist/features/scams/migrations.js +10 -0
- package/dist/features/search/api/route.d.ts +1 -1
- package/dist/features/search/api/route.js +3 -3
- package/dist/features/search/components/Search.d.ts +1 -1
- package/dist/features/search/schemas/index.d.ts +3 -3
- package/dist/features/search/schemas/index.js +3 -1
- package/dist/features/search/types/index.d.ts +2 -2
- package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
- package/dist/features/seller/components/SellerProductsView.js +20 -6
- package/dist/features/seller/migrations.d.ts +2 -0
- package/dist/features/seller/migrations.js +10 -0
- package/dist/features/seller/schemas/index.d.ts +2 -2
- package/dist/features/stores/components/StoreBundlesPageView.d.ts +12 -0
- package/dist/features/stores/components/StoreBundlesPageView.js +24 -0
- package/dist/features/stores/components/StoreDetailLayoutView.js +15 -3
- package/dist/features/stores/components/StorePrizeDrawsPageView.d.ts +11 -0
- package/dist/features/stores/components/StorePrizeDrawsPageView.js +27 -0
- package/dist/features/stores/components/index.d.ts +2 -0
- package/dist/features/stores/migrations.d.ts +2 -0
- package/dist/features/stores/migrations.js +10 -0
- package/dist/features/stores/schemas/index.d.ts +2 -2
- package/dist/features/stores/types/index.d.ts +1 -1
- package/dist/features/sublisting/migrations.d.ts +2 -0
- package/dist/features/sublisting/migrations.js +10 -0
- package/dist/features/sublisting/schemas/firestore.d.ts +2 -0
- package/dist/features/support/migrations.d.ts +2 -0
- package/dist/features/support/migrations.js +10 -0
- package/dist/features/wishlist/migrations.d.ts +2 -0
- package/dist/features/wishlist/migrations.js +10 -0
- package/dist/features/wishlist/types/index.d.ts +1 -1
- package/dist/index.d.ts +26 -18
- package/dist/index.js +41 -24
- package/dist/jobs.d.ts +1 -1
- package/dist/jobs.js +4 -0
- package/dist/next/routing/route-map.d.ts +4 -0
- package/dist/next/routing/route-map.js +2 -0
- package/dist/providers/db-firebase/filter-aliases.d.ts +2 -2
- package/dist/repositories/index.d.ts +0 -5
- package/dist/repositories/index.js +5 -4
- package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
- package/dist/seed/categories-seed-data.js +1105 -6
- package/dist/seed/faq-seed-data.js +160 -0
- package/dist/seed/grouped-listings-seed-data.js +32 -32
- package/dist/seed/homepage-sections-seed-data.js +52 -6
- package/dist/seed/index.d.ts +1 -3
- package/dist/seed/index.js +4 -3
- package/dist/seed/manifest.js +8 -13
- package/dist/seed/products-prize-draws-seed-data.d.ts +17 -0
- package/dist/seed/products-prize-draws-seed-data.js +313 -0
- package/dist/seo/json-ld.d.ts +1 -1
- package/dist/server-entry.d.ts +2 -2
- package/dist/server-entry.js +5 -3
- package/dist/server.d.ts +9 -2
- package/dist/server.js +11 -5
- package/dist/tailwind-utilities.css +1 -1
- package/dist/validation/schemas.d.ts +8 -8
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +2 -4
|
@@ -54,7 +54,7 @@ export declare const auctionItemSchema: z.ZodObject<{
|
|
|
54
54
|
storeId: z.ZodOptional<z.ZodString>;
|
|
55
55
|
storeSlug: z.ZodOptional<z.ZodString>;
|
|
56
56
|
featured: z.ZodBoolean;
|
|
57
|
-
|
|
57
|
+
listingType: z.ZodLiteral<"auction">;
|
|
58
58
|
createdAt: z.ZodString;
|
|
59
59
|
updatedAt: z.ZodString;
|
|
60
60
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -66,11 +66,11 @@ export declare const auctionItemSchema: z.ZodObject<{
|
|
|
66
66
|
title: string;
|
|
67
67
|
price: number;
|
|
68
68
|
featured: boolean;
|
|
69
|
+
listingType: "auction";
|
|
69
70
|
slug: string;
|
|
70
71
|
auctionEndDate: string;
|
|
71
72
|
startingBid: number;
|
|
72
73
|
bidCount: number;
|
|
73
|
-
isAuction: true;
|
|
74
74
|
sellerId: string;
|
|
75
75
|
storeId?: string | undefined;
|
|
76
76
|
media?: {
|
|
@@ -95,11 +95,11 @@ export declare const auctionItemSchema: z.ZodObject<{
|
|
|
95
95
|
title: string;
|
|
96
96
|
price: number;
|
|
97
97
|
featured: boolean;
|
|
98
|
+
listingType: "auction";
|
|
98
99
|
slug: string;
|
|
99
100
|
auctionEndDate: string;
|
|
100
101
|
startingBid: number;
|
|
101
102
|
bidCount: number;
|
|
102
|
-
isAuction: true;
|
|
103
103
|
sellerId: string;
|
|
104
104
|
storeId?: string | undefined;
|
|
105
105
|
media?: {
|
|
@@ -41,7 +41,7 @@ export const auctionItemSchema = z.object({
|
|
|
41
41
|
storeId: z.string().optional(),
|
|
42
42
|
storeSlug: z.string().optional(),
|
|
43
43
|
featured: z.boolean(),
|
|
44
|
-
|
|
44
|
+
listingType: z.literal("auction"),
|
|
45
45
|
createdAt: z.string(),
|
|
46
46
|
updatedAt: z.string(),
|
|
47
47
|
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SB-UNI X3 — migrations shell for user/session/token.
|
|
2
|
+
// v1 schema is current; no migrations needed yet.
|
|
3
|
+
//
|
|
4
|
+
// To add a migration:
|
|
5
|
+
// 1. Bump the relevant SCHEMA_VERSIONS entry in
|
|
6
|
+
// `_internal/shared/schema-versions.ts` (e.g. `auth: 2`)
|
|
7
|
+
// 2. Add a row below keyed by the FROM-version, returning the upgraded doc
|
|
8
|
+
// 3. Repository wraps reads with `migrateDocument(doc, current, migrations)`
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
export const migrations = {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SB-UNI X3 — migrations shell for blogPost.
|
|
2
|
+
// v1 schema is current; no migrations needed yet.
|
|
3
|
+
//
|
|
4
|
+
// To add a migration:
|
|
5
|
+
// 1. Bump the relevant SCHEMA_VERSIONS entry in
|
|
6
|
+
// `_internal/shared/schema-versions.ts` (e.g. `blog: 2`)
|
|
7
|
+
// 2. Add a row below keyed by the FROM-version, returning the upgraded doc
|
|
8
|
+
// 3. Repository wraps reads with `migrateDocument(doc, current, migrations)`
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
export const migrations = {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SB-UNI X3 — migrations shell for brand.
|
|
2
|
+
// v1 schema is current; no migrations needed yet.
|
|
3
|
+
//
|
|
4
|
+
// To add a migration:
|
|
5
|
+
// 1. Bump the relevant SCHEMA_VERSIONS entry in
|
|
6
|
+
// `_internal/shared/schema-versions.ts` (e.g. `brands: 2`)
|
|
7
|
+
// 2. Add a row below keyed by the FROM-version, returning the upgraded doc
|
|
8
|
+
// 3. Repository wraps reads with `migrateDocument(doc, current, migrations)`
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
export const migrations = {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { BundleDocument } from "../schemas/firestore";
|
|
2
|
+
export interface BundlesByCategoryListingProps {
|
|
3
|
+
initialBundles: BundleDocument[];
|
|
4
|
+
brandName?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function BundlesByCategoryListing({ initialBundles, brandName, }: BundlesByCategoryListingProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* BundlesByCategoryListing — SB7-C bundles tab (server-fetched via parent).
|
|
5
|
+
*
|
|
6
|
+
* Slim wrapper around `BundlesListingView` that hydrates from a parent-server
|
|
7
|
+
* fetch of `bundlesRepository.findByCategory(categorySlug)` or from a search
|
|
8
|
+
* by brand. The client owns its own filter state (sort + min/max) but does
|
|
9
|
+
* not refetch — the parent ships the full bundle list as `initialBundles`.
|
|
10
|
+
*
|
|
11
|
+
* For listing surfaces that need real pagination, swap to `useBundles`
|
|
12
|
+
* (not yet built — track in S7-PrizeDraws-3 follow-ups).
|
|
13
|
+
*/
|
|
14
|
+
import { useMemo, useState } from "react";
|
|
15
|
+
import Link from "next/link";
|
|
16
|
+
import { Badge, Div, Row, Stack, Text, } from "../../../ui";
|
|
17
|
+
import { ROUTES } from "../../../next/routing/route-map";
|
|
18
|
+
function formatRupees(paise) {
|
|
19
|
+
return `₹${(paise / 100).toLocaleString("en-IN")}`;
|
|
20
|
+
}
|
|
21
|
+
function savingsPct(b) {
|
|
22
|
+
if (!b.bundleOriginalTotal)
|
|
23
|
+
return 0;
|
|
24
|
+
const off = Math.max(0, b.bundleOriginalTotal - b.bundlePrice);
|
|
25
|
+
return Math.round((off / b.bundleOriginalTotal) * 100);
|
|
26
|
+
}
|
|
27
|
+
export function BundlesByCategoryListing({ initialBundles, brandName, }) {
|
|
28
|
+
const [sort, setSort] = useState("newest");
|
|
29
|
+
const filtered = useMemo(() => {
|
|
30
|
+
let list = initialBundles.slice();
|
|
31
|
+
if (brandName) {
|
|
32
|
+
const needle = brandName.toLowerCase();
|
|
33
|
+
list = list.filter((b) => b.brand?.toLowerCase?.() === needle ||
|
|
34
|
+
b.brandSlug?.toLowerCase?.() === needle ||
|
|
35
|
+
b.bundleItems.some((it) => String(it.brand ?? "").toLowerCase() === needle));
|
|
36
|
+
}
|
|
37
|
+
if (sort === "savings-desc")
|
|
38
|
+
list.sort((a, b) => savingsPct(b) - savingsPct(a));
|
|
39
|
+
else if (sort === "price-asc")
|
|
40
|
+
list.sort((a, b) => a.bundlePrice - b.bundlePrice);
|
|
41
|
+
return list;
|
|
42
|
+
}, [initialBundles, brandName, sort]);
|
|
43
|
+
return (_jsxs(Stack, { className: "gap-4", children: [_jsxs(Row, { className: "items-center justify-between flex-wrap gap-2", children: [_jsxs(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: [filtered.length, " ", filtered.length === 1 ? "bundle" : "bundles"] }), _jsxs("label", { className: "text-xs text-zinc-600 dark:text-zinc-300", children: ["Sort:", _jsxs("select", { value: sort, onChange: (e) => setSort(e.target.value), className: "ml-2 rounded border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-2 py-1 text-xs", children: [_jsx("option", { value: "newest", children: "Newest" }), _jsx("option", { value: "savings-desc", children: "Best savings" }), _jsx("option", { value: "price-asc", children: "Price: low \u2192 high" })] })] })] }), filtered.length === 0 ? (_jsx(Div, { className: "rounded border border-dashed border-zinc-300 dark:border-zinc-700 p-10 text-center", children: _jsx(Text, { children: "No bundles match these filters yet." }) })) : (_jsx(Div, { className: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4", children: filtered.map((b) => {
|
|
44
|
+
const oos = b.status === "out_of_stock";
|
|
45
|
+
const off = savingsPct(b);
|
|
46
|
+
return (_jsxs(Link, { href: ROUTES.PUBLIC.BUNDLE_DETAIL(b.slug), className: "group block rounded-lg border border-zinc-200 dark:border-zinc-700 overflow-hidden hover:shadow-md transition", children: [_jsxs(Div, { className: `relative aspect-video bg-zinc-100 dark:bg-zinc-800 ${oos ? "opacity-60" : ""}`, children: [b.images?.[0] && (
|
|
47
|
+
/* eslint-disable-next-line @next/next/no-img-element, @next/next/no-raw-media-elements */
|
|
48
|
+
_jsx("img", { src: b.images[0], alt: b.title, className: "h-full w-full object-cover" })), oos && (_jsx(Div, { className: "absolute inset-0 grid place-items-center bg-black/40", children: _jsx(Badge, { variant: "danger", children: "Currently unavailable" }) })), off > 0 && !oos && (_jsxs(Badge, { variant: "success", className: "absolute top-2 left-2", children: [off, "% off"] })), _jsxs(Badge, { variant: "secondary", className: "absolute top-2 right-2", children: [b.bundleItems.length, " items"] })] }), _jsxs(Stack, { className: "gap-1 p-3", children: [_jsx(Text, { className: "font-medium truncate", children: b.title }), _jsx(Text, { className: "text-xs text-[var(--appkit-color-text-muted)]", children: b.storeName }), _jsxs(Row, { className: "items-baseline gap-2", children: [_jsx(Text, { className: "font-semibold", children: formatRupees(b.bundlePrice) }), b.bundleOriginalTotal > b.bundlePrice && (_jsx(Text, { className: "text-xs line-through text-[var(--appkit-color-text-muted)]", children: formatRupees(b.bundleOriginalTotal) }))] })] })] }, b.id));
|
|
49
|
+
}) }))] }));
|
|
50
|
+
}
|
|
@@ -14,3 +14,5 @@ export { BundlesListingView } from "./BundlesListingView";
|
|
|
14
14
|
export type { BundlesListingViewProps, BundleSort, } from "./BundlesListingView";
|
|
15
15
|
export { BundleDetailPageView } from "./BundleDetailPageView";
|
|
16
16
|
export type { BundleDetailPageViewProps } from "./BundleDetailPageView";
|
|
17
|
+
export { BundlesByCategoryListing } from "./BundlesByCategoryListing";
|
|
18
|
+
export type { BundlesByCategoryListingProps } from "./BundlesByCategoryListing";
|
|
@@ -6,3 +6,4 @@ export { SellerBundleEditView } from "./SellerBundleEditView";
|
|
|
6
6
|
export { AdminBundleEditorView } from "./AdminBundleEditorView";
|
|
7
7
|
export { BundlesListingView } from "./BundlesListingView";
|
|
8
8
|
export { BundleDetailPageView } from "./BundleDetailPageView";
|
|
9
|
+
export { BundlesByCategoryListing } from "./BundlesByCategoryListing";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SB-UNI X3 — migrations shell for bundle.
|
|
2
|
+
// v1 schema is current; no migrations needed yet.
|
|
3
|
+
//
|
|
4
|
+
// To add a migration:
|
|
5
|
+
// 1. Bump the relevant SCHEMA_VERSIONS entry in
|
|
6
|
+
// `_internal/shared/schema-versions.ts` (e.g. `bundles: 2`)
|
|
7
|
+
// 2. Add a row below keyed by the FROM-version, returning the upgraded doc
|
|
8
|
+
// 3. Repository wraps reads with `migrateDocument(doc, current, migrations)`
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
export const migrations = {};
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle Zod schemas — SB3-J input validation for the `/api/bundles*`
|
|
3
|
+
* routes. Both schemas are intentionally narrower than `BundleDocument`:
|
|
4
|
+
*
|
|
5
|
+
* - `bundleCreateInputSchema` covers the POST body. `bundleItems` is the
|
|
6
|
+
* minimum required surface; everything else (slug, status, price,
|
|
7
|
+
* storeName) can be filled or normalised server-side.
|
|
8
|
+
* - `bundleUpdateInputSchema` is `bundleCreateInputSchema.partial()` so PUT
|
|
9
|
+
* can do partial edits while still validating any shape the caller does
|
|
10
|
+
* send.
|
|
11
|
+
*
|
|
12
|
+
* `partOfBundleProductIds` is NOT user-supplied — the route derives it
|
|
13
|
+
* from `bundleItems[]` to keep the reverse index in lock-step.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
export declare const BUNDLE_ITEM_MIN = 3;
|
|
17
|
+
export declare const BUNDLE_ITEM_MAX = 16;
|
|
18
|
+
export declare const bundleCreateInputSchema: z.ZodObject<{
|
|
19
|
+
id: z.ZodOptional<z.ZodString>;
|
|
20
|
+
slug: z.ZodOptional<z.ZodString>;
|
|
21
|
+
title: z.ZodString;
|
|
22
|
+
description: z.ZodOptional<z.ZodString>;
|
|
23
|
+
storeId: z.ZodString;
|
|
24
|
+
storeName: z.ZodString;
|
|
25
|
+
status: z.ZodOptional<z.ZodEnum<["draft", "published", "out_of_stock", "archived"]>>;
|
|
26
|
+
bundleItems: z.ZodEffects<z.ZodArray<z.ZodObject<{
|
|
27
|
+
productId: z.ZodString;
|
|
28
|
+
productSlug: z.ZodString;
|
|
29
|
+
title: z.ZodString;
|
|
30
|
+
listingType: z.ZodEnum<["standard", "pre-order"]>;
|
|
31
|
+
images: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
32
|
+
video: z.ZodOptional<z.ZodObject<{
|
|
33
|
+
url: z.ZodString;
|
|
34
|
+
thumbnailUrl: z.ZodOptional<z.ZodString>;
|
|
35
|
+
}, "strip", z.ZodTypeAny, {
|
|
36
|
+
url: string;
|
|
37
|
+
thumbnailUrl?: string | undefined;
|
|
38
|
+
}, {
|
|
39
|
+
url: string;
|
|
40
|
+
thumbnailUrl?: string | undefined;
|
|
41
|
+
}>>;
|
|
42
|
+
price: z.ZodNumber;
|
|
43
|
+
quantity: z.ZodNumber;
|
|
44
|
+
isSold: z.ZodDefault<z.ZodBoolean>;
|
|
45
|
+
}, "strip", z.ZodTypeAny, {
|
|
46
|
+
title: string;
|
|
47
|
+
productId: string;
|
|
48
|
+
quantity: number;
|
|
49
|
+
price: number;
|
|
50
|
+
images: string[];
|
|
51
|
+
listingType: "standard" | "pre-order";
|
|
52
|
+
isSold: boolean;
|
|
53
|
+
productSlug: string;
|
|
54
|
+
video?: {
|
|
55
|
+
url: string;
|
|
56
|
+
thumbnailUrl?: string | undefined;
|
|
57
|
+
} | undefined;
|
|
58
|
+
}, {
|
|
59
|
+
title: string;
|
|
60
|
+
productId: string;
|
|
61
|
+
quantity: number;
|
|
62
|
+
price: number;
|
|
63
|
+
listingType: "standard" | "pre-order";
|
|
64
|
+
productSlug: string;
|
|
65
|
+
video?: {
|
|
66
|
+
url: string;
|
|
67
|
+
thumbnailUrl?: string | undefined;
|
|
68
|
+
} | undefined;
|
|
69
|
+
images?: string[] | undefined;
|
|
70
|
+
isSold?: boolean | undefined;
|
|
71
|
+
}>, "many">, {
|
|
72
|
+
title: string;
|
|
73
|
+
productId: string;
|
|
74
|
+
quantity: number;
|
|
75
|
+
price: number;
|
|
76
|
+
images: string[];
|
|
77
|
+
listingType: "standard" | "pre-order";
|
|
78
|
+
isSold: boolean;
|
|
79
|
+
productSlug: string;
|
|
80
|
+
video?: {
|
|
81
|
+
url: string;
|
|
82
|
+
thumbnailUrl?: string | undefined;
|
|
83
|
+
} | undefined;
|
|
84
|
+
}[], {
|
|
85
|
+
title: string;
|
|
86
|
+
productId: string;
|
|
87
|
+
quantity: number;
|
|
88
|
+
price: number;
|
|
89
|
+
listingType: "standard" | "pre-order";
|
|
90
|
+
productSlug: string;
|
|
91
|
+
video?: {
|
|
92
|
+
url: string;
|
|
93
|
+
thumbnailUrl?: string | undefined;
|
|
94
|
+
} | undefined;
|
|
95
|
+
images?: string[] | undefined;
|
|
96
|
+
isSold?: boolean | undefined;
|
|
97
|
+
}[]>;
|
|
98
|
+
bundlePrice: z.ZodNumber;
|
|
99
|
+
bundleOriginalTotal: z.ZodOptional<z.ZodNumber>;
|
|
100
|
+
category: z.ZodOptional<z.ZodString>;
|
|
101
|
+
categorySlug: z.ZodOptional<z.ZodString>;
|
|
102
|
+
subcategory: z.ZodOptional<z.ZodString>;
|
|
103
|
+
sublistingCategoryId: z.ZodOptional<z.ZodString>;
|
|
104
|
+
brandSlug: z.ZodOptional<z.ZodString>;
|
|
105
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
106
|
+
images: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
107
|
+
video: z.ZodOptional<z.ZodObject<{
|
|
108
|
+
url: z.ZodString;
|
|
109
|
+
thumbnailUrl: z.ZodOptional<z.ZodString>;
|
|
110
|
+
}, "strip", z.ZodTypeAny, {
|
|
111
|
+
url: string;
|
|
112
|
+
thumbnailUrl?: string | undefined;
|
|
113
|
+
}, {
|
|
114
|
+
url: string;
|
|
115
|
+
thumbnailUrl?: string | undefined;
|
|
116
|
+
}>>;
|
|
117
|
+
maxPerUser: z.ZodOptional<z.ZodNumber>;
|
|
118
|
+
isFeatured: z.ZodOptional<z.ZodBoolean>;
|
|
119
|
+
isPromoted: z.ZodOptional<z.ZodBoolean>;
|
|
120
|
+
}, "strip", z.ZodTypeAny, {
|
|
121
|
+
storeId: string;
|
|
122
|
+
title: string;
|
|
123
|
+
storeName: string;
|
|
124
|
+
bundleItems: {
|
|
125
|
+
title: string;
|
|
126
|
+
productId: string;
|
|
127
|
+
quantity: number;
|
|
128
|
+
price: number;
|
|
129
|
+
images: string[];
|
|
130
|
+
listingType: "standard" | "pre-order";
|
|
131
|
+
isSold: boolean;
|
|
132
|
+
productSlug: string;
|
|
133
|
+
video?: {
|
|
134
|
+
url: string;
|
|
135
|
+
thumbnailUrl?: string | undefined;
|
|
136
|
+
} | undefined;
|
|
137
|
+
}[];
|
|
138
|
+
bundlePrice: number;
|
|
139
|
+
id?: string | undefined;
|
|
140
|
+
status?: "draft" | "published" | "archived" | "out_of_stock" | undefined;
|
|
141
|
+
video?: {
|
|
142
|
+
url: string;
|
|
143
|
+
thumbnailUrl?: string | undefined;
|
|
144
|
+
} | undefined;
|
|
145
|
+
category?: string | undefined;
|
|
146
|
+
images?: string[] | undefined;
|
|
147
|
+
description?: string | undefined;
|
|
148
|
+
isPromoted?: boolean | undefined;
|
|
149
|
+
slug?: string | undefined;
|
|
150
|
+
subcategory?: string | undefined;
|
|
151
|
+
brandSlug?: string | undefined;
|
|
152
|
+
tags?: string[] | undefined;
|
|
153
|
+
sublistingCategoryId?: string | undefined;
|
|
154
|
+
maxPerUser?: number | undefined;
|
|
155
|
+
categorySlug?: string | undefined;
|
|
156
|
+
isFeatured?: boolean | undefined;
|
|
157
|
+
bundleOriginalTotal?: number | undefined;
|
|
158
|
+
}, {
|
|
159
|
+
storeId: string;
|
|
160
|
+
title: string;
|
|
161
|
+
storeName: string;
|
|
162
|
+
bundleItems: {
|
|
163
|
+
title: string;
|
|
164
|
+
productId: string;
|
|
165
|
+
quantity: number;
|
|
166
|
+
price: number;
|
|
167
|
+
listingType: "standard" | "pre-order";
|
|
168
|
+
productSlug: string;
|
|
169
|
+
video?: {
|
|
170
|
+
url: string;
|
|
171
|
+
thumbnailUrl?: string | undefined;
|
|
172
|
+
} | undefined;
|
|
173
|
+
images?: string[] | undefined;
|
|
174
|
+
isSold?: boolean | undefined;
|
|
175
|
+
}[];
|
|
176
|
+
bundlePrice: number;
|
|
177
|
+
id?: string | undefined;
|
|
178
|
+
status?: "draft" | "published" | "archived" | "out_of_stock" | undefined;
|
|
179
|
+
video?: {
|
|
180
|
+
url: string;
|
|
181
|
+
thumbnailUrl?: string | undefined;
|
|
182
|
+
} | undefined;
|
|
183
|
+
category?: string | undefined;
|
|
184
|
+
images?: string[] | undefined;
|
|
185
|
+
description?: string | undefined;
|
|
186
|
+
isPromoted?: boolean | undefined;
|
|
187
|
+
slug?: string | undefined;
|
|
188
|
+
subcategory?: string | undefined;
|
|
189
|
+
brandSlug?: string | undefined;
|
|
190
|
+
tags?: string[] | undefined;
|
|
191
|
+
sublistingCategoryId?: string | undefined;
|
|
192
|
+
maxPerUser?: number | undefined;
|
|
193
|
+
categorySlug?: string | undefined;
|
|
194
|
+
isFeatured?: boolean | undefined;
|
|
195
|
+
bundleOriginalTotal?: number | undefined;
|
|
196
|
+
}>;
|
|
197
|
+
export declare const bundleUpdateInputSchema: z.ZodObject<{
|
|
198
|
+
id: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
199
|
+
slug: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
200
|
+
title: z.ZodOptional<z.ZodString>;
|
|
201
|
+
description: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
202
|
+
storeId: z.ZodOptional<z.ZodString>;
|
|
203
|
+
storeName: z.ZodOptional<z.ZodString>;
|
|
204
|
+
status: z.ZodOptional<z.ZodOptional<z.ZodEnum<["draft", "published", "out_of_stock", "archived"]>>>;
|
|
205
|
+
bundleItems: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodObject<{
|
|
206
|
+
productId: z.ZodString;
|
|
207
|
+
productSlug: z.ZodString;
|
|
208
|
+
title: z.ZodString;
|
|
209
|
+
listingType: z.ZodEnum<["standard", "pre-order"]>;
|
|
210
|
+
images: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
211
|
+
video: z.ZodOptional<z.ZodObject<{
|
|
212
|
+
url: z.ZodString;
|
|
213
|
+
thumbnailUrl: z.ZodOptional<z.ZodString>;
|
|
214
|
+
}, "strip", z.ZodTypeAny, {
|
|
215
|
+
url: string;
|
|
216
|
+
thumbnailUrl?: string | undefined;
|
|
217
|
+
}, {
|
|
218
|
+
url: string;
|
|
219
|
+
thumbnailUrl?: string | undefined;
|
|
220
|
+
}>>;
|
|
221
|
+
price: z.ZodNumber;
|
|
222
|
+
quantity: z.ZodNumber;
|
|
223
|
+
isSold: z.ZodDefault<z.ZodBoolean>;
|
|
224
|
+
}, "strip", z.ZodTypeAny, {
|
|
225
|
+
title: string;
|
|
226
|
+
productId: string;
|
|
227
|
+
quantity: number;
|
|
228
|
+
price: number;
|
|
229
|
+
images: string[];
|
|
230
|
+
listingType: "standard" | "pre-order";
|
|
231
|
+
isSold: boolean;
|
|
232
|
+
productSlug: string;
|
|
233
|
+
video?: {
|
|
234
|
+
url: string;
|
|
235
|
+
thumbnailUrl?: string | undefined;
|
|
236
|
+
} | undefined;
|
|
237
|
+
}, {
|
|
238
|
+
title: string;
|
|
239
|
+
productId: string;
|
|
240
|
+
quantity: number;
|
|
241
|
+
price: number;
|
|
242
|
+
listingType: "standard" | "pre-order";
|
|
243
|
+
productSlug: string;
|
|
244
|
+
video?: {
|
|
245
|
+
url: string;
|
|
246
|
+
thumbnailUrl?: string | undefined;
|
|
247
|
+
} | undefined;
|
|
248
|
+
images?: string[] | undefined;
|
|
249
|
+
isSold?: boolean | undefined;
|
|
250
|
+
}>, "many">, {
|
|
251
|
+
title: string;
|
|
252
|
+
productId: string;
|
|
253
|
+
quantity: number;
|
|
254
|
+
price: number;
|
|
255
|
+
images: string[];
|
|
256
|
+
listingType: "standard" | "pre-order";
|
|
257
|
+
isSold: boolean;
|
|
258
|
+
productSlug: string;
|
|
259
|
+
video?: {
|
|
260
|
+
url: string;
|
|
261
|
+
thumbnailUrl?: string | undefined;
|
|
262
|
+
} | undefined;
|
|
263
|
+
}[], {
|
|
264
|
+
title: string;
|
|
265
|
+
productId: string;
|
|
266
|
+
quantity: number;
|
|
267
|
+
price: number;
|
|
268
|
+
listingType: "standard" | "pre-order";
|
|
269
|
+
productSlug: string;
|
|
270
|
+
video?: {
|
|
271
|
+
url: string;
|
|
272
|
+
thumbnailUrl?: string | undefined;
|
|
273
|
+
} | undefined;
|
|
274
|
+
images?: string[] | undefined;
|
|
275
|
+
isSold?: boolean | undefined;
|
|
276
|
+
}[]>>;
|
|
277
|
+
bundlePrice: z.ZodOptional<z.ZodNumber>;
|
|
278
|
+
bundleOriginalTotal: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
|
|
279
|
+
category: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
280
|
+
categorySlug: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
281
|
+
subcategory: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
282
|
+
sublistingCategoryId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
283
|
+
brandSlug: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
284
|
+
tags: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
285
|
+
images: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
286
|
+
video: z.ZodOptional<z.ZodOptional<z.ZodObject<{
|
|
287
|
+
url: z.ZodString;
|
|
288
|
+
thumbnailUrl: z.ZodOptional<z.ZodString>;
|
|
289
|
+
}, "strip", z.ZodTypeAny, {
|
|
290
|
+
url: string;
|
|
291
|
+
thumbnailUrl?: string | undefined;
|
|
292
|
+
}, {
|
|
293
|
+
url: string;
|
|
294
|
+
thumbnailUrl?: string | undefined;
|
|
295
|
+
}>>>;
|
|
296
|
+
maxPerUser: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
|
|
297
|
+
isFeatured: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
|
|
298
|
+
isPromoted: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
|
|
299
|
+
}, "strip", z.ZodTypeAny, {
|
|
300
|
+
id?: string | undefined;
|
|
301
|
+
storeId?: string | undefined;
|
|
302
|
+
status?: "draft" | "published" | "archived" | "out_of_stock" | undefined;
|
|
303
|
+
title?: string | undefined;
|
|
304
|
+
video?: {
|
|
305
|
+
url: string;
|
|
306
|
+
thumbnailUrl?: string | undefined;
|
|
307
|
+
} | undefined;
|
|
308
|
+
category?: string | undefined;
|
|
309
|
+
images?: string[] | undefined;
|
|
310
|
+
description?: string | undefined;
|
|
311
|
+
isPromoted?: boolean | undefined;
|
|
312
|
+
slug?: string | undefined;
|
|
313
|
+
subcategory?: string | undefined;
|
|
314
|
+
brandSlug?: string | undefined;
|
|
315
|
+
storeName?: string | undefined;
|
|
316
|
+
tags?: string[] | undefined;
|
|
317
|
+
sublistingCategoryId?: string | undefined;
|
|
318
|
+
maxPerUser?: number | undefined;
|
|
319
|
+
categorySlug?: string | undefined;
|
|
320
|
+
isFeatured?: boolean | undefined;
|
|
321
|
+
bundleItems?: {
|
|
322
|
+
title: string;
|
|
323
|
+
productId: string;
|
|
324
|
+
quantity: number;
|
|
325
|
+
price: number;
|
|
326
|
+
images: string[];
|
|
327
|
+
listingType: "standard" | "pre-order";
|
|
328
|
+
isSold: boolean;
|
|
329
|
+
productSlug: string;
|
|
330
|
+
video?: {
|
|
331
|
+
url: string;
|
|
332
|
+
thumbnailUrl?: string | undefined;
|
|
333
|
+
} | undefined;
|
|
334
|
+
}[] | undefined;
|
|
335
|
+
bundlePrice?: number | undefined;
|
|
336
|
+
bundleOriginalTotal?: number | undefined;
|
|
337
|
+
}, {
|
|
338
|
+
id?: string | undefined;
|
|
339
|
+
storeId?: string | undefined;
|
|
340
|
+
status?: "draft" | "published" | "archived" | "out_of_stock" | undefined;
|
|
341
|
+
title?: string | undefined;
|
|
342
|
+
video?: {
|
|
343
|
+
url: string;
|
|
344
|
+
thumbnailUrl?: string | undefined;
|
|
345
|
+
} | undefined;
|
|
346
|
+
category?: string | undefined;
|
|
347
|
+
images?: string[] | undefined;
|
|
348
|
+
description?: string | undefined;
|
|
349
|
+
isPromoted?: boolean | undefined;
|
|
350
|
+
slug?: string | undefined;
|
|
351
|
+
subcategory?: string | undefined;
|
|
352
|
+
brandSlug?: string | undefined;
|
|
353
|
+
storeName?: string | undefined;
|
|
354
|
+
tags?: string[] | undefined;
|
|
355
|
+
sublistingCategoryId?: string | undefined;
|
|
356
|
+
maxPerUser?: number | undefined;
|
|
357
|
+
categorySlug?: string | undefined;
|
|
358
|
+
isFeatured?: boolean | undefined;
|
|
359
|
+
bundleItems?: {
|
|
360
|
+
title: string;
|
|
361
|
+
productId: string;
|
|
362
|
+
quantity: number;
|
|
363
|
+
price: number;
|
|
364
|
+
listingType: "standard" | "pre-order";
|
|
365
|
+
productSlug: string;
|
|
366
|
+
video?: {
|
|
367
|
+
url: string;
|
|
368
|
+
thumbnailUrl?: string | undefined;
|
|
369
|
+
} | undefined;
|
|
370
|
+
images?: string[] | undefined;
|
|
371
|
+
isSold?: boolean | undefined;
|
|
372
|
+
}[] | undefined;
|
|
373
|
+
bundlePrice?: number | undefined;
|
|
374
|
+
bundleOriginalTotal?: number | undefined;
|
|
375
|
+
}>;
|
|
376
|
+
export type BundleCreateInput = z.infer<typeof bundleCreateInputSchema>;
|
|
377
|
+
export type BundleUpdateInput = z.infer<typeof bundleUpdateInputSchema>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle Zod schemas — SB3-J input validation for the `/api/bundles*`
|
|
3
|
+
* routes. Both schemas are intentionally narrower than `BundleDocument`:
|
|
4
|
+
*
|
|
5
|
+
* - `bundleCreateInputSchema` covers the POST body. `bundleItems` is the
|
|
6
|
+
* minimum required surface; everything else (slug, status, price,
|
|
7
|
+
* storeName) can be filled or normalised server-side.
|
|
8
|
+
* - `bundleUpdateInputSchema` is `bundleCreateInputSchema.partial()` so PUT
|
|
9
|
+
* can do partial edits while still validating any shape the caller does
|
|
10
|
+
* send.
|
|
11
|
+
*
|
|
12
|
+
* `partOfBundleProductIds` is NOT user-supplied — the route derives it
|
|
13
|
+
* from `bundleItems[]` to keep the reverse index in lock-step.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
export const BUNDLE_ITEM_MIN = 3;
|
|
17
|
+
export const BUNDLE_ITEM_MAX = 16;
|
|
18
|
+
const bundleItemListingTypeSchema = z.enum(["standard", "pre-order"]);
|
|
19
|
+
const bundleItemInputSchema = z.object({
|
|
20
|
+
productId: z.string().min(1),
|
|
21
|
+
productSlug: z.string().min(1),
|
|
22
|
+
title: z.string().min(1).max(200),
|
|
23
|
+
listingType: bundleItemListingTypeSchema,
|
|
24
|
+
images: z.array(z.string()).default([]),
|
|
25
|
+
video: z
|
|
26
|
+
.object({
|
|
27
|
+
url: z.string(),
|
|
28
|
+
thumbnailUrl: z.string().optional(),
|
|
29
|
+
})
|
|
30
|
+
.optional(),
|
|
31
|
+
price: z.number().int().min(0),
|
|
32
|
+
quantity: z.number().int().min(1).max(99),
|
|
33
|
+
isSold: z.boolean().default(false),
|
|
34
|
+
});
|
|
35
|
+
const bundleStatusSchema = z.enum([
|
|
36
|
+
"draft",
|
|
37
|
+
"published",
|
|
38
|
+
"out_of_stock",
|
|
39
|
+
"archived",
|
|
40
|
+
]);
|
|
41
|
+
const mediaInputSchema = z.object({
|
|
42
|
+
url: z.string(),
|
|
43
|
+
thumbnailUrl: z.string().optional(),
|
|
44
|
+
});
|
|
45
|
+
export const bundleCreateInputSchema = z.object({
|
|
46
|
+
id: z.string().optional(),
|
|
47
|
+
slug: z.string().optional(),
|
|
48
|
+
title: z.string().min(1).max(200),
|
|
49
|
+
description: z.string().max(5000).optional(),
|
|
50
|
+
storeId: z.string().min(1),
|
|
51
|
+
storeName: z.string().min(1),
|
|
52
|
+
status: bundleStatusSchema.optional(),
|
|
53
|
+
bundleItems: z.array(bundleItemInputSchema)
|
|
54
|
+
.min(BUNDLE_ITEM_MIN, `Bundle must contain at least ${BUNDLE_ITEM_MIN} items`)
|
|
55
|
+
.max(BUNDLE_ITEM_MAX, `Bundle may contain at most ${BUNDLE_ITEM_MAX} items`)
|
|
56
|
+
.refine((items) => items.every((it) => it.listingType === items[0].listingType), { message: "All bundleItems must share the same listingType" }),
|
|
57
|
+
bundlePrice: z.number().int().min(0),
|
|
58
|
+
bundleOriginalTotal: z.number().int().min(0).optional(),
|
|
59
|
+
category: z.string().optional(),
|
|
60
|
+
categorySlug: z.string().optional(),
|
|
61
|
+
subcategory: z.string().optional(),
|
|
62
|
+
sublistingCategoryId: z.string().optional(),
|
|
63
|
+
brandSlug: z.string().optional(),
|
|
64
|
+
tags: z.array(z.string()).optional(),
|
|
65
|
+
images: z.array(z.string()).optional(),
|
|
66
|
+
video: mediaInputSchema.optional(),
|
|
67
|
+
maxPerUser: z.number().int().min(1).optional(),
|
|
68
|
+
isFeatured: z.boolean().optional(),
|
|
69
|
+
isPromoted: z.boolean().optional(),
|
|
70
|
+
});
|
|
71
|
+
export const bundleUpdateInputSchema = bundleCreateInputSchema.partial();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SB-UNI X3 — migrations shell for cart/cartItem.
|
|
2
|
+
// v1 schema is current; no migrations needed yet.
|
|
3
|
+
//
|
|
4
|
+
// To add a migration:
|
|
5
|
+
// 1. Bump the relevant SCHEMA_VERSIONS entry in
|
|
6
|
+
// `_internal/shared/schema-versions.ts` (e.g. `cart: 2`)
|
|
7
|
+
// 2. Add a row below keyed by the FROM-version, returning the upgraded doc
|
|
8
|
+
// 3. Repository wraps reads with `migrateDocument(doc, current, migrations)`
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
export const migrations = {};
|