@mohasinac/appkit 2.7.56 → 2.7.57
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/shared/actions/action-registry.js +31 -5
- package/dist/client.d.ts +1 -3
- package/dist/client.js +1 -2
- package/dist/constants/field-names.d.ts +3 -0
- package/dist/constants/field-names.js +3 -0
- package/dist/features/about/components/FAQPageView.js +2 -2
- package/dist/features/about/components/FeesView.js +1 -1
- package/dist/features/about/components/PolicyPageView.js +1 -1
- package/dist/features/about/components/PublicProfileView.js +1 -1
- package/dist/features/account/components/AddressesIndexListing.js +1 -1
- package/dist/features/account/components/MessagesView.js +1 -1
- package/dist/features/account/components/NotificationPreferencesPanel.js +12 -3
- package/dist/features/account/components/UserOffersPanel.js +2 -2
- package/dist/features/account/components/UserSidebar.js +3 -3
- package/dist/features/account/components/UserSupportView.js +1 -1
- package/dist/features/admin/components/AdminAllEventEntriesView.js +1 -1
- package/dist/features/admin/components/AdminBidsView.js +5 -1
- package/dist/features/admin/components/AdminBlogView.js +6 -1
- package/dist/features/admin/components/AdminBrandsView.js +6 -1
- package/dist/features/admin/components/AdminBundleEditorView.js +13 -9
- package/dist/features/admin/components/AdminBundlesView.js +3 -1
- package/dist/features/admin/components/AdminCarouselEditorView.js +7 -8
- package/dist/features/admin/components/AdminCarouselView.js +4 -2
- package/dist/features/admin/components/AdminCartsView.js +1 -1
- package/dist/features/admin/components/AdminCategoriesView.js +6 -1
- package/dist/features/admin/components/AdminContactView.js +3 -1
- package/dist/features/admin/components/AdminCouponsView.js +4 -2
- package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -1
- package/dist/features/admin/components/AdminFaqsView.js +3 -1
- package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -1
- package/dist/features/admin/components/AdminFeaturesView.js +4 -0
- package/dist/features/admin/components/AdminMediaView.js +10 -5
- package/dist/features/admin/components/AdminNavigationView.js +1 -1
- package/dist/features/admin/components/AdminNewsletterView.js +3 -1
- package/dist/features/admin/components/AdminNotificationsView.js +6 -1
- package/dist/features/admin/components/AdminOrdersView.js +10 -1
- package/dist/features/admin/components/AdminPayoutsView.js +5 -1
- package/dist/features/admin/components/AdminPrizeDrawsView.js +4 -0
- package/dist/features/admin/components/AdminProductsView.js +13 -1
- package/dist/features/admin/components/AdminReviewsView.js +6 -1
- package/dist/features/admin/components/AdminScammersView.js +1 -1
- package/dist/features/admin/components/AdminSectionsView.js +1 -1
- package/dist/features/admin/components/AdminSessionsView.js +5 -1
- package/dist/features/admin/components/AdminSidebar.js +3 -3
- package/dist/features/admin/components/AdminSiteSettingsView.js +1 -1
- package/dist/features/admin/components/AdminStoreEditorView.js +1 -1
- package/dist/features/admin/components/AdminStoresView.js +6 -1
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +2 -0
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
- package/dist/features/admin/components/AdminSupportTicketsView.js +1 -1
- package/dist/features/admin/components/AdminTeamView.js +3 -1
- package/dist/features/admin/components/AdminUserEditorView.js +1 -1
- package/dist/features/admin/components/AdminUsersView.js +5 -1
- package/dist/features/admin/components/AdminViewCards.js +2 -2
- package/dist/features/admin/constants/filter-tabs.d.ts +9 -0
- package/dist/features/admin/constants/filter-tabs.js +3 -0
- package/dist/features/auctions/components/AuctionBottomActions.d.ts +7 -0
- package/dist/features/auctions/components/AuctionBottomActions.js +24 -0
- package/dist/features/auctions/components/AuctionDetailPageView.js +7 -7
- package/dist/features/auctions/components/AuctionsListView.js +1 -1
- package/dist/features/auctions/components/MarketplaceAuctionGrid.js +1 -1
- package/dist/features/auctions/components/PlaceBidFormClient.js +1 -1
- package/dist/features/auth/components/LoginForm.js +1 -1
- package/dist/features/auth/components/VerifyEmailView.js +2 -2
- package/dist/features/before-after/components/BeforeAfterGallery.js +1 -1
- package/dist/features/blog/components/BlogFeaturedCard.js +1 -1
- package/dist/features/blog/components/BlogIndexListing.js +1 -1
- package/dist/features/blog/components/BlogListView.js +2 -2
- package/dist/features/blog/components/BlogPostView.js +8 -8
- package/dist/features/cart/components/CartDrawer.js +1 -1
- package/dist/features/cart/repository/cart.repository.js +11 -4
- package/dist/features/cart/schemas/firestore.d.ts +3 -0
- package/dist/features/categories/components/BrandDetailPageView.js +1 -1
- package/dist/features/categories/components/CategoriesIndexListing.js +1 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +39 -3
- package/dist/features/categories/components/CategoryDetailTabs.d.ts +4 -1
- package/dist/features/categories/components/CategoryDetailTabs.js +7 -2
- package/dist/features/categories/components/CategoryGrid.js +1 -1
- package/dist/features/categories/components/CategoryProductsView.js +1 -1
- package/dist/features/categories/components/CategoryStoresListing.d.ts +5 -0
- package/dist/features/categories/components/CategoryStoresListing.js +11 -0
- package/dist/features/categories/components/CategoryTableColumns.js +2 -2
- package/dist/features/categories/components/CategoryTree.js +1 -1
- package/dist/features/categories/components/index.d.ts +2 -0
- package/dist/features/categories/components/index.js +1 -0
- package/dist/features/checkout/components/CheckoutStepper.js +1 -1
- package/dist/features/classified/components/ClassifiedIndexListing.js +2 -0
- package/dist/features/classified/components/ClassifiedListView.js +1 -1
- package/dist/features/contact/components/ContactInfoSidebar.js +1 -1
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +2 -0
- package/dist/features/digital-codes/components/DigitalCodesListView.js +1 -1
- package/dist/features/events/components/AdminEventsView.js +5 -1
- package/dist/features/events/components/EventCard.js +1 -1
- package/dist/features/events/components/EventPollWidget.js +1 -1
- package/dist/features/events/components/EventStatusBadge.js +5 -5
- package/dist/features/events/components/EventsIndexListing.js +1 -1
- package/dist/features/events/components/EventsListView.js +2 -2
- package/dist/features/events/components/SpinWheelView.js +4 -2
- package/dist/features/filters/AsyncFacetSection.js +3 -3
- package/dist/features/filters/FilterFacetSection.js +5 -5
- package/dist/features/filters/RangeFilter.js +1 -1
- package/dist/features/forms/Input.js +2 -2
- package/dist/features/forms/Select.js +1 -1
- package/dist/features/forms/Slider.js +1 -1
- package/dist/features/forms/Textarea.js +1 -1
- package/dist/features/forms/utils.d.ts +1 -1
- package/dist/features/forms/utils.js +1 -1
- package/dist/features/history/hooks/useHistory.js +23 -10
- package/dist/features/homepage/components/AdvertisementBanner.js +2 -2
- package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
- package/dist/features/homepage/components/HeroSection.js +1 -1
- package/dist/features/homepage/components/NewsletterSection.js +1 -1
- package/dist/features/homepage/components/SectionCarousel.js +1 -1
- package/dist/features/live/components/LiveItemsIndexListing.js +2 -0
- package/dist/features/live/components/LiveItemsListView.js +1 -1
- package/dist/features/orders/components/OrdersList.js +12 -12
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +1 -1
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
- package/dist/features/pre-orders/components/PreOrderBadge.js +5 -5
- package/dist/features/pre-orders/components/PreOrderBottomActions.d.ts +5 -0
- package/dist/features/pre-orders/components/PreOrderBottomActions.js +22 -0
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +5 -5
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +47 -0
- package/dist/features/pre-orders/components/PreOrdersListView.js +1 -1
- package/dist/features/pre-orders/components/PreorderCard.js +3 -3
- package/dist/features/products/components/AuctionsIndexListing.js +23 -0
- package/dist/features/products/components/BidHistory.js +2 -2
- package/dist/features/products/components/CompareOverlay.js +1 -1
- package/dist/features/products/components/CustomFieldsEditor.js +1 -1
- package/dist/features/products/components/CustomSectionTabContent.js +1 -1
- package/dist/features/products/components/CustomSectionsEditor.js +1 -1
- package/dist/features/products/components/GroupSettingsPanel.js +2 -2
- package/dist/features/products/components/MakeOfferButton.js +1 -1
- package/dist/features/products/components/PrizeDrawBottomActions.d.ts +6 -0
- package/dist/features/products/components/PrizeDrawBottomActions.js +24 -0
- package/dist/features/products/components/PrizeDrawDetailPageView.js +3 -5
- package/dist/features/products/components/PrizeDrawEntryActions.js +5 -18
- package/dist/features/products/components/PrizeRevealModal.js +5 -2
- package/dist/features/products/components/ProductDetailActions.d.ts +6 -1
- package/dist/features/products/components/ProductDetailActions.js +36 -6
- package/dist/features/products/components/ProductDetailPageView.js +17 -16
- package/dist/features/products/components/ProductGalleryClient.js +1 -1
- package/dist/features/products/components/ProductGrid.js +6 -6
- package/dist/features/products/components/ProductTabs.js +1 -1
- package/dist/features/products/components/ProductTabsShell.js +1 -1
- package/dist/features/products/components/ProductsIndexListing.js +47 -0
- package/dist/features/products/components/RelatedProducts.js +1 -1
- package/dist/features/products/components/ShowGroupSection.js +1 -1
- package/dist/features/products/components/SublistingCarouselSection.js +1 -1
- package/dist/features/products/components/SublistingCategorySelect.js +1 -1
- package/dist/features/products/components/index.d.ts +0 -2
- package/dist/features/products/components/index.js +0 -1
- package/dist/features/products/constants/action-defs.d.ts +7 -0
- package/dist/features/products/constants/action-defs.js +14 -0
- package/dist/features/products/constants/listing-tabs.d.ts +6 -0
- package/dist/features/products/constants/listing-tabs.js +1 -0
- package/dist/features/promotions/components/CouponCard.js +2 -2
- package/dist/features/promotions/components/CouponsIndexListing.js +2 -2
- package/dist/features/reviews/components/ReviewDetailPageView.js +1 -1
- package/dist/features/reviews/components/ReviewDetailShell.js +3 -3
- package/dist/features/reviews/components/ReviewModal.js +2 -2
- package/dist/features/reviews/components/ReviewSummary.js +1 -1
- package/dist/features/reviews/components/ReviewsIndexListing.js +1 -1
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/seller/components/SellerAddressesView.js +4 -3
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +1 -1
- package/dist/features/seller/components/SellerAuctionsView.js +10 -3
- package/dist/features/seller/components/SellerBidsView.js +22 -7
- package/dist/features/seller/components/SellerBundlesView.js +10 -3
- package/dist/features/seller/components/SellerClassifiedView.js +10 -3
- package/dist/features/seller/components/SellerCouponsView.js +13 -4
- package/dist/features/seller/components/SellerDigitalCodesView.js +10 -3
- package/dist/features/seller/components/SellerGoogleReviewsView.js +10 -5
- package/dist/features/seller/components/SellerGroupedListingsView.js +2 -0
- package/dist/features/seller/components/SellerLiveView.js +10 -3
- package/dist/features/seller/components/SellerOffersPanel.js +2 -2
- package/dist/features/seller/components/SellerOffersView.js +1 -1
- package/dist/features/seller/components/SellerOrdersView.js +40 -17
- package/dist/features/seller/components/SellerPayoutMethodsView.js +13 -4
- package/dist/features/seller/components/SellerPayoutsView.js +1 -1
- package/dist/features/seller/components/SellerPreOrdersView.js +7 -2
- package/dist/features/seller/components/SellerPrizeDrawsView.js +7 -2
- package/dist/features/seller/components/SellerProductShell.js +27 -9
- package/dist/features/seller/components/SellerProductsCards.js +2 -1
- package/dist/features/seller/components/SellerProductsView.js +21 -8
- package/dist/features/seller/components/SellerReviewsView.js +8 -0
- package/dist/features/seller/components/SellerShippingConfigsView.js +13 -4
- package/dist/features/seller/components/SellerSidebar.js +2 -2
- package/dist/features/seller/components/SellerStoreCategoriesView.js +10 -3
- package/dist/features/seller/components/SellerTemplatesView.js +19 -6
- package/dist/features/shell/StepForm.js +9 -3
- package/dist/features/site-settings/components/ActionPermissionsManager.js +1 -1
- package/dist/features/site-settings/components/NavPermissionsManager.js +1 -1
- package/dist/features/stores/components/InteractiveStoreCard.js +1 -1
- package/dist/features/stores/components/StoreDetailLayoutView.js +1 -1
- package/dist/features/stores/components/StoreReviewsListing.js +1 -1
- package/dist/features/stores/components/StoresIndexListing.js +17 -1
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +1 -1
- package/dist/features/wishlist/components/WishlistPage.js +2 -2
- package/dist/features/wishlist/hooks/useWishlistToggle.js +6 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +6 -3
- package/dist/react/hooks/use-action-dispatch.d.ts +5 -0
- package/dist/react/hooks/use-action-dispatch.js +10 -0
- package/dist/seed/cart-seed-data.js +50 -3
- package/dist/seed/categories-seed-data.js +80 -16
- package/dist/seed/index.d.ts +3 -0
- package/dist/seed/index.js +3 -0
- package/dist/seed/manifest.js +15 -1
- package/dist/seed/products-classifieds-seed-data.d.ts +10 -0
- package/dist/seed/products-classifieds-seed-data.js +197 -0
- package/dist/seed/products-digital-codes-seed-data.d.ts +10 -0
- package/dist/seed/products-digital-codes-seed-data.js +204 -0
- package/dist/seed/products-live-items-seed-data.d.ts +13 -0
- package/dist/seed/products-live-items-seed-data.js +190 -0
- package/dist/styles.css +16 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/index.d.ts +3 -3
- package/dist/tokens/index.js +3 -3
- package/dist/ui/DataTable.js +3 -3
- package/dist/ui/components/Button.style.css +15 -0
- package/dist/ui/components/Input.js +1 -1
- package/dist/ui/components/ListingToolbar.js +1 -1
- package/dist/ui/components/Select.js +1 -1
- package/dist/ui/components/StatsGrid.js +1 -1
- package/dist/ui/index.d.ts +0 -4
- package/dist/ui/index.js +0 -2
- package/package.json +1 -1
- package/dist/_internal/client/features/seller/print-center/InventoryLabel.d.ts +0 -12
- package/dist/_internal/client/features/seller/print-center/InventoryLabel.js +0 -49
- package/dist/_internal/client/features/seller/print-center/LabelDesignPicker.d.ts +0 -7
- package/dist/_internal/client/features/seller/print-center/LabelDesignPicker.js +0 -32
- package/dist/_internal/client/features/seller/print-center/OrderPackingLabel.d.ts +0 -28
- package/dist/_internal/client/features/seller/print-center/OrderPackingLabel.js +0 -33
- package/dist/_internal/client/features/seller/print-center/PhysicalLocationModal.d.ts +0 -12
- package/dist/_internal/client/features/seller/print-center/PhysicalLocationModal.js +0 -30
- package/dist/_internal/client/features/seller/print-center/PrintCenterView.d.ts +0 -12
- package/dist/_internal/client/features/seller/print-center/PrintCenterView.js +0 -102
- package/dist/_internal/client/features/seller/print-center/PrintGrid.d.ts +0 -12
- package/dist/_internal/client/features/seller/print-center/PrintGrid.js +0 -13
- package/dist/_internal/client/features/seller/print-center/StoreCard.d.ts +0 -19
- package/dist/_internal/client/features/seller/print-center/StoreCard.js +0 -30
- package/dist/_internal/client/features/seller/print-center/WebsiteCard.d.ts +0 -11
- package/dist/_internal/client/features/seller/print-center/WebsiteCard.js +0 -25
- package/dist/_internal/client/features/seller/print-center/index.d.ts +0 -11
- package/dist/_internal/client/features/seller/print-center/index.js +0 -10
- package/dist/_internal/client/features/seller/print-center/types.d.ts +0 -20
- package/dist/_internal/client/features/seller/print-center/types.js +0 -20
- package/dist/_internal/client/features/seller/print-center/useInventoryPdf.d.ts +0 -18
- package/dist/_internal/client/features/seller/print-center/useInventoryPdf.js +0 -76
- package/dist/features/account/repository/address.repository.d.ts +0 -17
- package/dist/features/account/repository/address.repository.js +0 -184
- package/dist/features/auctions/components/AuctionCard.d.ts +0 -29
- package/dist/features/auctions/components/AuctionCard.js +0 -38
- package/dist/features/categories/components/BundleAddToCartCta.d.ts +0 -16
- package/dist/features/categories/components/BundleAddToCartCta.js +0 -54
- package/dist/features/categories/components/CategoriesListView.d.ts +0 -31
- package/dist/features/categories/components/CategoriesListView.js +0 -27
- package/dist/features/products/components/AuctionsView.d.ts +0 -6
- package/dist/features/products/components/AuctionsView.js +0 -5
- package/dist/features/products/components/BuyBar.d.ts +0 -21
- package/dist/features/products/components/BuyBar.js +0 -19
- package/dist/features/products/components/PreOrdersView.d.ts +0 -6
- package/dist/features/products/components/PreOrdersView.js +0 -5
- package/dist/features/reviews/components/ReviewsListView.d.ts +0 -31
- package/dist/features/reviews/components/ReviewsListView.js +0 -16
- package/dist/features/stores/components/StoresListView.d.ts +0 -19
- package/dist/features/stores/components/StoresListView.js +0 -25
- package/dist/features/stores/repository/store-address.repository.d.ts +0 -55
- package/dist/features/stores/repository/store-address.repository.js +0 -187
- package/dist/ui/components/BulkActionsBar.d.ts +0 -18
- package/dist/ui/components/BulkActionsBar.js +0 -25
- package/dist/ui/components/CollageLightbox.d.ts +0 -18
- package/dist/ui/components/CollageLightbox.js +0 -41
- package/dist/ui/components/StickyBottomBar.d.ts +0 -22
- package/dist/ui/components/StickyBottomBar.js +0 -20
|
@@ -4,13 +4,13 @@ import { Div, Pagination, Text } from "../../../ui";
|
|
|
4
4
|
import { EventCard } from "./EventCard";
|
|
5
5
|
export function EventsListView({ events, isLoading, totalPages = 1, currentPage = 1, total = 0, onPageChange, onParticipate, emptyLabel = "No events found", slots, }) {
|
|
6
6
|
if (isLoading) {
|
|
7
|
-
return (_jsx(Div, { className: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Div, { className: "animate-pulse overflow-hidden rounded-xl border border-
|
|
7
|
+
return (_jsx(Div, { className: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Div, { className: "animate-pulse overflow-hidden rounded-xl border border-zinc-200 dark:border-zinc-700 bg-zinc-100 dark:bg-zinc-800", children: [_jsx(Div, { className: "aspect-video bg-zinc-200 dark:bg-zinc-700" }), _jsxs(Div, { className: "space-y-2 p-4", children: [_jsx(Div, { className: "h-4 w-16 rounded bg-zinc-200 dark:bg-zinc-700" }), _jsx(Div, { className: "h-5 w-full rounded bg-zinc-200 dark:bg-zinc-700" }), _jsx(Div, { className: "h-4 w-3/4 rounded bg-zinc-200 dark:bg-zinc-700" })] })] }, i))) }));
|
|
8
8
|
}
|
|
9
9
|
if (events.length === 0) {
|
|
10
10
|
if (slots?.renderEmptyState) {
|
|
11
11
|
return _jsx(_Fragment, { children: slots.renderEmptyState() });
|
|
12
12
|
}
|
|
13
|
-
return (_jsx(Text, { className: "py-12 text-center text-sm text-
|
|
13
|
+
return (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: emptyLabel }));
|
|
14
14
|
}
|
|
15
15
|
return (_jsxs(Div, { className: "space-y-8", children: [slots?.renderHeader
|
|
16
16
|
? slots.renderHeader({ total })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useMemo, useState } from "react";
|
|
4
|
-
import { Button, ClaimCouponButton, Div, Heading, LoginRequiredModal, Span, Text } from "../../../ui";
|
|
4
|
+
import { Button, ClaimCouponButton, Div, Heading, LoginRequiredModal, Span, Text, useToast } from "../../../ui";
|
|
5
5
|
import { isAuthError } from "../../../utils/auth-error";
|
|
6
6
|
const DEFAULT_LABELS = {
|
|
7
7
|
heading: "Spin the Wheel",
|
|
@@ -22,6 +22,7 @@ export function SpinWheelView({ eventId, prizes, alreadyUsed, initialPrizeId, in
|
|
|
22
22
|
const [resultCoupon, setResultCoupon] = useState(initialCouponCode);
|
|
23
23
|
const [error, setError] = useState(null);
|
|
24
24
|
const [showLoginModal, setShowLoginModal] = useState(false);
|
|
25
|
+
const { showToast } = useToast();
|
|
25
26
|
const now = Date.now();
|
|
26
27
|
const startMs = windowStart ? new Date(windowStart).getTime() : null;
|
|
27
28
|
const endMs = windowEnd ? new Date(windowEnd).getTime() : null;
|
|
@@ -52,9 +53,10 @@ export function SpinWheelView({ eventId, prizes, alreadyUsed, initialPrizeId, in
|
|
|
52
53
|
}
|
|
53
54
|
else {
|
|
54
55
|
setError(l.errorFallback);
|
|
56
|
+
showToast(err instanceof Error ? err.message : l.errorFallback, "error");
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
|
-
}, [disabled, eventId, l.errorFallback, onSpin]);
|
|
59
|
+
}, [disabled, eventId, l.errorFallback, onSpin, showToast]);
|
|
58
60
|
const wonPrize = resultPrizeId
|
|
59
61
|
? activePrizes.find((p) => p.id === resultPrizeId)
|
|
60
62
|
: undefined;
|
|
@@ -58,8 +58,8 @@ export function AsyncFacetSection({ title, selected, onChange, loadOptions, sele
|
|
|
58
58
|
const selectedLabels = selected
|
|
59
59
|
.map((v) => labelMap.current.get(v) ?? v)
|
|
60
60
|
.slice(0, 3);
|
|
61
|
-
return (_jsxs(Div, { className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Row, { gap: "xs", children: [_jsxs(Button, { type: "button", onClick: () => setCollapsed((c) => !c), variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !collapsed, children: [_jsxs(Row, { as: Span, gap: "xs", children: [title, hasValue && (_jsx(Span, { className: "inline-flex items-center justify-center w-5 h-5 text-xs rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20 dark:ring-emerald-400/20", children: selected.length }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", collapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: "inline-flex items-center justify-center w-5 h-5 p-0 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 hover:bg-zinc-100 dark:hover:bg-slate-700 transition-colors rounded-full", "aria-label": "Clear filter", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), collapsed && hasValue && (_jsxs(Div, { className: "mt-2 flex flex-wrap gap-1", children: [selectedLabels.map((label) => (_jsx(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs bg-zinc-100 dark:bg-slate-700 text-zinc-700 dark:text-zinc-300 border border-zinc-200 dark:border-slate-600", children: label }, label))), selected.length > 3 && (_jsxs(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs text-zinc-400 dark:text-zinc-
|
|
61
|
+
return (_jsxs(Div, { className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Row, { gap: "xs", children: [_jsxs(Button, { type: "button", onClick: () => setCollapsed((c) => !c), variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !collapsed, children: [_jsxs(Row, { as: Span, gap: "xs", children: [title, hasValue && (_jsx(Span, { className: "inline-flex items-center justify-center w-5 h-5 text-xs rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20 dark:ring-emerald-400/20", children: selected.length }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", collapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: "inline-flex items-center justify-center w-5 h-5 p-0 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 hover:bg-zinc-100 dark:hover:bg-slate-700 transition-colors rounded-full", "aria-label": "Clear filter", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), collapsed && hasValue && (_jsxs(Div, { className: "mt-2 flex flex-wrap gap-1", children: [selectedLabels.map((label) => (_jsx(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs bg-zinc-100 dark:bg-slate-700 text-zinc-700 dark:text-zinc-300 border border-zinc-200 dark:border-slate-600", children: label }, label))), selected.length > 3 && (_jsxs(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs text-zinc-400 dark:text-zinc-400", children: ["+", selected.length - 3, " more"] }))] })), _jsx(Div, { className: "mt-2", children: _jsx(Input, { type: "search", placeholder: "Search\u2026", value: query, onChange: (e) => handleQueryChange(e.target.value), className: "w-full rounded-md border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-2.5 py-1.5 text-xs text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20" }) }), !collapsed && (_jsxs(Div, { className: "mt-3 space-y-1", children: [options.map((opt) => {
|
|
62
62
|
const isSelected = selected.includes(opt.value);
|
|
63
|
-
return (_jsxs(Row, { gap: "2.5", className: "py-1 cursor-pointer group", children: [_jsx("input", { type: selectionMode === "single" ? "radio" : "checkbox", checked: isSelected, onChange: () => toggle(opt.value), "aria-label": opt.label, className: "flex-shrink-0 w-4 h-4 rounded border-zinc-300 dark:border-slate-600 cursor-pointer text-primary-600 dark:text-secondary-500" }), _jsx(Span, { className: "flex-1 text-sm text-zinc-700 dark:text-zinc-300 group-hover:text-zinc-900 dark:group-hover:text-zinc-100 transition-colors truncate", children: opt.label }), opt.count !== undefined && (_jsx(Span, { className: "text-xs text-zinc-400 dark:text-zinc-
|
|
64
|
-
}), options.length === 0 && !loading && (_jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-
|
|
63
|
+
return (_jsxs(Row, { gap: "2.5", className: "py-1 cursor-pointer group", children: [_jsx("input", { type: selectionMode === "single" ? "radio" : "checkbox", checked: isSelected, onChange: () => toggle(opt.value), "aria-label": opt.label, className: "flex-shrink-0 w-4 h-4 rounded border-zinc-300 dark:border-slate-600 cursor-pointer text-primary-600 dark:text-secondary-500" }), _jsx(Span, { className: "flex-1 text-sm text-zinc-700 dark:text-zinc-300 group-hover:text-zinc-900 dark:group-hover:text-zinc-100 transition-colors truncate", children: opt.label }), opt.count !== undefined && (_jsx(Span, { className: "text-xs text-zinc-400 dark:text-zinc-400 tabular-nums flex-shrink-0", children: opt.count }))] }, opt.value));
|
|
64
|
+
}), options.length === 0 && !loading && (_jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 py-1", children: "No results" })), loading && (_jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 py-1 animate-pulse", children: "Loading\u2026" })), hasMore && !loading && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "w-full text-xs text-left text-zinc-400 dark:text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300 py-1", onClick: () => void load(query, page + 1), children: "Load more\u2026" }))] }))] }));
|
|
65
65
|
}
|
|
@@ -63,12 +63,12 @@ export function FilterFacetSection({ title, options, selected, onChange, selecti
|
|
|
63
63
|
? "border-emerald-500 bg-emerald-50 text-emerald-700 dark:border-emerald-500/60 dark:bg-emerald-900/20 dark:text-emerald-300"
|
|
64
64
|
: "border-zinc-200 bg-white text-zinc-700 hover:border-zinc-400 dark:border-slate-700 dark:bg-slate-900 dark:text-zinc-200 dark:hover:border-slate-500"), children: [title, hasValue && (_jsx(Span, { className: "inline-flex h-4 w-4 items-center justify-center rounded-full bg-emerald-600 text-[10px] font-bold text-white", children: selected.length })), _jsx("svg", { className: cn("h-3.5 w-3.5 text-zinc-400 transition-transform", dropdownOpen ? "rotate-180" : ""), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), dropdownOpen && (_jsxs(Div, { className: "absolute left-0 top-full z-[var(--appkit-z-dropdown,50)] mt-1 min-w-[180px] max-w-[260px] rounded-xl border border-zinc-200 bg-white shadow-lg dark:border-slate-700 dark:bg-slate-900", children: [searchable && (_jsx(Div, { className: "border-b border-zinc-100 p-2 dark:border-slate-800", children: _jsx(Input, { type: "search", placeholder: "Search\u2026", value: search, onChange: (e) => handleSearch(e.target.value), className: "w-full rounded-md border border-zinc-200 bg-white px-2 py-1 text-xs text-zinc-900 focus:outline-none dark:border-slate-700 dark:bg-slate-800/60 dark:text-zinc-100" }) })), _jsxs(Div, { className: "max-h-56 overflow-y-auto py-1", children: [filtered.map((option) => {
|
|
65
65
|
const isSelected = selected.includes(option.value);
|
|
66
|
-
return (_jsxs(Row, { gap: "xs", className: "cursor-pointer rounded-lg px-3 py-1.5 hover:bg-zinc-50 dark:hover:bg-slate-800 mx-1", onClick: () => toggle(option.value), children: [_jsx("input", { type: selectionMode === "single" ? "radio" : "checkbox", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: "h-3.5 w-3.5 flex-shrink-0 cursor-pointer rounded border-zinc-300 text-primary-600 dark:border-slate-600 dark:text-secondary-500" }), _jsx(Span, { className: "flex-1 truncate text-xs text-zinc-700 dark:text-zinc-300", children: option.label }), option.count !== undefined && (_jsx(Span, { className: "flex-shrink-0 text-[10px] tabular-nums text-zinc-400 dark:text-zinc-
|
|
67
|
-
}), filtered.length === 0 && (_jsx(Text, { className: "px-3 py-2 text-xs text-zinc-400 dark:text-zinc-
|
|
66
|
+
return (_jsxs(Row, { gap: "xs", className: "cursor-pointer rounded-lg px-3 py-1.5 hover:bg-zinc-50 dark:hover:bg-slate-800 mx-1", onClick: () => toggle(option.value), children: [_jsx("input", { type: selectionMode === "single" ? "radio" : "checkbox", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: "h-3.5 w-3.5 flex-shrink-0 cursor-pointer rounded border-zinc-300 text-primary-600 dark:border-slate-600 dark:text-secondary-500" }), _jsx(Span, { className: "flex-1 truncate text-xs text-zinc-700 dark:text-zinc-300", children: option.label }), option.count !== undefined && (_jsx(Span, { className: "flex-shrink-0 text-[10px] tabular-nums text-zinc-400 dark:text-zinc-400", children: option.count }))] }, option.value));
|
|
67
|
+
}), filtered.length === 0 && (_jsx(Text, { className: "px-3 py-2 text-xs text-zinc-400 dark:text-zinc-400", children: "No results" }))] }), hasValue && (_jsx(Div, { className: "border-t border-zinc-100 p-1 dark:border-slate-800", children: _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "w-full py-1 text-xs text-zinc-400 transition-colors hover:text-red-600", onClick: () => { onChange([]); onClear?.(); setDropdownOpen(false); }, children: "Clear" }) }))] }))] }));
|
|
68
68
|
}
|
|
69
69
|
// ── Accordion variant (default) ─────────────────────────────────────────
|
|
70
|
-
return (_jsxs(Div, { className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Row, { gap: "xs", children: [_jsxs(Button, { type: "button", onClick: handleToggle, variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsxs(Row, { as: Span, gap: "xs", children: [title, hasValue && (_jsx(Span, { className: "inline-flex items-center justify-center w-5 h-5 text-xs rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20 dark:ring-emerald-400/20", children: selected.length }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: "inline-flex items-center justify-center w-5 h-5 p-0 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 hover:bg-zinc-100 dark:hover:bg-slate-700 transition-colors rounded-full", "aria-label": "Clear filter", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), isCollapsed && hasValue && (_jsxs(Div, { className: "mt-2 flex flex-wrap gap-1", children: [selectedLabels.map((label) => (_jsx(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs bg-zinc-100 dark:bg-slate-700 text-zinc-700 dark:text-zinc-300 border border-zinc-200 dark:border-slate-600", children: label }, label))), selected.length > 3 && (_jsxs(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs text-zinc-400 dark:text-zinc-
|
|
70
|
+
return (_jsxs(Div, { className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Row, { gap: "xs", children: [_jsxs(Button, { type: "button", onClick: handleToggle, variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsxs(Row, { as: Span, gap: "xs", children: [title, hasValue && (_jsx(Span, { className: "inline-flex items-center justify-center w-5 h-5 text-xs rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20 dark:ring-emerald-400/20", children: selected.length }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: "inline-flex items-center justify-center w-5 h-5 p-0 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 hover:bg-zinc-100 dark:hover:bg-slate-700 transition-colors rounded-full", "aria-label": "Clear filter", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), isCollapsed && hasValue && (_jsxs(Div, { className: "mt-2 flex flex-wrap gap-1", children: [selectedLabels.map((label) => (_jsx(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs bg-zinc-100 dark:bg-slate-700 text-zinc-700 dark:text-zinc-300 border border-zinc-200 dark:border-slate-600", children: label }, label))), selected.length > 3 && (_jsxs(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs text-zinc-400 dark:text-zinc-400", children: ["+", selected.length - 3, " more"] }))] })), searchable && (_jsx(Div, { className: "mt-2", children: _jsx(Input, { type: "search", placeholder: "Search\u2026", value: search, onChange: (e) => handleSearch(e.target.value), className: "w-full rounded-md border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-2.5 py-1.5 text-xs text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20 dark:focus:ring-secondary-400/20" }) })), !isCollapsed && (_jsxs(Div, { className: "mt-3 space-y-1", children: [filtered.map((option) => {
|
|
71
71
|
const isSelected = selected.includes(option.value);
|
|
72
|
-
return (_jsxs(Row, { gap: "2.5", className: "py-1 cursor-pointer group", children: [selectionMode === "single" ? (_jsx("input", { type: "radio", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: cn("flex-shrink-0 border-zinc-300 dark:border-slate-600 cursor-pointer", "w-4 h-4 rounded-full text-primary-600 dark:text-secondary-500", "focus:ring-primary-500/30 dark:focus:ring-secondary-400/30") })) : (_jsx("input", { type: "checkbox", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: cn("flex-shrink-0 border-zinc-300 dark:border-slate-600 cursor-pointer", "w-4 h-4 rounded text-primary-600 dark:text-secondary-500 checked:bg-primary-600 dark:checked:bg-secondary-500", "focus:ring-primary-500/30 dark:focus:ring-secondary-400/30") })), _jsx(Span, { className: "flex-1 text-sm text-zinc-700 dark:text-zinc-300 group-hover:text-zinc-900 dark:group-hover:text-zinc-100 transition-colors truncate", children: option.label }), option.count !== undefined && (_jsx(Span, { className: "text-xs text-zinc-400 dark:text-zinc-
|
|
73
|
-
}), filtered.length === 0 && (_jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-
|
|
72
|
+
return (_jsxs(Row, { gap: "2.5", className: "py-1 cursor-pointer group", children: [selectionMode === "single" ? (_jsx("input", { type: "radio", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: cn("flex-shrink-0 border-zinc-300 dark:border-slate-600 cursor-pointer", "w-4 h-4 rounded-full text-primary-600 dark:text-secondary-500", "focus:ring-primary-500/30 dark:focus:ring-secondary-400/30") })) : (_jsx("input", { type: "checkbox", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: cn("flex-shrink-0 border-zinc-300 dark:border-slate-600 cursor-pointer", "w-4 h-4 rounded text-primary-600 dark:text-secondary-500 checked:bg-primary-600 dark:checked:bg-secondary-500", "focus:ring-primary-500/30 dark:focus:ring-secondary-400/30") })), _jsx(Span, { className: "flex-1 text-sm text-zinc-700 dark:text-zinc-300 group-hover:text-zinc-900 dark:group-hover:text-zinc-100 transition-colors truncate", children: option.label }), option.count !== undefined && (_jsx(Span, { className: "text-xs text-zinc-400 dark:text-zinc-400 tabular-nums flex-shrink-0", children: option.count }))] }, option.value));
|
|
73
|
+
}), filtered.length === 0 && (_jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 py-1", children: "No results" }))] }))] }));
|
|
74
74
|
}
|
|
@@ -24,5 +24,5 @@ export function RangeFilter({ title, minLabel, maxLabel, minValue, maxValue, onM
|
|
|
24
24
|
maxBound !== undefined;
|
|
25
25
|
const hasValue = !!(minValue || maxValue);
|
|
26
26
|
const inputClass = "w-full rounded-md border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-2.5 py-1.5 text-xs text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20 dark:focus:ring-secondary-400/20";
|
|
27
|
-
return (_jsxs(Div, { role: "group", "aria-labelledby": `rf-${title}`, className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Div, { className: "flex items-center gap-2", children: [_jsxs(Button, { type: "button", id: `rf-${title}`, onClick: handleToggle, variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsxs(Span, { className: "flex items-center gap-2", children: [title, hasValue && (_jsx(Span, { className: "inline-flex items-center justify-center w-5 h-5 text-xs rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20", children: "1" }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: "inline-flex items-center justify-center w-5 h-5 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 rounded-full transition-colors", "aria-label": "Clear", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), !isCollapsed && (_jsxs(Stack, { gap: "3", className: "mt-3", children: [canShowSlider && (_jsx(DualSlider, { minValue: minValue, maxValue: maxValue, onMinChange: onMinChange, onMaxChange: onMaxChange, minBound: minBound, maxBound: maxBound, step: step, prefix: prefix })), _jsxs(Div, { className: "flex items-end gap-2", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [minLabel && (_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: minLabel })), _jsxs(Div, { className: "relative", children: [prefix && (_jsx(Span, { className: "absolute left-2 top-1/2 -translate-y-1/2 text-xs text-zinc-400 dark:text-zinc-
|
|
27
|
+
return (_jsxs(Div, { role: "group", "aria-labelledby": `rf-${title}`, className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Div, { className: "flex items-center gap-2", children: [_jsxs(Button, { type: "button", id: `rf-${title}`, onClick: handleToggle, variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsxs(Span, { className: "flex items-center gap-2", children: [title, hasValue && (_jsx(Span, { className: "inline-flex items-center justify-center w-5 h-5 text-xs rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20", children: "1" }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: "inline-flex items-center justify-center w-5 h-5 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 rounded-full transition-colors", "aria-label": "Clear", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), !isCollapsed && (_jsxs(Stack, { gap: "3", className: "mt-3", children: [canShowSlider && (_jsx(DualSlider, { minValue: minValue, maxValue: maxValue, onMinChange: onMinChange, onMaxChange: onMaxChange, minBound: minBound, maxBound: maxBound, step: step, prefix: prefix })), _jsxs(Div, { className: "flex items-end gap-2", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [minLabel && (_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: minLabel })), _jsxs(Div, { className: "relative", children: [prefix && (_jsx(Span, { className: "absolute left-2 top-1/2 -translate-y-1/2 text-xs text-zinc-400 dark:text-zinc-400 pointer-events-none", children: prefix })), _jsx(Input, { type: type, value: minValue, onChange: (e) => onMinChange(e.target.value), placeholder: minPlaceholder ?? (type === "date" ? "From" : "Min"), className: cn(inputClass, prefix ? "pl-5" : "") })] })] }), _jsx(Span, { className: "flex-shrink-0 pb-1.5 text-zinc-400 dark:text-zinc-400 text-xs", children: "-" }), _jsxs(Div, { className: "flex-1 min-w-0", children: [maxLabel && (_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: maxLabel })), _jsxs(Div, { className: "relative", children: [prefix && (_jsx(Span, { className: "absolute left-2 top-1/2 -translate-y-1/2 text-xs text-zinc-400 dark:text-zinc-400 pointer-events-none", children: prefix })), _jsx(Input, { type: type, value: maxValue, onChange: (e) => onMaxChange(e.target.value), placeholder: maxPlaceholder ?? (type === "date" ? "To" : "Max"), className: cn(inputClass, prefix ? "pl-5" : "") })] })] })] })] }))] }));
|
|
28
28
|
}
|
|
@@ -12,12 +12,12 @@ export const Input = React.forwardRef(function Input({ label, error, helperText,
|
|
|
12
12
|
: "";
|
|
13
13
|
return (_jsxs(Div, { className: "w-full", children: [label && (_jsxs("label", { className: LABEL_BASE, children: [label, required && (_jsx(Span, { className: "text-red-500 ml-1", "aria-hidden": "true", children: "*" }))] })), _jsxs(Div, { className: "relative group", children: [icon && (_jsx(Div, { className: cn("absolute left-3 top-1/2 -translate-y-1/2 transition-colors duration-150", error
|
|
14
14
|
? "text-red-600 dark:text-red-400"
|
|
15
|
-
: "text-zinc-400 dark:text-zinc-
|
|
15
|
+
: "text-zinc-400 dark:text-zinc-400", "group-focus-within:text-primary-500 dark:group-focus-within:text-secondary-400"), children: icon })), _jsx("input", { ref: ref, className: cn("w-full", INPUT_BASE, icon ? INPUT_WITH_ICON : "", rightIcon ? "pr-10" : "", stateClasses, className), disabled: disabled, "aria-invalid": error ? "true" : undefined, "aria-describedby": error
|
|
16
16
|
? `${props.id}-error`
|
|
17
17
|
: helperText
|
|
18
18
|
? `${props.id}-helper`
|
|
19
19
|
: undefined, ...props }), rightIcon && (_jsx(Div, { className: cn("absolute right-3 top-1/2 -translate-y-1/2 transition-colors duration-150", error
|
|
20
20
|
? "text-red-600 dark:text-red-400"
|
|
21
|
-
: "text-zinc-400 dark:text-zinc-
|
|
21
|
+
: "text-zinc-400 dark:text-zinc-400"), children: rightIcon }))] }), error && (_jsx(Text, { id: `${props.id}-error`, className: ERROR_BASE, role: "alert", children: error })), !error && helperText && (_jsx(Text, { id: `${props.id}-helper`, className: HELPER_BASE, children: helperText }))] }));
|
|
22
22
|
});
|
|
23
23
|
Input.displayName = "Input";
|
|
@@ -4,5 +4,5 @@ import { cn, INPUT_BASE, INPUT_ERROR, LABEL_BASE, HELPER_BASE, ERROR_BASE, } fro
|
|
|
4
4
|
export function Select({ label, error, helperText, options, placeholder, className = "", required, ...props }) {
|
|
5
5
|
return (_jsxs(Div, { className: "w-full", children: [label && (_jsxs("label", { className: LABEL_BASE, children: [label, required && (_jsx(Span, { className: "text-red-500 ml-1", "aria-hidden": "true", children: "*" }))] })), _jsxs(Div, { className: "relative group", children: [_jsxs("select", { className: cn(INPUT_BASE, "pr-10 appearance-none cursor-pointer", error ? INPUT_ERROR : "", className), "aria-invalid": error ? "true" : undefined, ...props, children: [placeholder && (_jsx("option", { value: "", disabled: true, children: placeholder })), options.map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value)))] }), _jsx(Div, { className: "absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none transition-colors duration-150", children: _jsx("svg", { className: cn("w-5 h-5 transition-transform duration-200", error
|
|
6
6
|
? "text-red-500 dark:text-red-400"
|
|
7
|
-
: "text-zinc-400 dark:text-zinc-
|
|
7
|
+
: "text-zinc-400 dark:text-zinc-400"), viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true", children: _jsx("path", { fillRule: "evenodd", d: "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z", clipRule: "evenodd" }) }) })] }), error && (_jsx(Text, { className: ERROR_BASE, role: "alert", children: error })), !error && helperText && _jsx(Text, { className: HELPER_BASE, children: helperText })] }));
|
|
8
8
|
}
|
|
@@ -18,5 +18,5 @@ export function Slider({ value: controlledValue, defaultValue = 0, min = 0, max
|
|
|
18
18
|
onChange?.(newVal);
|
|
19
19
|
};
|
|
20
20
|
const displayValue = formatValue ? formatValue(value) : String(value);
|
|
21
|
-
return (_jsxs(Div, { className: cn("w-full space-y-2", className), children: [(label || showValue) && (_jsxs(Row, { justify: "between", children: [label && (_jsx("label", { htmlFor: sliderId, className: LABEL_BASE, children: label })), showValue && (_jsx(Span, { className: "text-sm font-semibold tabular-nums text-zinc-900 dark:text-zinc-100", children: displayValue }))] })), _jsxs(Row, { className: "relative h-5", children: [_jsx(Div, { className: "absolute inset-y-0 flex items-center w-full", children: _jsx(Div, { className: "w-full h-1.5 rounded-full bg-zinc-200 dark:bg-slate-700", children: _jsx(Div, { className: "h-full rounded-full bg-primary-500 dark:bg-secondary-500 transition-all", style: { width: `${pct}%` } }) }) }), _jsx("input", { type: "range", id: sliderId, min: min, max: max, step: step, value: value, disabled: disabled, onChange: handleChange, className: cn("relative w-full appearance-none bg-transparent cursor-pointer", "focus:outline-none", "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4", "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-white", "[&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-primary-500 dark:[&::-webkit-slider-thumb]:border-secondary-500", "[&::-webkit-slider-thumb]:shadow-sm", "[&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:h-4", "[&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-white", "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary-500 dark:[&::-moz-range-thumb]:border-secondary-500", disabled && "opacity-50 cursor-not-allowed") })] }), _jsxs(Row, { justify: "between", className: "text-xs text-zinc-400 dark:text-zinc-
|
|
21
|
+
return (_jsxs(Div, { className: cn("w-full space-y-2", className), children: [(label || showValue) && (_jsxs(Row, { justify: "between", children: [label && (_jsx("label", { htmlFor: sliderId, className: LABEL_BASE, children: label })), showValue && (_jsx(Span, { className: "text-sm font-semibold tabular-nums text-zinc-900 dark:text-zinc-100", children: displayValue }))] })), _jsxs(Row, { className: "relative h-5", children: [_jsx(Div, { className: "absolute inset-y-0 flex items-center w-full", children: _jsx(Div, { className: "w-full h-1.5 rounded-full bg-zinc-200 dark:bg-slate-700", children: _jsx(Div, { className: "h-full rounded-full bg-primary-500 dark:bg-secondary-500 transition-all", style: { width: `${pct}%` } }) }) }), _jsx("input", { type: "range", id: sliderId, min: min, max: max, step: step, value: value, disabled: disabled, onChange: handleChange, className: cn("relative w-full appearance-none bg-transparent cursor-pointer", "focus:outline-none", "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4", "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-white", "[&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-primary-500 dark:[&::-webkit-slider-thumb]:border-secondary-500", "[&::-webkit-slider-thumb]:shadow-sm", "[&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:h-4", "[&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-white", "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary-500 dark:[&::-moz-range-thumb]:border-secondary-500", disabled && "opacity-50 cursor-not-allowed") })] }), _jsxs(Row, { justify: "between", className: "text-xs text-zinc-400 dark:text-zinc-400", children: [_jsx(Span, { children: formatValue ? formatValue(min) : min }), _jsx(Span, { children: formatValue ? formatValue(max) : max })] }), error && (_jsx(Text, { className: ERROR_BASE, role: "alert", children: error }))] }));
|
|
22
22
|
}
|
|
@@ -10,6 +10,6 @@ export const Textarea = React.forwardRef(function Textarea({ label, error, helpe
|
|
|
10
10
|
: 0;
|
|
11
11
|
return (_jsxs(Div, { className: "w-full", children: [label && (_jsxs("label", { className: LABEL_BASE, children: [label, required && (_jsx(Span, { className: "text-red-500 ml-1", "aria-hidden": "true", children: "*" }))] })), _jsx("textarea", { ref: ref, className: cn(INPUT_BASE, "resize-y min-h-[80px]", error ? INPUT_ERROR : "", className), "aria-invalid": error ? "true" : undefined, maxLength: maxLength, value: value, defaultValue: defaultValue, ...props }), _jsxs(Div, { className: "flex items-center justify-between mt-1.5", children: [_jsxs(Div, { className: "flex-1", children: [error && (_jsx(Text, { className: ERROR_BASE, role: "alert", children: error })), !error && helperText && (_jsx(Text, { className: HELPER_BASE, children: helperText }))] }), showCharCount && maxLength && (_jsxs("p", { className: cn("text-xs tabular-nums ml-2 flex-shrink-0", charCount >= maxLength
|
|
12
12
|
? "text-red-500 dark:text-red-400"
|
|
13
|
-
: "text-zinc-400 dark:text-zinc-
|
|
13
|
+
: "text-zinc-400 dark:text-zinc-400"), children: [charCount, " / ", maxLength] }))] })] }));
|
|
14
14
|
});
|
|
15
15
|
Textarea.displayName = "Textarea";
|
|
@@ -3,7 +3,7 @@ export declare function cn(...classes: (string | undefined | null | false)[]): s
|
|
|
3
3
|
export declare const INPUT_BASE = "rounded-lg border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-3.5 py-2.5 text-sm text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-primary-500/20 dark:focus:ring-secondary-400/20 focus:border-primary-500 dark:focus:border-secondary-400 focus:outline-none transition-colors duration-150 placeholder:text-zinc-400 dark:placeholder:text-zinc-500";
|
|
4
4
|
export declare const INPUT_ERROR = "border-red-400 dark:border-red-500 focus:ring-red-500/20 focus:border-red-500 bg-red-50/30 dark:bg-red-950/10";
|
|
5
5
|
export declare const INPUT_SUCCESS = "border-emerald-400 dark:border-emerald-500 focus:ring-emerald-500/20 focus:border-emerald-500";
|
|
6
|
-
export declare const INPUT_DISABLED = "bg-zinc-50 dark:bg-slate-800/30 text-zinc-400 dark:text-zinc-
|
|
6
|
+
export declare const INPUT_DISABLED = "bg-zinc-50 dark:bg-slate-800/30 text-zinc-400 dark:text-zinc-400 cursor-not-allowed opacity-60";
|
|
7
7
|
export declare const INPUT_WITH_ICON = "pl-10";
|
|
8
8
|
export declare const LABEL_BASE = "block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1.5";
|
|
9
9
|
export declare const HELPER_BASE = "text-xs text-zinc-500 dark:text-zinc-400 mt-1";
|
|
@@ -6,7 +6,7 @@ export function cn(...classes) {
|
|
|
6
6
|
export const INPUT_BASE = "rounded-lg border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-3.5 py-2.5 text-sm text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-primary-500/20 dark:focus:ring-secondary-400/20 focus:border-primary-500 dark:focus:border-secondary-400 focus:outline-none transition-colors duration-150 placeholder:text-zinc-400 dark:placeholder:text-zinc-500";
|
|
7
7
|
export const INPUT_ERROR = "border-red-400 dark:border-red-500 focus:ring-red-500/20 focus:border-red-500 bg-red-50/30 dark:bg-red-950/10";
|
|
8
8
|
export const INPUT_SUCCESS = "border-emerald-400 dark:border-emerald-500 focus:ring-emerald-500/20 focus:border-emerald-500";
|
|
9
|
-
export const INPUT_DISABLED = "bg-zinc-50 dark:bg-slate-800/30 text-zinc-400 dark:text-zinc-
|
|
9
|
+
export const INPUT_DISABLED = "bg-zinc-50 dark:bg-slate-800/30 text-zinc-400 dark:text-zinc-400 cursor-not-allowed opacity-60";
|
|
10
10
|
export const INPUT_WITH_ICON = "pl-10";
|
|
11
11
|
export const LABEL_BASE = "block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1.5";
|
|
12
12
|
export const HELPER_BASE = "text-xs text-zinc-500 dark:text-zinc-400 mt-1";
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* per page session even across remounts.
|
|
11
11
|
*/
|
|
12
12
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
13
|
+
import { useToast } from "../../../ui";
|
|
13
14
|
import { ACCOUNT_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
14
15
|
import { clearGuestHistory, getGuestHistory, removeGuestHistoryItem, trackGuestHistory, } from "../utils/guest-history";
|
|
15
16
|
const TRACK_DEBOUNCE_MS = 1500;
|
|
@@ -64,14 +65,20 @@ async function deleteAuthAll() {
|
|
|
64
65
|
}
|
|
65
66
|
export function useHistory(userId) {
|
|
66
67
|
const isAuth = !!userId;
|
|
68
|
+
const { showToast } = useToast();
|
|
67
69
|
const [items, setItems] = useState([]);
|
|
68
70
|
const trackTimers = useRef(new Map());
|
|
69
71
|
const loadItems = useCallback(async () => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
try {
|
|
73
|
+
if (isAuth) {
|
|
74
|
+
setItems(await fetchAuthHistory());
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
setItems(getGuestHistory());
|
|
78
|
+
}
|
|
72
79
|
}
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
catch {
|
|
81
|
+
// Data loading — silent fallback to empty
|
|
75
82
|
}
|
|
76
83
|
}, [isAuth]);
|
|
77
84
|
useEffect(() => {
|
|
@@ -128,14 +135,20 @@ export function useHistory(userId) {
|
|
|
128
135
|
}
|
|
129
136
|
}, [isAuth, loadItems]);
|
|
130
137
|
const clear = useCallback(async () => {
|
|
131
|
-
|
|
132
|
-
|
|
138
|
+
try {
|
|
139
|
+
if (isAuth) {
|
|
140
|
+
await deleteAuthAll();
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
clearGuestHistory();
|
|
144
|
+
}
|
|
145
|
+
setItems([]);
|
|
146
|
+
showToast("History cleared.", "success");
|
|
133
147
|
}
|
|
134
|
-
|
|
135
|
-
|
|
148
|
+
catch {
|
|
149
|
+
showToast("Failed to clear history.", "error");
|
|
136
150
|
}
|
|
137
|
-
|
|
138
|
-
}, [isAuth]);
|
|
151
|
+
}, [isAuth, showToast]);
|
|
139
152
|
return {
|
|
140
153
|
items,
|
|
141
154
|
count: items.length,
|
|
@@ -13,7 +13,7 @@ export function AdvertisementBanner({ title, subtitle, ctaLabel = "Shop now", on
|
|
|
13
13
|
}
|
|
14
14
|
// -- Split layout: when a backgroundImage is provided --
|
|
15
15
|
if (backgroundImage) {
|
|
16
|
-
return (_jsx(Section, { className: `p-8 ${wrapClass} ${className}`, children: _jsx("div", { className: CLS_CONTAINER, "data-section": "advertisementbanner-div-298", children: _jsx("div", { className: "relative overflow-hidden rounded-2xl bg-zinc-900 shadow-xl", "data-section": "advertisementbanner-div-299", children: _jsxs("div", { className: `${THEME_CONSTANTS.grid.cols2Md} min-h-[clamp(300px,40vh,420px)]`, "data-section": "advertisementbanner-div-300", children: [_jsxs("div", { className: `relative ${THEME_CONSTANTS.card.aspectBanner} order-last md:order-first min-h-0 min-h-[clamp(300px,40vh,420px)]`, "data-section": "advertisementbanner-div-301", children: [_jsx(MediaImage, { src: backgroundImage, alt: title, size: "banner", priority: true }), _jsx("div", { className: "hidden md:block absolute inset-y-0 right-0 w-24 bg-gradient-to-r from-transparent to-zinc-900/60 pointer-events-none" })] }), _jsxs("div", { className: "relative flex flex-col justify-center px-8 py-10 md:px-12 md:py-14", "data-section": "advertisementbanner-div-302", children: [_jsx("div", { className: "absolute top-0 right-0 w-32 h-32 opacity-10 pointer-events-none bg-[radial-gradient(circle,_white_1px,_transparent_1px)] bg-[length:12px_12px]", "aria-hidden": true }), tagLabel && (_jsxs("div", { className: "inline-flex items-center gap-1.5 self-start bg-white/10 text-white/80 text-xs font-semibold uppercase tracking-widest px-3 py-1 rounded-full mb-5 backdrop-blur-sm", "data-section": "advertisementbanner-div-303", children: [_jsx(Sparkles, { className: "w-3.5 h-3.5" }), tagLabel] })), _jsx(Heading, { level: 2, variant: "none", className: "text-3xl md:text-4xl lg:text-5xl font-extrabold text-white mb-4 leading-tight", children: title }), subtitle && (_jsx(Text, { variant: "none", className: "text-white/75 text-base md:text-lg mb-8 leading-relaxed", children: subtitle })), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "lg", onClick: onCtaClick, className: "self-start bg-white text-zinc-900 hover:bg-zinc-100 font-semibold shadow-lg gap-2", children: [ctaLabel, _jsx(ArrowRight, { className: "w-4 h-4" })] }))] })] }) }) }) }));
|
|
16
|
+
return (_jsx(Section, { className: `p-8 ${wrapClass} ${className}`, children: _jsx("div", { className: CLS_CONTAINER, "data-section": "advertisementbanner-div-298", children: _jsx("div", { className: "relative overflow-hidden rounded-2xl bg-zinc-900 shadow-xl", "data-section": "advertisementbanner-div-299", children: _jsxs("div", { className: `${THEME_CONSTANTS.grid.cols2Md} min-h-[clamp(300px,40vh,420px)]`, "data-section": "advertisementbanner-div-300", children: [_jsxs("div", { className: `relative ${THEME_CONSTANTS.card.aspectBanner} order-last md:order-first min-h-0 min-h-[clamp(300px,40vh,420px)]`, "data-section": "advertisementbanner-div-301", children: [_jsx(MediaImage, { src: backgroundImage, alt: title, size: "banner", priority: true }), _jsx("div", { className: "hidden md:block absolute inset-y-0 right-0 w-24 bg-gradient-to-r from-transparent to-zinc-900/60 pointer-events-none" })] }), _jsxs("div", { className: "relative flex flex-col justify-center px-8 py-10 md:px-12 md:py-14", "data-section": "advertisementbanner-div-302", children: [_jsx("div", { className: "absolute top-0 right-0 w-32 h-32 opacity-10 pointer-events-none bg-[radial-gradient(circle,_white_1px,_transparent_1px)] bg-[length:12px_12px]", "aria-hidden": true }), tagLabel && (_jsxs("div", { className: "inline-flex items-center gap-1.5 self-start bg-white/10 text-white/80 text-xs font-semibold uppercase tracking-widest px-3 py-1 rounded-full mb-5 backdrop-blur-sm", "data-section": "advertisementbanner-div-303", children: [_jsx(Sparkles, { className: "w-3.5 h-3.5" }), tagLabel] })), _jsx(Heading, { level: 2, variant: "none", className: "text-3xl md:text-4xl lg:text-5xl font-extrabold text-white mb-4 leading-tight", children: title }), subtitle && (_jsx(Text, { variant: "none", className: "text-white/75 text-base md:text-lg mb-8 leading-relaxed", children: subtitle })), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "lg", onClick: onCtaClick, className: "self-start bg-white text-zinc-900 hover:bg-zinc-100 dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-200 font-semibold shadow-lg gap-2", children: [ctaLabel, _jsx(ArrowRight, { className: "w-4 h-4" })] }))] })] }) }) }) }));
|
|
17
17
|
}
|
|
18
18
|
// -- Full-width gradient layout --
|
|
19
19
|
return (_jsx(Section, { className: `p-8 ${wrapClass} ${className}`, children: _jsx("div", { className: CLS_CONTAINER, "data-section": "advertisementbanner-div-304", children: _jsxs("div", { className: [
|
|
@@ -21,5 +21,5 @@ export function AdvertisementBanner({ title, subtitle, ctaLabel = "Shop now", on
|
|
|
21
21
|
compact
|
|
22
22
|
? "h-[clamp(112px,16vh,160px)]"
|
|
23
23
|
: "min-h-[clamp(240px,34vh,360px)]",
|
|
24
|
-
].join(" "), style: backgroundColor ? { backgroundColor } : undefined, "data-section": "advertisementbanner-div-305", children: [!backgroundColor && (_jsx("div", { className: "absolute inset-0 bg-gradient-to-br from-indigo-600 via-purple-600 to-fuchsia-600", "aria-hidden": true })), _jsxs("div", { className: "absolute inset-0 overflow-hidden", "aria-hidden": true, "data-section": "advertisementbanner-div-306", children: [_jsx("div", { className: "absolute -top-16 -left-16 w-64 h-64 rounded-full bg-primary/20 blur-3xl animate-pulse" }), _jsx("div", { className: "absolute -bottom-16 right-0 w-80 h-80 rounded-full bg-cobalt/20 blur-3xl animate-pulse" })] }), compact ? (_jsxs(Row, { justify: "between", className: "relative z-10 w-full px-6 py-4 gap-4 flex-wrap", children: [_jsxs("div", { className: "inline-flex items-center gap-2", "data-section": "advertisementbanner-div-307", children: [_jsx(Sparkles, { className: "w-4 h-4 text-white/80" }), _jsx(Span, { className: "text-white font-semibold text-sm", children: title })] }), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "sm", onClick: onCtaClick, className: "bg-white text-indigo-700 hover:bg-zinc-50 font-semibold gap-1.5 flex-shrink-0", children: [ctaLabel, _jsx(ArrowRight, { className: "w-3.5 h-3.5" })] }))] })) : (_jsxs("div", { className: "relative z-10 w-full max-w-4xl mx-auto px-6 py-12 md:py-16 text-center", "data-section": "advertisementbanner-div-308", children: [tagLabel && (_jsxs("div", { className: "inline-flex items-center gap-1.5 bg-white/15 text-white/90 text-xs font-semibold uppercase tracking-widest px-4 py-1.5 rounded-full mb-5 backdrop-blur-sm shadow-sm", "data-section": "advertisementbanner-div-309", children: [_jsx(Sparkles, { className: "w-3.5 h-3.5" }), tagLabel] })), _jsx(Heading, { level: 2, variant: "none", className: "text-3xl md:text-5xl lg:text-6xl font-extrabold text-white mb-4 drop-shadow-lg leading-tight", children: title }), subtitle && (_jsx(Text, { variant: "none", className: "text-white text-base md:text-xl mb-10 max-w-2xl mx-auto", children: subtitle })), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "lg", onClick: onCtaClick, className: "bg-white text-indigo-700 hover:bg-zinc-50 font-semibold shadow-lg gap-2", children: [ctaLabel, _jsx(ArrowRight, { className: "w-4 h-4" })] }))] }))] }) }) }));
|
|
24
|
+
].join(" "), style: backgroundColor ? { backgroundColor } : undefined, "data-section": "advertisementbanner-div-305", children: [!backgroundColor && (_jsx("div", { className: "absolute inset-0 bg-gradient-to-br from-indigo-600 via-purple-600 to-fuchsia-600", "aria-hidden": true })), _jsxs("div", { className: "absolute inset-0 overflow-hidden", "aria-hidden": true, "data-section": "advertisementbanner-div-306", children: [_jsx("div", { className: "absolute -top-16 -left-16 w-64 h-64 rounded-full bg-primary/20 blur-3xl animate-pulse" }), _jsx("div", { className: "absolute -bottom-16 right-0 w-80 h-80 rounded-full bg-cobalt/20 blur-3xl animate-pulse" })] }), compact ? (_jsxs(Row, { justify: "between", className: "relative z-10 w-full px-6 py-4 gap-4 flex-wrap", children: [_jsxs("div", { className: "inline-flex items-center gap-2", "data-section": "advertisementbanner-div-307", children: [_jsx(Sparkles, { className: "w-4 h-4 text-white/80" }), _jsx(Span, { className: "text-white font-semibold text-sm", children: title })] }), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "sm", onClick: onCtaClick, className: "bg-white dark:bg-zinc-100 text-indigo-700 hover:bg-zinc-50 dark:hover:bg-zinc-200 font-semibold gap-1.5 flex-shrink-0", children: [ctaLabel, _jsx(ArrowRight, { className: "w-3.5 h-3.5" })] }))] })) : (_jsxs("div", { className: "relative z-10 w-full max-w-4xl mx-auto px-6 py-12 md:py-16 text-center", "data-section": "advertisementbanner-div-308", children: [tagLabel && (_jsxs("div", { className: "inline-flex items-center gap-1.5 bg-white/15 text-white/90 text-xs font-semibold uppercase tracking-widest px-4 py-1.5 rounded-full mb-5 backdrop-blur-sm shadow-sm", "data-section": "advertisementbanner-div-309", children: [_jsx(Sparkles, { className: "w-3.5 h-3.5" }), tagLabel] })), _jsx(Heading, { level: 2, variant: "none", className: "text-3xl md:text-5xl lg:text-6xl font-extrabold text-white mb-4 drop-shadow-lg leading-tight", children: title }), subtitle && (_jsx(Text, { variant: "none", className: "text-white text-base md:text-xl mb-10 max-w-2xl mx-auto", children: subtitle })), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "lg", onClick: onCtaClick, className: "bg-white dark:bg-zinc-100 text-indigo-700 hover:bg-zinc-50 dark:hover:bg-zinc-200 font-semibold shadow-lg gap-2", children: [ctaLabel, _jsx(ArrowRight, { className: "w-4 h-4" })] }))] }))] }) }) }));
|
|
25
25
|
}
|
|
@@ -8,7 +8,7 @@ export function FeaturedResultsSection({ title, subtitle, pillLabel, ornamentLab
|
|
|
8
8
|
const pillCls = "inline-flex items-center gap-2 rounded-full border border-primary-500/30 bg-primary-500/10 px-5 py-1.5 text-xs font-medium uppercase tracking-[0.2em] text-primary-700 backdrop-blur-sm dark:text-primary-400";
|
|
9
9
|
if (!items.length)
|
|
10
10
|
return null;
|
|
11
|
-
return (_jsxs(Section, { className: `px-4 py-16 md:py-20 ${className}`, children: [_jsxs(Div, { className: "mb-12 text-center", children: [pillLabel && (_jsxs(Span, { className: pillCls, children: [_jsx(Span, { className: "inline-block h-1.5 w-1.5 rounded-full bg-primary-500", "aria-hidden": "true" }), pillLabel] })), _jsx(Heading, { level: 2, className: "mt-3 font-display text-4xl text-zinc-900 dark:text-white", children: title }), _jsxs(Div, { className: `mt-3 ${flex.center} gap-2 text-zinc-400 dark:text-zinc-
|
|
11
|
+
return (_jsxs(Section, { className: `px-4 py-16 md:py-20 ${className}`, children: [_jsxs(Div, { className: "mb-12 text-center", children: [pillLabel && (_jsxs(Span, { className: pillCls, children: [_jsx(Span, { className: "inline-block h-1.5 w-1.5 rounded-full bg-primary-500", "aria-hidden": "true" }), pillLabel] })), _jsx(Heading, { level: 2, className: "mt-3 font-display text-4xl text-zinc-900 dark:text-white", children: title }), _jsxs(Div, { className: `mt-3 ${flex.center} gap-2 text-zinc-400 dark:text-zinc-400`, "aria-hidden": "true", children: [_jsx(Span, { className: "h-px w-6 bg-current" }), _jsx(Span, { className: "text-xs", children: ornamentLabel }), _jsx(Span, { className: "h-px w-6 bg-current" })] }), subtitle && (_jsx(Text, { className: "mx-auto mt-4 max-w-md text-sm text-zinc-500 dark:text-zinc-400", children: subtitle }))] }), _jsx("div", { className: "mx-auto max-w-7xl", children: _jsx(HorizontalScroller, { items: items, renderItem: (item, i) => (_jsx("div", { className: "w-full sm:w-auto", children: _jsx(BeforeAfterCard, { item: {
|
|
12
12
|
id: item.id ?? `result-${i}`,
|
|
13
13
|
beforeImage: item.beforeImage,
|
|
14
14
|
afterImage: item.afterImage,
|
|
@@ -8,5 +8,5 @@ export function HeroSection({ section, onCtaClick }) {
|
|
|
8
8
|
backgroundSize: "cover",
|
|
9
9
|
backgroundPosition: "center",
|
|
10
10
|
}
|
|
11
|
-
: undefined, children: [_jsx(Div, { className: "absolute inset-0 bg-black/40" }), _jsxs(Div, { className: "relative mx-auto max-w-7xl px-4 py-16 text-center text-white sm:px-6 lg:px-8", children: [content?.title && (_jsx(Heading, { level: 1, className: "text-4xl font-bold leading-tight sm:text-5xl lg:text-6xl", children: content.title })), content?.subtitle && (_jsx(Text, { className: "mx-auto mt-4 max-w-2xl text-lg opacity-90", children: content.subtitle })), content?.ctaLabel && (_jsx(Button, { onClick: onCtaClick, className: "mt-8 inline-block rounded-full bg-white px-8 py-3 text-sm font-semibold text-
|
|
11
|
+
: undefined, children: [_jsx(Div, { className: "absolute inset-0 bg-black/40" }), _jsxs(Div, { className: "relative mx-auto max-w-7xl px-4 py-16 text-center text-white sm:px-6 lg:px-8", children: [content?.title && (_jsx(Heading, { level: 1, className: "text-4xl font-bold leading-tight sm:text-5xl lg:text-6xl", children: content.title })), content?.subtitle && (_jsx(Text, { className: "mx-auto mt-4 max-w-2xl text-lg opacity-90", children: content.subtitle })), content?.ctaLabel && (_jsx(Button, { onClick: onCtaClick, className: "mt-8 inline-block rounded-full bg-white px-8 py-3 text-sm font-semibold text-zinc-900 dark:text-zinc-100 transition hover:bg-neutral-100", children: content.ctaLabel }))] })] }));
|
|
12
12
|
}
|
|
@@ -3,5 +3,5 @@ import { Heading, Section, Text, TextLink } from "../../../ui";
|
|
|
3
3
|
import { Mail } from "lucide-react";
|
|
4
4
|
// --- Section -----------------------------------------------------------------
|
|
5
5
|
export function NewsletterSection({ title, subtitle, privacyLabel, privacyHref, renderForm, className = "", }) {
|
|
6
|
-
return (_jsxs(Section, { className: `py-16 px-4 relative overflow-hidden ${className}`, children: [_jsx("div", { className: "absolute inset-0 bg-gradient-to-br from-primary/10 via-cobalt/5 to-secondary/10 dark:from-primary/15 dark:via-cobalt/10 dark:to-secondary/15 pointer-events-none", "aria-hidden": true }), _jsx("div", { className: "absolute -top-20 -right-20 w-80 h-80 rounded-full bg-primary/5 dark:bg-primary/10 pointer-events-none", "aria-hidden": true }), _jsx("div", { className: "absolute -bottom-16 -left-16 w-64 h-64 rounded-full bg-cobalt/5 dark:bg-cobalt/10 pointer-events-none", "aria-hidden": true }), _jsxs("div", { className: "relative z-10 max-w-2xl mx-auto text-center", "data-section": "newslettersection-div-347", children: [_jsx("div", { className: "inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-primary/10 dark:bg-primary/20 border border-primary/20 mb-5 mx-auto", "data-section": "newslettersection-div-348", children: _jsx(Mail, { className: "w-7 h-7 text-primary" }) }), _jsx(Heading, { level: 2, className: "text-2xl sm:text-3xl font-bold text-zinc-900 dark:text-white mb-3", children: title }), subtitle && (_jsx(Text, { size: "base", className: "text-zinc-500 dark:text-zinc-400 mb-8 max-w-md mx-auto", children: subtitle })), renderForm(), privacyLabel && privacyHref && (_jsxs(Text, { size: "xs", className: "text-zinc-400 dark:text-zinc-
|
|
6
|
+
return (_jsxs(Section, { className: `py-16 px-4 relative overflow-hidden ${className}`, children: [_jsx("div", { className: "absolute inset-0 bg-gradient-to-br from-primary/10 via-cobalt/5 to-secondary/10 dark:from-primary/15 dark:via-cobalt/10 dark:to-secondary/15 pointer-events-none", "aria-hidden": true }), _jsx("div", { className: "absolute -top-20 -right-20 w-80 h-80 rounded-full bg-primary/5 dark:bg-primary/10 pointer-events-none", "aria-hidden": true }), _jsx("div", { className: "absolute -bottom-16 -left-16 w-64 h-64 rounded-full bg-cobalt/5 dark:bg-cobalt/10 pointer-events-none", "aria-hidden": true }), _jsxs("div", { className: "relative z-10 max-w-2xl mx-auto text-center", "data-section": "newslettersection-div-347", children: [_jsx("div", { className: "inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-primary/10 dark:bg-primary/20 border border-primary/20 mb-5 mx-auto", "data-section": "newslettersection-div-348", children: _jsx(Mail, { className: "w-7 h-7 text-primary" }) }), _jsx(Heading, { level: 2, className: "text-2xl sm:text-3xl font-bold text-zinc-900 dark:text-white mb-3", children: title }), subtitle && (_jsx(Text, { size: "base", className: "text-zinc-500 dark:text-zinc-400 mb-8 max-w-md mx-auto", children: subtitle })), renderForm(), privacyLabel && privacyHref && (_jsxs(Text, { size: "xs", className: "text-zinc-400 dark:text-zinc-400 mt-4", children: [privacyLabel, " ", _jsx(TextLink, { href: privacyHref, className: "underline underline-offset-2 hover:text-primary", children: "Privacy Policy" }), "."] }))] })] }));
|
|
7
7
|
}
|
|
@@ -36,7 +36,7 @@ export function SectionCarousel({ title, description, headingVariant = "editoria
|
|
|
36
36
|
headingClass,
|
|
37
37
|
]
|
|
38
38
|
.filter(Boolean)
|
|
39
|
-
.join(" "), children: title }), headingVariant === "editorial" && (_jsxs("div", { className: `${flex.center} gap-2 mt-1 text-zinc-400 dark:text-zinc-
|
|
39
|
+
.join(" "), children: title }), headingVariant === "editorial" && (_jsxs("div", { className: `${flex.center} gap-2 mt-1 text-zinc-400 dark:text-zinc-400 text-xs select-none`, "aria-hidden": "true", "data-section": "sectioncarousel-div-355", children: [_jsx(Span, { className: "h-px w-6 bg-current" }), _jsx(Span, { className: "text-xs", children: "\u2736" }), _jsx(Span, { className: "h-px w-6 bg-current" })] })), description && (_jsx(Text, { className: `text-base ${descVariant} mt-2`, children: description }))] }), isLoading ? (_jsx(CarouselSkeleton, { count: skeletonCount })) : (_jsx(HorizontalScroller, { items: items, renderItem: renderItem, perView: perView, gap: gap, autoScroll: autoScroll, autoScrollInterval: autoScrollInterval, loop: rows === 1, keyExtractor: keyExtractor, rows: rows, minItemWidth: minItemWidth, showArrows: true, snapToItems: true, showFadeEdges: true, showScrollbar: false, pauseOnHover: true })), viewMoreHref && !isLoading && (_jsx("div", { className: "mt-6 flex justify-center", "data-section": "sectioncarousel-div-356", children: _jsx(TextLink, { href: viewMoreHref, className: `inline-flex items-center gap-1.5 rounded-lg border px-6 py-2.5 text-sm font-medium transition-colors ${useLightText
|
|
40
40
|
? "border-white/40 text-white hover:bg-white/10"
|
|
41
41
|
: "border-zinc-200 dark:border-zinc-700 text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-zinc-800"}`, children: viewMoreLabel }) }))] })] }));
|
|
42
42
|
}
|
|
@@ -17,6 +17,7 @@ import { ROUTES } from "../../../next";
|
|
|
17
17
|
import { InteractiveProductCard } from "../../products/components/InteractiveProductCard";
|
|
18
18
|
import { LiveItemFilters } from "./LiveItemFilters";
|
|
19
19
|
import { ACTION_ID } from "../../products/constants/action-defs";
|
|
20
|
+
import { useBottomActions } from "../../layout";
|
|
20
21
|
const DEFAULT_SORT = sortBy(PRODUCT_FIELDS.CREATED_AT);
|
|
21
22
|
const SORT_OPTIONS = [
|
|
22
23
|
{ value: sortBy(PRODUCT_FIELDS.CREATED_AT), label: "Newest First" },
|
|
@@ -101,6 +102,7 @@ export function LiveItemsIndexListing({ initialData }) {
|
|
|
101
102
|
wishlistActions.addToWishlist(id);
|
|
102
103
|
}
|
|
103
104
|
}
|
|
105
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [] } } : {});
|
|
104
106
|
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search live items\u2026", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: (e) => { if (e.key === "Enter")
|
|
105
107
|
commitSearch(); }, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: (v) => { if (v !== "table")
|
|
106
108
|
setView(v); }, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: products.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx("div", { className: "py-6", children: isLoading ? (_jsx("div", { className: gridClass, children: Array.from({ length: 10 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border border-zinc-100 dark:border-slate-700 overflow-hidden animate-pulse", children: [_jsx("div", { className: "aspect-square bg-zinc-200 dark:bg-slate-700" }), _jsxs("div", { className: "p-3 space-y-2", children: [_jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-1/3" })] })] }, i))) })) : products.length === 0 ? (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "No live item listings found." })) : (_jsx("div", { className: view === "list" ? "flex flex-col divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800" : gridClass, children: products.map((product) => (_jsx(InteractiveProductCard, { product: product, href: String(ROUTES.PUBLIC.LIVE_DETAIL(product.id)), variant: view === "list" ? "list" : "grid", isWishlisted: wishlistActions.isWishlisted(product.id), onToggleWishlist: handleToggleWishlist, selectable: selection.isSelecting, isSelected: selection.isSelected(product.id), onSelect: (id) => selection.toggle(id) }, product.id))) })) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: onFilterClear, activeCount: filterActiveCount, hideTrigger: true, children: _jsx(LiveItemFilters, { table: pendingTable, categoryOptions: categoryOptions }) }), _jsx(LoginRequiredModal, { isOpen: modalOpen, onClose: closeModal, message: modalMessage })] }));
|
|
@@ -39,5 +39,5 @@ export async function LiveItemsListView({ searchParams = {} }) {
|
|
|
39
39
|
const result = await productRepository
|
|
40
40
|
.list({ filters, sorts: sort, page, pageSize })
|
|
41
41
|
.catch(() => null);
|
|
42
|
-
return (_jsx(Main, { children: _jsx(Section, { className: "py-10", children: _jsxs(Container, { size: "xl", children: [_jsx(Heading, { level: 1, className: "mb-8 text-3xl font-semibold text-zinc-900", children: "Live Items" }), _jsx(AdSlot, { id: "listing-sidebar-top", className: "mb-6" }), _jsx(LiveItemsIndexListing, { initialData: result ?? undefined }), _jsx(AdSlot, { id: "listing-sidebar-bottom", className: "mt-8" })] }) }) }));
|
|
42
|
+
return (_jsx(Main, { children: _jsx(Section, { className: "py-10", children: _jsxs(Container, { size: "xl", children: [_jsx(Heading, { level: 1, className: "mb-8 text-3xl font-semibold text-zinc-900 dark:text-zinc-50", children: "Live Items" }), _jsx(AdSlot, { id: "listing-sidebar-top", className: "mb-6" }), _jsx(LiveItemsIndexListing, { initialData: result ?? undefined }), _jsx(AdSlot, { id: "listing-sidebar-bottom", className: "mt-8" })] }) }) }));
|
|
43
43
|
}
|
|
@@ -4,15 +4,15 @@ import { formatCurrency } from "../../../utils/number.formatter";
|
|
|
4
4
|
import { getDefaultLocale } from "../../../core/baseline-resolver";
|
|
5
5
|
import { THEME_CONSTANTS } from "../../../tokens";
|
|
6
6
|
const STATUS_COLORS = {
|
|
7
|
-
pending: "bg-yellow-100 text-yellow-700",
|
|
8
|
-
confirmed: "bg-blue-100 text-blue-700",
|
|
9
|
-
processing: "bg-blue-100 text-blue-700",
|
|
10
|
-
shipped: "bg-indigo-100 text-indigo-700",
|
|
11
|
-
delivered: "bg-green-100 text-green-700",
|
|
12
|
-
cancelled: "bg-red-100 text-red-700",
|
|
13
|
-
refunded: "bg-orange-100 text-orange-700",
|
|
14
|
-
return_requested: "bg-amber-100 text-amber-700",
|
|
15
|
-
returned: "bg-neutral-100 text-neutral-600",
|
|
7
|
+
pending: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/40 dark:text-yellow-300",
|
|
8
|
+
confirmed: "bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300",
|
|
9
|
+
processing: "bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300",
|
|
10
|
+
shipped: "bg-indigo-100 text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-300",
|
|
11
|
+
delivered: "bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300",
|
|
12
|
+
cancelled: "bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-300",
|
|
13
|
+
refunded: "bg-orange-100 text-orange-700 dark:bg-orange-900/40 dark:text-orange-300",
|
|
14
|
+
return_requested: "bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300",
|
|
15
|
+
returned: "bg-neutral-100 text-neutral-600 dark:bg-neutral-800 dark:text-neutral-300",
|
|
16
16
|
};
|
|
17
17
|
export function OrderCard({ order, onClick, labels = {} }) {
|
|
18
18
|
const date = order.createdAt
|
|
@@ -22,7 +22,7 @@ export function OrderCard({ order, onClick, labels = {} }) {
|
|
|
22
22
|
day: "numeric",
|
|
23
23
|
})
|
|
24
24
|
: "";
|
|
25
|
-
const statusColor = STATUS_COLORS[order.orderStatus] ?? "bg-neutral-100 text-neutral-700";
|
|
25
|
+
const statusColor = STATUS_COLORS[order.orderStatus] ?? "bg-neutral-100 text-neutral-700 dark:bg-neutral-800 dark:text-neutral-300";
|
|
26
26
|
// SB8-F — count unrevealed prize-draw entries to surface a "reveals pending" badge.
|
|
27
27
|
const unrevealedPrizeDraws = order.items.filter((it) => it.listingType === "prize-draw" &&
|
|
28
28
|
it.prizeRevealStatus !== undefined &&
|
|
@@ -34,14 +34,14 @@ export function OrderCard({ order, onClick, labels = {} }) {
|
|
|
34
34
|
.sort()[0];
|
|
35
35
|
return (_jsxs(Div, { role: onClick ? "button" : undefined, tabIndex: onClick ? 0 : undefined, onKeyDown: onClick
|
|
36
36
|
? (e) => (e.key === "Enter" || e.key === " ") && onClick(order)
|
|
37
|
-
: undefined, onClick: onClick ? () => onClick(order) : undefined, className: `rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-5 ${onClick ? "cursor-pointer transition hover:shadow-md" : ""}`, children: [_jsxs(Row, { wrap: true, align: "start", justify: "between", gap: "3", children: [_jsxs(Div, { children: [_jsxs(Text, { className: "text-xs text-neutral-500 dark:text-zinc-400", children: ["Order #", order.id.slice(-8).toUpperCase()] }), date && (_jsx(Text, { className: "mt-0.5 text-xs text-
|
|
37
|
+
: undefined, onClick: onClick ? () => onClick(order) : undefined, className: `rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-5 ${onClick ? "cursor-pointer transition hover:shadow-md" : ""}`, children: [_jsxs(Row, { wrap: true, align: "start", justify: "between", gap: "3", children: [_jsxs(Div, { children: [_jsxs(Text, { className: "text-xs text-neutral-500 dark:text-zinc-400", children: ["Order #", order.id.slice(-8).toUpperCase()] }), date && (_jsx(Text, { className: "mt-0.5 text-xs text-zinc-400 dark:text-zinc-400", children: date }))] }), _jsx(Span, { className: `rounded-full px-3 py-1 text-xs font-semibold capitalize ${statusColor}`, children: labels[order.orderStatus] ?? order.orderStatus.replace(/_/g, " ") })] }), revealsRemaining > 0 && (_jsxs(Row, { gap: "sm", className: "mt-2", children: [_jsxs(Span, { className: "inline-flex items-center rounded-full bg-fuchsia-100 dark:bg-fuchsia-900/30 px-2.5 py-0.5 text-xs font-semibold text-fuchsia-700 dark:text-fuchsia-300", children: [revealsRemaining, " ", revealsRemaining === 1 ? "reveal" : "reveals", " pending"] }), earliestDeadline && (_jsxs(Span, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: ["before ", new Date(earliestDeadline).toLocaleDateString(getDefaultLocale(), { month: "short", day: "numeric" })] }))] })), _jsxs(Row, { wrap: true, gap: "3", className: "mt-4", children: [order.items.slice(0, 3).map((item, i) => (_jsxs(Row, { className: "gap-2", children: [item.image && (_jsx(Div, { role: "img", "aria-label": item.title, className: "h-10 w-10 rounded-lg bg-center bg-cover", style: { backgroundImage: `url(${item.image})` } })), _jsxs(Div, { children: [_jsx(Text, { className: `text-sm font-medium text-neutral-900 dark:text-zinc-100 ${THEME_CONSTANTS.utilities.textClamp1}`, children: item.title }), _jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400", children: ["\u00D7", item.quantity] })] })] }, i))), order.items.length > 3 && (_jsxs(Span, { className: "self-center text-xs text-zinc-400 dark:text-zinc-400", children: ["+", order.items.length - 3, " more"] }))] }), _jsxs(Row, { justify: "between", className: "mt-4 border-t border-neutral-100 dark:border-slate-700 pt-3", children: [_jsxs(Span, { className: "text-sm text-neutral-500 dark:text-zinc-400", children: [order.currency ?? "", " Total"] }), _jsx(Span, { className: "font-semibold text-neutral-900 dark:text-zinc-100", children: formatCurrency(order.total, order.currency) })] })] }));
|
|
38
38
|
}
|
|
39
39
|
export function OrdersList({ orders, isLoading, onOrderClick, totalPages = 1, currentPage = 1, onPageChange, emptyLabel = "No orders found", }) {
|
|
40
40
|
if (isLoading) {
|
|
41
41
|
return (_jsx(Stack, { gap: "md", children: Array.from({ length: 3 }).map((_, i) => (_jsxs(Div, { className: "animate-pulse rounded-xl border border-neutral-200 dark:border-slate-700 p-5", children: [_jsxs(Div, { className: "flex justify-between", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Div, { className: "h-3 w-20 rounded bg-neutral-200 dark:bg-slate-700" }), _jsx(Div, { className: "h-3 w-16 rounded bg-neutral-200 dark:bg-slate-700" })] }), _jsx(Div, { className: "h-6 w-20 rounded-full bg-neutral-200 dark:bg-slate-700" })] }), _jsxs(Div, { className: "mt-4 flex gap-3", children: [_jsx(Div, { className: "h-10 w-10 rounded-lg bg-neutral-200 dark:bg-slate-700" }), _jsx(Div, { className: "h-10 w-10 rounded-lg bg-neutral-200 dark:bg-slate-700" })] })] }, i))) }));
|
|
42
42
|
}
|
|
43
43
|
if (orders.length === 0) {
|
|
44
|
-
return (_jsx(Text, { className: "py-12 text-center text-sm text-
|
|
44
|
+
return (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: emptyLabel }));
|
|
45
45
|
}
|
|
46
46
|
return (_jsxs(Stack, { gap: "lg", children: [_jsx(Stack, { gap: "md", children: orders.map((order) => (_jsx(OrderCard, { order: order, onClick: onOrderClick }, order.id))) }), totalPages > 1 && onPageChange && (_jsx(Div, { className: "flex justify-center", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: onPageChange }) }))] }));
|
|
47
47
|
}
|
|
@@ -59,5 +59,5 @@ export function MarketplacePreorderCard({ product, className = "", variant = "gr
|
|
|
59
59
|
/* ── Compact list layout ── */
|
|
60
60
|
_jsxs(_Fragment, { children: [_jsxs(Div, { className: "flex items-start justify-between gap-2 min-w-0", children: [_jsx(TextLink, { href: detailHref, className: "min-w-0 flex-1", children: _jsx(Text, { className: `${THEME_CONSTANTS.utilities.textClamp2} text-sm font-medium text-zinc-900 dark:text-zinc-100`, children: product.title }) }), wishlistActions && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: `shrink-0 p-1 text-base leading-none ${inWishlist ? "text-primary" : "text-zinc-400"}`, onClick: handleWishlist, "aria-label": inWishlist ? mergedLabels.removeFromWishlist : mergedLabels.addToWishlist, children: inWishlist ? "♥" : "♡" }))] }), _jsxs(Div, { className: "flex items-center gap-2 flex-wrap", children: [_jsx(Text, { className: "text-sm font-bold text-primary", children: formatCurrency(product.price, getDefaultCurrency()) }), shipDate && _jsx(PreorderBadge, { shipDate: shipDate })] }), _jsx(Button, { type: "button", variant: "primary", size: "sm", className: "self-start text-xs mt-0.5", onClick: handleNavigate, children: mergedLabels.reserveNow })] })) : (
|
|
61
61
|
/* ── Full grid layout ── */
|
|
62
|
-
_jsxs(_Fragment, { children: [_jsx(TextLink, { href: detailHref, children: _jsx(Text, { className: `${THEME_CONSTANTS.utilities.textClamp2} text-sm font-medium text-zinc-900 dark:text-zinc-100`, children: product.title }) }), product.description ? (_jsx(RichText, { html: normalizeRichTextHtml(product.description), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: `${THEME_CONSTANTS.utilities.textClamp2} text-xs text-zinc-500` })) : null, _jsxs(Row, { justify: "between", className: "mt-1 gap-2", children: [_jsx(Text, { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: formatCurrency(product.price, getDefaultCurrency()) }), shipDate && _jsx(PreorderBadge, { shipDate: shipDate })] }), _jsxs(Row, { justify: "between", className: "mt-2 gap-2", children: [_jsx(Button, { type: "button", variant: "primary", size: "sm", className: "flex-1 text-xs", onClick: handleNavigate, children: mergedLabels.reserveNow }), onAddToCart ? (_jsx(Button, { type: "button", variant: "outline", size: "sm", className: "flex-1 text-xs", onClick: (e) => { e.stopPropagation(); onAddToCart(product); }, children: mergedLabels.addToCart })) : null, wishlistActions ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: `text-base ${inWishlist ? "text-primary" : "text-zinc-500"}`, onClick: handleWishlist, "aria-label": inWishlist ? mergedLabels.removeFromWishlist : mergedLabels.addToWishlist, children: inWishlist ? "♥" : "♡" })) : null] })] })) })] }));
|
|
62
|
+
_jsxs(_Fragment, { children: [_jsx(TextLink, { href: detailHref, children: _jsx(Text, { className: `${THEME_CONSTANTS.utilities.textClamp2} text-sm font-medium text-zinc-900 dark:text-zinc-100`, children: product.title }) }), product.description ? (_jsx(RichText, { html: normalizeRichTextHtml(product.description), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: `${THEME_CONSTANTS.utilities.textClamp2} text-xs text-zinc-500 dark:text-zinc-400` })) : null, _jsxs(Row, { justify: "between", className: "mt-1 gap-2", children: [_jsx(Text, { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: formatCurrency(product.price, getDefaultCurrency()) }), shipDate && _jsx(PreorderBadge, { shipDate: shipDate })] }), _jsxs(Row, { justify: "between", className: "mt-2 gap-2", children: [_jsx(Button, { type: "button", variant: "primary", size: "sm", className: "flex-1 text-xs", onClick: handleNavigate, children: mergedLabels.reserveNow }), onAddToCart ? (_jsx(Button, { type: "button", variant: "outline", size: "sm", className: "flex-1 text-xs", onClick: (e) => { e.stopPropagation(); onAddToCart(product); }, children: mergedLabels.addToCart })) : null, wishlistActions ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: `text-base ${inWishlist ? "text-primary" : "text-zinc-500 dark:text-zinc-400"}`, onClick: handleWishlist, "aria-label": inWishlist ? mergedLabels.removeFromWishlist : mergedLabels.addToWishlist, children: inWishlist ? "♥" : "♡" })) : null] })] })) })] }));
|
|
63
63
|
}
|
|
@@ -27,7 +27,7 @@ export function PreOrderActionsClient({ productId, price, currency, depositAmoun
|
|
|
27
27
|
}
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
|
-
return (_jsxs(Div, { className: "space-y-4", children: [price !== null && (_jsxs(Div, { children: [_jsx(Text, { className: "text-2xl font-bold text-zinc-900 dark:text-zinc-50", children: formatCurrency(price, currency) }), depositAmount !== null && (_jsxs(Text, { className: "mt-0.5 text-xs text-zinc-500", children: ["Reserve with ", formatCurrency(depositAmount, currency), depositPercent !== null ? ` (${depositPercent}% deposit)` : ""] }))] })), error && (_jsx(Text, { className: "text-xs text-red-600 dark:text-red-400", children: error })), success && (_jsx(Text, { className: "text-xs text-emerald-600 dark:text-emerald-400", children: "\u2713 Reserved! Redirecting to checkout\u2026" })), _jsx(LoginRequiredModal, { isOpen: showLoginModal, onClose: () => setShowLoginModal(false), message: "You need to be signed in to reserve this pre-order. Please log in or create an account to continue." }), _jsxs(Stack, { gap: "sm", children: [_jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isPending, onClick: handleReserve, children: isPending ? "Processing…" : "Reserve Now" }), isCancellable && (_jsx(Text, { className: "text-center text-xs text-zinc-500 dark:text-zinc-400", children: "\u2713 Free cancellation before production" }))] }), tags.length > 0 && (_jsx(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: _jsx("div", { className: "flex flex-wrap gap-1.5", 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))) }) })), _jsx(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: _jsx("div", { className: "flex flex-wrap gap-4 justify-center text-center", children: [
|
|
30
|
+
return (_jsxs(Div, { className: "space-y-4", children: [price !== null && (_jsxs(Div, { children: [_jsx(Text, { className: "text-2xl font-bold text-zinc-900 dark:text-zinc-50", children: formatCurrency(price, currency) }), depositAmount !== null && (_jsxs(Text, { className: "mt-0.5 text-xs text-zinc-500 dark:text-zinc-400", children: ["Reserve with ", formatCurrency(depositAmount, currency), depositPercent !== null ? ` (${depositPercent}% deposit)` : ""] }))] })), error && (_jsx(Text, { className: "text-xs text-red-600 dark:text-red-400", children: error })), success && (_jsx(Text, { className: "text-xs text-emerald-600 dark:text-emerald-400", children: "\u2713 Reserved! Redirecting to checkout\u2026" })), _jsx(LoginRequiredModal, { isOpen: showLoginModal, onClose: () => setShowLoginModal(false), message: "You need to be signed in to reserve this pre-order. Please log in or create an account to continue." }), _jsxs(Stack, { gap: "sm", children: [_jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isPending, onClick: handleReserve, children: isPending ? "Processing…" : "Reserve Now" }), isCancellable && (_jsx(Text, { className: "text-center text-xs text-zinc-500 dark:text-zinc-400", children: "\u2713 Free cancellation before production" }))] }), tags.length > 0 && (_jsx(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: _jsx("div", { className: "flex flex-wrap gap-1.5", 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))) }) })), _jsx(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: _jsx("div", { className: "flex flex-wrap gap-4 justify-center text-center", children: [
|
|
31
31
|
{ icon: "🔒", label: "Secure\nPayment" },
|
|
32
32
|
{ icon: "📅", label: "Guaranteed\nDelivery" },
|
|
33
33
|
{ icon: "↩", label: "Free\nCancellation" },
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Div, Span } from "../../../ui";
|
|
3
3
|
const STATUS_MAP = {
|
|
4
|
-
pending: { label: "Pending", color: "bg-yellow-100 text-yellow-700" },
|
|
5
|
-
confirmed: { label: "Confirmed", color: "bg-blue-100 text-blue-700" },
|
|
6
|
-
ready: { label: "Ready", color: "bg-green-100 text-green-700" },
|
|
7
|
-
fulfilled: { label: "Fulfilled", color: "bg-gray-100 text-gray-
|
|
8
|
-
cancelled: { label: "Cancelled", color: "bg-red-100 text-red-
|
|
4
|
+
pending: { label: "Pending", color: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/40 dark:text-yellow-300" },
|
|
5
|
+
confirmed: { label: "Confirmed", color: "bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300" },
|
|
6
|
+
ready: { label: "Ready", color: "bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300" },
|
|
7
|
+
fulfilled: { label: "Fulfilled", color: "bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300" },
|
|
8
|
+
cancelled: { label: "Cancelled", color: "bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-300" },
|
|
9
9
|
};
|
|
10
10
|
export function PreOrderBadge({ status, className = "" }) {
|
|
11
11
|
const { label, color } = STATUS_MAP[status] ?? STATUS_MAP.pending;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useBottomActions } from "../../layout/hooks/useBottomActions";
|
|
3
|
+
import { formatCurrency } from "../../../utils/number.formatter";
|
|
4
|
+
import { ACTION_ID } from "../../products/constants/action-defs";
|
|
5
|
+
export function PreOrderBottomActions({ price, currency, }) {
|
|
6
|
+
useBottomActions({
|
|
7
|
+
actions: [
|
|
8
|
+
{
|
|
9
|
+
id: ACTION_ID.RESERVE_NOW,
|
|
10
|
+
label: "Reserve Now",
|
|
11
|
+
variant: "primary",
|
|
12
|
+
onClick: () => {
|
|
13
|
+
document
|
|
14
|
+
.getElementById("pre-order-buy-bar")
|
|
15
|
+
?.scrollIntoView({ behavior: "smooth" });
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
infoLabel: price !== null ? formatCurrency(price, currency) : undefined,
|
|
20
|
+
});
|
|
21
|
+
return null;
|
|
22
|
+
}
|