@mohasinac/appkit 4.55.0 → 4.56.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 +4 -4
- package/dist/_internal/server/features/checkout/actions.d.ts +22 -0
- package/dist/_internal/server/features/checkout/actions.js +39 -3
- package/dist/_internal/server/features/shipping/reconcile.d.ts +28 -0
- package/dist/_internal/server/features/shipping/reconcile.js +93 -0
- package/dist/_internal/shared/config/schema.d.ts +6 -0
- package/dist/_internal/shared/listing-types/route-gating.d.ts +56 -0
- package/dist/_internal/shared/listing-types/route-gating.js +114 -0
- package/dist/_internal/shared/shipping/quote.d.ts +153 -0
- package/dist/_internal/shared/shipping/quote.js +124 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +8 -0
- package/dist/features/auctions/components/AuctionDetailPageView.js +2 -1
- package/dist/features/auth/schemas/firestore.d.ts +15 -0
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +2 -1
- package/dist/features/homepage/components/HeroCarousel.js +4 -2
- package/dist/features/homepage/components/MarketplaceHomepageView.js +16 -1
- package/dist/features/homepage/components/WelcomeSection.d.ts +16 -3
- package/dist/features/homepage/components/WelcomeSection.js +3 -3
- package/dist/features/homepage/lib/section-renderer.d.ts +9 -0
- package/dist/features/homepage/lib/section-renderer.js +22 -5
- package/dist/features/homepage/lib/slide-gating.d.ts +52 -0
- package/dist/features/homepage/lib/slide-gating.js +98 -0
- package/dist/features/live/components/LiveItemDetailPageView.js +2 -1
- package/dist/features/media/MediaAvatar.js +1 -1
- package/dist/features/media/MediaImage.d.ts +18 -1
- package/dist/features/media/MediaImage.js +1 -1
- package/dist/features/orders/schemas/firestore.d.ts +38 -0
- package/dist/features/points/repository/points.repository.d.ts +81 -0
- package/dist/features/points/repository/points.repository.js +155 -0
- package/dist/features/points/schemas/firestore.d.ts +102 -0
- package/dist/features/points/schemas/firestore.js +99 -0
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +2 -1
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -1
- package/dist/features/products/components/ProductDetailPageView.js +3 -1
- package/dist/features/seller/actions/seller-actions.d.ts +17 -0
- package/dist/features/seller/actions/seller-actions.js +33 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +8 -0
- package/dist/seed/carousel-slides-seed-data.js +48 -7
- package/dist/styles.css +38 -6
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/ImageMosaic.d.ts +17 -1
- package/dist/ui/components/ImageMosaic.js +28 -5
- package/dist/ui/components/ImageMosaic.style.css +37 -5
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { serverLogger } from "../../../monitoring/index.js";
|
|
12
12
|
import { normalizeError } from "../../../errors/normalize.js";
|
|
13
|
+
import { reconcileOrderShipping } from "../../../_internal/server/features/shipping/reconcile.js";
|
|
13
14
|
import { enqueueJob } from "../../jobs/actions/enqueue-job.js";
|
|
14
15
|
import { isAdminUser, isStrictSellerUser, isTesterUser } from "../../auth/role-predicates.js";
|
|
15
16
|
import { ApiError, AuthorizationError, NotFoundError, ValidationError, } from "../../../errors/index.js";
|
|
@@ -712,6 +713,38 @@ export async function customShipOrder(userId, userRole, orderId, input) {
|
|
|
712
713
|
shippingDate: new Date(),
|
|
713
714
|
payoutStatus: "eligible",
|
|
714
715
|
});
|
|
716
|
+
/*
|
|
717
|
+
* 🛑 AFTER the order is marked shipped, and never allowed to fail the
|
|
718
|
+
* dispatch.
|
|
719
|
+
*
|
|
720
|
+
* The parcel has physically gone. If reconciliation throws — the points
|
|
721
|
+
* ledger is unreachable, the order read fails — the correct outcome is a
|
|
722
|
+
* shipped order that has not been reconciled yet, which is recoverable by
|
|
723
|
+
* re-running it. Letting it propagate would leave the seller unable to mark
|
|
724
|
+
* a parcel shipped because of an accounting step they have no control over,
|
|
725
|
+
* and they would retry the dispatch, which is the one thing that must not
|
|
726
|
+
* happen twice.
|
|
727
|
+
*
|
|
728
|
+
* `reconcileOrderShipping` is itself idempotent on
|
|
729
|
+
* `order.shippingReconciliation`, so a retry is safe.
|
|
730
|
+
*/
|
|
731
|
+
if (typeof input.actualShippingCost === "number") {
|
|
732
|
+
try {
|
|
733
|
+
const outcome = await reconcileOrderShipping(orderId, {
|
|
734
|
+
courierId: input.actualCourierName ?? input.shippingCarrier,
|
|
735
|
+
courierName: input.actualCourierName ?? input.shippingCarrier,
|
|
736
|
+
actualRate: input.actualShippingCost,
|
|
737
|
+
});
|
|
738
|
+
serverLogger.info("shipping reconciled", { orderId, ...outcome });
|
|
739
|
+
}
|
|
740
|
+
catch (err) {
|
|
741
|
+
const normalized = normalizeError(err);
|
|
742
|
+
serverLogger.error("shipping reconciliation failed after dispatch", {
|
|
743
|
+
orderId,
|
|
744
|
+
message: normalized.message,
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
}
|
|
715
748
|
serverLogger.info("customShipOrder", {
|
|
716
749
|
orderId,
|
|
717
750
|
userId,
|
package/dist/index.d.ts
CHANGED
|
@@ -3123,6 +3123,7 @@ export { withRetry } from "./http/retry";
|
|
|
3123
3123
|
export { normalizeError, getErrorMessage, isApiNormalized, isAppNormalized, isFirebaseAuthNormalized, isFirebaseFirestoreNormalized, isFirebaseStorageNormalized, isNativeNormalized, isNetworkNormalized, isUnknownNormalized, isZodNormalized, } from "./errors/normalize";
|
|
3124
3124
|
export type { NormalizedError, NormalizedApiError, NormalizedAppError, NormalizedFirebaseAuthError, NormalizedFirebaseFirestoreError, NormalizedFirebaseStorageError, NormalizedNativeError, NormalizedNetworkError, NormalizedUnknownThrownValue, NormalizedZodError, } from "./errors/normalize";
|
|
3125
3125
|
export { CART_LANE, CART_LANE_PRIORITY, CART_LANE_LABELS, laneOf, activeLane, laneItems, laneCounts, isLaneCheckoutable, laneBlockReason, isLockedLane, canAddNewItems, type CartLane, type LaneAssignable, } from "./_internal/shared/checkout/lanes";
|
|
3126
|
+
export { roundShippingUp, toQuoteOptions, reconcileShipping, SHIPPING_ROUND_UP_TO, type ShippingQuoteOption, type SelectedShippingQuote, type ActualShipmentCost, type ShippingReconciliation, } from "./_internal/shared/shipping/quote";
|
|
3126
3127
|
export { newsletterSubscribeSchema, quickCreateTaxonomySchema, payoutMarkPaidSchema, } from "./features/admin/schemas/small-forms";
|
|
3127
3128
|
export { raffleEntrySchema } from "./features/contact/schemas/inquiry-forms";
|
|
3128
3129
|
export { orderCancelSchema, paymentProofSchema, } from "./features/orders/schemas/buyer-forms";
|
package/dist/index.js
CHANGED
|
@@ -5559,6 +5559,14 @@ export { normalizeError, getErrorMessage, isApiNormalized, isAppNormalized, isFi
|
|
|
5559
5559
|
// Checkout lanes — the derived auction > offer > standard partition of the
|
|
5560
5560
|
// cart, and the priority rule that decides which one may be checked out.
|
|
5561
5561
|
export { CART_LANE, CART_LANE_PRIORITY, CART_LANE_LABELS, laneOf, activeLane, laneItems, laneCounts, isLaneCheckoutable, laneBlockReason, isLockedLane, canAddNewItems, } from "./_internal/shared/checkout/lanes.js";
|
|
5562
|
+
/*
|
|
5563
|
+
* Shipping quote model. Public because the CONSUMER owns the route that asks
|
|
5564
|
+
* the carrier for rates (`/api/shipping/quote`) and the checkout UI that
|
|
5565
|
+
* renders them — the rounding rule has to be reachable from both, and it must
|
|
5566
|
+
* be the same rule the server-side reconciliation uses, or the buyer is
|
|
5567
|
+
* credited against a figure they were never charged.
|
|
5568
|
+
*/
|
|
5569
|
+
export { roundShippingUp, toQuoteOptions, reconcileShipping, SHIPPING_ROUND_UP_TO, } from "./_internal/shared/shipping/quote.js";
|
|
5562
5570
|
export { newsletterSubscribeSchema, quickCreateTaxonomySchema, payoutMarkPaidSchema, } from "./features/admin/schemas/small-forms.js";
|
|
5563
5571
|
export { raffleEntrySchema } from "./features/contact/schemas/inquiry-forms.js";
|
|
5564
5572
|
export { orderCancelSchema, paymentProofSchema, } from "./features/orders/schemas/buyer-forms.js";
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* WHY: Seeds 6 carousel slides for the marketplace homepage promo carousel.
|
|
3
|
-
* WHAT:
|
|
3
|
+
* WHAT: 4 active + 2 inactive. Deterministic Picsum backgrounds with a dim
|
|
4
4
|
* overlay, plus a headline / supporting line / CTA on each.
|
|
5
5
|
*
|
|
6
|
+
* 🛑 FOUR ACTIVE, NOT FIVE, SINCE 2026-10-20. `MAX_ACTIVE_SLIDES` is a
|
|
7
|
+
* ceiling, not a quota — `slide-beyblade-auction` went inactive with
|
|
8
|
+
* `listings.listingTypes.auction: false` and nothing was promoted to backfill
|
|
9
|
+
* it. Do NOT activate `slide-upcoming-promo` to get back to five: that one is
|
|
10
|
+
* the fixture `getActiveSlides()`' own filter is tested against, and it says
|
|
11
|
+
* "A draft slide kept unpublished so admins have a starting point to copy."
|
|
12
|
+
*
|
|
6
13
|
* 🛑 EVERY ACTIVE SLIDE MUST CARRY AN `overlay` OR `cards`, OR IT RENDERS BLANK.
|
|
7
14
|
* `HeroCarousel` gates all slide copy on `slide.overlay` (line ~412) and the
|
|
8
15
|
* card grid on `slide.cards.length` (line ~451). Before this pass every seeded
|
|
@@ -107,16 +114,34 @@ const _rawSlides = [
|
|
|
107
114
|
hover: { effect: "scale" },
|
|
108
115
|
},
|
|
109
116
|
{
|
|
110
|
-
|
|
117
|
+
/*
|
|
118
|
+
* 🛑 THIS WAS THE AUCTIONS CARD ("Bid / Live auctions / Place a bid
|
|
119
|
+
* before the timer runs out" → `/auctions`), and it was still on the
|
|
120
|
+
* first screen of the site weeks after `listings.listingTypes.auction`
|
|
121
|
+
* went `false`. The section-level gate in `MarketplaceHomepageView` is
|
|
122
|
+
* keyed on `SectionType` and a carousel is type `carousel` whatever it
|
|
123
|
+
* contains, so nothing could see it. `gateCarouselSlides` now can — but
|
|
124
|
+
* a filter that leaves a hole in a `repeat(3, 1fr)` row is a fallback,
|
|
125
|
+
* not a fix, so the slot gets real content instead.
|
|
126
|
+
*
|
|
127
|
+
* 🛑 NOT `/spares` and NOT `/art`, which were the obvious swaps: both
|
|
128
|
+
* types are ENABLED, both have a working browse page, and both held
|
|
129
|
+
* ZERO published products when this was written (measured against
|
|
130
|
+
* production, 2026-10-20). Replacing a dead-end card with a different
|
|
131
|
+
* dead-end card is not a fix. `/categories` is populated — six roots,
|
|
132
|
+
* 28 brands, 8 franchises — and browsing the tree is genuinely the
|
|
133
|
+
* third way to shop here.
|
|
134
|
+
*/
|
|
135
|
+
id: "card-hero-browse",
|
|
111
136
|
zone: 2,
|
|
112
137
|
mobileZone: 2,
|
|
113
138
|
background: { type: "image", url: MEDIA.lDrago, dimOverlay: { enabled: true, opacity: 0.45 } },
|
|
114
139
|
content: {
|
|
115
|
-
eyebrow: "
|
|
116
|
-
title: "
|
|
117
|
-
description: "
|
|
140
|
+
eyebrow: "Explore",
|
|
141
|
+
title: "Shop by category",
|
|
142
|
+
description: "Walk the tree from generation down to a single part.",
|
|
118
143
|
},
|
|
119
|
-
buttons: [{ id: "card-hero-
|
|
144
|
+
buttons: [{ id: "card-hero-browse-cta", text: "Browse categories", href: String(ROUTES.PUBLIC.CATEGORIES), variant: "primary" }],
|
|
120
145
|
hover: { effect: "scale" },
|
|
121
146
|
},
|
|
122
147
|
{
|
|
@@ -139,10 +164,26 @@ const _rawSlides = [
|
|
|
139
164
|
updatedAt: daysAgo(3),
|
|
140
165
|
},
|
|
141
166
|
{
|
|
167
|
+
/*
|
|
168
|
+
* 🛑 DISABLED, NOT DELETED — the same arrangement the auctions RAIL uses in
|
|
169
|
+
* `homepage-sections-seed-data.ts`, and for the same reason. Every word of
|
|
170
|
+
* the copy, the video background and the CTA stay exactly as they were, so
|
|
171
|
+
* flipping `listings.listingTypes.auction` back to `true` and this flag
|
|
172
|
+
* with it restores the slide intact.
|
|
173
|
+
*
|
|
174
|
+
* Two locks, deliberately. `gateCarouselSlides` already drops this at
|
|
175
|
+
* render because `overlay.button.link` and `link.url` both resolve to
|
|
176
|
+
* `/auctions` — but that one is invisible, and a slide listed as active in
|
|
177
|
+
* the carousel admin while never appearing on the page reads as a bug in
|
|
178
|
+
* the admin. `active: false` is the lock a human sees.
|
|
179
|
+
*
|
|
180
|
+
* 🛑 The copy names no listing type — "Win it at your price" — which is
|
|
181
|
+
* exactly why the gate matches on the LINK and not on the words.
|
|
182
|
+
*/
|
|
142
183
|
id: "slide-beyblade-auction",
|
|
143
184
|
title: "Live auctions",
|
|
144
185
|
order: 2,
|
|
145
|
-
active:
|
|
186
|
+
active: false,
|
|
146
187
|
background: {
|
|
147
188
|
type: "video",
|
|
148
189
|
// Direct MP4 URL, deliberately NOT wrapped in seedExtMedia() — that
|