@mohasinac/appkit 4.59.0 → 4.60.1
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/.build-stamp.json +3 -3
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +62 -5
- package/dist/_internal/client/features/maintenance/views/MaintenanceDashboardView.js +2 -2
- package/dist/_internal/server/features/brands/actions.js +78 -4
- package/dist/_internal/server/features/checkout/actions.d.ts +36 -13
- package/dist/_internal/server/features/checkout/actions.js +668 -183
- package/dist/_internal/server/features/checkout/supplier-identity.js +18 -1
- package/dist/_internal/server/features/gateway-events/index.d.ts +10 -0
- package/dist/_internal/server/features/gateway-events/index.js +10 -0
- package/dist/_internal/server/features/gateway-events/ingest.d.ts +127 -0
- package/dist/_internal/server/features/gateway-events/ingest.js +188 -0
- package/dist/_internal/server/features/gateway-events/redact.d.ts +66 -0
- package/dist/_internal/server/features/gateway-events/redact.js +151 -0
- package/dist/_internal/server/features/grievance/actions.d.ts +63 -0
- package/dist/_internal/server/features/grievance/actions.js +173 -0
- package/dist/_internal/server/features/grievance/index.d.ts +8 -0
- package/dist/_internal/server/features/grievance/index.js +8 -0
- package/dist/_internal/server/features/grouped/data.js +28 -3
- package/dist/_internal/server/features/lottery/actions.js +99 -4
- package/dist/_internal/server/features/order-completion/actions.d.ts +92 -0
- package/dist/_internal/server/features/order-completion/actions.js +336 -0
- package/dist/_internal/server/features/order-completion/index.d.ts +7 -0
- package/dist/_internal/server/features/order-completion/index.js +7 -0
- package/dist/_internal/server/features/orders/actions.d.ts +13 -0
- package/dist/_internal/server/features/orders/actions.js +56 -2
- package/dist/_internal/server/features/orders/adapters.d.ts +20 -2
- package/dist/_internal/server/features/orders/adapters.js +44 -0
- package/dist/_internal/server/features/orders/cancellation-refund.d.ts +116 -0
- package/dist/_internal/server/features/orders/cancellation-refund.js +466 -0
- package/dist/_internal/server/features/orders/index.d.ts +2 -1
- package/dist/_internal/server/features/orders/index.js +1 -1
- package/dist/_internal/server/features/orders/service.d.ts +60 -0
- package/dist/_internal/server/features/orders/service.js +74 -0
- package/dist/_internal/server/features/payment-cases/disputes.d.ts +76 -0
- package/dist/_internal/server/features/payment-cases/disputes.js +241 -0
- package/dist/_internal/server/features/payment-cases/index.d.ts +9 -0
- package/dist/_internal/server/features/payment-cases/index.js +9 -0
- package/dist/_internal/server/features/payouts/actions.d.ts +28 -3
- package/dist/_internal/server/features/payouts/actions.js +84 -10
- package/dist/_internal/server/features/points/adjust.d.ts +61 -0
- package/dist/_internal/server/features/points/adjust.js +121 -0
- package/dist/_internal/server/features/points/award.d.ts +65 -0
- package/dist/_internal/server/features/points/award.js +145 -0
- package/dist/_internal/server/features/price-index/market.d.ts +33 -0
- package/dist/_internal/server/features/price-index/market.js +54 -1
- package/dist/_internal/server/features/products/data.js +40 -22
- package/dist/_internal/server/features/protection-claims/actions.d.ts +72 -0
- package/dist/_internal/server/features/protection-claims/actions.js +228 -0
- package/dist/_internal/server/features/protection-claims/index.d.ts +8 -0
- package/dist/_internal/server/features/protection-claims/index.js +8 -0
- package/dist/_internal/server/features/refunds/actions.d.ts +20 -0
- package/dist/_internal/server/features/refunds/actions.js +259 -17
- package/dist/_internal/server/features/refunds/capacity.d.ts +29 -0
- package/dist/_internal/server/features/refunds/capacity.js +37 -0
- package/dist/_internal/server/features/reviews/actions.js +3 -2
- package/dist/_internal/server/features/search/index-build/sources.js +20 -1
- package/dist/_internal/server/features/shipping/reconcile.d.ts +10 -1
- package/dist/_internal/server/features/shipping/reconcile.js +34 -3
- package/dist/_internal/server/features/shipping/reimbursement.d.ts +117 -0
- package/dist/_internal/server/features/shipping/reimbursement.js +223 -0
- package/dist/_internal/server/features/stores/tabs.d.ts +19 -4
- package/dist/_internal/server/features/stores/tabs.js +24 -4
- package/dist/_internal/server/functions/https.d.ts +31 -1
- package/dist/_internal/server/functions/https.js +52 -1
- package/dist/_internal/server/functions/scheduled.d.ts +72 -1
- package/dist/_internal/server/functions/scheduled.js +124 -1
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +62 -16
- package/dist/_internal/server/jobs/core/boxRollupReconcile.d.ts +46 -0
- package/dist/_internal/server/jobs/core/boxRollupReconcile.js +142 -0
- package/dist/_internal/server/jobs/core/dailyDataCleanup.js +149 -1
- package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +14 -0
- package/dist/_internal/server/jobs/core/dailyStatusDigest.js +79 -1
- package/dist/_internal/server/jobs/core/index.d.ts +2 -0
- package/dist/_internal/server/jobs/core/index.js +2 -0
- package/dist/_internal/server/jobs/core/marketPriceRollup.d.ts +64 -0
- package/dist/_internal/server/jobs/core/marketPriceRollup.js +153 -0
- package/dist/_internal/server/jobs/core/obligationSweep.d.ts +36 -0
- package/dist/_internal/server/jobs/core/obligationSweep.js +503 -0
- package/dist/_internal/server/jobs/core/paymentReconcile.d.ts +79 -0
- package/dist/_internal/server/jobs/core/paymentReconcile.js +614 -0
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +34 -0
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +35 -4
- package/dist/_internal/server/jobs/handlers/boxRollupReconcile.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/boxRollupReconcile.js +15 -0
- package/dist/_internal/server/jobs/handlers/countersReconcileNow.d.ts +65 -0
- package/dist/_internal/server/jobs/handlers/countersReconcileNow.js +89 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +5 -0
- package/dist/_internal/server/jobs/handlers/index.js +5 -0
- package/dist/_internal/server/jobs/handlers/marketPriceRollup.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/marketPriceRollup.js +2 -0
- package/dist/_internal/server/jobs/handlers/obligationSweep.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/obligationSweep.js +15 -0
- package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +30 -1
- package/dist/_internal/server/jobs/handlers/paymentReconcile.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/paymentReconcile.js +6 -0
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +71 -0
- package/dist/_internal/shared/checkout/coupon-discount.d.ts +73 -0
- package/dist/_internal/shared/checkout/coupon-discount.js +103 -0
- package/dist/_internal/shared/checkout/lanes.d.ts +42 -0
- package/dist/_internal/shared/checkout/lanes.js +46 -0
- package/dist/_internal/shared/checkout/order-math.d.ts +149 -1
- package/dist/_internal/shared/checkout/order-math.js +251 -3
- package/dist/_internal/shared/checkout/refundable-base.d.ts +116 -0
- package/dist/_internal/shared/checkout/refundable-base.js +122 -0
- package/dist/_internal/shared/features/auctions/config.d.ts +14 -1
- package/dist/_internal/shared/features/auctions/config.js +30 -1
- package/dist/_internal/shared/features/brands/schema.d.ts +42 -0
- package/dist/_internal/shared/features/brands/schema.js +18 -0
- package/dist/_internal/shared/features/orders/refund-copy.d.ts +22 -0
- package/dist/_internal/shared/features/orders/refund-copy.js +34 -0
- package/dist/_internal/shared/features/print/label-profiles.d.ts +198 -0
- package/dist/_internal/shared/features/print/label-profiles.js +350 -0
- package/dist/_internal/shared/features/products/to-product-item.js +33 -5
- package/dist/_internal/shared/fees/calculator.d.ts +31 -2
- package/dist/_internal/shared/fees/calculator.js +103 -5
- package/dist/_internal/shared/fees/india-states.d.ts +195 -0
- package/dist/_internal/shared/fees/india-states.js +190 -0
- package/dist/_internal/shared/fees/payout-hold.d.ts +80 -0
- package/dist/_internal/shared/fees/payout-hold.js +74 -0
- package/dist/_internal/shared/obligations/deadlines.d.ts +94 -0
- package/dist/_internal/shared/obligations/deadlines.js +155 -0
- package/dist/_internal/shared/shipping/quote.d.ts +96 -0
- package/dist/_internal/shared/shipping/quote.js +67 -0
- package/dist/_internal/shared/time/business-days.d.ts +91 -0
- package/dist/_internal/shared/time/business-days.js +185 -0
- package/dist/cli/index.js +0 -2
- package/dist/client.d.ts +10 -4
- package/dist/client.js +29 -3
- package/dist/configs/tailwind.d.ts +0 -12
- package/dist/configs/tailwind.js +28 -15
- package/dist/constants/api-endpoints.d.ts +51 -9
- package/dist/constants/api-endpoints.js +23 -7
- package/dist/constants/index.d.ts +1 -1
- package/dist/constants/index.js +1 -1
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/payment.d.ts +131 -0
- package/dist/features/about/components/AboutView.js +1 -1
- package/dist/features/about/components/DeveloperView.js +5 -2
- package/dist/features/about/components/FAQPageView.js +2 -1
- package/dist/features/about/components/FeesView.js +2 -1
- package/dist/features/about/components/HelpPageView.js +2 -1
- package/dist/features/about/components/HowAuctionsWorkView.js +2 -1
- package/dist/features/about/components/HowCheckoutWorksView.js +2 -1
- package/dist/features/about/components/HowEmiWorksView.js +2 -1
- package/dist/features/about/components/HowOffersWorkView.js +2 -1
- package/dist/features/about/components/HowOrdersWorkView.js +2 -1
- package/dist/features/about/components/HowPayoutsWorkView.js +2 -1
- package/dist/features/about/components/HowPreOrdersWorkView.js +2 -1
- package/dist/features/about/components/HowReviewsWorkView.js +2 -1
- package/dist/features/about/components/PolicyPageView.js +2 -1
- package/dist/features/about/components/ProseHero.d.ts +73 -0
- package/dist/features/about/components/ProseHero.js +18 -0
- package/dist/features/about/components/SecurityPrivacyView.js +2 -1
- package/dist/features/about/components/ShippingPolicyView.js +2 -1
- package/dist/features/about/components/TrackOrderView.js +2 -1
- package/dist/features/about/components/UnauthorizedView.js +1 -1
- package/dist/features/about/index.d.ts +2 -0
- package/dist/features/about/index.js +5 -0
- package/dist/features/account/actions/address-actions.d.ts +26 -2
- package/dist/features/account/actions/address-actions.js +25 -1
- package/dist/features/account/components/BuyerShoppingGuideView.js +1 -1
- package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
- package/dist/features/account/components/UserOrdersView.js +17 -0
- package/dist/features/account/components/UserSidebar.js +1 -1
- package/dist/features/account/hooks/useNotifications.js +29 -0
- package/dist/features/admin/actions/admin-coupon-actions.js +36 -0
- package/dist/features/admin/components/AdminBeysView.js +2 -2
- package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
- package/dist/features/admin/components/AdminBrandEditorView.js +32 -2
- package/dist/features/admin/components/AdminBundleEditorView.js +1 -1
- package/dist/features/admin/components/AdminCarouselEditorView.js +1 -1
- package/dist/features/admin/components/AdminCategoriesView.js +1 -1
- package/dist/features/admin/components/AdminCategoryEditorView.js +73 -17
- package/dist/features/admin/components/AdminContactEditorView.js +1 -1
- package/dist/features/admin/components/AdminCouponEditorView.js +26 -1
- package/dist/features/admin/components/AdminFaqEditorView.js +1 -1
- package/dist/features/admin/components/AdminFaqsView.js +2 -2
- package/dist/features/admin/components/AdminGatewayEventsView.d.ts +54 -0
- package/dist/features/admin/components/AdminGatewayEventsView.js +209 -0
- package/dist/features/admin/components/AdminGuideHubView.js +1 -1
- package/dist/features/admin/components/AdminMoneyCasesView.d.ts +60 -0
- package/dist/features/admin/components/AdminMoneyCasesView.js +287 -0
- package/dist/features/admin/components/AdminPartsView.js +2 -2
- package/dist/features/admin/components/AdminProductsView.js +75 -4
- package/dist/features/admin/components/AdminSidebar.js +2 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +65 -7
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +2 -0
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
- package/dist/features/admin/components/AdminSupportTicketsView.js +2 -2
- package/dist/features/admin/components/AdminTesterChecklistView.js +2 -2
- package/dist/features/admin/components/AdminUsersView.js +72 -1
- package/dist/features/admin/components/AdminViewCards.d.ts +3 -1
- package/dist/features/admin/components/AdminViewCards.js +4 -4
- package/dist/features/admin/components/DataListingView.d.ts +28 -0
- package/dist/features/admin/components/DataListingView.js +175 -14
- package/dist/features/admin/components/DataTable.d.ts +12 -1
- package/dist/features/admin/components/DataTable.js +3 -3
- package/dist/features/admin/components/OwnerQuickActions.d.ts +1 -1
- package/dist/features/admin/components/OwnerQuickActions.js +60 -2
- package/dist/features/admin/components/RecordOwnerQuickActions.d.ts +1 -1
- package/dist/features/admin/components/RecordOwnerQuickActions.js +61 -14
- package/dist/features/admin/components/analytics/AdminStatCard.d.ts +35 -1
- package/dist/features/admin/components/analytics/AdminStatCard.js +77 -2
- package/dist/features/admin/components/index.d.ts +4 -0
- package/dist/features/admin/components/index.js +6 -0
- package/dist/features/admin/constants/filter-tabs.d.ts +156 -0
- package/dist/features/admin/constants/filter-tabs.js +106 -0
- package/dist/features/admin/repository/site-settings.repository.d.ts +22 -0
- package/dist/features/admin/repository/site-settings.repository.js +82 -1
- package/dist/features/admin/schemas/admin-editor-forms.d.ts +21 -0
- package/dist/features/admin/schemas/admin-editor-forms.js +44 -0
- package/dist/features/admin/schemas/firestore.js +5 -1
- package/dist/features/admin/schemas/site-settings-form.js +30 -1
- package/dist/features/auctions/actions/bid-actions.js +13 -1
- package/dist/features/auctions/components/AuctionBottomActions.js +2 -2
- package/dist/features/auctions/components/AuctionDetailPageView.js +3 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +11 -0
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +5 -3
- package/dist/features/auctions/components/PlaceBidFormClient.d.ts +8 -1
- package/dist/features/auctions/components/PlaceBidFormClient.js +2 -2
- package/dist/features/audit-log/schemas/firestore.d.ts +28 -0
- package/dist/features/audit-log/schemas/firestore.js +14 -0
- package/dist/features/auth/permissions/constants.d.ts +17 -1
- package/dist/features/auth/permissions/constants.js +18 -0
- package/dist/features/blog/components/BlogPostView.js +1 -1
- package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +1 -1
- package/dist/features/categories/api/[id]/description-template/route.js +107 -1
- package/dist/features/categories/components/BrandDetailPageView.js +2 -2
- package/dist/features/categories/components/BreadcrumbTrail.js +7 -1
- package/dist/features/categories/components/BundleDetailView.js +1 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
- package/dist/features/categories/components/CategoryForm.js +12 -1
- package/dist/features/categories/components/CategoryTemplatePicker.js +38 -5
- package/dist/features/categories/repository/market-price-index.repository.d.ts +123 -0
- package/dist/features/categories/repository/market-price-index.repository.js +105 -0
- package/dist/features/categories/repository/price-observation.repository.d.ts +166 -0
- package/dist/features/categories/repository/price-observation.repository.js +132 -0
- package/dist/features/events/components/EventSaleBanner.js +1 -1
- package/dist/features/events/components/EventStatusBadge.js +1 -1
- package/dist/features/faq/components/FAQAccordion.js +2 -1
- package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
- package/dist/features/faq/components/FAQHelpfulButtons.js +4 -4
- package/dist/features/faq/components/RelatedFAQs.js +1 -1
- package/dist/features/filters/FilterFacetSection.js +1 -1
- package/dist/features/filters/SwitchFilter.js +1 -1
- package/dist/features/gateway-events/repository/gateway-events.repository.d.ts +117 -0
- package/dist/features/gateway-events/repository/gateway-events.repository.js +274 -0
- package/dist/features/gateway-events/schemas/firestore.d.ts +217 -0
- package/dist/features/gateway-events/schemas/firestore.js +125 -0
- package/dist/features/gateway-events/schemas/index.d.ts +81 -0
- package/dist/features/gateway-events/schemas/index.js +79 -0
- package/dist/features/grouped/components/GroupedListingDetailView.js +1 -1
- package/dist/features/homepage/components/AnnouncementBar.js +37 -1
- package/dist/features/homepage/components/AnnouncementBar.style.css +30 -0
- package/dist/features/homepage/components/BrandsSection.js +1 -1
- package/dist/features/homepage/components/CTABannerSection.js +1 -1
- package/dist/features/homepage/components/FeaturedBundlesSection.js +14 -24
- package/dist/features/homepage/components/HeroCarousel.js +2 -2
- package/dist/features/homepage/components/SocialPostCard.js +1 -1
- package/dist/features/inventory/components/AdminMoveLedgerView.d.ts +7 -0
- package/dist/features/inventory/components/AdminMoveLedgerView.js +157 -0
- package/dist/features/inventory/components/AdminStorageBoxesView.d.ts +11 -0
- package/dist/features/inventory/components/AdminStorageBoxesView.js +168 -0
- package/dist/features/inventory/components/ReceiveStationView.d.ts +39 -0
- package/dist/features/inventory/components/ReceiveStationView.js +413 -0
- package/dist/features/inventory/components/operator-message.d.ts +29 -0
- package/dist/features/inventory/components/operator-message.js +41 -0
- package/dist/features/inventory/index.d.ts +13 -0
- package/dist/features/inventory/index.js +28 -0
- package/dist/features/inventory/repository/inventory-movements.repository.d.ts +97 -0
- package/dist/features/inventory/repository/inventory-movements.repository.js +186 -0
- package/dist/features/inventory/repository/inventory-placements.repository.d.ts +179 -0
- package/dist/features/inventory/repository/inventory-placements.repository.js +345 -0
- package/dist/features/inventory/repository/storage-boxes.repository.d.ts +83 -0
- package/dist/features/inventory/repository/storage-boxes.repository.js +127 -0
- package/dist/features/inventory/schemas/firestore.d.ts +197 -0
- package/dist/features/inventory/schemas/firestore.js +159 -0
- package/dist/features/layout/AppLayoutShell.d.ts +12 -1
- package/dist/features/layout/AppLayoutShell.js +25 -12
- package/dist/features/layout/AutoBreadcrumbs.js +162 -3
- package/dist/features/layout/AutoBreadcrumbs.style.css +45 -0
- package/dist/features/layout/BottomNavbar.d.ts +1 -1
- package/dist/features/layout/BottomNavbar.js +2 -2
- package/dist/features/media/MediaAvatar.js +1 -1
- package/dist/features/media/MediaImage.d.ts +24 -4
- package/dist/features/media/MediaImage.js +44 -4
- package/dist/features/media/MediaLightbox.js +1 -1
- package/dist/features/media/modals/ImageCropModal.js +1 -1
- package/dist/features/media/modals/ImageEditor.js +1 -1
- package/dist/features/media/upload/MediaUploadField.js +91 -3
- package/dist/features/obligations/constants/policies.d.ts +92 -0
- package/dist/features/obligations/constants/policies.js +378 -0
- package/dist/features/obligations/repository/obligations.repository.d.ts +68 -0
- package/dist/features/obligations/repository/obligations.repository.js +158 -0
- package/dist/features/obligations/schemas/firestore.d.ts +160 -0
- package/dist/features/obligations/schemas/firestore.js +87 -0
- package/dist/features/orders/actions/order-actions.d.ts +43 -4
- package/dist/features/orders/actions/order-actions.js +60 -3
- package/dist/features/orders/actions/refund-actions.js +70 -10
- package/dist/features/orders/components/OrderCompletionPanel.d.ts +27 -0
- package/dist/features/orders/components/OrderCompletionPanel.js +192 -0
- package/dist/features/orders/components/OrdersList.js +2 -2
- package/dist/features/orders/components/RefundHistoryTable.js +3 -1
- package/dist/features/orders/components/index.d.ts +2 -0
- package/dist/features/orders/components/index.js +6 -0
- package/dist/features/orders/constants/transitions.d.ts +59 -0
- package/dist/features/orders/constants/transitions.js +104 -0
- package/dist/features/orders/repository/orders.repository.d.ts +109 -6
- package/dist/features/orders/repository/orders.repository.js +464 -21
- package/dist/features/orders/schemas/firestore.d.ts +270 -0
- package/dist/features/orders/schemas/firestore.js +24 -0
- package/dist/features/orders/schemas/index.d.ts +61 -0
- package/dist/features/orders/schemas/index.js +22 -0
- package/dist/features/orders/types/index.d.ts +79 -0
- package/dist/features/parts/components/PartsIndexPageView.js +8 -1
- package/dist/features/payment-cases/repository/payment-cases.repository.d.ts +170 -0
- package/dist/features/payment-cases/repository/payment-cases.repository.js +342 -0
- package/dist/features/payment-cases/schemas/firestore.d.ts +229 -0
- package/dist/features/payment-cases/schemas/firestore.js +105 -0
- package/dist/features/payment-cases/schemas/resolve-form.d.ts +97 -0
- package/dist/features/payment-cases/schemas/resolve-form.js +114 -0
- package/dist/features/payments/repository/payout.repository.d.ts +0 -1
- package/dist/features/payments/repository/payout.repository.js +0 -1
- package/dist/features/points/repository/points.repository.d.ts +122 -0
- package/dist/features/points/repository/points.repository.js +304 -1
- package/dist/features/points/schemas/adjust-form.d.ts +58 -0
- package/dist/features/points/schemas/adjust-form.js +63 -0
- package/dist/features/points/schemas/firestore.d.ts +108 -1
- package/dist/features/points/schemas/firestore.js +84 -0
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -3
- package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
- package/dist/features/price-index/components/PriceIndexToolView.d.ts +23 -4
- package/dist/features/price-index/components/PriceIndexToolView.js +71 -6
- package/dist/features/price-index/market-stats.d.ts +82 -0
- package/dist/features/price-index/market-stats.js +230 -0
- package/dist/features/print/components/BoxLabelPrintView.d.ts +25 -0
- package/dist/features/print/components/BoxLabelPrintView.js +66 -0
- package/dist/features/print/components/LabelProfilePicker.d.ts +13 -0
- package/dist/features/print/components/LabelProfilePicker.js +38 -0
- package/dist/features/print/components/labels.d.ts +117 -0
- package/dist/features/print/components/labels.js +258 -0
- package/dist/features/print/components/labels.style.css +46 -0
- package/dist/features/print/index.d.ts +6 -0
- package/dist/features/print/index.js +16 -0
- package/dist/features/products/columns/productTableColumns.js +5 -4
- package/dist/features/products/components/MarketplaceBundleCard.js +2 -2
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +6 -6
- package/dist/features/products/components/PrizeDrawCollage.js +1 -1
- package/dist/features/products/components/PrizeDrawItemsEditor.js +1 -1
- package/dist/features/products/components/PrizeRevealModal.js +2 -2
- package/dist/features/products/components/ProductDetailPageView.js +18 -4
- package/dist/features/products/components/ProductForm.js +34 -23
- package/dist/features/products/components/ProductGrid.js +86 -62
- package/dist/features/products/constants/card-badges.d.ts +97 -0
- package/dist/features/products/constants/card-badges.js +100 -0
- package/dist/features/products/repository/products.repository.js +34 -1
- package/dist/features/products/schemas/firestore.d.ts +46 -3
- package/dist/features/products/schemas/firestore.js +21 -0
- package/dist/features/promotions/components/PromotionsView.js +1 -1
- package/dist/features/promotions/repository/claimed-coupons.repository.d.ts +32 -0
- package/dist/features/promotions/repository/claimed-coupons.repository.js +58 -0
- package/dist/features/promotions/schemas/firestore.js +30 -3
- package/dist/features/promotions/schemas/index.d.ts +6 -6
- package/dist/features/protection-claims/repository/protection-claims.repository.d.ts +54 -0
- package/dist/features/protection-claims/repository/protection-claims.repository.js +174 -0
- package/dist/features/protection-claims/schemas/firestore.d.ts +168 -0
- package/dist/features/protection-claims/schemas/firestore.js +130 -0
- package/dist/features/reviews/actions/review-actions.js +3 -2
- package/dist/features/reviews/components/ReviewModal.js +1 -1
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/reviews/schemas/firestore.d.ts +20 -1
- package/dist/features/scams/constants/scam-types.d.ts +2 -0
- package/dist/features/scams/constants/scam-types.js +18 -0
- package/dist/features/scams/schemas/report-form.d.ts +3 -3
- package/dist/features/scams/schemas/report-form.js +26 -1
- package/dist/features/search/components/Search.js +9 -9
- package/dist/features/search/components/SearchResultsClient.js +18 -3
- package/dist/features/search/components/SearchResultsPageView.d.ts +1 -6
- package/dist/features/search/components/SearchResultsPageView.js +2 -2
- package/dist/features/seller/actions/offer-actions.js +16 -1
- package/dist/features/seller/actions/seller-actions.js +14 -3
- package/dist/features/seller/components/CategoryInlineSelect.js +75 -11
- package/dist/features/seller/components/PrintCenterView.d.ts +5 -0
- package/dist/features/seller/components/PrintCenterView.js +41 -30
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutRequestView.js +16 -5
- package/dist/features/seller/components/SellerPayoutSettingsView.js +1 -1
- package/dist/features/seller/components/SellerProductShell.d.ts +16 -0
- package/dist/features/seller/components/SellerProductShell.js +123 -13
- package/dist/features/seller/components/SellerReviewsView.js +4 -2
- package/dist/features/seller/components/SellerSidebar.js +1 -1
- package/dist/features/seller/schemas/coupon-form.d.ts +26 -0
- package/dist/features/seller/schemas/coupon-form.js +27 -0
- package/dist/features/seller/schemas/product-form.d.ts +3 -0
- package/dist/features/seller/schemas/product-form.js +5 -0
- package/dist/features/shell/FormShell.js +2 -2
- package/dist/features/shell/QuickFormDrawer.js +14 -0
- package/dist/features/shell/SectionForm.d.ts +19 -0
- package/dist/features/shell/SectionForm.js +133 -9
- package/dist/features/shell/SectionForm.style.css +54 -0
- package/dist/features/shipments/components/AdminShipmentsView.js +16 -1
- package/dist/features/shipments/repository/shipment-items.repository.d.ts +9 -0
- package/dist/features/shipments/repository/shipment-items.repository.js +14 -0
- package/dist/features/site-settings/components/ActionPermissionsManager.js +1 -1
- package/dist/features/sticker-trace/components/StickerCommitPanel.js +1 -1
- package/dist/features/store-extensions/schemas/report-review-form.d.ts +8 -8
- package/dist/features/stores/components/StoreGuideHubView.js +1 -1
- package/dist/features/stores/components/StoreHeader.js +1 -1
- package/dist/features/support/schemas/firestore.d.ts +73 -2
- package/dist/features/support/schemas/firestore.js +59 -0
- package/dist/index.d.ts +16 -24
- package/dist/index.js +38 -47
- package/dist/next/ErrorBoundary.js +1 -1
- package/dist/next/routing/route-map.d.ts +24 -0
- package/dist/next/routing/route-map.js +40 -0
- package/dist/providers/payment-manual/index.d.ts +15 -1
- package/dist/providers/payment-manual/index.js +37 -0
- package/dist/providers/payment-phonepe/index.d.ts +14 -1
- package/dist/providers/payment-phonepe/index.js +36 -0
- package/dist/providers/payment-razorpay/index.d.ts +44 -1
- package/dist/providers/payment-razorpay/index.js +99 -0
- package/dist/providers/shipping-shiprocket/index.d.ts +18 -0
- package/dist/providers/shipping-shiprocket/index.js +18 -0
- package/dist/schemas/registry.d.ts +44 -11
- package/dist/server-entry.d.ts +2 -0
- package/dist/server-entry.js +27 -0
- package/dist/server.d.ts +43 -0
- package/dist/server.js +98 -0
- package/dist/styles.css +418 -149
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +15 -12
- package/dist/tokens/themes/default-light.js +14 -11
- package/dist/tokens/tokens.css +106 -23
- package/dist/ui/DataTable.style.css +4 -4
- package/dist/ui/columns/cell-renderers.d.ts +20 -0
- package/dist/ui/columns/cell-renderers.js +26 -1
- package/dist/ui/columns/index.d.ts +1 -1
- package/dist/ui/columns/index.js +4 -1
- package/dist/ui/components/Badge.style.css +1 -1
- package/dist/ui/components/Breadcrumb.js +19 -1
- package/dist/ui/components/BulkActionBar.style.css +4 -4
- package/dist/ui/components/Button.style.css +1 -1
- package/dist/ui/components/Checkbox.style.css +1 -1
- package/dist/ui/components/FallbackShell.js +1 -1
- package/dist/ui/components/Form.d.ts +14 -1
- package/dist/ui/components/Form.js +2 -2
- package/dist/ui/components/FormField.js +18 -4
- package/dist/ui/components/FormField.style.css +43 -3
- package/dist/ui/components/GatedPrice.style.css +1 -1
- package/dist/ui/components/IconButton.style.css +1 -1
- package/dist/ui/components/Input.js +22 -1
- package/dist/ui/components/Input.style.css +38 -22
- package/dist/ui/components/ListingFilterDrawer.js +1 -1
- package/dist/ui/components/ListingToolbar.js +1 -1
- package/dist/ui/components/PaginatedSelect.js +0 -0
- package/dist/ui/components/Radio.style.css +1 -1
- package/dist/ui/components/Repeater.d.ts +53 -0
- package/dist/ui/components/Repeater.js +7 -0
- package/dist/ui/components/RichTextEditor.d.ts +20 -1
- package/dist/ui/components/RichTextEditor.js +23 -2
- package/dist/ui/components/Select.style.css +7 -21
- package/dist/ui/components/Semantic.js +27 -3
- package/dist/ui/components/TagInput.style.css +4 -9
- package/dist/ui/components/Textarea.style.css +4 -18
- package/dist/ui/components/Toggle.style.css +1 -1
- package/dist/ui/components/Typography.d.ts +3 -3
- package/dist/ui/components/Typography.js +15 -15
- package/dist/ui/components/ViewToggle.style.css +4 -4
- package/dist/ui/forms/AddAnotherToggle.d.ts +16 -0
- package/dist/ui/forms/AddAnotherToggle.js +56 -0
- package/dist/ui/forms/ColorPickerField.js +15 -2
- package/dist/ui/forms/FieldCheckbox.js +15 -2
- package/dist/ui/forms/FieldInput.d.ts +22 -1
- package/dist/ui/forms/FieldInput.js +19 -5
- package/dist/ui/forms/FieldLabel.d.ts +35 -0
- package/dist/ui/forms/FieldLabel.js +70 -0
- package/dist/ui/forms/FieldSelect.d.ts +4 -1
- package/dist/ui/forms/FieldSelect.js +27 -5
- package/dist/ui/forms/FieldTextarea.d.ts +4 -1
- package/dist/ui/forms/FieldTextarea.js +22 -5
- package/dist/ui/forms/FormShell.d.ts +17 -1
- package/dist/ui/forms/FormShell.js +36 -2
- package/dist/ui/forms/FormShell.style.css +41 -33
- package/dist/ui/forms/index.d.ts +5 -1
- package/dist/ui/forms/index.js +2 -0
- package/dist/ui/icons/icon-registry.d.ts +1 -0
- package/dist/ui/icons/icon-registry.js +17 -1
- package/dist/utils/id-generators.d.ts +80 -0
- package/dist/utils/id-generators.js +93 -0
- package/dist/utils/search-txt-builders.d.ts +12 -0
- package/dist/utils/search-txt-builders.js +17 -0
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +106 -5
- package/dist/features/loyalty/api/admin/loyalty/grant/route.d.ts +0 -12
- package/dist/features/loyalty/api/admin/loyalty/grant/route.js +0 -38
- package/dist/features/loyalty/api/balance/route.d.ts +0 -12
- package/dist/features/loyalty/api/balance/route.js +0 -41
- package/dist/features/loyalty/api/earn/route.d.ts +0 -12
- package/dist/features/loyalty/api/earn/route.js +0 -38
- package/dist/features/loyalty/api/history/route.d.ts +0 -12
- package/dist/features/loyalty/api/history/route.js +0 -58
- package/dist/features/loyalty/api/redeem/route.d.ts +0 -12
- package/dist/features/loyalty/api/redeem/route.js +0 -38
- package/dist/features/loyalty/columns/index.d.ts +0 -17
- package/dist/features/loyalty/columns/index.js +0 -40
- package/dist/features/loyalty/components/CoinsDisplay.d.ts +0 -12
- package/dist/features/loyalty/components/CoinsDisplay.js +0 -10
- package/dist/features/loyalty/components/index.d.ts +0 -1
- package/dist/features/loyalty/components/index.js +0 -1
- package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +0 -4
- package/dist/features/loyalty/hooks/useLoyaltyBalance.js +0 -25
- package/dist/features/loyalty/index.d.ts +0 -6
- package/dist/features/loyalty/index.js +0 -6
- package/dist/features/loyalty/manifest.d.ts +0 -2
- package/dist/features/loyalty/manifest.js +0 -16
- package/dist/features/loyalty/messages/en.json +0 -19
- package/dist/features/loyalty/repository/loyalty.repository.d.ts +0 -8
- package/dist/features/loyalty/repository/loyalty.repository.js +0 -22
- package/dist/features/loyalty/schemas/index.d.ts +0 -85
- package/dist/features/loyalty/schemas/index.js +0 -40
- package/dist/features/loyalty/server.d.ts +0 -6
- package/dist/features/loyalty/server.js +0 -6
- package/dist/features/loyalty/types/index.d.ts +0 -31
- package/dist/features/loyalty/types/index.js +0 -1
- package/dist/features/loyalty/types/loyalty-config.d.ts +0 -7
- package/dist/features/loyalty/types/loyalty-config.js +0 -1
- package/dist/features/loyalty/types/loyalty-math.d.ts +0 -9
- package/dist/features/loyalty/types/loyalty-math.js +0 -27
- package/dist/features/products/components/ProductOwnerQuickActions.d.ts +0 -11
- package/dist/features/products/components/ProductOwnerQuickActions.js +0 -120
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import type { BaseDocument } from "../../../_internal/shared/types/base-document";
|
|
2
|
+
export declare const STORAGE_BOXES_COLLECTION = "storageBoxes";
|
|
3
|
+
export declare const INVENTORY_PLACEMENTS_COLLECTION = "inventoryPlacements";
|
|
4
|
+
export declare const INVENTORY_MOVEMENTS_COLLECTION = "inventoryMovements";
|
|
5
|
+
/**
|
|
6
|
+
* The two box sizes actually owned.
|
|
7
|
+
*
|
|
8
|
+
* 🛑 A TS UNION, not a seeded reference list, and this was one of the plan's
|
|
9
|
+
* open questions. The deciding argument is that the LABEL GEOMETRY depends on
|
|
10
|
+
* it: a box label's dimensions are chosen per type, so a third type is a code
|
|
11
|
+
* change in the label profiles whatever the data model says. A seeded list
|
|
12
|
+
* would let an admin create an `AC90` that no label profile can print, and
|
|
13
|
+
* discover it at the printer.
|
|
14
|
+
*
|
|
15
|
+
* Adding a type is therefore deliberately a two-line code change plus a
|
|
16
|
+
* profile, not a form submission.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* How many rows the receive station stages before it must commit.
|
|
20
|
+
*
|
|
21
|
+
* 🛑 THIS IS A FIRESTORE LIMIT, NOT A UI PREFERENCE. A transaction caps at 500
|
|
22
|
+
* writes and each received row is two of them (the placement and its movement
|
|
23
|
+
* row), so 50 rows is 100 writes with ample room for the ledger growing a
|
|
24
|
+
* field later. The whole table commits in ONE transaction because the operator
|
|
25
|
+
* has already physically filled the boxes — a partial write leaves the ledger
|
|
26
|
+
* disagreeing with the shelf and nothing saying which rows landed.
|
|
27
|
+
*
|
|
28
|
+
* 🛑 Declared here so the route and the station cannot disagree. It was a
|
|
29
|
+
* local `MAX_ROWS` in the route and a second literal in the view for one
|
|
30
|
+
* revision, which is the two-owners shape that drifts the moment either moves
|
|
31
|
+
* (Root Cause #42) — and the failure would be silent in the worst direction:
|
|
32
|
+
* a UI cap above the route's gives the operator a full table and a 400.
|
|
33
|
+
*/
|
|
34
|
+
export declare const MAX_RECEIVE_ROWS = 50;
|
|
35
|
+
export declare const BoxTypeValues: readonly ["AC60", "AC30"];
|
|
36
|
+
export type BoxType = (typeof BoxTypeValues)[number];
|
|
37
|
+
/**
|
|
38
|
+
* `retired` rather than deleting: a box's movements are permanent, and a
|
|
39
|
+
* ledger row pointing at a box that no longer exists cannot be read back.
|
|
40
|
+
*/
|
|
41
|
+
export declare const BoxStatusValues: readonly ["active", "full", "retired"];
|
|
42
|
+
export type BoxStatus = (typeof BoxStatusValues)[number];
|
|
43
|
+
/**
|
|
44
|
+
* Why stock moved. Every movement has one.
|
|
45
|
+
*
|
|
46
|
+
* `receive` inbound from a procurement shipment
|
|
47
|
+
* `move` box → box
|
|
48
|
+
* `pick` out of a box, for an order
|
|
49
|
+
* `adjust` a human reconciling a variance they investigated
|
|
50
|
+
* `audit` a count that AGREED — recorded so "last verified" is answerable
|
|
51
|
+
*
|
|
52
|
+
* 🛑 `pick` is MANUAL and does not auto-fire from checkout — the other open
|
|
53
|
+
* question in the plan. An automatic decrement would have the ledger assert a
|
|
54
|
+
* movement nobody performed: the stock is sold, but it is still in the box
|
|
55
|
+
* until someone walks over and takes it out. A ledger that records intentions
|
|
56
|
+
* rather than actions cannot be used to find a missing item, which is its
|
|
57
|
+
* only real job.
|
|
58
|
+
*/
|
|
59
|
+
export declare const MovementKindValues: readonly ["receive", "move", "pick", "adjust", "audit"];
|
|
60
|
+
export type MovementKind = (typeof MovementKindValues)[number];
|
|
61
|
+
export interface StorageBoxDocument extends BaseDocument {
|
|
62
|
+
/**
|
|
63
|
+
* `AC60-03` — what is written on the physical label.
|
|
64
|
+
*
|
|
65
|
+
* 🛑 The id is `storagebox-{code}` and this is a PURE SLUG: a second
|
|
66
|
+
* `AC60-03` *is* the same box. A generated id would let two registry rows
|
|
67
|
+
* describe one physical object, and then "where is this" has two answers
|
|
68
|
+
* with no way to tell which shelf was meant.
|
|
69
|
+
*/
|
|
70
|
+
code: string;
|
|
71
|
+
boxType: BoxType;
|
|
72
|
+
/** The number in the code, denormalised so a list can sort numerically. */
|
|
73
|
+
ordinal: number;
|
|
74
|
+
status: BoxStatus;
|
|
75
|
+
/** Free text — "shelf B, second from top". Deliberately not a taxonomy. */
|
|
76
|
+
location?: string;
|
|
77
|
+
/** "fits ~40 Burst tops" — a human's note, never a computed capacity. */
|
|
78
|
+
capacityNote?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Rollups, for a list that does not fan out one read per box.
|
|
81
|
+
*
|
|
82
|
+
* 🛑 Maintained by a SCHEDULED REPAIR JOB, never a Firestore trigger. A
|
|
83
|
+
* trigger on a collection it also writes back to is Root Cause #92's exact
|
|
84
|
+
* shape — the one that cost 12M invocations against a 2M/month quota,
|
|
85
|
+
* because its no-op guard used `JSON.stringify` on a map whose key order
|
|
86
|
+
* Firestore does not preserve. A scheduled recompute cannot recurse.
|
|
87
|
+
*
|
|
88
|
+
* Treat as ADVISORY. `inventoryPlacements` is the truth; this is a cache.
|
|
89
|
+
*/
|
|
90
|
+
rollup?: {
|
|
91
|
+
distinctProducts: number;
|
|
92
|
+
totalUnits: number;
|
|
93
|
+
computedAt: Date;
|
|
94
|
+
};
|
|
95
|
+
/** Word-prefix search tokens. Derived on write. */
|
|
96
|
+
searchTxt?: string[];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* How many of one product are in one box, right now.
|
|
100
|
+
*
|
|
101
|
+
* 🛑 The id is DETERMINISTIC — `${boxId}__${productId}` — which makes "is X
|
|
102
|
+
* in Y" an O(1) document read and makes the write an idempotent upsert. With
|
|
103
|
+
* a generated id, the same question is a two-field query needing its own
|
|
104
|
+
* composite index, and a double-submit creates a second row for the same
|
|
105
|
+
* pair that silently doubles the count.
|
|
106
|
+
*
|
|
107
|
+
* `__` as the separator because both ids contain `-` (`storagebox-ac60-03`,
|
|
108
|
+
* `product-beyblade-x-dran-sword`), so a single hyphen could not be split
|
|
109
|
+
* back apart.
|
|
110
|
+
*/
|
|
111
|
+
export interface InventoryPlacementDocument extends BaseDocument {
|
|
112
|
+
boxId: string;
|
|
113
|
+
productId: string;
|
|
114
|
+
/** Always ≥ 1. A zero placement is deleted — see the header. */
|
|
115
|
+
quantity: number;
|
|
116
|
+
/** "slot 4", "front left" — optional, free text, for a big box. */
|
|
117
|
+
slot?: string;
|
|
118
|
+
boxCode: string;
|
|
119
|
+
productTitle: string;
|
|
120
|
+
/** The human stock key at the time of placement — what is on the label. */
|
|
121
|
+
productSku?: string;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* One movement. Append-only.
|
|
125
|
+
*
|
|
126
|
+
* 🛑 `quantity` IS ALWAYS POSITIVE. Direction is carried by `from`/`to`, not
|
|
127
|
+
* by the sign — a signed quantity means every reader has to agree on what a
|
|
128
|
+
* negative means, and the first one that disagrees double-counts. A `receive`
|
|
129
|
+
* has no `from`; a `pick` has no `to`; a `move` has both.
|
|
130
|
+
*
|
|
131
|
+
* Immutability is enforced by the repository overriding `update` and `delete`
|
|
132
|
+
* to throw, and by `audit-inventory-ledger-append-only`. A ledger that can be
|
|
133
|
+
* edited is a ledger nobody can use as evidence.
|
|
134
|
+
*/
|
|
135
|
+
export interface InventoryMovementDocument extends BaseDocument {
|
|
136
|
+
kind: MovementKind;
|
|
137
|
+
productId: string;
|
|
138
|
+
/** Always positive. See the header. */
|
|
139
|
+
quantity: number;
|
|
140
|
+
/** Absent on `receive` — stock came from outside the system. */
|
|
141
|
+
fromBoxId?: string;
|
|
142
|
+
/** Absent on `pick` — stock left the system. */
|
|
143
|
+
toBoxId?: string;
|
|
144
|
+
/** When it physically happened, which is not always when it was recorded. */
|
|
145
|
+
occurredAt: Date;
|
|
146
|
+
/** Who did it. A uid, never a name — this collection is not PII-encrypted. */
|
|
147
|
+
actorUid: string;
|
|
148
|
+
/** Required on `adjust`: a variance nobody explained is not reconciled. */
|
|
149
|
+
reason?: string;
|
|
150
|
+
/** The procurement shipment a `receive` came from, when there was one. */
|
|
151
|
+
shipmentId?: string;
|
|
152
|
+
/** Denormalised for a readable ledger. Advisory, like the placement's. */
|
|
153
|
+
productTitle?: string;
|
|
154
|
+
fromBoxCode?: string;
|
|
155
|
+
toBoxCode?: string;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* The deterministic placement id.
|
|
159
|
+
*
|
|
160
|
+
* One definition, used by the repository, the receive station and the seed —
|
|
161
|
+
* a second copy of this string concatenation is a second answer to "is X in
|
|
162
|
+
* Y", and the two would disagree the first time one of them changed.
|
|
163
|
+
*/
|
|
164
|
+
export declare function placementId(boxId: string, productId: string): string;
|
|
165
|
+
/** Field-name constants, so a query never spells a path by hand. */
|
|
166
|
+
export declare const STORAGE_BOX_FIELDS: {
|
|
167
|
+
readonly CODE: "code";
|
|
168
|
+
readonly BOX_TYPE: "boxType";
|
|
169
|
+
readonly ORDINAL: "ordinal";
|
|
170
|
+
readonly STATUS: "status";
|
|
171
|
+
readonly LOCATION: "location";
|
|
172
|
+
readonly SEARCH_TXT: "searchTxt";
|
|
173
|
+
readonly CREATED_AT: "createdAt";
|
|
174
|
+
readonly UPDATED_AT: "updatedAt";
|
|
175
|
+
};
|
|
176
|
+
export declare const INVENTORY_PLACEMENT_FIELDS: {
|
|
177
|
+
readonly BOX_ID: "boxId";
|
|
178
|
+
readonly PRODUCT_ID: "productId";
|
|
179
|
+
readonly QUANTITY: "quantity";
|
|
180
|
+
readonly SLOT: "slot";
|
|
181
|
+
readonly BOX_CODE: "boxCode";
|
|
182
|
+
readonly PRODUCT_TITLE: "productTitle";
|
|
183
|
+
readonly PRODUCT_SKU: "productSku";
|
|
184
|
+
readonly CREATED_AT: "createdAt";
|
|
185
|
+
readonly UPDATED_AT: "updatedAt";
|
|
186
|
+
};
|
|
187
|
+
export declare const INVENTORY_MOVEMENT_FIELDS: {
|
|
188
|
+
readonly KIND: "kind";
|
|
189
|
+
readonly PRODUCT_ID: "productId";
|
|
190
|
+
readonly QUANTITY: "quantity";
|
|
191
|
+
readonly FROM_BOX_ID: "fromBoxId";
|
|
192
|
+
readonly TO_BOX_ID: "toBoxId";
|
|
193
|
+
readonly OCCURRED_AT: "occurredAt";
|
|
194
|
+
readonly ACTOR_UID: "actorUid";
|
|
195
|
+
readonly SHIPMENT_ID: "shipmentId";
|
|
196
|
+
readonly CREATED_AT: "createdAt";
|
|
197
|
+
};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: Stock lives in physical AC60 and AC30 boxes with a label maker, and
|
|
3
|
+
* "where is this" is a question the catalogue could not answer. The
|
|
4
|
+
* previous attempt — `ProductDocument.physicalLocation`, a free-text
|
|
5
|
+
* zone/shelf/bin triple — carried 0 of 1,039 products and had no write
|
|
6
|
+
* path at all, because a location typed once and never moved is not an
|
|
7
|
+
* inventory system. A box registry plus an append-only move ledger is.
|
|
8
|
+
*
|
|
9
|
+
* WHAT: Three TOP-LEVEL collections.
|
|
10
|
+
*
|
|
11
|
+
* storageBoxes/{storagebox-slug} one physical box
|
|
12
|
+
* inventoryPlacements/{boxId__prodId} how many of X are in Y, right now
|
|
13
|
+
* inventoryMovements/{auto} every move, immutable
|
|
14
|
+
*
|
|
15
|
+
* ── 🛑 TOP-LEVEL, NOT SUBCOLLECTIONS, and the reason is structural ─────────
|
|
16
|
+
*
|
|
17
|
+
* `BaseRepository.getCollection()` returns a `CollectionReference` and every
|
|
18
|
+
* write method depends on it, while `collectionGroup()` returns a `Query`.
|
|
19
|
+
* Measured: the repo has 685 `COLLECTION` indexes, 3 `COLLECTION_GROUP`
|
|
20
|
+
* indexes, and **zero `collectionGroup(` call sites** — all three of those
|
|
21
|
+
* indexes are dead. A subcollection here would mean hand-rolling the
|
|
22
|
+
* repository base and losing PII encryption, `searchTxt` and `mapDoc` with it.
|
|
23
|
+
*
|
|
24
|
+
* ── 🛑 A ZERO-QUANTITY PLACEMENT IS DELETED, NEVER STORED AT ZERO ──────────
|
|
25
|
+
*
|
|
26
|
+
* Keeping zeros forces every "what is in this box" read to pair
|
|
27
|
+
* `quantity > 0` with an `orderBy`, and Firestore appends an inequality's
|
|
28
|
+
* field to the sort implicitly — so it demands a composite index in an order
|
|
29
|
+
* nobody declares, fails with FAILED_PRECONDITION, and every caller in this
|
|
30
|
+
* codebase wraps such a read in `.catch(() => null)`. That renders as an
|
|
31
|
+
* EMPTY BOX rather than an error (Root Cause #59). Absence means zero.
|
|
32
|
+
*
|
|
33
|
+
* ── 🛑 NO STOCK RECONCILIATION. `stockQuantity` STAYS AUTHORITATIVE ───────
|
|
34
|
+
*
|
|
35
|
+
* This system never writes it. Deriving it would write the left side of
|
|
36
|
+
* `resolveStockResync`'s invariant (`reserved = prevStock − prevAvailable`)
|
|
37
|
+
* from a measurement blind to reservations, handing reserved units back to
|
|
38
|
+
* the shelf. And a nightly reconciler would be Root Cause #102 verbatim: a
|
|
39
|
+
* three-way state (authored / reserved / located) against one number cannot
|
|
40
|
+
* distinguish "3 are lost" from "3 are on the photography table". Variance is
|
|
41
|
+
* a REPORT a human resolves with an `adjust` movement.
|
|
42
|
+
*
|
|
43
|
+
* EXPORTS: STORAGE_BOXES_COLLECTION, INVENTORY_PLACEMENTS_COLLECTION,
|
|
44
|
+
* INVENTORY_MOVEMENTS_COLLECTION, BoxTypeValues, BoxType, BoxStatusValues,
|
|
45
|
+
* BoxStatus, MovementKindValues, MovementKind, StorageBoxDocument,
|
|
46
|
+
* InventoryPlacementDocument, InventoryMovementDocument, placementId,
|
|
47
|
+
* STORAGE_BOX_FIELDS, INVENTORY_PLACEMENT_FIELDS, INVENTORY_MOVEMENT_FIELDS
|
|
48
|
+
*
|
|
49
|
+
* @tag domain:inventory
|
|
50
|
+
* @tag layer:feature
|
|
51
|
+
* @tag pattern:firestore-schema
|
|
52
|
+
* @tag access:server
|
|
53
|
+
* @tag sideEffects:none
|
|
54
|
+
*/
|
|
55
|
+
export const STORAGE_BOXES_COLLECTION = "storageBoxes";
|
|
56
|
+
export const INVENTORY_PLACEMENTS_COLLECTION = "inventoryPlacements";
|
|
57
|
+
export const INVENTORY_MOVEMENTS_COLLECTION = "inventoryMovements";
|
|
58
|
+
/**
|
|
59
|
+
* The two box sizes actually owned.
|
|
60
|
+
*
|
|
61
|
+
* 🛑 A TS UNION, not a seeded reference list, and this was one of the plan's
|
|
62
|
+
* open questions. The deciding argument is that the LABEL GEOMETRY depends on
|
|
63
|
+
* it: a box label's dimensions are chosen per type, so a third type is a code
|
|
64
|
+
* change in the label profiles whatever the data model says. A seeded list
|
|
65
|
+
* would let an admin create an `AC90` that no label profile can print, and
|
|
66
|
+
* discover it at the printer.
|
|
67
|
+
*
|
|
68
|
+
* Adding a type is therefore deliberately a two-line code change plus a
|
|
69
|
+
* profile, not a form submission.
|
|
70
|
+
*/
|
|
71
|
+
/**
|
|
72
|
+
* How many rows the receive station stages before it must commit.
|
|
73
|
+
*
|
|
74
|
+
* 🛑 THIS IS A FIRESTORE LIMIT, NOT A UI PREFERENCE. A transaction caps at 500
|
|
75
|
+
* writes and each received row is two of them (the placement and its movement
|
|
76
|
+
* row), so 50 rows is 100 writes with ample room for the ledger growing a
|
|
77
|
+
* field later. The whole table commits in ONE transaction because the operator
|
|
78
|
+
* has already physically filled the boxes — a partial write leaves the ledger
|
|
79
|
+
* disagreeing with the shelf and nothing saying which rows landed.
|
|
80
|
+
*
|
|
81
|
+
* 🛑 Declared here so the route and the station cannot disagree. It was a
|
|
82
|
+
* local `MAX_ROWS` in the route and a second literal in the view for one
|
|
83
|
+
* revision, which is the two-owners shape that drifts the moment either moves
|
|
84
|
+
* (Root Cause #42) — and the failure would be silent in the worst direction:
|
|
85
|
+
* a UI cap above the route's gives the operator a full table and a 400.
|
|
86
|
+
*/
|
|
87
|
+
export const MAX_RECEIVE_ROWS = 50;
|
|
88
|
+
export const BoxTypeValues = ["AC60", "AC30"];
|
|
89
|
+
/**
|
|
90
|
+
* `retired` rather than deleting: a box's movements are permanent, and a
|
|
91
|
+
* ledger row pointing at a box that no longer exists cannot be read back.
|
|
92
|
+
*/
|
|
93
|
+
export const BoxStatusValues = ["active", "full", "retired"];
|
|
94
|
+
/**
|
|
95
|
+
* Why stock moved. Every movement has one.
|
|
96
|
+
*
|
|
97
|
+
* `receive` inbound from a procurement shipment
|
|
98
|
+
* `move` box → box
|
|
99
|
+
* `pick` out of a box, for an order
|
|
100
|
+
* `adjust` a human reconciling a variance they investigated
|
|
101
|
+
* `audit` a count that AGREED — recorded so "last verified" is answerable
|
|
102
|
+
*
|
|
103
|
+
* 🛑 `pick` is MANUAL and does not auto-fire from checkout — the other open
|
|
104
|
+
* question in the plan. An automatic decrement would have the ledger assert a
|
|
105
|
+
* movement nobody performed: the stock is sold, but it is still in the box
|
|
106
|
+
* until someone walks over and takes it out. A ledger that records intentions
|
|
107
|
+
* rather than actions cannot be used to find a missing item, which is its
|
|
108
|
+
* only real job.
|
|
109
|
+
*/
|
|
110
|
+
export const MovementKindValues = [
|
|
111
|
+
"receive",
|
|
112
|
+
"move",
|
|
113
|
+
"pick",
|
|
114
|
+
"adjust",
|
|
115
|
+
"audit",
|
|
116
|
+
];
|
|
117
|
+
/**
|
|
118
|
+
* The deterministic placement id.
|
|
119
|
+
*
|
|
120
|
+
* One definition, used by the repository, the receive station and the seed —
|
|
121
|
+
* a second copy of this string concatenation is a second answer to "is X in
|
|
122
|
+
* Y", and the two would disagree the first time one of them changed.
|
|
123
|
+
*/
|
|
124
|
+
export function placementId(boxId, productId) {
|
|
125
|
+
return `${boxId}__${productId}`;
|
|
126
|
+
}
|
|
127
|
+
/** Field-name constants, so a query never spells a path by hand. */
|
|
128
|
+
export const STORAGE_BOX_FIELDS = {
|
|
129
|
+
CODE: "code",
|
|
130
|
+
BOX_TYPE: "boxType",
|
|
131
|
+
ORDINAL: "ordinal",
|
|
132
|
+
STATUS: "status",
|
|
133
|
+
LOCATION: "location",
|
|
134
|
+
SEARCH_TXT: "searchTxt",
|
|
135
|
+
CREATED_AT: "createdAt",
|
|
136
|
+
UPDATED_AT: "updatedAt",
|
|
137
|
+
};
|
|
138
|
+
export const INVENTORY_PLACEMENT_FIELDS = {
|
|
139
|
+
BOX_ID: "boxId",
|
|
140
|
+
PRODUCT_ID: "productId",
|
|
141
|
+
QUANTITY: "quantity",
|
|
142
|
+
SLOT: "slot",
|
|
143
|
+
BOX_CODE: "boxCode",
|
|
144
|
+
PRODUCT_TITLE: "productTitle",
|
|
145
|
+
PRODUCT_SKU: "productSku",
|
|
146
|
+
CREATED_AT: "createdAt",
|
|
147
|
+
UPDATED_AT: "updatedAt",
|
|
148
|
+
};
|
|
149
|
+
export const INVENTORY_MOVEMENT_FIELDS = {
|
|
150
|
+
KIND: "kind",
|
|
151
|
+
PRODUCT_ID: "productId",
|
|
152
|
+
QUANTITY: "quantity",
|
|
153
|
+
FROM_BOX_ID: "fromBoxId",
|
|
154
|
+
TO_BOX_ID: "toBoxId",
|
|
155
|
+
OCCURRED_AT: "occurredAt",
|
|
156
|
+
ACTOR_UID: "actorUid",
|
|
157
|
+
SHIPMENT_ID: "shipmentId",
|
|
158
|
+
CREATED_AT: "createdAt",
|
|
159
|
+
};
|
|
@@ -59,6 +59,17 @@ export interface AppLayoutShellProps {
|
|
|
59
59
|
homeHref: string;
|
|
60
60
|
shopHref: string;
|
|
61
61
|
footer: FooterLayoutProps;
|
|
62
|
+
/**
|
|
63
|
+
* Render the public marketing footer. Defaults to `true`.
|
|
64
|
+
*
|
|
65
|
+
* Pass `false` on a dashboard. `footer` stays REQUIRED either way, so the
|
|
66
|
+
* consumer keeps one code path and there is no "which half did I forget"
|
|
67
|
+
* state — this only decides whether it is shown.
|
|
68
|
+
*
|
|
69
|
+
* 🛑 It also moves the bottom-chrome reservation: the footer owns it when
|
|
70
|
+
* rendered, `<Main>` owns it when not. See the comment on `<Main>`.
|
|
71
|
+
*/
|
|
72
|
+
showFooter?: boolean;
|
|
62
73
|
searchSlot?: React.ReactNode;
|
|
63
74
|
/** Render-prop alternative to searchSlot — receives onClose so the slot can close the overlay. */
|
|
64
75
|
searchSlotRenderer?: (onClose: () => void) => React.ReactNode;
|
|
@@ -137,4 +148,4 @@ export interface AppLayoutShellProps {
|
|
|
137
148
|
};
|
|
138
149
|
};
|
|
139
150
|
}
|
|
140
|
-
export declare function AppLayoutShell({ children, navItems, sidebarItems, sidebarSections, sidebarPrimaryActions, sidebarTitle, hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, messagesHref, unreadMessageCount, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle, suppressDashboardNav, hideSidebarToggle, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar, sidebarProfileLabels, eventBannerSlot, showBottomNav, contentClassName, lightBackground, darkBackground, }: AppLayoutShellProps): React.JSX.Element;
|
|
151
|
+
export declare function AppLayoutShell({ children, navItems, sidebarItems, sidebarSections, sidebarPrimaryActions, sidebarTitle, hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, messagesHref, unreadMessageCount, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, showFooter, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle, suppressDashboardNav, hideSidebarToggle, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar, sidebarProfileLabels, eventBannerSlot, showBottomNav, contentClassName, lightBackground, darkBackground, }: AppLayoutShellProps): React.JSX.Element;
|
|
@@ -120,7 +120,7 @@ function CollapsibleSidebarSection({ section, navItemClass, navItemActiveClass,
|
|
|
120
120
|
return (_jsxs(Stack, { gap: "none", className: "", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex w-full items-center justify-between px-[var(--appkit-space-1)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-semibold uppercase tracking-wider text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text-muted)] transition-colors", children: [_jsx(Span, { children: section.title }), _jsx("svg", { className: `w-3.5 h-3.5 transition-transform duration-200 ${open ? "rotate-180" : ""} shrink-0`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })] }), open && (_jsx(SidebarSectionLinks, { items: section.items, activeHref: activeHref, activeItem: activeItem, navItemClass: navItemClass, navItemActiveClass: navItemActiveClass }))] }));
|
|
121
121
|
}
|
|
122
122
|
/** Sidebar header when a user is logged in — avatar + display name + close button. */
|
|
123
|
-
function SidebarUserHeader({ user, onClose, }) {
|
|
123
|
+
function SidebarUserHeader({ user, onClose, profileHref, }) {
|
|
124
124
|
return (_jsxs(Row, { align: "center", justify: "between", gap: "3", children: [_jsxs(Row, { className: "flex-1 min-w-0", align: "center", gap: "3", children: [_jsxs(Div, { className: "flex-shrink-0 relative", children: [_jsx(AvatarDisplay, { cropData: user.avatarMetadata
|
|
125
125
|
? {
|
|
126
126
|
url: user.avatarMetadata.url,
|
|
@@ -129,11 +129,11 @@ function SidebarUserHeader({ user, onClose, }) {
|
|
|
129
129
|
}
|
|
130
130
|
: user.photoURL
|
|
131
131
|
? { url: user.photoURL, position: { x: 50, y: 50 }, zoom: 1 }
|
|
132
|
-
: null, size: "md", alt: user.displayName || "User", displayName: user.displayName, email: user.email }), user.role && !isBuyerUser(user) && (_jsx(Row, { textWeight: "bold", className: `absolute -bottom-0.5 -right-0.5 w-4 h-4 border-2 border-white text-white text-[9px] leading-none select-none ${ROLE_DOT_BG_CLASS[user.role] ?? "bg-[var(--appkit-color-text-muted)]"}`, align: "center", justify: "center", rounded: "full", title: user.role.charAt(0).toUpperCase() + user.role.slice(1), "aria-label": user.role, children: user.role.charAt(0).toUpperCase() }))] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "truncate", color: "primary", size: "sm", weight: "medium", children: user.displayName || "User" }), _jsx(Text, { className: "truncate", color: "muted", size: "xs", children: user.email || "" })] })] }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: onClose, className: "flex-shrink-0 rounded-full p-[var(--appkit-space-2)]
|
|
132
|
+
: null, size: "md", alt: user.displayName || "User", displayName: user.displayName, email: user.email }), user.role && !isBuyerUser(user) && (_jsx(Row, { textWeight: "bold", className: `absolute -bottom-0.5 -right-0.5 w-4 h-4 border-2 border-white text-white text-[9px] leading-none select-none ${ROLE_DOT_BG_CLASS[user.role] ?? "bg-[var(--appkit-color-text-muted)]"}`, align: "center", justify: "center", rounded: "full", title: user.role.charAt(0).toUpperCase() + user.role.slice(1), "aria-label": user.role, children: user.role.charAt(0).toUpperCase() })), profileHref && (_jsx(TextLink, { href: profileHref, variant: "none", onClick: onClose, className: "absolute inset-0 rounded-full", children: _jsx(Span, { className: "sr-only", children: "View your profile" }) }))] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "truncate", color: "primary", size: "sm", weight: "medium", children: user.displayName || "User" }), _jsx(Text, { className: "truncate", color: "muted", size: "xs", children: user.email || "" })] })] }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: onClose, className: "flex-shrink-0 rounded-full p-[var(--appkit-space-2)] hover:bg-surface-hover hover:text-zinc-900 text-[var(--appkit-color-text-muted)] dark:hover:text-zinc-100 transition-all hover:rotate-90", children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }));
|
|
133
133
|
}
|
|
134
134
|
/** Sidebar header when no user is logged in — title + close button. */
|
|
135
135
|
function SidebarGuestHeader({ sidebarTitle, onClose, }) {
|
|
136
|
-
return (_jsxs(Row, { align: "center", justify: "between", children: [_jsx(Div, { textWeight: "semibold", textSize: "sm", color: "primary", children: sidebarTitle }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: onClose, className: "rounded-full p-[var(--appkit-space-2)]
|
|
136
|
+
return (_jsxs(Row, { align: "center", justify: "between", children: [_jsx(Div, { textWeight: "semibold", textSize: "sm", color: "primary", children: sidebarTitle }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: onClose, className: "rounded-full p-[var(--appkit-space-2)] hover:bg-surface-hover hover:text-zinc-900 text-[var(--appkit-color-text-muted)] dark:hover:text-zinc-100 transition-all hover:rotate-90", children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }));
|
|
137
137
|
}
|
|
138
138
|
function SidebarContent({ sidebarItems, sidebarSections, sidebarPrimaryActions, user, activeHref, profileHref, userOrdersHref, userWishlistHref, userSettingsHref, adminHref, storeHref, sellerHref, sidebarLocaleSlot, showThemeToggleInSidebar, sidebarProfileLabels, theme, activeThemeName, toggleTheme, onLogout, onAfterLogout, }) {
|
|
139
139
|
const hasLegacyItems = sidebarItems.length > 0;
|
|
@@ -177,10 +177,10 @@ function SidebarContent({ sidebarItems, sidebarSections, sidebarPrimaryActions,
|
|
|
177
177
|
action.variant === "outline"
|
|
178
178
|
? "border hover:bg-surface-hover border-[var(--appkit-color-border)] text-[var(--appkit-color-text)]"
|
|
179
179
|
: "bg-primary text-white hover:bg-primary-600 dark:bg-primary dark:hover:bg-primary-600 btn-glow",
|
|
180
|
-
].join(" "), children: action.label }, `${action.href}-${action.label}`))) })), isAuthenticated && (_jsx(CollapsibleNavGroup, { title: labels.sectionTitle, hasActive: !!activeProfileLink, children: _jsxs(Ul, { spacing: "2xs", children: [_jsx(Li, { children: _jsx(TextLink, { href: profileHref, variant: "none", className: activeProfileLink?.href === profileHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === profileHref ? "page" : undefined, children: labels.profile }) }), userOrdersHref && (_jsx(Li, { children: _jsx(TextLink, { href: userOrdersHref, variant: "none", className: activeProfileLink?.href === userOrdersHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userOrdersHref ? "page" : undefined, children: labels.orders }) })), userWishlistHref && (_jsx(Li, { children: _jsx(TextLink, { href: userWishlistHref, variant: "none", className: activeProfileLink?.href === userWishlistHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userWishlistHref ? "page" : undefined, children: labels.wishlist }) })), userSettingsHref && (_jsx(Li, { children: _jsx(TextLink, { href: userSettingsHref, variant: "none", className: activeProfileLink?.href === userSettingsHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userSettingsHref ? "page" : undefined, children: labels.settings }) }))] }) })), isAuthenticated && user?.stats && (_jsxs(Div, { layout: "grid", gap: "2", className: "grid-cols-2", children: [user.stats.totalOrders != null && (_jsxs(
|
|
180
|
+
].join(" "), children: action.label }, `${action.href}-${action.label}`))) })), isAuthenticated && (_jsx(CollapsibleNavGroup, { title: labels.sectionTitle, hasActive: !!activeProfileLink, children: _jsxs(Ul, { spacing: "2xs", children: [_jsx(Li, { children: _jsx(TextLink, { href: profileHref, variant: "none", className: activeProfileLink?.href === profileHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === profileHref ? "page" : undefined, children: labels.profile }) }), userOrdersHref && (_jsx(Li, { children: _jsx(TextLink, { href: userOrdersHref, variant: "none", className: activeProfileLink?.href === userOrdersHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userOrdersHref ? "page" : undefined, children: labels.orders }) })), userWishlistHref && (_jsx(Li, { children: _jsx(TextLink, { href: userWishlistHref, variant: "none", className: activeProfileLink?.href === userWishlistHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userWishlistHref ? "page" : undefined, children: labels.wishlist }) })), userSettingsHref && (_jsx(Li, { children: _jsx(TextLink, { href: userSettingsHref, variant: "none", className: activeProfileLink?.href === userSettingsHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userSettingsHref ? "page" : undefined, children: labels.settings }) }))] }) })), isAuthenticated && user?.stats && (_jsxs(Div, { layout: "grid", gap: "2", className: "grid-cols-2", children: [user.stats.totalOrders != null && userOrdersHref && (_jsxs(TextLink, { href: userOrdersHref, variant: "none", className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.totalOrders }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Orders" })] })), user.stats.reviewsCount != null && (_jsxs(TextLink, { href: `${profileHref}#reviews`, variant: "none", className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.reviewsCount }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Reviews" })] })), user.stats.auctionsWon != null && userOrdersHref && (_jsxs(TextLink, { href: `${userOrdersHref}?orderType=auction`, variant: "none", className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.auctionsWon }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Auctions Won" })] })), user.stats.itemsSold != null && resolvedStoreHref && (_jsxs(TextLink, { href: resolvedStoreHref, variant: "none", className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.itemsSold }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Items Sold" })] }))] })), isAuthenticated && isAdminOrSeller && (adminHref || resolvedStoreHref) && (_jsx(CollapsibleNavGroup, { title: labels.dashboardSectionTitle, hasActive: !!activeDashboardLink, children: _jsxs(Ul, { spacing: "2xs", children: [adminHref && role === "admin" && (_jsx(Li, { children: _jsx(TextLink, { href: adminHref, variant: "none", className: activeDashboardLink?.href === adminHref ? navItemActiveClass : navItemClass, "aria-current": activeDashboardLink?.href === adminHref ? "page" : undefined, children: labels.adminDashboard }) })), resolvedStoreHref && isAdminOrSeller && (_jsx(Li, { children: _jsx(TextLink, { href: resolvedStoreHref, variant: "none", className: activeDashboardLink?.href === resolvedStoreHref ? navItemActiveClass : navItemClass, "aria-current": activeDashboardLink?.href === resolvedStoreHref ? "page" : undefined, children: labels.storeDashboard }) }))] }) })), normalizedSections.map((section, sectionIndex) => (_jsx(CollapsibleSidebarSection, { section: section, navItemClass: navItemClass, navItemActiveClass: navItemActiveClass, activeHref: activeHref }, `sidebar-section-${sectionIndex}`))), (sidebarLocaleSlot || showThemeToggleInSidebar || (isAuthenticated && onLogout)) && (_jsxs(Stack, { border: "default", className: "border-t border-[var(--appkit-color-border-subtle)]", padding: "t-md", gap: "3", children: [sidebarLocaleSlot, showThemeToggleInSidebar && (_jsxs("button", { type: "button", onClick: toggleTheme, className: "flex w-full items-center justify-end gap-[var(--appkit-space-3)] rounded-lg px-[var(--appkit-space-3)] py-[var(--appkit-space-2)] text-[length:var(--appkit-text-sm)] text-[var(--appkit-color-text-muted)] transition-colors hover:bg-primary-surface hover:text-primary-800 dark:hover:text-primary-200", children: [_jsx(Span, { "aria-hidden": "true", children: theme === "dark" ? "☀️" : "🌙" }), activeThemeName] })), isAuthenticated && onLogout && (_jsx("button", { type: "button", onClick: () => { onLogout(); onAfterLogout(); }, className: CLS_LOGOUT_BTN, children: labels.logout }))] }))] }));
|
|
181
181
|
}
|
|
182
182
|
// ─── Main component ────────────────────────────────────────────────────────────
|
|
183
|
-
export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarSections, sidebarPrimaryActions, sidebarTitle = "Navigation", hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, messagesHref, unreadMessageCount, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle = false, suppressDashboardNav = false, hideSidebarToggle = false, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar = false, sidebarProfileLabels, eventBannerSlot, showBottomNav = true, contentClassName, lightBackground = DEFAULT_LIGHT_BG, darkBackground = DEFAULT_DARK_BG, }) {
|
|
183
|
+
export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarSections, sidebarPrimaryActions, sidebarTitle = "Navigation", hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, messagesHref, unreadMessageCount, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, showFooter = true, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle = false, suppressDashboardNav = false, hideSidebarToggle = false, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar = false, sidebarProfileLabels, eventBannerSlot, showBottomNav = true, contentClassName, lightBackground = DEFAULT_LIGHT_BG, darkBackground = DEFAULT_DARK_BG, }) {
|
|
184
184
|
// QueryClientProvider used to be created here so AppLayoutShell could stand
|
|
185
185
|
// alone. The real cause of the 2026-06-10/11 "No QueryClient set" prod crash
|
|
186
186
|
// turned out to be a peer-dep duplicate of @tanstack/query-core under
|
|
@@ -247,12 +247,18 @@ export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarS
|
|
|
247
247
|
opacity: darkBackground.overlay?.opacity ?? 0,
|
|
248
248
|
},
|
|
249
249
|
};
|
|
250
|
-
return (_jsx(_Fragment, { children: _jsxs(Stack, { className: "min-h-screen w-full overflow-x-clip transition-colors duration-300", children: [_jsx(BackgroundRenderer, { mode: theme === "dark" ? "dark" : "light", lightMode: normalizedLightBackground, darkMode: normalizedDarkBackground }), _jsx(Div, { id: TOP_BANNER_SLOT_ID, className: "w-full" }), _jsxs(Div, { ref: headerRef, className: "sticky top-0 z-50 w-full", children: [_jsx(TitleBar, { onToggleSidebar: handleTogglePublicSidebar, sidebarOpen: sidebarOpen, onSearchToggle: () => setSearchOpen((prev) => !prev), searchOpen: searchOpen, brandName: brandName, brandShortName: brandShortName, siteLogoUrl: siteLogoUrl, logoHref: logoHref, promotionsHref: promotionsHref, cartHref: cartHref, wishlistHref: wishlistHref, messagesHref: messagesHref, unreadMessageCount: unreadMessageCount, userId: userId, profileHref: profileHref, loginHref: loginHref, registerHref: registerHref, user: user, navSlot: titleBarNavSlot, notificationSlot: titleBarNotificationSlot, devSlot: titleBarDevSlot, promoStripText: titleBarPromoStripText, isDark: theme === "dark", onToggleTheme: showThemeToggle ? toggleTheme : undefined, onBeforeToggleDashboardNav: handleBeforeDashboardNavToggle, suppressDashboardNav: suppressDashboardNav, hideSidebarToggle: hideSidebarToggle }), _jsx(NavbarWithSettings, { navItems: navItems, hiddenNavItems: hiddenNavItems, permissions: authUser?.permissions }), searchOpen && (searchSlotRenderer ? searchSlotRenderer(() => setSearchOpen(false)) : searchSlot), eventBannerSlot] }), _jsx(AutoBreadcrumbs, {}), _jsxs(Div, { layout: "flex", className: "relative w-full flex-1 overflow-x-clip", children: [_jsx(SidebarLayout, { isOpen: sidebarOpen, ariaLabel: "Secondary navigation", header: user ? (_jsx(SidebarUserHeader, { user: user, onClose: () => setSidebarOpen(false) })) : (_jsx(SidebarGuestHeader, { sidebarTitle: sidebarTitle, onClose: () => setSidebarOpen(false) })), onClose: () => setSidebarOpen(false), children: sidebarContent }), _jsx(Main, { id: "main-content",
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
//
|
|
255
|
-
//
|
|
250
|
+
return (_jsx(_Fragment, { children: _jsxs(Stack, { className: "min-h-screen w-full overflow-x-clip transition-colors duration-300", children: [_jsx(BackgroundRenderer, { mode: theme === "dark" ? "dark" : "light", lightMode: normalizedLightBackground, darkMode: normalizedDarkBackground }), _jsx(Div, { id: TOP_BANNER_SLOT_ID, className: "w-full" }), _jsxs(Div, { ref: headerRef, className: "sticky top-0 z-50 w-full", children: [_jsx(TitleBar, { onToggleSidebar: handleTogglePublicSidebar, sidebarOpen: sidebarOpen, onSearchToggle: () => setSearchOpen((prev) => !prev), searchOpen: searchOpen, brandName: brandName, brandShortName: brandShortName, siteLogoUrl: siteLogoUrl, logoHref: logoHref, promotionsHref: promotionsHref, cartHref: cartHref, wishlistHref: wishlistHref, messagesHref: messagesHref, unreadMessageCount: unreadMessageCount, userId: userId, profileHref: profileHref, loginHref: loginHref, registerHref: registerHref, user: user, navSlot: titleBarNavSlot, notificationSlot: titleBarNotificationSlot, devSlot: titleBarDevSlot, promoStripText: titleBarPromoStripText, isDark: theme === "dark", onToggleTheme: showThemeToggle ? toggleTheme : undefined, onBeforeToggleDashboardNav: handleBeforeDashboardNavToggle, suppressDashboardNav: suppressDashboardNav, hideSidebarToggle: hideSidebarToggle }), _jsx(NavbarWithSettings, { navItems: navItems, hiddenNavItems: hiddenNavItems, permissions: authUser?.permissions }), searchOpen && (searchSlotRenderer ? searchSlotRenderer(() => setSearchOpen(false)) : searchSlot), eventBannerSlot] }), _jsx(AutoBreadcrumbs, {}), _jsxs(Div, { layout: "flex", className: "relative w-full flex-1 overflow-x-clip", children: [_jsx(SidebarLayout, { isOpen: sidebarOpen, ariaLabel: "Secondary navigation", header: user ? (_jsx(SidebarUserHeader, { user: user, onClose: () => setSidebarOpen(false), profileHref: profileHref })) : (_jsx(SidebarGuestHeader, { sidebarTitle: sidebarTitle, onClose: () => setSidebarOpen(false) })), onClose: () => setSidebarOpen(false), children: sidebarContent }), _jsx(Main, { id: "main-content",
|
|
251
|
+
// Bottom-chrome clearance belongs to whichever element is LAST.
|
|
252
|
+
//
|
|
253
|
+
// With the footer rendered it is the footer's, and a margin here
|
|
254
|
+
// would only gap main-to-footer — it would never clear the bottom
|
|
255
|
+
// of the page, which is what the fixed nav + tier actually
|
|
256
|
+
// overlap. That is why this carried no bottom padding.
|
|
257
|
+
//
|
|
258
|
+
// With the footer SUPPRESSED (`showFooter={false}`, which is every
|
|
259
|
+
// dashboard page) `<Main>` becomes the last element, so the same
|
|
260
|
+
// reasoning puts the reservation here instead. Exactly one of the
|
|
261
|
+
// two owns it at a time; both would add a screen of dead space.
|
|
256
262
|
//
|
|
257
263
|
// The TOP tier is the mirror image and does belong here: at `lg` the
|
|
258
264
|
// chrome tier hangs under the header as a fixed bar, so without this
|
|
@@ -260,5 +266,12 @@ export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarS
|
|
|
260
266
|
// is 0 below `lg` and 0 whenever no bar is published, so this
|
|
261
267
|
// reserves exactly nothing until there is something to reserve —
|
|
262
268
|
// which is why it can be unconditional rather than route-gated.
|
|
263
|
-
className:
|
|
269
|
+
className: [
|
|
270
|
+
"w-full flex-1 flex flex-col pt-[var(--top-chrome-height,0px)] transition-[padding-top] duration-300 ease-out",
|
|
271
|
+
showFooter
|
|
272
|
+
? ""
|
|
273
|
+
: "pb-[calc(var(--bottom-nav-height,4rem)+var(--bottom-chrome-height,0px))]",
|
|
274
|
+
]
|
|
275
|
+
.filter(Boolean)
|
|
276
|
+
.join(" "), children: _jsx(Div, { padding: contentClassName ? "none" : "y-lg", className: `flex-1 ${contentClassName ?? "mx-auto w-full max-w-screen-xl px-[var(--appkit-space-5)] md:px-[var(--appkit-space-6)] lg:px-[var(--appkit-space-8)]"}`, children: children }) })] }), _jsx(BackToTop, {}), showFooter && _jsx(FooterLayout, { ...footer }), _jsx(BottomChrome, { children: _jsx(BottomActions, {}) }), _jsx(SideActionDock, {}), showBottomNav && (_jsx(BottomNavbar, { user: user, userId: userId, homeHref: homeHref, shopHref: shopHref, cartHref: cartHref, wishlistHref: wishlistHref, profileHref: profileHref, loginHref: loginHref, onSearchToggle: () => setSearchOpen((prev) => !prev), navItems: navItems, onMoreToggle: handleTogglePublicSidebar })), _jsx(UnsavedChangesModal, {})] }) }));
|
|
264
277
|
}
|