@mohasinac/appkit 2.7.49 → 2.7.52
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/layout/SidebarCollapseToggle.d.ts +19 -0
- package/dist/_internal/client/features/layout/SidebarCollapseToggle.js +15 -0
- package/dist/_internal/client/features/layout/index.d.ts +2 -0
- package/dist/_internal/client/features/layout/index.js +1 -0
- package/dist/_internal/server/features/checkout/actions.js +25 -2
- package/dist/_internal/server/features/promotions/actions.js +3 -1
- package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.js +65 -0
- package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.js +163 -0
- package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.js +115 -0
- package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.js +96 -0
- package/dist/_internal/shared/actions/action-registry.js +149 -0
- package/dist/client.d.ts +45 -6
- package/dist/client.js +27 -4
- package/dist/constants/api-endpoints.d.ts +42 -0
- package/dist/constants/api-endpoints.js +14 -0
- package/dist/features/_guide-cls.d.ts +13 -0
- package/dist/features/_guide-cls.js +14 -0
- package/dist/features/about/components/HelpPageView.js +29 -26
- package/dist/features/account/components/BuyerAccountGuideView.d.ts +1 -0
- package/dist/features/account/components/BuyerAccountGuideView.js +39 -0
- package/dist/features/account/components/BuyerAuctionsGuideView.d.ts +1 -0
- package/dist/features/account/components/BuyerAuctionsGuideView.js +38 -0
- package/dist/features/account/components/BuyerOrdersGuideView.d.ts +1 -0
- package/dist/features/account/components/BuyerOrdersGuideView.js +48 -0
- package/dist/features/account/components/BuyerShoppingGuideView.d.ts +1 -0
- package/dist/features/account/components/BuyerShoppingGuideView.js +38 -0
- package/dist/features/account/components/UserSidebar.js +2 -1
- package/dist/features/admin/components/AdminAnalyticsGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminAnalyticsGuideView.js +24 -0
- package/dist/features/admin/components/AdminBlogEditorView.js +102 -75
- package/dist/features/admin/components/AdminBundleEditorView.js +20 -14
- package/dist/features/admin/components/AdminBundlesView.d.ts +1 -3
- package/dist/features/admin/components/AdminBundlesView.js +173 -52
- package/dist/features/admin/components/AdminCatalogGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminCatalogGuideView.js +28 -0
- package/dist/features/admin/components/AdminContentGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminContentGuideView.js +36 -0
- package/dist/features/admin/components/AdminCouponEditorView.js +1 -1
- package/dist/features/admin/components/AdminGuideHubView.d.ts +5 -0
- package/dist/features/admin/components/AdminGuideHubView.js +79 -0
- package/dist/features/admin/components/AdminOrdersGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminOrdersGuideView.js +44 -0
- package/dist/features/admin/components/AdminProductsView.js +8 -3
- package/dist/features/admin/components/AdminSidebar.js +2 -1
- package/dist/features/admin/components/AdminSiteConfigGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminSiteConfigGuideView.js +21 -0
- package/dist/features/admin/components/AdminStoresGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminStoresGuideView.js +32 -0
- package/dist/features/admin/components/AdminTeamGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminTeamGuideView.js +33 -0
- package/dist/features/admin/components/AdminTrustGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminTrustGuideView.js +40 -0
- package/dist/features/admin/components/AdminUsersGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminUsersGuideView.js +38 -0
- package/dist/features/auth/repository/session.repository.js +16 -1
- package/dist/features/cart/hooks/useAddToCart.d.ts +2 -0
- package/dist/features/cart/hooks/useAddToCart.js +2 -0
- package/dist/features/cart/hooks/useGuestCart.d.ts +2 -0
- package/dist/features/cart/utils/guest-cart.d.ts +7 -0
- package/dist/features/cart/utils/pending-ops.d.ts +6 -0
- package/dist/features/categories/components/CategoryBundlesListing.js +3 -25
- package/dist/features/categories/components/CategoryProductsListing.js +6 -10
- package/dist/features/categories/components/index.d.ts +0 -2
- package/dist/features/categories/components/index.js +0 -1
- package/dist/features/categories/schemas/firestore.d.ts +9 -0
- package/dist/features/events/components/AdminEventEditorView.js +223 -269
- package/dist/features/events/components/EventRaffleWinnerView.d.ts +9 -1
- package/dist/features/events/components/EventRaffleWinnerView.js +3 -3
- package/dist/features/events/components/SpinWheelView.js +3 -3
- package/dist/features/grouped/repository/grouped-listings.repository.d.ts +9 -0
- package/dist/features/grouped/repository/grouped-listings.repository.js +12 -0
- package/dist/features/layout/BottomNavLayout.d.ts +5 -0
- package/dist/features/layout/BottomNavLayout.js +21 -0
- package/dist/features/layout/TitleBar.js +7 -1
- package/dist/features/layout/TitleBarLayout.d.ts +8 -2
- package/dist/features/layout/TitleBarLayout.js +11 -7
- package/dist/features/media/upload/MediaUploadField.js +1 -1
- package/dist/features/orders/schemas/index.d.ts +2 -2
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +12 -6
- package/dist/features/products/components/AuctionsIndexListing.js +3 -1
- package/dist/features/products/components/MarketplaceBundleCard.d.ts +21 -0
- package/dist/features/products/components/MarketplaceBundleCard.js +56 -0
- package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
- package/dist/features/products/components/PrizeDrawEntryActions.d.ts +3 -1
- package/dist/features/products/components/PrizeDrawEntryActions.js +8 -12
- package/dist/features/products/components/ProductDetailActions.d.ts +5 -1
- package/dist/features/products/components/ProductDetailActions.js +3 -1
- package/dist/features/products/components/ProductDetailPageView.d.ts +2 -0
- package/dist/features/products/components/ProductDetailPageView.js +4 -0
- package/dist/features/products/components/ProductGrid.js +3 -3
- package/dist/features/products/components/ProductsIndexListing.js +18 -9
- package/dist/features/products/components/index.d.ts +2 -4
- package/dist/features/products/components/index.js +1 -2
- package/dist/features/promotions/components/CouponCard.d.ts +11 -1
- package/dist/features/promotions/components/CouponCard.js +36 -2
- package/dist/features/promotions/repository/claimed-coupons.repository.d.ts +27 -0
- package/dist/features/promotions/repository/claimed-coupons.repository.js +115 -0
- package/dist/features/promotions/schemas/firestore.d.ts +34 -0
- package/dist/features/promotions/schemas/firestore.js +14 -1
- package/dist/features/reviews/components/index.d.ts +0 -2
- package/dist/features/reviews/components/index.js +0 -1
- package/dist/features/seller/components/BrandInlineSelect.js +23 -3
- package/dist/features/seller/components/CategoryInlineSelect.js +20 -3
- package/dist/features/seller/components/SellerAddressesView.js +3 -2
- package/dist/features/seller/components/SellerAnalyticsAlertsView.d.ts +6 -0
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +124 -0
- package/dist/features/seller/components/SellerAnalyticsView.d.ts +2 -0
- package/dist/features/seller/components/SellerAnalyticsView.js +17 -9
- package/dist/features/seller/components/SellerBidsView.js +33 -3
- package/dist/features/seller/components/SellerBundlesView.d.ts +5 -0
- package/dist/features/seller/components/SellerBundlesView.js +104 -0
- package/dist/features/seller/components/SellerClassifiedView.d.ts +5 -0
- package/dist/features/seller/components/SellerClassifiedView.js +113 -0
- package/dist/features/seller/components/SellerDashboardView.js +19 -7
- package/dist/features/seller/components/SellerDigitalCodesView.d.ts +5 -0
- package/dist/features/seller/components/SellerDigitalCodesView.js +115 -0
- package/dist/features/seller/components/SellerGoogleReviewsView.d.ts +14 -0
- package/dist/features/seller/components/SellerGoogleReviewsView.js +95 -0
- package/dist/features/seller/components/SellerGroupedListingsView.d.ts +6 -0
- package/dist/features/seller/components/SellerGroupedListingsView.js +112 -0
- package/dist/features/seller/components/SellerLiveView.d.ts +5 -0
- package/dist/features/seller/components/SellerLiveView.js +113 -0
- package/dist/features/seller/components/SellerOrdersView.js +53 -2
- package/dist/features/seller/components/SellerPayoutMethodsView.d.ts +7 -0
- package/dist/features/seller/components/SellerPayoutMethodsView.js +120 -0
- package/dist/features/seller/components/SellerPayoutSettingsView.js +50 -12
- package/dist/features/seller/components/SellerProductShell.d.ts +3 -1
- package/dist/features/seller/components/SellerProductShell.js +35 -11
- package/dist/features/seller/components/SellerProductsCards.d.ts +19 -0
- package/dist/features/seller/components/SellerProductsCards.js +19 -0
- package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +14 -0
- package/dist/features/seller/components/SellerProductsFilterDrawer.js +22 -0
- package/dist/features/seller/components/SellerProductsView.d.ts +3 -1
- package/dist/features/seller/components/SellerProductsView.js +92 -49
- package/dist/features/seller/components/SellerReviewsView.js +67 -4
- package/dist/features/seller/components/SellerShippingConfigsView.d.ts +7 -0
- package/dist/features/seller/components/SellerShippingConfigsView.js +149 -0
- package/dist/features/seller/components/SellerShippingView.js +37 -10
- package/dist/features/seller/components/SellerSidebar.js +2 -1
- package/dist/features/seller/components/SellerStoreCategoriesView.d.ts +9 -0
- package/dist/features/seller/components/SellerStoreCategoriesView.js +122 -0
- package/dist/features/seller/components/SellerStorefrontView.d.ts +0 -7
- package/dist/features/seller/components/SellerStorefrontView.js +26 -29
- package/dist/features/seller/components/SellerTemplatesView.d.ts +10 -0
- package/dist/features/seller/components/SellerTemplatesView.js +265 -0
- package/dist/features/seller/components/index.d.ts +26 -0
- package/dist/features/seller/components/index.js +13 -0
- package/dist/features/seller/components/seller-products-styles.d.ts +7 -0
- package/dist/features/seller/components/seller-products-styles.js +14 -0
- package/dist/features/shell/FormShell.d.ts +7 -1
- package/dist/features/shell/FormShell.js +5 -2
- package/dist/features/store-extensions/index.d.ts +4 -0
- package/dist/features/store-extensions/index.js +4 -0
- package/dist/features/store-extensions/repository/rbac.repositories.d.ts +23 -0
- package/dist/features/store-extensions/repository/rbac.repositories.js +32 -0
- package/dist/features/store-extensions/repository/store-extensions.repositories.d.ts +91 -0
- package/dist/features/store-extensions/repository/store-extensions.repositories.js +127 -0
- package/dist/features/store-extensions/schemas/firestore.d.ts +244 -0
- package/dist/features/store-extensions/schemas/firestore.js +158 -0
- package/dist/features/store-extensions/schemas/rbac.d.ts +65 -0
- package/dist/features/store-extensions/schemas/rbac.js +43 -0
- package/dist/features/stores/api/[storeSlug]/reviews/route.js +49 -7
- package/dist/features/stores/components/InteractiveStoreCard.js +7 -3
- package/dist/features/stores/components/StoreCapabilitiesGuideView.d.ts +3 -0
- package/dist/features/stores/components/StoreCapabilitiesGuideView.js +101 -0
- package/dist/features/stores/components/StoreFinanceGuideView.d.ts +3 -0
- package/dist/features/stores/components/StoreFinanceGuideView.js +79 -0
- package/dist/features/stores/components/StoreGuideHubView.d.ts +5 -0
- package/dist/features/stores/components/StoreGuideHubView.js +89 -0
- package/dist/features/stores/components/StoreListingsGuideView.d.ts +3 -0
- package/dist/features/stores/components/StoreListingsGuideView.js +151 -0
- package/dist/features/stores/components/StoreOrdersGuideView.d.ts +3 -0
- package/dist/features/stores/components/StoreOrdersGuideView.js +122 -0
- package/dist/features/stores/components/StoreProductsListing.js +6 -10
- package/dist/features/stores/components/StoreReviewsListing.js +100 -23
- package/dist/features/stores/components/StoreSettingsGuideView.d.ts +3 -0
- package/dist/features/stores/components/StoreSettingsGuideView.js +56 -0
- package/dist/features/stores/components/index.d.ts +12 -1
- package/dist/features/stores/components/index.js +6 -1
- package/dist/features/stores/hooks/useStores.d.ts +5 -0
- package/dist/features/stores/hooks/useStores.js +10 -0
- package/dist/features/stores/manifest.js +1 -1
- package/dist/features/stores/schemas/firestore.d.ts +2 -0
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +13 -2
- package/dist/index.d.ts +60 -9
- package/dist/index.js +66 -15
- package/dist/next/routing/route-map.d.ts +134 -0
- package/dist/next/routing/route-map.js +59 -0
- package/dist/providers/db-firebase/__tests__/filter-aliases.test.d.ts +1 -0
- package/dist/providers/db-firebase/__tests__/filter-aliases.test.js +93 -0
- package/dist/providers/db-firebase/sieve.d.ts +49 -0
- package/dist/providers/db-firebase/sieve.js +61 -8
- package/dist/react/hooks/useFormStatePreservation.d.ts +17 -0
- package/dist/react/hooks/useFormStatePreservation.js +62 -0
- package/dist/react/hooks/useInlineRowEdit.d.ts +24 -0
- package/dist/react/hooks/useInlineRowEdit.js +68 -0
- package/dist/react/index.d.ts +4 -0
- package/dist/react/index.js +4 -0
- package/dist/repositories/index.d.ts +5 -0
- package/dist/repositories/index.js +7 -0
- package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
- package/dist/seed/claimed-coupons-seed-data.d.ts +13 -0
- package/dist/seed/claimed-coupons-seed-data.js +79 -0
- package/dist/seed/index.d.ts +2 -0
- package/dist/seed/index.js +3 -0
- package/dist/seed/manifest.js +17 -0
- package/dist/seed/store-extensions-seed-data.d.ts +19 -0
- package/dist/seed/store-extensions-seed-data.js +421 -0
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Button.style.css +20 -12
- package/dist/ui/components/ClaimCouponButton.d.ts +28 -0
- package/dist/ui/components/ClaimCouponButton.js +89 -0
- package/dist/ui/components/ListingToolbar.d.ts +8 -1
- package/dist/ui/components/ListingToolbar.js +4 -2
- package/dist/ui/components/QuickCreateModal.d.ts +15 -0
- package/dist/ui/components/QuickCreateModal.js +48 -0
- package/dist/ui/components/QuickCreateModal.style.css +84 -0
- package/dist/ui/components/StickyBottomBar.d.ts +22 -0
- package/dist/ui/components/StickyBottomBar.js +20 -0
- package/dist/ui/components/VacationBanner.d.ts +11 -0
- package/dist/ui/components/VacationBanner.js +16 -0
- package/dist/ui/components/__tests__/BulkActionBar.test.d.ts +1 -0
- package/dist/ui/components/__tests__/BulkActionBar.test.js +96 -0
- package/dist/ui/components/__tests__/ListingToolbar.test.d.ts +1 -0
- package/dist/ui/components/__tests__/ListingToolbar.test.js +125 -0
- package/dist/ui/index.d.ts +9 -1
- package/dist/ui/index.js +4 -0
- package/package.json +8 -2
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useCallback } from "react";
|
|
4
|
+
import { Plus } from "lucide-react";
|
|
5
|
+
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
6
|
+
import { Button, ConfirmDeleteModal, Div, ListingToolbar, Text, } from "../../../ui";
|
|
7
|
+
import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
8
|
+
import { ROUTES } from "../../..";
|
|
9
|
+
import { toRecordArray, toStringValue, useSellerListingData, } from "../hooks/useSellerListingData";
|
|
10
|
+
import { TABLE_KEYS } from "../../../constants/table-keys";
|
|
11
|
+
const PAGE_SIZE = 50;
|
|
12
|
+
const DEFAULT_SORT = "-createdAt";
|
|
13
|
+
const SORT_OPTIONS = [
|
|
14
|
+
{ value: "-createdAt", label: "Newest" },
|
|
15
|
+
{ value: "createdAt", label: "Oldest" },
|
|
16
|
+
{ value: "label", label: "Label A–Z" },
|
|
17
|
+
];
|
|
18
|
+
function getMaskedIdentifier(item) {
|
|
19
|
+
if (item.upiVpa && typeof item.upiVpa === "string") {
|
|
20
|
+
return item.upiVpa;
|
|
21
|
+
}
|
|
22
|
+
if (item.accountNumber && typeof item.accountNumber === "string") {
|
|
23
|
+
const acc = item.accountNumber;
|
|
24
|
+
return `••••${acc.slice(-4)}`;
|
|
25
|
+
}
|
|
26
|
+
return "—";
|
|
27
|
+
}
|
|
28
|
+
function TypeBadge({ type }) {
|
|
29
|
+
return (_jsx("span", { className: "inline-flex items-center rounded-full px-2 py-0.5 text-xs font-semibold uppercase tracking-wide bg-violet-100 text-violet-700 dark:bg-violet-900/40 dark:text-violet-300", children: type === "upi" ? "UPI" : type === "bank" ? "Bank" : type.toUpperCase() }));
|
|
30
|
+
}
|
|
31
|
+
export function SellerPayoutMethodsView({ onCreateClick, onEditClick, onDelete, onSetDefault, }) {
|
|
32
|
+
const table = useUrlTable({ defaults: { sort: DEFAULT_SORT } });
|
|
33
|
+
const [searchInput, setSearchInput] = useState(table.get(TABLE_KEYS.QUERY) || "");
|
|
34
|
+
const [deleteTargetId, setDeleteTargetId] = useState(null);
|
|
35
|
+
const [deletingId, setDeletingId] = useState(null);
|
|
36
|
+
const [settingDefaultId, setSettingDefaultId] = useState(null);
|
|
37
|
+
const commitSearch = useCallback(() => {
|
|
38
|
+
table.set(TABLE_KEYS.QUERY, searchInput.trim());
|
|
39
|
+
}, [searchInput, table]);
|
|
40
|
+
const resetAll = useCallback(() => {
|
|
41
|
+
table.setMany({ [TABLE_KEYS.QUERY]: "", [TABLE_KEYS.SORT]: "" });
|
|
42
|
+
setSearchInput("");
|
|
43
|
+
}, [table]);
|
|
44
|
+
const hasActiveState = !!table.get(TABLE_KEYS.QUERY) || table.get(TABLE_KEYS.SORT) !== DEFAULT_SORT;
|
|
45
|
+
const { rows, isLoading, errorMessage, refetch } = useSellerListingData({
|
|
46
|
+
queryKey: ["seller", "payout-methods"],
|
|
47
|
+
endpoint: SELLER_ENDPOINTS.PAYOUT_METHODS,
|
|
48
|
+
page: 1,
|
|
49
|
+
pageSize: PAGE_SIZE,
|
|
50
|
+
sorts: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT,
|
|
51
|
+
q: table.get(TABLE_KEYS.QUERY) || undefined,
|
|
52
|
+
mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
|
|
53
|
+
id: toStringValue(item.id, `pm-${index}`),
|
|
54
|
+
raw: item,
|
|
55
|
+
label: String(item.label ?? ""),
|
|
56
|
+
type: String(item.type ?? ""),
|
|
57
|
+
isDefault: Boolean(item.isDefault),
|
|
58
|
+
isActive: Boolean(item.isActive),
|
|
59
|
+
maskedIdentifier: getMaskedIdentifier(item),
|
|
60
|
+
})),
|
|
61
|
+
});
|
|
62
|
+
const handleDelete = useCallback(async (id) => {
|
|
63
|
+
setDeletingId(id);
|
|
64
|
+
try {
|
|
65
|
+
if (onDelete) {
|
|
66
|
+
await onDelete(id);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
await fetch(SELLER_ENDPOINTS.PAYOUT_METHOD_BY_ID(id), {
|
|
70
|
+
method: "DELETE",
|
|
71
|
+
credentials: "include",
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
refetch?.();
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
setDeletingId(null);
|
|
78
|
+
setDeleteTargetId(null);
|
|
79
|
+
}
|
|
80
|
+
}, [onDelete, refetch]);
|
|
81
|
+
const handleSetDefault = useCallback(async (id) => {
|
|
82
|
+
setSettingDefaultId(id);
|
|
83
|
+
try {
|
|
84
|
+
if (onSetDefault) {
|
|
85
|
+
await onSetDefault(id);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
await fetch(SELLER_ENDPOINTS.PAYOUT_METHOD_BY_ID(id), {
|
|
89
|
+
method: "PATCH",
|
|
90
|
+
headers: { "Content-Type": "application/json" },
|
|
91
|
+
credentials: "include",
|
|
92
|
+
body: JSON.stringify({ isDefault: true }),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
refetch?.();
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
setSettingDefaultId(null);
|
|
99
|
+
}
|
|
100
|
+
}, [onSetDefault, refetch]);
|
|
101
|
+
const handleCreate = useCallback(() => {
|
|
102
|
+
if (onCreateClick) {
|
|
103
|
+
onCreateClick();
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
window.location.href = String(ROUTES.STORE.PAYOUT_METHODS_NEW);
|
|
107
|
+
}
|
|
108
|
+
}, [onCreateClick]);
|
|
109
|
+
const handleEdit = useCallback((id) => {
|
|
110
|
+
if (onEditClick) {
|
|
111
|
+
onEditClick(id);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
window.location.href = String(ROUTES.STORE.PAYOUT_METHODS_EDIT(id));
|
|
115
|
+
}
|
|
116
|
+
}, [onEditClick]);
|
|
117
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search payout methods...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: handleCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Method" })] }) }), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-red-200 bg-red-50 dark:bg-red-950/40 dark:border-red-900/60 px-4 py-3 text-sm text-red-700 dark:text-red-200", children: errorMessage })), isLoading ? (_jsx(Div, { className: "space-y-3", children: Array.from({ length: 3 }).map((_, i) => (_jsx(Div, { className: "h-20 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : rows.length === 0 ? (_jsxs(Div, { className: "py-16 text-center", children: [_jsx(Text, { className: "text-zinc-400 dark:text-zinc-500", children: "No payout methods yet \u2014 add a UPI VPA or bank account to receive payouts" }), _jsx("div", { className: "mt-4", children: _jsx(Button, { size: "sm", onClick: handleCreate, children: "Add payout method" }) })] })) : (_jsx("div", { className: "space-y-3", children: rows.map((row) => (_jsx("div", { className: "rounded-xl border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-900 px-4 py-3", children: _jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsx("div", { className: "flex items-start gap-3 min-w-0", children: _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsx(Text, { className: "text-sm font-medium", children: row.label }), _jsx(TypeBadge, { type: row.type }), row.isDefault && (_jsx("span", { className: "inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300", children: "Default" })), _jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${row.isActive
|
|
118
|
+
? "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300"
|
|
119
|
+
: "bg-zinc-100 text-zinc-600 dark:bg-slate-800 dark:text-slate-400"}`, children: row.isActive ? "Active" : "Inactive" })] }), _jsx(Text, { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400 font-mono", children: row.maskedIdentifier })] }) }), _jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [!row.isDefault && (_jsx(Button, { size: "sm", variant: "ghost", isLoading: settingDefaultId === row.id, onClick: () => handleSetDefault(row.id), children: "Set Default" })), _jsx(Button, { size: "sm", variant: "outline", onClick: () => handleEdit(row.id), children: "Edit" }), _jsx(Button, { size: "sm", variant: "danger", disabled: deletingId === row.id, onClick: () => setDeleteTargetId(row.id), children: "Delete" })] })] }) }, row.id))) }))] }), deleteTargetId && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Payout Method", message: "Are you sure you want to delete this payout method? This cannot be undone.", onConfirm: () => handleDelete(deleteTargetId), onClose: () => setDeleteTargetId(null), isDeleting: deletingId === deleteTargetId }))] }));
|
|
120
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useEffect, useState } from "react";
|
|
4
|
-
import { Alert, Badge,
|
|
4
|
+
import { Alert, Badge, Div, FormField, FormGroup, Heading, Stack, Text, Toggle } from "../../../ui";
|
|
5
5
|
import { StackedViewShell } from "../../../ui";
|
|
6
|
+
import { StepForm } from "../../shell";
|
|
6
7
|
const DEFAULT_DRAFT = {
|
|
7
8
|
method: "upi",
|
|
8
9
|
upiId: "",
|
|
@@ -11,6 +12,11 @@ const DEFAULT_DRAFT = {
|
|
|
11
12
|
ifscCode: "",
|
|
12
13
|
bankName: "",
|
|
13
14
|
accountType: "savings",
|
|
15
|
+
gstin: "",
|
|
16
|
+
pan: "",
|
|
17
|
+
businessType: "",
|
|
18
|
+
autoPayout: true,
|
|
19
|
+
minimumThreshold: "",
|
|
14
20
|
};
|
|
15
21
|
export function SellerPayoutSettingsView({ apiBase = "/api/store/payout-settings" }) {
|
|
16
22
|
const [draft, setDraft] = useState(DEFAULT_DRAFT);
|
|
@@ -19,6 +25,7 @@ export function SellerPayoutSettingsView({ apiBase = "/api/store/payout-settings
|
|
|
19
25
|
const [saving, setSaving] = useState(false);
|
|
20
26
|
const [error, setError] = useState(null);
|
|
21
27
|
const [success, setSuccess] = useState(false);
|
|
28
|
+
const [currentStep, setCurrentStep] = useState(0);
|
|
22
29
|
useEffect(() => {
|
|
23
30
|
fetch(apiBase)
|
|
24
31
|
.then((r) => r.json())
|
|
@@ -33,13 +40,20 @@ export function SellerPayoutSettingsView({ apiBase = "/api/store/payout-settings
|
|
|
33
40
|
ifscCode: details.bankAccount?.ifscCode ?? "",
|
|
34
41
|
bankName: details.bankAccount?.bankName ?? "",
|
|
35
42
|
accountType: details.bankAccount?.accountType ?? "savings",
|
|
43
|
+
gstin: res?.data?.taxInfo?.gstin ?? "",
|
|
44
|
+
pan: res?.data?.taxInfo?.pan ?? "",
|
|
45
|
+
businessType: res?.data?.taxInfo?.businessType ?? "",
|
|
46
|
+
autoPayout: res?.data?.preferences?.autoPayout ?? true,
|
|
47
|
+
minimumThreshold: res?.data?.preferences?.minimumThreshold
|
|
48
|
+
? String(res.data.preferences.minimumThreshold / 100)
|
|
49
|
+
: "",
|
|
36
50
|
});
|
|
37
51
|
})
|
|
38
52
|
.catch(() => { })
|
|
39
53
|
.finally(() => setLoading(false));
|
|
40
54
|
}, [apiBase]);
|
|
41
|
-
const update = useCallback((
|
|
42
|
-
setDraft((prev) => ({ ...prev,
|
|
55
|
+
const update = useCallback((partial) => {
|
|
56
|
+
setDraft((prev) => ({ ...prev, ...partial }));
|
|
43
57
|
setSuccess(false);
|
|
44
58
|
}, []);
|
|
45
59
|
const handleSave = async () => {
|
|
@@ -47,7 +61,7 @@ export function SellerPayoutSettingsView({ apiBase = "/api/store/payout-settings
|
|
|
47
61
|
setSuccess(false);
|
|
48
62
|
setSaving(true);
|
|
49
63
|
try {
|
|
50
|
-
const
|
|
64
|
+
const methodFields = draft.method === "upi"
|
|
51
65
|
? { method: "upi", upiId: draft.upiId.trim() }
|
|
52
66
|
: {
|
|
53
67
|
method: "bank_transfer",
|
|
@@ -57,6 +71,18 @@ export function SellerPayoutSettingsView({ apiBase = "/api/store/payout-settings
|
|
|
57
71
|
bankName: draft.bankName.trim(),
|
|
58
72
|
accountType: draft.accountType,
|
|
59
73
|
};
|
|
74
|
+
const body = {
|
|
75
|
+
...methodFields,
|
|
76
|
+
taxInfo: {
|
|
77
|
+
gstin: draft.gstin.trim(),
|
|
78
|
+
pan: draft.pan.trim(),
|
|
79
|
+
businessType: draft.businessType.trim(),
|
|
80
|
+
},
|
|
81
|
+
preferences: {
|
|
82
|
+
autoPayout: draft.autoPayout,
|
|
83
|
+
minimumThreshold: Math.round(parseFloat(draft.minimumThreshold || "0") * 100),
|
|
84
|
+
},
|
|
85
|
+
};
|
|
60
86
|
const res = await fetch(apiBase, {
|
|
61
87
|
method: "PATCH",
|
|
62
88
|
headers: { "Content-Type": "application/json" },
|
|
@@ -68,7 +94,6 @@ export function SellerPayoutSettingsView({ apiBase = "/api/store/payout-settings
|
|
|
68
94
|
setSuccess(true);
|
|
69
95
|
const updated = json?.data?.payoutDetails ?? { method: draft.method, isConfigured: false };
|
|
70
96
|
setCurrent(updated);
|
|
71
|
-
// clear sensitive field
|
|
72
97
|
setDraft((prev) => ({ ...prev, accountNumber: "" }));
|
|
73
98
|
}
|
|
74
99
|
catch (err) {
|
|
@@ -78,14 +103,27 @@ export function SellerPayoutSettingsView({ apiBase = "/api/store/payout-settings
|
|
|
78
103
|
setSaving(false);
|
|
79
104
|
}
|
|
80
105
|
};
|
|
81
|
-
const isUpi = draft.method === "upi";
|
|
82
106
|
const busy = loading || saving;
|
|
83
|
-
|
|
84
|
-
|
|
107
|
+
const steps = [
|
|
108
|
+
{
|
|
109
|
+
label: "Payout Method",
|
|
110
|
+
render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Payout Method" }), current && (_jsx(Div, { className: "flex items-center gap-2 mb-2", children: _jsx(Badge, { variant: current.isConfigured ? "success" : "warning", children: current.isConfigured ? "Payout configured" : "Not configured" }) })), current?.isConfigured && (_jsx(Alert, { variant: "info", children: current.method === "upi"
|
|
85
111
|
? `Current UPI: ${current.upiId}`
|
|
86
|
-
: `Current bank: ${current.bankAccount?.bankName ?? ""} — ••••${current.bankAccount?.accountNumberMasked?.slice(-4) ?? "••••"} (${current.bankAccount?.accountType})` })),
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
112
|
+
: `Current bank: ${current.bankAccount?.bankName ?? ""} — ••••${current.bankAccount?.accountNumberMasked?.slice(-4) ?? "••••"} (${current.bankAccount?.accountType})` })), _jsx(Stack, { gap: "sm", children: ([
|
|
113
|
+
{ value: "upi", label: "UPI", desc: "Instant payouts via UPI VPA (e.g. name@upi)." },
|
|
114
|
+
{ value: "bank_transfer", label: "Bank Transfer", desc: "NEFT/RTGS to your bank account within 2–3 business days." },
|
|
115
|
+
]).map(({ value, label, desc }) => (_jsxs("label", { className: "flex items-center gap-3 p-3 rounded-lg border border-[var(--appkit-color-border)] cursor-pointer has-[:checked]:border-[var(--appkit-color-primary)] has-[:checked]:bg-[var(--appkit-color-primary)]/5", children: [_jsx("input", { type: "radio", name: "payoutMethod", value: value, checked: values.method === value, onChange: () => onChange({ method: value }), className: "accent-[var(--appkit-color-primary)]", disabled: busy }), _jsxs(Div, { children: [_jsx(Text, { className: "font-medium", children: label }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: desc })] })] }, value))) }), values.method === "upi" && (_jsx(FormField, { name: "upiId", label: "UPI ID (VPA)", type: "text", value: values.upiId, onChange: (v) => onChange({ upiId: v }), placeholder: "yourname@upi", helpText: "Ensure this VPA is registered and active.", disabled: busy })), values.method === "bank_transfer" && (_jsxs(Stack, { gap: "md", className: "mt-2", children: [_jsx(FormField, { name: "accountHolderName", label: "Account Holder Name", type: "text", value: values.accountHolderName, onChange: (v) => onChange({ accountHolderName: v }), placeholder: "Name as on bank account", disabled: busy }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "accountNumber", label: "Account Number", type: "text", value: values.accountNumber, onChange: (v) => onChange({ accountNumber: v }), placeholder: "Enter full account number", helpText: current?.bankAccount ? `Saved: ••••${current.bankAccount.accountNumberMasked?.slice(-4) ?? "••••"}` : "Stored securely, never displayed in full.", disabled: busy }), _jsx(FormField, { name: "ifscCode", label: "IFSC Code", type: "text", value: values.ifscCode, onChange: (v) => onChange({ ifscCode: v.toUpperCase() }), placeholder: "e.g. SBIN0001234", disabled: busy })] }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "bankName", label: "Bank Name", type: "text", value: values.bankName, onChange: (v) => onChange({ bankName: v }), placeholder: "e.g. State Bank of India", disabled: busy }), _jsxs(Div, { children: [_jsx(Text, { className: "text-sm font-medium mb-1.5", children: "Account Type" }), _jsx(Stack, { gap: "xs", className: "flex-row", children: ["savings", "current"].map((t) => (_jsxs("label", { className: "flex items-center gap-2 cursor-pointer", children: [_jsx("input", { type: "radio", name: "accountType", value: t, checked: values.accountType === t, onChange: () => onChange({ accountType: t }), className: "accent-[var(--appkit-color-primary)]", disabled: busy }), _jsx(Text, { className: "capitalize text-sm", children: t })] }, t))) })] })] })] }))] })),
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
label: "Tax Info",
|
|
119
|
+
render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Tax Information" }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: "Optional \u2014 required only for GST invoice generation and TDS compliance." }), _jsx(FormField, { name: "gstin", label: "GSTIN (optional)", type: "text", value: values.gstin, onChange: (v) => onChange({ gstin: v.toUpperCase() }), placeholder: "e.g. 22AAAAA0000A1Z5", helpText: "15-character Goods and Services Tax Identification Number.", disabled: busy }), _jsx(FormField, { name: "pan", label: "PAN (optional)", type: "text", value: values.pan, onChange: (v) => onChange({ pan: v.toUpperCase() }), placeholder: "e.g. ABCDE1234F", helpText: "Required for payouts above \u20B950,000 per year (TDS threshold).", disabled: busy }), _jsx(FormField, { name: "businessType", label: "Business Type (optional)", type: "text", value: values.businessType, onChange: (v) => onChange({ businessType: v }), placeholder: "e.g. Individual, Sole Proprietor, Private Limited", disabled: busy })] })),
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
label: "Preferences",
|
|
123
|
+
render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Payout Preferences" }), _jsx(Toggle, { checked: values.autoPayout, onChange: (checked) => onChange({ autoPayout: checked }), label: "Enable auto-payout \u2014 automatically transfer earnings on schedule", disabled: busy }), _jsx(FormField, { name: "minimumThreshold", label: "Minimum Payout Threshold (\u20B9)", type: "number", value: values.minimumThreshold, onChange: (v) => onChange({ minimumThreshold: v }), placeholder: "e.g. 500", helpText: "Payouts are held until your balance exceeds this amount. Leave blank for no minimum.", disabled: busy }), _jsxs(Div, { className: "p-3 rounded-lg bg-[var(--appkit-color-surface-alt)] border border-[var(--appkit-color-border)]", children: [_jsx(Text, { className: "text-sm font-medium mb-1", children: "Payout Schedule" }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: "Auto-payouts run every Monday for the previous week's settled orders. Manual payouts can be requested from the Payouts page at any time." })] })] })),
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
return (_jsx(StackedViewShell, { portal: "seller", title: "Payout Settings", sections: [
|
|
127
|
+
_jsxs("div", { children: [error && _jsx(Alert, { variant: "error", className: "mb-4", children: error }), success && _jsx(Alert, { variant: "success", className: "mb-4", children: "Payout details saved." }), _jsx(StepForm, { steps: steps, values: draft, onChange: update, onComplete: handleSave, formId: "seller-payout-settings", currentStep: currentStep, onStepChange: setCurrentStep, completeLabel: "Save Payout Details", isLoading: busy })] }, "payout"),
|
|
90
128
|
] }));
|
|
91
129
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export type ProductListingMode = "standard" | "auction" | "pre-order" | "prize-draw" | "classified" | "digital-code" | "live";
|
|
2
|
+
export type ProductListingMode = "standard" | "auction" | "pre-order" | "prize-draw" | "bundle" | "classified" | "digital-code" | "live";
|
|
3
3
|
export interface SellerProductDraft {
|
|
4
4
|
title?: string;
|
|
5
5
|
slug?: string;
|
|
@@ -26,6 +26,8 @@ export interface SellerProductDraft {
|
|
|
26
26
|
status?: "draft" | "published";
|
|
27
27
|
seoTitle?: string;
|
|
28
28
|
seoDescription?: string;
|
|
29
|
+
/** S-STORE-3-B — 3rd-party hosted video URL. Queues moderation on save. */
|
|
30
|
+
externalVideoUrl?: string;
|
|
29
31
|
startingBid?: number;
|
|
30
32
|
reservePrice?: number;
|
|
31
33
|
buyNowPrice?: number;
|
|
@@ -57,7 +57,7 @@ function StepMedia({ values, onChange, storeSlug = "store", }) {
|
|
|
57
57
|
type: "product-video",
|
|
58
58
|
name: values.title ?? "product",
|
|
59
59
|
store: storeSlug,
|
|
60
|
-
}), kind: "video", helperText: "MP4, WebM or QuickTime \u2014 max 50 MB" }), _jsx(FormField, { name: "youtubeId", label: "YouTube Video ID (optional)", type: "text", value: values.youtubeId ?? "", onChange: (v) => onChange({ youtubeId: v }), placeholder: "e.g. dQw4w9WgXcQ", helpText: "Paste the 11-character ID from the YouTube URL" })] }));
|
|
60
|
+
}), kind: "video", helperText: "MP4, WebM or QuickTime \u2014 max 50 MB" }), _jsx(FormField, { name: "externalVideoUrl", label: "3rd-party video URL (YouTube / Vimeo)", type: "text", value: values.externalVideoUrl ?? "", onChange: (v) => onChange({ externalVideoUrl: v }), placeholder: "https://www.youtube.com/watch?v=\u2026", hint: "External video links are queued for moderation and become visible to buyers after admin approval." }), _jsx(FormField, { name: "youtubeId", label: "YouTube Video ID (optional)", type: "text", value: values.youtubeId ?? "", onChange: (v) => onChange({ youtubeId: v }), placeholder: "e.g. dQw4w9WgXcQ", helpText: "Paste the 11-character ID from the YouTube URL" })] }));
|
|
61
61
|
}
|
|
62
62
|
// ── Step 3: Auction Settings ───────────────────────────────────────────────
|
|
63
63
|
function StepAuctionSettings({ values, onChange, }) {
|
|
@@ -167,9 +167,31 @@ export function SellerProductShell({ mode, listingType = "standard", initialValu
|
|
|
167
167
|
clearTimeout(autoSaveTimer.current); };
|
|
168
168
|
}, [draft, isDirty, mode]);
|
|
169
169
|
const update = useCallback((partial) => {
|
|
170
|
-
setDraft((prev) =>
|
|
170
|
+
setDraft((prev) => {
|
|
171
|
+
const next = { ...prev, ...partial };
|
|
172
|
+
// S-STORE-3-C — auto-fill slug + SEO from title on create when not manually set.
|
|
173
|
+
if (mode === "create" && partial.title) {
|
|
174
|
+
const autoSlug = partial.title
|
|
175
|
+
.toLowerCase()
|
|
176
|
+
.trim()
|
|
177
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
178
|
+
.replace(/^-|-$/g, "")
|
|
179
|
+
.slice(0, 80);
|
|
180
|
+
if (!prev.slug || prev.slug === "")
|
|
181
|
+
next.slug = autoSlug;
|
|
182
|
+
if (!prev.seoTitle || prev.seoTitle === "")
|
|
183
|
+
next.seoTitle = partial.title.slice(0, 60);
|
|
184
|
+
}
|
|
185
|
+
if (mode === "create" && partial.description) {
|
|
186
|
+
const text = String(partial.description).replace(/<[^>]+>/g, "").trim();
|
|
187
|
+
if (!prev.seoDescription || prev.seoDescription === "") {
|
|
188
|
+
next.seoDescription = text.slice(0, 160);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return next;
|
|
192
|
+
});
|
|
171
193
|
markDirty();
|
|
172
|
-
}, [markDirty]);
|
|
194
|
+
}, [markDirty, mode]);
|
|
173
195
|
const handleDiscard = useCallback(() => {
|
|
174
196
|
if (onDiscard)
|
|
175
197
|
onDiscard();
|
|
@@ -188,13 +210,15 @@ export function SellerProductShell({ mode, listingType = "standard", initialValu
|
|
|
188
210
|
? "Auction"
|
|
189
211
|
: listingType === "pre-order"
|
|
190
212
|
? "Pre-Order"
|
|
191
|
-
: listingType === "
|
|
192
|
-
? "
|
|
193
|
-
: listingType === "
|
|
194
|
-
? "
|
|
195
|
-
: listingType === "
|
|
196
|
-
? "
|
|
197
|
-
: "
|
|
213
|
+
: listingType === "bundle"
|
|
214
|
+
? "Bundle"
|
|
215
|
+
: listingType === "classified"
|
|
216
|
+
? "Classified"
|
|
217
|
+
: listingType === "digital-code"
|
|
218
|
+
? "Digital Code"
|
|
219
|
+
: listingType === "live"
|
|
220
|
+
? "Live Item"
|
|
221
|
+
: "Product";
|
|
198
222
|
const typeSpecificStep = listingType === "auction"
|
|
199
223
|
? {
|
|
200
224
|
label: "Auction Settings",
|
|
@@ -276,7 +300,7 @@ export function SellerProductShell({ mode, listingType = "standard", initialValu
|
|
|
276
300
|
? `New ${listingTypeLabel}`
|
|
277
301
|
: draft.title ?? `Edit ${listingTypeLabel}`;
|
|
278
302
|
if (mode === "create") {
|
|
279
|
-
return (_jsx(FormShell, { isOpen: true, onClose: handleDiscard, title: title, breadcrumb: breadcrumb, isDirty: isDirty, isLoading: isLoading, previewSlot: previewSlot, renderBottomBar: () => (_jsxs("div", { className: "flex-shrink-0 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", children: [_jsx(StepFormActions, { currentStep: currentStep, totalSteps: steps.length, onNext: () => void handleNext(), onPrev: currentStep > 0 ? () => setCurrentStep((c) => c - 1) : undefined, completeLabel: `Publish ${listingTypeLabel}`, isLoading: isLoading && currentStep === steps.length - 1, disabled: isLoading }), stepError && (_jsx(Text, { className: "px-5 pb-3 text-sm text-[var(--appkit-color-error)]", children: stepError }))] })), children: _jsx(FormShellProvider, { isDirty: isDirty, values: draft, children: _jsx(StepForm, { steps: steps, values: draft, onChange: update, onComplete: handlePublish, completeLabel: `Publish ${listingTypeLabel}`, currentStep: currentStep, onStepChange: setCurrentStep, isLoading: isLoading, hideActions: true, stepErrors: stepValidationErrors }) }) }));
|
|
303
|
+
return (_jsx(FormShell, { isOpen: true, onClose: handleDiscard, title: title, breadcrumb: breadcrumb, isDirty: isDirty, isLoading: isLoading, previewSlot: previewSlot, splitPreview: !!previewSlot, renderBottomBar: () => (_jsxs("div", { className: "flex-shrink-0 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", children: [_jsx(StepFormActions, { currentStep: currentStep, totalSteps: steps.length, onNext: () => void handleNext(), onPrev: currentStep > 0 ? () => setCurrentStep((c) => c - 1) : undefined, completeLabel: `Publish ${listingTypeLabel}`, isLoading: isLoading && currentStep === steps.length - 1, disabled: isLoading }), currentStep === 0 && (_jsx("div", { className: "px-5 pb-3", children: _jsx(Button, { variant: "ghost", size: "sm", onClick: () => void handleSave(), disabled: isLoading || !draft.title?.trim(), children: "Save as draft & finish later" }) })), stepError && (_jsx(Text, { className: "px-5 pb-3 text-sm text-[var(--appkit-color-error)]", children: stepError }))] })), children: _jsx(FormShellProvider, { isDirty: isDirty, values: draft, children: _jsx(StepForm, { steps: steps, values: draft, onChange: update, onComplete: handlePublish, completeLabel: `Publish ${listingTypeLabel}`, currentStep: currentStep, onStepChange: setCurrentStep, isLoading: isLoading, hideActions: true, stepErrors: stepValidationErrors }) }) }));
|
|
280
304
|
}
|
|
281
305
|
// Edit mode — FormShell with section nav + full form
|
|
282
306
|
const editSections = [
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface SellerProductsCardsRowShape {
|
|
2
|
+
id: string;
|
|
3
|
+
primary: string;
|
|
4
|
+
secondary: string;
|
|
5
|
+
imageUrl?: string;
|
|
6
|
+
listingKind: string;
|
|
7
|
+
}
|
|
8
|
+
export interface SellerProductsCardsProps<TRow extends SellerProductsCardsRowShape> {
|
|
9
|
+
view: "grid" | "list";
|
|
10
|
+
rows: TRow[];
|
|
11
|
+
isLoading: boolean;
|
|
12
|
+
listingKind: string;
|
|
13
|
+
selectedIds: Set<string>;
|
|
14
|
+
toggle: (id: string) => void;
|
|
15
|
+
onEdit: (row: TRow) => void;
|
|
16
|
+
onDuplicate: (row: TRow) => void;
|
|
17
|
+
onDelete?: (row: TRow) => void;
|
|
18
|
+
}
|
|
19
|
+
export declare function SellerProductsCards<TRow extends SellerProductsCardsRowShape>({ view, rows, isLoading, listingKind, selectedIds, toggle, onEdit, onDuplicate, onDelete, }: SellerProductsCardsProps<TRow>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Badge, Button, Div, Row, Text } from "../../../ui";
|
|
4
|
+
import { CARD_BORDER, CARD_BORDER_ACTIVE, CARD_GRID_CLS, CARD_LIST_CLS, KIND_BADGE_VARIANT } from "./seller-products-styles";
|
|
5
|
+
function buildHref(row) {
|
|
6
|
+
if (row.listingKind === "auction")
|
|
7
|
+
return `/auctions/${row.id}`;
|
|
8
|
+
if (row.listingKind === "pre-order")
|
|
9
|
+
return `/pre-orders/${row.id}`;
|
|
10
|
+
return `/products/${row.id}`;
|
|
11
|
+
}
|
|
12
|
+
export function SellerProductsCards({ view, rows, isLoading, listingKind, selectedIds, toggle, onEdit, onDuplicate, onDelete, }) {
|
|
13
|
+
return (_jsxs(Div, { className: view === "grid" ? CARD_GRID_CLS : CARD_LIST_CLS, children: [rows.length === 0 && !isLoading && (_jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)] col-span-full", children: listingKind !== "all" ? `No ${listingKind} listings found` : "No products listed yet" })), rows.map((row) => {
|
|
14
|
+
const isSelected = selectedIds.has(row.id);
|
|
15
|
+
const href = buildHref(row);
|
|
16
|
+
const borderCls = isSelected ? CARD_BORDER_ACTIVE : CARD_BORDER;
|
|
17
|
+
return view === "grid" ? (_jsxs(Div, { className: `group relative rounded-xl border bg-[var(--appkit-color-surface)] overflow-hidden hover:shadow-md transition-shadow ${borderCls}`, children: [_jsx(Div, { className: "absolute top-2 left-2 z-10", children: _jsx("input", { type: "checkbox", checked: isSelected, onChange: () => toggle(row.id), className: "h-4 w-4 rounded border-[var(--appkit-color-border)]", onClick: (e) => e.stopPropagation(), "aria-label": "Select" }) }), _jsxs("a", { href: href, className: "block", children: [row.imageUrl ? (_jsx("img", { src: row.imageUrl, alt: "", className: "w-full aspect-square object-cover" })) : (_jsx(Div, { className: "w-full aspect-square bg-[var(--appkit-color-surface-raised)] flex items-center justify-center text-[var(--appkit-color-text-faint)]", children: "\u2014" })), _jsxs(Div, { className: "p-3 space-y-1", children: [_jsx(Text, { className: "font-medium text-sm line-clamp-1", children: row.primary }), _jsxs(Row, { className: "gap-2 items-center", children: [_jsx(Badge, { variant: KIND_BADGE_VARIANT[row.listingKind] ?? "default", children: row.listingKind }), _jsx(Text, { className: "text-xs text-[var(--appkit-color-text-muted)] line-clamp-1", children: row.secondary })] })] })] }), _jsxs(Div, { className: "border-t border-[var(--appkit-color-border)] flex justify-end gap-1 p-2", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: (e) => { e.stopPropagation(); onEdit(row); }, "aria-label": "Edit", children: "Edit" }), _jsx(Button, { variant: "ghost", size: "sm", onClick: (e) => { e.stopPropagation(); onDuplicate(row); }, "aria-label": "Duplicate", children: "Duplicate" }), onDelete && (_jsx(Button, { variant: "ghost", size: "sm", onClick: (e) => { e.stopPropagation(); onDelete(row); }, "aria-label": "Delete", children: "Delete" }))] })] }, row.id)) : (_jsxs(Div, { className: `flex items-center gap-3 rounded-lg border bg-[var(--appkit-color-surface)] px-3 py-2 hover:bg-[var(--appkit-color-surface-raised)] ${borderCls}`, children: [_jsx("input", { type: "checkbox", checked: isSelected, onChange: () => toggle(row.id), className: "h-4 w-4 rounded border-[var(--appkit-color-border)]", "aria-label": "Select" }), row.imageUrl ? (_jsx("img", { src: row.imageUrl, alt: "", className: "w-12 h-12 rounded object-cover" })) : (_jsx(Div, { className: "w-12 h-12 rounded bg-[var(--appkit-color-surface-raised)]" })), _jsxs("a", { href: href, className: "flex-1 min-w-0", children: [_jsx(Text, { className: "font-medium text-sm line-clamp-1", children: row.primary }), _jsxs(Row, { className: "gap-2 items-center", children: [_jsx(Badge, { variant: KIND_BADGE_VARIANT[row.listingKind] ?? "default", children: row.listingKind }), _jsx(Text, { className: "text-xs text-[var(--appkit-color-text-muted)] line-clamp-1", children: row.secondary })] })] }), _jsxs(Row, { className: "gap-1 flex-shrink-0", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: () => onEdit(row), "aria-label": "Edit", children: "Edit" }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => onDuplicate(row), "aria-label": "Duplicate", children: "Duplicate" }), onDelete && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => onDelete(row), "aria-label": "Delete", children: "Delete" }))] })] }, row.id));
|
|
18
|
+
})] }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface SellerProductsFilterDrawerProps {
|
|
2
|
+
isOpen: boolean;
|
|
3
|
+
pendingFilters: Record<string, string>;
|
|
4
|
+
statusOptions: ReadonlyArray<{
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
}>;
|
|
8
|
+
activeFilterCount: number;
|
|
9
|
+
onChange: (next: Record<string, string>) => void;
|
|
10
|
+
onClear: () => void;
|
|
11
|
+
onApply: () => void;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
}
|
|
14
|
+
export declare function SellerProductsFilterDrawer({ isOpen, pendingFilters, statusOptions, activeFilterCount, onChange, onClear, onApply, onClose, }: SellerProductsFilterDrawerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { X } from "lucide-react";
|
|
4
|
+
import { Button, Div, FilterChipGroup, Row, Text } from "../../../ui";
|
|
5
|
+
import { INPUT_CLS, FILTER_LABEL_CLS } from "./seller-products-styles";
|
|
6
|
+
import { CategoryInlineSelect } from "./CategoryInlineSelect";
|
|
7
|
+
import { BrandInlineSelect } from "./BrandInlineSelect";
|
|
8
|
+
const HALF_INPUT_CLS = INPUT_CLS.replace("w-full", "w-1/2");
|
|
9
|
+
const CONDITION_OPTIONS = [
|
|
10
|
+
{ value: "", label: "Any" },
|
|
11
|
+
{ value: "mint", label: "Mint" },
|
|
12
|
+
{ value: "new", label: "New" },
|
|
13
|
+
{ value: "used", label: "Used" },
|
|
14
|
+
{ value: "refurbished", label: "Refurbished" },
|
|
15
|
+
{ value: "for-parts", label: "For parts" },
|
|
16
|
+
];
|
|
17
|
+
export function SellerProductsFilterDrawer({ isOpen, pendingFilters, statusOptions, activeFilterCount, onChange, onClear, onApply, onClose, }) {
|
|
18
|
+
if (!isOpen)
|
|
19
|
+
return null;
|
|
20
|
+
const patch = (k, v) => onChange({ ...pendingFilters, [k]: v });
|
|
21
|
+
return (_jsxs(_Fragment, { children: [_jsx(Div, { role: "presentation", className: "fixed inset-0 z-40 bg-black/40", onClick: onClose }), _jsxs(Div, { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-[var(--appkit-color-surface)] shadow-2xl", children: [_jsxs(Row, { justify: "between", className: "border-b border-[var(--appkit-color-border)] px-4 py-3.5", children: [_jsx(Text, { className: "text-base font-semibold text-[var(--appkit-color-text)]", children: "Filters" }), _jsxs(Row, { className: "gap-2", children: [activeFilterCount > 0 && (_jsx(Button, { variant: "ghost", size: "sm", onClick: onClear, className: "text-xs text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-error)]", children: "Clear all" })), _jsx(Button, { variant: "ghost", size: "sm", onClick: onClose, "aria-label": "Close filters", children: _jsx(X, { className: "h-5 w-5" }) })] })] }), _jsxs(Div, { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5", children: [_jsx(FilterChipGroup, { label: "Status", tabs: statusOptions, value: pendingFilters.status ?? "", onChange: (id) => patch("status", id) }), _jsxs(Div, { className: "space-y-1.5", children: [_jsx(Text, { className: FILTER_LABEL_CLS, children: "Category" }), _jsx(CategoryInlineSelect, { value: pendingFilters.category ?? "", onChange: (v) => patch("category", v), placeholder: "Search categories\u2026" })] }), _jsxs(Div, { className: "space-y-1.5", children: [_jsx(Text, { className: FILTER_LABEL_CLS, children: "Brand" }), _jsx(BrandInlineSelect, { value: pendingFilters.brand ?? "", onChange: (v) => patch("brand", v), placeholder: "Search brands\u2026", allowCreate: false })] }), _jsxs(Div, { className: "space-y-1.5", children: [_jsx(Text, { className: FILTER_LABEL_CLS, children: "Condition" }), _jsx("select", { value: pendingFilters.condition ?? "", onChange: (e) => patch("condition", e.target.value), className: INPUT_CLS, children: CONDITION_OPTIONS.map((o) => (_jsx("option", { value: o.value, children: o.label }, o.value))) })] }), _jsxs(Div, { className: "space-y-1.5", children: [_jsx(Text, { className: FILTER_LABEL_CLS, children: "Price (\u20B9 Rupees)" }), _jsxs(Row, { className: "gap-2", children: [_jsx("input", { type: "number", min: 0, value: pendingFilters.minPrice ?? "", onChange: (e) => patch("minPrice", e.target.value), placeholder: "min", className: HALF_INPUT_CLS }), _jsx("input", { type: "number", min: 0, value: pendingFilters.maxPrice ?? "", onChange: (e) => patch("maxPrice", e.target.value), placeholder: "max", className: HALF_INPUT_CLS })] })] }), _jsxs(Div, { className: "space-y-1.5", children: [_jsx(Text, { className: FILTER_LABEL_CLS, children: "Tags (comma-separated)" }), _jsx("input", { type: "text", value: pendingFilters.tags ?? "", onChange: (e) => patch("tags", e.target.value), placeholder: "pokemon, vintage, holo", className: INPUT_CLS })] }), _jsxs(Div, { className: "space-y-1.5", children: [_jsx(Text, { className: FILTER_LABEL_CLS, children: "Badges (feature slugs)" }), _jsx("input", { type: "text", value: pendingFilters.badges ?? "", onChange: (e) => patch("badges", e.target.value), placeholder: "feature-free-shipping, feature-verified", className: INPUT_CLS })] })] }), _jsx(Div, { className: "border-t border-[var(--appkit-color-border)] px-4 py-3.5", children: _jsxs(Button, { variant: "primary", onClick: onApply, className: "w-full rounded-lg py-2.5 active:scale-[0.98]", children: ["Apply Filters", activeFilterCount > 0 ? ` (${activeFilterCount})` : ""] }) })] })] }));
|
|
22
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ListingViewShellProps } from "../../../ui";
|
|
2
2
|
export interface SellerProductsViewProps extends ListingViewShellProps {
|
|
3
3
|
onDeleteProduct?: (id: string) => Promise<void>;
|
|
4
|
+
/** S-STORE-2-E — "New Listing" toolbar button. */
|
|
5
|
+
onCreateClick?: () => void;
|
|
4
6
|
}
|
|
5
|
-
export declare function SellerProductsView({ onDeleteProduct, children, ...props }: SellerProductsViewProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare function SellerProductsView({ onDeleteProduct, onCreateClick, children, ...props }: SellerProductsViewProps): import("react/jsx-runtime").JSX.Element;
|