@mohasinac/appkit 4.14.0 → 4.16.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/_internal/server/features/auctions/actions.js +2 -2
- package/dist/_internal/server/features/cart/service.d.ts +3 -3
- package/dist/_internal/server/features/checkout/actions.js +19 -0
- package/dist/_internal/server/features/checkout/source-context.d.ts +5 -0
- package/dist/_internal/server/features/checkout/source-context.js +157 -0
- package/dist/_internal/server/features/offers/adapters.d.ts +103 -0
- package/dist/_internal/server/features/offers/adapters.js +88 -0
- package/dist/_internal/server/features/offers/index.d.ts +2 -0
- package/dist/_internal/server/features/offers/index.js +1 -0
- package/dist/_internal/server/features/orders/adapters.js +24 -0
- package/dist/_internal/server/jobs/core/offerExpiry.js +10 -10
- package/dist/_internal/shared/actions/action-registry.d.ts +9 -2
- package/dist/_internal/shared/actions/action-registry.js +458 -7
- package/dist/_internal/shared/features/auctions/schema.d.ts +14 -2
- package/dist/_internal/shared/features/auctions/schema.js +13 -1
- package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
- package/dist/_internal/shared/features/cart/schema.d.ts +25 -20
- package/dist/_internal/shared/features/cart/schema.js +15 -0
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +22 -22
- package/dist/_internal/shared/features/orders/schema.d.ts +4 -4
- package/dist/_internal/shared/features/products/schema.d.ts +27 -27
- package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
- package/dist/_internal/shared/features/reviews/schema.d.ts +2 -2
- package/dist/_internal/shared/history/history.d.ts +22 -0
- package/dist/_internal/shared/history/history.js +41 -1
- package/dist/client.d.ts +13 -2
- package/dist/client.js +20 -2
- package/dist/constants/field-names.d.ts +8 -6
- package/dist/constants/field-names.js +48 -6
- package/dist/contracts/extend.d.ts +29 -0
- package/dist/contracts/extend.js +20 -0
- package/dist/contracts/index.d.ts +2 -1
- package/dist/contracts/index.js +2 -0
- package/dist/features/account/components/UserBidsView.js +12 -4
- package/dist/features/account/components/UserReturnsView.d.ts +3 -0
- package/dist/features/account/components/UserReturnsView.js +17 -1
- package/dist/features/admin/components/AdminAuditLogView.js +1 -0
- package/dist/features/admin/components/AdminBidsView.js +15 -2
- package/dist/features/admin/components/AdminBlogEditorView.js +65 -33
- package/dist/features/admin/components/AdminFeatureEditorView.js +35 -6
- package/dist/features/admin/components/AdminNavEditorView.js +15 -5
- package/dist/features/admin/components/AdminNewsletterView.js +18 -2
- package/dist/features/admin/components/AdminOffersView.js +62 -18
- package/dist/features/admin/components/AdminPaymentMethodsView.js +24 -4
- package/dist/features/admin/components/AdminScammerEditorView.d.ts +2 -1
- package/dist/features/admin/components/AdminScammerEditorView.js +3 -13
- package/dist/features/admin/components/AdminScammersView.js +3 -8
- package/dist/features/admin/components/AdminSectionsView.js +32 -23
- package/dist/features/admin/components/AdminSessionsView.js +17 -2
- package/dist/features/admin/components/AdminViewCards.js +24 -17
- package/dist/features/admin/components/DataListingView.js +15 -1
- package/dist/features/admin/components/DataTable.js +7 -17
- package/dist/features/admin/components/ViewAuditLogEntryModal.js +1 -0
- package/dist/features/admin/components/sections/adminSectionsTypes.d.ts +4 -2
- package/dist/features/admin/components/sections/adminSectionsTypes.js +45 -27
- package/dist/features/admin/constants/filter-tabs.d.ts +3 -0
- package/dist/features/admin/constants/filter-tabs.js +1 -0
- package/dist/features/admin/schemas/homepage-section-form.d.ts +22 -0
- package/dist/features/admin/schemas/homepage-section-form.js +68 -0
- package/dist/features/admin/schemas/nav-item-form.d.ts +74 -0
- package/dist/features/admin/schemas/nav-item-form.js +72 -0
- package/dist/features/auctions/components/AuctionBidsTable.d.ts +10 -1
- package/dist/features/auctions/components/AuctionBidsTable.js +22 -4
- package/dist/features/auctions/components/bid-detail-fields.d.ts +29 -0
- package/dist/features/auctions/components/bid-detail-fields.js +103 -0
- package/dist/features/auctions/schemas/index.d.ts +14 -14
- package/dist/features/audit-log/schemas/firestore.d.ts +14 -0
- package/dist/features/audit-log/schemas/firestore.js +7 -0
- package/dist/features/auth/schemas/index.d.ts +2 -2
- package/dist/features/blog/actions/blog-actions.d.ts +7 -7
- package/dist/features/blog/schemas/blog-form.d.ts +80 -0
- package/dist/features/blog/schemas/blog-form.js +100 -0
- package/dist/features/blog/schemas/index.d.ts +10 -10
- package/dist/features/cart/schemas/index.d.ts +3 -3
- package/dist/features/catalogue/schemas/validation.d.ts +12 -12
- package/dist/features/categories/schemas/index.d.ts +16 -16
- package/dist/features/collections/schemas/index.d.ts +8 -8
- package/dist/features/events/components/AdminEventEditorView.js +32 -54
- package/dist/features/events/components/AdminEventEntriesView.js +22 -3
- package/dist/features/events/schemas/event-form.d.ts +113 -0
- package/dist/features/events/schemas/event-form.js +82 -0
- package/dist/features/events/schemas/index.d.ts +2 -2
- package/dist/features/faq/actions/faq-actions.d.ts +6 -6
- package/dist/features/faq/schemas/index.d.ts +6 -6
- package/dist/features/grouped/schemas/grouped-listing-form.d.ts +101 -0
- package/dist/features/grouped/schemas/grouped-listing-form.js +89 -0
- package/dist/features/grouped/schemas/index.d.ts +4 -4
- package/dist/features/homepage/actions/homepage-section-actions.d.ts +11 -3
- package/dist/features/homepage/actions/homepage-section-actions.js +33 -1
- package/dist/features/homepage/schemas/index.d.ts +71 -40
- package/dist/features/homepage/schemas/index.js +24 -0
- package/dist/features/messages/schemas/index.d.ts +2 -2
- package/dist/features/orders/components/OrderStatusTimeline.d.ts +5 -1
- package/dist/features/orders/components/OrderStatusTimeline.js +39 -20
- package/dist/features/orders/repository/orders.repository.js +5 -0
- package/dist/features/orders/schemas/firestore.d.ts +36 -1
- package/dist/features/orders/schemas/index.d.ts +24 -24
- package/dist/features/orders/types/index.d.ts +35 -7
- package/dist/features/pre-orders/schemas/index.d.ts +4 -4
- package/dist/features/products/components/GroupSettingsPanel.js +5 -1
- package/dist/features/products/schemas/index.d.ts +38 -38
- package/dist/features/products/schemas/product-features.validators.d.ts +75 -2
- package/dist/features/products/schemas/product-features.validators.js +63 -0
- package/dist/features/promotions/schemas/index.d.ts +14 -14
- package/dist/features/reviews/schemas/index.d.ts +14 -14
- package/dist/features/scams/constants/scammer-status-display.d.ts +28 -0
- package/dist/features/scams/constants/scammer-status-display.js +79 -0
- package/dist/features/scams/schemas/index.d.ts +2 -2
- package/dist/features/search/schemas/index.d.ts +2 -2
- package/dist/features/seller/actions/offer-actions.js +32 -2
- package/dist/features/seller/components/OfferPhaseTimeline.d.ts +59 -0
- package/dist/features/seller/components/OfferPhaseTimeline.js +107 -0
- package/dist/features/seller/components/SellerBidsView.js +11 -4
- package/dist/features/seller/components/SellerCouponEditorView.js +17 -17
- package/dist/features/seller/components/SellerOffersView.js +2 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +38 -14
- package/dist/features/seller/repository/offer.repository.d.ts +69 -8
- package/dist/features/seller/repository/offer.repository.js +127 -23
- package/dist/features/seller/schemas/coupon-form.d.ts +72 -0
- package/dist/features/seller/schemas/coupon-form.js +116 -0
- package/dist/features/seller/schemas/firestore.d.ts +56 -2
- package/dist/features/seller/schemas/firestore.js +27 -0
- package/dist/features/seller/schemas/index.d.ts +2 -2
- package/dist/features/seller/schemas/offer-forms.d.ts +21 -0
- package/dist/features/seller/schemas/offer-forms.js +21 -0
- package/dist/features/shell/build-sections.d.ts +63 -0
- package/dist/features/shell/build-sections.js +207 -0
- package/dist/features/shell/field-ui-meta.d.ts +115 -0
- package/dist/features/shell/field-ui-meta.js +324 -0
- package/dist/features/shell/index.d.ts +4 -0
- package/dist/features/shell/index.js +2 -0
- package/dist/features/shipments/schemas/validation.d.ts +22 -22
- package/dist/features/status-history/components/StatusTimeline.d.ts +74 -0
- package/dist/features/status-history/components/StatusTimeline.js +46 -0
- package/dist/features/status-history/index.d.ts +11 -0
- package/dist/features/status-history/index.js +10 -0
- package/dist/features/store-extensions/components/ReviewDecisionModal.d.ts +27 -0
- package/dist/features/store-extensions/components/ReviewDecisionModal.js +82 -0
- package/dist/features/store-extensions/index.d.ts +12 -0
- package/dist/features/store-extensions/index.js +12 -0
- package/dist/features/store-extensions/schemas/admin-notification-form.d.ts +36 -0
- package/dist/features/store-extensions/schemas/admin-notification-form.js +114 -0
- package/dist/features/store-extensions/schemas/analytics-forms.d.ts +57 -0
- package/dist/features/store-extensions/schemas/analytics-forms.js +158 -0
- package/dist/features/store-extensions/schemas/custom-role-form.d.ts +85 -0
- package/dist/features/store-extensions/schemas/custom-role-form.js +118 -0
- package/dist/features/store-extensions/schemas/firestore.d.ts +21 -1
- package/dist/features/store-extensions/schemas/firestore.js +60 -0
- package/dist/features/store-extensions/schemas/google-config-form.d.ts +53 -0
- package/dist/features/store-extensions/schemas/google-config-form.js +105 -0
- package/dist/features/store-extensions/schemas/item-request-create-form.d.ts +28 -0
- package/dist/features/store-extensions/schemas/item-request-create-form.js +80 -0
- package/dist/features/store-extensions/schemas/listing-template-form.d.ts +78 -0
- package/dist/features/store-extensions/schemas/listing-template-form.js +87 -0
- package/dist/features/store-extensions/schemas/moderation-review-form.d.ts +49 -0
- package/dist/features/store-extensions/schemas/moderation-review-form.js +101 -0
- package/dist/features/store-extensions/schemas/payout-method-form.d.ts +153 -0
- package/dist/features/store-extensions/schemas/payout-method-form.js +155 -0
- package/dist/features/store-extensions/schemas/report-create-form.d.ts +25 -0
- package/dist/features/store-extensions/schemas/report-create-form.js +79 -0
- package/dist/features/store-extensions/schemas/report-review-form.d.ts +47 -0
- package/dist/features/store-extensions/schemas/report-review-form.js +111 -0
- package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +148 -0
- package/dist/features/store-extensions/schemas/shipping-config-form.js +104 -0
- package/dist/features/store-extensions/schemas/store-category-form.d.ts +54 -0
- package/dist/features/store-extensions/schemas/store-category-form.js +73 -0
- package/dist/features/stores/schemas/index.d.ts +4 -4
- package/dist/features/support/schemas/index.d.ts +4 -4
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +350 -0
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.js +12 -2
- package/dist/next/routing/route-map.d.ts +16 -2
- package/dist/next/routing/route-map.js +9 -2
- package/dist/schemas/firestore-value.d.ts +8 -0
- package/dist/schemas/firestore-value.js +44 -0
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.js +1 -1
- package/dist/schemas/registry.d.ts +734 -101
- package/dist/schemas/registry.js +64 -1
- package/dist/seed/bids-seed-data.js +30 -0
- package/dist/seed/offers-seed-data.js +212 -7
- package/dist/seed/orders-seed-data.js +336 -1
- package/dist/seed/products-auctions-seed-data.js +41 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +5 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/DataTable.js +4 -2
- package/dist/ui/columns/build-columns.d.ts +6 -1
- package/dist/ui/columns/build-columns.js +53 -0
- package/dist/ui/columns/cell-renderers.d.ts +68 -0
- package/dist/ui/columns/cell-renderers.js +111 -0
- package/dist/ui/columns/column-renderers.d.ts +6 -1
- package/dist/ui/columns/column-renderers.js +6 -1
- package/dist/ui/columns/index.d.ts +2 -1
- package/dist/ui/columns/index.js +5 -1
- package/dist/ui/components/Button.js +27 -2
- package/dist/ui/components/RecordDetailModal.d.ts +10 -1
- package/dist/ui/components/RecordDetailModal.js +2 -2
- package/dist/ui/icons/icon-registry.d.ts +65 -0
- package/dist/ui/icons/icon-registry.js +115 -0
- package/package.json +2 -1
- package/scripts/node-esm-loader.mjs +65 -0
- package/scripts/seed-cli-loader.mjs +6 -49
- package/scripts/seed-cli.mjs +1 -1
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
|
-
* OrderStatusTimeline —
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
4
|
+
* OrderStatusTimeline — the order-shaped wrapper around `<StatusTimeline>`.
|
|
5
|
+
*
|
|
6
|
+
* Two branches, and the fallback matters as much as the primary path:
|
|
7
|
+
*
|
|
8
|
+
* **Branch A — real history.** When the order carries `timeline` entries
|
|
9
|
+
* (written by the repository since W2), each status change becomes a step
|
|
10
|
+
* dated by when it actually happened, stamped with who did it. This finally
|
|
11
|
+
* makes transitions with no dedicated date field visible at all — a payment
|
|
12
|
+
* review, a re-upload request, a partial refund.
|
|
13
|
+
*
|
|
14
|
+
* **Branch B — legacy orders.** Every order written before `statusHistory`
|
|
15
|
+
* existed has none, and back-filling one would mean inventing timestamps. So
|
|
16
|
+
* the original derivation from the four scalar dates is kept verbatim for
|
|
17
|
+
* those. Statuses with no dedicated date field render without one.
|
|
18
|
+
*
|
|
19
|
+
* No live courier API: `trackingUrl` is the passthrough link a seller entered.
|
|
12
20
|
*/
|
|
13
|
-
import { Anchor, Badge,
|
|
21
|
+
import { Anchor, Badge, Row, Stack, Text } from "../../../ui";
|
|
22
|
+
import { StatusTimeline, stepsFromEntries, } from "../../status-history/components/StatusTimeline";
|
|
14
23
|
const STAGE_SEQUENCE = ["pending", "confirmed", "processing", "shipped", "delivered"];
|
|
15
24
|
const STAGE_LABELS = {
|
|
16
25
|
pending: "Order placed",
|
|
@@ -23,10 +32,16 @@ const STAGE_LABELS = {
|
|
|
23
32
|
returned: "Returned",
|
|
24
33
|
refunded: "Refunded",
|
|
25
34
|
};
|
|
26
|
-
|
|
35
|
+
const NEGATIVE_STATUSES = new Set(["cancelled"]);
|
|
36
|
+
const labelFor = (status) => STAGE_LABELS[status] ?? status;
|
|
37
|
+
const isNegative = (status) => NEGATIVE_STATUSES.has(status);
|
|
38
|
+
/** Branch B — derive from the four scalar dates, for orders with no history. */
|
|
39
|
+
function buildLegacySteps(props) {
|
|
27
40
|
const status = (props.orderStatus ?? "").toLowerCase();
|
|
28
41
|
const currentIndex = STAGE_SEQUENCE.indexOf(status);
|
|
29
|
-
const steps = [
|
|
42
|
+
const steps = [
|
|
43
|
+
{ key: "pending", label: STAGE_LABELS.pending, date: props.orderDate },
|
|
44
|
+
];
|
|
30
45
|
if ((status === "confirmed" || status === "processing") && !props.shippingDate) {
|
|
31
46
|
steps.push({ key: status, label: STAGE_LABELS[status] });
|
|
32
47
|
}
|
|
@@ -37,19 +52,23 @@ function buildSteps(props) {
|
|
|
37
52
|
steps.push({ key: "delivered", label: STAGE_LABELS.delivered, date: props.deliveryDate });
|
|
38
53
|
}
|
|
39
54
|
if (status === "cancelled" || props.cancellationDate) {
|
|
40
|
-
steps.push({
|
|
55
|
+
steps.push({
|
|
56
|
+
key: "cancelled",
|
|
57
|
+
label: STAGE_LABELS.cancelled,
|
|
58
|
+
date: props.cancellationDate,
|
|
59
|
+
negative: true,
|
|
60
|
+
});
|
|
41
61
|
}
|
|
42
62
|
else if (status === "return_requested" || status === "returned" || status === "refunded") {
|
|
43
63
|
steps.push({ key: status, label: STAGE_LABELS[status] ?? status });
|
|
44
64
|
}
|
|
45
65
|
return steps;
|
|
46
66
|
}
|
|
47
|
-
export function OrderStatusTimeline({ orderStatus, orderDate, shippingDate, deliveryDate, cancellationDate, trackingNumber, shippingCarrier, trackingUrl, className = "", }) {
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}) }), (trackingNumber || shippingCarrier || trackingUrl) && !isTerminalNegative && (_jsx(Div, { className: "mt-3 border-t border-[var(--appkit-color-border)]", padding: "t-sm", children: _jsxs(Stack, { gap: "xs", children: [shippingCarrier && (_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "sm", color: "muted", children: "Carrier" }), _jsx(Text, { size: "sm", weight: "medium", children: shippingCarrier })] })), trackingNumber && (_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "sm", color: "muted", children: "Tracking number" }), _jsx(Text, { size: "sm", weight: "medium", children: trackingNumber })] })), trackingUrl && (_jsx(Row, { justify: "end", children: _jsx(Anchor, { href: trackingUrl, tone: "brand", weight: "semibold", size: "sm", children: "Track with carrier \u2192" }) }))] }) })), !trackingNumber && !trackingUrl && !isTerminalNegative && (_jsx(Badge, { variant: "default", className: "mt-3", children: "No tracking details yet" }))] }));
|
|
67
|
+
export function OrderStatusTimeline({ orderStatus, timeline, timelineTruncated, orderDate, shippingDate, deliveryDate, cancellationDate, trackingNumber, shippingCarrier, trackingUrl, className = "", }) {
|
|
68
|
+
const fromHistory = stepsFromEntries(timeline, labelFor, isNegative);
|
|
69
|
+
const steps = fromHistory.length
|
|
70
|
+
? fromHistory
|
|
71
|
+
: buildLegacySteps({ orderStatus, orderDate, shippingDate, deliveryDate, cancellationDate });
|
|
72
|
+
const hasTracking = Boolean(trackingNumber || shippingCarrier || trackingUrl);
|
|
73
|
+
return (_jsx(StatusTimeline, { title: "Tracking", steps: steps, truncatedCount: timelineTruncated, className: className, footer: hasTracking ? (_jsxs(Stack, { gap: "xs", children: [shippingCarrier && (_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "sm", color: "muted", children: "Carrier" }), _jsx(Text, { size: "sm", weight: "medium", children: shippingCarrier })] })), trackingNumber && (_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "sm", color: "muted", children: "Tracking number" }), _jsx(Text, { size: "sm", weight: "medium", children: trackingNumber })] })), trackingUrl && (_jsx(Row, { justify: "end", children: _jsx(Anchor, { href: trackingUrl, tone: "brand", weight: "semibold", size: "sm", children: "Track with carrier \u2192" }) }))] })) : (_jsx(Badge, { variant: "default", children: "No tracking details yet" })) }));
|
|
55
74
|
}
|
|
@@ -95,6 +95,11 @@ class OrderRepository extends BaseRepository {
|
|
|
95
95
|
reason: ctx?.reason,
|
|
96
96
|
note: ctx?.note,
|
|
97
97
|
extraChanges: ctx?.extraChanges,
|
|
98
|
+
// `encryptPiiFields` is a flat top-level loop and never descends into
|
|
99
|
+
// arrays, so anything PII-named reaching `changes` would persist in
|
|
100
|
+
// PLAINTEXT inside statusHistory. None of ORDER_TRACKED_FIELDS is PII
|
|
101
|
+
// today — this is defence for the next field somebody adds.
|
|
102
|
+
piiFields: ORDER_PII_FIELDS,
|
|
98
103
|
historyField: "statusHistory",
|
|
99
104
|
truncatedField: "statusHistoryTruncated",
|
|
100
105
|
});
|
|
@@ -24,12 +24,39 @@ export interface OrderSourceAuctionWon {
|
|
|
24
24
|
/** Second-highest bid, when there was one. */
|
|
25
25
|
runnerUpAmount?: number;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* A buyout is a REAL BID, not a bid-free purchase.
|
|
29
|
+
*
|
|
30
|
+
* An earlier draft of this type asserted "zero bids BY DEFINITION, because
|
|
31
|
+
* buy-now is only valid while `!bidsHaveStarted`". That gate no longer
|
|
32
|
+
* exists: `buyNowAuction` places an actual `BidDocument` (`isBuyout: true`)
|
|
33
|
+
* plus a 1h locked cart line and leaves the auction **live**, and Buy Now is
|
|
34
|
+
* offered whenever `buyNowPrice` still beats the standing bid. Recording
|
|
35
|
+
* `bidCount: 0` would bake a falsehood into an immutable audit record.
|
|
36
|
+
*
|
|
37
|
+
* `standingBidAtBuyout` is the highest NON-buyout bid the buyout beat — read
|
|
38
|
+
* from the bids rather than `product.currentBid`, because a pending buyout
|
|
39
|
+
* deliberately never writes to that mirror.
|
|
40
|
+
*
|
|
41
|
+
* An unpaid buyout lapses to **`cancelled`**, not `forfeited`, and the seller
|
|
42
|
+
* is deliberately not notified: nothing was ever sold. That makes its
|
|
43
|
+
* timeline materially different from a lapsed auction win.
|
|
44
|
+
*/
|
|
27
45
|
export interface OrderSourceAuctionBuyNow {
|
|
28
46
|
path: "auction-buy-now";
|
|
29
47
|
auctionId: string;
|
|
48
|
+
/** The buyout bid itself — a buyout IS a bid. */
|
|
49
|
+
bidId: string;
|
|
30
50
|
buyNowPrice: number;
|
|
31
51
|
listPrice: number;
|
|
52
|
+
/** Highest non-buyout bid at the moment of buyout. 0 when nobody had bid. */
|
|
53
|
+
standingBidAtBuyout: number;
|
|
54
|
+
/** Active non-buyout bids at buyout time. NOT always zero. */
|
|
55
|
+
bidCount: number;
|
|
32
56
|
boughtAt: Date;
|
|
57
|
+
/** `min(now + AUCTION_BUYOUT_WINDOW_MS, auctionEndDate)`. */
|
|
58
|
+
checkoutDeadline: Date;
|
|
59
|
+
auctionEndDate?: Date;
|
|
33
60
|
}
|
|
34
61
|
export interface OrderSourceOfferAccepted {
|
|
35
62
|
path: "offer-accepted";
|
|
@@ -38,7 +65,15 @@ export interface OrderSourceOfferAccepted {
|
|
|
38
65
|
/** The asking price at the moment the offer was made. */
|
|
39
66
|
listPriceAtOffer: number;
|
|
40
67
|
counterAmount?: number;
|
|
41
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* How many counter rounds before agreement. 1 = accepted outright.
|
|
70
|
+
*
|
|
71
|
+
* Read straight off the accepted offer's `counterRound`, which W2 made a
|
|
72
|
+
* persisted field. Before that this number was **unknowable**: each counter
|
|
73
|
+
* created an unlinked document and `previousOfferId` lived only inside a
|
|
74
|
+
* `serverLogger.info` call, so a three-round negotiation left no trace of
|
|
75
|
+
* having been one.
|
|
76
|
+
*/
|
|
42
77
|
counterRounds: number;
|
|
43
78
|
acceptedBy: string;
|
|
44
79
|
acceptedAt: Date;
|
|
@@ -91,17 +91,17 @@ export declare const orderDocumentItemSchema: z.ZodObject<{
|
|
|
91
91
|
listingType: z.ZodOptional<z.ZodEnum<["standard", "auction", "pre-order", "prize-draw", "classified", "digital-code", "live"]>>;
|
|
92
92
|
prizeRevealStatus: z.ZodOptional<z.ZodEnum<["pending", "open", "closed", "revealed"]>>;
|
|
93
93
|
}, "strip", z.ZodTypeAny, {
|
|
94
|
+
quantity: number;
|
|
94
95
|
productId: string;
|
|
95
96
|
productTitle: string;
|
|
96
|
-
quantity: number;
|
|
97
97
|
unitPrice: number;
|
|
98
98
|
totalPrice: number;
|
|
99
99
|
listingType?: "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | undefined;
|
|
100
100
|
prizeRevealStatus?: "closed" | "open" | "pending" | "revealed" | undefined;
|
|
101
101
|
}, {
|
|
102
|
+
quantity: number;
|
|
102
103
|
productId: string;
|
|
103
104
|
productTitle: string;
|
|
104
|
-
quantity: number;
|
|
105
105
|
unitPrice: number;
|
|
106
106
|
totalPrice: number;
|
|
107
107
|
listingType?: "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | undefined;
|
|
@@ -168,14 +168,14 @@ export declare const appliedOrderDiscountSchema: z.ZodObject<{
|
|
|
168
168
|
code: string;
|
|
169
169
|
type: "auto" | "coupon" | "deal";
|
|
170
170
|
discountAmount: number;
|
|
171
|
-
scope?: "
|
|
171
|
+
scope?: "admin" | "seller" | undefined;
|
|
172
172
|
storeId?: string | undefined;
|
|
173
173
|
couponId?: string | undefined;
|
|
174
174
|
}, {
|
|
175
175
|
code: string;
|
|
176
176
|
type: "auto" | "coupon" | "deal";
|
|
177
177
|
discountAmount: number;
|
|
178
|
-
scope?: "
|
|
178
|
+
scope?: "admin" | "seller" | undefined;
|
|
179
179
|
storeId?: string | undefined;
|
|
180
180
|
couponId?: string | undefined;
|
|
181
181
|
}>;
|
|
@@ -250,17 +250,17 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
250
250
|
listingType: z.ZodOptional<z.ZodEnum<["standard", "auction", "pre-order", "prize-draw", "classified", "digital-code", "live"]>>;
|
|
251
251
|
prizeRevealStatus: z.ZodOptional<z.ZodEnum<["pending", "open", "closed", "revealed"]>>;
|
|
252
252
|
}, "strip", z.ZodTypeAny, {
|
|
253
|
+
quantity: number;
|
|
253
254
|
productId: string;
|
|
254
255
|
productTitle: string;
|
|
255
|
-
quantity: number;
|
|
256
256
|
unitPrice: number;
|
|
257
257
|
totalPrice: number;
|
|
258
258
|
listingType?: "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | undefined;
|
|
259
259
|
prizeRevealStatus?: "closed" | "open" | "pending" | "revealed" | undefined;
|
|
260
260
|
}, {
|
|
261
|
+
quantity: number;
|
|
261
262
|
productId: string;
|
|
262
263
|
productTitle: string;
|
|
263
|
-
quantity: number;
|
|
264
264
|
unitPrice: number;
|
|
265
265
|
totalPrice: number;
|
|
266
266
|
listingType?: "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | undefined;
|
|
@@ -326,14 +326,14 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
326
326
|
code: string;
|
|
327
327
|
type: "auto" | "coupon" | "deal";
|
|
328
328
|
discountAmount: number;
|
|
329
|
-
scope?: "
|
|
329
|
+
scope?: "admin" | "seller" | undefined;
|
|
330
330
|
storeId?: string | undefined;
|
|
331
331
|
couponId?: string | undefined;
|
|
332
332
|
}, {
|
|
333
333
|
code: string;
|
|
334
334
|
type: "auto" | "coupon" | "deal";
|
|
335
335
|
discountAmount: number;
|
|
336
|
-
scope?: "
|
|
336
|
+
scope?: "admin" | "seller" | undefined;
|
|
337
337
|
storeId?: string | undefined;
|
|
338
338
|
couponId?: string | undefined;
|
|
339
339
|
}>, "many">>;
|
|
@@ -547,11 +547,11 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
547
547
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
548
548
|
}, z.ZodTypeAny, "passthrough">;
|
|
549
549
|
userId: string;
|
|
550
|
+
quantity: number;
|
|
550
551
|
productId: string;
|
|
551
552
|
productTitle: string;
|
|
552
553
|
userName: string;
|
|
553
554
|
userEmail: string;
|
|
554
|
-
quantity: number;
|
|
555
555
|
unitPrice: number;
|
|
556
556
|
totalPrice: number;
|
|
557
557
|
paymentStatus: "paid" | "failed" | "pending" | "processing" | "refunded" | "partial_refund";
|
|
@@ -562,6 +562,7 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
562
562
|
platformFee?: number | undefined;
|
|
563
563
|
paymentMethod?: string | undefined;
|
|
564
564
|
notes?: string | undefined;
|
|
565
|
+
storeName?: string | undefined;
|
|
565
566
|
prizeRevealMode?: "scheduled" | "instant" | undefined;
|
|
566
567
|
paymentId?: string | undefined;
|
|
567
568
|
shippingAddress?: string | undefined;
|
|
@@ -587,9 +588,9 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
587
588
|
shippingCarrier?: string | undefined;
|
|
588
589
|
trackingUrl?: string | undefined;
|
|
589
590
|
items?: {
|
|
591
|
+
quantity: number;
|
|
590
592
|
productId: string;
|
|
591
593
|
productTitle: string;
|
|
592
|
-
quantity: number;
|
|
593
594
|
unitPrice: number;
|
|
594
595
|
totalPrice: number;
|
|
595
596
|
listingType?: "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | undefined;
|
|
@@ -605,7 +606,6 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
605
606
|
}, z.ZodTypeAny, "passthrough">;
|
|
606
607
|
} | undefined;
|
|
607
608
|
prizeDrawProductId?: string | undefined;
|
|
608
|
-
storeName?: string | undefined;
|
|
609
609
|
couponCode?: string | undefined;
|
|
610
610
|
physicalLocation?: {
|
|
611
611
|
zone: string;
|
|
@@ -622,7 +622,7 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
622
622
|
code: string;
|
|
623
623
|
type: "auto" | "coupon" | "deal";
|
|
624
624
|
discountAmount: number;
|
|
625
|
-
scope?: "
|
|
625
|
+
scope?: "admin" | "seller" | undefined;
|
|
626
626
|
storeId?: string | undefined;
|
|
627
627
|
couponId?: string | undefined;
|
|
628
628
|
}[] | undefined;
|
|
@@ -695,11 +695,11 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
695
695
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
696
696
|
}, z.ZodTypeAny, "passthrough">;
|
|
697
697
|
userId: string;
|
|
698
|
+
quantity: number;
|
|
698
699
|
productId: string;
|
|
699
700
|
productTitle: string;
|
|
700
701
|
userName: string;
|
|
701
702
|
userEmail: string;
|
|
702
|
-
quantity: number;
|
|
703
703
|
unitPrice: number;
|
|
704
704
|
totalPrice: number;
|
|
705
705
|
paymentStatus: "paid" | "failed" | "pending" | "processing" | "refunded" | "partial_refund";
|
|
@@ -710,6 +710,7 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
710
710
|
platformFee?: number | undefined;
|
|
711
711
|
paymentMethod?: string | undefined;
|
|
712
712
|
notes?: string | undefined;
|
|
713
|
+
storeName?: string | undefined;
|
|
713
714
|
prizeRevealMode?: "scheduled" | "instant" | undefined;
|
|
714
715
|
paymentId?: string | undefined;
|
|
715
716
|
shippingAddress?: string | undefined;
|
|
@@ -735,9 +736,9 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
735
736
|
shippingCarrier?: string | undefined;
|
|
736
737
|
trackingUrl?: string | undefined;
|
|
737
738
|
items?: {
|
|
739
|
+
quantity: number;
|
|
738
740
|
productId: string;
|
|
739
741
|
productTitle: string;
|
|
740
|
-
quantity: number;
|
|
741
742
|
unitPrice: number;
|
|
742
743
|
totalPrice: number;
|
|
743
744
|
listingType?: "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | undefined;
|
|
@@ -753,7 +754,6 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
753
754
|
}, z.ZodTypeAny, "passthrough">;
|
|
754
755
|
} | undefined;
|
|
755
756
|
prizeDrawProductId?: string | undefined;
|
|
756
|
-
storeName?: string | undefined;
|
|
757
757
|
couponCode?: string | undefined;
|
|
758
758
|
physicalLocation?: {
|
|
759
759
|
zone: string;
|
|
@@ -770,7 +770,7 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
770
770
|
code: string;
|
|
771
771
|
type: "auto" | "coupon" | "deal";
|
|
772
772
|
discountAmount: number;
|
|
773
|
-
scope?: "
|
|
773
|
+
scope?: "admin" | "seller" | undefined;
|
|
774
774
|
storeId?: string | undefined;
|
|
775
775
|
couponId?: string | undefined;
|
|
776
776
|
}[] | undefined;
|
|
@@ -847,8 +847,8 @@ export declare const orderItemSchema: z.ZodObject<{
|
|
|
847
847
|
}, "strip", z.ZodTypeAny, {
|
|
848
848
|
title: string;
|
|
849
849
|
price: number;
|
|
850
|
-
productId: string;
|
|
851
850
|
quantity: number;
|
|
851
|
+
productId: string;
|
|
852
852
|
currency?: string | undefined;
|
|
853
853
|
image?: string | undefined;
|
|
854
854
|
storeId?: string | undefined;
|
|
@@ -856,8 +856,8 @@ export declare const orderItemSchema: z.ZodObject<{
|
|
|
856
856
|
}, {
|
|
857
857
|
title: string;
|
|
858
858
|
price: number;
|
|
859
|
-
productId: string;
|
|
860
859
|
quantity: number;
|
|
860
|
+
productId: string;
|
|
861
861
|
currency?: string | undefined;
|
|
862
862
|
image?: string | undefined;
|
|
863
863
|
storeId?: string | undefined;
|
|
@@ -907,8 +907,8 @@ export declare const orderSchema: z.ZodObject<{
|
|
|
907
907
|
}, "strip", z.ZodTypeAny, {
|
|
908
908
|
title: string;
|
|
909
909
|
price: number;
|
|
910
|
-
productId: string;
|
|
911
910
|
quantity: number;
|
|
911
|
+
productId: string;
|
|
912
912
|
currency?: string | undefined;
|
|
913
913
|
image?: string | undefined;
|
|
914
914
|
storeId?: string | undefined;
|
|
@@ -916,8 +916,8 @@ export declare const orderSchema: z.ZodObject<{
|
|
|
916
916
|
}, {
|
|
917
917
|
title: string;
|
|
918
918
|
price: number;
|
|
919
|
-
productId: string;
|
|
920
919
|
quantity: number;
|
|
920
|
+
productId: string;
|
|
921
921
|
currency?: string | undefined;
|
|
922
922
|
image?: string | undefined;
|
|
923
923
|
storeId?: string | undefined;
|
|
@@ -962,18 +962,18 @@ export declare const orderSchema: z.ZodObject<{
|
|
|
962
962
|
[k: string]: unknown;
|
|
963
963
|
};
|
|
964
964
|
userId: string;
|
|
965
|
+
total: number;
|
|
965
966
|
paymentStatus: string;
|
|
966
967
|
items: {
|
|
967
968
|
title: string;
|
|
968
969
|
price: number;
|
|
969
|
-
productId: string;
|
|
970
970
|
quantity: number;
|
|
971
|
+
productId: string;
|
|
971
972
|
currency?: string | undefined;
|
|
972
973
|
image?: string | undefined;
|
|
973
974
|
storeId?: string | undefined;
|
|
974
975
|
attributes?: Record<string, string> | undefined;
|
|
975
976
|
}[];
|
|
976
|
-
total: number;
|
|
977
977
|
subtotal: number;
|
|
978
978
|
orderStatus: "pending" | "cancelled" | "processing" | "refunded" | "delivered" | "confirmed" | "shipped" | "return_requested" | "returned";
|
|
979
979
|
createdAt?: string | undefined;
|
|
@@ -999,18 +999,18 @@ export declare const orderSchema: z.ZodObject<{
|
|
|
999
999
|
[k: string]: unknown;
|
|
1000
1000
|
};
|
|
1001
1001
|
userId: string;
|
|
1002
|
+
total: number;
|
|
1002
1003
|
paymentStatus: string;
|
|
1003
1004
|
items: {
|
|
1004
1005
|
title: string;
|
|
1005
1006
|
price: number;
|
|
1006
|
-
productId: string;
|
|
1007
1007
|
quantity: number;
|
|
1008
|
+
productId: string;
|
|
1008
1009
|
currency?: string | undefined;
|
|
1009
1010
|
image?: string | undefined;
|
|
1010
1011
|
storeId?: string | undefined;
|
|
1011
1012
|
attributes?: Record<string, string> | undefined;
|
|
1012
1013
|
}[];
|
|
1013
|
-
total: number;
|
|
1014
1014
|
subtotal: number;
|
|
1015
1015
|
orderStatus: "pending" | "cancelled" | "processing" | "refunded" | "delivered" | "confirmed" | "shipped" | "return_requested" | "returned";
|
|
1016
1016
|
createdAt?: string | undefined;
|
|
@@ -2,7 +2,8 @@ import { type PaymentGateway, PaymentGatewayValues } from "../../payments/schema
|
|
|
2
2
|
export { type PaymentGateway, PaymentGatewayValues };
|
|
3
3
|
import type { ListingType } from "../../products/types/index";
|
|
4
4
|
import type { OrderType } from "../utils/order-splitter";
|
|
5
|
-
import type { AppliedOrderDiscount } from "../schemas/firestore";
|
|
5
|
+
import type { AppliedOrderDiscount, OrderSourceContext } from "../schemas/firestore";
|
|
6
|
+
import type { FieldChange } from "../../../_internal/shared/history/index";
|
|
6
7
|
export type PaymentStatus = "pending" | "processing" | "paid" | "failed" | "refunded" | "partial_refund";
|
|
7
8
|
export interface UserAddress {
|
|
8
9
|
id: string;
|
|
@@ -46,12 +47,34 @@ export interface OrderItem {
|
|
|
46
47
|
/** Snapshot of bundle.bundleProductIds at order-creation time. */
|
|
47
48
|
bundleProductIds?: string[];
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
/**
|
|
51
|
+
* One entry on an order's timeline — the client-facing shape of
|
|
52
|
+
* `StatusChangeEntry`, with dates as ISO strings.
|
|
53
|
+
*
|
|
54
|
+
* The previous declaration here was `{status, message?, timestamp, actor?}`
|
|
55
|
+
* and had **zero writers** in the entire codebase since the day it was
|
|
56
|
+
* added, so nothing depended on it. `OrderStatusTimeline` synthesised its
|
|
57
|
+
* steps from four scalar date fields instead, which meant any transition
|
|
58
|
+
* without a dedicated date field — payment reviewed, proof re-upload asked
|
|
59
|
+
* for, a partial refund posted — could not appear at all.
|
|
60
|
+
*/
|
|
61
|
+
export interface OrderTimelineEntry {
|
|
62
|
+
at: string;
|
|
63
|
+
actorUid?: string;
|
|
64
|
+
actorRole: "buyer" | "seller" | "admin" | "system";
|
|
65
|
+
/**
|
|
66
|
+
* Delta only: `{ status: { from: "confirmed", to: "shipped" } }`.
|
|
67
|
+
* Reuses the primitive's `FieldChange` rather than restating the shape, so
|
|
68
|
+
* the client type cannot drift from what the repository writes.
|
|
69
|
+
*/
|
|
70
|
+
changes: Record<string, FieldChange>;
|
|
71
|
+
reason?: string;
|
|
72
|
+
note?: string;
|
|
73
|
+
/** The function or job that caused it — what the timeline renders by. */
|
|
74
|
+
trigger: string;
|
|
54
75
|
}
|
|
76
|
+
/** @deprecated Use {@link OrderTimelineEntry}. Kept only to avoid breaking a stale import. */
|
|
77
|
+
export type OrderTimeline = OrderTimelineEntry;
|
|
55
78
|
export interface Order {
|
|
56
79
|
id: string;
|
|
57
80
|
userId: string;
|
|
@@ -108,7 +131,12 @@ export interface Order {
|
|
|
108
131
|
/** Carrier tracking page URL — rendered as an external link that opens in a new tab. No live-tracking API integration; this is just the passthrough URL a seller/admin entered. */
|
|
109
132
|
trackingUrl?: string;
|
|
110
133
|
notes?: string;
|
|
111
|
-
|
|
134
|
+
/** Real recorded transitions — see {@link OrderTimelineEntry}. */
|
|
135
|
+
timeline?: OrderTimelineEntry[];
|
|
136
|
+
/** Entries trimmed off the front of the capped history, if any. */
|
|
137
|
+
timelineTruncated?: number;
|
|
138
|
+
/** How the buyer acquired the right to buy. Written once, at creation. */
|
|
139
|
+
sourceContext?: OrderSourceContext;
|
|
112
140
|
physicalLocation?: {
|
|
113
141
|
zone: string;
|
|
114
142
|
shelf: string;
|
|
@@ -50,14 +50,13 @@ export declare const preorderItemSchema: z.ZodObject<{
|
|
|
50
50
|
}, "strip", z.ZodTypeAny, {
|
|
51
51
|
id: string;
|
|
52
52
|
name: string;
|
|
53
|
-
active: boolean;
|
|
54
53
|
slug: string;
|
|
54
|
+
active: boolean;
|
|
55
55
|
isFeatured: boolean;
|
|
56
56
|
salePrice: number;
|
|
57
57
|
regularPrice: number;
|
|
58
58
|
brand?: string | undefined;
|
|
59
59
|
createdAt?: string | undefined;
|
|
60
|
-
images?: string[] | undefined;
|
|
61
60
|
media?: {
|
|
62
61
|
type: "video" | "image" | "file";
|
|
63
62
|
url: string;
|
|
@@ -67,6 +66,7 @@ export declare const preorderItemSchema: z.ZodObject<{
|
|
|
67
66
|
youtubeId?: string | undefined;
|
|
68
67
|
duration?: number | undefined;
|
|
69
68
|
}[] | undefined;
|
|
69
|
+
images?: string[] | undefined;
|
|
70
70
|
franchise?: string | undefined;
|
|
71
71
|
preorderShipDate?: string | undefined;
|
|
72
72
|
}, {
|
|
@@ -78,8 +78,6 @@ export declare const preorderItemSchema: z.ZodObject<{
|
|
|
78
78
|
brand?: string | undefined;
|
|
79
79
|
createdAt?: string | undefined;
|
|
80
80
|
active?: boolean | undefined;
|
|
81
|
-
images?: string[] | undefined;
|
|
82
|
-
isFeatured?: boolean | undefined;
|
|
83
81
|
media?: {
|
|
84
82
|
type: "video" | "image" | "file";
|
|
85
83
|
url: string;
|
|
@@ -89,6 +87,8 @@ export declare const preorderItemSchema: z.ZodObject<{
|
|
|
89
87
|
youtubeId?: string | undefined;
|
|
90
88
|
duration?: number | undefined;
|
|
91
89
|
}[] | undefined;
|
|
90
|
+
images?: string[] | undefined;
|
|
91
|
+
isFeatured?: boolean | undefined;
|
|
92
92
|
franchise?: string | undefined;
|
|
93
93
|
preorderShipDate?: string | undefined;
|
|
94
94
|
}>;
|
|
@@ -235,7 +235,11 @@ export function GroupSettingsPanel({ productId, productSlug, groupId, isGroupPar
|
|
|
235
235
|
setOpen(next);
|
|
236
236
|
if (next && isGroupParent && children === null)
|
|
237
237
|
loadChildren();
|
|
238
|
-
}, paddingX: "none", paddingY: "xs", justify: "between", className: "w-full text-left group", "aria-expanded": open, children: [_jsx(Heading, { level: 3, size: "sm", weight: "semibold", color: "muted", children: "Group Settings" }), _jsx(Span, { size: "xs", className: "group-hover:text-[var(--appkit-color-text-muted)] dark:group-hover:text-[var(--appkit-color-text-faint)] transition-colors", color: "faint", children: open ? "▲" : "▼" })] }), open && (_jsxs(Stack, { gap: "sm", className: `mt-3 ${__P.p4}`, surface: "muted", rounded: "lg", border: "default", children: [!groupId && !groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "xs", color: "muted", children: "Group related listings together \u2014 e.g. a set, bundle, or multi-part item. Parts can be sold individually but shown together." }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: startGroup, isLoading: loading, children: "Start a group" })] })), isGroupParent && groupId && (_jsxs(Stack, { gap: "md", children: [_jsxs(FormShellContext.Provider, { value: titleShellCtx, children: [_jsxs(Row, { align: "start", gap: "sm", wrap: true, children: [_jsx(Div, { className: "flex-1 min-w-[200px]", children: _jsx(FormField, { name: "groupTitle", label: "Group title", type: "text", value: editTitle, onChange: setEditTitle, placeholder: "e.g. Human Toy Complete Set" }) }), _jsx(Div, { padding: "t-lg", children: _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: saveTitle, isLoading: loading, children: "Save title" }) })] }), _jsx(FormErrorSummary, {})] }), _jsxs(Div, { children: [_jsxs(Text, { className: "mb-2", color: "muted", size: "xs", weight: "semibold", children: ["Members (", childSlugsCount + 1, " \u2014 including this listing)"] }), loading && !children ? (_jsx(Text, { size: "xs", color: "faint", children: "Loading\u2026" })) : (_jsxs(Div, { className: "divide-y divide-zinc-100 divide-[var(--appkit-color-border-subtle)]", children: [_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [_jsx(Span, { padding: "pill-2xs", weight: "semibold", className: "bg-[var(--appkit-color-primary)]/10 text-[var(--appkit-color-primary)] text-[10px]", rounded: "default", children: "Parent" }), _jsx(Text, { className: "flex-1", color: "primary", size: "sm", children: productSlug })] }), (children ?? []).filter((c) => c.id !== productId).map((child) => (_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [child.images?.[0] ? (_jsx(Div, { className: "relative w-8 h-8 flex-shrink-0 border border-[var(--appkit-color-border)]", rounded: "full", overflow: "hidden", children: _jsx(MediaImage, { src: child.images[0], alt: child.title, size: "thumbnail" }) })) : (_jsx(Div, { className: "w-8 h-8", surface: "subtle", rounded: "full" })), _jsx(Text, { className: "flex-1 truncate", color: "primary", size: "sm", children: child.title }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => requestUnlinkChild(child.id), isLoading: loading, className: `${CLS_DELETE_LINK} text-[length:var(--appkit-text-xs)]`, children: "Unlink" })] }, child.id)))] }))] }), _jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => setShowAddModal(true), children: "Add child listing" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestDissolveGroup, isLoading: loading, className: CLS_DELETE_LINK, children: "Dissolve group" })] })] })), !isGroupParent && groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsxs(Text, { size: "sm", color: "muted", children: ["Part of:", " ", _jsx(Span, { weight: "medium", color: "primary", children: groupTitle ?? groupParentSlug })] }), _jsxs(Text, { size: "xs", color: "muted", children: ["Parent listing: ", _jsx(Code, { className: "font-mono", children: groupParentSlug })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestLeaveGroup, isLoading: loading, className: `${CLS_DELETE_LINK} w-fit`, children: "Leave group" })] }))] })), (
|
|
238
|
+
}, paddingX: "none", paddingY: "xs", justify: "between", className: "w-full text-left group", "aria-expanded": open, children: [_jsx(Heading, { level: 3, size: "sm", weight: "semibold", color: "muted", children: "Group Settings" }), _jsx(Span, { size: "xs", className: "group-hover:text-[var(--appkit-color-text-muted)] dark:group-hover:text-[var(--appkit-color-text-faint)] transition-colors", color: "faint", children: open ? "▲" : "▼" })] }), open && (_jsxs(Stack, { gap: "sm", className: `mt-3 ${__P.p4}`, surface: "muted", rounded: "lg", border: "default", children: [!groupId && !groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "xs", color: "muted", children: "Group related listings together \u2014 e.g. a set, bundle, or multi-part item. Parts can be sold individually but shown together." }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: startGroup, isLoading: loading, children: "Start a group" })] })), isGroupParent && groupId && (_jsxs(Stack, { gap: "md", children: [_jsxs(FormShellContext.Provider, { value: titleShellCtx, children: [_jsxs(Row, { align: "start", gap: "sm", wrap: true, children: [_jsx(Div, { className: "flex-1 min-w-[200px]", children: _jsx(FormField, { name: "groupTitle", label: "Group title", type: "text", value: editTitle, onChange: setEditTitle, placeholder: "e.g. Human Toy Complete Set" }) }), _jsx(Div, { padding: "t-lg", children: _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: saveTitle, isLoading: loading, children: "Save title" }) })] }), _jsx(FormErrorSummary, {})] }), _jsxs(Div, { children: [_jsxs(Text, { className: "mb-2", color: "muted", size: "xs", weight: "semibold", children: ["Members (", childSlugsCount + 1, " \u2014 including this listing)"] }), loading && !children ? (_jsx(Text, { size: "xs", color: "faint", children: "Loading\u2026" })) : (_jsxs(Div, { className: "divide-y divide-zinc-100 divide-[var(--appkit-color-border-subtle)]", children: [_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [_jsx(Span, { padding: "pill-2xs", weight: "semibold", className: "bg-[var(--appkit-color-primary)]/10 text-[var(--appkit-color-primary)] text-[10px]", rounded: "default", children: "Parent" }), _jsx(Text, { className: "flex-1", color: "primary", size: "sm", children: productSlug })] }), (children ?? []).filter((c) => c.id !== productId).map((child) => (_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [child.images?.[0] ? (_jsx(Div, { className: "relative w-8 h-8 flex-shrink-0 border border-[var(--appkit-color-border)]", rounded: "full", overflow: "hidden", children: _jsx(MediaImage, { src: child.images[0], alt: child.title, size: "thumbnail" }) })) : (_jsx(Div, { className: "w-8 h-8", surface: "subtle", rounded: "full" })), _jsx(Text, { className: "flex-1 truncate", color: "primary", size: "sm", children: child.title }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => requestUnlinkChild(child.id), isLoading: loading, className: `${CLS_DELETE_LINK} text-[length:var(--appkit-text-xs)]`, children: "Unlink" })] }, child.id)))] }))] }), _jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => setShowAddModal(true), children: "Add child listing" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestDissolveGroup, isLoading: loading, className: CLS_DELETE_LINK, children: "Dissolve group" })] })] })), !isGroupParent && groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsxs(Text, { size: "sm", color: "muted", children: ["Part of:", " ", _jsx(Span, { weight: "medium", color: "primary", children: groupTitle ?? groupParentSlug })] }), _jsxs(Text, { size: "xs", color: "muted", children: ["Parent listing: ", _jsx(Code, { className: "font-mono", children: groupParentSlug })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestLeaveGroup, isLoading: loading, className: `${CLS_DELETE_LINK} w-fit`, children: "Leave group" })] }))] })), (() => {
|
|
239
|
+
const content = (_jsx(AddChildContent, { addTab: addTab, setAddTab: setAddTab, createForm: createForm, setCreateForm: setCreateForm, productSlug: productSlug, storeProductsEndpoint: storeProductsEndpoint, linkTargets: linkTargets, setLinkTargets: setLinkTargets, onAddCreate: addCreateChild, onAddLink: addLinkChild, loading: loading }));
|
|
240
|
+
const close = () => setShowAddModal(false);
|
|
241
|
+
return (groupChildSlugs?.length ?? 0) >= 4 ? (_jsx(SideDrawer, { isOpen: showAddModal, onClose: close, title: "Add child listing", children: content })) : (_jsx(Modal, { open: showAddModal, onClose: close, title: "Add child listing", size: "lg", children: content }));
|
|
242
|
+
})(), confirmAction && (_jsx(ConfirmDeleteModal, { isOpen: true, title: confirmAction.title, message: confirmAction.message, onConfirm: confirmAction.onConfirm, onClose: () => setConfirmAction(null), isDeleting: loading }))] }));
|
|
239
243
|
}
|
|
240
244
|
function AddChildContent({ addTab, setAddTab, createForm, setCreateForm, productSlug, storeProductsEndpoint, linkTargets, setLinkTargets, onAddCreate, onAddLink, loading, }) {
|
|
241
245
|
const { shellCtx, validate } = useFormShellState(createChildSchema);
|