@mohasinac/appkit 4.1.0 → 4.1.3
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/client/features/maintenance/index.d.ts +2 -0
- package/dist/_internal/client/features/maintenance/index.js +1 -0
- package/dist/_internal/client/features/maintenance/views/CloudLogsListView.d.ts +9 -0
- package/dist/_internal/client/features/maintenance/views/CloudLogsListView.js +55 -0
- package/dist/_internal/server/features/auctions/index.d.ts +1 -1
- package/dist/_internal/server/features/auctions/index.js +1 -1
- package/dist/_internal/server/features/auctions/service.js +2 -2
- package/dist/_internal/server/features/maintenance/cloud-logs-data.d.ts +50 -0
- package/dist/_internal/server/features/maintenance/cloud-logs-data.js +152 -0
- package/dist/_internal/server/jobs/core/onOrderCreate.d.ts +4 -12
- package/dist/_internal/server/jobs/core/onOrderCreate.js +3 -3
- package/dist/_internal/server/jobs/core/onProductWrite.js +14 -2
- package/dist/_internal/shared/features/auctions/config.d.ts +1 -1
- package/dist/_internal/shared/features/auctions/config.js +1 -1
- package/dist/_internal/shared/features/auctions/schema.js +1 -1
- package/dist/_internal/shared/features/cart/schema.js +2 -2
- package/dist/_internal/shared/features/events/schema.js +1 -1
- package/dist/_internal/shared/features/orders/schema.js +1 -1
- package/dist/_internal/shared/features/products/schema.js +3 -3
- package/dist/_internal/shared/features/promotions/schema.js +3 -3
- package/dist/_internal/shared/fees/calculator.d.ts +6 -7
- package/dist/client.d.ts +4 -4
- package/dist/client.js +4 -2
- package/dist/constants/api-endpoints.d.ts +9 -6
- package/dist/constants/api-endpoints.js +3 -2
- package/dist/contracts/client-payment-gateway.d.ts +1 -2
- package/dist/features/about/components/AboutView.d.ts +6 -16
- package/dist/features/about/components/AboutView.js +3 -3
- package/dist/features/about/index.d.ts +2 -1
- package/dist/features/about/schemas/firestore.d.ts +47 -0
- package/dist/features/about/schemas/firestore.js +6 -0
- package/dist/features/about/schemas/index.d.ts +210 -0
- package/dist/features/about/schemas/index.js +45 -0
- package/dist/features/account/hooks/useProfile.js +3 -0
- package/dist/features/admin/components/AdminCarouselGroupEditorView.d.ts +6 -0
- package/dist/features/admin/components/AdminCarouselGroupEditorView.js +50 -0
- package/dist/features/admin/components/AdminCartsView.js +16 -3
- package/dist/features/admin/components/AdminCouponEditorView.js +2 -2
- package/dist/features/admin/components/AdminCouponsView.js +14 -4
- package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -42
- package/dist/features/admin/components/AdminMediaView.js +1 -1
- package/dist/features/admin/components/AdminNotificationsView.js +31 -19
- package/dist/features/admin/components/AdminOrdersView.js +7 -0
- package/dist/features/admin/components/AdminPayoutsView.js +18 -3
- package/dist/features/admin/components/AdminProductsView.js +17 -2
- package/dist/features/admin/components/AdminReviewsView.js +16 -2
- package/dist/features/admin/components/AdminScammersView.js +7 -0
- package/dist/features/admin/components/AdminSectionsView.js +4 -0
- package/dist/features/admin/components/AdminSiteConfigGuideView.js +1 -1
- package/dist/features/admin/components/AdminSiteSettingsView.js +44 -2
- package/dist/features/admin/components/AdminStoreEditorView.d.ts +2 -1
- package/dist/features/admin/components/AdminStoreEditorView.js +4 -4
- package/dist/features/admin/components/AdminStoresView.js +1 -1
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +23 -5
- package/dist/features/admin/components/AdminSupportTicketsView.js +20 -2
- package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +4 -1
- package/dist/features/admin/components/AdminTesterChecklistView.js +8 -0
- package/dist/features/admin/components/index.d.ts +2 -0
- package/dist/features/admin/components/index.js +1 -0
- package/dist/features/admin/constants/filter-tabs.d.ts +55 -41
- package/dist/features/admin/constants/filter-tabs.js +55 -27
- package/dist/features/admin/schemas/firestore.d.ts +5 -0
- package/dist/features/auctions/actions/bid-actions.js +1 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +2 -2
- package/dist/features/auctions/components/AuctionsListView.js +8 -1
- package/dist/features/auth/components/LoginForm.js +2 -2
- package/dist/features/auth/components/RegisterForm.js +2 -2
- package/dist/features/auth/permissions/constants.d.ts +16 -0
- package/dist/features/auth/permissions/constants.js +53 -0
- package/dist/features/auth/schemas/firestore.js +1 -0
- package/dist/features/blog/components/BlogFilters.js +1 -1
- package/dist/features/cart/schemas/firestore.d.ts +1 -1
- package/dist/features/categories/schemas/firestore.d.ts +1 -1
- package/dist/features/consultation/components/ConsultationForm.js +1 -1
- package/dist/features/events/components/EventFilters.js +2 -0
- package/dist/features/homepage/components/WelcomeSection.js +2 -2
- package/dist/features/layout/TitleBarLayout.d.ts +2 -2
- package/dist/features/layout/TitleBarLayout.js +4 -4
- package/dist/features/media/AvatarUpload.js +7 -3
- package/dist/features/media/MediaVideo.js +1 -1
- package/dist/features/media/finalize.d.ts +9 -13
- package/dist/features/media/finalize.js +23 -74
- package/dist/features/media/server.d.ts +1 -1
- package/dist/features/media/server.js +1 -1
- package/dist/features/orders/hooks/useOrders.js +16 -4
- package/dist/features/orders/schemas/firestore.d.ts +5 -5
- package/dist/features/payments/schemas/firestore.d.ts +2 -2
- package/dist/features/pre-orders/components/PreOrdersListView.js +7 -0
- package/dist/features/products/components/ArtStickersListView.js +5 -0
- package/dist/features/products/components/ProductDetailPageView.d.ts +7 -1
- package/dist/features/products/components/ProductForm.js +14 -1
- package/dist/features/products/components/ProductsIndexPageView.js +7 -0
- package/dist/features/products/constants/action-defs.d.ts +1 -0
- package/dist/features/products/constants/action-defs.js +1 -0
- package/dist/features/products/schemas/firestore.d.ts +1 -1
- package/dist/features/products/schemas/product-templates.d.ts +1 -1
- package/dist/features/products/types/index.d.ts +4 -0
- package/dist/features/scams/schemas/index.js +2 -2
- package/dist/features/search/components/Search.js +3 -3
- package/dist/features/seller/components/SellerAuctionsView.js +27 -2
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutsView.js +24 -10
- package/dist/features/seller/components/SellerPreOrdersView.js +12 -4
- package/dist/features/seller/components/SellerPrizeDrawsView.js +23 -5
- package/dist/features/seller/components/SellerProductShell.d.ts +2 -0
- package/dist/features/seller/components/SellerProductShell.js +1 -1
- package/dist/features/seller/components/SellerProductsView.js +8 -6
- package/dist/features/seller/components/SellerReviewsView.js +27 -6
- package/dist/features/seller/components/index.d.ts +0 -2
- package/dist/features/seller/components/index.js +0 -1
- package/dist/features/stores/components/StoreListingsGuideView.js +2 -1
- package/dist/features/stores/components/StoreProductsView.js +1 -1
- package/dist/features/stores/schemas/firestore.d.ts +11 -0
- package/dist/features/stores/schemas/firestore.js +5 -0
- package/dist/features/stores/schemas/index.d.ts +2 -2
- package/dist/features/tester/actions/checklist-item-actions.d.ts +6 -0
- package/dist/features/tester/actions/checklist-item-actions.js +2 -0
- package/dist/features/tester/components/AdminTesterFeedbackIssuesView.js +13 -2
- package/dist/features/tester/components/AdminTesterFeedbackListView.js +2 -1
- package/dist/features/tester/components/AdminTesterFeedbackReportView.js +9 -5
- package/dist/features/tester/components/TesterHubView.js +34 -21
- package/dist/features/tester/repository/tester-checklist-item.repository.js +1 -0
- package/dist/features/tester/repository/tester-checklist-response.repository.d.ts +18 -4
- package/dist/features/tester/repository/tester-checklist-response.repository.js +43 -8
- package/dist/features/tester/schemas/firestore.d.ts +8 -3
- package/dist/features/tester/schemas/firestore.js +6 -0
- package/dist/features/tester/seed-data/bids-tester-seed-data.d.ts +2 -0
- package/dist/features/tester/seed-data/bids-tester-seed-data.js +37 -0
- package/dist/features/tester/seed-data/coupons-tester-seed-data.d.ts +2 -0
- package/dist/features/tester/seed-data/coupons-tester-seed-data.js +76 -0
- package/dist/features/tester/seed-data/events-tester-seed-data.js +50 -2
- package/dist/features/tester/seed-data/index.d.ts +3 -0
- package/dist/features/tester/seed-data/index.js +3 -0
- package/dist/features/tester/seed-data/orders-tester-seed-data.d.ts +2 -0
- package/dist/features/tester/seed-data/orders-tester-seed-data.js +265 -0
- package/dist/features/tester/seed-data/products-tester-seed-data.js +213 -8
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +294 -12
- package/dist/features/tester/utils/phases.d.ts +31 -0
- package/dist/features/tester/utils/phases.js +46 -0
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +1 -1
- package/dist/features/whatsapp-bot/types/index.d.ts +1 -1
- package/dist/features/wishlist/types/index.d.ts +3 -0
- package/dist/index.d.ts +11 -4
- package/dist/index.js +15 -7
- package/dist/next/api/routeHandler.js +6 -10
- package/dist/next/components/NotFoundView.js +2 -1
- package/dist/next/routing/route-map.d.ts +4 -12
- package/dist/next/routing/route-map.js +2 -4
- package/dist/providers/db-firebase/admin.d.ts +1 -0
- package/dist/providers/db-firebase/admin.js +1 -1
- package/dist/schemas/registry.d.ts +2 -2
- package/dist/seed/addresses-seed-data.js +18 -18
- package/dist/seed/bids-seed-data.js +4 -4
- package/dist/seed/blog-posts-seed-data.js +82 -82
- package/dist/seed/carousel-slides-seed-data.js +14 -10
- package/dist/seed/carousels-seed-data.js +3 -3
- package/dist/seed/cart-seed-data.js +92 -92
- package/dist/seed/claimed-coupons-seed-data.js +10 -10
- package/dist/seed/conversations-seed-data.js +75 -75
- package/dist/seed/coupon-usage-seed-data.js +12 -12
- package/dist/seed/coupons-seed-data.js +41 -41
- package/dist/seed/events-seed-data.js +105 -105
- package/dist/seed/grouped-listings-seed-data.d.ts +2 -137
- package/dist/seed/grouped-listings-seed-data.js +79 -143
- package/dist/seed/history-seed-data.js +38 -38
- package/dist/seed/homepage-sections-seed-data.js +9 -9
- package/dist/seed/index.d.ts +1 -1
- package/dist/seed/index.js +1 -1
- package/dist/seed/manifest.js +4 -4
- package/dist/seed/notifications-seed-data.js +56 -56
- package/dist/seed/offers-seed-data.js +91 -91
- package/dist/seed/orders-seed-data.js +125 -106
- package/dist/seed/payouts-seed-data.js +42 -42
- package/dist/seed/products-auctions-seed-data.js +10 -2
- package/dist/seed/products-classifieds-seed-data.js +48 -5
- package/dist/seed/products-digital-codes-seed-data.js +48 -5
- package/dist/seed/products-live-items-seed-data.js +6 -1
- package/dist/seed/products-prize-draws-seed-data.js +58 -5
- package/dist/seed/products-standard-seed-data.js +40 -8
- package/dist/seed/reviews-seed-data.js +42 -23
- package/dist/seed/scammers-seed-data.js +22 -22
- package/dist/seed/sessions-seed-data.js +7 -7
- package/dist/seed/shipments-seed-data.js +10 -10
- package/dist/seed/site-settings-seed-data.js +82 -0
- package/dist/seed/store-addresses-seed-data.js +2 -2
- package/dist/seed/store-extensions-seed-data.js +93 -93
- package/dist/seed/stores-seed-data.js +2 -0
- package/dist/seed/support-tickets-seed-data.js +47 -47
- package/dist/seed/users-seed-data.js +55 -89
- package/dist/seed/wishlists-seed-data.js +22 -22
- package/dist/server.d.ts +2 -1
- package/dist/server.js +5 -5
- package/dist/styles.css +1 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/PageLoader.js +8 -3
- package/dist/ui/components/Select.d.ts +8 -1
- package/dist/ui/components/Select.js +2 -2
- package/dist/ui/components/SiteMark.d.ts +23 -0
- package/dist/ui/components/SiteMark.js +76 -0
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +1 -0
- package/dist/validation/schemas.d.ts +0 -2
- package/dist/validation/schemas.js +0 -2
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +27 -19
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { Code, useApiMutation } from "@mohasinac/appkit/client";
|
|
4
4
|
import React from "react";
|
|
5
|
-
import { useQueryClient } from "@tanstack/react-query";
|
|
5
|
+
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
6
6
|
import { Button, Div, FormActions, HorizontalRule, Input, Label, Row, Select, SideDrawer, Span, Stack, Text, Textarea, Toggle, useToast } from "../../../ui";
|
|
7
7
|
import { apiClient } from "../../../http";
|
|
8
8
|
import { ADMIN_ENDPOINTS, SUPPORT_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
@@ -109,6 +109,24 @@ export function AdminSupportTicketDetailView({ open, onClose, ticketId, subject,
|
|
|
109
109
|
const [storeIsFeatured, setStoreIsFeatured] = React.useState(false);
|
|
110
110
|
const linkedStoreId = parties.storeId?.trim();
|
|
111
111
|
const isStoreChangeRequest = category === "store_change_request";
|
|
112
|
+
// Seed the panel from the store's REAL current values, not hardcoded
|
|
113
|
+
// defaults — applyStoreChange below sends all three fields unconditionally,
|
|
114
|
+
// so an unseeded default would silently reset a real verified/featured
|
|
115
|
+
// store back to false/"active" on the very first unrelated save.
|
|
116
|
+
const storeQuery = useQuery({
|
|
117
|
+
queryKey: ["admin", "support-ticket-store-change", linkedStoreId],
|
|
118
|
+
queryFn: async () => {
|
|
119
|
+
const res = await apiClient.get(ADMIN_ENDPOINTS.STORE_BY_ID(linkedStoreId));
|
|
120
|
+
return (res?.data ?? res);
|
|
121
|
+
},
|
|
122
|
+
enabled: open && isStoreChangeRequest && !!linkedStoreId,
|
|
123
|
+
select: (data) => {
|
|
124
|
+
setStoreStatus(data.status ?? "active");
|
|
125
|
+
setStoreIsVerified(Boolean(data.isVerified));
|
|
126
|
+
setStoreIsFeatured(Boolean(data.isFeatured));
|
|
127
|
+
return data;
|
|
128
|
+
},
|
|
129
|
+
});
|
|
112
130
|
const applyStoreChange = useApiMutation({
|
|
113
131
|
mutationFn: async () => {
|
|
114
132
|
if (!linkedStoreId)
|
|
@@ -247,7 +265,7 @@ export function AdminSupportTicketDetailView({ open, onClose, ticketId, subject,
|
|
|
247
265
|
["orderId", "Order ID"],
|
|
248
266
|
["productId", "Product slug"],
|
|
249
267
|
["bidId", "Bid ID"],
|
|
250
|
-
].map(([key, label]) => (_jsx(Input, { label: label, type: "text", value: parties[key] ?? "", onChange: (e) => setParties((p) => ({ ...p, [key]: e.target.value })), placeholder: label }, key)))] }), isOrderModificationRequest && (_jsx(OrderItemsPanel, { linkedOrderId: linkedOrderId, orderItemsOpen: orderItemsOpen, setOrderItemsOpen: setOrderItemsOpen, orderItems: orderItems, setOrderItems: setOrderItems, loadOrderItems: loadOrderItems, applyOrderItems: applyOrderItems })), isStoreChangeRequest && (_jsx(StoreChangePanel, { linkedStoreId: linkedStoreId, storeStatus: storeStatus, setStoreStatus: setStoreStatus, storeIsVerified: storeIsVerified, setStoreIsVerified: setStoreIsVerified, storeIsFeatured: storeIsFeatured, setStoreIsFeatured: setStoreIsFeatured, applyStoreChange: applyStoreChange })), isUnbanRequest && (_jsx(UnbanRequestPanel, { linkedUserId: linkedUserId, liftHardBan: liftHardBan, liftSoftBanTickets: liftSoftBanTickets })), _jsxs(FormActions, { align: "right", children: [_jsx(Button, { type: "button", variant: "secondary", onClick: onClose, children: "Cancel" }), _jsx(Button, { type: "button", isLoading: updateMutation.isPending, disabled: !ticketId || updateMutation.isPending, onClick: () => updateMutation.mutate(), children: "Save changes" })] })] }) }));
|
|
268
|
+
].map(([key, label]) => (_jsx(Input, { label: label, type: "text", value: parties[key] ?? "", onChange: (e) => setParties((p) => ({ ...p, [key]: e.target.value })), placeholder: label }, key)))] }), isOrderModificationRequest && (_jsx(OrderItemsPanel, { linkedOrderId: linkedOrderId, orderItemsOpen: orderItemsOpen, setOrderItemsOpen: setOrderItemsOpen, orderItems: orderItems, setOrderItems: setOrderItems, loadOrderItems: loadOrderItems, applyOrderItems: applyOrderItems })), isStoreChangeRequest && (_jsx(StoreChangePanel, { linkedStoreId: linkedStoreId, storeStatus: storeStatus, setStoreStatus: setStoreStatus, storeIsVerified: storeIsVerified, setStoreIsVerified: setStoreIsVerified, storeIsFeatured: storeIsFeatured, setStoreIsFeatured: setStoreIsFeatured, applyStoreChange: applyStoreChange, isLoadingStore: storeQuery.isLoading })), isUnbanRequest && (_jsx(UnbanRequestPanel, { linkedUserId: linkedUserId, liftHardBan: liftHardBan, liftSoftBanTickets: liftSoftBanTickets })), _jsxs(FormActions, { align: "right", children: [_jsx(Button, { type: "button", variant: "secondary", onClick: onClose, children: "Cancel" }), _jsx(Button, { type: "button", isLoading: updateMutation.isPending, disabled: !ticketId || updateMutation.isPending, onClick: () => updateMutation.mutate(), children: "Save changes" })] })] }) }));
|
|
251
269
|
}
|
|
252
270
|
function OrderItemsPanel(props) {
|
|
253
271
|
const { linkedOrderId, orderItemsOpen, setOrderItemsOpen, orderItems, setOrderItems, loadOrderItems, applyOrderItems, } = props;
|
|
@@ -258,13 +276,13 @@ function OrderItemsPanel(props) {
|
|
|
258
276
|
return (_jsxs(Stack, { padding: "sm", className: "border border-info/40 bg-[var(--appkit-color-info-surface)]/40", gap: "sm", rounded: "lg", children: [_jsx(Text, { className: "text-info tracking-wide", size: "xs", weight: "semibold", transform: "uppercase", children: "Modify order items" }), linkedOrderId ? (_jsxs(_Fragment, { children: [_jsxs(Text, { size: "xs", color: "muted", children: ["Editing order: ", _jsx(Code, { className: "font-mono", children: linkedOrderId })] }), !orderItemsOpen ? (_jsx(Button, { type: "button", variant: "secondary", size: "sm", isLoading: loadOrderItems.isPending, disabled: loadOrderItems.isPending, onClick: () => loadOrderItems.mutate(), children: "Load current items" })) : (_jsxs(_Fragment, { children: [orderItems.length === 0 ? (_jsx(Text, { size: "xs", color: "muted", children: "Order has no items." })) : (_jsx(Stack, { gap: "sm", children: orderItems.map((it, idx) => (_jsxs(Row, { paddingY: "y-2xs", padding: "x-xs", rounded: "default", align: "center", gap: "sm", border: "default", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "truncate", size: "xs", weight: "medium", children: it.productTitle }), _jsxs(Text, { size: "xs", color: "muted", children: [it.productId, " \u00B7 \u20B9", it.unitPrice.toFixed(2), "/ea"] })] }), _jsx(Input, { bare: true, type: "number", min: "0", value: it.quantity, onChange: (e) => updateQty(idx, e.target.value), className: "w-16 rounded border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-2)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)]" })] }, `${it.productId}-${idx}`))) })), _jsxs(Row, { gap: "sm", children: [_jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => setOrderItemsOpen(false), children: "Cancel" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", isLoading: applyOrderItems.isPending, disabled: applyOrderItems.isPending, onClick: () => applyOrderItems.mutate(), children: "Apply changes" })] })] }))] })) : (_jsxs(Text, { size: "xs", color: "muted", children: ["Set the", " ", _jsx(Text, { as: "span", weight: "semibold", children: "Order ID" }), " ", "field in the Linked parties panel above to enable this action."] }))] }));
|
|
259
277
|
}
|
|
260
278
|
function StoreChangePanel(props) {
|
|
261
|
-
const { linkedStoreId, storeStatus, setStoreStatus, storeIsVerified, setStoreIsVerified, storeIsFeatured, setStoreIsFeatured, applyStoreChange, } = props;
|
|
262
|
-
return (_jsxs(Stack, { padding: "sm", className: "border border-warning/40 bg-[var(--appkit-color-warning-surface)]/40", gap: "sm", rounded: "lg", children: [_jsx(Text, { className: "text-warning tracking-wide", size: "xs", weight: "semibold", transform: "uppercase", children: "Apply store change" }), linkedStoreId ? (_jsxs(_Fragment, { children: [_jsxs(Text, { size: "xs", color: "muted", children: ["Editing store: ", _jsx(Code, { className: "font-mono", children: linkedStoreId })] }), _jsx(Select, { label: "Store status", options: [
|
|
279
|
+
const { linkedStoreId, storeStatus, setStoreStatus, storeIsVerified, setStoreIsVerified, storeIsFeatured, setStoreIsFeatured, applyStoreChange, isLoadingStore, } = props;
|
|
280
|
+
return (_jsxs(Stack, { padding: "sm", className: "border border-warning/40 bg-[var(--appkit-color-warning-surface)]/40", gap: "sm", rounded: "lg", children: [_jsx(Text, { className: "text-warning tracking-wide", size: "xs", weight: "semibold", transform: "uppercase", children: "Apply store change" }), linkedStoreId ? (_jsxs(_Fragment, { children: [_jsxs(Text, { size: "xs", color: "muted", children: ["Editing store: ", _jsx(Code, { className: "font-mono", children: linkedStoreId })] }), isLoadingStore && (_jsx(Text, { size: "xs", color: "muted", children: "Loading current store state\u2026" })), _jsx(Select, { label: "Store status", options: [
|
|
263
281
|
{ label: "Active", value: "active" },
|
|
264
282
|
{ label: "Pending", value: "pending" },
|
|
265
283
|
{ label: "Suspended", value: "suspended" },
|
|
266
284
|
{ label: "Rejected", value: "rejected" },
|
|
267
|
-
], value: storeStatus, onValueChange: setStoreStatus }), _jsx(Toggle, { label: "Verified badge", checked: storeIsVerified, onChange: setStoreIsVerified }), _jsx(Toggle, { label: "Featured store", checked: storeIsFeatured, onChange: setStoreIsFeatured }), _jsx(Button, { type: "button", variant: "primary", size: "sm", isLoading: applyStoreChange.isPending, disabled: applyStoreChange.isPending, onClick: () => applyStoreChange.mutate(), children: "Apply store change" })] })) : (_jsxs(Text, { size: "xs", color: "muted", children: ["Set the", " ", _jsx(Text, { as: "span", weight: "semibold", children: "Store slug" }), " ", "field in the Linked parties panel above to enable this action."] }))] }));
|
|
285
|
+
], value: storeStatus, onValueChange: setStoreStatus, disabled: isLoadingStore }), _jsx(Toggle, { label: "Verified badge", checked: storeIsVerified, onChange: setStoreIsVerified, disabled: isLoadingStore }), _jsx(Toggle, { label: "Featured store", checked: storeIsFeatured, onChange: setStoreIsFeatured, disabled: isLoadingStore }), _jsx(Button, { type: "button", variant: "primary", size: "sm", isLoading: applyStoreChange.isPending, disabled: applyStoreChange.isPending || isLoadingStore, onClick: () => applyStoreChange.mutate(), children: "Apply store change" })] })) : (_jsxs(Text, { size: "xs", color: "muted", children: ["Set the", " ", _jsx(Text, { as: "span", weight: "semibold", children: "Store slug" }), " ", "field in the Linked parties panel above to enable this action."] }))] }));
|
|
268
286
|
}
|
|
269
287
|
function UnbanRequestPanel(props) {
|
|
270
288
|
const { linkedUserId, liftHardBan, liftSoftBanTickets } = props;
|
|
@@ -3,9 +3,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
import { SIEVE_OP, Stack, sieveFilter } from "@mohasinac/appkit";
|
|
4
4
|
import { sortBy } from "@mohasinac/appkit";
|
|
5
5
|
import React, { useState } from "react";
|
|
6
|
+
import { useRouter } from "next/navigation";
|
|
6
7
|
import { FilterChipGroup, ListingLayout, RowActionMenu, Span, Text } from "../../../ui";
|
|
7
8
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
8
9
|
import { ROW_ACTION_META, ROW_ACTION_ID } from "../../../features/products/constants/action-defs";
|
|
10
|
+
import { ROUTES } from "../../../next/routing/route-map";
|
|
9
11
|
import { ADMIN_SUPPORT_TICKET_STATUS_TABS, ADMIN_SUPPORT_TICKET_PRIORITY_TABS, } from "../constants/filter-tabs";
|
|
10
12
|
import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdminListingData";
|
|
11
13
|
import { DataListingView } from "./DataListingView";
|
|
@@ -46,6 +48,7 @@ const TICKET_COLUMNS = [
|
|
|
46
48
|
},
|
|
47
49
|
];
|
|
48
50
|
export function AdminSupportTicketsView({ children, ...props }) {
|
|
51
|
+
const router = useRouter();
|
|
49
52
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
50
53
|
const [selectedRow, setSelectedRow] = useState(null);
|
|
51
54
|
if (React.Children.count(children) > 0) {
|
|
@@ -56,7 +59,7 @@ export function AdminSupportTicketsView({ children, ...props }) {
|
|
|
56
59
|
title: "Support Tickets",
|
|
57
60
|
searchPlaceholder: "Search by subject",
|
|
58
61
|
emptyLabel: "No support tickets found",
|
|
59
|
-
filterKeys: ["status", "priority"],
|
|
62
|
+
filterKeys: ["status", "priority", "showResolved"],
|
|
60
63
|
defaultSort: sortBy("createdAt", "DESC"),
|
|
61
64
|
queryKey: ["admin", "support-tickets", "listing"],
|
|
62
65
|
endpoint: ADMIN_ENDPOINTS.SUPPORT_TICKETS,
|
|
@@ -91,8 +94,19 @@ export function AdminSupportTicketsView({ children, ...props }) {
|
|
|
91
94
|
},
|
|
92
95
|
buildFilters: (f) => {
|
|
93
96
|
const parts = [];
|
|
94
|
-
if (f.status && f.status !== "All")
|
|
97
|
+
if (f.status && f.status !== "All") {
|
|
95
98
|
parts.push(sieveFilter("status", SIEVE_OP.EQ, f.status));
|
|
99
|
+
}
|
|
100
|
+
else if (f.showResolved !== "true") {
|
|
101
|
+
// Hide resolved and closed tickets by default (open-only quick
|
|
102
|
+
// view). Pipe-joined EQ, not NEQ: sievejs parses a same-field pipe
|
|
103
|
+
// as an OR group, upgraded by the Firestore adapter to an IN query.
|
|
104
|
+
// Unlike NEQ, IN has no orderBy-must-match-filtered-field
|
|
105
|
+
// restriction, so this stays compatible with the default createdAt
|
|
106
|
+
// sort. See sieve.ts for the documented Sieve/Firestore
|
|
107
|
+
// incompatibility this avoids.
|
|
108
|
+
parts.push(sieveFilter("status", SIEVE_OP.EQ, "open|in_progress|waiting_on_user"));
|
|
109
|
+
}
|
|
96
110
|
if (f.priority && f.priority !== "All")
|
|
97
111
|
parts.push(sieveFilter("priority", SIEVE_OP.EQ, f.priority));
|
|
98
112
|
return parts.join(",") || undefined;
|
|
@@ -105,6 +119,10 @@ export function AdminSupportTicketsView({ children, ...props }) {
|
|
|
105
119
|
setDrawerOpen(true);
|
|
106
120
|
},
|
|
107
121
|
},
|
|
122
|
+
{
|
|
123
|
+
label: "Open full page",
|
|
124
|
+
onClick: () => router.push(String(ROUTES.ADMIN.SUPPORT_TICKET_BY_ID(row.id))),
|
|
125
|
+
},
|
|
108
126
|
] })),
|
|
109
127
|
renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsxs(_Fragment, { children: [_jsx(FilterChipGroup, { label: "Status", tabs: ADMIN_SUPPORT_TICKET_STATUS_TABS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) }), _jsx(FilterChipGroup, { label: "Priority", tabs: ADMIN_SUPPORT_TICKET_PRIORITY_TABS, value: pendingFilters.priority ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, priority: id })) })] })),
|
|
110
128
|
};
|
|
@@ -39,6 +39,7 @@ export function AdminTesterChecklistItemEditorView({ itemId, onSaved, onDeleted,
|
|
|
39
39
|
const [description, setDescription] = React.useState("");
|
|
40
40
|
const [href, setHref] = React.useState("");
|
|
41
41
|
const [order, setOrder] = React.useState(0);
|
|
42
|
+
const [phase, setPhase] = React.useState(1);
|
|
42
43
|
const [isActive, setIsActive] = React.useState(true);
|
|
43
44
|
const [adminOnly, setAdminOnly] = React.useState(false);
|
|
44
45
|
const [deleteConfirmOpen, setDeleteConfirmOpen] = React.useState(false);
|
|
@@ -63,6 +64,7 @@ export function AdminTesterChecklistItemEditorView({ itemId, onSaved, onDeleted,
|
|
|
63
64
|
setDescription(item.description ?? "");
|
|
64
65
|
setHref(item.href ?? "");
|
|
65
66
|
setOrder(typeof item.order === "number" ? item.order : 0);
|
|
67
|
+
setPhase(typeof item.phase === "number" ? item.phase : 1);
|
|
66
68
|
setIsActive(item.isActive ?? true);
|
|
67
69
|
setAdminOnly(item.adminOnly ?? false);
|
|
68
70
|
}, [itemQuery.data]);
|
|
@@ -87,6 +89,7 @@ export function AdminTesterChecklistItemEditorView({ itemId, onSaved, onDeleted,
|
|
|
87
89
|
description: description || "",
|
|
88
90
|
href: href || "",
|
|
89
91
|
order,
|
|
92
|
+
phase,
|
|
90
93
|
isActive,
|
|
91
94
|
adminOnly,
|
|
92
95
|
};
|
|
@@ -116,7 +119,7 @@ export function AdminTesterChecklistItemEditorView({ itemId, onSaved, onDeleted,
|
|
|
116
119
|
});
|
|
117
120
|
const isSubmitting = saveMutation.isPending || itemQuery.isLoading;
|
|
118
121
|
const canSave = Boolean(groupLabel.trim()) && Boolean(pageLabel.trim()) && Boolean(label.trim());
|
|
119
|
-
const formSection = (_jsxs(_Fragment, { children: [_jsx(Form, { schema: checklistItemFormSchema, onSubmit: (e) => e.preventDefault(), spacing: "md", children: ({ setFieldError, clearErrors }) => (_jsxs(_Fragment, { children: [_jsxs(Div, { layout: "grid", gap: "4", className: "grid-cols-2", children: [_jsx(FieldInput, { name: "groupLabel", label: "Group", value: groupLabel, onChange: handleGroupLabelChange, required: true, placeholder: "e.g. Buying", hint: "Top-level accordion section on the Tester Hub." }), _jsx(Input, { label: "Group key", value: groupKey, onChange: (e) => setGroupKey(e.target.value), placeholder: "buying", helperText: "Auto-generated from the group name." })] }), _jsxs(Div, { layout: "grid", gap: "4", className: "grid-cols-2", children: [_jsx(FieldInput, { name: "pageLabel", label: "Page", value: pageLabel, onChange: handlePageLabelChange, required: true, placeholder: "e.g. Checkout", hint: "Sub-accordion within the group." }), _jsx(Input, { label: "Page key", value: pageKey, onChange: (e) => setPageKey(e.target.value), placeholder: "checkout", helperText: "Auto-generated from the page name." })] }), _jsx(FieldInput, { name: "label", label: "Test case (Yes/No question)", value: label, onChange: setLabel, required: true, placeholder: "e.g. Coupon discount is correctly reflected in the order total" }), _jsx(FieldTextarea, { name: "description", label: "Description (optional)", value: description, onChange: setDescription, placeholder: "Extra context for the tester." }), _jsx(FieldInput, { name: "href", label: "Deep link (optional)", value: href, onChange: setHref, placeholder: "/cart", hint: "Jumps the tester straight to the feature being tested." }), _jsx(Input, { label: "Display order", value: String(order), onChange: (e) => setOrder(parseInt(e.target.value, 10) || 0), type: "number", min: 0, helperText: "Lower = shown first within the page." }), _jsxs(Stack, { className: `${__P.p4}`, gap: "3", rounded: "lg", border: "default", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Visibility" }), _jsx(Toggle, { label: "Active (visible to testers)", checked: isActive, onChange: setIsActive }), _jsx(Toggle, { label: "Admin-only (requires canTestAdmin)", checked: adminOnly, onChange: setAdminOnly })] }), _jsxs(Row, { gap: "3", padding: "t-xs", children: [_jsx(Button, { type: "submit", isLoading: isSubmitting, disabled: !canSave || isSubmitting, onClick: () => {
|
|
122
|
+
const formSection = (_jsxs(_Fragment, { children: [_jsx(Form, { schema: checklistItemFormSchema, onSubmit: (e) => e.preventDefault(), spacing: "md", children: ({ setFieldError, clearErrors }) => (_jsxs(_Fragment, { children: [_jsxs(Div, { layout: "grid", gap: "4", className: "grid-cols-2", children: [_jsx(FieldInput, { name: "groupLabel", label: "Group", value: groupLabel, onChange: handleGroupLabelChange, required: true, placeholder: "e.g. Buying", hint: "Top-level accordion section on the Tester Hub." }), _jsx(Input, { label: "Group key", value: groupKey, onChange: (e) => setGroupKey(e.target.value), placeholder: "buying", helperText: "Auto-generated from the group name." })] }), _jsxs(Div, { layout: "grid", gap: "4", className: "grid-cols-2", children: [_jsx(FieldInput, { name: "pageLabel", label: "Page", value: pageLabel, onChange: handlePageLabelChange, required: true, placeholder: "e.g. Checkout", hint: "Sub-accordion within the group." }), _jsx(Input, { label: "Page key", value: pageKey, onChange: (e) => setPageKey(e.target.value), placeholder: "checkout", helperText: "Auto-generated from the page name." })] }), _jsx(FieldInput, { name: "label", label: "Test case (Yes/No question)", value: label, onChange: setLabel, required: true, placeholder: "e.g. Coupon discount is correctly reflected in the order total" }), _jsx(FieldTextarea, { name: "description", label: "Description (optional)", value: description, onChange: setDescription, placeholder: "Extra context for the tester." }), _jsx(FieldInput, { name: "href", label: "Deep link (optional)", value: href, onChange: setHref, placeholder: "/cart", hint: "Jumps the tester straight to the feature being tested." }), _jsxs(Div, { layout: "grid", gap: "4", className: "grid-cols-2", children: [_jsx(Input, { label: "Display order", value: String(order), onChange: (e) => setOrder(parseInt(e.target.value, 10) || 0), type: "number", min: 0, helperText: "Lower = shown first within the page." }), _jsx(Input, { label: "Phase", value: String(phase), onChange: (e) => setPhase(Math.max(1, parseInt(e.target.value, 10) || 1)), type: "number", min: 1, helperText: "Test batch this case belongs to \u2014 testers work through one phase at a time." })] }), _jsxs(Stack, { className: `${__P.p4}`, gap: "3", rounded: "lg", border: "default", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Visibility" }), _jsx(Toggle, { label: "Active (visible to testers)", checked: isActive, onChange: setIsActive }), _jsx(Toggle, { label: "Admin-only (requires canTestAdmin)", checked: adminOnly, onChange: setAdminOnly })] }), _jsxs(Row, { gap: "3", padding: "t-xs", children: [_jsx(Button, { type: "submit", isLoading: isSubmitting, disabled: !canSave || isSubmitting, onClick: () => {
|
|
120
123
|
clearErrors();
|
|
121
124
|
if (!label.trim()) {
|
|
122
125
|
setFieldError("label", "Test case label is required");
|
|
@@ -16,6 +16,12 @@ const COLUMNS = [
|
|
|
16
16
|
sortable: true,
|
|
17
17
|
render: (row) => (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { weight: "semibold", color: "primary", children: row.primary }), _jsx(Text, { size: "xs", color: "muted", children: row.secondary })] })),
|
|
18
18
|
},
|
|
19
|
+
{
|
|
20
|
+
key: "phase",
|
|
21
|
+
header: "Phase",
|
|
22
|
+
className: "w-20",
|
|
23
|
+
render: (row) => _jsx(Text, { size: "sm", color: "muted", children: row.phase }),
|
|
24
|
+
},
|
|
19
25
|
{
|
|
20
26
|
key: "status",
|
|
21
27
|
header: "Status",
|
|
@@ -41,6 +47,7 @@ export function AdminTesterChecklistView({ children, onBulkDelete, ...props }) {
|
|
|
41
47
|
endpoint: ADMIN_ENDPOINTS.TESTER_CHECKLIST_ITEMS,
|
|
42
48
|
sortOptions: [
|
|
43
49
|
{ value: "order", label: "Order" },
|
|
50
|
+
{ value: "phase", label: "Phase" },
|
|
44
51
|
{ value: sortBy("createdAt", "DESC"), label: "Newest" },
|
|
45
52
|
{ value: "label", label: "Test case A–Z" },
|
|
46
53
|
],
|
|
@@ -49,6 +56,7 @@ export function AdminTesterChecklistView({ children, onBulkDelete, ...props }) {
|
|
|
49
56
|
id: toStringValue(item.id, `checklist-${index}`),
|
|
50
57
|
primary: toStringValue(item.label, "Untitled test case"),
|
|
51
58
|
secondary: `${toStringValue(item.groupLabel, "Uncategorized")} / ${toStringValue(item.pageLabel, "")}`,
|
|
59
|
+
phase: typeof item.phase === "number" ? item.phase : 1,
|
|
52
60
|
status: toStringValue(typeof item.isActive === "boolean"
|
|
53
61
|
? item.isActive
|
|
54
62
|
? "Active"
|
|
@@ -46,6 +46,8 @@ export { AdminStickersView } from "./AdminStickersView";
|
|
|
46
46
|
export type { AdminStickersViewProps } from "./AdminStickersView";
|
|
47
47
|
export { AdminGroupedListingsView } from "./AdminGroupedListingsView";
|
|
48
48
|
export type { AdminGroupedListingsViewProps } from "./AdminGroupedListingsView";
|
|
49
|
+
export { AdminCarouselGroupEditorView } from "./AdminCarouselGroupEditorView";
|
|
50
|
+
export type { AdminCarouselGroupEditorViewProps } from "./AdminCarouselGroupEditorView";
|
|
49
51
|
export { AdminBundlesView } from "./AdminBundlesView";
|
|
50
52
|
export type { AdminBundlesViewProps } from "./AdminBundlesView";
|
|
51
53
|
export { AdminBundleEditorView } from "./AdminBundleEditorView";
|
|
@@ -26,6 +26,7 @@ export { AdminLiveView } from "./AdminLiveView";
|
|
|
26
26
|
export { AdminArtView } from "./AdminArtView";
|
|
27
27
|
export { AdminStickersView } from "./AdminStickersView";
|
|
28
28
|
export { AdminGroupedListingsView } from "./AdminGroupedListingsView";
|
|
29
|
+
export { AdminCarouselGroupEditorView } from "./AdminCarouselGroupEditorView";
|
|
29
30
|
// S-SBUNI-4 2026-05-13 — admin bundle CRUD views.
|
|
30
31
|
export { AdminBundlesView } from "./AdminBundlesView";
|
|
31
32
|
export { AdminBundleEditorView } from "./AdminBundleEditorView";
|
|
@@ -19,12 +19,14 @@ export declare const ALL_TAB: {
|
|
|
19
19
|
readonly id: "All";
|
|
20
20
|
readonly label: "All";
|
|
21
21
|
};
|
|
22
|
-
/** Admin > Products — listing status filter chip set.
|
|
22
|
+
/** Admin > Products — listing status filter chip set. Real `ProductStatus`
|
|
23
|
+
* is draft|published|in_review|archived — "pending" fixed to "in_review"
|
|
24
|
+
* (its real meaning); the previous id never matched any document. */
|
|
23
25
|
export declare const ADMIN_PRODUCT_STATUS_TABS: readonly [{
|
|
24
26
|
readonly id: "All";
|
|
25
27
|
readonly label: "All";
|
|
26
28
|
}, {
|
|
27
|
-
readonly id: "
|
|
29
|
+
readonly id: "in_review";
|
|
28
30
|
readonly label: "Pending";
|
|
29
31
|
}, {
|
|
30
32
|
readonly id: "published";
|
|
@@ -264,13 +266,15 @@ export declare const ADMIN_EVENT_ENTRY_STATUS_TABS: readonly [{
|
|
|
264
266
|
readonly id: "CANCELLED";
|
|
265
267
|
readonly label: "Cancelled";
|
|
266
268
|
}];
|
|
267
|
-
/** Admin > Events — event-state filter chip set.
|
|
269
|
+
/** Admin > Events — event-state filter chip set. Real `EventStatus` is
|
|
270
|
+
* draft|active|paused|ended|cancelled — there is no "published" value
|
|
271
|
+
* (field-names.ts's copy of this enum is stale; verified against the
|
|
272
|
+
* feature's own events/types/index.ts). A "Published" chip previously
|
|
273
|
+
* returned zero rows every time — removed rather than aliased since
|
|
274
|
+
* "Active" already covers the intended meaning. */
|
|
268
275
|
export declare const ADMIN_EVENT_STATUS_TABS: readonly [{
|
|
269
276
|
readonly id: "All";
|
|
270
277
|
readonly label: "All";
|
|
271
|
-
}, {
|
|
272
|
-
readonly id: "published";
|
|
273
|
-
readonly label: "Published";
|
|
274
278
|
}, {
|
|
275
279
|
readonly id: "draft";
|
|
276
280
|
readonly label: "Draft";
|
|
@@ -371,12 +375,18 @@ export declare const EMPTY_TAB: {
|
|
|
371
375
|
readonly id: "";
|
|
372
376
|
readonly label: "All";
|
|
373
377
|
};
|
|
374
|
-
/** Seller > Products — listing-state filter chip set.
|
|
378
|
+
/** Seller > Products — listing-state filter chip set. Real `ProductStatus`
|
|
379
|
+
* is draft|published|in_review|archived — there is no "active" or "sold"
|
|
380
|
+
* value on the `status` field. "Active" was fixed to "published" (its real
|
|
381
|
+
* meaning); "Sold" was removed since sold-filtering already has its own
|
|
382
|
+
* correct, working mechanism (the `isSold`-driven "Show sold" toolbar
|
|
383
|
+
* toggle in SellerProductsView.tsx) — the status chip duplicated it with
|
|
384
|
+
* a broken `status=="sold"` query that always returned zero rows. */
|
|
375
385
|
export declare const SELLER_PRODUCT_STATUS_TABS: readonly [{
|
|
376
386
|
readonly id: "All";
|
|
377
387
|
readonly label: "All";
|
|
378
388
|
}, {
|
|
379
|
-
readonly id: "
|
|
389
|
+
readonly id: "published";
|
|
380
390
|
readonly label: "Active";
|
|
381
391
|
}, {
|
|
382
392
|
readonly id: "draft";
|
|
@@ -384,33 +394,36 @@ export declare const SELLER_PRODUCT_STATUS_TABS: readonly [{
|
|
|
384
394
|
}, {
|
|
385
395
|
readonly id: "archived";
|
|
386
396
|
readonly label: "Archived";
|
|
387
|
-
}, {
|
|
388
|
-
readonly id: "sold";
|
|
389
|
-
readonly label: "Sold";
|
|
390
397
|
}];
|
|
391
|
-
/** Seller > Auctions — auction-state filter chip set.
|
|
398
|
+
/** Seller > Auctions — auction-state filter chip set. Real `ProductStatus`
|
|
399
|
+
* has no "active"/"ended"/"cancelled" values. "Active" fixed to
|
|
400
|
+
* "published". "Ended" and "Cancelled" removed — "ended" is a derived
|
|
401
|
+
* state (auctionEndDate vs now), not a stored status, and is now handled
|
|
402
|
+
* by SellerAuctionsView's "Show ended" toolbar toggle; there is no stored
|
|
403
|
+
* "cancelled" state for auctions at all (an auction that expires with no
|
|
404
|
+
* bids becomes `archived`, indistinguishable in storage from a listing the
|
|
405
|
+
* seller archived for any other reason — aliasing "Cancelled" to
|
|
406
|
+
* `status==archived` would be misleading, so it's dropped rather than
|
|
407
|
+
* reintroduced under a wrong mapping). */
|
|
392
408
|
export declare const SELLER_AUCTION_STATUS_TABS: readonly [{
|
|
393
409
|
readonly id: "All";
|
|
394
410
|
readonly label: "All";
|
|
395
411
|
}, {
|
|
396
|
-
readonly id: "
|
|
412
|
+
readonly id: "published";
|
|
397
413
|
readonly label: "Active";
|
|
398
414
|
}, {
|
|
399
415
|
readonly id: "draft";
|
|
400
416
|
readonly label: "Draft";
|
|
401
|
-
}, {
|
|
402
|
-
readonly id: "ended";
|
|
403
|
-
readonly label: "Ended";
|
|
404
|
-
}, {
|
|
405
|
-
readonly id: "cancelled";
|
|
406
|
-
readonly label: "Cancelled";
|
|
407
417
|
}];
|
|
408
|
-
/** Seller > Pre-orders — pre-order-state filter chip set.
|
|
418
|
+
/** Seller > Pre-orders — pre-order-state filter chip set. Same root cause
|
|
419
|
+
* and fix as SELLER_AUCTION_STATUS_TABS above — no "active"/"cancelled"
|
|
420
|
+
* status values exist; pre-order cancellation, if tracked, lives in the
|
|
421
|
+
* separate `preOrderProductionStatus` field, not `status`. */
|
|
409
422
|
export declare const SELLER_PRE_ORDER_STATUS_TABS: readonly [{
|
|
410
423
|
readonly id: "All";
|
|
411
424
|
readonly label: "All";
|
|
412
425
|
}, {
|
|
413
|
-
readonly id: "
|
|
426
|
+
readonly id: "published";
|
|
414
427
|
readonly label: "Active";
|
|
415
428
|
}, {
|
|
416
429
|
readonly id: "draft";
|
|
@@ -418,53 +431,54 @@ export declare const SELLER_PRE_ORDER_STATUS_TABS: readonly [{
|
|
|
418
431
|
}, {
|
|
419
432
|
readonly id: "archived";
|
|
420
433
|
readonly label: "Archived";
|
|
421
|
-
}, {
|
|
422
|
-
readonly id: "cancelled";
|
|
423
|
-
readonly label: "Cancelled";
|
|
424
434
|
}];
|
|
425
|
-
/** Seller > Prize Draws — draw-state filter chip set.
|
|
435
|
+
/** Seller > Prize Draws — draw-state filter chip set. Same root cause and
|
|
436
|
+
* fix as SELLER_AUCTION_STATUS_TABS — "ended" is derived from
|
|
437
|
+
* `prizeRevealWindowEnd` vs now (handled by the "Show closed" toolbar
|
|
438
|
+
* toggle), no stored "cancelled" state exists. */
|
|
426
439
|
export declare const SELLER_PRIZE_DRAW_STATUS_TABS: readonly [{
|
|
427
440
|
readonly id: "All";
|
|
428
441
|
readonly label: "All";
|
|
429
442
|
}, {
|
|
430
|
-
readonly id: "
|
|
443
|
+
readonly id: "published";
|
|
431
444
|
readonly label: "Active";
|
|
432
445
|
}, {
|
|
433
446
|
readonly id: "draft";
|
|
434
447
|
readonly label: "Draft";
|
|
435
|
-
}, {
|
|
436
|
-
readonly id: "ended";
|
|
437
|
-
readonly label: "Ended";
|
|
438
|
-
}, {
|
|
439
|
-
readonly id: "cancelled";
|
|
440
|
-
readonly label: "Cancelled";
|
|
441
448
|
}];
|
|
442
449
|
/** Seller > Orders — order-state filter chip set. Subset of
|
|
443
450
|
* `ADMIN_ORDER_STATUS_TABS` — sellers don't see `RETURN_REQUESTED` until
|
|
444
|
-
* the buyer initiates one through support.
|
|
451
|
+
* the buyer initiates one through support. IDs are lowercase to match the
|
|
452
|
+
* real stored `OrderStatusValues` (Firestore `==` is byte-exact — the
|
|
453
|
+
* previous uppercase ids never matched any document, every chip here
|
|
454
|
+
* silently returned zero rows). */
|
|
445
455
|
export declare const SELLER_ORDER_STATUS_TABS: readonly [{
|
|
446
456
|
readonly id: "All";
|
|
447
457
|
readonly label: "All";
|
|
448
458
|
}, {
|
|
449
|
-
readonly id: "
|
|
459
|
+
readonly id: "pending";
|
|
450
460
|
readonly label: "Pending";
|
|
451
461
|
}, {
|
|
452
|
-
readonly id: "
|
|
462
|
+
readonly id: "processing";
|
|
453
463
|
readonly label: "Processing";
|
|
454
464
|
}, {
|
|
455
|
-
readonly id: "
|
|
465
|
+
readonly id: "shipped";
|
|
456
466
|
readonly label: "Shipped";
|
|
457
467
|
}, {
|
|
458
|
-
readonly id: "
|
|
468
|
+
readonly id: "delivered";
|
|
459
469
|
readonly label: "Delivered";
|
|
460
470
|
}, {
|
|
461
|
-
readonly id: "
|
|
471
|
+
readonly id: "cancelled";
|
|
462
472
|
readonly label: "Cancelled";
|
|
463
473
|
}, {
|
|
464
|
-
readonly id: "
|
|
474
|
+
readonly id: "refunded";
|
|
465
475
|
readonly label: "Refunded";
|
|
466
476
|
}];
|
|
467
|
-
/** Seller > Offers — offer-state filter chip set.
|
|
477
|
+
/** Seller > Offers — offer-state filter chip set. Real `OfferStatus` is
|
|
478
|
+
* pending|accepted|declined|countered|expired|withdrawn|paid — there is no
|
|
479
|
+
* "rejected" value, the real one is "declined" (the id below was fixed;
|
|
480
|
+
* the previous "rejected" id always returned zero rows). Label kept as
|
|
481
|
+
* "Rejected" for continuity with existing seller-facing wording. */
|
|
468
482
|
export declare const SELLER_OFFER_STATUS_TABS: readonly [{
|
|
469
483
|
readonly id: "All";
|
|
470
484
|
readonly label: "All";
|
|
@@ -475,7 +489,7 @@ export declare const SELLER_OFFER_STATUS_TABS: readonly [{
|
|
|
475
489
|
readonly id: "accepted";
|
|
476
490
|
readonly label: "Accepted";
|
|
477
491
|
}, {
|
|
478
|
-
readonly id: "
|
|
492
|
+
readonly id: "declined";
|
|
479
493
|
readonly label: "Rejected";
|
|
480
494
|
}, {
|
|
481
495
|
readonly id: "expired";
|
|
@@ -10,10 +10,12 @@
|
|
|
10
10
|
* primitive and stay in sync when statuses are added.
|
|
11
11
|
*/
|
|
12
12
|
export const ALL_TAB = { id: "All", label: "All" };
|
|
13
|
-
/** Admin > Products — listing status filter chip set.
|
|
13
|
+
/** Admin > Products — listing status filter chip set. Real `ProductStatus`
|
|
14
|
+
* is draft|published|in_review|archived — "pending" fixed to "in_review"
|
|
15
|
+
* (its real meaning); the previous id never matched any document. */
|
|
14
16
|
export const ADMIN_PRODUCT_STATUS_TABS = [
|
|
15
17
|
ALL_TAB,
|
|
16
|
-
{ id: "
|
|
18
|
+
{ id: "in_review", label: "Pending" },
|
|
17
19
|
{ id: "published", label: "Published" },
|
|
18
20
|
{ id: "draft", label: "Draft" },
|
|
19
21
|
{ id: "archived", label: "Archived" },
|
|
@@ -129,10 +131,14 @@ export const ADMIN_EVENT_ENTRY_STATUS_TABS = [
|
|
|
129
131
|
{ id: "WAITLISTED", label: "Waitlisted" },
|
|
130
132
|
{ id: "CANCELLED", label: "Cancelled" },
|
|
131
133
|
];
|
|
132
|
-
/** Admin > Events — event-state filter chip set.
|
|
134
|
+
/** Admin > Events — event-state filter chip set. Real `EventStatus` is
|
|
135
|
+
* draft|active|paused|ended|cancelled — there is no "published" value
|
|
136
|
+
* (field-names.ts's copy of this enum is stale; verified against the
|
|
137
|
+
* feature's own events/types/index.ts). A "Published" chip previously
|
|
138
|
+
* returned zero rows every time — removed rather than aliased since
|
|
139
|
+
* "Active" already covers the intended meaning. */
|
|
133
140
|
export const ADMIN_EVENT_STATUS_TABS = [
|
|
134
141
|
ALL_TAB,
|
|
135
|
-
{ id: "published", label: "Published" },
|
|
136
142
|
{ id: "draft", label: "Draft" },
|
|
137
143
|
{ id: "active", label: "Active" },
|
|
138
144
|
{ id: "ended", label: "Ended" },
|
|
@@ -184,56 +190,78 @@ export const ADMIN_COUPON_TYPE_TABS = [
|
|
|
184
190
|
* filter URL with `""` instead of `"All"` so the `"" == no filter` invariant
|
|
185
191
|
* stays a single shape across queries. */
|
|
186
192
|
export const EMPTY_TAB = { id: "", label: "All" };
|
|
187
|
-
/** Seller > Products — listing-state filter chip set.
|
|
193
|
+
/** Seller > Products — listing-state filter chip set. Real `ProductStatus`
|
|
194
|
+
* is draft|published|in_review|archived — there is no "active" or "sold"
|
|
195
|
+
* value on the `status` field. "Active" was fixed to "published" (its real
|
|
196
|
+
* meaning); "Sold" was removed since sold-filtering already has its own
|
|
197
|
+
* correct, working mechanism (the `isSold`-driven "Show sold" toolbar
|
|
198
|
+
* toggle in SellerProductsView.tsx) — the status chip duplicated it with
|
|
199
|
+
* a broken `status=="sold"` query that always returned zero rows. */
|
|
188
200
|
export const SELLER_PRODUCT_STATUS_TABS = [
|
|
189
201
|
ALL_TAB,
|
|
190
|
-
{ id: "
|
|
202
|
+
{ id: "published", label: "Active" },
|
|
191
203
|
{ id: "draft", label: "Draft" },
|
|
192
204
|
{ id: "archived", label: "Archived" },
|
|
193
|
-
{ id: "sold", label: "Sold" },
|
|
194
205
|
];
|
|
195
|
-
/** Seller > Auctions — auction-state filter chip set.
|
|
206
|
+
/** Seller > Auctions — auction-state filter chip set. Real `ProductStatus`
|
|
207
|
+
* has no "active"/"ended"/"cancelled" values. "Active" fixed to
|
|
208
|
+
* "published". "Ended" and "Cancelled" removed — "ended" is a derived
|
|
209
|
+
* state (auctionEndDate vs now), not a stored status, and is now handled
|
|
210
|
+
* by SellerAuctionsView's "Show ended" toolbar toggle; there is no stored
|
|
211
|
+
* "cancelled" state for auctions at all (an auction that expires with no
|
|
212
|
+
* bids becomes `archived`, indistinguishable in storage from a listing the
|
|
213
|
+
* seller archived for any other reason — aliasing "Cancelled" to
|
|
214
|
+
* `status==archived` would be misleading, so it's dropped rather than
|
|
215
|
+
* reintroduced under a wrong mapping). */
|
|
196
216
|
export const SELLER_AUCTION_STATUS_TABS = [
|
|
197
217
|
ALL_TAB,
|
|
198
|
-
{ id: "
|
|
218
|
+
{ id: "published", label: "Active" },
|
|
199
219
|
{ id: "draft", label: "Draft" },
|
|
200
|
-
{ id: "ended", label: "Ended" },
|
|
201
|
-
{ id: "cancelled", label: "Cancelled" },
|
|
202
220
|
];
|
|
203
|
-
/** Seller > Pre-orders — pre-order-state filter chip set.
|
|
221
|
+
/** Seller > Pre-orders — pre-order-state filter chip set. Same root cause
|
|
222
|
+
* and fix as SELLER_AUCTION_STATUS_TABS above — no "active"/"cancelled"
|
|
223
|
+
* status values exist; pre-order cancellation, if tracked, lives in the
|
|
224
|
+
* separate `preOrderProductionStatus` field, not `status`. */
|
|
204
225
|
export const SELLER_PRE_ORDER_STATUS_TABS = [
|
|
205
226
|
ALL_TAB,
|
|
206
|
-
{ id: "
|
|
227
|
+
{ id: "published", label: "Active" },
|
|
207
228
|
{ id: "draft", label: "Draft" },
|
|
208
229
|
{ id: "archived", label: "Archived" },
|
|
209
|
-
{ id: "cancelled", label: "Cancelled" },
|
|
210
230
|
];
|
|
211
|
-
/** Seller > Prize Draws — draw-state filter chip set.
|
|
231
|
+
/** Seller > Prize Draws — draw-state filter chip set. Same root cause and
|
|
232
|
+
* fix as SELLER_AUCTION_STATUS_TABS — "ended" is derived from
|
|
233
|
+
* `prizeRevealWindowEnd` vs now (handled by the "Show closed" toolbar
|
|
234
|
+
* toggle), no stored "cancelled" state exists. */
|
|
212
235
|
export const SELLER_PRIZE_DRAW_STATUS_TABS = [
|
|
213
236
|
ALL_TAB,
|
|
214
|
-
{ id: "
|
|
237
|
+
{ id: "published", label: "Active" },
|
|
215
238
|
{ id: "draft", label: "Draft" },
|
|
216
|
-
{ id: "ended", label: "Ended" },
|
|
217
|
-
{ id: "cancelled", label: "Cancelled" },
|
|
218
239
|
];
|
|
219
240
|
/** Seller > Orders — order-state filter chip set. Subset of
|
|
220
241
|
* `ADMIN_ORDER_STATUS_TABS` — sellers don't see `RETURN_REQUESTED` until
|
|
221
|
-
* the buyer initiates one through support.
|
|
242
|
+
* the buyer initiates one through support. IDs are lowercase to match the
|
|
243
|
+
* real stored `OrderStatusValues` (Firestore `==` is byte-exact — the
|
|
244
|
+
* previous uppercase ids never matched any document, every chip here
|
|
245
|
+
* silently returned zero rows). */
|
|
222
246
|
export const SELLER_ORDER_STATUS_TABS = [
|
|
223
247
|
ALL_TAB,
|
|
224
|
-
{ id: "
|
|
225
|
-
{ id: "
|
|
226
|
-
{ id: "
|
|
227
|
-
{ id: "
|
|
228
|
-
{ id: "
|
|
229
|
-
{ id: "
|
|
248
|
+
{ id: "pending", label: "Pending" },
|
|
249
|
+
{ id: "processing", label: "Processing" },
|
|
250
|
+
{ id: "shipped", label: "Shipped" },
|
|
251
|
+
{ id: "delivered", label: "Delivered" },
|
|
252
|
+
{ id: "cancelled", label: "Cancelled" },
|
|
253
|
+
{ id: "refunded", label: "Refunded" },
|
|
230
254
|
];
|
|
231
|
-
/** Seller > Offers — offer-state filter chip set.
|
|
255
|
+
/** Seller > Offers — offer-state filter chip set. Real `OfferStatus` is
|
|
256
|
+
* pending|accepted|declined|countered|expired|withdrawn|paid — there is no
|
|
257
|
+
* "rejected" value, the real one is "declined" (the id below was fixed;
|
|
258
|
+
* the previous "rejected" id always returned zero rows). Label kept as
|
|
259
|
+
* "Rejected" for continuity with existing seller-facing wording. */
|
|
232
260
|
export const SELLER_OFFER_STATUS_TABS = [
|
|
233
261
|
ALL_TAB,
|
|
234
262
|
{ id: "pending", label: "Pending" },
|
|
235
263
|
{ id: "accepted", label: "Accepted" },
|
|
236
|
-
{ id: "
|
|
264
|
+
{ id: "declined", label: "Rejected" },
|
|
237
265
|
{ id: "expired", label: "Expired" },
|
|
238
266
|
];
|
|
239
267
|
/** Seller > Bids — bid-state filter chip set. Uses the empty-sentinel
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Admin Feature Firestore Document Types & Constants
|
|
3
3
|
* Covers: notifications, chat rooms, site settings
|
|
4
4
|
*/
|
|
5
|
+
import type { AboutContentDocument } from "../../about/schemas/firestore";
|
|
5
6
|
export declare const ADMIN_CHECKOUT_BYPASS_FLAG_KEY: "adminCheckoutBypass";
|
|
6
7
|
export type NotificationType = "order_placed" | "order_confirmed" | "order_shipped" | "order_delivered" | "order_cancelled" | "bid_placed" | "bid_outbid" | "bid_won" | "bid_lost" | "review_approved" | "review_replied" | "product_available" | "promotion" | "system" | "welcome" | "account_action" | "offer_received" | "offer_responded" | "offer_expired" | "offer_counter_accepted" | "refund_initiated" | "prize_reveal_ready" | "prize_reveal_expired" | "prize_reveal_reminder" | "emi_installment_due_soon" | "emi_installment_overdue" | "payment_review";
|
|
7
8
|
import type { BaseDocument } from "../../../_internal/shared/types/base-document";
|
|
@@ -426,6 +427,10 @@ export interface SiteSettingsDocument extends BaseDocument {
|
|
|
426
427
|
codDeposit: number;
|
|
427
428
|
};
|
|
428
429
|
};
|
|
430
|
+
/** About Us page content, admin-editable via Site Settings. Optional so
|
|
431
|
+
* pre-existing docs without it still type-check; `about/page.tsx` falls
|
|
432
|
+
* back to i18n defaults when absent. */
|
|
433
|
+
aboutContent?: AboutContentDocument;
|
|
429
434
|
navbarConfig?: {
|
|
430
435
|
hiddenNavItems?: string[];
|
|
431
436
|
};
|
|
@@ -47,7 +47,7 @@ export async function placeBid(userId, userEmail, input) {
|
|
|
47
47
|
const baseBid = (product.currentBid ?? 0) > 0
|
|
48
48
|
? product.currentBid
|
|
49
49
|
: (product.startingBid ?? product.price);
|
|
50
|
-
const minIncrement = product.minBidIncrement ??
|
|
50
|
+
const minIncrement = product.minBidIncrement ?? 1;
|
|
51
51
|
// Proxy-bid semantics (eBay style): the buyer's `bidAmount` is treated as
|
|
52
52
|
// their **maximum** they're willing to pay; the visible price only steps up
|
|
53
53
|
// in `minIncrement` units as needed to stay ahead of the previous high bid.
|
|
@@ -125,9 +125,9 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, on
|
|
|
125
125
|
price: typeof p.price === "number" ? p.price : undefined,
|
|
126
126
|
storeId: typeof p.storeId === "string" ? p.storeId : undefined,
|
|
127
127
|
storeName: typeof p.storeName === "string" ? p.storeName : undefined,
|
|
128
|
-
} }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Nav, { "aria-label": "Breadcrumb", layout: "flex-wrap", gap: "2xs", textSize: "xs", color: "muted", children: [_jsx(Link, { href: String(ROUTES.HOME), className: CLS_BREADCRUMB_LINK, children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: CLS_BREADCRUMB_LINK, children: "Auctions" }), category && (_jsxs(_Fragment, { children: [_jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: CLS_BREADCRUMB_LINK, children: categoryName || category })] })), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(AuctionDetailView, { renderGallery: () => (_jsx(ProductGalleryClient, { images: images, productName: title })), renderInfo: () => renderAuctionInfoPanel({ title, currentBid, currency, bidCount, isEnded, endDate, buyNowPrice, featured, freeShipping, condition, category, categoryName, brand, brandSlug, productFeatures, features, descriptionHtml, safeSeller, storeHref }), renderBidForm: () => onPlaceBid ? (_jsx(Stack, { id: "auction-bid-form", gap: "3", children: _jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "3", rounded: "xl", surface: "muted", children: [_jsxs(Row, { justify: "between", align: "baseline", children: [_jsx(Span, { size: "xl", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", color: "muted", children: [bidCount, " ", bidCount === 1 ? "bid" : "bids", " \u00B7 min increment ", formatCurrency(minBidIncrement, currency)] })] }), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] }) })) : (
|
|
128
|
+
} }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Nav, { "aria-label": "Breadcrumb", layout: "flex-wrap", gap: "2xs", textSize: "xs", color: "muted", children: [_jsx(Link, { href: String(ROUTES.HOME), className: CLS_BREADCRUMB_LINK, children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: CLS_BREADCRUMB_LINK, children: "Auctions" }), category && (_jsxs(_Fragment, { children: [_jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: CLS_BREADCRUMB_LINK, children: categoryName || category })] })), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(AuctionDetailView, { renderGallery: () => (_jsx(ProductGalleryClient, { images: images, productName: title })), renderInfo: () => renderAuctionInfoPanel({ title, currentBid, currency, bidCount, isEnded, endDate, buyNowPrice, featured, freeShipping, condition, category, categoryName, brand, brandSlug, productFeatures, features, descriptionHtml, safeSeller, storeHref }), renderBidForm: () => onPlaceBid ? (_jsx(Stack, { id: "auction-bid-form", gap: "3", children: _jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "3", rounded: "xl", surface: "muted", children: [_jsxs(Row, { justify: "between", align: "baseline", children: [_jsx(Span, { size: "xl", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", color: "muted", children: [bidCount, " ", bidCount === 1 ? "bid" : "bids", !isEnded && _jsxs(_Fragment, { children: [" \u00B7 min increment ", formatCurrency(minBidIncrement, currency)] })] })] }), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] }) })) : (
|
|
129
129
|
/* Read-only bid panel — shown when no bid action is wired (preview/demo) */
|
|
130
|
-
_jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "md", rounded: "xl", surface: "muted", children: [_jsx(Stack, { gap: "xs", children: _jsxs(Text, { size: "xs", color: "muted", children: ["Starting bid: ", formatCurrency(startingBid, currency), " \u00B7 min increment ", formatCurrency(minBidIncrement, currency)] }) }), _jsxs(Stack, { gap: "sm", children: [_jsx(Input, { type: "number", placeholder: `At least ${formatCurrency(currentBid + minBidIncrement, currency)}`, min: currentBid + minBidIncrement, "aria-label": "Your bid amount", disabled: isEnded }), _jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isEnded, children: isEnded ? "Auction Ended" : "Place Bid" }), buyNowPrice !== null && !isEnded && !bidsHaveStarted && (_jsxs(Button, { variant: "secondary", size: "md", className: "w-full", disabled: true, children: ["Buy Now \u2014 ", formatCurrency(buyNowPrice, currency)] }))] }), tags.length > 0 && (_jsx(Div, { border: "default", className: "border-t", padding: "t-md", children: _jsx(Row, { wrap: true, gap: "xs", children: tags.map((tag) => (_jsx(Span, { size: "xs", rounded: "full", padding: "pill-sm-tall", surface: "subtle", color: "muted", children: tag }, tag))) }) }))] })), renderMobileBidForm: () => !isEnded && onPlaceBid ? (_jsxs(Stack, { className: `lg:hidden ${__P.p4}`, border: "subtle", gap: "3", rounded: "xl", surface: "muted", children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { size: "base", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", color: "muted", children: [bidCount, " bids"] })] }), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] })) : !isEnded ? (_jsxs(Div, { className: `${__P.p4} lg:hidden`, border: "subtle", rounded: "xl", surface: "muted", children: [_jsxs(Row, { align: "center", gap: "sm", className: "mb-3", children: [_jsx(Span, { size: "base", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", color: "muted", children: [bidCount, " bids"] })] }), _jsx(Button, { variant: "primary", size: "md", className: "w-full", children: "Place Bid" })] })) : null, renderSublistingSection: sublistingCategoryId
|
|
130
|
+
_jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "md", rounded: "xl", surface: "muted", children: [_jsx(Stack, { gap: "xs", children: _jsxs(Text, { size: "xs", color: "muted", children: ["Starting bid: ", formatCurrency(startingBid, currency), !isEnded && _jsxs(_Fragment, { children: [" \u00B7 min increment ", formatCurrency(minBidIncrement, currency)] })] }) }), _jsxs(Stack, { gap: "sm", children: [_jsx(Input, { type: "number", placeholder: `At least ${formatCurrency(currentBid + minBidIncrement, currency)}`, min: currentBid + minBidIncrement, "aria-label": "Your bid amount", disabled: isEnded }), _jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isEnded, children: isEnded ? "Auction Ended" : "Place Bid" }), buyNowPrice !== null && !isEnded && !bidsHaveStarted && (_jsxs(Button, { variant: "secondary", size: "md", className: "w-full", disabled: true, children: ["Buy Now \u2014 ", formatCurrency(buyNowPrice, currency)] }))] }), tags.length > 0 && (_jsx(Div, { border: "default", className: "border-t", padding: "t-md", children: _jsx(Row, { wrap: true, gap: "xs", children: tags.map((tag) => (_jsx(Span, { size: "xs", rounded: "full", padding: "pill-sm-tall", surface: "subtle", color: "muted", children: tag }, tag))) }) }))] })), renderMobileBidForm: () => !isEnded && onPlaceBid ? (_jsxs(Stack, { className: `lg:hidden ${__P.p4}`, border: "subtle", gap: "3", rounded: "xl", surface: "muted", children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { size: "base", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", color: "muted", children: [bidCount, " bids"] })] }), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] })) : !isEnded ? (_jsxs(Div, { className: `${__P.p4} lg:hidden`, border: "subtle", rounded: "xl", surface: "muted", children: [_jsxs(Row, { align: "center", gap: "sm", className: "mb-3", children: [_jsx(Span, { size: "base", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", color: "muted", children: [bidCount, " bids"] })] }), _jsx(Button, { variant: "primary", size: "md", className: "w-full", children: "Place Bid" })] })) : null, renderSublistingSection: sublistingCategoryId
|
|
131
131
|
? () => (_jsx(SublistingCarouselSection, { sublistingCategoryId: sublistingCategoryId, currentListingId: String(product.id) }))
|
|
132
132
|
: undefined, renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-[var(--appkit-color-text-muted)]" })) : undefined, specsContent: specs.length > 0 ? (_jsx(Dl, { divide: "subtle", rounded: "xl", border: "subtle", className: "overflow-hidden", children: specs.map((s, i) => (_jsxs(Row, { gap: "md", oddEven: "zebra", surface: "default", padding: "inline", children: [_jsx(Dt, { className: "w-36 flex-shrink-0", color: "primary", weight: "medium", children: s.name }), _jsxs(Dd, { className: "flex-1", color: "muted", children: [s.value, s.unit ? ` ${s.unit}` : ""] })] }, i))) })) : undefined, customTabs: customSections.map((s) => ({
|
|
133
133
|
id: s.id,
|