@mohasinac/appkit 4.62.0 → 4.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.build-stamp.json +3 -3
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -29
- package/dist/_internal/client/features/layout/filterNavItems.d.ts +28 -0
- package/dist/_internal/client/features/layout/filterNavItems.js +35 -0
- package/dist/_internal/server/features/ads/booking.d.ts +118 -0
- package/dist/_internal/server/features/ads/booking.js +326 -0
- package/dist/_internal/server/features/checkout/actions.d.ts +129 -9
- package/dist/_internal/server/features/checkout/actions.js +850 -79
- package/dist/_internal/server/features/checkout/expand-order-items.d.ts +1 -2
- package/dist/_internal/server/features/checkout/expand-order-items.js +32 -0
- package/dist/_internal/server/features/checkout/freeze-parts.d.ts +50 -0
- package/dist/_internal/server/features/checkout/freeze-parts.js +94 -0
- package/dist/_internal/server/features/checkout/value-otp-gate.d.ts +55 -0
- package/dist/_internal/server/features/checkout/value-otp-gate.js +60 -0
- package/dist/_internal/server/features/dashboard/attention.d.ts +128 -0
- package/dist/_internal/server/features/dashboard/attention.js +183 -0
- package/dist/_internal/server/features/dashboard/data.d.ts +47 -0
- package/dist/_internal/server/features/dashboard/data.js +82 -0
- package/dist/_internal/server/features/inventory/reservations.d.ts +99 -0
- package/dist/_internal/server/features/inventory/reservations.js +273 -0
- package/dist/_internal/server/features/invoicing/allocate.d.ts +63 -0
- package/dist/_internal/server/features/invoicing/allocate.js +162 -0
- package/dist/_internal/server/features/invoicing/credit-note.d.ts +57 -0
- package/dist/_internal/server/features/invoicing/credit-note.js +126 -0
- package/dist/_internal/server/features/invoicing/gstr1.d.ts +74 -0
- package/dist/_internal/server/features/invoicing/gstr1.js +251 -0
- package/dist/_internal/server/features/invoicing/issue.d.ts +96 -0
- package/dist/_internal/server/features/invoicing/issue.js +202 -0
- package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
- package/dist/_internal/server/features/offers/destinations.js +65 -0
- package/dist/_internal/server/features/orders/actions.d.ts +8 -1
- package/dist/_internal/server/features/orders/actions.js +81 -8
- package/dist/_internal/server/features/orders/adapters.js +54 -0
- package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
- package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
- package/dist/_internal/server/features/orders/balance.d.ts +89 -0
- package/dist/_internal/server/features/orders/balance.js +256 -0
- package/dist/_internal/server/features/orders/cancellation-refund.d.ts +15 -9
- package/dist/_internal/server/features/orders/cancellation-refund.js +15 -9
- package/dist/_internal/server/features/points/award.js +46 -4
- package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
- package/dist/_internal/server/features/pricing/actions.js +144 -0
- package/dist/_internal/server/features/refunds/actions.js +26 -0
- package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
- package/dist/_internal/server/features/shipping/book-split.js +130 -0
- package/dist/_internal/server/features/shipping/book.d.ts +61 -0
- package/dist/_internal/server/features/shipping/book.js +176 -0
- package/dist/_internal/server/features/shipping/courier-block.d.ts +69 -0
- package/dist/_internal/server/features/shipping/courier-block.js +264 -0
- package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
- package/dist/_internal/server/features/site-settings/adapters.js +29 -0
- package/dist/_internal/server/features/stores/adapters.d.ts +2 -2
- package/dist/_internal/server/features/stores/adapters.js +65 -0
- package/dist/_internal/server/functions/scheduled.d.ts +2 -1
- package/dist/_internal/server/functions/scheduled.js +95 -2
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +11 -2
- package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +4 -0
- package/dist/_internal/server/jobs/core/dailyStatusDigest.js +19 -2
- package/dist/_internal/server/jobs/core/index.d.ts +2 -1
- package/dist/_internal/server/jobs/core/index.js +2 -1
- package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
- package/dist/_internal/server/jobs/core/onJobCreated.d.ts +30 -7
- package/dist/_internal/server/jobs/core/onJobCreated.js +78 -45
- package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +7 -0
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +65 -0
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +33 -0
- package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
- package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
- package/dist/_internal/server/jobs/core/runJobOnce.d.ts +48 -0
- package/dist/_internal/server/jobs/core/runJobOnce.js +195 -0
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +25 -2
- package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
- package/dist/_internal/server/jobs/handlers/index.js +1 -0
- package/dist/_internal/server/jobs/handlers/onOrderStatusChange.js +17 -0
- package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
- package/dist/_internal/server/notifications/channel-health.d.ts +26 -3
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +296 -0
- package/dist/_internal/shared/checkout/coupon-discount.d.ts +43 -1
- package/dist/_internal/shared/checkout/coupon-discount.js +26 -1
- package/dist/_internal/shared/checkout/order-math.d.ts +174 -0
- package/dist/_internal/shared/checkout/order-math.js +159 -0
- package/dist/_internal/shared/checkout/refundable-base.d.ts +25 -0
- package/dist/_internal/shared/checkout/refundable-base.js +13 -1
- package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
- package/dist/_internal/shared/checkout/rules/index.js +1 -1
- package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
- package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
- package/dist/_internal/shared/checkout/split.d.ts +75 -0
- package/dist/_internal/shared/checkout/split.js +120 -0
- package/dist/_internal/shared/content/disclaimers.d.ts +88 -0
- package/dist/_internal/shared/content/disclaimers.js +217 -0
- package/dist/_internal/shared/content/published-values.d.ts +93 -0
- package/dist/_internal/shared/content/published-values.js +206 -0
- package/dist/_internal/shared/features/admin/integrations.d.ts +139 -0
- package/dist/_internal/shared/features/admin/integrations.js +263 -0
- package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
- package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
- package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
- package/dist/_internal/shared/features/emi/choice.js +69 -0
- package/dist/_internal/shared/features/emi/group.d.ts +84 -0
- package/dist/_internal/shared/features/emi/group.js +126 -0
- package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
- package/dist/_internal/shared/features/ledger/posting.js +165 -0
- package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
- package/dist/_internal/shared/features/ledger/reports.js +127 -0
- package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
- package/dist/_internal/shared/features/ledger/rules.js +221 -0
- package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
- package/dist/_internal/shared/features/offers/coordination.js +80 -0
- package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
- package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
- package/dist/_internal/shared/features/orders/dispute-reasons.d.ts +113 -0
- package/dist/_internal/shared/features/orders/dispute-reasons.js +181 -0
- package/dist/_internal/shared/features/orders/refund-copy.d.ts +1 -1
- package/dist/_internal/shared/features/orders/refund-copy.js +18 -1
- package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
- package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
- package/dist/_internal/shared/features/points/accepts.d.ts +29 -0
- package/dist/_internal/shared/features/points/accepts.js +49 -0
- package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
- package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
- package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
- package/dist/_internal/shared/features/shipping/parcel.js +139 -0
- package/dist/_internal/shared/features/shipping/shared-purchase.d.ts +91 -0
- package/dist/_internal/shared/features/shipping/shared-purchase.js +108 -0
- package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
- package/dist/_internal/shared/features/site-settings/fees.js +12 -8
- package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
- package/dist/_internal/shared/fees/calculator.d.ts +33 -1
- package/dist/_internal/shared/fees/calculator.js +32 -2
- package/dist/_internal/shared/fees/explain.d.ts +81 -0
- package/dist/_internal/shared/fees/explain.js +101 -0
- package/dist/_internal/shared/history/index.d.ts +1 -1
- package/dist/_internal/shared/history/index.js +1 -1
- package/dist/_internal/shared/history/types.d.ts +7 -1
- package/dist/_internal/shared/history/types.js +25 -0
- package/dist/client.d.ts +21 -0
- package/dist/client.js +43 -0
- package/dist/constants/api-endpoints.d.ts +114 -0
- package/dist/constants/api-endpoints.js +55 -0
- package/dist/constants/field-names.d.ts +42 -0
- package/dist/constants/field-names.js +52 -0
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/shipping.d.ts +45 -0
- package/dist/contracts/shipping.js +15 -0
- package/dist/features/about/components/AboutView.js +1 -1
- package/dist/features/account/components/BuyerAuctionsGuideView.js +4 -1
- package/dist/features/account/components/UserOrdersView.js +47 -35
- package/dist/features/admin/components/AdminCouponEditorView.js +17 -0
- package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
- package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
- package/dist/features/admin/components/AdminInvoicingView.d.ts +2 -0
- package/dist/features/admin/components/AdminInvoicingView.js +65 -0
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +33 -1
- package/dist/features/admin/components/AdminOrderEditorView.js +81 -3
- package/dist/features/admin/components/AdminOrdersGuideView.js +23 -2
- package/dist/features/admin/components/AdminOrdersView.js +86 -5
- package/dist/features/admin/components/OwnerQuickActions.js +24 -2
- package/dist/features/admin/constants/filter-tabs.d.ts +6 -0
- package/dist/features/admin/constants/filter-tabs.js +6 -0
- package/dist/features/admin/constants/site-settings-tabs.d.ts +1 -1
- package/dist/features/admin/hooks/useAdminListingData.js +16 -0
- package/dist/features/admin/schemas/admin-user-form.d.ts +2 -2
- package/dist/features/admin/schemas/firestore.d.ts +62 -0
- package/dist/features/admin/schemas/firestore.js +5 -0
- package/dist/features/ads/schemas/booking-write.d.ts +120 -0
- package/dist/features/ads/schemas/booking-write.js +75 -0
- package/dist/features/ads/schemas/creative-form.d.ts +18 -0
- package/dist/features/ads/schemas/creative-form.js +51 -0
- package/dist/features/ads/schemas/firestore.d.ts +140 -0
- package/dist/features/ads/schemas/firestore.js +109 -0
- package/dist/features/auctions/repository/bid.repository.js +3 -1
- package/dist/features/audit-log/schemas/firestore.d.ts +140 -0
- package/dist/features/audit-log/schemas/firestore.js +89 -0
- package/dist/features/auth/actions/profile-actions.d.ts +69 -1
- package/dist/features/auth/actions/profile-actions.js +62 -1
- package/dist/features/auth/permissions/constants.js +13 -0
- package/dist/features/auth/schemas/firestore.d.ts +16 -2
- package/dist/features/auth/schemas/firestore.js +2 -1
- package/dist/features/blog/actions/blog-actions.d.ts +6 -0
- package/dist/features/blog/actions/blog-actions.js +17 -2
- package/dist/features/blog/api/route.js +4 -1
- package/dist/features/blog/columns/index.js +5 -0
- package/dist/features/blog/components/BlogIndexPageView.js +2 -1
- package/dist/features/blog/repository/blog.repository.d.ts +4 -0
- package/dist/features/blog/repository/blog.repository.js +5 -0
- package/dist/features/blog/schemas/blog-form.d.ts +3 -0
- package/dist/features/blog/schemas/blog-form.js +1 -0
- package/dist/features/blog/schemas/firestore.d.ts +38 -1
- package/dist/features/blog/schemas/firestore.js +23 -0
- package/dist/features/blog/schemas/index.d.ts +6 -0
- package/dist/features/blog/schemas/index.js +2 -0
- package/dist/features/blog/types/index.d.ts +2 -0
- package/dist/features/cart/components/CartPriceBreakdown.d.ts +25 -1
- package/dist/features/cart/components/CartPriceBreakdown.js +29 -6
- package/dist/features/cart/components/PointsTenderPicker.d.ts +61 -0
- package/dist/features/cart/components/PointsTenderPicker.js +15 -0
- package/dist/features/cart/components/StoreAddonsPicker.js +2 -1
- package/dist/features/cart/components/index.d.ts +2 -0
- package/dist/features/cart/components/index.js +1 -0
- package/dist/features/cart/repository/cart.repository.d.ts +33 -0
- package/dist/features/cart/repository/cart.repository.js +47 -0
- package/dist/features/cart/schemas/firestore.d.ts +116 -0
- package/dist/features/contact/email.d.ts +27 -10
- package/dist/features/contact/email.js +20 -3
- package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
- package/dist/features/dashboard/components/DashboardHubView.js +56 -0
- package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
- package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
- package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
- package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
- package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +62 -0
- package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +108 -0
- package/dist/features/dispute-reasons/schemas/firestore.d.ts +62 -0
- package/dist/features/dispute-reasons/schemas/firestore.js +40 -0
- package/dist/features/events/components/EventSaleBanner.js +1 -1
- package/dist/features/faq/components/FAQAccordion.d.ts +13 -1
- package/dist/features/faq/components/FAQAccordion.js +29 -4
- package/dist/features/faq/components/FAQPageContent.js +2 -2
- package/dist/features/gateway-events/schemas/index.d.ts +2 -2
- package/dist/features/homepage/schemas/index.d.ts +8 -8
- package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
- package/dist/features/inventory/schemas/stock-reservation.js +103 -0
- package/dist/features/invoicing/schemas/firestore.d.ts +112 -0
- package/dist/features/invoicing/schemas/firestore.js +45 -0
- package/dist/features/invoicing/utils/financial-year.d.ts +43 -0
- package/dist/features/invoicing/utils/financial-year.js +53 -0
- package/dist/features/jobs/actions/enqueue-job.js +18 -1
- package/dist/features/jobs/repository/jobs.repository.d.ts +62 -1
- package/dist/features/jobs/repository/jobs.repository.js +84 -1
- package/dist/features/jobs/schemas/firestore.d.ts +80 -0
- package/dist/features/jobs/schemas/firestore.js +37 -0
- package/dist/features/layout/AppLayoutShell.d.ts +9 -1
- package/dist/features/layout/AppLayoutShell.js +12 -4
- package/dist/features/layout/BottomActions.js +2 -1
- package/dist/features/layout/BottomNavbar.d.ts +10 -2
- package/dist/features/layout/SideActionDock.js +52 -2
- package/dist/features/layout/TitleBarLayout.js +13 -4
- package/dist/features/layout/TitleBarLayout.style.css +59 -0
- package/dist/features/layout/useCtaReveal.d.ts +16 -1
- package/dist/features/layout/useCtaReveal.js +17 -26
- package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
- package/dist/features/ledger/repository/journal.repository.js +312 -0
- package/dist/features/ledger/schemas/expenses.d.ts +87 -0
- package/dist/features/ledger/schemas/expenses.js +27 -0
- package/dist/features/ledger/schemas/firestore.d.ts +183 -0
- package/dist/features/ledger/schemas/firestore.js +69 -0
- package/dist/features/lottery/schemas/zod.d.ts +6 -6
- package/dist/features/media/MediaImage.js +22 -1
- package/dist/features/media/upload/ImageUpload.js +1 -1
- package/dist/features/obligations/constants/policies.js +24 -1
- package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
- package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
- package/dist/features/orders/components/OrderPaymentSummary.js +10 -1
- package/dist/features/orders/components/OrderProvenanceCard.d.ts +8 -0
- package/dist/features/orders/components/OrderProvenanceCard.js +185 -0
- package/dist/features/orders/components/RaiseDisputeForm.d.ts +14 -0
- package/dist/features/orders/components/RaiseDisputeForm.js +119 -0
- package/dist/features/orders/components/RefundRequestView.js +19 -1
- package/dist/features/orders/components/index.d.ts +4 -0
- package/dist/features/orders/components/index.js +2 -0
- package/dist/features/orders/constants/order-lane-tabs.d.ts +69 -0
- package/dist/features/orders/constants/order-lane-tabs.js +88 -0
- package/dist/features/orders/repository/orders.repository.d.ts +85 -1
- package/dist/features/orders/repository/orders.repository.js +205 -6
- package/dist/features/orders/schemas/balance.d.ts +40 -0
- package/dist/features/orders/schemas/balance.js +47 -0
- package/dist/features/orders/schemas/firestore.d.ts +398 -1
- package/dist/features/orders/schemas/firestore.js +43 -0
- package/dist/features/orders/schemas/index.d.ts +56 -8
- package/dist/features/orders/schemas/index.js +12 -0
- package/dist/features/orders/types/index.d.ts +47 -0
- package/dist/features/orders/utils/courier-block.d.ts +25 -0
- package/dist/features/orders/utils/courier-block.js +23 -0
- package/dist/features/payment-cases/schemas/firestore.d.ts +26 -1
- package/dist/features/payment-cases/schemas/firestore.js +1 -0
- package/dist/features/payments/repository/payout.repository.js +3 -2
- package/dist/features/payments/schemas/firestore.d.ts +92 -1
- package/dist/features/payments/schemas/firestore.js +23 -0
- package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
- package/dist/features/pricing/components/AdminPricingView.js +157 -0
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -2
- package/dist/features/products/components/ProductDetailPageView.d.ts +17 -1
- package/dist/features/products/components/ProductDetailPageView.js +2 -2
- package/dist/features/products/schemas/firestore.d.ts +26 -1
- package/dist/features/products/schemas/firestore.js +2 -0
- package/dist/features/products/schemas/index.d.ts +2 -2
- package/dist/features/products/schemas/product-features.validators.d.ts +10 -10
- package/dist/features/promotions/actions/coupon-stacking.d.ts +30 -3
- package/dist/features/promotions/actions/coupon-stacking.js +21 -2
- package/dist/features/promotions/components/CouponCard.js +13 -0
- package/dist/features/promotions/constants/coupon-help.d.ts +2 -2
- package/dist/features/promotions/constants/coupon-help.js +9 -1
- package/dist/features/promotions/schemas/firestore.d.ts +24 -0
- package/dist/features/promotions/schemas/firestore.js +4 -0
- package/dist/features/promotions/types/index.d.ts +19 -1
- package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
- package/dist/features/reviews/repository/reviews.repository.js +16 -0
- package/dist/features/scams/components/ScamProfileView.js +2 -2
- package/dist/features/scams/components/ScamRegistryView.js +2 -2
- package/dist/features/scams/repository/scammer.repository.js +2 -1
- package/dist/features/scams/schemas/firestore.d.ts +2 -1
- package/dist/features/scams/schemas/firestore.js +2 -1
- package/dist/features/search/action-index/tab-entries.js +1 -1
- package/dist/features/seller/actions/offer-actions.js +56 -0
- package/dist/features/seller/actions/seller-actions.d.ts +1 -1
- package/dist/features/seller/actions/seller-actions.js +37 -3
- package/dist/features/seller/components/DispatchForm.d.ts +11 -0
- package/dist/features/seller/components/DispatchForm.js +190 -0
- package/dist/features/seller/components/SellerOrdersView.js +221 -27
- package/dist/features/seller/components/index.d.ts +1 -0
- package/dist/features/seller/components/index.js +1 -0
- package/dist/features/seller/hooks/useSellerListingData.js +25 -0
- package/dist/features/seller/repository/offer.repository.js +4 -3
- package/dist/features/seller/schemas/firestore.d.ts +23 -2
- package/dist/features/seller/schemas/firestore.js +3 -2
- package/dist/features/seller/schemas/index.d.ts +4 -4
- package/dist/features/seller/schemas/order-forms.d.ts +61 -4
- package/dist/features/seller/schemas/order-forms.js +41 -8
- package/dist/features/shipments/schemas/firestore.d.ts +25 -0
- package/dist/features/shipments/schemas/validation.d.ts +4 -4
- package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +82 -0
- package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +145 -0
- package/dist/features/shipping-boxes/schemas/firestore.d.ts +80 -0
- package/dist/features/shipping-boxes/schemas/firestore.js +53 -0
- package/dist/features/store-extensions/schemas/report-create-form.d.ts +2 -2
- package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +2 -2
- package/dist/features/stores/components/StoreOrdersGuideView.js +6 -1
- package/dist/features/stores/repository/store.repository.d.ts +18 -0
- package/dist/features/stores/repository/store.repository.js +27 -1
- package/dist/features/stores/schemas/firestore.d.ts +112 -0
- package/dist/features/stores/schemas/firestore.js +20 -0
- package/dist/features/stores/schemas/index.d.ts +6 -6
- package/dist/features/stores/types/index.d.ts +19 -0
- package/dist/features/support/repository/support.repository.js +72 -6
- package/dist/features/support/schemas/firestore.d.ts +17 -0
- package/dist/features/support/schemas/index.d.ts +8 -8
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +33 -1
- package/dist/next/routing/route-map.d.ts +112 -0
- package/dist/next/routing/route-map.js +63 -0
- package/dist/providers/shipping-shiprocket/index.d.ts +27 -1
- package/dist/providers/shipping-shiprocket/index.js +84 -1
- package/dist/react/contexts/SessionContext.d.ts +17 -1
- package/dist/schemas/registry.d.ts +69 -34
- package/dist/schemas/sieve.d.ts +2 -2
- package/dist/security/pii-schemas.d.ts +1 -1
- package/dist/security/pii-schemas.js +45 -0
- package/dist/server-entry.d.ts +2 -2
- package/dist/server-entry.js +8 -1
- package/dist/server.d.ts +36 -1
- package/dist/server.js +183 -1
- package/dist/styles.css +412 -80
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +1 -0
- package/dist/tokens/themes/default-light.js +1 -0
- package/dist/tokens/themes/required.d.ts +1 -1
- package/dist/tokens/themes/required.js +1 -0
- package/dist/tokens/tokens.css +15 -0
- package/dist/ui/components/Button.d.ts +10 -1
- package/dist/ui/components/Button.js +25 -3
- package/dist/ui/components/Chart.d.ts +63 -0
- package/dist/ui/components/Chart.js +169 -0
- package/dist/ui/components/Chart.style.css +214 -0
- package/dist/ui/components/Disclaimer.d.ts +19 -0
- package/dist/ui/components/Disclaimer.js +83 -0
- package/dist/ui/components/OverflowRow.js +54 -2
- package/dist/ui/components/OverflowRow.style.css +38 -0
- package/dist/ui/components/RichTextEditor.js +99 -8
- package/dist/ui/components/chart-spec.d.ts +68 -0
- package/dist/ui/components/chart-spec.js +140 -0
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/components/surface-tokens.d.ts +1 -1
- package/dist/ui/components/surface-tokens.js +9 -0
- package/dist/ui/components/tabs-overflow.js +64 -11
- package/dist/ui/components/toolbar-collapse.d.ts +13 -0
- package/dist/ui/components/toolbar-collapse.js +10 -1
- package/dist/ui/index.d.ts +8 -0
- package/dist/ui/index.js +9 -0
- package/dist/ui/rich-text/RichText.d.ts +10 -1
- package/dist/ui/rich-text/RichText.js +33 -2
- package/dist/ui/rich-text/RichText.style.css +83 -79
- package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
- package/dist/ui/rich-text/RichTextRenderer.js +34 -2
- package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
- package/dist/ui/rich-text/chart-blocks.js +87 -0
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +1834 -1822
|
@@ -590,6 +590,53 @@ export class CartRepository extends BaseRepository {
|
|
|
590
590
|
updatedAt: new Date(),
|
|
591
591
|
}, { merge: true });
|
|
592
592
|
}
|
|
593
|
+
/**
|
|
594
|
+
* Opt the cart in or out of paying with points (D46/D47, decision 24).
|
|
595
|
+
*
|
|
596
|
+
* 🛑 A BOOLEAN, and the schema deliberately has no numeric sibling. Opt in
|
|
597
|
+
* and the server applies as many points as the 50% cap allows; whatever
|
|
598
|
+
* cannot be applied stays in the balance for a later order. A client-supplied
|
|
599
|
+
* amount is a client-supplied discount, which is the whole reason
|
|
600
|
+
* `storeAddons` is the source of truth for add-on fees rather than a request
|
|
601
|
+
* body.
|
|
602
|
+
*
|
|
603
|
+
* Written with the same `set(..., { merge: true })` as its neighbours so a
|
|
604
|
+
* concurrent add-on or selection write is not clobbered.
|
|
605
|
+
*
|
|
606
|
+
* 🛑 Opting OUT deletes the field rather than writing `false` — absent and
|
|
607
|
+
* `false` mean the same thing to every reader (`cart.useAllPoints === true`),
|
|
608
|
+
* and keeping both shapes invites a reader that handles only one. Same
|
|
609
|
+
* reasoning as `setStoreAddons` directly above.
|
|
610
|
+
*/
|
|
611
|
+
/**
|
|
612
|
+
* Set or clear the instalment plan.
|
|
613
|
+
*
|
|
614
|
+
* 🛑 `null` DELETES the field rather than storing `{ optIn: false }`. The
|
|
615
|
+
* schema's rule is that absent means "no instalments", so a second
|
|
616
|
+
* representation of the same state is one more thing every reader has to
|
|
617
|
+
* get right (Root Cause #42's shape). `tenureMonths` is stored verbatim and
|
|
618
|
+
* validated against the live `emi.tenureOptions` at order time — the admin
|
|
619
|
+
* can change those options after a cart was saved, so validating here would
|
|
620
|
+
* freeze a tenure that is no longer offered.
|
|
621
|
+
*/
|
|
622
|
+
async setEmiPlan(userId, plan) {
|
|
623
|
+
await this.db
|
|
624
|
+
.collection(this.collection)
|
|
625
|
+
.doc(userId)
|
|
626
|
+
.set({
|
|
627
|
+
emiPlan: plan ? { tenureMonths: plan.tenureMonths } : FieldValue.delete(),
|
|
628
|
+
updatedAt: new Date(),
|
|
629
|
+
}, { merge: true });
|
|
630
|
+
}
|
|
631
|
+
async setUseAllPoints(userId, useAllPoints) {
|
|
632
|
+
await this.db
|
|
633
|
+
.collection(this.collection)
|
|
634
|
+
.doc(userId)
|
|
635
|
+
.set({
|
|
636
|
+
useAllPoints: useAllPoints ? true : FieldValue.delete(),
|
|
637
|
+
updatedAt: new Date(),
|
|
638
|
+
}, { merge: true });
|
|
639
|
+
}
|
|
593
640
|
/*
|
|
594
641
|
* `pruneStoreAddons(userId, keepStoreIds)` used to live here. It had zero
|
|
595
642
|
* callers from the day it was written, and `pruneForItems` now does the same
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { BaseDocument } from "../../../_internal/shared/types/base-document";
|
|
8
8
|
import type { ListingType } from "../../products/types/index";
|
|
9
|
+
import type { CouponType } from "../../promotions/types/index";
|
|
9
10
|
/**
|
|
10
11
|
* What KIND of thing one cart line represents.
|
|
11
12
|
*
|
|
@@ -57,6 +58,33 @@ export interface CartLineMember {
|
|
|
57
58
|
gstRate?: 0 | 5 | 12 | 18 | 28;
|
|
58
59
|
hsnCode?: string;
|
|
59
60
|
listingType?: ListingType;
|
|
61
|
+
/**
|
|
62
|
+
* How the coordinator expressed this member's share of the line.
|
|
63
|
+
*
|
|
64
|
+
* Absent means `"amount"` — every line written before splits existed, so no
|
|
65
|
+
* migration and no behaviour change until a coordinator picks percentages.
|
|
66
|
+
*
|
|
67
|
+
* 🛑 The PERCENTAGE is the stored fact, not the resolved rupees. Percentages
|
|
68
|
+
* apply to the LANDED cost (goods + shipping + fees), so a member's figure
|
|
69
|
+
* MOVES when shipping is re-quoted — storing the computed amount instead
|
|
70
|
+
* would freeze a number that no longer matches the agreed share. The
|
|
71
|
+
* computed figures are snapshotted at COMMIT, which is where the
|
|
72
|
+
* coordinator's agreement actually becomes binding (D61).
|
|
73
|
+
*
|
|
74
|
+
* `resolveSplit` (`_internal/shared/checkout/split.ts`) is the only thing
|
|
75
|
+
* that turns these into money.
|
|
76
|
+
*/
|
|
77
|
+
splitMode?: "amount" | "percent";
|
|
78
|
+
/** 0–100, read only when `splitMode === "percent"`. */
|
|
79
|
+
percent?: number;
|
|
80
|
+
/**
|
|
81
|
+
* The member's agreed contribution in decimal rupees, when typed directly.
|
|
82
|
+
*
|
|
83
|
+
* 🛑 NOT the same as `unitPrice`. `unitPrice` is what the ITEM costs;
|
|
84
|
+
* this is what this PERSON agreed to put in, and the two differ by design
|
|
85
|
+
* the moment a split is uneven or the total exceeds the landed cost.
|
|
86
|
+
*/
|
|
87
|
+
contribution?: number;
|
|
60
88
|
}
|
|
61
89
|
export interface CartItemDocument {
|
|
62
90
|
itemId: string;
|
|
@@ -183,6 +211,26 @@ export interface CartItemDocument {
|
|
|
183
211
|
chosenShippingProviderId?: string;
|
|
184
212
|
/** Fee in decimal rupees for the chosen provider, snapshotted at cart time. */
|
|
185
213
|
chosenShippingFee?: number;
|
|
214
|
+
/**
|
|
215
|
+
* ── S5a: which address THIS line ships to ────────────────────────────────
|
|
216
|
+
*
|
|
217
|
+
* One payer, N destinations. Absent means "the order's own shipping
|
|
218
|
+
* address", which is every cart that predates this and every ordinary
|
|
219
|
+
* single-destination order — so nothing changes for them.
|
|
220
|
+
*
|
|
221
|
+
* 🛑 An `addresses/{id}` REFERENCE, never a copied address. Copying would
|
|
222
|
+
* put a name, a phone number and a street address onto the cart document,
|
|
223
|
+
* which is a PII store with no encryption, no `*_PII_FIELDS` entry and no
|
|
224
|
+
* retention story — and carts are swept by a TTL job that is not written to
|
|
225
|
+
* handle personal data. The id resolves server-side at checkout, where the
|
|
226
|
+
* address is already being read and decrypted.
|
|
227
|
+
*
|
|
228
|
+
* 🛑 It must belong to the BUYER. An arbitrary `addresses` id would let a
|
|
229
|
+
* caller address a parcel to any stored address on the platform, which is
|
|
230
|
+
* both a delivery hijack and a way to read whether an id exists. Checked
|
|
231
|
+
* server-side at the write, not trusted from the client.
|
|
232
|
+
*/
|
|
233
|
+
destinationAddressId?: string;
|
|
186
234
|
addedAt: Date;
|
|
187
235
|
updatedAt: Date;
|
|
188
236
|
}
|
|
@@ -196,6 +244,28 @@ export interface CartAppliedCoupon {
|
|
|
196
244
|
storeId?: string;
|
|
197
245
|
/** Item IDs (CartItemDocument.itemId) this coupon was calculated against */
|
|
198
246
|
applicableItemIds?: string[];
|
|
247
|
+
/**
|
|
248
|
+
* The coupon's type, snapshotted at apply time (D51).
|
|
249
|
+
*
|
|
250
|
+
* 🛑 Needed because `detectCouponConflict` buckets on TYPE, not scope: a
|
|
251
|
+
* `points_earn` coupon is admin-scoped like every platform coupon but
|
|
252
|
+
* competes for its own slot, so without this field on the stored entry the
|
|
253
|
+
* detector could not tell a points coupon already in the cart from an
|
|
254
|
+
* ordinary platform one, and `RIPLI05` would block every other admin coupon
|
|
255
|
+
* — the exact defect the third bucket exists to prevent.
|
|
256
|
+
*
|
|
257
|
+
* Absent means "a discount coupon", which is what every cart written before
|
|
258
|
+
* this field holds, and is the reading that preserves the previous
|
|
259
|
+
* behaviour exactly.
|
|
260
|
+
*
|
|
261
|
+
* 🛑 Snapshotted deliberately, unlike the restrictions: a coupon's TYPE
|
|
262
|
+
* decides which slot it occupies, so re-reading it live would mean an admin
|
|
263
|
+
* editing a coupon's type could retroactively make a live cart's
|
|
264
|
+
* combination illegal. The money is still re-validated against the live
|
|
265
|
+
* coupon at placement (`revalidateAppliedCoupons`), which is where a changed
|
|
266
|
+
* discount has to be caught.
|
|
267
|
+
*/
|
|
268
|
+
type?: CouponType;
|
|
199
269
|
}
|
|
200
270
|
/**
|
|
201
271
|
* Paid add-ons the buyer opted into, for ONE store.
|
|
@@ -239,6 +309,52 @@ export interface CartDocument extends BaseDocument {
|
|
|
239
309
|
* rather than a flag someone has to remember to check.
|
|
240
310
|
*/
|
|
241
311
|
storeAddons?: Record<string, CartStoreAddons>;
|
|
312
|
+
/**
|
|
313
|
+
* The buyer has opted to spend points on this checkout.
|
|
314
|
+
*
|
|
315
|
+
* ## 🛑 A BOOLEAN, and the amount is never stored or sent
|
|
316
|
+
*
|
|
317
|
+
* Owner's rule: *"if use point it is all and then the balance is returned if
|
|
318
|
+
* excess"* — one opt-in, all-or-nothing. Ticked, the checkout applies as many
|
|
319
|
+
* points as the 50% cap allows; whatever cannot be applied stays in the
|
|
320
|
+
* balance. The buyer never types a number.
|
|
321
|
+
*
|
|
322
|
+
* So this is the ONLY thing the client may say about points. The amount is
|
|
323
|
+
* derived server-side from the live balance and
|
|
324
|
+
* `POINTS_MAX_REDEMPTION_PERCENT` at the moment the order is priced — the
|
|
325
|
+
* same rule that makes `storeAddons` above the source of truth rather than a
|
|
326
|
+
* request body, and for the same reason: a client-supplied money figure is a
|
|
327
|
+
* client-supplied discount.
|
|
328
|
+
*
|
|
329
|
+
* 🛑 This replaces a deleted `pointsToRedeem?: number` on the checkout input,
|
|
330
|
+
* whose handler debited the buyer AFTER the gateway had captured full price
|
|
331
|
+
* (D46). A number was the wrong shape as well as the wrong place.
|
|
332
|
+
*/
|
|
333
|
+
useAllPoints?: boolean;
|
|
334
|
+
/**
|
|
335
|
+
* "Pay in instalments", with the chosen tenure — an opt-in ON THE ORDER,
|
|
336
|
+
* orthogonal to how the token is tendered.
|
|
337
|
+
*
|
|
338
|
+
* 🛑 It lives HERE, on the cart, for exactly the reason `storeAddons` does:
|
|
339
|
+
* the online path creates the gateway order in one request
|
|
340
|
+
* (`/api/payment/create-order`, which decides the CAPTURE amount) and the
|
|
341
|
+
* order document in a later one (`/api/payment/verify`). A choice carried in
|
|
342
|
+
* a request body cannot be read by both, so the two would be free to
|
|
343
|
+
* disagree about how much of the total is deferred — and the difference is
|
|
344
|
+
* money captured that the order does not record (the D37/D38/D40 class).
|
|
345
|
+
*
|
|
346
|
+
* `useAllPoints` is the precedent and the shape is deliberately the same: a
|
|
347
|
+
* durable selection the server re-reads, never a client-supplied amount.
|
|
348
|
+
*
|
|
349
|
+
* Absent means a plain full-price order, which is why it is written with
|
|
350
|
+
* `FieldValue.delete()` rather than `{ optIn: false }` — a stored false and
|
|
351
|
+
* an absent field must not be two ways of saying the same thing.
|
|
352
|
+
*/
|
|
353
|
+
emiPlan?: CartEmiPlan;
|
|
354
|
+
}
|
|
355
|
+
/** The buyer's instalment selection. `tenureMonths` is validated against the live `emi.tenureOptions` at order time, never here. */
|
|
356
|
+
export interface CartEmiPlan {
|
|
357
|
+
tenureMonths: number;
|
|
242
358
|
}
|
|
243
359
|
export declare const CART_COLLECTION: "carts";
|
|
244
360
|
export declare const CART_INDEXED_FIELDS: string[];
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import "server-only";
|
|
2
2
|
import type { SendGuardContext } from "../../_internal/shared/features/messaging/config";
|
|
3
3
|
import type { JsonValue } from "@mohasinac/appkit";
|
|
4
|
-
type
|
|
5
|
-
|
|
6
|
-
subject: string;
|
|
4
|
+
import type { EmailOptions } from "../../contracts/email";
|
|
5
|
+
type SendEmailOptions = Omit<EmailOptions, "html"> & {
|
|
7
6
|
html?: string;
|
|
8
|
-
text?: string;
|
|
9
|
-
from?: string;
|
|
10
|
-
cc?: string | string[];
|
|
11
|
-
replyTo?: string;
|
|
12
7
|
};
|
|
13
8
|
/**
|
|
14
9
|
* Everything `sendEmail` needs beyond the message itself.
|
|
@@ -22,9 +17,9 @@ type SendEmailOptions = Record<string, JsonValue> & {
|
|
|
22
17
|
* (CLAUDE.md Rule #22: make the wrong thing unrepresentable).
|
|
23
18
|
*
|
|
24
19
|
* Kept as a separate second parameter rather than a field on
|
|
25
|
-
* `SendEmailOptions
|
|
26
|
-
*
|
|
27
|
-
*
|
|
20
|
+
* `SendEmailOptions`, which is now the provider's own `EmailOptions`. The
|
|
21
|
+
* guard is about who may send and why; it is not part of the message, and
|
|
22
|
+
* folding it in would put it on the wire to the provider.
|
|
28
23
|
*/
|
|
29
24
|
export type SendEmailGuard = SendGuardContext;
|
|
30
25
|
/**
|
|
@@ -59,6 +54,28 @@ export interface OrderConfirmationEmailParams {
|
|
|
59
54
|
unitPrice: number;
|
|
60
55
|
totalPrice: number;
|
|
61
56
|
}>;
|
|
57
|
+
/**
|
|
58
|
+
* Phase 7 — the invoice PDF to attach, as STORED bytes.
|
|
59
|
+
*
|
|
60
|
+
* 🛑 Bytes, never a path and never a renderer. Two renders can disagree — a
|
|
61
|
+
* changed template, a different library version — and the buyer's copy must
|
|
62
|
+
* be byte-identical to ours. Letting this function render would be a second
|
|
63
|
+
* render by definition.
|
|
64
|
+
*
|
|
65
|
+
* 🛑 Optional, and absence must stay silent. The invoice is numbered on the
|
|
66
|
+
* PAID transition and its bytes are produced on first request, so a COD
|
|
67
|
+
* order confirmed before payment legitimately has none — and this email has
|
|
68
|
+
* always sent without an attachment. Failing or warning here would turn the
|
|
69
|
+
* normal case into a noisy one.
|
|
70
|
+
*
|
|
71
|
+
* Resend supports attachments already (`email-resend/provider.ts`), so this
|
|
72
|
+
* needs no new send, no new credential and no change to the 80/day ceiling.
|
|
73
|
+
* Only the payload is bigger.
|
|
74
|
+
*/
|
|
75
|
+
invoicePdf?: {
|
|
76
|
+
filename: string;
|
|
77
|
+
content: Buffer;
|
|
78
|
+
};
|
|
62
79
|
}
|
|
63
80
|
export declare function sendOrderConfirmationEmail(params: OrderConfirmationEmailParams): Promise<{
|
|
64
81
|
success: boolean;
|
|
@@ -124,9 +124,10 @@ export async function sendEmail(opts, guard) {
|
|
|
124
124
|
? opts.cc
|
|
125
125
|
: undefined,
|
|
126
126
|
replyTo: typeof opts.replyTo === "string" ? opts.replyTo : undefined,
|
|
127
|
-
headers:
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
headers: opts.headers,
|
|
128
|
+
// Forwarded, not dropped — the provider has mapped these to Resend's
|
|
129
|
+
// `attachments` all along; nothing here ever handed them over.
|
|
130
|
+
attachments: opts.attachments,
|
|
130
131
|
});
|
|
131
132
|
void recordSendAttempt({
|
|
132
133
|
to: opts.to,
|
|
@@ -184,6 +185,22 @@ export async function sendOrderConfirmationEmail(params) {
|
|
|
184
185
|
to,
|
|
185
186
|
subject: `Order Confirmed — ${orderId}`,
|
|
186
187
|
html,
|
|
188
|
+
/*
|
|
189
|
+
* Phase 7 — the invoice, when there is one. The STORED bytes, handed
|
|
190
|
+
* in by the caller: see `invoicePdf` on the params type for why this
|
|
191
|
+
* function must not render its own.
|
|
192
|
+
*/
|
|
193
|
+
...(params.invoicePdf
|
|
194
|
+
? {
|
|
195
|
+
attachments: [
|
|
196
|
+
{
|
|
197
|
+
filename: params.invoicePdf.filename,
|
|
198
|
+
content: params.invoicePdf.content,
|
|
199
|
+
contentType: "application/pdf",
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
}
|
|
203
|
+
: {}),
|
|
187
204
|
text: `Hi ${userName},\n\nYour order ${orderId} has been confirmed!\n\n${itemsText}\nTotal: ${formattedTotal}\nPayment: ${paymentLabel}\nShip to: ${shippingAddress ?? "-"}\n\nView your order: ${orderUrl}\n\n© ${currentYear()} ${siteName}`,
|
|
188
205
|
}, {
|
|
189
206
|
channel: "email",
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { AttentionCounts } from "../../../_internal/server/features/dashboard/attention";
|
|
3
|
+
import type { DashboardHubSection } from "../../../_internal/shared/features/dashboard/hub-sections";
|
|
4
|
+
/**
|
|
5
|
+
* The dashboard hub — one component, two modes, zero copy of its own.
|
|
6
|
+
*
|
|
7
|
+
* ## Why one component and not two
|
|
8
|
+
*
|
|
9
|
+
* A landing page lists SECTIONS; a section hub lists SCREENS. Those read as
|
|
10
|
+
* two features and are one: a grid of link cards, each with a title, a
|
|
11
|
+
* sentence about what it is for, and an optional count of things waiting. Same
|
|
12
|
+
* prop surface, same renderer — which the Duplication Framework calls a
|
|
13
|
+
* consolidate-on-sight ("copies accept the same parameters and return the same
|
|
14
|
+
* shape"), not a Rule-of-Three wait.
|
|
15
|
+
*
|
|
16
|
+
* The thing it must not become is `AdminGuideHubView`, which is the visual
|
|
17
|
+
* pattern here and hand-writes its own 13-card list — so a guide added to the
|
|
18
|
+
* nav never appears on it. Every card below comes from a nav item's existing
|
|
19
|
+
* `label` and `description`.
|
|
20
|
+
*
|
|
21
|
+
* ## Not a client component
|
|
22
|
+
*
|
|
23
|
+
* It takes plain data and renders. No hook, no fetch, no `"use client"` — the
|
|
24
|
+
* page that mounts it is already per-request (its layout reads the session), so
|
|
25
|
+
* the counts arrive with the render rather than costing a second invocation
|
|
26
|
+
* after it. See `_internal/server/features/dashboard/data.ts`.
|
|
27
|
+
*
|
|
28
|
+
* ## No icons, on purpose
|
|
29
|
+
*
|
|
30
|
+
* A nav item carries no `iconKey`, so icons would mean a hand-written map of
|
|
31
|
+
* 22 sections or ~130 screens — a second list to drift from the first, which is
|
|
32
|
+
* the whole defect this feature exists to avoid (Root Cause #61). The section
|
|
33
|
+
* heading plus the card's own sentence is the distinction; `<Badge>` carries
|
|
34
|
+
* the only signal that needs to catch the eye.
|
|
35
|
+
*/
|
|
36
|
+
export interface DashboardHubViewProps {
|
|
37
|
+
/**
|
|
38
|
+
* Page heading. Omit when the grid is embedded in a page that already has
|
|
39
|
+
* one — `/store` renders it inside a `CollapsibleSection`, and a second
|
|
40
|
+
* `<h1>` mid-page breaks the heading outline for a screen reader.
|
|
41
|
+
*/
|
|
42
|
+
title?: string;
|
|
43
|
+
/** One sentence under the heading. Only rendered alongside a `title`. */
|
|
44
|
+
description?: string;
|
|
45
|
+
/**
|
|
46
|
+
* What to render.
|
|
47
|
+
*
|
|
48
|
+
* - `"sections"` — one card per section, linking to its hub. The landing page.
|
|
49
|
+
* - `"screens"` — one card per screen in `sections[0]`. A section hub.
|
|
50
|
+
*
|
|
51
|
+
* 🛑 A hub is passed a ONE-section array rather than a section plus a mode
|
|
52
|
+
* flag, so the two modes cannot disagree about what they are rendering.
|
|
53
|
+
*/
|
|
54
|
+
mode: "sections" | "screens";
|
|
55
|
+
sections: DashboardHubSection[];
|
|
56
|
+
/** Built by the caller from `ROUTES.{PORTAL}.SECTION(slug)`. */
|
|
57
|
+
sectionHrefs: Record<string, string>;
|
|
58
|
+
counts: AttentionCounts;
|
|
59
|
+
/**
|
|
60
|
+
* Rendered above the cards — the live stat tiles on `/store` and `/user`.
|
|
61
|
+
*
|
|
62
|
+
* Those are real data and stay: the plan's "bland tile walls" are the
|
|
63
|
+
* undifferentiated grids of ~19 nav shortcuts, not the figures beside them.
|
|
64
|
+
* Deleting a working panel while replacing its neighbour is Root Cause #60's
|
|
65
|
+
* shape, so the slot exists and the caller keeps passing them.
|
|
66
|
+
*/
|
|
67
|
+
above?: React.ReactNode;
|
|
68
|
+
/** Shown when the viewer can see nothing at all. */
|
|
69
|
+
emptyMessage?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Render "7 screens" on a section card. Default `true`.
|
|
72
|
+
*
|
|
73
|
+
* 🛑 Pass `false` whenever `sections` has NOT been through every filter that
|
|
74
|
+
* applies to the portal. `/store` is the live case: its entitlement filter
|
|
75
|
+
* (`filterStoreNavGroups`) runs in the layout and on the hub pages, but the
|
|
76
|
+
* client landing does not hold the store document, so its "Listings" card
|
|
77
|
+
* would claim nine screens where the seller can reach six. The section itself
|
|
78
|
+
* is still correct — it is the COUNT that would over-promise, so the count is
|
|
79
|
+
* withheld rather than guessed.
|
|
80
|
+
*/
|
|
81
|
+
showScreenCount?: boolean;
|
|
82
|
+
}
|
|
83
|
+
export declare function DashboardHubView({ title, description, mode, sections, sectionHrefs, counts, above, emptyMessage, showScreenCount, }: DashboardHubViewProps): React.JSX.Element;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Alert, Badge, Div, Grid, Heading, Row, Section, Stack, Text, TextLink } from "../../../ui/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Sum of the counts inside a section, or `null` when it has none.
|
|
5
|
+
*
|
|
6
|
+
* 🛑 `null` and `0` are different answers and a card renders only the first as
|
|
7
|
+
* "no badge". A section whose every count FAILED must not read as "nothing
|
|
8
|
+
* waiting" (Root Cause #72), so a failed read inside an otherwise-countless
|
|
9
|
+
* section stays `null` rather than collapsing to a sum of zero.
|
|
10
|
+
*/
|
|
11
|
+
function sectionTotal(section, counts) {
|
|
12
|
+
let total = null;
|
|
13
|
+
for (const item of section.items) {
|
|
14
|
+
const value = item.id ? counts[item.id] : undefined;
|
|
15
|
+
if (typeof value !== "number")
|
|
16
|
+
continue;
|
|
17
|
+
total = (total ?? 0) + value;
|
|
18
|
+
}
|
|
19
|
+
return total;
|
|
20
|
+
}
|
|
21
|
+
/** A count worth showing. Zero is not — a `0` badge is noise on every card. */
|
|
22
|
+
function badgeFor(value) {
|
|
23
|
+
if (typeof value !== "number" || value <= 0)
|
|
24
|
+
return null;
|
|
25
|
+
return (_jsx(Badge, { variant: "warning", "aria-label": `${value} waiting`, children: value }));
|
|
26
|
+
}
|
|
27
|
+
function CardGrid({ cards }) {
|
|
28
|
+
return (_jsx(Grid, { cols: "cards", gap: "md", children: cards.map((card) => (_jsxs(TextLink, { variant: "bare", href: card.href, rounded: "xl", layout: "flex-col", gap: "sm", paddingX: "lg", paddingY: "lg", shadow: "hover-md", className: "group border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] hover:border-[var(--appkit-color-primary)] transition-all", children: [_jsxs(Row, { align: "center", justify: "between", gap: "sm", className: "min-w-0 w-full", children: [_jsx(Text, { weight: "semibold", className: "min-w-0 text-[var(--appkit-color-text)] group-hover:text-[var(--appkit-color-primary)] transition-colors", children: card.label }), badgeFor(card.count)] }), card.description && (_jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text-muted)] leading-relaxed", children: card.description })), card.meta && (_jsx(Text, { size: "xs", className: "text-[var(--appkit-color-text-faint)] mt-auto", children: card.meta }))] }, card.key))) }));
|
|
29
|
+
}
|
|
30
|
+
export function DashboardHubView({ title, description, mode, sections, sectionHrefs, counts, above, emptyMessage, showScreenCount = true, }) {
|
|
31
|
+
const hasAny = sections.some((section) => section.items.length > 0);
|
|
32
|
+
return (_jsxs(Stack, { gap: "lg", children: [title && (_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 1, size: "xl", weight: "semibold", color: "primary", children: title }), description && (_jsx(Text, { size: "sm", color: "muted", children: description }))] })), above, !hasAny && (_jsx(Alert, { variant: "info", title: "Nothing here yet", children: emptyMessage ??
|
|
33
|
+
"Your permission set doesn't include access to any of these screens yet. Ask an admin for the permissions you need." })), hasAny && mode === "sections" && (_jsx(CardGrid, { cards: sections.map((section) => ({
|
|
34
|
+
key: section.slug,
|
|
35
|
+
href: sectionHrefs[section.slug] ?? "",
|
|
36
|
+
label: section.title,
|
|
37
|
+
/*
|
|
38
|
+
* A section has no description of its own and must not invent one —
|
|
39
|
+
* so it names what is inside it instead. `items.length` is the
|
|
40
|
+
* post-filter count, which is what this viewer will actually find
|
|
41
|
+
* PROVIDED every filter has run; see `showScreenCount`.
|
|
42
|
+
*/
|
|
43
|
+
meta: showScreenCount
|
|
44
|
+
? `${section.items.length} ${section.items.length === 1 ? "screen" : "screens"}`
|
|
45
|
+
: undefined,
|
|
46
|
+
count: sectionTotal(section, counts),
|
|
47
|
+
})) })), hasAny &&
|
|
48
|
+
mode === "screens" &&
|
|
49
|
+
sections.map((section) => (_jsxs(Section, { children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", className: "mb-4 text-[var(--appkit-color-text)]", children: section.title }), _jsx(CardGrid, { cards: section.items.map((item) => ({
|
|
50
|
+
key: item.id ?? item.href,
|
|
51
|
+
href: item.href,
|
|
52
|
+
label: item.label,
|
|
53
|
+
description: item.description,
|
|
54
|
+
count: item.id ? (counts[item.id] ?? null) : null,
|
|
55
|
+
})) })] }, section.slug))), hasAny && mode === "sections" && (_jsx(Div, { children: _jsx(Text, { size: "xs", color: "faint", children: "Every card above is a section of the sidebar. The screens inside one are the same screens, with a sentence each on what they are for." }) }))] }));
|
|
56
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { NavPortal, SidebarNavGroup } from "../../../_internal/shared/features/layout/types";
|
|
3
|
+
export interface DashboardSectionsClientProps {
|
|
4
|
+
portal: NavPortal;
|
|
5
|
+
/**
|
|
6
|
+
* The portal's nav groups.
|
|
7
|
+
*
|
|
8
|
+
* 🛑 Pass the groups the SIDEBAR was given, already put through any
|
|
9
|
+
* portal-specific filter (`filterStoreNavGroups` for `/store`). This applies
|
|
10
|
+
* only the navConfig/permission filter; a section the store is not entitled
|
|
11
|
+
* to would otherwise appear here and nowhere else.
|
|
12
|
+
*/
|
|
13
|
+
groups: readonly SidebarNavGroup[];
|
|
14
|
+
/** `null` means admin; `undefined` means "no permission gating applies". */
|
|
15
|
+
permissions?: string[] | null;
|
|
16
|
+
/** Omit when embedding in a page that already has a heading. */
|
|
17
|
+
title?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
/** Live stat tiles and anything else that belongs above the cards. */
|
|
20
|
+
above?: React.ReactNode;
|
|
21
|
+
emptyMessage?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function DashboardSectionsClient({ portal, groups, permissions, title, description, above, emptyMessage, }: DashboardSectionsClientProps): React.JSX.Element;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { useSiteSettings } from "../../../core/hooks/useSiteSettings.js";
|
|
5
|
+
import { filterNavGroups } from "../../../_internal/client/features/layout/filterNavItems.js";
|
|
6
|
+
import { hubSections } from "../../../_internal/shared/features/dashboard/hub-sections.js";
|
|
7
|
+
import { ROUTES } from "../../../next/routing/route-map.js";
|
|
8
|
+
import { DashboardHubView } from "./DashboardHubView.js";
|
|
9
|
+
/**
|
|
10
|
+
* The sectioned index of a dashboard, for a landing page that is already a
|
|
11
|
+
* CLIENT component.
|
|
12
|
+
*
|
|
13
|
+
* ## Why a client variant exists at all
|
|
14
|
+
*
|
|
15
|
+
* `/store/page.tsx` and `/user/page.tsx` are `"use client"` and carry live stat
|
|
16
|
+
* tiles (`useStoreDashboard`, `useNotifications`, an avatar uploader). Turning
|
|
17
|
+
* either into a server component to fetch hub data would mean moving a working
|
|
18
|
+
* 250–360 line page into a sibling file for the sake of a card grid — a large
|
|
19
|
+
* diff over a working feature, which is the shape of Root Cause #60.
|
|
20
|
+
*
|
|
21
|
+
* So the DATA source differs and the RENDERER does not: this resolves sections
|
|
22
|
+
* from the same `useSiteSettings` navConfig the sidebar reads, and hands them to
|
|
23
|
+
* the same `<DashboardHubView>` the admin landing renders server-side. One card
|
|
24
|
+
* grid, two ways in — not two card grids.
|
|
25
|
+
*
|
|
26
|
+
* ## 🛑 No attention counts here, and that is honest rather than lazy
|
|
27
|
+
*
|
|
28
|
+
* Counts need Firestore, which a client component can only reach through an
|
|
29
|
+
* endpoint — a second billed invocation per landing visit for numbers the page
|
|
30
|
+
* did not previously show (Root Cause #94). The admin landing, which is a
|
|
31
|
+
* server component under a session-reading layout, gets them for free in its
|
|
32
|
+
* own render. A seller's one countable figure (pending orders) is already a
|
|
33
|
+
* live stat tile on `/store`, so the badge would be the second place for it.
|
|
34
|
+
*
|
|
35
|
+
* `counts={{}}` means every card renders without a badge — never with a `0`,
|
|
36
|
+
* which is the one answer that would wrongly read as "nothing waiting"
|
|
37
|
+
* (Root Cause #72).
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* 🛑 `Record<NavPortal, …>` so a fourth portal is a COMPILE error here rather
|
|
41
|
+
* than a landing page whose section cards all link to `""`. An object keyed on
|
|
42
|
+
* `string` would accept the omission silently (Root Cause #61).
|
|
43
|
+
*/
|
|
44
|
+
const SECTION_ROUTE = {
|
|
45
|
+
admin: (slug) => String(ROUTES.ADMIN.SECTION(slug)),
|
|
46
|
+
store: (slug) => String(ROUTES.STORE.SECTION(slug)),
|
|
47
|
+
user: (slug) => String(ROUTES.USER.SECTION(slug)),
|
|
48
|
+
};
|
|
49
|
+
export function DashboardSectionsClient({ portal, groups, permissions, title, description, above, emptyMessage, }) {
|
|
50
|
+
const { data: settings } = useSiteSettings();
|
|
51
|
+
/*
|
|
52
|
+
* Derived, never copied into state — the settings query can resolve after
|
|
53
|
+
* first paint, and a `useState` seeded from it would freeze the pre-settings
|
|
54
|
+
* answer. Same reasoning as `AdminIntegrationsView`.
|
|
55
|
+
*/
|
|
56
|
+
const sections = useMemo(() => hubSections(filterNavGroups([...groups], settings?.navConfig, permissions)), [groups, settings?.navConfig, permissions]);
|
|
57
|
+
const sectionHrefs = useMemo(() => Object.fromEntries(sections.map((s) => [s.slug, SECTION_ROUTE[portal](s.slug)])), [sections, portal]);
|
|
58
|
+
return (_jsx(DashboardHubView, { title: title, description: description, mode: "sections", sections: sections, sectionHrefs: sectionHrefs, counts: {}, above: above, emptyMessage: emptyMessage,
|
|
59
|
+
/*
|
|
60
|
+
* 🛑 Withheld deliberately. `/store`'s entitlement filter lives in the
|
|
61
|
+
* layout and on the hub pages, not here, so a count rendered from these
|
|
62
|
+
* groups would over-promise on the Listings card. See the prop's own
|
|
63
|
+
* header — the section is right, the number would not be.
|
|
64
|
+
*/
|
|
65
|
+
showScreenCount: false }));
|
|
66
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type DisputeKind } from "../../../_internal/shared/features/orders/dispute-reasons";
|
|
3
|
+
/**
|
|
4
|
+
* Admin → Trust & Safety → Dispute reasons.
|
|
5
|
+
*
|
|
6
|
+
* ## Why a management page exists at all
|
|
7
|
+
*
|
|
8
|
+
* Inline create in the triage drawer was the cheaper half and was rejected on
|
|
9
|
+
* its own, for a reason worth keeping: **with no management page nothing can
|
|
10
|
+
* ever retire a reason**, so the list only grows and a typo'd row is permanent.
|
|
11
|
+
* Both shipped — the drawer so an agent never leaves a ticket to add a missing
|
|
12
|
+
* reason, this page so the eleven seeded rows are reviewable and retire has a
|
|
13
|
+
* home.
|
|
14
|
+
*
|
|
15
|
+
* ## 🛑 A row is OPENABLE, not just actionable
|
|
16
|
+
*
|
|
17
|
+
* `audit-listing-detail-affordance` requires it and the reason is Root Cause
|
|
18
|
+
* #56: a menu of pure mutations lets staff act on a record they were never able
|
|
19
|
+
* to read. Here that would mean retiring a reason without seeing its KIND — and
|
|
20
|
+
* the kind is the only field that decides which gate the reason inherits, so
|
|
21
|
+
* retiring the wrong one silently narrows the wrong form.
|
|
22
|
+
*
|
|
23
|
+
* `RecordDetailModal` is the shared primitive for exactly this; a bespoke modal
|
|
24
|
+
* would have tripped the Duplication Framework's Rule of Three on sight.
|
|
25
|
+
*/
|
|
26
|
+
export interface AdminDisputeReasonsViewProps {
|
|
27
|
+
/**
|
|
28
|
+
* The staff list endpoint, supplied by the consumer.
|
|
29
|
+
*
|
|
30
|
+
* 🛑 A PROP rather than a literal in here, for the same reason
|
|
31
|
+
* `RaiseDisputeForm` takes `reasonsEndpoint`: appkit holds no consumer
|
|
32
|
+
* routes. The path belongs in `API_ROUTES`, which is the one registry, and a
|
|
33
|
+
* literal here would be a second place it is written — exactly what
|
|
34
|
+
* `audit-hardcoded-api-routes` blocks.
|
|
35
|
+
*/
|
|
36
|
+
endpoint: string;
|
|
37
|
+
/** `PATCH /api/admin/dispute-reasons/{id}` with `{ isActive }`. */
|
|
38
|
+
onSetActive: (id: string, isActive: boolean) => Promise<void>;
|
|
39
|
+
/** `POST /api/dispute-reasons` — the same endpoint the triage drawer uses. */
|
|
40
|
+
onCreate: (input: {
|
|
41
|
+
label: string;
|
|
42
|
+
kind: DisputeKind;
|
|
43
|
+
}) => Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The two fields, exported so the triage drawer's inline create and this page
|
|
47
|
+
* cannot drift on the label bound or the kind vocabulary.
|
|
48
|
+
*/
|
|
49
|
+
export declare function DisputeReasonFields({ label, kind, onLabel, onKind, }: {
|
|
50
|
+
label: string;
|
|
51
|
+
kind: DisputeKind;
|
|
52
|
+
onLabel: (v: string) => void;
|
|
53
|
+
onKind: (v: DisputeKind) => void;
|
|
54
|
+
}): React.JSX.Element;
|
|
55
|
+
export declare function AdminDisputeReasonsView({ endpoint, onSetActive, onCreate, }: AdminDisputeReasonsViewProps): React.JSX.Element;
|