@mohasinac/appkit 2.7.57 → 2.7.58
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/DashboardLayoutClient.d.ts +7 -1
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -2
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/configs/tailwind.d.ts +16 -3
- package/dist/configs/tailwind.js +18 -5
- package/dist/features/account/components/AddressBook.js +1 -1
- package/dist/features/account/components/BuyerAccountGuideView.js +7 -7
- package/dist/features/account/components/BuyerAuctionsGuideView.js +7 -7
- package/dist/features/account/components/BuyerOrdersGuideView.js +6 -6
- package/dist/features/account/components/BuyerShoppingGuideView.js +7 -7
- package/dist/features/account/components/UserOffersPanel.js +1 -1
- package/dist/features/account/components/UserSupportView.js +4 -4
- package/dist/features/admin/components/AdminAdsView.js +1 -1
- package/dist/features/admin/components/AdminAllEventEntriesView.js +1 -1
- package/dist/features/admin/components/AdminAnalyticsGuideView.js +3 -3
- package/dist/features/admin/components/AdminBidsView.js +1 -1
- package/dist/features/admin/components/AdminBlogView.js +1 -1
- package/dist/features/admin/components/AdminBrandsView.js +1 -1
- package/dist/features/admin/components/AdminBundlesView.js +1 -1
- package/dist/features/admin/components/AdminCarouselView.js +2 -2
- package/dist/features/admin/components/AdminCartsView.js +1 -1
- package/dist/features/admin/components/AdminCatalogGuideView.js +5 -5
- package/dist/features/admin/components/AdminCategoriesView.js +1 -1
- package/dist/features/admin/components/AdminContactEditorView.js +2 -2
- package/dist/features/admin/components/AdminContactView.js +1 -1
- package/dist/features/admin/components/AdminContentGuideView.js +6 -6
- package/dist/features/admin/components/AdminCouponsView.js +1 -1
- package/dist/features/admin/components/AdminFaqsView.js +1 -1
- package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -1
- package/dist/features/admin/components/AdminFeaturesView.js +1 -1
- package/dist/features/admin/components/AdminGuideHubView.js +1 -1
- package/dist/features/admin/components/AdminHistoryView.js +1 -1
- package/dist/features/admin/components/AdminListingScaffold.js +1 -1
- package/dist/features/admin/components/AdminNewsletterView.js +1 -1
- package/dist/features/admin/components/AdminNotificationsView.js +1 -1
- package/dist/features/admin/components/AdminOrdersGuideView.js +5 -5
- package/dist/features/admin/components/AdminOrdersView.js +1 -1
- package/dist/features/admin/components/AdminPayoutsView.js +1 -1
- package/dist/features/admin/components/AdminProductsView.js +1 -1
- package/dist/features/admin/components/AdminReturnRequestsView.js +1 -1
- package/dist/features/admin/components/AdminReviewsView.js +1 -1
- package/dist/features/admin/components/AdminScammerEditorView.js +3 -3
- package/dist/features/admin/components/AdminScammersView.js +4 -4
- package/dist/features/admin/components/AdminSectionsView.js +1 -1
- package/dist/features/admin/components/AdminSessionsView.js +1 -1
- package/dist/features/admin/components/AdminSiteSettingsView.js +1 -1
- package/dist/features/admin/components/AdminStoreAddressesView.js +1 -1
- package/dist/features/admin/components/AdminStoresGuideView.js +6 -6
- package/dist/features/admin/components/AdminStoresView.js +1 -1
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +1 -1
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +4 -4
- package/dist/features/admin/components/AdminSupportTicketsView.js +7 -7
- package/dist/features/admin/components/AdminTeamGuideView.js +4 -4
- package/dist/features/admin/components/AdminTeamView.js +1 -1
- package/dist/features/admin/components/AdminTrustGuideView.js +5 -5
- package/dist/features/admin/components/AdminUserEditorView.js +1 -1
- package/dist/features/admin/components/AdminUsersGuideView.js +5 -5
- package/dist/features/admin/components/AdminUsersView.js +1 -1
- package/dist/features/admin/components/AdminViewCards.js +1 -1
- package/dist/features/admin/components/AdminWishlistsView.js +1 -1
- package/dist/features/admin/components/DataTable.js +1 -1
- package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +2 -2
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +2 -2
- package/dist/features/auctions/components/PlaceBidFormClient.js +1 -1
- package/dist/features/auth/components/VerifyEmailView.js +1 -1
- package/dist/features/blog/components/BlogListView.js +1 -1
- package/dist/features/blog/components/BlogPostView.js +1 -1
- package/dist/features/cart/components/CartDrawer.js +1 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +1 -1
- package/dist/features/checkout/components/CheckoutStepper.js +1 -1
- package/dist/features/collections/components/CollectionCard.js +1 -1
- package/dist/features/copilot/components/AdminCopilotView.js +2 -2
- package/dist/features/events/components/AdminEventsView.js +1 -1
- package/dist/features/events/components/EventPollWidget.js +2 -2
- package/dist/features/events/components/EventStatusBadge.js +4 -4
- package/dist/features/events/components/SpinWheelView.js +1 -1
- package/dist/features/faq/components/FAQAccordion.js +2 -2
- package/dist/features/forms/Input.js +3 -3
- package/dist/features/forms/Select.js +2 -2
- package/dist/features/forms/Textarea.js +2 -2
- package/dist/features/forms/utils.d.ts +1 -1
- package/dist/features/forms/utils.js +1 -1
- package/dist/features/homepage/components/CharacterHotspotForm.js +2 -2
- package/dist/features/layout/BottomActions.js +2 -2
- package/dist/features/layout/ListingLayout.js +3 -3
- package/dist/features/layout/TitleBarLayout.js +1 -1
- package/dist/features/media/index.d.ts +2 -0
- package/dist/features/media/index.js +1 -0
- package/dist/features/media/modals/ImageCropModal.js +1 -1
- package/dist/features/media/modals/ImageEditor.d.ts +12 -0
- package/dist/features/media/modals/ImageEditor.js +73 -0
- package/dist/features/media/upload/ImageUpload.d.ts +5 -1
- package/dist/features/media/upload/ImageUpload.js +33 -8
- package/dist/features/media/upload/MediaUploadField.d.ts +5 -1
- package/dist/features/media/upload/MediaUploadField.js +26 -12
- package/dist/features/orders/components/OrdersList.js +7 -7
- package/dist/features/orders/components/RefundHistoryTable.js +2 -2
- package/dist/features/orders/components/RefundRequestView.js +3 -3
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
- package/dist/features/pre-orders/components/PreOrderBadge.js +4 -4
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
- package/dist/features/pre-orders/components/PreorderCard.js +2 -2
- package/dist/features/products/components/CustomSectionsEditor.js +1 -1
- package/dist/features/products/components/MakeOfferButton.js +2 -2
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -2
- package/dist/features/products/components/PrizeDrawItemsEditor.js +3 -3
- package/dist/features/products/components/PrizeRevealModal.js +3 -3
- package/dist/features/products/components/ProductDetailPageView.js +4 -4
- package/dist/features/products/components/ProductFeaturesSelector.js +1 -1
- package/dist/features/products/components/ProductGrid.js +3 -3
- package/dist/features/promotions/components/CouponCard.js +2 -2
- package/dist/features/promotions/components/PromotionsView.js +1 -1
- package/dist/features/reviews/components/ReviewDetailShell.js +2 -2
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/seller/components/SellerAddressesView.js +2 -2
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +2 -2
- package/dist/features/seller/components/SellerAuctionsView.js +1 -1
- package/dist/features/seller/components/SellerBidsView.js +1 -1
- package/dist/features/seller/components/SellerBundlesView.js +2 -2
- package/dist/features/seller/components/SellerClassifiedView.js +3 -3
- package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
- package/dist/features/seller/components/SellerFeaturesView.js +1 -1
- package/dist/features/seller/components/SellerLiveView.js +4 -4
- package/dist/features/seller/components/SellerOffersPanel.js +2 -2
- package/dist/features/seller/components/SellerOffersView.js +1 -1
- package/dist/features/seller/components/SellerOrdersView.js +2 -2
- package/dist/features/seller/components/SellerPayoutMethodsView.js +2 -2
- package/dist/features/seller/components/SellerPayoutsView.js +1 -1
- package/dist/features/seller/components/SellerProductsCards.js +1 -1
- package/dist/features/seller/components/SellerProductsView.js +1 -1
- package/dist/features/seller/components/SellerReviewsView.js +1 -1
- package/dist/features/seller/components/SellerShippingConfigsView.js +3 -3
- package/dist/features/seller/components/SellerStoreCategoriesView.js +2 -2
- package/dist/features/seller/components/SellerTemplatesView.js +2 -2
- package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
- package/dist/features/stores/components/StoreFinanceGuideView.js +2 -2
- package/dist/features/stores/components/StoreHeader.js +1 -1
- package/dist/features/stores/components/StoreListingsGuideView.js +3 -3
- package/dist/features/stores/components/StoreOrdersGuideView.js +4 -4
- package/dist/features/stores/components/StoreSettingsGuideView.js +2 -2
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +4 -4
- package/dist/features/wishlist/components/WishlistPage.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/styles.css +286 -3
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/motion.d.ts +162 -0
- package/dist/tokens/motion.js +89 -0
- package/dist/ui/DataTable.js +3 -2
- package/dist/ui/components/Accordion.js +2 -1
- package/dist/ui/components/Card.d.ts +5 -2
- package/dist/ui/components/Card.js +29 -11
- package/dist/ui/components/Div.d.ts +2 -16
- package/dist/ui/components/Div.js +2 -16
- package/dist/ui/components/Layout.d.ts +9 -19
- package/dist/ui/components/Layout.js +9 -7
- package/dist/ui/components/Modal.js +7 -4
- package/dist/ui/components/Motion.d.ts +75 -0
- package/dist/ui/components/Motion.js +122 -0
- package/dist/ui/components/Semantic.d.ts +81 -14
- package/dist/ui/components/Semantic.js +75 -10
- package/dist/ui/components/Semantic.style.css +261 -2
- package/dist/ui/components/SideDrawer.d.ts +1 -1
- package/dist/ui/components/SideDrawer.js +8 -6
- package/dist/ui/components/SideModal.d.ts +1 -1
- package/dist/ui/components/SideModal.js +11 -9
- package/dist/ui/components/StackedViewShell.js +6 -1
- package/dist/ui/components/Toast.js +5 -2
- package/dist/ui/components/Typography.d.ts +44 -3
- package/dist/ui/components/Typography.js +15 -30
- package/dist/ui/components/Typography.style.css +24 -0
- package/dist/ui/components/VacationBanner.js +2 -1
- package/dist/ui/components/surface-tokens.d.ts +70 -0
- package/dist/ui/components/surface-tokens.js +68 -0
- package/dist/ui/forms/FormShell.d.ts +6 -1
- package/dist/ui/forms/FormShell.js +32 -4
- package/dist/ui/index.d.ts +9 -2
- package/dist/ui/index.js +4 -2
- package/dist/validation/schemas.d.ts +28 -28
- package/package.json +3 -1
|
@@ -171,7 +171,7 @@ export function AdminCarouselView({ children, onBulkDelete, ...props }) {
|
|
|
171
171
|
{
|
|
172
172
|
key: "status",
|
|
173
173
|
header: "Status",
|
|
174
|
-
render: (row) => (_jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${row.status === "Active" ? "bg-
|
|
174
|
+
render: (row) => (_jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${row.status === "Active" ? "bg-success-surface text-success" : "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400"}`, children: row.status })),
|
|
175
175
|
},
|
|
176
176
|
{
|
|
177
177
|
key: "updatedAt",
|
|
@@ -191,5 +191,5 @@ export function AdminCarouselView({ children, onBulkDelete, ...props }) {
|
|
|
191
191
|
] })),
|
|
192
192
|
},
|
|
193
193
|
];
|
|
194
|
-
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search slide titles", onSearchChange: setSearchInput, onSearchCommit: commitSearch, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
194
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search slide titles", onSearchChange: setSearchInput, onSearchCommit: commitSearch, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), _jsx(DataTable, { rows: displayRows, columns: columns, isLoading: isLoading, emptyLabel: "No carousel slides \u2014 use 'New slide' to add one", getRowHref: (row) => `/admin/carousel/${row.id}/edit` })] }), _jsx(CarouselFilterDrawer, { filterOpen: filterOpen, setFilterOpen: setFilterOpen, activeFilterCount: activeFilterCount, clearFilters: clearFilters, pendingFilters: pendingFilters, setPendingFilters: setPendingFilters, applyFilters: applyFilters })] }));
|
|
195
195
|
}
|
|
@@ -91,5 +91,5 @@ export function AdminCartsView({ children, ...props }) {
|
|
|
91
91
|
if (hasChildren) {
|
|
92
92
|
return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
|
|
93
93
|
}
|
|
94
|
-
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by user ID or session", 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("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
94
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by user ID or session", 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("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No carts found", selectedIds: selectedIds, onToggleSelect: toggleSelect, onToggleSelectAll: (next) => setSelectedIds(next ? new Set(rows.map((r) => r.id)) : new Set()) })] }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsx("span", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Filters" }), _jsxs("div", { className: "flex items-center gap-2", children: [activeFilterCount > 0 && (_jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 hover:text-rose-500 dark:text-zinc-400 transition-colors", children: "Clear all" })), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close", className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5", children: _jsx(FilterChipGroup, { label: "Type", tabs: TYPE_OPTIONS, value: pendingFilters.type ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, type: id })) }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsxs("button", { type: "button", onClick: applyFilters, className: "w-full rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors active:scale-[0.98]", children: ["Apply Filters", activeFilterCount > 0 ? ` (${activeFilterCount})` : ""] }) })] })] }))] }));
|
|
95
95
|
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Package, FolderTree, Tag, Star, AlertTriangle } from "lucide-react";
|
|
3
|
-
import { Div, Heading, Text, Section, Alert } from "../../../ui";
|
|
3
|
+
import { Div, Heading, Span, Text, Section, Alert } from "../../../ui";
|
|
4
4
|
import { GC } from "../../_guide-cls";
|
|
5
5
|
export function AdminCatalogGuideView() {
|
|
6
6
|
return (_jsxs(Div, { className: "space-y-8 pb-10 max-w-3xl mx-auto", children: [_jsxs(Section, { children: [_jsxs(Div, { className: "flex items-center gap-3 mb-2", children: [_jsx(Div, { className: "flex-shrink-0 w-10 h-10 rounded-xl flex items-center justify-center", style: { background: "linear-gradient(135deg,var(--appkit-color-primary-700,#4f46e5) 0%,var(--appkit-color-cobalt,#2563eb) 100%)" }, children: _jsx(Package, { className: "w-5 h-5 text-white" }) }), _jsx(Text, { className: "text-sm font-semibold text-[var(--appkit-color-text-muted)] uppercase tracking-widest", children: "Admin Guide" })] }), _jsx(Heading, { level: 1, className: "text-2xl md:text-3xl font-bold text-[var(--appkit-color-text)] mb-2", children: "Catalog" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "Products, categories, brands, and reviews \u2014 how the LetItRip catalog is structured and managed." })] }), [
|
|
7
7
|
{
|
|
8
8
|
Icon: Package, title: "Product Management",
|
|
9
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
9
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Listing types" }), ": ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "standard" }), " (prefix ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "product-" }), "), ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "auction" }), " (prefix ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "auction-" }), "), ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "pre-order" }), " (prefix ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "preorder-" }), ")."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Admin vs store creation" }), ": Admins can create products on behalf of any store via the store picker in AdminProductEditorView."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Status lifecycle" }), ": DRAFT \u2192 PUBLISHED \u2192 ARCHIVED. Published products appear in search. Archived products are hidden but not deleted."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "J13 rule" }), ": Always use ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "listingType" }), " field \u2014 the legacy ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "isAuction" }), "/", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "isPreOrder" }), " booleans have been removed. All queries use ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "where(\"listingType\", \"==\", x)" }), "."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Media URLs" }), ": Never write raw Firebase Storage URLs to Firestore. All product image URLs must use the ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "/api/media/[slug]" }), " proxy format."] })] })),
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
Icon: FolderTree, title: "Category Taxonomy",
|
|
13
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
13
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "3-tier system" }), ": Root (tier 1) \u2192 Subcategory (tier 2) \u2192 Leaf (tier 3). Only leaf categories can be assigned to products."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Key fields" }), ": ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "parentId" }), " points to the direct parent; ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "rootId" }), " always points to the tier-1 root; ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "path" }), " stores the full hierarchy path."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "isLeaf" }), ": Must be ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "true" }), " on any category that can be selected in the product form. Tier-1 and tier-2 categories must have ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "isLeaf: false" }), "."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Slug prefix" }), ": All category slugs start with ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "category-" }), "."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Adding a new root" }), ": Rare. Requires: ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "display.icon" }), ", decision on ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "showOnHomepage" }), ", and a senior admin sign-off."] })] })),
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
Icon: Tag, title: "Brands",
|
|
17
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
17
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Slug prefix" }), ": ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "brand-" }), ". Slugs are immutable after products reference them."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "displayOrder" }), ": Controls the sort order on public brand pages. Lower numbers appear first."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "isActive: false" }), ": Hides the brand from public discovery but preserves historical product links. Use this instead of deleting a brand."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "logoURL / bannerURL" }), ": Must use the ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "/api/media/" }), " proxy \u2014 never raw Storage URLs."] })] })),
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
Icon: Star, title: "Reviews",
|
|
21
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
21
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "isVerifiedPurchase" }), ": Set automatically by the system after order DELIVERED. Never manually toggle this field."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "sellerResponse" }), ": Written by the seller via their store dashboard. Admins should not edit seller responses \u2014 only remove clearly violating ones."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "When to delete vs hide" }), ": Delete for violations (PII, slurs, spam). Hide (move to unlisted) if a dispute is pending resolution."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "helpfulCount" }), ": Read-only \u2014 incremented by buyer votes. Do not manually edit this field."] })] })),
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
Icon: AlertTriangle, title: "Common Admin Mistakes",
|
|
@@ -101,5 +101,5 @@ export function AdminCategoriesView({ children, getRowHref, ...props }) {
|
|
|
101
101
|
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(Heading, { level: 1, className: "sr-only", children: "Categories" }), _jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search categories, slugs, or parent category", 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, extra: _jsxs(Button, { size: "sm", onClick: openCreatePanel, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add Category"] }) }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
102
102
|
{ id: "edit", label: ACTIONS.ADMIN["edit-category"].label, variant: "primary", onClick: () => { const id = selection.selectedIds[0]; if (id)
|
|
103
103
|
openEditPanel(id); selection.clearSelection(); } },
|
|
104
|
-
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
104
|
+
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), view === "table" ? (_jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No categories found", selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: (next) => next ? selection.setSelectedIds(rows.map(r => r.id)) : selection.clearSelection(), onRowClick: (row) => openEditPanel(row.id) })) : (_jsx(AdminViewCards, { rows: rows, view: view, isLoading: isLoading, emptyLabel: "No categories found", onRowClick: (row) => openEditPanel(row.id), selectedIdSet: selection.selectedIdSet, onToggleSelect: selection.toggle }))] }), _jsx(CategoriesFilterDrawer, { filterOpen: filterOpen, setFilterOpen: setFilterOpen, activeFilterCount: activeFilterCount, clearFilters: clearFilters, pendingFilters: pendingFilters, setPendingFilters: setPendingFilters, applyFilters: applyFilters }), _jsx(SideDrawer, { isOpen: isCreateOpen || isEditOpen, onClose: closePanel, title: isCreateOpen ? "Add Category" : "Edit Category", mode: isCreateOpen ? "create" : "edit", children: (isCreateOpen || isEditOpen) && (_jsx(AdminCategoryEditorView, { categoryId: editId ?? undefined, onSaved: closePanel, onDeleted: closePanel, embedded: true })) })] }));
|
|
105
105
|
}
|
|
@@ -22,9 +22,9 @@ export function AdminContactEditorView({ open, onClose, submissionId, subject, n
|
|
|
22
22
|
},
|
|
23
23
|
});
|
|
24
24
|
const statusColor = {
|
|
25
|
-
new: "bg-
|
|
25
|
+
new: "bg-info-surface text-info",
|
|
26
26
|
read: "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400",
|
|
27
|
-
resolved: "bg-
|
|
27
|
+
resolved: "bg-success-surface text-success",
|
|
28
28
|
};
|
|
29
29
|
return (_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: subject ?? "Contact Submission", children: _jsxs(Div, { className: "flex flex-col gap-5 p-4", children: [_jsxs(Div, { className: "flex items-center gap-2", children: [_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "Status:" }), _jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${statusColor[currentStatus ?? "new"] ?? statusColor.new}`, children: currentStatus ?? "new" })] }), _jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Text, { className: "text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wide", children: "From" }), _jsx(Text, { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: name ?? "Unknown" }), email && (_jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: email }))] }), _jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Text, { className: "text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wide", children: "Message" }), _jsx(Div, { className: "rounded-lg border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800 p-3 max-h-64 overflow-y-auto", children: _jsx(Text, { className: "text-sm text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap leading-relaxed", children: message ?? "No message body." }) })] }), _jsxs(FormActions, { align: "right", children: [email && (_jsx(Button, { type: "button", variant: "outline", onClick: () => {
|
|
30
30
|
window.location.href = `mailto:${email}?subject=Re: ${encodeURIComponent(subject ?? "")}`;
|
|
@@ -146,7 +146,7 @@ export function AdminContactView({ children, onBulkMarkRead, onBulkArchive, onBu
|
|
|
146
146
|
if (hasChildren) {
|
|
147
147
|
return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
|
|
148
148
|
}
|
|
149
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by subject, name, or email", 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("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
149
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by subject, name, or email", 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("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No contact submissions found", renderRowActions: (row) => {
|
|
150
150
|
const cr = row;
|
|
151
151
|
return (_jsx(RowActionMenu, { actions: [
|
|
152
152
|
{ label: ROW_ACTION_META[ROW_ACTION_ID.VIEW].label, onClick: () => { setSelectedRow(cr); setDrawerOpen(true); } },
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { FileText, Calendar, BookOpen, Layout, Grid, Megaphone, Mail } from "lucide-react";
|
|
3
|
-
import { Div, Heading, Text, Section, Alert } from "../../../ui";
|
|
3
|
+
import { Div, Heading, Span, Text, Section, Alert } from "../../../ui";
|
|
4
4
|
import { GC } from "../../_guide-cls";
|
|
5
5
|
export function AdminContentGuideView() {
|
|
6
6
|
return (_jsxs(Div, { className: "space-y-8 pb-10 max-w-3xl mx-auto", children: [_jsxs(Section, { children: [_jsxs(Div, { className: "flex items-center gap-3 mb-2", children: [_jsx(Div, { className: "flex-shrink-0 w-10 h-10 rounded-xl flex items-center justify-center", style: { background: "linear-gradient(135deg,var(--appkit-color-primary-700,#4f46e5) 0%,var(--appkit-color-cobalt,#2563eb) 100%)" }, children: _jsx(FileText, { className: "w-5 h-5 text-white" }) }), _jsx(Text, { className: "text-sm font-semibold text-[var(--appkit-color-text-muted)] uppercase tracking-widest", children: "Admin Guide" })] }), _jsx(Heading, { level: 1, className: "text-2xl md:text-3xl font-bold text-[var(--appkit-color-text)] mb-2", children: "Content & Marketing" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "Blog posts, events, FAQs, carousel, homepage sections, ads, and newsletter on LetItRip." })] }), [
|
|
7
7
|
{
|
|
8
8
|
Icon: FileText, title: "Blog Posts",
|
|
9
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
9
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Statuses" }), ": ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "draft" }), " (not public), ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "published" }), " (live, indexed)."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "readTimeMinutes" }), ": Auto-calculated from content word count (200 wpm). Override manually if the post has heavy media."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "youtubeId" }), ": Optional embedded YouTube video. Use only the video ID (e.g. ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "dQw4w9WgXcQ" }), "), not the full URL."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Media in body" }), ": All images in rich text must use the ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "/api/media/" }), " proxy URL, not raw Firebase Storage links."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "isFeatured" }), ": Sets the post as featured in the blog listing. Different from the homepage featured section \u2014 that is driven by a separate ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "homepageSections" }), " config."] })] })),
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
Icon: Calendar, title: "Events",
|
|
13
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
13
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Event types" }), ": ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "sale" }), ", ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "offer" }), ", ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "poll" }), ", ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "survey" }), ", ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "feedback" }), ", ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "raffle" }), ", ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "spin_wheel" }), "."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Status" }), ": Computed from ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "startsAt" }), "/", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "endsAt" }), " (upcoming \u2192 active \u2192 ended). Do not set a status field manually \u2014 it will be overwritten."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "stats.totalEntries vs approvedEntries" }), ": ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "totalEntries" }), " = all submitted (including waitlisted); ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "approvedEntries" }), " = CONFIRMED only."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Cancelling an entry" }), ": Set status to CANCELLED in the entry doc. Do not delete entries \u2014 audit trail is needed for raffle fairness."] })] })),
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
Icon: BookOpen, title: "FAQs",
|
|
17
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
17
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Categories" }), " and where they appear: Shipping (help + footer), Returns (help), Payments (help), Auctions (help), Pre-orders (help). Set ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "showOnHomepage: true" }), " for up to 5 FAQs shown on the public home page."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "searchTokens[]" }), ": Must be manually filled \u2014 drives the FAQ search feature. Include synonyms, misspellings, and related keywords."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "priority + order" }), ": ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "priority" }), " sorts FAQs within their category; ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "order" }), " is the global absolute position. ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "isPinned: true" }), " floats the FAQ above non-pinned items in its category."] })] })),
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
Icon: Layout, title: "Carousel Slides",
|
|
21
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
21
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "MAX_ACTIVE_SLIDES = 5" }), ": You cannot activate a 6th slide. Deactivate an existing slide first."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "background.type" }), ": ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "image" }), ", ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "video" }), ", ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "color" }), ", ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "gradient" }), ". Do not have 2 active video slides simultaneously \u2014 auto-playing two videos degrades mobile performance."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Reordering" }), ": Drag slides in AdminCarouselView to reorder. The ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "order" }), " field is updated automatically."] }), _jsxs("li", { children: [_jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "cards[]" }), ": Each slide contains an array of content cards displayed as an overlay. Max 3 cards per slide recommended for readability."] })] })),
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
Icon: Grid, title: "Homepage Sections",
|
|
25
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
25
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "21 section types" }), ": product-grid, brand-grid, category-grid, event-highlight, blog-preview, etc. The full list and config shapes are in ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "appkit/src/features/homepage/schemas/firestore.ts" }), "."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "order" }), ": Controls render sequence on the public homepage. Lower numbers appear higher on the page."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "enabled: false" }), ": Hides the section without deleting it \u2014 useful for temporary removal."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Never edit Firestore directly" }), ": Always use AdminSectionsView. The config shapes are validated on write \u2014 direct Firestore edits can produce invalid shapes that crash the home page render."] })] })),
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
Icon: Megaphone, title: "Ads",
|
|
@@ -121,5 +121,5 @@ export function AdminCouponsView({ children, getRowHref, onBulkArchive, onBulkDe
|
|
|
121
121
|
if (hasChildren) {
|
|
122
122
|
return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
|
|
123
123
|
}
|
|
124
|
-
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search codes, campaigns, or seller scopes", 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, extra: _jsxs(Button, { size: "sm", onClick: openCreatePanel, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add Coupon"] }) }), selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
124
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search codes, campaigns, or seller scopes", 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, extra: _jsxs(Button, { size: "sm", onClick: openCreatePanel, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add Coupon"] }) }), selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), isLoading ? (_jsx(Div, { className: "fluid-grid-card gap-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Div, { className: "rounded-xl border-2 border-zinc-100 dark:border-slate-700 p-4 animate-pulse space-y-3", children: [_jsx(Div, { className: "h-6 bg-zinc-200 dark:bg-slate-700 rounded w-2/3" }), _jsx(Div, { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-full" }), _jsx(Div, { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-1/2" })] }, i))) })) : rows.length === 0 ? (_jsx(Div, { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: "No coupons found" }) })) : (_jsx(Div, { className: "fluid-grid-card gap-3", children: rows.map((row) => (_jsx(CouponCard, { coupon: row.raw, onEdit: openEditPanel, onToggleActive: handleToggle, onDelete: handleDelete }, row.id))) }))] }), _jsx(CouponsFilterDrawer, { filterOpen: filterOpen, setFilterOpen: setFilterOpen, activeFilterCount: activeFilterCount, clearFilters: clearFilters, pendingFilters: pendingFilters, setPendingFilters: setPendingFilters, applyFilters: applyFilters }), _jsx(SideDrawer, { isOpen: isCreateOpen || isEditOpen, onClose: closePanel, title: isCreateOpen ? "Add Coupon" : "Edit Coupon", mode: isCreateOpen ? "create" : "edit", children: (isCreateOpen || isEditOpen) && (_jsx(AdminCouponEditorView, { couponId: editId ?? undefined, onSaved: closePanel, onDeleted: closePanel, embedded: true })) })] }));
|
|
125
125
|
}
|
|
@@ -99,5 +99,5 @@ export function AdminFaqsView({ children, getRowHref, onBulkArchive, onBulkDelet
|
|
|
99
99
|
if (hasChildren) {
|
|
100
100
|
return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
|
|
101
101
|
}
|
|
102
|
-
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(Heading, { level: 1, className: "sr-only", children: "FAQs" }), _jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search questions, categories, or tokens", 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, extra: _jsxs(Button, { size: "sm", onClick: openCreatePanel, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add FAQ"] }) }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
102
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(Heading, { level: 1, className: "sr-only", children: "FAQs" }), _jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search questions, categories, or tokens", 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, extra: _jsxs(Button, { size: "sm", onClick: openCreatePanel, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add FAQ"] }) }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), view === "table" ? (_jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No FAQs found", onRowClick: (row) => openEditPanel(row.id) })) : (_jsx(AdminViewCards, { rows: rows, view: view, isLoading: isLoading, emptyLabel: "No FAQs found", onRowClick: undefined, selectedIdSet: selection.selectedIdSet, onToggleSelect: selection.toggle }))] }), _jsx(FaqsFilterDrawer, { filterOpen: filterOpen, setFilterOpen: setFilterOpen, activeFilterCount: activeFilterCount, clearFilters: clearFilters, pendingFilters: pendingFilters, setPendingFilters: setPendingFilters, applyFilters: applyFilters }), _jsx(SideDrawer, { isOpen: isCreateOpen || isEditOpen, onClose: closePanel, title: isCreateOpen ? "Add FAQ" : "Edit FAQ", mode: isCreateOpen ? "create" : "edit", children: (isCreateOpen || isEditOpen) && (_jsx(AdminFaqEditorView, { faqId: editId ?? undefined, onSaved: closePanel, onDeleted: closePanel, embedded: true })) })] }));
|
|
103
103
|
}
|
|
@@ -41,7 +41,7 @@ function AccordionSection({ title, defaultOpen = true, children }) {
|
|
|
41
41
|
return (_jsxs(Div, { className: "rounded-lg border border-zinc-200 dark:border-zinc-700 overflow-hidden", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 bg-zinc-50 dark:bg-zinc-800/60 text-left", "aria-expanded": open, children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest text-zinc-500 dark:text-zinc-400", children: title }), _jsx("svg", { className: `h-4 w-4 text-zinc-400 transition-transform ${open ? "rotate-180" : ""}`, fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), open && (_jsx(Div, { className: "divide-y divide-zinc-100 dark:divide-zinc-800", children: children }))] }));
|
|
42
42
|
}
|
|
43
43
|
function FlagRow({ label, desc, checked, onChange, rollout, onRolloutChange, showRollout }) {
|
|
44
|
-
return (_jsxs(Div, { className: "flex items-center justify-between gap-4
|
|
44
|
+
return (_jsxs(Div, { surface: "default", padding: "inline", className: "flex items-center justify-between gap-4", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Toggle, { checked: checked, onChange: onChange, label: label }), _jsx(Text, { className: "mt-0.5 ml-10 text-xs text-zinc-400 dark:text-zinc-400 truncate", children: desc })] }), showRollout && (_jsxs(Div, { className: "flex flex-col gap-1 w-28 shrink-0", children: [_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "Rollout %" }), _jsx(Input, { type: "number", min: 0, max: 100, value: rollout ?? 100, onChange: (e) => onRolloutChange?.(Math.min(100, Math.max(0, Number(e.target.value)))), disabled: !checked, className: "w-full" })] }))] }));
|
|
45
45
|
}
|
|
46
46
|
export function AdminFeatureFlagsView({ labels = {}, renderFlags, ...rest }) {
|
|
47
47
|
const queryClient = useQueryClient();
|
|
@@ -27,7 +27,7 @@ const TAB_BASE_CLASS = "rounded-full px-3 py-1 text-xs font-medium border transi
|
|
|
27
27
|
const TAB_ACTIVE_CLASS = "bg-primary text-white border-primary";
|
|
28
28
|
const TAB_INACTIVE_CLASS = "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-slate-800";
|
|
29
29
|
const PAGINATION_BAR_CLASS = "flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5";
|
|
30
|
-
const ERROR_BANNER_CLASS = "mb-4 rounded-xl border border-red-200 bg-
|
|
30
|
+
const ERROR_BANNER_CLASS = "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60";
|
|
31
31
|
function mapFeatureRow(item, index) {
|
|
32
32
|
const productTypes = Array.isArray(item.productTypes)
|
|
33
33
|
? item.productTypes
|
|
@@ -75,5 +75,5 @@ export function AdminGuideHubView({ permissions = [], isFullAdmin = false }) {
|
|
|
75
75
|
background: "linear-gradient(135deg,var(--appkit-color-primary-700,#4f46e5) 0%,var(--appkit-color-cobalt,#2563eb) 60%,var(--appkit-color-secondary-400,#7c3aed) 100%)",
|
|
76
76
|
}, children: [_jsxs(Div, { className: "flex items-center gap-3 mb-3", children: [_jsx(Div, { className: "flex-shrink-0 w-10 h-10 rounded-xl bg-white/20 flex items-center justify-center", children: _jsx(BookOpen, { className: "w-5 h-5 text-white" }) }), _jsx(Text, { className: "text-sm font-semibold text-white/80 uppercase tracking-widest", children: "Admin & Employee Guide" })] }), _jsx(Heading, { level: 1, className: "text-2xl md:text-3xl font-bold text-white mb-2", children: "LetItRip Internal Guide" }), _jsx(Text, { className: "text-white/80 text-base", children: "Everything you need to operate and manage LetItRip \u2014 India's largest collectibles marketplace." })] }) }), _jsx(Alert, { variant: "info", compact: true, children: "These guides describe expected platform behaviour. Real access to each section is enforced independently by the permission system \u2014 this page is reference only." }), !hasAny && (_jsx(Alert, { variant: "info", title: "Limited access", children: "Your permission set doesn't include read access to any admin sections yet. Contact your admin to request the permissions you need." })), hasAny && (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "text-lg font-semibold text-[var(--appkit-color-text)] mb-4", children: "Guides" }), _jsx(Div, { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: visibleCards.map(({ Icon, title, description, href }) => (_jsxs("a", { href: href, className: "group flex flex-col gap-3 rounded-xl border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] p-5 hover:border-[var(--appkit-color-primary)] hover:shadow-md transition-all", children: [_jsxs(Div, { className: "flex items-center gap-3", children: [_jsx(Div, { className: "flex-shrink-0 w-9 h-9 rounded-lg flex items-center justify-center", style: {
|
|
77
77
|
background: "linear-gradient(135deg,var(--appkit-color-primary-700,#4f46e5) 0%,var(--appkit-color-cobalt,#2563eb) 100%)",
|
|
78
|
-
}, children: _jsx(Icon, { className: "w-4 h-4 text-white" }) }), _jsx(Text, { className: "font-semibold text-[var(--appkit-color-text)] group-hover:text-[var(--appkit-color-primary)] transition-colors", children: title })] }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)] leading-relaxed", children: description }), _jsx(Text, { className: "text-xs font-medium text-[var(--appkit-color-primary)] mt-auto", children: "Read guide \u2192" })] }, title))) })] })), _jsx(Section, { className: "rounded-2xl border border-amber-200 bg-
|
|
78
|
+
}, children: _jsx(Icon, { className: "w-4 h-4 text-white" }) }), _jsx(Text, { className: "font-semibold text-[var(--appkit-color-text)] group-hover:text-[var(--appkit-color-primary)] transition-colors", children: title })] }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)] leading-relaxed", children: description }), _jsx(Text, { className: "text-xs font-medium text-[var(--appkit-color-primary)] mt-auto", children: "Read guide \u2192" })] }, title))) })] })), _jsx(Section, { className: "rounded-2xl border border-amber-200 bg-warning-surface dark:border-amber-800 p-6", children: _jsxs(Div, { className: "flex items-start gap-3", children: [_jsx(AlertTriangle, { className: "w-5 h-5 text-warning flex-shrink-0 mt-0.5" }), _jsxs(Div, { children: [_jsx(Text, { className: "font-semibold text-amber-800 dark:text-amber-300 mb-1", children: "Remember: with great access comes responsibility" }), _jsx(Text, { className: "text-sm text-amber-700 dark:text-amber-400", children: "Admin actions are logged. Never access user PII (email, phone) without a legitimate support reason. Never grant capabilities or permissions without documented approval. When in doubt, escalate to a senior admin." })] })] }) })] }));
|
|
79
79
|
}
|
|
@@ -57,5 +57,5 @@ export function AdminHistoryView({ children, ...props }) {
|
|
|
57
57
|
if (hasChildren) {
|
|
58
58
|
return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
|
|
59
59
|
}
|
|
60
|
-
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search by user ID", 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("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
60
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search by user ID", 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("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), view === "table" ? (_jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No user history records found" })) : (_jsx(AdminViewCards, { rows: rows, view: view, isLoading: isLoading, emptyLabel: "No user history records found", onRowClick: undefined, selectedIdSet: selection.selectedIdSet, onToggleSelect: selection.toggle }))] })] }));
|
|
61
61
|
}
|
|
@@ -64,5 +64,5 @@ export function AdminListingScaffold({ title, subtitle, actionLabel, actionHref,
|
|
|
64
64
|
} })), sortSlot: sortSlot ?? (_jsx(Button, { type: "button", variant: "outline", size: "sm", children: "Newest first" })), actionsSlot: actionsSlot ??
|
|
65
65
|
(actionLabel ? (actionHref ? (_jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: () => {
|
|
66
66
|
window.location.href = actionHref;
|
|
67
|
-
}, children: actionLabel })) : (_jsx(Button, { type: "button", variant: "primary", size: "sm", children: actionLabel }))) : undefined), filterActiveCount: activeFilters?.length ?? 0, filterPendingCount: 0, errorSlot: errorMessage ? (_jsx(Div, { className: "rounded-xl border border-red-200 bg-
|
|
67
|
+
}, children: actionLabel })) : (_jsx(Button, { type: "button", variant: "primary", size: "sm", children: actionLabel }))) : undefined), filterActiveCount: activeFilters?.length ?? 0, filterPendingCount: 0, errorSlot: errorMessage ? (_jsx(Div, { className: "rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })) : undefined, children: hasChildren ? (children) : (_jsx(DataTable, { columns: columns ?? buildColumns(), rows: rows, isLoading: isLoading, emptyLabel: emptyLabel, getRowHref: getRowHref, renderRowActions: renderRowActions })) }));
|
|
68
68
|
}
|
|
@@ -137,7 +137,7 @@ export function AdminNewsletterView({ children, onBulkUnsubscribe, ...props }) {
|
|
|
137
137
|
if (hasChildren) {
|
|
138
138
|
return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
|
|
139
139
|
}
|
|
140
|
-
return (_jsxs(_Fragment, { children: [selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by email or source", 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, extra: _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: handleExportCsv, children: ACTIONS.ADMIN["export-csv"].label }) }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
140
|
+
return (_jsxs(_Fragment, { children: [selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by email or source", 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, extra: _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: handleExportCsv, children: ACTIONS.ADMIN["export-csv"].label }) }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No subscribers found", renderRowActions: (row) => {
|
|
141
141
|
const nr = row;
|
|
142
142
|
return (_jsx(RowActionMenu, { actions: [
|
|
143
143
|
{
|
|
@@ -122,7 +122,7 @@ export function AdminNotificationsView({ children, ...props }) {
|
|
|
122
122
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by title or user ID", 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 }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
123
123
|
{ id: ROW_ACTION_ID.MARK_READ, label: ACTIONS.ADMIN["mark-read"].label, variant: "primary", onClick: () => { selection.clearSelection(); } },
|
|
124
124
|
{ id: ROW_ACTION_ID.DELETE, label: ACTIONS.ADMIN["delete-notification"].label, variant: "secondary", onClick: () => { selection.clearSelection(); } },
|
|
125
|
-
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
125
|
+
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No notifications found", renderRowActions: (row) => {
|
|
126
126
|
const nr = row;
|
|
127
127
|
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
128
128
|
{ id: ROW_ACTION_ID.MARK_READ, label: ACTIONS.ADMIN["mark-read"].label, variant: "primary", onClick: () => { selection.clearSelection(); } },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { ShoppingBag, Hash, Scale, Wallet, RotateCcw, DollarSign, Gavel } from "lucide-react";
|
|
3
|
-
import { Div, Heading, Text, Section } from "../../../ui";
|
|
3
|
+
import { Div, Heading, Span, Text, Section } from "../../../ui";
|
|
4
4
|
import { GC } from "../../_guide-cls";
|
|
5
5
|
export function AdminOrdersGuideView() {
|
|
6
6
|
return (_jsxs(Div, { className: "space-y-8 pb-10 max-w-3xl mx-auto", children: [_jsxs(Section, { children: [_jsxs(Div, { className: "flex items-center gap-3 mb-2", children: [_jsx(Div, { className: "flex-shrink-0 w-10 h-10 rounded-xl flex items-center justify-center", style: { background: "linear-gradient(135deg,var(--appkit-color-primary-700,#4f46e5) 0%,var(--appkit-color-cobalt,#2563eb) 100%)" }, children: _jsx(ShoppingBag, { className: "w-5 h-5 text-white" }) }), _jsx(Text, { className: "text-sm font-semibold text-[var(--appkit-color-text-muted)] uppercase tracking-widest", children: "Admin Guide" })] }), _jsx(Heading, { level: 1, className: "text-2xl md:text-3xl font-bold text-[var(--appkit-color-text)] mb-2", children: "Orders & Finance" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "Order statuses, payouts, disputes, returns, and commission math on LetItRip." })] }), [
|
|
@@ -22,19 +22,19 @@ export function AdminOrdersGuideView() {
|
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
Icon: Scale, title: "Intervening in a Dispute",
|
|
25
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsx("li", { children: "Admin steps in when: seller is unresponsive for 3+ days on a return, or buyer escalates via support ticket." }), _jsxs("li", { children: ["Admin dispute tools: ", _jsx("
|
|
25
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsx("li", { children: "Admin steps in when: seller is unresponsive for 3+ days on a return, or buyer escalates via support ticket." }), _jsxs("li", { children: ["Admin dispute tools: ", _jsx(Span, { weight: "bold", children: "force-accept return" }), " (moves to REFUNDED and withholds seller payout), ", _jsx(Span, { weight: "bold", children: "platform credit" }), " (future feature)."] }), _jsx("li", { children: "Document your reasoning in the support ticket before taking any force action." })] })),
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
Icon: Wallet, title: "Payouts",
|
|
29
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
29
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Payout cycle" }), ": Weekly. All DELIVERED orders (minus platform commission) are batched into a single payout per store."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Status flow" }), ": PENDING \u2192 PROCESSING \u2192 PAID / FAILED."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "FAILED payout" }), ": Check the store's ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "payoutDetails" }), " \u2014 UPI VPA or bank details may be stale. Contact the seller via their store email before retrying."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "ordersIncluded" }), ": Array of order IDs bundled in this payout batch \u2014 use to audit which orders are covered."] })] })),
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
Icon: RotateCcw, title: "Return Requests",
|
|
33
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsx("li", { children: "Admin can view the return reason and attached photos on the order detail page." }), _jsxs("li", { children: [_jsx("
|
|
33
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsx("li", { children: "Admin can view the return reason and attached photos on the order detail page." }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "When to override a seller rejection" }), ": Only when photographic evidence clearly supports the buyer's claim of a significant not-as-described defect. Do not override for buyer's remorse."] }), _jsx("li", { children: "After admin override: refund is issued automatically via Razorpay (3\u20137 business days for card, 1\u20132 for UPI). Seller payout for that order is withheld." })] })),
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
Icon: DollarSign, title: "Commission & Settlement Math",
|
|
37
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
37
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "platformFee" }), ": Set in ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "siteSettings.fees.platformFee" }), " (percentage). Applied to the order's item subtotal."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "customCommissionRate" }), ": Stored on ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "StoreDocument" }), " for stores with the ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "lower_commission_rate" }), " capability. Overrides the platform default for that store."] }), _jsx("li", { children: "Payout = order subtotal \u00D7 (1 \u2212 commission rate). Shipping fees are passed through to the seller at cost." })] })),
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
Icon: Gavel, title: "Auction Settlement",
|
|
@@ -118,7 +118,7 @@ export function AdminOrdersView({ children, ...props }) {
|
|
|
118
118
|
void handleQuickStatus(id, "DELIVERED"); selection.clearSelection(); } },
|
|
119
119
|
{ id: "mark-cancelled", label: ACTIONS.ADMIN["cancel-order"].label, variant: "danger", onClick: () => { for (const id of selection.selectedIds)
|
|
120
120
|
void handleQuickStatus(id, "CANCELLED"); selection.clearSelection(); } },
|
|
121
|
-
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
121
|
+
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), view === "table" ? (_jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No orders found", selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: (next) => next ? selection.setSelectedIds(rows.map(r => r.id)) : selection.clearSelection(), renderRowActions: (row) => (_jsx(QuickEditMenu, { actions: [
|
|
122
122
|
{
|
|
123
123
|
label: "View full details",
|
|
124
124
|
onClick: () => { setSelectedRow(row); setDrawerOpen(true); },
|
|
@@ -133,7 +133,7 @@ export function AdminPayoutsView({ children, ...props }) {
|
|
|
133
133
|
}
|
|
134
134
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search stores, payout IDs, or order groups", 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, extra: _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: handleExportCsv, children: ACTIONS.ADMIN["export-csv"].label }) }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
135
135
|
{ id: "mark-paid", label: ACTIONS.ADMIN["mark-paid"].label, variant: "primary", onClick: () => { selection.clearSelection(); } },
|
|
136
|
-
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
136
|
+
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No payouts found", renderRowActions: (row) => {
|
|
137
137
|
const pr = row;
|
|
138
138
|
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
139
139
|
{ id: "mark-paid", label: ACTIONS.ADMIN["mark-paid"].label, variant: "primary", onClick: () => { selection.clearSelection(); } },
|
|
@@ -200,7 +200,7 @@ export function AdminProductsView({ children, actionHref, getRowHref, ...props }
|
|
|
200
200
|
void handleToggle(id, "isPromoted", !rows.find(r => r.id === id)?.isPromoted); selection.clearSelection(); } },
|
|
201
201
|
{ id: "sale", label: ACTIONS.ADMIN["toggle-on-sale"].label, variant: "secondary", onClick: () => { for (const id of selection.selectedIds)
|
|
202
202
|
void handleToggle(id, "isOnSale", !rows.find(r => r.id === id)?.isOnSale); selection.clearSelection(); } },
|
|
203
|
-
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
203
|
+
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), view === "table" ? (_jsx(DataTable, { rows: rows, columns: [...buildBaseColumns(), flagColumn], isLoading: isLoading, emptyLabel: "No products found", onRowClick: (row) => openEditPanel(row.id), selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: (next) => next ? selection.setSelectedIds(rows.map(r => r.id)) : selection.clearSelection(), renderRowActions: (row) => (_jsx(QuickEditMenu, { actions: [
|
|
204
204
|
{
|
|
205
205
|
label: ACTIONS.ADMIN["approve-product"].label,
|
|
206
206
|
onClick: () => handleQuickEdit(row.id, { status: "published" }),
|
|
@@ -86,7 +86,7 @@ export function AdminReturnRequestsView({ children: _children }) {
|
|
|
86
86
|
const currentPage = table.getNumber("page", 1);
|
|
87
87
|
const totalPages = Math.ceil(total / PAGE_SIZE);
|
|
88
88
|
const selection = useBulkSelection({ items: rows ?? [], keyExtractor: (r) => r.id });
|
|
89
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search by order ID or buyer", 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("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
89
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search by order ID or buyer", 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("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No return requests", renderRowActions: (row) => {
|
|
90
90
|
const rr = row;
|
|
91
91
|
return (_jsx(RowActionMenu, { actions: [
|
|
92
92
|
{
|
|
@@ -155,7 +155,7 @@ export function AdminReviewsView({ renderDetailView, children, ...props }) {
|
|
|
155
155
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search reviews, products, or seller names", 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 }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
156
156
|
{ id: "approve", label: `${ACTIONS.ADMIN["approve-review"].label} Selected`, variant: "primary", onClick: () => { selection.clearSelection(); } },
|
|
157
157
|
{ id: "reject", label: `${ACTIONS.ADMIN["reject-review"].label} Selected`, variant: "secondary", onClick: () => { selection.clearSelection(); } },
|
|
158
|
-
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
158
|
+
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No reviews found", renderRowActions: (row) => {
|
|
159
159
|
const rr = row;
|
|
160
160
|
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
161
161
|
{ id: "approve", label: `${ACTIONS.ADMIN["approve-review"].label} Selected`, variant: "primary", onClick: () => { selection.clearSelection(); } },
|
|
@@ -13,9 +13,9 @@ const STATUS_OPTIONS = [
|
|
|
13
13
|
{ label: "Removed", value: "removed" },
|
|
14
14
|
];
|
|
15
15
|
const STATUS_COLOR = {
|
|
16
|
-
pending_review: "bg-
|
|
17
|
-
verified: "bg-
|
|
18
|
-
rejected: "bg-
|
|
16
|
+
pending_review: "bg-warning-surface text-warning",
|
|
17
|
+
verified: "bg-success-surface text-success",
|
|
18
|
+
rejected: "bg-error-surface text-error",
|
|
19
19
|
removed: "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400",
|
|
20
20
|
};
|
|
21
21
|
export function AdminScammerEditorView({ open, onClose, scammerId, displayNames = [], scamType, description, phones = [], upiIds = [], currentStatus, verificationNote, reportedBy, reportedByAnon, }) {
|
|
@@ -47,9 +47,9 @@ function buildScammerColumns(setSelectedRow, setDrawerOpen) {
|
|
|
47
47
|
];
|
|
48
48
|
}
|
|
49
49
|
const STATUS_BADGE = {
|
|
50
|
-
pending_review: "bg-
|
|
51
|
-
verified: "bg-
|
|
52
|
-
rejected: "bg-
|
|
50
|
+
pending_review: "bg-warning-surface text-warning",
|
|
51
|
+
verified: "bg-success-surface text-success",
|
|
52
|
+
rejected: "bg-error-surface text-error",
|
|
53
53
|
removed: "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400",
|
|
54
54
|
};
|
|
55
55
|
export function AdminScammersView({ children, ...props }) {
|
|
@@ -134,7 +134,7 @@ export function AdminScammersView({ children, ...props }) {
|
|
|
134
134
|
}
|
|
135
135
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by name, phone, UPI ID", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => {
|
|
136
136
|
table.set("sort", v);
|
|
137
|
-
}, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
137
|
+
}, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No scammer profiles found", renderRowActions: (row) => (_jsx(RowActionMenu, { actions: [
|
|
138
138
|
{
|
|
139
139
|
label: ACTIONS.ADMIN["review-scammer"].label,
|
|
140
140
|
onClick: () => {
|