@mohasinac/appkit 4.42.17 → 4.42.18
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.
|
@@ -6,6 +6,7 @@ import { sortBy } from "@mohasinac/appkit/client";
|
|
|
6
6
|
import { useState, useCallback } from "react";
|
|
7
7
|
import { Badge, Button, Div, FilterChipGroup, RecordDetailModal, Span, Text, useToast } from "../../../ui";
|
|
8
8
|
import { buildBidDetailFields, bidStatusBadge } from "../../auctions/components/bid-detail-fields";
|
|
9
|
+
import { RecordStatusTimeline } from "../../status-history/components/RecordStatusTimeline";
|
|
9
10
|
import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
10
11
|
import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
11
12
|
import { buildBulkAction } from "../../../_internal/shared/actions/bulk-helpers";
|
|
@@ -113,6 +114,9 @@ export function SellerBidsView({ endpoint = SELLER_ENDPOINTS.BIDS }) {
|
|
|
113
114
|
bidAmount: Number(item.bidAmount ?? 0),
|
|
114
115
|
status: toStringValue(item.status, "active"),
|
|
115
116
|
bidDate: toRelativeDate(item.bidDate ?? item.createdAt),
|
|
117
|
+
// The one cast, at the JSON -> document boundary where it belongs, so
|
|
118
|
+
// that every CONSUMER of `raw` typechecks for real.
|
|
119
|
+
raw: item,
|
|
116
120
|
})),
|
|
117
121
|
getTotal: (response, mappedRows) => (typeof response.total === "number" ? response.total : mappedRows.length),
|
|
118
122
|
buildFilters: (state) => (state.status ? sieveFilter("status", SIEVE_OP.EQ, state.status) : undefined),
|
|
@@ -145,8 +149,14 @@ export function SellerBidsView({ endpoint = SELLER_ENDPOINTS.BIDS }) {
|
|
|
145
149
|
},
|
|
146
150
|
};
|
|
147
151
|
const detailBadge = detail ? bidStatusBadge(detail.status) : null;
|
|
148
|
-
return (_jsxs(_Fragment, { children: [_jsx(DataListingView, { config: config }), _jsx(RecordDetailModal, { isOpen: detail !== null, onClose: () => setDetail(null), title: detail?.productTitle || "Bid", badges: detailBadge ? [{ label: detailBadge.label }] : undefined, fields: detail ? buildBidDetailFields(detail, "seller") : undefined, footer: detail ? (
|
|
152
|
+
return (_jsxs(_Fragment, { children: [_jsx(DataListingView, { config: config }), _jsx(RecordDetailModal, { isOpen: detail !== null, onClose: () => setDetail(null), title: detail?.productTitle || "Bid", badges: detailBadge ? [{ label: detailBadge.label }] : undefined, fields: detail ? buildBidDetailFields(detail.raw, "seller") : undefined, footer: detail ? (
|
|
149
153
|
// The full page — a modal cannot be linked, bookmarked or reloaded
|
|
150
154
|
// into, which is the whole reason the page exists.
|
|
151
|
-
_jsx(TextLink, { href: String(ROUTES.STORE.BID_DETAIL(detail.id)), children: "Open full page \u2192" })) : undefined
|
|
155
|
+
_jsx(TextLink, { href: String(ROUTES.STORE.BID_DETAIL(detail.id)), children: "Open full page \u2192" })) : undefined, extra:
|
|
156
|
+
// Present on the seller's full page and absent from this modal until
|
|
157
|
+
// 2026-10-04, which is a label the two surfaces disagreed about —
|
|
158
|
+
// exactly what the modal-vs-page case exists to catch. Mirrors
|
|
159
|
+
// AdminBidsView: absent history renders the empty label, never a
|
|
160
|
+
// step invented from `updatedAt`.
|
|
161
|
+
_jsx(RecordStatusTimeline, { entries: detail?.raw?.statusHistory, truncatedCount: detail?.raw?.statusHistoryTruncated }) })] }));
|
|
152
162
|
}
|
|
@@ -40,8 +40,20 @@ export const authored = {
|
|
|
40
40
|
"Read the current bid, the minimum increment and the bid panel.",
|
|
41
41
|
],
|
|
42
42
|
expectedBehaviour: "The twin of the guest case above — the bid figures and the working bid form are exactly what the gate must not cost a signed-in buyer.",
|
|
43
|
-
expectedUiState:
|
|
44
|
-
|
|
43
|
+
expectedUiState:
|
|
44
|
+
/*
|
|
45
|
+
* Literals corrected 2026-10-04 to the auction this case actually opens.
|
|
46
|
+
* They read '₹15,000.00' and a '₹1,000.00' increment, which are the
|
|
47
|
+
* numbers of a DIFFERENT fixture — `auction-money-flows-closing`, seeded
|
|
48
|
+
* by fixtures/money-flows__auction-win-to-payment.mjs at
|
|
49
|
+
* startingBid/currentBid 15000 with a 1000 increment, because its own
|
|
50
|
+
* case enters 16000 against it. This case's startPage is
|
|
51
|
+
* auction-beyblade-original-dragoon-storm, seeded startingBid 2999 /
|
|
52
|
+
* currentBid 3499 / buyNowPrice 5999, and the page renders exactly that.
|
|
53
|
+
* The product was never wrong; the expectation named another auction.
|
|
54
|
+
*/
|
|
55
|
+
"'Current bid ₹3,499.00' is shown with its bid count, a 'min increment ₹200.00' is stated, a Buy Now price of ₹5,999.00 is offered, and the bid panel carries a real amount input and a 'Place bid' submit button. Neither 'Sign in to see price' nor any other gate prompt appears anywhere on the page.",
|
|
56
|
+
expectedData: { currentBid: 3499, minIncrement: 200 },
|
|
45
57
|
endResult: "Nothing persists unless a bid is actually submitted, which this case does not do.",
|
|
46
58
|
},
|
|
47
59
|
"checklist-buying-product-detail-bundle-purchase": {
|
|
@@ -55,6 +55,27 @@ const _rawproductsLiveItemsSeedData = [
|
|
|
55
55
|
seedPhoto("live-image-golden-retriever-1-20260816", 900, 900),
|
|
56
56
|
seedPhoto("live-image-golden-retriever-2-20260816", 900, 900),
|
|
57
57
|
],
|
|
58
|
+
/*
|
|
59
|
+
* 🛑 A LIVE LISTING WITHOUT A VIDEO IS NOT A LISTING THE PRODUCT WOULD ACCEPT.
|
|
60
|
+
*
|
|
61
|
+
* `/store/live/new` refuses to save one — "a buyer purchasing an animal or
|
|
62
|
+
* plant needs to see it move" — so a seeded live fixture carrying only
|
|
63
|
+
* stills is data no seller could have created through the form, and every
|
|
64
|
+
* case written against the real creation flow then asserts against a
|
|
65
|
+
* fixture that contradicts it. Found 2026-10-04 driving
|
|
66
|
+
* `live-item-detail`, whose expectation that the gallery strip offers a
|
|
67
|
+
* "View video" entry was correct about the product and wrong about the
|
|
68
|
+
* data: the page shipped `video: undefined` and rendered 2 image slides.
|
|
69
|
+
*
|
|
70
|
+
* `url` stays RAW and unwrapped (Root Cause #27) — the media proxy is
|
|
71
|
+
* image-only and 400s on video/mp4 — while `thumbnailUrl` is wrapped,
|
|
72
|
+
* because a poster frame IS an image and should carry the watermark.
|
|
73
|
+
*/
|
|
74
|
+
video: {
|
|
75
|
+
url: "/demo-media/sample-video.mp4",
|
|
76
|
+
thumbnailUrl: seedPhoto("live-video-thumb-golden-retriever-20261004", 800, 450),
|
|
77
|
+
duration: 15,
|
|
78
|
+
},
|
|
58
79
|
status: PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED,
|
|
59
80
|
condition: PRODUCT_FIELDS.CONDITION_VALUES.NEW,
|
|
60
81
|
listingType: "live",
|
|
@@ -102,6 +123,12 @@ const _rawproductsLiveItemsSeedData = [
|
|
|
102
123
|
isSold: false,
|
|
103
124
|
mainImage: seedPhoto("live-image-bearded-dragon-1-20260817", 900, 900),
|
|
104
125
|
images: [seedPhoto("live-image-bearded-dragon-1-20260817", 900, 900)],
|
|
126
|
+
// Required for a live listing — see the note on the retriever above.
|
|
127
|
+
video: {
|
|
128
|
+
url: "/demo-media/sample-video.mp4",
|
|
129
|
+
thumbnailUrl: seedPhoto("live-video-thumb-bearded-dragon-20261004", 800, 450),
|
|
130
|
+
duration: 15,
|
|
131
|
+
},
|
|
105
132
|
status: PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED,
|
|
106
133
|
condition: PRODUCT_FIELDS.CONDITION_VALUES.NEW,
|
|
107
134
|
listingType: "live",
|
|
@@ -153,6 +180,12 @@ const _rawproductsLiveItemsSeedData = [
|
|
|
153
180
|
seedPhoto("live-image-bonsai-juniper-1-20260818", 900, 900),
|
|
154
181
|
seedPhoto("live-image-bonsai-juniper-2-20260818", 900, 900),
|
|
155
182
|
],
|
|
183
|
+
// Required for a live listing — see the note on the retriever above.
|
|
184
|
+
video: {
|
|
185
|
+
url: "/demo-media/sample-video.mp4",
|
|
186
|
+
thumbnailUrl: seedPhoto("live-video-thumb-bonsai-juniper-20261004", 800, 450),
|
|
187
|
+
duration: 15,
|
|
188
|
+
},
|
|
156
189
|
status: PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED,
|
|
157
190
|
condition: PRODUCT_FIELDS.CONDITION_VALUES.NEW,
|
|
158
191
|
listingType: "live",
|
|
@@ -203,6 +236,15 @@ const _rawproductsLiveItemsSeedData = [
|
|
|
203
236
|
images: [
|
|
204
237
|
seedPhoto("live-image-juniper-bonsai-sold-1-20260824", 900, 900),
|
|
205
238
|
],
|
|
239
|
+
// Required for a live listing — see the note on the retriever above. A SOLD
|
|
240
|
+
// fixture needs it just as much: it is the row the "Sold & Ended" scope
|
|
241
|
+
// renders, and a sold listing that could never have been created is no
|
|
242
|
+
// more representative than an available one.
|
|
243
|
+
video: {
|
|
244
|
+
url: "/demo-media/sample-video.mp4",
|
|
245
|
+
thumbnailUrl: seedPhoto("live-video-thumb-juniper-bonsai-sold-20261004", 800, 450),
|
|
246
|
+
duration: 15,
|
|
247
|
+
},
|
|
206
248
|
status: PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED,
|
|
207
249
|
condition: PRODUCT_FIELDS.CONDITION_VALUES.NEW,
|
|
208
250
|
listingType: "live",
|