@mohasinac/appkit 3.3.3 → 3.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +1 -1
- package/dist/_internal/client/features/lottery/LotteryDetailView.js +2 -1
- package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.js +2 -1
- package/dist/_internal/server/features/auth/permissions.js +4 -3
- package/dist/_internal/server/features/cart/actions.js +1 -1
- package/dist/_internal/server/features/lottery/data.d.ts +2 -3
- package/dist/_internal/server/features/products/actions.js +1 -1
- package/dist/features/about/components/AboutView.js +1 -1
- package/dist/features/about/components/PolicyPageView.js +1 -1
- package/dist/features/about/components/TrackOrderView.js +1 -1
- package/dist/features/account/components/AddressesIndexListing.js +1 -1
- package/dist/features/admin/components/AdminBlogEditorView.js +1 -1
- package/dist/features/admin/components/AdminCarouselEditorView.js +2 -1
- package/dist/features/admin/components/AdminCarouselView.js +1 -1
- package/dist/features/admin/components/AdminNavEditorView.js +2 -1
- package/dist/features/admin/components/AdminProductsView.js +2 -2
- package/dist/features/admin/components/AdminSectionsView.js +11 -7
- package/dist/features/admin/components/AdminSiteSettingsView.js +2 -1
- package/dist/features/admin/components/DrawerFormFooter.js +2 -2
- package/dist/features/admin/components/QuickEditMenu.js +1 -1
- package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +1 -1
- package/dist/features/admin/components/sections/adminSectionsTypes.js +3 -2
- package/dist/features/admin/constants/filter-tabs.js +11 -0
- package/dist/features/auctions/columns/index.js +1 -1
- package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
- package/dist/features/auctions/schemas/index.d.ts +2 -2
- package/dist/features/auth/hooks/useRBAC.js +6 -1
- package/dist/features/blog/columns/index.js +1 -1
- package/dist/features/cart/components/CartDrawer.js +2 -2
- package/dist/features/categories/components/BrandDetailPageView.js +1 -1
- package/dist/features/categories/components/BreadcrumbTrail.js +2 -1
- package/dist/features/categories/schemas/firestore.d.ts +1 -1
- package/dist/features/contact/email.js +0 -1
- package/dist/features/events/components/EventBanner.js +2 -1
- package/dist/features/events/components/EventLeaderboard.js +1 -1
- package/dist/features/faq/components/FAQCategorySidebar.js +2 -1
- package/dist/features/forms/Slider.js +5 -2
- package/dist/features/forms/Toggle.js +4 -1
- package/dist/features/homepage/components/AdSlot.js +2 -2
- package/dist/features/homepage/components/BeforeAfterCard.js +1 -1
- package/dist/features/homepage/components/CTABannerSection.js +2 -1
- package/dist/features/homepage/components/CharacterHotspot.js +2 -1
- package/dist/features/homepage/components/FAQSection.js +1 -1
- package/dist/features/homepage/components/FeaturedBundlesSection.js +1 -1
- package/dist/features/homepage/components/HowItWorksInfoView.js +1 -1
- package/dist/features/homepage/components/HowItWorksSection.js +1 -1
- package/dist/features/homepage/components/NewsletterBanner.js +1 -1
- package/dist/features/homepage/components/SecurityHighlightsSection.js +1 -1
- package/dist/features/homepage/components/SiteFeaturesSection.js +1 -1
- package/dist/features/homepage/components/TrustFeaturesSection.js +1 -1
- package/dist/features/homepage/components/TrustIndicatorsSection.js +1 -1
- package/dist/features/layout/BottomActions.js +29 -2
- package/dist/features/layout/BottomActionsContext.d.ts +36 -0
- package/dist/features/layout/BottomActionsContext.js +36 -0
- package/dist/features/orders/components/MarketplaceOrderCard.js +2 -2
- package/dist/features/orders/schemas/index.d.ts +2 -2
- package/dist/features/payments/schemas/index.d.ts +4 -4
- package/dist/features/products/components/BidHistory.js +1 -1
- package/dist/features/products/components/MarketplaceBundleCard.js +1 -1
- package/dist/features/products/components/ProductGalleryClient.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/repository/products.repository.js +1 -1
- package/dist/features/products/schemas/product-features.validators.d.ts +6 -6
- package/dist/features/promotions/repository/claimed-coupons.repository.js +1 -1
- package/dist/features/reviews/columns/index.js +1 -1
- package/dist/features/scams/components/ScamAwarenessModal.js +1 -1
- package/dist/features/search/components/Search.js +1 -1
- package/dist/features/search/schemas/index.d.ts +2 -2
- package/dist/features/seller/actions/seller-actions.d.ts +2 -2
- package/dist/features/seller/components/SellerCouponEditorView.js +1 -1
- package/dist/features/seller/components/SellerGoogleReviewsView.js +1 -1
- package/dist/features/seller/components/SellerOrdersView.js +4 -1
- package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
- package/dist/features/seller/components/SellerProductsView.js +35 -31
- package/dist/features/seller/components/SellerReviewsView.js +1 -1
- package/dist/features/seller/schemas/index.d.ts +2 -2
- package/dist/features/shell/QuickFormDrawer.js +1 -1
- package/dist/features/stores/columns/index.js +1 -1
- package/dist/features/stores/components/StoresIndexListing.js +20 -15
- package/dist/features/wishlist/actions/wishlist-actions.js +1 -1
- package/dist/next/ErrorBoundary.js +2 -1
- package/dist/next/components/NotFoundView.js +17 -0
- package/dist/next/components/UnauthorizedView.js +13 -0
- package/dist/schemas/registry.d.ts +93 -94
- package/dist/schemas/webhooks/razorpay.d.ts +86 -86
- package/dist/seed/carousel-slides-seed-data.js +3 -2
- package/dist/seed/defaults/homepage-sections.js +2 -1
- package/dist/seed/factories/carousel.factory.js +2 -1
- package/dist/seed/homepage-sections-seed-data.js +4 -3
- package/dist/seed/notifications-seed-data.js +2 -1
- package/dist/seed/site-settings-seed-data.js +3 -2
- package/dist/seo/metadata.js +2 -1
- package/dist/ui/columns/column-renderers.js +1 -1
- package/dist/ui/components/Accordion.js +10 -6
- package/dist/ui/components/ListingLayout.js +6 -2
- package/package.json +1 -1
|
@@ -6,5 +6,5 @@ import { Div, Grid, Heading, Row, Section, Span, Text } from "../../../ui";
|
|
|
6
6
|
export function HowItWorksInfoView({ title, subtitle, heroClass = "", stepsTitle, steps, detailsSectionTitle, details = [], renderDiagram, renderFooter, accentClass = "bg-info-surface dark:bg-info-surface text-info dark:text-info", className = "", }) {
|
|
7
7
|
const themed = { bgSecondary: THEMED_BG_SECONDARY, border: THEMED_BORDER };
|
|
8
8
|
const spacing = { stack: SPACING_STACK };
|
|
9
|
-
return (_jsxs(Div, { className: `-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10 ${className}`, children: [_jsx(Section, { color: "inverse", tone: "accent-banner", className: heroClass, paddingY: "y-5xl", children: _jsxs(Div, { paddingX: "x-page", className: "max-w-4xl mx-auto text-center", children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-4", children: title }), subtitle && (_jsx(Text, { color: "inverse", variant: "none", className: "/80 max-w-2xl mx-auto", children: subtitle }))] }) }), _jsxs(Div, { paddingX: "x-page", className: "max-w-4xl mx-auto", padding: "content-banner", children: [renderDiagram?.(), stepsTitle && (_jsx(Heading, { level: 2, className: "mb-6", children: stepsTitle })), _jsx(Div, { className: `${spacing.stack} mb-14`, children: steps.map(({ number, icon, title: stepTitle, text, accentClass: stepAccent, textClass, }) => (_jsxs(Section, { layout: "flex", gap: "md", align: "start", border: "default", surface: "subtle", rounded: "xl", padding: "lg", children: [_jsx(Row, { textWeight: "bold", align: "center", justify: "center", textSize: "sm", className: `shrink-0 w-10 h-10 ${stepAccent ?? accentClass}`, rounded: "xl", children: _jsx(Span, { className: textClass, children: number }) }), _jsxs(Div, { children: [_jsxs(Heading, { level: 3, className: "mb-1", weight: "semibold", children: [icon, " ", stepTitle] }), _jsx(Text, { variant: "secondary", size: "sm", className: "leading-relaxed", children: text })] })] }, number))) }), details.length > 0 && (_jsxs(_Fragment, { children: [detailsSectionTitle && (_jsx(Heading, { level: 2, className: "mb-6", children: detailsSectionTitle })), _jsx(Grid, { className: "grid-cols-1 sm:grid-cols-2 xl:grid-cols-2 2xl:grid-cols-3 mb-12", children: details.map(({ title: dt, text: dx }) => (_jsxs(
|
|
9
|
+
return (_jsxs(Div, { className: `-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10 ${className}`, children: [_jsx(Section, { color: "inverse", tone: "accent-banner", className: heroClass, paddingY: "y-5xl", children: _jsxs(Div, { paddingX: "x-page", className: "max-w-4xl mx-auto text-center", children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-4", children: title }), subtitle && (_jsx(Text, { color: "inverse", variant: "none", className: "/80 max-w-2xl mx-auto", children: subtitle }))] }) }), _jsxs(Div, { paddingX: "x-page", className: "max-w-4xl mx-auto", padding: "content-banner", children: [renderDiagram?.(), stepsTitle && (_jsx(Heading, { level: 2, className: "mb-6", children: stepsTitle })), _jsx(Div, { className: `${spacing.stack} mb-14`, children: steps.map(({ number, icon, title: stepTitle, text, accentClass: stepAccent, textClass, }) => (_jsxs(Section, { layout: "flex", gap: "md", align: "start", border: "default", surface: "subtle", rounded: "xl", padding: "lg", children: [_jsx(Row, { textWeight: "bold", align: "center", justify: "center", textSize: "sm", className: `shrink-0 w-10 h-10 ${stepAccent ?? accentClass}`, rounded: "xl", children: _jsx(Span, { className: textClass, children: number }) }), _jsxs(Div, { children: [_jsxs(Heading, { level: 3, className: "mb-1", weight: "semibold", children: [icon, " ", stepTitle] }), _jsx(Text, { variant: "secondary", size: "sm", className: "leading-relaxed", children: text })] })] }, number))) }), details.length > 0 && (_jsxs(_Fragment, { children: [detailsSectionTitle && (_jsx(Heading, { level: 2, className: "mb-6", children: detailsSectionTitle })), _jsx(Grid, { className: "grid-cols-1 sm:grid-cols-2 xl:grid-cols-2 2xl:grid-cols-3 mb-12", children: details.map(({ title: dt, text: dx }) => (_jsxs(Div, { className: `${themed.bgSecondary} border ${themed.border} rounded-xl p-5`, children: [_jsx(Heading, { level: 3, className: "mb-2", weight: "semibold", children: dt }), _jsx(Text, { variant: "secondary", size: "sm", className: "leading-relaxed", children: dx })] }, dt))) })] })), renderFooter?.()] })] }));
|
|
10
10
|
}
|
|
@@ -9,7 +9,7 @@ const STEP_DELAYS = ["delay-0", "delay-150", "delay-300", "delay-[450ms]"];
|
|
|
9
9
|
// --- Single step card ---------------------------------------------------------
|
|
10
10
|
function StepCard({ step, visible, delayClass, }) {
|
|
11
11
|
const { badgeBg = "bg-primary", iconColor = "text-primary", iconBg = "bg-primary/5 dark:bg-primary/10", } = step;
|
|
12
|
-
return (_jsxs(
|
|
12
|
+
return (_jsxs(Div, { className: [
|
|
13
13
|
"relative rounded-3xl p-8",
|
|
14
14
|
"bg-[var(--appkit-color-surface)]",
|
|
15
15
|
"shadow-md group hover:-translate-y-2 hover:shadow-xl",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { normalizeError } from "../../../errors/normalize";
|
|
4
4
|
import { useState } from "react";
|
|
5
|
-
import { Button, Div, Heading, Span, Text
|
|
5
|
+
import { Button, Div, Heading, Span, Text } from "../../../ui";
|
|
6
6
|
import { DynamicBgDiv } from "../../../ui/components/DynamicBgDiv";
|
|
7
7
|
import { Form } from "../../../ui/components/Form";
|
|
8
8
|
import { FieldInput } from "../../../ui/forms/FieldInput";
|
|
@@ -10,7 +10,7 @@ function SecurityCard({ item, visible, delayClass, }) {
|
|
|
10
10
|
const colorClass = item.colorClass ??
|
|
11
11
|
"bg-primary/5 border-primary/20 dark:bg-primary/10 dark:border-primary/30";
|
|
12
12
|
const iconColorClass = item.iconColorClass ?? "text-primary";
|
|
13
|
-
return (_jsxs(
|
|
13
|
+
return (_jsxs(Div, { className: [
|
|
14
14
|
"rounded-xl border p-5 transition-all duration-500",
|
|
15
15
|
colorClass,
|
|
16
16
|
delayClass,
|
|
@@ -7,5 +7,5 @@ const __P = {
|
|
|
7
7
|
// --- Section -----------------------------------------------------------------
|
|
8
8
|
export function SiteFeaturesSection({ title, subtitle, features, className = "", }) {
|
|
9
9
|
const themed = { textPrimary: THEMED_TEXT_PRIMARY, textSecondary: THEMED_TEXT_SECONDARY };
|
|
10
|
-
return (_jsx(Section, { className: `${__P.p8} ${className}`, surface: "subtle", children: _jsxs(Div, { className: "w-full", children: [_jsxs(Div, { className: "text-center mb-12", children: [_jsx(Heading, { level: 2, className: `${themed.textPrimary} mb-3`, size: "3xl", mdSize: "4xl", weight: "bold", children: title }), subtitle && (_jsx(Text, { className: `${themed.textSecondary} max-w-2xl mx-auto`, size: "base", children: subtitle }))] }), _jsx(Grid, { gap: "section", className: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4", children: features.map((feature) => (_jsxs(
|
|
10
|
+
return (_jsx(Section, { className: `${__P.p8} ${className}`, surface: "subtle", children: _jsxs(Div, { className: "w-full", children: [_jsxs(Div, { className: "text-center mb-12", children: [_jsx(Heading, { level: 2, className: `${themed.textPrimary} mb-3`, size: "3xl", mdSize: "4xl", weight: "bold", children: title }), subtitle && (_jsx(Text, { className: `${themed.textSecondary} max-w-2xl mx-auto`, size: "base", children: subtitle }))] }), _jsx(Grid, { gap: "section", className: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4", children: features.map((feature) => (_jsxs(Div, { className: "p-6 text-center hover:shadow-lg transition-all group rounded-2xl bg-[var(--appkit-color-surface)] border border-zinc-100 border-[var(--appkit-color-border-subtle)]", children: [_jsx(Div, { className: "text-[3.75rem] mb-4 group-hover:scale-110 transition-transform", children: feature.icon }), _jsx(Heading, { level: 3, className: `${themed.textPrimary} mb-2`, size: "base", weight: "bold", children: feature.title }), _jsx(Text, { className: `${themed.textSecondary}`, size: "base", children: feature.description })] }, feature.id))) })] }) }));
|
|
11
11
|
}
|
|
@@ -6,7 +6,7 @@ import { Div, Grid, Heading, Row, Section, Span, Text } from "../../../ui";
|
|
|
6
6
|
const CARD_DELAYS = ["delay-0", "delay-100", "delay-200", "delay-300", "delay-[400ms]", "delay-500"];
|
|
7
7
|
// --- Single cards-variant card -----------------------------------------------
|
|
8
8
|
function TrustFeatureCard({ item, visible, delayClass, }) {
|
|
9
|
-
return (_jsxs(
|
|
9
|
+
return (_jsxs(Div, { className: [
|
|
10
10
|
"flex flex-col items-center text-center p-4",
|
|
11
11
|
"transition-all duration-500",
|
|
12
12
|
delayClass,
|
|
@@ -7,5 +7,5 @@ const __P = {
|
|
|
7
7
|
// --- Section -----------------------------------------------------------------
|
|
8
8
|
export function TrustIndicatorsSection({ items, className = "", }) {
|
|
9
9
|
const themed = { textPrimary: THEMED_TEXT_PRIMARY, textSecondary: THEMED_TEXT_SECONDARY };
|
|
10
|
-
return (_jsx(Section, { className: `${__P.p6} ${className}`, surface: "subtle", children: _jsx(Div, { className: "w-full", children: _jsx(Grid, { gap: "section", className: "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-4 2xl:grid-cols-4", children: items.map((indicator, index) => (_jsxs(
|
|
10
|
+
return (_jsx(Section, { className: `${__P.p6} ${className}`, surface: "subtle", children: _jsx(Div, { className: "w-full", children: _jsx(Grid, { gap: "section", className: "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-4 2xl:grid-cols-4", children: items.map((indicator, index) => (_jsxs(Div, { className: "text-center p-4 rounded-2xl bg-[var(--appkit-color-surface)] border border-zinc-100 border-[var(--appkit-color-border-subtle)] hover:shadow-md transition-shadow", children: [_jsx(Div, { className: "text-[2.25rem] md:text-[3rem] mb-2 md:mb-3", children: indicator.icon }), _jsx(Heading, { level: 3, className: `${themed.textPrimary} mb-1 md:mb-2`, size: "sm", weight: "semibold", children: indicator.title }), _jsx(Text, { className: `${themed.textSecondary}`, size: "xs", children: indicator.description })] }, index))) }) }) }));
|
|
11
11
|
}
|
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* BottomActions Component
|
|
5
|
+
*
|
|
6
|
+
* A fixed-bottom mobile action bar rendered **above** BottomNavbar (bottom-14).
|
|
7
|
+
* Reads from `BottomActionsContext` — features register their actions via the
|
|
8
|
+
* `useBottomActions` hook; this component just renders whatever is registered.
|
|
9
|
+
*
|
|
10
|
+
* Two modes:
|
|
11
|
+
* - **Page mode** — shows registered page-level actions inline (Add to Cart,
|
|
12
|
+
* Buy Now, Place Bid, Proceed to Checkout, etc.) with an optional info label.
|
|
13
|
+
* - **Bulk mode** — activates when sieveFilter("bulk.selectedCount", SIEVE_OP.GT, "0"); shows:
|
|
14
|
+
* • Selection count pill on the left (tap to deselect all)
|
|
15
|
+
* • An upward-opening type-picker dropdown (middle, flex-1) — tap to
|
|
16
|
+
* choose WHICH action to run; the chosen label is always visible.
|
|
17
|
+
* • An "Apply" submit button on the right — executes the selected action,
|
|
18
|
+
* styled with the selected action's variant (danger = red, etc.).
|
|
19
|
+
*
|
|
20
|
+
* Layout rules:
|
|
21
|
+
* - Hidden on lg+ screens (`lg:hidden`) — desktop shows inline action panels.
|
|
22
|
+
* - The bar slides up with a 300 ms ease-out transition; `pointer-events-none`
|
|
23
|
+
* while off-screen.
|
|
24
|
+
*
|
|
25
|
+
* @component
|
|
26
|
+
* @example
|
|
27
|
+
* // Automatically rendered by LayoutClient — no manual usage required.
|
|
28
|
+
* // Features use `useBottomActions` to register their actions.
|
|
29
|
+
*/
|
|
3
30
|
import { useState, useRef, useEffect } from "react";
|
|
4
31
|
import { X, ChevronUp, ChevronDown, Check } from "lucide-react";
|
|
5
32
|
import { useBottomActionsContext } from "./BottomActionsContext";
|
|
@@ -13,7 +40,7 @@ const FLEX_CENTER = "flex items-center justify-center";
|
|
|
13
40
|
const CLS_COUNT_BADGE = "bg-error-surface text-white";
|
|
14
41
|
// ─── Sub-components ───────────────────────────────────────────────────────────
|
|
15
42
|
function BulkPickerPanel({ bulkActions, selectedActionId, pickerOpen, onSelect, }) {
|
|
16
|
-
return (_jsx(
|
|
43
|
+
return (_jsx(Div, { role: "listbox", "aria-label": "Bulk actions", className: [
|
|
17
44
|
"absolute bottom-full left-0 right-0 overflow-hidden",
|
|
18
45
|
BOTTOM_NAV_BG,
|
|
19
46
|
"border-t border-zinc-200/80 border-[var(--appkit-color-border)]/80",
|
|
@@ -91,7 +118,7 @@ export default function BottomActions() {
|
|
|
91
118
|
bulkCallbacksRef.current.get(selectedActionId)?.();
|
|
92
119
|
setPickerOpen(false);
|
|
93
120
|
};
|
|
94
|
-
return (_jsxs(
|
|
121
|
+
return (_jsxs(Div, { ref: containerRef, role: "toolbar", "aria-label": isBulkMode ? "Bulk actions" : "Page actions", "aria-hidden": !isVisible, className: [
|
|
95
122
|
"fixed bottom-14 left-0 right-0 lg:hidden",
|
|
96
123
|
Z_BOTTOM_ACTIONS,
|
|
97
124
|
BOTTOM_NAV_BG,
|
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BottomActionsContext
|
|
3
|
+
*
|
|
4
|
+
* Provides a context for registering page-level mobile action bars.
|
|
5
|
+
* Features call `useBottomActions` to push actions; the `<BottomActions>`
|
|
6
|
+
* layout component reads this context and renders the bar above BottomNavbar.
|
|
7
|
+
*
|
|
8
|
+
* Supports two modes:
|
|
9
|
+
* - Page mode: primary page actions (Add to Cart, Buy Now, Place Bid, etc.)
|
|
10
|
+
* - Bulk mode: activated when sieveFilter("bulk.selectedCount", SIEVE_OP.GT, "0") — shows selection
|
|
11
|
+
* count + custom bulk action buttons (Delete, Archive, Export, etc.)
|
|
12
|
+
*
|
|
13
|
+
* @example — product detail page
|
|
14
|
+
* ```tsx
|
|
15
|
+
* useBottomActions({
|
|
16
|
+
* actions: [
|
|
17
|
+
* { id: "wishlist", icon: <Heart className="w-4 h-4" />, label: t("wishlist"), variant: "ghost", grow: false, onClick: handleWishlist },
|
|
18
|
+
* { id: "cart", label: t("addToCart"), variant: "outline", onClick: handleAddToCart },
|
|
19
|
+
* { id: "buy", label: t("buyNow"), variant: "primary", onClick: handleBuyNow },
|
|
20
|
+
* ],
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example — admin listing with bulk select
|
|
25
|
+
* ```tsx
|
|
26
|
+
* useBottomActions({
|
|
27
|
+
* bulk: {
|
|
28
|
+
* selectedCount: selectedIds.length,
|
|
29
|
+
* onClearSelection: () => setSelectedIds([]),
|
|
30
|
+
* actions: [
|
|
31
|
+
* { id: "delete", label: t("bulkDelete", { count: selectedIds.length }), variant: "danger", onClick: handleBulkDelete },
|
|
32
|
+
* ],
|
|
33
|
+
* },
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
1
37
|
import React from "react";
|
|
2
38
|
import type { ButtonProps } from "../../ui";
|
|
3
39
|
export interface BottomAction {
|
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* BottomActionsContext
|
|
5
|
+
*
|
|
6
|
+
* Provides a context for registering page-level mobile action bars.
|
|
7
|
+
* Features call `useBottomActions` to push actions; the `<BottomActions>`
|
|
8
|
+
* layout component reads this context and renders the bar above BottomNavbar.
|
|
9
|
+
*
|
|
10
|
+
* Supports two modes:
|
|
11
|
+
* - Page mode: primary page actions (Add to Cart, Buy Now, Place Bid, etc.)
|
|
12
|
+
* - Bulk mode: activated when sieveFilter("bulk.selectedCount", SIEVE_OP.GT, "0") — shows selection
|
|
13
|
+
* count + custom bulk action buttons (Delete, Archive, Export, etc.)
|
|
14
|
+
*
|
|
15
|
+
* @example — product detail page
|
|
16
|
+
* ```tsx
|
|
17
|
+
* useBottomActions({
|
|
18
|
+
* actions: [
|
|
19
|
+
* { id: "wishlist", icon: <Heart className="w-4 h-4" />, label: t("wishlist"), variant: "ghost", grow: false, onClick: handleWishlist },
|
|
20
|
+
* { id: "cart", label: t("addToCart"), variant: "outline", onClick: handleAddToCart },
|
|
21
|
+
* { id: "buy", label: t("buyNow"), variant: "primary", onClick: handleBuyNow },
|
|
22
|
+
* ],
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @example — admin listing with bulk select
|
|
27
|
+
* ```tsx
|
|
28
|
+
* useBottomActions({
|
|
29
|
+
* bulk: {
|
|
30
|
+
* selectedCount: selectedIds.length,
|
|
31
|
+
* onClearSelection: () => setSelectedIds([]),
|
|
32
|
+
* actions: [
|
|
33
|
+
* { id: "delete", label: t("bulkDelete", { count: selectedIds.length }), variant: "danger", onClick: handleBulkDelete },
|
|
34
|
+
* ],
|
|
35
|
+
* },
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
3
39
|
import { createContext, useCallback, useContext, useMemo, useRef, useState, } from "react";
|
|
4
40
|
const EMPTY = { actions: [] };
|
|
5
41
|
const BottomActionsContext = createContext(null);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback } from "react";
|
|
4
4
|
import { Package } from "lucide-react";
|
|
5
|
-
import { BaseListingCard, Button, Caption, Row, Span, Stack, StatusBadge, Text, TextLink } from "../../../ui";
|
|
5
|
+
import { BaseListingCard, Button, Caption, Row, Span, Stack, StatusBadge, Text, TextLink, Div } from "../../../ui";
|
|
6
6
|
import { formatCurrency, formatDate } from "../../../utils";
|
|
7
7
|
import { OrderStatusValues } from "../schemas";
|
|
8
8
|
import { useLongPress } from "../../../react/hooks/useLongPress";
|
|
@@ -48,7 +48,7 @@ export function MarketplaceOrderCard({ order, links, labels, className = "", var
|
|
|
48
48
|
const longPress = useLongPress(() => onSelect?.(orderId, !isSelected));
|
|
49
49
|
const isListVariant = variant === "list";
|
|
50
50
|
const itemCount = order.items?.length ?? 0;
|
|
51
|
-
return (_jsxs(
|
|
51
|
+
return (_jsxs(Div, { className: `group relative overflow-hidden rounded-xl border border-zinc-200 bg-[var(--appkit-color-surface)] transition-all duration-200 hover:shadow-md border-[var(--appkit-color-border-subtle)] bg-[var(--appkit-color-surface)] ${isSelected ? "ring-2 ring-primary-500 dark:ring-primary-400" : ""} ${className}`, onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, "data-section": "marketplaceordercard-div-411", children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: handleSelect, label: isSelected ? "Deselect order" : "Select order", position: "top-2 left-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsxs(Div, { className: `flex gap-4 p-4 ${isListVariant ? "flex-row items-center justify-between" : "flex-col"}`, "data-section": "marketplaceordercard-div-412", children: [_jsxs(Div, { className: `flex items-start gap-3 ${selectable ? "pl-8" : ""} ${isListVariant ? "min-w-0 flex-1" : ""}`, "data-section": "marketplaceordercard-div-413", children: [_jsx(Row, { className: "h-10 w-10 flex-shrink-0", surface: "subtle", align: "center", justify: "center", rounded: "lg", children: _jsx(Package, { className: "h-5 w-5 text-[var(--appkit-color-text-muted)] text-[var(--appkit-color-text-muted)]" }) }), _jsxs(Stack, { className: "min-w-0", gap: "xs", children: [_jsx(TextLink, { href: detailHref, className: "leading-tight", children: _jsx(Text, { weight: "semibold", className: "truncate", children: order.productTitle ?? shortId }) }), _jsxs(Caption, { className: "font-mono", children: [mergedLabels.orderNumber, " ", shortId] }), _jsxs(Caption, { children: [mergedLabels.placedOn, " ", formatDate(order.orderDate)] }), itemCount > 1 && (_jsxs(Caption, { children: [mergedLabels.items, ": ", _jsx(Span, { weight: "medium", children: itemCount })] }))] })] }), _jsxs(Div, { className: `flex ${isListVariant ? "flex-shrink-0 items-center gap-4" : "flex-col gap-3"}`, "data-section": "marketplaceordercard-div-416", children: [_jsxs(Div, { className: `flex ${isListVariant ? "items-center gap-4" : "flex-wrap items-center justify-between gap-3"}`, "data-section": "marketplaceordercard-div-417", children: [_jsx(StatusBadge, { status: status, label: statusLabel }), _jsx(Text, { weight: "semibold", className: "tabular-nums", children: formatCurrency(order.totalPrice, order.currency) })] }), _jsxs(Row, { align: "center", gap: "sm", wrap: true, children: [(isShipped || isDelivered) &&
|
|
52
52
|
trackHref &&
|
|
53
53
|
order.trackingNumber && (_jsx(Button, { variant: "ghost", size: "sm", className: CLS_ACTION_BUTTON, onClick: () => navigate(trackHref), children: mergedLabels.trackOrder })), isDelivered && reviewHref && (_jsx(Button, { variant: "outline", size: "sm", className: CLS_ACTION_BUTTON, onClick: () => navigate(reviewHref), children: mergedLabels.writeReview })), _jsx(Button, { variant: "secondary", size: "sm", className: CLS_ACTION_BUTTON, onClick: () => navigate(detailHref), children: mergedLabels.viewOrder })] })] })] })] }));
|
|
54
54
|
}
|
|
@@ -521,8 +521,8 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
521
521
|
bin: string;
|
|
522
522
|
}>>;
|
|
523
523
|
}, "strip", z.ZodTypeAny, {
|
|
524
|
-
status: "cancelled" | "pending" | "processing" | "refunded" | "confirmed" | "shipped" | "delivered" | "return_requested" | "returned";
|
|
525
524
|
currency: string;
|
|
525
|
+
status: "cancelled" | "pending" | "processing" | "refunded" | "confirmed" | "shipped" | "delivered" | "return_requested" | "returned";
|
|
526
526
|
createdAt: string | Date | z.objectOutputType<{
|
|
527
527
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
528
528
|
}, z.ZodTypeAny, "passthrough">;
|
|
@@ -666,8 +666,8 @@ export declare const orderFirestoreSchema: z.ZodObject<{
|
|
|
666
666
|
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
667
667
|
shippingProofUploadedBy?: string | undefined;
|
|
668
668
|
}, {
|
|
669
|
-
status: "cancelled" | "pending" | "processing" | "refunded" | "confirmed" | "shipped" | "delivered" | "return_requested" | "returned";
|
|
670
669
|
currency: string;
|
|
670
|
+
status: "cancelled" | "pending" | "processing" | "refunded" | "confirmed" | "shipped" | "delivered" | "return_requested" | "returned";
|
|
671
671
|
createdAt: string | Date | z.objectInputType<{
|
|
672
672
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
673
673
|
}, z.ZodTypeAny, "passthrough">;
|
|
@@ -150,8 +150,8 @@ export declare const payoutFirestoreSchema: z.ZodObject<{
|
|
|
150
150
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
151
151
|
}, z.ZodTypeAny, "passthrough">>]>>;
|
|
152
152
|
}, "strip", z.ZodTypeAny, {
|
|
153
|
-
status: "pending" | "paid" | "failed" | "processing";
|
|
154
153
|
currency: string;
|
|
154
|
+
status: "pending" | "paid" | "failed" | "processing";
|
|
155
155
|
storeId: string;
|
|
156
156
|
createdAt: string | Date | z.objectOutputType<{
|
|
157
157
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
@@ -200,8 +200,8 @@ export declare const payoutFirestoreSchema: z.ZodObject<{
|
|
|
200
200
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
201
201
|
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
202
202
|
}, {
|
|
203
|
-
status: "pending" | "paid" | "failed" | "processing";
|
|
204
203
|
currency: string;
|
|
204
|
+
status: "pending" | "paid" | "failed" | "processing";
|
|
205
205
|
storeId: string;
|
|
206
206
|
createdAt: string | Date | z.objectInputType<{
|
|
207
207
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
@@ -289,8 +289,8 @@ export declare const paymentRecordSchema: z.ZodObject<{
|
|
|
289
289
|
status: z.ZodDefault<z.ZodEnum<["pending", "authorized", "captured", "failed", "refunded", "partially_refunded"]>>;
|
|
290
290
|
createdAt: z.ZodOptional<z.ZodString>;
|
|
291
291
|
}, "strip", z.ZodTypeAny, {
|
|
292
|
-
status: "pending" | "failed" | "captured" | "authorized" | "refunded" | "partially_refunded";
|
|
293
292
|
currency: string;
|
|
293
|
+
status: "pending" | "failed" | "captured" | "authorized" | "refunded" | "partially_refunded";
|
|
294
294
|
id: string;
|
|
295
295
|
amount: number;
|
|
296
296
|
orderId: string;
|
|
@@ -302,8 +302,8 @@ export declare const paymentRecordSchema: z.ZodObject<{
|
|
|
302
302
|
amount: number;
|
|
303
303
|
orderId: string;
|
|
304
304
|
gateway: "bank_transfer" | "upi" | "razorpay" | "stripe" | "paypal" | "cod" | "whatsapp";
|
|
305
|
-
status?: "pending" | "failed" | "captured" | "authorized" | "refunded" | "partially_refunded" | undefined;
|
|
306
305
|
currency?: string | undefined;
|
|
306
|
+
status?: "pending" | "failed" | "captured" | "authorized" | "refunded" | "partially_refunded" | undefined;
|
|
307
307
|
createdAt?: string | undefined;
|
|
308
308
|
gatewayPaymentId?: string | undefined;
|
|
309
309
|
}>;
|
|
@@ -32,5 +32,5 @@ export function BidHistory({ isLoading = false, isEmpty = false, renderList, ren
|
|
|
32
32
|
}
|
|
33
33
|
if (renderList)
|
|
34
34
|
return _jsx(Div, { className: className, children: renderList() });
|
|
35
|
-
return (_jsxs(Div, { className: className, children: [labels.title && (_jsx(Heading, { level: 3, className: "mb-3 tracking-wide", color: "muted", size: "sm", weight: "semibold", transform: "uppercase", children: labels.title })), _jsx(Stack, { gap: "sm", children: bids.map((bid, i) => renderBid ? (_jsx(React.Fragment, { children: renderBid(bid, i) }, bid.id)) : (_jsxs(
|
|
35
|
+
return (_jsxs(Div, { className: className, children: [labels.title && (_jsx(Heading, { level: 3, className: "mb-3 tracking-wide", color: "muted", size: "sm", weight: "semibold", transform: "uppercase", children: labels.title })), _jsx(Stack, { gap: "sm", children: bids.map((bid, i) => renderBid ? (_jsx(React.Fragment, { children: renderBid(bid, i) }, bid.id)) : (_jsxs(Div, { className: "flex items-center justify-between rounded-lg border border-[var(--appkit-color-border-subtle)] bg-[var(--appkit-color-surface)] p-3 text-sm", "data-section": "bidhistory-div-422", children: [_jsx(Span, { weight: "bold", className: "text-primary-600 dark:text-primary-400", children: currency ? formatCurrency(bid.amount, currency) : bid.amount.toLocaleString() }), _jsx(Span, { size: "xs", color: "muted", children: formatBidDate(bid.placedAt) })] }, bid.id))) })] }));
|
|
36
36
|
}
|
|
@@ -51,6 +51,6 @@ export function MarketplaceBundleCard({ bundle, className = "", variant = "grid"
|
|
|
51
51
|
? "opacity-100"
|
|
52
52
|
: "opacity-0 group-hover:opacity-100 transition-opacity" }))] }), _jsxs(BaseListingCard.Info, { variant: variant, children: [_jsx(TextLink, { href: String(detailHref), children: _jsx(Text, { size: "sm", weight: "medium", color: "primary", truncate: 2, children: bundle.name }) }), _jsxs(Row, { justify: "between", className: "mt-1", gap: "sm", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: price
|
|
53
53
|
? formatCurrency(price / 100, getDefaultCurrency())
|
|
54
|
-
: "—" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "xs", children: mergedLabels.itemsLabel(memberCount) })] }), _jsx(
|
|
54
|
+
: "—" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "xs", children: mergedLabels.itemsLabel(memberCount) })] }), _jsx(Div, { className: CLS_VIEW_BTN, role: "button", tabIndex: 0, onClick: handleNavigate, onKeyDown: (e) => { if (e.key === "Enter" || e.key === " ")
|
|
55
55
|
handleNavigate(); }, children: "View Bundle" })] })] }));
|
|
56
56
|
}
|
|
@@ -20,7 +20,7 @@ export function ProductGalleryClient({ images, productName }) {
|
|
|
20
20
|
return (_jsx(Div, { className: `${__O.hidden}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsx(Row, { className: "aspect-square text-[var(--appkit-color-border)] dark:text-[var(--appkit-color-border-subtle)]", align: "center", justify: "center", children: _jsx(PlaceholderSvg, {}) }) }));
|
|
21
21
|
}
|
|
22
22
|
const mainImage = images[activeIndex] ?? images[0];
|
|
23
|
-
return (_jsxs(Stack, { gap: "3", children: [_jsx(
|
|
23
|
+
return (_jsxs(Stack, { gap: "3", children: [_jsx(Div, { className: "overflow-hidden rounded-xl border border-[var(--appkit-color-border-subtle)] cursor-zoom-in aspect-square w-full", onClick: () => setLightboxIndex(activeIndex), role: "button", tabIndex: 0, onKeyDown: (e) => {
|
|
24
24
|
if (e.key === "Enter" || e.key === " ")
|
|
25
25
|
setLightboxIndex(activeIndex);
|
|
26
26
|
}, "aria-label": `View ${productName ?? "product"} image in full screen`, children: _jsx(MediaImage, { src: mainImage, alt: productName ? `${productName} — image ${activeIndex + 1}` : `Product image ${activeIndex + 1}`, size: "gallery", className: "transition-transform duration-300 hover:scale-105" }) }), images.length > 1 && (_jsx(Div, { layout: "flex", gap: "2", className: `${__O.xAuto}`, padding: "b-2xs", children: images.map((src, i) => (_jsx("button", { type: "button", onClick: () => setActiveIndex(i), className: `flex-shrink-0 h-16 w-16 overflow-hidden rounded-lg border-2 transition-all${i === activeIndex
|
|
@@ -19,7 +19,7 @@ function MemberThumb({ member, isCurrent }) {
|
|
|
19
19
|
const image = member.images?.[0] ?? "";
|
|
20
20
|
const href = memberHref(member);
|
|
21
21
|
const price = formatCurrency(member.price, member.currency ?? "INR");
|
|
22
|
-
return (_jsxs(Link, { href: href, "aria-label": member.title, className: "flex flex-col items-center gap-1.5 flex-shrink-0 w-16 group", children: [_jsxs(
|
|
22
|
+
return (_jsxs(Link, { href: href, "aria-label": member.title, className: "flex flex-col items-center gap-1.5 flex-shrink-0 w-16 group", children: [_jsxs(Div, { className: `relative w-14 h-14 rounded-full overflow-hidden border-2 transition-all ${isCurrent
|
|
23
23
|
? "border-[var(--appkit-color-primary)] ring-2 ring-[var(--appkit-color-primary)]/30"
|
|
24
24
|
: "border-[var(--appkit-color-border)] group-hover:border-[var(--appkit-color-primary)]"}`, children: [_jsx(MediaImage, { src: image, alt: member.title, size: "card" }), member.isGroupParent && (_jsx(Span, { color: "inverse", rounded: "sm", className: "absolute bottom-0 right-0 bg-[var(--appkit-color-primary)] text-[8px] leading-none px-[0.25rem] py-[0.125rem]", children: "Set" }))] }), _jsx(Text, { className: "text-[10px] leading-tight line-clamp-2 w-full", color: "muted", align: "center", children: member.title }), _jsx(Text, { className: "text-[10px]", color: "primary", weight: "semibold", children: price })] }));
|
|
25
25
|
}
|
|
@@ -19,7 +19,7 @@ function ListingThumb({ listing, isCurrent, }) {
|
|
|
19
19
|
const image = listing.images?.[0] ?? listing.mainImage ?? "";
|
|
20
20
|
const href = getHref(listing);
|
|
21
21
|
const price = formatCurrency(listing.price, listing.currency ?? "INR");
|
|
22
|
-
return (_jsxs(Link, { href: href, "aria-label": listing.title, className: "flex flex-col items-center gap-1.5 flex-shrink-0 w-16 group", children: [_jsx(
|
|
22
|
+
return (_jsxs(Link, { href: href, "aria-label": listing.title, className: "flex flex-col items-center gap-1.5 flex-shrink-0 w-16 group", children: [_jsx(Div, { className: `w-14 h-14 rounded-full overflow-hidden border-2 transition-all ${isCurrent
|
|
23
23
|
? "border-[var(--appkit-color-primary)] ring-2 ring-[var(--appkit-color-primary)]/30"
|
|
24
24
|
: "border-[var(--appkit-color-border)] group-hover:border-[var(--appkit-color-primary)]"}`, children: image ? (
|
|
25
25
|
// eslint-disable-next-line @next/next/no-img-element
|
|
@@ -4,7 +4,7 @@ import { DatabaseError } from "../../../errors";
|
|
|
4
4
|
import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
|
|
5
5
|
import { cacheManager } from "../../../core";
|
|
6
6
|
import { generateUniqueId, slugify, buildSearchTokens, tokenizeQuery, generateBarcodeId } from "../../../utils";
|
|
7
|
-
import { PRODUCT_COLLECTION, ProductStatusValues
|
|
7
|
+
import { PRODUCT_COLLECTION, ProductStatusValues } from "../schemas";
|
|
8
8
|
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
9
9
|
/**
|
|
10
10
|
* Canonical listing-kind tokens used in `listingType`. Note: the public Sieve
|
|
@@ -22,7 +22,7 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
|
|
|
22
22
|
isActive: z.ZodBoolean;
|
|
23
23
|
displayOrder: z.ZodNumber;
|
|
24
24
|
}, "strip", z.ZodTypeAny, {
|
|
25
|
-
category: "
|
|
25
|
+
category: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform";
|
|
26
26
|
label: string;
|
|
27
27
|
scope: "store" | "platform";
|
|
28
28
|
icon: string;
|
|
@@ -33,7 +33,7 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
|
|
|
33
33
|
description?: string | undefined;
|
|
34
34
|
iconColor?: string | undefined;
|
|
35
35
|
}, {
|
|
36
|
-
category: "
|
|
36
|
+
category: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform";
|
|
37
37
|
label: string;
|
|
38
38
|
scope: "store" | "platform";
|
|
39
39
|
icon: string;
|
|
@@ -55,7 +55,7 @@ export declare const productFeatureStoreCreateSchema: z.ZodObject<{
|
|
|
55
55
|
isActive: z.ZodBoolean;
|
|
56
56
|
displayOrder: z.ZodNumber;
|
|
57
57
|
}, "strip", z.ZodTypeAny, {
|
|
58
|
-
category: "
|
|
58
|
+
category: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform";
|
|
59
59
|
label: string;
|
|
60
60
|
icon: string;
|
|
61
61
|
isActive: boolean;
|
|
@@ -64,7 +64,7 @@ export declare const productFeatureStoreCreateSchema: z.ZodObject<{
|
|
|
64
64
|
description?: string | undefined;
|
|
65
65
|
iconColor?: string | undefined;
|
|
66
66
|
}, {
|
|
67
|
-
category: "
|
|
67
|
+
category: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform";
|
|
68
68
|
label: string;
|
|
69
69
|
icon: string;
|
|
70
70
|
isActive: boolean;
|
|
@@ -84,7 +84,7 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
|
|
|
84
84
|
isActive: z.ZodOptional<z.ZodBoolean>;
|
|
85
85
|
displayOrder: z.ZodOptional<z.ZodNumber>;
|
|
86
86
|
}, "strip", z.ZodTypeAny, {
|
|
87
|
-
category?: "
|
|
87
|
+
category?: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform" | undefined;
|
|
88
88
|
description?: string | undefined;
|
|
89
89
|
label?: string | undefined;
|
|
90
90
|
icon?: string | undefined;
|
|
@@ -93,7 +93,7 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
|
|
|
93
93
|
iconColor?: string | undefined;
|
|
94
94
|
productTypes?: ("auction" | "prize-draw" | "classified" | "digital-code" | "live" | "all" | "product" | "preorder")[] | undefined;
|
|
95
95
|
}, {
|
|
96
|
-
category?: "
|
|
96
|
+
category?: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform" | undefined;
|
|
97
97
|
description?: string | undefined;
|
|
98
98
|
label?: string | undefined;
|
|
99
99
|
icon?: string | undefined;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
|
|
9
9
|
import { normalizeError } from "../../../errors/normalize";
|
|
10
|
-
import { CLAIMED_COUPONS_COLLECTION, createClaimedCouponId
|
|
10
|
+
import { CLAIMED_COUPONS_COLLECTION, createClaimedCouponId } from "../schemas";
|
|
11
11
|
import { DatabaseError } from "../../../errors";
|
|
12
12
|
import { COUPON_USAGE_FIELDS } from "../../../constants/field-names";
|
|
13
13
|
export class ClaimedCouponsRepository extends BaseRepository {
|
|
@@ -28,5 +28,5 @@ export function ScamAwarenessModal({ isOpen, onAcknowledged }) {
|
|
|
28
28
|
onAcknowledged();
|
|
29
29
|
},
|
|
30
30
|
});
|
|
31
|
-
return (_jsx(Modal, { isOpen: isOpen, onClose: () => { }, showCloseButton: false, size: "lg", title: _jsxs(Row, { gap: "sm", align: "center", children: [_jsx(Shield, { className: "h-5 w-5 text-[color:var(--appkit-color-warning,theme(colors.amber.500))]" }), _jsx(Span, { children: "Before you start \u2014 Stay Safe on LetItRip" })] }), actions: _jsx(Row, { gap: "sm", justify: "end", className: "w-full", children: _jsx("button", { className: "appkit-button appkit-button--primary appkit-button--md", disabled: !checked || mutation.isPending, onClick: () => mutation.mutate(), children: mutation.isPending ? "Saving…" : "Continue to LetItRip →" }) }), children: _jsxs(Stack, { gap: "md", children: [_jsx(Text, { variant: "secondary", size: "sm", children: "LetItRip connects you with verified sellers, but collectibles markets attract scams. Take 60 seconds to learn the most common patterns \u2014 it could save your money." }), _jsx(Div, { layout: "grid", gap: "3", className: "grid-cols-1 sm:grid-cols-2", children: SCAM_CATEGORIES.map((cat) => (_jsxs(
|
|
31
|
+
return (_jsx(Modal, { isOpen: isOpen, onClose: () => { }, showCloseButton: false, size: "lg", title: _jsxs(Row, { gap: "sm", align: "center", children: [_jsx(Shield, { className: "h-5 w-5 text-[color:var(--appkit-color-warning,theme(colors.amber.500))]" }), _jsx(Span, { children: "Before you start \u2014 Stay Safe on LetItRip" })] }), actions: _jsx(Row, { gap: "sm", justify: "end", className: "w-full", children: _jsx("button", { className: "appkit-button appkit-button--primary appkit-button--md", disabled: !checked || mutation.isPending, onClick: () => mutation.mutate(), children: mutation.isPending ? "Saving…" : "Continue to LetItRip →" }) }), children: _jsxs(Stack, { gap: "md", children: [_jsx(Text, { variant: "secondary", size: "sm", children: "LetItRip connects you with verified sellers, but collectibles markets attract scams. Take 60 seconds to learn the most common patterns \u2014 it could save your money." }), _jsx(Div, { layout: "grid", gap: "3", className: "grid-cols-1 sm:grid-cols-2", children: SCAM_CATEGORIES.map((cat) => (_jsxs(Div, { className: "flex gap-3 rounded-lg border border-[color:var(--appkit-color-border,theme(colors.zinc.200))] bg-[color:var(--appkit-color-surface,theme(colors.zinc.50))] p-3", children: [_jsx(Span, { layout: "flex-center", className: "mt-0.5 h-8 w-8 shrink-0 bg-[color:var(--appkit-color-warning,theme(colors.amber.500))]/10 text-[color:var(--appkit-color-warning,theme(colors.amber.600))]", rounded: "md", children: CATEGORY_ICONS[cat.id] ?? _jsx(Shield, { className: "h-4 w-4" }) }), _jsxs(Stack, { gap: "none", children: [_jsx(Text, { weight: "semibold", size: "sm", children: cat.label }), _jsx(Text, { variant: "secondary", className: "leading-relaxed", size: "xs", children: cat.description })] })] }, cat.id))) }), _jsxs(Row, { textSize: "sm", gap: "md", wrap: true, children: [_jsx("a", { href: String(ROUTES.PUBLIC.SCAM_TYPES), target: "_blank", rel: "noopener noreferrer", className: "text-[color:var(--appkit-color-primary,theme(colors.blue.600))] hover:underline", children: "See all 27 scam types \u2192" }), _jsx("a", { href: String(ROUTES.PUBLIC.SCAM_FAQS), target: "_blank", rel: "noopener noreferrer", className: "text-[color:var(--appkit-color-primary,theme(colors.blue.600))] hover:underline", children: "Common scam FAQs \u2192" })] }), mutation.isError && (_jsx(Text, { variant: "error", size: "sm", children: "Something went wrong \u2014 please try again." })), _jsx(Checkbox, { id: "scam-awareness-ack", checked: checked, onChange: (e) => setChecked(e.target.checked), label: "I have read the above and understand the risks of buying and selling collectibles online." })] }) }));
|
|
32
32
|
}
|
|
@@ -216,7 +216,7 @@ export function Search({ isOpen, onClose, onSearch, onOpen, value, onChange, pla
|
|
|
216
216
|
if (inlineBlurRef.current)
|
|
217
217
|
clearTimeout(inlineBlurRef.current);
|
|
218
218
|
inlineBlurRef.current = setTimeout(() => setIsInlineOpen(false), 120);
|
|
219
|
-
}, placeholder: placeholder ?? labels.placeholder, className: "w-full rounded-lg border border-zinc-300 bg-[var(--appkit-color-surface)] pl-9 text-zinc-900 placeholder:text-zinc-400 focus:border-primary focus:ring-2 focus:ring-primary/20 border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] dark:text-white dark:placeholder:text-slate-500" }), query && (_jsx(Button, { rounded: "full", textColor: "faint", type: "button", variant: "ghost", onClick: handleClear, className: "absolute right-3 p-[0.125rem] hover:text-[var(--appkit-color-text-muted)] dark:hover:text-[var(--appkit-color-text)] transition-colors", "aria-label": labels.clearAriaLabel, children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }))] }), resourceTypes && resourceTypes.length > 0 && (_jsx("select", { value: selectedType, onChange: (e) => handleTypeChange(e.target.value), "aria-label": labels.resourceTypeLabel ?? "Search in", className: "flex-shrink-0 rounded-lg border border-zinc-300 bg-white px-2 py-2 text-sm text-zinc-700 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] text-[var(--appkit-color-text-muted)] cursor-pointer", children: resourceTypes.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) })), deferred && (_jsx(Button, { rounded: "lg", paddingX: "sm", paddingY: "sm", type: "button", variant: "primary", onClick: handleDeferredSubmit, "aria-label": labels.ariaLabel, className: "flex-shrink-0", children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }) })), isInlineOpen && (filteredQuickLinks.length > 0 || query) && (_jsxs(
|
|
219
|
+
}, placeholder: placeholder ?? labels.placeholder, className: "w-full rounded-lg border border-zinc-300 bg-[var(--appkit-color-surface)] pl-9 text-zinc-900 placeholder:text-zinc-400 focus:border-primary focus:ring-2 focus:ring-primary/20 border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] dark:text-white dark:placeholder:text-slate-500" }), query && (_jsx(Button, { rounded: "full", textColor: "faint", type: "button", variant: "ghost", onClick: handleClear, className: "absolute right-3 p-[0.125rem] hover:text-[var(--appkit-color-text-muted)] dark:hover:text-[var(--appkit-color-text)] transition-colors", "aria-label": labels.clearAriaLabel, children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }))] }), resourceTypes && resourceTypes.length > 0 && (_jsx("select", { value: selectedType, onChange: (e) => handleTypeChange(e.target.value), "aria-label": labels.resourceTypeLabel ?? "Search in", className: "flex-shrink-0 rounded-lg border border-zinc-300 bg-white px-2 py-2 text-sm text-zinc-700 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] text-[var(--appkit-color-text-muted)] cursor-pointer", children: resourceTypes.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) })), deferred && (_jsx(Button, { rounded: "lg", paddingX: "sm", paddingY: "sm", type: "button", variant: "primary", onClick: handleDeferredSubmit, "aria-label": labels.ariaLabel, className: "flex-shrink-0", children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }) })), isInlineOpen && (filteredQuickLinks.length > 0 || query) && (_jsxs(Div, { className: "absolute top-full left-0 right-0 mt-2 rounded-xl overflow-hidden border border-zinc-200 bg-[var(--appkit-color-surface)] shadow-lg border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] [z-index:var(--appkit-z-dropdown)]", onMouseDown: (event) => event.preventDefault(), children: [filteredQuickLinks.length > 0 && (_jsx(Ul, { children: filteredQuickLinks.map((link, index) => renderInlineQuickLink(link, index)) })), query && suggestionsLoading && (_jsx(Div, { padding: "inline", children: _jsx(Text, { variant: "secondary", size: "sm", children: labels.searching }) })), query &&
|
|
220
220
|
suggestions.slice(0, 5).map((suggestion, suggestionIndex) => {
|
|
221
221
|
const itemIndex = inlineQuickLinkItems.length + suggestionIndex;
|
|
222
222
|
const isActive = activeIndex === itemIndex;
|
|
@@ -24,8 +24,8 @@ export declare const searchProductItemSchema: z.ZodObject<{
|
|
|
24
24
|
title: string;
|
|
25
25
|
slug: string;
|
|
26
26
|
id: string;
|
|
27
|
-
status?: string | undefined;
|
|
28
27
|
currency?: string | undefined;
|
|
28
|
+
status?: string | undefined;
|
|
29
29
|
featured?: boolean | undefined;
|
|
30
30
|
listingType?: "standard" | "auction" | "pre-order" | "prize-draw" | "bundle" | undefined;
|
|
31
31
|
isPromoted?: boolean | undefined;
|
|
@@ -35,8 +35,8 @@ export declare const searchProductItemSchema: z.ZodObject<{
|
|
|
35
35
|
title: string;
|
|
36
36
|
slug: string;
|
|
37
37
|
id: string;
|
|
38
|
-
status?: string | undefined;
|
|
39
38
|
currency?: string | undefined;
|
|
39
|
+
status?: string | undefined;
|
|
40
40
|
featured?: boolean | undefined;
|
|
41
41
|
listingType?: "standard" | "auction" | "pre-order" | "prize-draw" | "bundle" | undefined;
|
|
42
42
|
isPromoted?: boolean | undefined;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* (src/actions/seller.actions.ts) alongside the other seller server actions.
|
|
10
10
|
*/
|
|
11
11
|
import type { JsonValue } from "../../../schemas/types";
|
|
12
|
-
import type { SellerPayoutDetails
|
|
12
|
+
import type { SellerPayoutDetails } from "../../auth/schemas/firestore";
|
|
13
13
|
import type { StoreDocument } from "../../stores/schemas/firestore";
|
|
14
14
|
import type { ProductDocument } from "../../products/schemas/firestore";
|
|
15
15
|
import type { OrderDocument } from "../../orders/schemas/firestore";
|
|
@@ -115,7 +115,7 @@ export declare function requestPayout(userId: string, userName: string, userEmai
|
|
|
115
115
|
export declare function bulkSellerOrder(userId: string, userRole: string, userDisplayName: string, userEmail: string, orderIds: string[]): Promise<BulkSellerOrderResult>;
|
|
116
116
|
export declare function createSellerProduct(userId: string, userName: string, userEmail: string, input: Record<string, JsonValue>): Promise<void>;
|
|
117
117
|
export declare function getSellerStore(userId: string): Promise<StoreDocument | null>;
|
|
118
|
-
export declare function getSellerShipping(userId: string): Promise<SellerShippingConfig | null>;
|
|
118
|
+
export declare function getSellerShipping(userId: string): Promise<import("../../auth").SellerShippingConfig | null>;
|
|
119
119
|
export declare function getSellerPayoutSettings(userId: string): Promise<SellerPayoutDetails | {
|
|
120
120
|
method: string;
|
|
121
121
|
isConfigured: boolean;
|
|
@@ -71,7 +71,7 @@ export function SellerCouponEditorView({ couponId, initial, onSave, onCancel, })
|
|
|
71
71
|
}
|
|
72
72
|
};
|
|
73
73
|
const isEdit = Boolean(couponId);
|
|
74
|
-
return (_jsx(Form, { onSubmit: handleSubmit, noValidate: true, children: _jsxs(Stack, { gap: "none", className: `max-w-lg mx-auto border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] ${__O.hidden}`, rounded: "xl", shadow: "sm", children: [_jsx(
|
|
74
|
+
return (_jsx(Form, { onSubmit: handleSubmit, noValidate: true, children: _jsxs(Stack, { gap: "none", className: `max-w-lg mx-auto border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] ${__O.hidden}`, rounded: "xl", shadow: "sm", children: [_jsx(Div, { className: "h-[3px] w-full [background:linear-gradient(to_right,var(--appkit-color-primary-700)_0%,var(--appkit-color-cobalt)_55%,var(--appkit-color-secondary-400)_100%)]", "aria-hidden": "true" }), _jsx(Div, { border: "bottom", paddingY: "y-md-lg", padding: "x-lg", children: _jsxs(Row, { justify: "between", gap: "3", children: [_jsx(Heading, { level: 2, className: "text-[var(--appkit-color-text)]", size: "lg", weight: "semibold", children: isEdit ? "Edit Coupon" : "Create Coupon" }), isEdit && (_jsx(Badge, { variant: draft.isActive ? "success" : "default", children: draft.isActive ? "Active" : "Inactive" }))] }) }), _jsxs(Stack, { gap: "5", padding: "lg", children: [error && (_jsx(Div, { textSize: "sm", className: "border border-error/20", color: "error", surface: "danger-surface", padding: "inline", rounded: "lg", children: error })), _jsx(Input, { label: "Coupon Code", value: draft.code, onChange: (e) => set("code", e.target.value.toUpperCase().replace(/\s+/g, "")), placeholder: "e.g. WELCOME10", required: true, disabled: isEdit, helperText: isEdit ? "Code cannot be changed after creation" : "Customers enter this at checkout" }), _jsx(Select, { label: "Discount Type", value: draft.type, options: TYPE_OPTIONS, onChange: (e) => set("type", e.target.value) }), draft.type !== "free_shipping" && (_jsx(Input, { label: draft.type === "percentage" ? "Discount Percentage (%)" : "Discount Amount (₹)", type: "number", min: 1, max: draft.type === "percentage" ? 100 : undefined, value: draft.value, onChange: (e) => set("value", e.target.value), placeholder: draft.type === "percentage" ? "e.g. 10" : "e.g. 50", required: true, helperText: draft.type === "percentage"
|
|
75
75
|
? "Enter a value between 1 and 100"
|
|
76
76
|
: "Fixed rupee discount applied to the order" })), draft.type === "percentage" && (_jsx(Input, { label: "Max Discount Cap (\u20B9, optional)", type: "number", min: 0, value: draft.maxDiscount, onChange: (e) => set("maxDiscount", e.target.value), placeholder: "Leave blank for no cap", helperText: "Maximum rupee discount regardless of percentage" })), _jsx(Input, { label: "Minimum Order Amount (\u20B9, optional)", type: "number", min: 0, value: draft.minPurchase, onChange: (e) => set("minPurchase", e.target.value), placeholder: "Leave blank for no minimum" }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", className: CLS_SECTION_LABEL, children: "Usage Limits" }), _jsxs(Div, { layout: "grid", gap: "3", className: "grid-cols-2", children: [_jsx(Input, { label: "Total Uses", type: "number", min: 0, value: draft.totalLimit, onChange: (e) => set("totalLimit", e.target.value), placeholder: "0 = unlimited" }), _jsx(Input, { label: "Per Customer", type: "number", min: 0, value: draft.perUserLimit, onChange: (e) => set("perUserLimit", e.target.value), placeholder: "0 = unlimited" })] })] }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", className: CLS_SECTION_LABEL, children: "Validity Period" }), _jsxs(Div, { layout: "grid", gap: "3", className: "grid-cols-2", children: [_jsx(Input, { label: "Start Date", type: "date", value: draft.startDate, onChange: (e) => set("startDate", e.target.value), required: true }), _jsx(Input, { label: "End Date", type: "date", value: draft.endDate, onChange: (e) => set("endDate", e.target.value), required: true })] })] }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", className: CLS_SECTION_LABEL, children: "Applicability (optional)" }), _jsxs(Stack, { gap: "sm", children: [_jsxs(Div, { children: [_jsx(Text, { size: "xs", className: "mb-1 text-[var(--appkit-color-text-secondary)]", children: "Applicable products" }), _jsx(ProductInlineSelect, { scope: "store", multiple: true, value: draft.applicableProducts, onChange: (v) => set("applicableProducts", v), placeholder: "Restrict to specific products\u2026" })] }), _jsxs(Div, { children: [_jsx(Text, { size: "xs", className: "mb-1 text-[var(--appkit-color-text-secondary)]", children: "Applicable categories" }), _jsx(CategoryInlineSelect, { value: "", onChange: (id) => {
|
|
77
77
|
if (!id || draft.applicableCategories.includes(id))
|
|
@@ -92,7 +92,7 @@ export function SellerGoogleReviewsView({ onSave, onSync, }) {
|
|
|
92
92
|
}
|
|
93
93
|
}, [onSync, showToast]);
|
|
94
94
|
if (loading) {
|
|
95
|
-
return (_jsx(Stack, { gap: "md", paddingY: "y-lg", paddingX: "x-md", children: Array.from({ length: 3 }).map((_, i) => (_jsx(
|
|
95
|
+
return (_jsx(Stack, { gap: "md", paddingY: "y-lg", paddingX: "x-md", children: Array.from({ length: 3 }).map((_, i) => (_jsx(Div, { className: "h-12 animate-pulse rounded-xl border border-zinc-100 border-[var(--appkit-color-border)] bg-zinc-50 bg-[var(--appkit-color-surface-elevated)]" }, i))) }));
|
|
96
96
|
}
|
|
97
97
|
const formattedLastSync = draft.lastSyncedAt
|
|
98
98
|
? new Date(draft.lastSyncedAt).toLocaleString("en-IN", {
|
|
@@ -358,9 +358,12 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
|
|
|
358
358
|
buildBulkAction(ACTIONS.STORE["set-location"], () => setSetLocationOpen(true), { icon: _jsx(MapPin, { className: "w-4 h-4" }) }),
|
|
359
359
|
buildBulkAction(ACTIONS.STORE["request-payout"], () => void requestPayoutForSelection(), { variant: "primary" }),
|
|
360
360
|
];
|
|
361
|
+
// useBottomActions must run unconditionally on every render — it was
|
|
362
|
+
// previously called after the `hasChildren` early return below, which
|
|
363
|
+
// skips the hook call in passthrough mode, violating the Rules of Hooks.
|
|
364
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
|
|
361
365
|
if (hasChildren) {
|
|
362
366
|
return _jsx(ListingLayout, { portal: "seller", ...props, children: children });
|
|
363
367
|
}
|
|
364
|
-
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
|
|
365
368
|
return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by order ID or buyer name", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set("sort", v); }, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx(Row, { border: "bottom", className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 backdrop-blur-sm", surface: "default", padding: "toolbar", justify: "center", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedIds.length > 0 && (_jsx(Div, { border: "default", paddingX: "x-sm-md", className: "sticky top-[calc(var(--header-height,0px)+88px)] z-20 backdrop-blur-sm border-b", surface: "default", padding: "y-xs", children: _jsx(BulkActionBar, { selectedCount: selection.selectedIds.length, onClearSelection: selection.clearSelection, actions: bulkActions }) })), _jsxs(Div, { paddingX: "x-sm-md", padding: "y-md", children: [errorMessage && (_jsx(Div, { textSize: "sm", className: "mb-4 border border-error/20", color: "error", surface: "danger-surface", padding: "inline", rounded: "xl", children: errorMessage })), _jsx(DataTable, { rows: rows, columns: columns, isLoading: isLoading, emptyLabel: "No orders yet", selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: () => selection.toggleAll(), renderRowActions: renderRowActions })] }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: _jsx(FilterChipGroup, { label: "Status", tabs: STATUS_OPTIONS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) }) }), selectedOrderId && (_jsx(OrderDetailDrawer, { orderId: selectedOrderId, apiBase: orderDetailApiBase, onClose: () => setSelectedOrderId(null) })), setLocationOpen && (_jsx(PhysicalLocationModal, { count: selection.selectedIds.length, onSave: handleSetLocation, onClose: () => setSetLocationOpen(false) }))] }));
|
|
366
369
|
}
|