@mohasinac/appkit 2.4.5 → 2.4.6
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/features/auctions/components/AuctionDetailPageView.js +5 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +5 -1
- package/dist/features/products/components/AuctionDetailView.d.ts +3 -1
- package/dist/features/products/components/AuctionDetailView.js +6 -3
- package/dist/features/products/components/PreOrderDetailView.d.ts +4 -2
- package/dist/features/products/components/PreOrderDetailView.js +2 -2
- package/dist/features/products/components/ProductDetailPageView.js +5 -1
- package/dist/features/products/components/ProductDetailView.d.ts +4 -2
- package/dist/features/products/components/ProductDetailView.js +2 -2
- package/dist/features/products/components/index.d.ts +2 -0
- package/dist/features/products/components/index.js +2 -0
- package/dist/next/routing/route-map.d.ts +9 -0
- package/dist/next/routing/route-map.js +3 -0
- package/package.json +1 -1
|
@@ -20,6 +20,7 @@ import { MarketplaceAuctionGrid } from "./MarketplaceAuctionGrid";
|
|
|
20
20
|
import { listReviewsBySeller } from "../../reviews/actions/review-actions";
|
|
21
21
|
import { PlaceBidFormClient } from "./PlaceBidFormClient";
|
|
22
22
|
import { CollapsibleBidHistory } from "./CollapsibleBidHistory";
|
|
23
|
+
import { SublistingCarouselSection } from "../../products/components/SublistingCarouselSection";
|
|
23
24
|
function toDescriptionHtml(raw) {
|
|
24
25
|
if (!raw)
|
|
25
26
|
return "";
|
|
@@ -90,6 +91,7 @@ export async function AuctionDetailPageView({ id, onPlaceBid }) {
|
|
|
90
91
|
? p.customSections
|
|
91
92
|
: [];
|
|
92
93
|
const descriptionHtml = toDescriptionHtml(p.description);
|
|
94
|
+
const sublistingCategoryId = typeof p.sublistingCategoryId === "string" ? p.sublistingCategoryId : null;
|
|
93
95
|
const relatedDocs = await productRepository
|
|
94
96
|
.findByCategory(String(p.category ?? ""))
|
|
95
97
|
.catch(() => []);
|
|
@@ -107,7 +109,9 @@ export async function AuctionDetailPageView({ id, onPlaceBid }) {
|
|
|
107
109
|
codAvailable: "Cash on Delivery",
|
|
108
110
|
wishlistCount: (n) => `${n} wishlisted`,
|
|
109
111
|
categoryProductCount: (n, cat) => `${n} in ${cat}`,
|
|
110
|
-
} }), (categoryName || category || brand) && (_jsxs(Row, { align: "center", gap: "xs", className: "text-xs text-zinc-400 dark:text-zinc-500 flex-wrap", children: [category ? (_jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: "hover:text-primary-600 dark:hover:text-primary-400 transition-colors", children: categoryName || category })) : categoryName ? (_jsx(Span, { children: categoryName })) : null, (category || categoryName) && brand && _jsx(Span, { children: "\u203A" }), brand && (brandSlug ? (_jsx(Link, { href: String(ROUTES.PUBLIC.BRAND_DETAIL(brandSlug)), className: "font-medium text-zinc-600 dark:text-zinc-300 hover:text-primary-600 dark:hover:text-primary-400 transition-colors", children: brand })) : (_jsx(Span, { className: "font-medium text-zinc-600 dark:text-zinc-300", children: brand })))] })), features.length > 0 && (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 px-4 py-3", children: [_jsx(Text, { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "About this item" }), _jsx("ul", { className: "space-y-1.5", children: features.map((f, i) => (_jsxs("li", { className: "flex items-start gap-2 text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i))) })] })), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-zinc-600 dark:text-zinc-400 line-clamp-4" })), safeSeller && (_jsx(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-3", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] uppercase tracking-wide text-zinc-400 dark:text-zinc-500 mb-0.5", children: "Listed by" }), _jsx(Text, { className: "text-sm font-semibold text-zinc-800 dark:text-zinc-200", children: safeSeller })] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-3 py-1.5 text-xs font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderBidForm: () => onPlaceBid ? (_jsx(Div, { id: "auction-bid-form", children: _jsx(PlaceBidFormClient, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid }) })) : (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-5 space-y-4", children: [_jsxs(Div, { className: "space-y-1", children: [_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-xs text-zinc-500", children: "Current bid" }), _jsx(Text, { className: "text-xs text-zinc-500", children: "Starting bid" })] }), _jsxs(Row, { justify: "between", align: "baseline", children: [_jsx(Span, { className: "text-xl font-bold text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsx(Span, { className: "text-sm text-zinc-500", children: formatCurrency(startingBid, currency) })] }), _jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-500", children: [bidCount, " ", bidCount === 1 ? "bid" : "bids", " \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 && (_jsxs(Button, { variant: "secondary", size: "md", className: "w-full", children: ["Buy Now \u2014 ", formatCurrency(buyNowPrice, currency)] }))] }), tags.length > 0 && (_jsx(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: _jsx(Row, { wrap: true, gap: "xs", children: tags.map((tag) => (_jsx(Span, { className: "rounded-full bg-zinc-100 dark:bg-zinc-800 px-2.5 py-1 text-xs text-zinc-600 dark:text-zinc-300", children: tag }, tag))) }) }))] })), renderMobileBidForm: () => !isEnded && onPlaceBid ? (_jsx(Div, { className: "lg:hidden", children: _jsx(PlaceBidFormClient, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid }) })) : !isEnded ? (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-4 lg:hidden", children: [_jsxs(Row, { align: "center", gap: "sm", className: "mb-3", children: [_jsx(Span, { className: "text-base font-bold text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { className: "text-xs text-zinc-500", children: [bidCount, " bids"] })] }), _jsx(Button, { variant: "primary", size: "md", className: "w-full", children: "Place Bid" })] })) : null,
|
|
112
|
+
} }), (categoryName || category || brand) && (_jsxs(Row, { align: "center", gap: "xs", className: "text-xs text-zinc-400 dark:text-zinc-500 flex-wrap", children: [category ? (_jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: "hover:text-primary-600 dark:hover:text-primary-400 transition-colors", children: categoryName || category })) : categoryName ? (_jsx(Span, { children: categoryName })) : null, (category || categoryName) && brand && _jsx(Span, { children: "\u203A" }), brand && (brandSlug ? (_jsx(Link, { href: String(ROUTES.PUBLIC.BRAND_DETAIL(brandSlug)), className: "font-medium text-zinc-600 dark:text-zinc-300 hover:text-primary-600 dark:hover:text-primary-400 transition-colors", children: brand })) : (_jsx(Span, { className: "font-medium text-zinc-600 dark:text-zinc-300", children: brand })))] })), features.length > 0 && (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 px-4 py-3", children: [_jsx(Text, { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "About this item" }), _jsx("ul", { className: "space-y-1.5", children: features.map((f, i) => (_jsxs("li", { className: "flex items-start gap-2 text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i))) })] })), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-zinc-600 dark:text-zinc-400 line-clamp-4" })), safeSeller && (_jsx(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-3", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] uppercase tracking-wide text-zinc-400 dark:text-zinc-500 mb-0.5", children: "Listed by" }), _jsx(Text, { className: "text-sm font-semibold text-zinc-800 dark:text-zinc-200", children: safeSeller })] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-3 py-1.5 text-xs font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderBidForm: () => onPlaceBid ? (_jsx(Div, { id: "auction-bid-form", children: _jsx(PlaceBidFormClient, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid }) })) : (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-5 space-y-4", children: [_jsxs(Div, { className: "space-y-1", children: [_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-xs text-zinc-500", children: "Current bid" }), _jsx(Text, { className: "text-xs text-zinc-500", children: "Starting bid" })] }), _jsxs(Row, { justify: "between", align: "baseline", children: [_jsx(Span, { className: "text-xl font-bold text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsx(Span, { className: "text-sm text-zinc-500", children: formatCurrency(startingBid, currency) })] }), _jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-500", children: [bidCount, " ", bidCount === 1 ? "bid" : "bids", " \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 && (_jsxs(Button, { variant: "secondary", size: "md", className: "w-full", children: ["Buy Now \u2014 ", formatCurrency(buyNowPrice, currency)] }))] }), tags.length > 0 && (_jsx(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: _jsx(Row, { wrap: true, gap: "xs", children: tags.map((tag) => (_jsx(Span, { className: "rounded-full bg-zinc-100 dark:bg-zinc-800 px-2.5 py-1 text-xs text-zinc-600 dark:text-zinc-300", children: tag }, tag))) }) }))] })), renderMobileBidForm: () => !isEnded && onPlaceBid ? (_jsx(Div, { className: "lg:hidden", children: _jsx(PlaceBidFormClient, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid }) })) : !isEnded ? (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-4 lg:hidden", children: [_jsxs(Row, { align: "center", gap: "sm", className: "mb-3", children: [_jsx(Span, { className: "text-base font-bold text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { className: "text-xs text-zinc-500", children: [bidCount, " bids"] })] }), _jsx(Button, { variant: "primary", size: "md", className: "w-full", children: "Place Bid" })] })) : null, renderSublistingSection: sublistingCategoryId
|
|
113
|
+
? () => (_jsx(SublistingCarouselSection, { sublistingCategoryId: sublistingCategoryId, currentListingId: String(product.id) }))
|
|
114
|
+
: undefined, renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-zinc-700 dark:text-zinc-300" })) : undefined, specsContent: specs.length > 0 ? (_jsx("dl", { className: "divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800 overflow-hidden text-sm", children: specs.map((s, i) => (_jsxs("div", { className: "flex gap-4 px-4 py-3 bg-white dark:bg-zinc-900 even:bg-zinc-50 dark:even:bg-zinc-800/50", children: [_jsx("dt", { className: "w-36 flex-shrink-0 font-medium text-zinc-700 dark:text-zinc-300", children: s.name }), _jsxs("dd", { className: "flex-1 text-zinc-600 dark:text-zinc-400", children: [s.value, s.unit ? ` ${s.unit}` : ""] })] }, i))) })) : undefined, customTabs: customSections.map((s) => ({
|
|
111
115
|
id: s.id,
|
|
112
116
|
label: s.title,
|
|
113
117
|
content: _jsx(CustomSectionTabContent, { section: s }),
|
|
@@ -15,6 +15,7 @@ import { PreOrderActionsClient } from "./PreOrderActionsClient";
|
|
|
15
15
|
import { ProductGalleryClient } from "../../products/components/ProductGalleryClient";
|
|
16
16
|
import { ProductFeatureBadges } from "../../products/components/ProductFeatureBadges";
|
|
17
17
|
import { ShareButton } from "../../products/components/ShareButton";
|
|
18
|
+
import { SublistingCarouselSection } from "../../products/components/SublistingCarouselSection";
|
|
18
19
|
function toDescriptionHtml(raw) {
|
|
19
20
|
if (!raw)
|
|
20
21
|
return "";
|
|
@@ -95,6 +96,7 @@ export async function PreOrderDetailPageView({ id, onReserveNow }) {
|
|
|
95
96
|
? p.customSections
|
|
96
97
|
: [];
|
|
97
98
|
const descriptionHtml = toDescriptionHtml(p.description);
|
|
99
|
+
const sublistingCategoryId = typeof p.sublistingCategoryId === "string" ? p.sublistingCategoryId : null;
|
|
98
100
|
return (_jsx(Main, { children: _jsxs(Container, { size: "xl", className: "px-4 py-6", children: [_jsxs("div", { className: "mb-4 flex items-center justify-between flex-wrap gap-2", children: [_jsxs("nav", { "aria-label": "Breadcrumb", className: "flex items-center gap-1.5 text-xs text-zinc-500 dark:text-zinc-400 flex-wrap", children: [_jsx(Link, { href: String(ROUTES.HOME), className: "hover:text-primary-600 transition-colors", children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRE_ORDERS), className: "hover:text-primary-600 transition-colors", children: "Pre-Orders" }), category && (_jsxs(_Fragment, { children: [_jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: "hover:text-primary-600 transition-colors", children: categoryName || category })] })), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "text-zinc-700 dark:text-zinc-300 truncate max-w-[200px]", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(PreOrderDetailView, { renderGallery: () => (_jsx(ProductGalleryClient, { images: images, productName: title })), renderInfo: () => (_jsxs(Stack, { gap: "sm", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", className: "mb-1.5 flex-wrap", children: [_jsx(Span, { className: "inline-block rounded-full bg-indigo-100 dark:bg-indigo-900/30 px-2.5 py-0.5 text-xs font-semibold text-indigo-700 dark:text-indigo-300", children: "Pre-Order" }), productionStatus && (_jsx(Span, { className: "inline-block rounded-full bg-zinc-100 dark:bg-zinc-800 px-2.5 py-0.5 text-xs font-medium text-zinc-600 dark:text-zinc-300", children: PRODUCTION_STATUS_LABELS[productionStatus] ?? productionStatus }))] }), _jsx(Heading, { level: 1, className: "text-xl font-bold leading-snug text-zinc-900 dark:text-zinc-50 sm:text-2xl", children: title })] }), price !== null && (_jsx(Span, { className: "text-2xl font-bold text-zinc-900 dark:text-zinc-50", children: formatCurrency(price, currency) })), deliveryDate && (_jsxs(Row, { align: "center", gap: "xs", className: "text-sm text-zinc-600 dark:text-zinc-400", children: [_jsx(Span, { children: "\uD83D\uDCC5" }), _jsx(Span, { children: "Estimated delivery:" }), _jsx(Span, { className: "font-medium", children: deliveryDate.toLocaleDateString(undefined, { year: "numeric", month: "long" }) })] })), _jsx(ProductFeatureBadges, { featured: featured, freeShipping: freeShipping, condition: condition ?? undefined, returnable: isCancellable, labels: {
|
|
99
101
|
featured: "Featured",
|
|
100
102
|
fasterDelivery: "Faster Delivery",
|
|
@@ -109,7 +111,9 @@ export async function PreOrderDetailPageView({ id, onReserveNow }) {
|
|
|
109
111
|
codAvailable: "Cash on Delivery",
|
|
110
112
|
wishlistCount: (n) => `${n} wishlisted`,
|
|
111
113
|
categoryProductCount: (n, cat) => `${n} in ${cat}`,
|
|
112
|
-
} }), (categoryName || category || brand) && (_jsxs(Row, { align: "center", gap: "xs", className: "text-xs text-zinc-400 dark:text-zinc-500 flex-wrap", children: [category ? (_jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: "hover:text-primary-600 dark:hover:text-primary-400 transition-colors", children: categoryName || category })) : (categoryName ? _jsx(Span, { children: categoryName }) : null), brand && (categoryName || category) && (_jsx(Span, { className: "text-zinc-300 dark:text-zinc-600", children: "\u00B7" })), brand && (brandSlug ? (_jsx(Link, { href: String(ROUTES.PUBLIC.BRAND_DETAIL(brandSlug)), className: "hover:text-primary-600 dark:hover:text-primary-400 transition-colors", children: brand })) : (_jsx(Span, { children: brand })))] })), features.length > 0 && (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 px-4 py-3", children: [_jsx(Text, { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "About this product" }), _jsx("ul", { className: "space-y-1.5", children: features.map((f, i) => (_jsxs("li", { className: "flex items-start gap-2 text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i))) })] })), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-zinc-600 dark:text-zinc-400 line-clamp-4" })), safeSeller && (_jsx(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-3", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] uppercase tracking-wide text-zinc-400 dark:text-zinc-500 mb-0.5", children: "Sold by" }), _jsx(Text, { className: "text-sm font-semibold text-zinc-800 dark:text-zinc-200", children: safeSeller })] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-3 py-1.5 text-xs font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })),
|
|
114
|
+
} }), (categoryName || category || brand) && (_jsxs(Row, { align: "center", gap: "xs", className: "text-xs text-zinc-400 dark:text-zinc-500 flex-wrap", children: [category ? (_jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: "hover:text-primary-600 dark:hover:text-primary-400 transition-colors", children: categoryName || category })) : (categoryName ? _jsx(Span, { children: categoryName }) : null), brand && (categoryName || category) && (_jsx(Span, { className: "text-zinc-300 dark:text-zinc-600", children: "\u00B7" })), brand && (brandSlug ? (_jsx(Link, { href: String(ROUTES.PUBLIC.BRAND_DETAIL(brandSlug)), className: "hover:text-primary-600 dark:hover:text-primary-400 transition-colors", children: brand })) : (_jsx(Span, { children: brand })))] })), features.length > 0 && (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 px-4 py-3", children: [_jsx(Text, { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "About this product" }), _jsx("ul", { className: "space-y-1.5", children: features.map((f, i) => (_jsxs("li", { className: "flex items-start gap-2 text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i))) })] })), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-zinc-600 dark:text-zinc-400 line-clamp-4" })), safeSeller && (_jsx(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-3", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] uppercase tracking-wide text-zinc-400 dark:text-zinc-500 mb-0.5", children: "Sold by" }), _jsx(Text, { className: "text-sm font-semibold text-zinc-800 dark:text-zinc-200", children: safeSeller })] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-3 py-1.5 text-xs font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderSublistingSection: sublistingCategoryId
|
|
115
|
+
? () => (_jsx(SublistingCarouselSection, { sublistingCategoryId: sublistingCategoryId, currentListingId: String(product.id) }))
|
|
116
|
+
: undefined, renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-zinc-700 dark:text-zinc-300" })) : undefined, specsContent: specs.length > 0 ? (_jsx("dl", { className: "divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800 overflow-hidden text-sm", children: specs.map((s, i) => (_jsxs("div", { className: "flex gap-4 px-4 py-3 bg-white dark:bg-zinc-900 even:bg-zinc-50 dark:even:bg-zinc-800/50", children: [_jsx("dt", { className: "w-36 flex-shrink-0 font-medium text-zinc-700 dark:text-zinc-300", children: s.name }), _jsxs("dd", { className: "flex-1 text-zinc-600 dark:text-zinc-400", children: [s.value, s.unit ? ` ${s.unit}` : ""] })] }, i))) })) : undefined, customTabs: customSections.map((s) => ({
|
|
113
117
|
id: s.id,
|
|
114
118
|
label: s.title,
|
|
115
119
|
content: _jsx(CustomSectionTabContent, { section: s }),
|
|
@@ -7,8 +7,10 @@ export interface AuctionDetailViewProps extends Omit<DetailViewShellProps, "main
|
|
|
7
7
|
renderBidForm?: () => React.ReactNode;
|
|
8
8
|
/** Mobile bid form shown below the grid on small screens */
|
|
9
9
|
renderMobileBidForm?: () => React.ReactNode;
|
|
10
|
+
/** Rendered between the main grid and the below-fold tabs (e.g. sub-listing carousel). */
|
|
11
|
+
renderSublistingSection?: () => React.ReactNode;
|
|
10
12
|
renderTabs?: () => React.ReactNode;
|
|
11
13
|
renderBidHistory?: () => React.ReactNode;
|
|
12
14
|
renderRelated?: () => React.ReactNode;
|
|
13
15
|
}
|
|
14
|
-
export declare function AuctionDetailView({ renderGallery, renderInfo, renderBidForm, renderMobileBidForm, renderTabs, renderBidHistory, renderRelated, isLoading, ...rest }: AuctionDetailViewProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export declare function AuctionDetailView({ renderGallery, renderInfo, renderBidForm, renderMobileBidForm, renderSublistingSection, renderTabs, renderBidHistory, renderRelated, isLoading, ...rest }: AuctionDetailViewProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment as _Fragment, jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { DetailViewShell, Div } from "../../../ui";
|
|
3
|
-
export function AuctionDetailView({ renderGallery, renderInfo, renderBidForm, renderMobileBidForm, renderTabs, renderBidHistory, renderRelated, isLoading = false, ...rest }) {
|
|
3
|
+
export function AuctionDetailView({ renderGallery, renderInfo, renderBidForm, renderMobileBidForm, renderSublistingSection, renderTabs, renderBidHistory, renderRelated, isLoading = false, ...rest }) {
|
|
4
|
+
const mobileBid = renderMobileBidForm?.();
|
|
5
|
+
const sublistingSection = renderSublistingSection?.();
|
|
6
|
+
const afterMainContent = (mobileBid || sublistingSection) ? (_jsxs(_Fragment, { children: [mobileBid, sublistingSection] })) : undefined;
|
|
4
7
|
return (_jsx(DetailViewShell, { portal: "public", ...rest, layout: "grid-3", isLoading: isLoading, mainSlots: [
|
|
5
8
|
renderGallery?.(isLoading),
|
|
6
9
|
renderInfo?.(isLoading),
|
|
7
10
|
_jsx(Div, { className: "hidden lg:block", children: renderBidForm?.() }, "bid"),
|
|
8
|
-
], afterMain:
|
|
11
|
+
], afterMain: afterMainContent, belowFold: [renderTabs?.(), renderBidHistory?.(), renderRelated?.()] }));
|
|
9
12
|
}
|
|
@@ -4,11 +4,13 @@ import type { DetailViewShellProps } from "../../../ui";
|
|
|
4
4
|
* PreOrderDetailView — shell for pre-order product detail pages.
|
|
5
5
|
* Uses grid-2 layout (gallery | info+buyBar).
|
|
6
6
|
*/
|
|
7
|
-
export interface PreOrderDetailViewProps extends Omit<DetailViewShellProps, "mainSlots" | "belowFold" | "layout"> {
|
|
7
|
+
export interface PreOrderDetailViewProps extends Omit<DetailViewShellProps, "mainSlots" | "belowFold" | "layout" | "afterMain"> {
|
|
8
8
|
renderGallery?: (isLoading: boolean) => React.ReactNode;
|
|
9
9
|
renderInfo?: (isLoading: boolean) => React.ReactNode;
|
|
10
10
|
renderBuyBar?: () => React.ReactNode;
|
|
11
|
+
/** Rendered between the main grid and the below-fold tabs (e.g. sub-listing carousel). */
|
|
12
|
+
renderSublistingSection?: () => React.ReactNode;
|
|
11
13
|
renderTabs?: () => React.ReactNode;
|
|
12
14
|
renderRelated?: () => React.ReactNode;
|
|
13
15
|
}
|
|
14
|
-
export declare function PreOrderDetailView({ renderGallery, renderInfo, renderBuyBar, renderTabs, renderRelated, isLoading, ...rest }: PreOrderDetailViewProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export declare function PreOrderDetailView({ renderGallery, renderInfo, renderBuyBar, renderSublistingSection, renderTabs, renderRelated, isLoading, ...rest }: PreOrderDetailViewProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { DetailViewShell } from "../../../ui";
|
|
4
|
-
export function PreOrderDetailView({ renderGallery, renderInfo, renderBuyBar, renderTabs, renderRelated, isLoading = false, ...rest }) {
|
|
4
|
+
export function PreOrderDetailView({ renderGallery, renderInfo, renderBuyBar, renderSublistingSection, renderTabs, renderRelated, isLoading = false, ...rest }) {
|
|
5
5
|
return (_jsx(DetailViewShell, { portal: "public", ...rest, layout: "grid-2", isLoading: isLoading, mainSlots: [
|
|
6
6
|
renderGallery?.(isLoading),
|
|
7
7
|
_jsxs(React.Fragment, { children: [renderInfo?.(isLoading), renderBuyBar?.()] }, "info"),
|
|
8
|
-
], belowFold: [renderTabs?.(), renderRelated?.()] }));
|
|
8
|
+
], afterMain: renderSublistingSection?.(), belowFold: [renderTabs?.(), renderRelated?.()] }));
|
|
9
9
|
}
|
|
@@ -16,6 +16,7 @@ import { RelatedProductsCarousel } from "./RelatedProductsCarousel";
|
|
|
16
16
|
import { BuyBar } from "./BuyBar";
|
|
17
17
|
import { ShareButton } from "./ShareButton";
|
|
18
18
|
import { CustomSectionTabContent } from "./CustomSectionTabContent";
|
|
19
|
+
import { SublistingCarouselSection } from "./SublistingCarouselSection";
|
|
19
20
|
// ---------------------------------------------------------------------------
|
|
20
21
|
// Helpers
|
|
21
22
|
// ---------------------------------------------------------------------------
|
|
@@ -155,6 +156,7 @@ export async function ProductDetailPageView({ slug, renderOfferAction, }) {
|
|
|
155
156
|
? String(ROUTES.PUBLIC.SELLER_DETAIL(sellerId))
|
|
156
157
|
: null;
|
|
157
158
|
const descriptionHtml = toDescriptionHtml(p.description);
|
|
159
|
+
const sublistingCategoryId = typeof p.sublistingCategoryId === "string" ? p.sublistingCategoryId : null;
|
|
158
160
|
// -- Fetch reviews + related in parallel ------------------------------------
|
|
159
161
|
const [reviewDocs, relatedDocs] = await Promise.all([
|
|
160
162
|
reviewRepository
|
|
@@ -210,7 +212,9 @@ export async function ProductDetailPageView({ slug, renderOfferAction, }) {
|
|
|
210
212
|
{ icon: "🔒", label: "Secure\nPayment" },
|
|
211
213
|
{ icon: "✓", label: "Verified\nSeller" },
|
|
212
214
|
{ icon: "⭐", label: "Quality\nGuarantee" },
|
|
213
|
-
].map(({ icon, label }) => (_jsxs(Div, { className: "flex flex-col items-center gap-1 text-xs text-zinc-500 dark:text-zinc-400 min-w-[60px]", children: [_jsx(Span, { className: "text-base", children: icon }), _jsx(Span, { className: "whitespace-pre-line leading-tight", children: label })] }, label))) }) })] })),
|
|
215
|
+
].map(({ icon, label }) => (_jsxs(Div, { className: "flex flex-col items-center gap-1 text-xs text-zinc-500 dark:text-zinc-400 min-w-[60px]", children: [_jsx(Span, { className: "text-base", children: icon }), _jsx(Span, { className: "whitespace-pre-line leading-tight", children: label })] }, label))) }) })] })), renderSublistingSection: sublistingCategoryId
|
|
216
|
+
? () => (_jsx(SublistingCarouselSection, { sublistingCategoryId: sublistingCategoryId, currentListingId: String(product.id) }))
|
|
217
|
+
: undefined, renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-zinc-700 dark:text-zinc-300" })) : undefined, specsContent: specs.length > 0 ? (_jsx("dl", { className: "divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800 overflow-hidden text-sm", children: specs.map((s, i) => (_jsxs("div", { className: "flex gap-4 px-4 py-3 bg-white dark:bg-zinc-900 even:bg-zinc-50 dark:even:bg-zinc-800/50", children: [_jsx("dt", { className: "w-36 flex-shrink-0 font-medium text-zinc-700 dark:text-zinc-300", children: s.name }), _jsxs("dd", { className: "flex-1 text-zinc-600 dark:text-zinc-400", children: [s.value, s.unit ? ` ${s.unit}` : ""] })] }, i))) })) : undefined, ingredientsContent: ingredients.length > 0 ? (_jsx("ul", { className: "space-y-2", children: ingredients.map((item, i) => (_jsxs("li", { className: "flex items-start gap-2 text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx(Span, { className: "mt-1 flex-shrink-0 h-1.5 w-1.5 rounded-full bg-primary-400" }), item] }, i))) })) : undefined, howToUseContent: howToUse.length > 0 ? (_jsx("ol", { className: "space-y-3", children: howToUse.map((step, i) => (_jsxs("li", { className: "flex items-start gap-3 text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx(Span, { className: "flex-shrink-0 flex h-6 w-6 items-center justify-center rounded-full bg-primary-100 dark:bg-primary-900/30 text-xs font-bold text-primary-700 dark:text-primary-300", children: i + 1 }), step] }, i))) })) : undefined, reviewsContent: _jsx(ReviewsList, { reviews: reviews, emptyLabel: "No reviews yet \u2014 be the first to review this product." }), customTabs: customSections.map((s) => ({
|
|
214
218
|
id: s.id,
|
|
215
219
|
label: s.title,
|
|
216
220
|
content: _jsx(CustomSectionTabContent, { section: s }),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { DetailViewShellProps } from "../../../ui";
|
|
3
|
-
export interface ProductDetailViewProps extends Omit<DetailViewShellProps, "mainSlots" | "belowFold" | "layout"> {
|
|
3
|
+
export interface ProductDetailViewProps extends Omit<DetailViewShellProps, "mainSlots" | "belowFold" | "layout" | "afterMain"> {
|
|
4
4
|
renderGallery?: (isLoading: boolean) => React.ReactNode;
|
|
5
5
|
renderInfo?: (isLoading: boolean) => React.ReactNode;
|
|
6
6
|
/**
|
|
@@ -8,6 +8,8 @@ export interface ProductDetailViewProps extends Omit<DetailViewShellProps, "main
|
|
|
8
8
|
* `useBottomActions` in the consumer to also register mobile bottom actions.
|
|
9
9
|
*/
|
|
10
10
|
renderActions?: () => React.ReactNode;
|
|
11
|
+
/** Rendered between the main grid and the below-fold tabs (e.g. sub-listing carousel). */
|
|
12
|
+
renderSublistingSection?: () => React.ReactNode;
|
|
11
13
|
renderTabs?: () => React.ReactNode;
|
|
12
14
|
renderRelated?: () => React.ReactNode;
|
|
13
15
|
/**
|
|
@@ -21,4 +23,4 @@ export interface ProductDetailViewProps extends Omit<DetailViewShellProps, "main
|
|
|
21
23
|
*/
|
|
22
24
|
stickyRailOffset?: string;
|
|
23
25
|
}
|
|
24
|
-
export declare function ProductDetailView({ renderGallery, renderInfo, renderActions, renderTabs, renderRelated, isLoading, stickyActionRail, stickyRailOffset, ...rest }: ProductDetailViewProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export declare function ProductDetailView({ renderGallery, renderInfo, renderActions, renderSublistingSection, renderTabs, renderRelated, isLoading, stickyActionRail, stickyRailOffset, ...rest }: ProductDetailViewProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { DetailViewShell } from "../../../ui";
|
|
3
|
-
export function ProductDetailView({ renderGallery, renderInfo, renderActions, renderTabs, renderRelated, isLoading = false, stickyActionRail = true, stickyRailOffset = "top-20", ...rest }) {
|
|
3
|
+
export function ProductDetailView({ renderGallery, renderInfo, renderActions, renderSublistingSection, renderTabs, renderRelated, isLoading = false, stickyActionRail = true, stickyRailOffset = "top-20", ...rest }) {
|
|
4
4
|
return (_jsx(DetailViewShell, { portal: "public", ...rest, layout: "grid-3", isLoading: isLoading, stickyActionRail: stickyActionRail, stickyRailOffset: stickyRailOffset, mainSlots: [
|
|
5
5
|
renderGallery?.(isLoading),
|
|
6
6
|
renderInfo?.(isLoading),
|
|
7
7
|
renderActions?.(),
|
|
8
|
-
], belowFold: [renderTabs?.(), renderRelated?.()] }));
|
|
8
|
+
], afterMain: renderSublistingSection?.(), belowFold: [renderTabs?.(), renderRelated?.()] }));
|
|
9
9
|
}
|
|
@@ -44,3 +44,5 @@ export { CustomSectionsEditor } from "./CustomSectionsEditor";
|
|
|
44
44
|
export type { CustomSectionsEditorProps } from "./CustomSectionsEditor";
|
|
45
45
|
export { CustomSectionTabContent } from "./CustomSectionTabContent";
|
|
46
46
|
export { RelatedProductsCarousel } from "./RelatedProductsCarousel";
|
|
47
|
+
export { SublistingCategorySelect } from "./SublistingCategorySelect";
|
|
48
|
+
export { SublistingCarouselSection } from "./SublistingCarouselSection";
|
|
@@ -23,3 +23,5 @@ export { CustomFieldsEditor } from "./CustomFieldsEditor";
|
|
|
23
23
|
export { CustomSectionsEditor } from "./CustomSectionsEditor";
|
|
24
24
|
export { CustomSectionTabContent } from "./CustomSectionTabContent";
|
|
25
25
|
export { RelatedProductsCarousel } from "./RelatedProductsCarousel";
|
|
26
|
+
export { SublistingCategorySelect } from "./SublistingCategorySelect";
|
|
27
|
+
export { SublistingCarouselSection } from "./SublistingCarouselSection";
|
|
@@ -134,6 +134,9 @@ export declare const DEFAULT_ROUTE_MAP: {
|
|
|
134
134
|
readonly WHATSAPP: "/store/whatsapp";
|
|
135
135
|
readonly REVIEWS: "/store/reviews";
|
|
136
136
|
readonly BIDS: "/store/bids";
|
|
137
|
+
readonly SUBLISTING_CATEGORIES: "/store/sublisting-categories";
|
|
138
|
+
readonly SUBLISTING_CATEGORIES_NEW: "/store/sublisting-categories/new";
|
|
139
|
+
readonly SUBLISTING_CATEGORIES_EDIT: (id: string) => string;
|
|
137
140
|
};
|
|
138
141
|
readonly ADMIN: {
|
|
139
142
|
readonly DASHBOARD: "/admin/dashboard";
|
|
@@ -326,6 +329,9 @@ export declare const ROUTES: {
|
|
|
326
329
|
readonly WHATSAPP: "/store/whatsapp";
|
|
327
330
|
readonly REVIEWS: "/store/reviews";
|
|
328
331
|
readonly BIDS: "/store/bids";
|
|
332
|
+
readonly SUBLISTING_CATEGORIES: "/store/sublisting-categories";
|
|
333
|
+
readonly SUBLISTING_CATEGORIES_NEW: "/store/sublisting-categories/new";
|
|
334
|
+
readonly SUBLISTING_CATEGORIES_EDIT: (id: string) => string;
|
|
329
335
|
};
|
|
330
336
|
readonly ADMIN: {
|
|
331
337
|
readonly DASHBOARD: "/admin/dashboard";
|
|
@@ -424,6 +430,9 @@ export declare const SELLER_ROUTES: {
|
|
|
424
430
|
readonly WHATSAPP: "/store/whatsapp";
|
|
425
431
|
readonly REVIEWS: "/store/reviews";
|
|
426
432
|
readonly BIDS: "/store/bids";
|
|
433
|
+
readonly SUBLISTING_CATEGORIES: "/store/sublisting-categories";
|
|
434
|
+
readonly SUBLISTING_CATEGORIES_NEW: "/store/sublisting-categories/new";
|
|
435
|
+
readonly SUBLISTING_CATEGORIES_EDIT: (id: string) => string;
|
|
427
436
|
};
|
|
428
437
|
export declare const PUBLIC_ROUTES: readonly ["/", string, string, string, string, string, string, string, string, string, string, string, string, string, string, string, "/unauthorized", "/auth/login", "/auth/register", "/auth/forgot-password", "/auth/reset-password", "/auth/verify-email"];
|
|
429
438
|
export declare const PROTECTED_ROUTES: readonly [string, string, string, string, string, string, string];
|
|
@@ -121,6 +121,9 @@ export const DEFAULT_ROUTE_MAP = {
|
|
|
121
121
|
WHATSAPP: "/store/whatsapp",
|
|
122
122
|
REVIEWS: "/store/reviews",
|
|
123
123
|
BIDS: "/store/bids",
|
|
124
|
+
SUBLISTING_CATEGORIES: "/store/sublisting-categories",
|
|
125
|
+
SUBLISTING_CATEGORIES_NEW: "/store/sublisting-categories/new",
|
|
126
|
+
SUBLISTING_CATEGORIES_EDIT: (id) => `/store/sublisting-categories/${id}/edit`,
|
|
124
127
|
},
|
|
125
128
|
ADMIN: {
|
|
126
129
|
DASHBOARD: "/admin/dashboard",
|