@mohasinac/appkit 3.3.3 → 3.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +1 -1
  2. package/dist/_internal/client/features/lottery/LotteryDetailView.js +2 -1
  3. package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.js +2 -1
  4. package/dist/_internal/server/features/auth/permissions.js +4 -3
  5. package/dist/_internal/server/features/cart/actions.js +1 -1
  6. package/dist/_internal/server/features/lottery/data.d.ts +2 -3
  7. package/dist/_internal/server/features/products/actions.js +1 -1
  8. package/dist/features/about/components/AboutView.js +1 -1
  9. package/dist/features/about/components/PolicyPageView.js +1 -1
  10. package/dist/features/about/components/TrackOrderView.js +1 -1
  11. package/dist/features/account/components/AddressesIndexListing.js +1 -1
  12. package/dist/features/admin/components/AdminBlogEditorView.js +1 -1
  13. package/dist/features/admin/components/AdminCarouselEditorView.js +2 -1
  14. package/dist/features/admin/components/AdminCarouselView.js +1 -1
  15. package/dist/features/admin/components/AdminNavEditorView.js +2 -1
  16. package/dist/features/admin/components/AdminProductsView.js +2 -2
  17. package/dist/features/admin/components/AdminSectionsView.js +11 -7
  18. package/dist/features/admin/components/AdminSiteSettingsView.js +2 -1
  19. package/dist/features/admin/components/DrawerFormFooter.js +2 -2
  20. package/dist/features/admin/components/QuickEditMenu.js +1 -1
  21. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +1 -1
  22. package/dist/features/admin/components/sections/adminSectionsTypes.js +3 -2
  23. package/dist/features/admin/constants/filter-tabs.js +11 -0
  24. package/dist/features/auctions/columns/index.js +1 -1
  25. package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
  26. package/dist/features/auctions/schemas/index.d.ts +2 -2
  27. package/dist/features/auth/hooks/useRBAC.js +6 -1
  28. package/dist/features/blog/columns/index.js +1 -1
  29. package/dist/features/cart/components/CartDrawer.js +2 -2
  30. package/dist/features/categories/components/BrandDetailPageView.js +1 -1
  31. package/dist/features/categories/components/BreadcrumbTrail.js +2 -1
  32. package/dist/features/categories/schemas/firestore.d.ts +1 -1
  33. package/dist/features/contact/email.js +0 -1
  34. package/dist/features/events/components/EventBanner.js +2 -1
  35. package/dist/features/events/components/EventLeaderboard.js +1 -1
  36. package/dist/features/faq/components/FAQCategorySidebar.js +2 -1
  37. package/dist/features/forms/Slider.js +5 -2
  38. package/dist/features/forms/Toggle.js +4 -1
  39. package/dist/features/homepage/components/AdSlot.js +2 -2
  40. package/dist/features/homepage/components/BeforeAfterCard.js +1 -1
  41. package/dist/features/homepage/components/CTABannerSection.js +2 -1
  42. package/dist/features/homepage/components/CharacterHotspot.js +2 -1
  43. package/dist/features/homepage/components/FAQSection.js +1 -1
  44. package/dist/features/homepage/components/FeaturedBundlesSection.js +1 -1
  45. package/dist/features/homepage/components/HowItWorksInfoView.js +1 -1
  46. package/dist/features/homepage/components/HowItWorksSection.js +1 -1
  47. package/dist/features/homepage/components/NewsletterBanner.js +1 -1
  48. package/dist/features/homepage/components/SecurityHighlightsSection.js +1 -1
  49. package/dist/features/homepage/components/SiteFeaturesSection.js +1 -1
  50. package/dist/features/homepage/components/TrustFeaturesSection.js +1 -1
  51. package/dist/features/homepage/components/TrustIndicatorsSection.js +1 -1
  52. package/dist/features/layout/BottomActions.js +29 -2
  53. package/dist/features/layout/BottomActionsContext.d.ts +36 -0
  54. package/dist/features/layout/BottomActionsContext.js +36 -0
  55. package/dist/features/orders/components/MarketplaceOrderCard.js +2 -2
  56. package/dist/features/orders/schemas/index.d.ts +2 -2
  57. package/dist/features/payments/schemas/index.d.ts +4 -4
  58. package/dist/features/products/components/BidHistory.js +1 -1
  59. package/dist/features/products/components/MarketplaceBundleCard.js +1 -1
  60. package/dist/features/products/components/ProductGalleryClient.js +1 -1
  61. package/dist/features/products/components/ShowGroupSection.js +1 -1
  62. package/dist/features/products/components/SublistingCarouselSection.js +1 -1
  63. package/dist/features/products/repository/products.repository.js +1 -1
  64. package/dist/features/products/schemas/product-features.validators.d.ts +6 -6
  65. package/dist/features/promotions/repository/claimed-coupons.repository.js +1 -1
  66. package/dist/features/reviews/columns/index.js +1 -1
  67. package/dist/features/scams/components/ScamAwarenessModal.js +1 -1
  68. package/dist/features/search/components/Search.js +1 -1
  69. package/dist/features/search/schemas/index.d.ts +2 -2
  70. package/dist/features/seller/actions/seller-actions.d.ts +2 -2
  71. package/dist/features/seller/components/SellerCouponEditorView.js +1 -1
  72. package/dist/features/seller/components/SellerGoogleReviewsView.js +1 -1
  73. package/dist/features/seller/components/SellerOrdersView.js +4 -1
  74. package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
  75. package/dist/features/seller/components/SellerProductsView.js +35 -31
  76. package/dist/features/seller/components/SellerReviewsView.js +1 -1
  77. package/dist/features/seller/schemas/index.d.ts +2 -2
  78. package/dist/features/shell/QuickFormDrawer.js +1 -1
  79. package/dist/features/stores/columns/index.js +1 -1
  80. package/dist/features/stores/components/StoresIndexListing.js +20 -15
  81. package/dist/features/wishlist/actions/wishlist-actions.js +1 -1
  82. package/dist/next/ErrorBoundary.js +2 -1
  83. package/dist/next/components/NotFoundView.js +17 -0
  84. package/dist/next/components/UnauthorizedView.js +13 -0
  85. package/dist/schemas/registry.d.ts +93 -94
  86. package/dist/schemas/webhooks/razorpay.d.ts +86 -86
  87. package/dist/seed/carousel-slides-seed-data.js +3 -2
  88. package/dist/seed/defaults/homepage-sections.js +2 -1
  89. package/dist/seed/factories/carousel.factory.js +2 -1
  90. package/dist/seed/homepage-sections-seed-data.js +4 -3
  91. package/dist/seed/notifications-seed-data.js +2 -1
  92. package/dist/seed/site-settings-seed-data.js +3 -2
  93. package/dist/seo/metadata.js +2 -1
  94. package/dist/ui/columns/column-renderers.js +1 -1
  95. package/dist/ui/components/Accordion.js +10 -6
  96. package/dist/ui/components/ListingLayout.js +6 -2
  97. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
- import { Stack, Text, Heading, Badge, Section, Container, DataTable, } from "../../../../ui";
3
+ import { Stack, Text, Heading, Badge, Section, Container, DataTable } from "../../../../ui";
4
4
  /**
5
5
  * Admin-only view showing slots with price + weight + % chance.
6
6
  * Separate from LotterySlotGrid (public) which never shows price/weight.
@@ -2,6 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
4
  import { Stack, Row, Text, Heading, Badge, Section, Container, Div, Anchor, } from "../../../../ui";
5
+ import { ROUTES } from "../../../../next/routing/route-map";
5
6
  import { LotterySlotGrid } from "./LotterySlotGrid";
6
7
  import { LotteryPullForm } from "./LotteryPullForm";
7
8
  /**
@@ -13,5 +14,5 @@ export function LotteryDetailView({ event, user, currentEntry }) {
13
14
  const config = event.lotteryConfig;
14
15
  const isActive = event.status === "active";
15
16
  const isEnded = event.status === "ended" || event.status === "cancelled";
16
- return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { gap: "xl", children: [event.coverImageUrl ? (_jsx(Div, { rounded: "2xl", className: "overflow-hidden", style: { aspectRatio: "16/9", maxHeight: "16rem" }, children: _jsx("img", { src: event.coverImageUrl, alt: event.title, className: "w-full h-full object-cover" }) })) : (_jsx(Div, { rounded: "2xl", surface: "subtle", padding: "xl", align: "center", justify: "center", children: _jsx(Text, { size: "5xl", children: "\uD83C\uDFB0" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "xs", align: "center", wrap: true, children: [_jsx(Badge, { variant: isActive ? "success" : isEnded ? "danger" : "warning", children: event.status }), config && (_jsxs(Badge, { variant: "info", children: [config.slots.filter((s) => s.isBooked).length, "/", config.totalSlots, " slots claimed"] }))] }), _jsx(Heading, { level: 1, size: "3xl", weight: "bold", children: event.title }), event.description ? (_jsx(Text, { color: "muted", size: "sm", children: event.description.replace(/<[^>]+>/g, "").slice(0, 200) })) : null, event.endsAt ? (_jsxs(Text, { size: "sm", color: "muted", children: ["Ends: ", new Date(event.endsAt).toLocaleDateString("en-IN", { dateStyle: "long" })] })) : null] }), config && config.slots.length > 0 ? (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Slots" }), _jsx(LotterySlotGrid, { slots: config.slots, totalSlots: config.totalSlots })] })) : null, isActive && config && (_jsx(Div, { padding: "md", rounded: "2xl", surface: "card", className: "border border-[var(--appkit-color-border)]", children: !user ? (_jsxs(Stack, { gap: "md", className: "text-center", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Want to Participate?" }), _jsx(Text, { color: "muted", children: "Log in to submit your lottery entry." }), _jsx(Anchor, { href: "/login", tone: "brand", children: "Log In to Enter" })] })) : pulledEntry ? (_jsxs(Stack, { gap: "sm", surface: "success-surface", padding: "md", rounded: "xl", className: "border border-success/20", children: [_jsxs(Heading, { level: 2, size: "lg", weight: "bold", className: "text-success", children: ["You're Lottery #", pulledEntry.userLotteryNumber, "!"] }), _jsxs(Text, { className: "text-success", size: "sm", children: ["Assigned to Slot #", pulledEntry.assignedPrizeSlotNumber, pulledEntry.slotName ? ` — ${pulledEntry.slotName}` : "", "."] })] })) : (_jsx(LotteryPullForm, { sourceType: "event", eventId: event.id, totalSlots: config.totalSlots, maxPullsPerUser: config.maxPullsPerUser, onSuccess: (res) => setPulledEntry(res) })) })), isEnded && !pulledEntry && (_jsx(Stack, { gap: "sm", surface: "muted", padding: "md", rounded: "xl", children: _jsx(Text, { color: "muted", weight: "semibold", children: "This lottery has ended." }) }))] }) }) }));
17
+ return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { gap: "xl", children: [event.coverImageUrl ? (_jsx(Div, { rounded: "2xl", className: "overflow-hidden", style: { aspectRatio: "16/9", maxHeight: "16rem" }, children: _jsx("img", { src: event.coverImageUrl, alt: event.title, className: "w-full h-full object-cover" }) })) : (_jsx(Div, { rounded: "2xl", surface: "subtle", padding: "xl", align: "center", justify: "center", children: _jsx(Text, { size: "5xl", children: "\uD83C\uDFB0" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "xs", align: "center", wrap: true, children: [_jsx(Badge, { variant: isActive ? "success" : isEnded ? "danger" : "warning", children: event.status }), config && (_jsxs(Badge, { variant: "info", children: [config.slots.filter((s) => s.isBooked).length, "/", config.totalSlots, " slots claimed"] }))] }), _jsx(Heading, { level: 1, size: "3xl", weight: "bold", children: event.title }), event.description ? (_jsx(Text, { color: "muted", size: "sm", children: event.description.replace(/<[^>]+>/g, "").slice(0, 200) })) : null, event.endsAt ? (_jsxs(Text, { size: "sm", color: "muted", children: ["Ends: ", new Date(event.endsAt).toLocaleDateString("en-IN", { dateStyle: "long" })] })) : null] }), config && config.slots.length > 0 ? (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Slots" }), _jsx(LotterySlotGrid, { slots: config.slots, totalSlots: config.totalSlots })] })) : null, isActive && config && (_jsx(Div, { padding: "md", rounded: "2xl", surface: "card", className: "border border-[var(--appkit-color-border)]", children: !user ? (_jsxs(Stack, { gap: "md", className: "text-center", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Want to Participate?" }), _jsx(Text, { color: "muted", children: "Log in to submit your lottery entry." }), _jsx(Anchor, { href: String(ROUTES.AUTH.LOGIN), tone: "brand", children: "Log In to Enter" })] })) : pulledEntry ? (_jsxs(Stack, { gap: "sm", surface: "success-surface", padding: "md", rounded: "xl", className: "border border-success/20", children: [_jsxs(Heading, { level: 2, size: "lg", weight: "bold", className: "text-success", children: ["You're Lottery #", pulledEntry.userLotteryNumber, "!"] }), _jsxs(Text, { className: "text-success", size: "sm", children: ["Assigned to Slot #", pulledEntry.assignedPrizeSlotNumber, pulledEntry.slotName ? ` — ${pulledEntry.slotName}` : "", "."] })] })) : (_jsx(LotteryPullForm, { sourceType: "event", eventId: event.id, totalSlots: config.totalSlots, maxPullsPerUser: config.maxPullsPerUser, onSuccess: (res) => setPulledEntry(res) })) })), isEnded && !pulledEntry && (_jsx(Stack, { gap: "sm", surface: "muted", padding: "md", rounded: "xl", children: _jsx(Text, { color: "muted", weight: "semibold", children: "This lottery has ended." }) }))] }) }) }));
17
18
  }
@@ -2,6 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
4
  import { Stack, Row, Text, Heading, Badge, Section, Container, Div, Anchor, } from "../../../../ui";
5
+ import { ROUTES } from "../../../../next/routing/route-map";
5
6
  import { LotterySlotGrid } from "./LotterySlotGrid";
6
7
  import { LotteryPullForm } from "./LotteryPullForm";
7
8
  /**
@@ -14,5 +15,5 @@ export function PrizeDrawLotteryDetailView({ product, user, currentEntry, }) {
14
15
  : null);
15
16
  const config = product.lotteryConfig;
16
17
  const isActive = product.status === "published";
17
- return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { gap: "xl", children: [product.mainImage ? (_jsx(Div, { rounded: "2xl", className: "overflow-hidden", style: { aspectRatio: "16/9", maxHeight: "16rem" }, children: _jsx("img", { src: product.mainImage, alt: product.title, className: "w-full h-full object-cover" }) })) : (_jsx(Div, { rounded: "2xl", surface: "muted", padding: "xl", align: "center", justify: "center", children: _jsx(Text, { size: "5xl", children: "\uD83C\uDF81" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "xs", align: "center", wrap: true, children: [_jsx(Badge, { variant: "info", children: "Lottery Prize Draw" }), config && (_jsxs(Badge, { variant: isActive ? "success" : "secondary", children: [config.slots.filter((s) => s.isBooked).length, "/", config.totalSlots, " claimed"] }))] }), _jsx(Heading, { level: 1, size: "3xl", weight: "bold", children: product.title }), product.description ? (_jsx(Text, { color: "muted", children: product.description })) : null] }), config && config.slots.length > 0 ? (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Slots" }), _jsx(LotterySlotGrid, { slots: config.slots, totalSlots: config.totalSlots })] })) : null, isActive && config && (_jsx(Div, { padding: "md", rounded: "2xl", surface: "card", className: "border border-[var(--appkit-color-border)]", children: !user ? (_jsxs(Stack, { gap: "md", className: "text-center", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Want to Enter?" }), _jsx(Text, { color: "muted", children: "Log in to submit your entry." }), _jsx(Anchor, { href: "/login", tone: "brand", children: "Log In to Enter" })] })) : pulledEntry ? (_jsxs(Stack, { gap: "sm", surface: "success-surface", padding: "md", rounded: "xl", className: "border border-success/20", children: [_jsxs(Heading, { level: 2, size: "lg", weight: "bold", className: "text-success", children: ["You're Entry #", pulledEntry.userLotteryNumber, "!"] }), _jsxs(Text, { className: "text-success", size: "sm", children: ["Assigned to Slot #", pulledEntry.assignedPrizeSlotNumber, pulledEntry.slotName ? ` — ${pulledEntry.slotName}` : "", "."] })] })) : (_jsx(LotteryPullForm, { sourceType: "product", productId: product.id, totalSlots: config.totalSlots, maxPullsPerUser: config.maxPullsPerUser, onSuccess: (res) => setPulledEntry(res) })) }))] }) }) }));
18
+ return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { gap: "xl", children: [product.mainImage ? (_jsx(Div, { rounded: "2xl", className: "overflow-hidden", style: { aspectRatio: "16/9", maxHeight: "16rem" }, children: _jsx("img", { src: product.mainImage, alt: product.title, className: "w-full h-full object-cover" }) })) : (_jsx(Div, { rounded: "2xl", surface: "muted", padding: "xl", align: "center", justify: "center", children: _jsx(Text, { size: "5xl", children: "\uD83C\uDF81" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "xs", align: "center", wrap: true, children: [_jsx(Badge, { variant: "info", children: "Lottery Prize Draw" }), config && (_jsxs(Badge, { variant: isActive ? "success" : "secondary", children: [config.slots.filter((s) => s.isBooked).length, "/", config.totalSlots, " claimed"] }))] }), _jsx(Heading, { level: 1, size: "3xl", weight: "bold", children: product.title }), product.description ? (_jsx(Text, { color: "muted", children: product.description })) : null] }), config && config.slots.length > 0 ? (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Slots" }), _jsx(LotterySlotGrid, { slots: config.slots, totalSlots: config.totalSlots })] })) : null, isActive && config && (_jsx(Div, { padding: "md", rounded: "2xl", surface: "card", className: "border border-[var(--appkit-color-border)]", children: !user ? (_jsxs(Stack, { gap: "md", className: "text-center", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Want to Enter?" }), _jsx(Text, { color: "muted", children: "Log in to submit your entry." }), _jsx(Anchor, { href: String(ROUTES.AUTH.LOGIN), tone: "brand", children: "Log In to Enter" })] })) : pulledEntry ? (_jsxs(Stack, { gap: "sm", surface: "success-surface", padding: "md", rounded: "xl", className: "border border-success/20", children: [_jsxs(Heading, { level: 2, size: "lg", weight: "bold", className: "text-success", children: ["You're Entry #", pulledEntry.userLotteryNumber, "!"] }), _jsxs(Text, { className: "text-success", size: "sm", children: ["Assigned to Slot #", pulledEntry.assignedPrizeSlotNumber, pulledEntry.slotName ? ` — ${pulledEntry.slotName}` : "", "."] })] })) : (_jsx(LotteryPullForm, { sourceType: "product", productId: product.id, totalSlots: config.totalSlots, maxPullsPerUser: config.maxPullsPerUser, onSuccess: (res) => setPulledEntry(res) })) }))] }) }) }));
18
19
  }
@@ -9,6 +9,7 @@
9
9
  * - all other roles get empty permissions (no admin access)
10
10
  */
11
11
  import { userRepository } from "../../../../repositories";
12
+ import { ROUTES } from "../../../../next/routing/route-map";
12
13
  // ── Core resolver ─────────────────────────────────────────────────────────────
13
14
  /**
14
15
  * Fetch and resolve permissions for a user.
@@ -55,7 +56,7 @@ export function makeAdminSectionLayout(permission, opts) {
55
56
  const { redirect } = await import("next/navigation");
56
57
  const user = await opts.getUser();
57
58
  if (!user) {
58
- redirect(opts.loginPath ?? "/auth/login");
59
+ redirect(opts.loginPath ?? String(ROUTES.AUTH.LOGIN));
59
60
  return null;
60
61
  }
61
62
  // admin role passes without a permission check
@@ -63,12 +64,12 @@ export function makeAdminSectionLayout(permission, opts) {
63
64
  return children;
64
65
  // non-employee non-admin roles have no business in /admin
65
66
  if (user.role !== "employee") {
66
- redirect(opts.unauthorizedPath ?? "/unauthorized");
67
+ redirect(opts.unauthorizedPath ?? String(ROUTES.ERRORS.UNAUTHORIZED));
67
68
  return null;
68
69
  }
69
70
  const resolved = await getServerPermissions(user.uid);
70
71
  if (!checkPermission(resolved, permission)) {
71
- redirect(opts.unauthorizedPath ?? "/unauthorized");
72
+ redirect(opts.unauthorizedPath ?? String(ROUTES.ERRORS.UNAUTHORIZED));
72
73
  return null;
73
74
  }
74
75
  return children;
@@ -2,7 +2,7 @@
2
2
  import { wrapAction } from "@mohasinac/appkit/server";
3
3
  import { cartRepository } from "../../../../repositories";
4
4
  import { requireRoleUser } from "../../../../providers/auth-firebase/helpers";
5
- import { addToCartSchema, removeFromCartSchema, mergeGuestCartSchema, } from "../../../shared/features/cart/schema";
5
+ import { addToCartSchema, removeFromCartSchema, mergeGuestCartSchema } from "../../../shared/features/cart/schema";
6
6
  import { upsertCartItem, mergeGuestItems } from "./service";
7
7
  import { ValidationError } from "../../../shared/errors/index";
8
8
  export async function addToCartAction(input) {
@@ -1,6 +1,5 @@
1
1
  import type { SieveModel } from "../../../../providers/db-firebase";
2
2
  import type { EventDocument } from "../../../../features/events/schemas/firestore";
3
- import type { LotteryEntryDocument } from "../../../../features/lottery/schemas/firestore";
4
3
  import type { ClientLotteryConfig } from "../../../../features/lottery/types";
5
4
  /** Event shape with lottery config stripped of price/weight. */
6
5
  export type LotteryEventClient = Omit<EventDocument, "lotteryConfig"> & {
@@ -15,6 +14,6 @@ export declare const listLotteryEvents: (opts?: {
15
14
  pageSize?: number;
16
15
  }) => Promise<LotteryEventClient[]>;
17
16
  /** Fetch lottery entries for admin view (includes phone + txId via PII decrypt). */
18
- export declare function getLotteryEntriesForAdmin(sourceType: "event" | "product", sourceId: string, model: SieveModel): Promise<import("../../../..").FirebaseSieveResult<LotteryEntryDocument>>;
17
+ export declare function getLotteryEntriesForAdmin(sourceType: "event" | "product", sourceId: string, model: SieveModel): Promise<import("../../../..").FirebaseSieveResult<import("../../../..").LotteryEntryDocument>>;
19
18
  /** Fetch lottery entries for a specific user (own entries only). */
20
- export declare function getLotteryEntriesForUser(userId: string, model: SieveModel): Promise<import("../../../..").FirebaseSieveResult<LotteryEntryDocument>>;
19
+ export declare function getLotteryEntriesForUser(userId: string, model: SieveModel): Promise<import("../../../..").FirebaseSieveResult<import("../../../..").LotteryEntryDocument>>;
@@ -3,7 +3,7 @@ import { wrapAction } from "@mohasinac/appkit/server";
3
3
  import { productRepository } from "../../../../repositories";
4
4
  import { requireRoleUser } from "../../../../providers/auth-firebase/helpers";
5
5
  import { isAdminUser } from "../../../../features/auth/role-predicates";
6
- import { productInputSchema, productUpdateSchema, auctionInputSchema, preOrderInputSchema, setFeaturedSchema, setStatusSchema, } from "../../../shared/features/products/schema";
6
+ import { productInputSchema, productUpdateSchema, auctionInputSchema, preOrderInputSchema, setFeaturedSchema, setStatusSchema } from "../../../shared/features/products/schema";
7
7
  import { assertProductOwnership, assertStatusTransition } from "./service";
8
8
  import { ValidationError } from "../../../shared/errors/index";
9
9
  export async function createProductAction(input) {
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Card, Div, Heading, Row, Section, Span, Stack, Text } from "../../../ui";
3
3
  export function AboutView({ labels = {}, howItems = [], valueItems = [], milestones = [], ctaBannerClass = "", renderCtaButtons, }) {
4
- return (_jsxs(Div, { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", children: [_jsx(Section, { color: "inverse", tone: "accent-banner", padding: "y-4xl", children: _jsxs(Div, { paddingX: "x-page", className: "max-w-4xl mx-auto text-center", children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-6", mdSize: "5xl", size: "4xl", weight: "bold", children: labels.title }), _jsx(Text, { color: "inverse", variant: "none", className: "/80 max-w-2xl mx-auto", size: "xl", children: labels.subtitle })] }) }), _jsxs(Div, { paddingX: "x-page", className: "max-w-5xl mx-auto", padding: "y-4xl", children: [_jsxs(Section, { className: "text-center max-w-3xl mx-auto", children: [_jsx(Heading, { level: 2, className: "mb-4", children: labels.missionTitle }), _jsx(Text, { size: "lg", variant: "secondary", className: "leading-relaxed", children: labels.missionText })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-12", align: "center", children: labels.howItWorksTitle }), _jsx(Div, { className: "grid md:grid-cols-3", gap: "6", children: howItems.map(({ title, text, icon, tone }) => (_jsxs(Card, { variant: `gradient-${tone ?? "indigo"}`, padding: "md", spacing: "sm", children: [_jsx(Div, { children: _jsx(Span, { size: "4xl", children: icon }) }), _jsx(Heading, { level: 3, children: title }), _jsx(Text, { size: "sm", variant: "secondary", className: "leading-relaxed", children: text })] }, title))) })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-12", align: "center", children: labels.valuesTitle }), _jsx(Div, { className: "grid md:grid-cols-3", gap: "5", children: valueItems.map(({ title, text, icon }) => (_jsxs("div", { className: "bg-[var(--appkit-color-surface)] rounded-xl p-6 space-y-3 border border-[var(--appkit-color-border)]", children: [_jsx(Div, { children: _jsx(Span, { size: "3xl", children: icon }) }), _jsx(Heading, { level: 3, children: title }), _jsx(Text, { size: "sm", variant: "secondary", className: "leading-relaxed", children: text })] }, title))) })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-10", align: "center", children: labels.milestonesTitle }), _jsx(Stack, { className: "relative border-l-2 border-primary/30 max-w-2xl mx-auto pl-[2rem]", gap: "xl", children: milestones.map(({ year, text }) => (_jsxs(Div, { className: "relative", children: [_jsx(Div, { className: "absolute -left-10 top-1 w-4 h-4 bg-primary border-2 border-white", rounded: "full" }), _jsx(Span, { size: "xs", weight: "bold", className: "text-primary tracking-wide", transform: "uppercase", children: year }), _jsx(Text, { className: "mt-1", children: text })] }, year))) })] }), _jsxs(Section, { color: "inverse", tone: "accent-banner", className: `text-center ${ctaBannerClass}`, padding: "xl", rounded: "2xl", children: [_jsx(Heading, { color: "inverse", level: 2, variant: "none", className: "mb-8", size: "3xl", weight: "bold", children: labels.ctaTitle }), renderCtaButtons ? (renderCtaButtons()) : (_jsx(Row, { justify: "center", gap: "3", wrap: true, children: _jsxs(Span, { color: "inverse", size: "sm", className: "/70", children: [labels.ctaSell, " \u00B7 ", labels.ctaShop] }) }))] })] })] }));
4
+ return (_jsxs(Div, { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", children: [_jsx(Section, { color: "inverse", tone: "accent-banner", padding: "y-4xl", children: _jsxs(Div, { paddingX: "x-page", className: "max-w-4xl mx-auto text-center", children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-6", mdSize: "5xl", size: "4xl", weight: "bold", children: labels.title }), _jsx(Text, { color: "inverse", variant: "none", className: "/80 max-w-2xl mx-auto", size: "xl", children: labels.subtitle })] }) }), _jsxs(Div, { paddingX: "x-page", className: "max-w-5xl mx-auto", padding: "y-4xl", children: [_jsxs(Section, { className: "text-center max-w-3xl mx-auto", children: [_jsx(Heading, { level: 2, className: "mb-4", children: labels.missionTitle }), _jsx(Text, { size: "lg", variant: "secondary", className: "leading-relaxed", children: labels.missionText })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-12", align: "center", children: labels.howItWorksTitle }), _jsx(Div, { className: "grid md:grid-cols-3", gap: "6", children: howItems.map(({ title, text, icon, tone }) => (_jsxs(Card, { variant: `gradient-${tone ?? "indigo"}`, padding: "md", spacing: "sm", children: [_jsx(Div, { children: _jsx(Span, { size: "4xl", children: icon }) }), _jsx(Heading, { level: 3, children: title }), _jsx(Text, { size: "sm", variant: "secondary", className: "leading-relaxed", children: text })] }, title))) })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-12", align: "center", children: labels.valuesTitle }), _jsx(Div, { className: "grid md:grid-cols-3", gap: "5", children: valueItems.map(({ title, text, icon }) => (_jsxs(Div, { className: "bg-[var(--appkit-color-surface)] rounded-xl p-6 space-y-3 border border-[var(--appkit-color-border)]", children: [_jsx(Div, { children: _jsx(Span, { size: "3xl", children: icon }) }), _jsx(Heading, { level: 3, children: title }), _jsx(Text, { size: "sm", variant: "secondary", className: "leading-relaxed", children: text })] }, title))) })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-10", align: "center", children: labels.milestonesTitle }), _jsx(Stack, { className: "relative border-l-2 border-primary/30 max-w-2xl mx-auto pl-[2rem]", gap: "xl", children: milestones.map(({ year, text }) => (_jsxs(Div, { className: "relative", children: [_jsx(Div, { className: "absolute -left-10 top-1 w-4 h-4 bg-primary border-2 border-white", rounded: "full" }), _jsx(Span, { size: "xs", weight: "bold", className: "text-primary tracking-wide", transform: "uppercase", children: year }), _jsx(Text, { className: "mt-1", children: text })] }, year))) })] }), _jsxs(Section, { color: "inverse", tone: "accent-banner", className: `text-center ${ctaBannerClass}`, padding: "xl", rounded: "2xl", children: [_jsx(Heading, { color: "inverse", level: 2, variant: "none", className: "mb-8", size: "3xl", weight: "bold", children: labels.ctaTitle }), renderCtaButtons ? (renderCtaButtons()) : (_jsx(Row, { justify: "center", gap: "3", wrap: true, children: _jsxs(Span, { color: "inverse", size: "sm", className: "/70", children: [labels.ctaSell, " \u00B7 ", labels.ctaShop] }) }))] })] })] }));
5
5
  }
@@ -47,5 +47,5 @@ export async function PolicyPageView({ policy, }) {
47
47
  });
48
48
  return (_jsxs(Div, { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", children: [_jsx(Section, { color: "inverse", tone: "accent-banner", padding: "banner", children: _jsxs(Div, { className: `${page.container.sm}`, children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-3", children: t("title") }), _jsx(Text, { color: "inverse", variant: "none", className: "/80", size: "sm", children: t("lastUpdated") })] }) }), _jsxs(Div, { className: `${page.container.sm}`, padding: "content-banner", children: [adminHtml ? (
49
49
  /* Admin-set HTML takes priority */
50
- _jsx("div", { className: "prose prose-neutral dark:prose-invert max-w-none", dangerouslySetInnerHTML: { __html: adminHtml } })) : (_jsxs(_Fragment, { children: [t("intro") && (_jsx(Text, { variant: "secondary", className: "mb-10 leading-relaxed", size: "base", children: t("intro") })), _jsx(Stack, { gap: "xl", children: sections.map((section, i) => (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-3", children: section.heading }), _jsx(Text, { variant: "secondary", className: "leading-relaxed whitespace-pre-line", children: section.body })] }, i))) })] })), relatedLinks.length > 0 && (_jsxs(Div, { className: `mt-14 border-t`, border: "default", padding: "t-xl", children: [_jsx(Heading, { level: 3, className: "mb-3 uppercase tracking-wide", color: "muted", size: "sm", weight: "semibold", children: t("relatedTitle") }), _jsx(Row, { wrap: true, gap: "md", children: relatedLinks.map((l) => (_jsx(TextLink, { href: l.href, variant: "muted", size: "sm", children: l.label }, l.href))) })] }))] })] }));
50
+ _jsx(Div, { className: "prose prose-neutral dark:prose-invert max-w-none", dangerouslySetInnerHTML: { __html: adminHtml } })) : (_jsxs(_Fragment, { children: [t("intro") && (_jsx(Text, { variant: "secondary", className: "mb-10 leading-relaxed", size: "base", children: t("intro") })), _jsx(Stack, { gap: "xl", children: sections.map((section, i) => (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-3", children: section.heading }), _jsx(Text, { variant: "secondary", className: "leading-relaxed whitespace-pre-line", children: section.body })] }, i))) })] })), relatedLinks.length > 0 && (_jsxs(Div, { className: `mt-14 border-t`, border: "default", padding: "t-xl", children: [_jsx(Heading, { level: 3, className: "mb-3 uppercase tracking-wide", color: "muted", size: "sm", weight: "semibold", children: t("relatedTitle") }), _jsx(Row, { wrap: true, gap: "md", children: relatedLinks.map((l) => (_jsx(TextLink, { href: l.href, variant: "muted", size: "sm", children: l.label }, l.href))) })] }))] })] }));
51
51
  }
@@ -47,5 +47,5 @@ export async function TrackOrderView({} = {}) {
47
47
  bg: "bg-emerald-100 dark:bg-emerald-900/40",
48
48
  },
49
49
  ];
50
- return (_jsxs(Div, { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", children: [_jsx(Section, { color: "inverse", tone: "accent-banner", padding: "banner", children: _jsxs(Div, { className: `${page.container.sm} text-center`, children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-4", children: t("title") }), _jsx(Text, { color: "inverse", variant: "none", className: "/80", children: t("subtitle") })] }) }), _jsx(Div, { className: page.container.md, padding: "y-4xl", children: _jsxs(Stack, { gap: "hero", children: [_jsxs(Section, { className: `text-center`, border: "default", surface: "subtle", rounded: "2xl", padding: "xl", children: [_jsx(Row, { align: "center", justify: "center", className: `w-16 h-16 bg-primary/10 dark:bg-primary/15 mx-auto mb-4`, rounded: "full", children: _jsx(ShoppingBag, { className: "w-8 h-8 text-primary" }) }), _jsx(Heading, { level: 2, className: "mb-3", children: t("signInPrompt") }), _jsxs(Stack, { direction: "sm-row", justify: "center", className: "mt-6", gap: "3", children: [_jsx(TextLink, { rounded: "lg", paddingX: "xl", paddingY: "md", layout: "inline-flex", align: "center", justify: "center", gap: "sm", href: String(ROUTES.AUTH.LOGIN), className: `bg-primary hover:bg-primary/90 text-white transition-colors`, weight: "medium", children: t("signIn") }), _jsx(TextLink, { rounded: "lg", paddingX: "xl", paddingY: "md", layout: "inline-flex", align: "center", justify: "center", gap: "sm", href: String(ROUTES.USER.ORDERS), className: `${themed.bgPrimary} border ${themed.border} ${themed.textPrimary} hover:opacity-80 transition-opacity`, weight: "medium", children: t("viewOrders") })] })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-10", align: "center", children: t("howItWorksTitle") }), _jsx(Grid, { className: "grid-cols-1 sm:grid-cols-2 xl:grid-cols-4", gap: "lg", children: STEPS.map(({ icon: Icon, title, text, color, bg }, index) => (_jsxs("div", { className: `${themed.bgSecondary} rounded-xl border ${themed.border} p-6 relative`, children: [_jsx(Caption, { className: "absolute top-4 right-4", weight: "bold", children: String(index + 1).padStart(2, "0") }), _jsx(Row, { align: "center", justify: "center", className: `w-12 h-12 ${bg} mb-4`, rounded: "xl", children: _jsx(Icon, { className: `w-6 h-6 ${color}` }) }), _jsx(Heading, { level: 3, className: "mb-2", children: title }), _jsx(Text, { variant: "secondary", size: "sm", className: "leading-relaxed", children: text })] }, title))) })] }), _jsxs(Section, { layout: "flex-sm-row-between", gap: "md", border: "default", surface: "subtle", rounded: "xl", padding: "lg", children: [_jsxs(Div, { children: [_jsx(Heading, { level: 2, className: "mb-1", children: t("needHelpTitle") }), _jsx(Text, { variant: "secondary", size: "sm", children: t("needHelpText") })] }), _jsxs(Row, { gap: "3", className: "flex-shrink-0", children: [_jsx(TextLink, { href: String(ROUTES.PUBLIC.HELP), className: `${themed.textSecondary} hover:text-primary underline underline-offset-4 transition-colors`, size: "sm", children: t("helpCenter") }), _jsx(TextLink, { rounded: "lg", paddingX: "md", paddingY: "xs", href: String(ROUTES.PUBLIC.CONTACT), className: "bg-primary hover:bg-primary/90 text-white transition-colors", size: "sm", children: t("contactSupport") })] })] })] }) })] }));
50
+ return (_jsxs(Div, { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", children: [_jsx(Section, { color: "inverse", tone: "accent-banner", padding: "banner", children: _jsxs(Div, { className: `${page.container.sm} text-center`, children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-4", children: t("title") }), _jsx(Text, { color: "inverse", variant: "none", className: "/80", children: t("subtitle") })] }) }), _jsx(Div, { className: page.container.md, padding: "y-4xl", children: _jsxs(Stack, { gap: "hero", children: [_jsxs(Section, { className: `text-center`, border: "default", surface: "subtle", rounded: "2xl", padding: "xl", children: [_jsx(Row, { align: "center", justify: "center", className: `w-16 h-16 bg-primary/10 dark:bg-primary/15 mx-auto mb-4`, rounded: "full", children: _jsx(ShoppingBag, { className: "w-8 h-8 text-primary" }) }), _jsx(Heading, { level: 2, className: "mb-3", children: t("signInPrompt") }), _jsxs(Stack, { direction: "sm-row", justify: "center", className: "mt-6", gap: "3", children: [_jsx(TextLink, { rounded: "lg", paddingX: "xl", paddingY: "md", layout: "inline-flex", align: "center", justify: "center", gap: "sm", href: String(ROUTES.AUTH.LOGIN), className: `bg-primary hover:bg-primary/90 text-white transition-colors`, weight: "medium", children: t("signIn") }), _jsx(TextLink, { rounded: "lg", paddingX: "xl", paddingY: "md", layout: "inline-flex", align: "center", justify: "center", gap: "sm", href: String(ROUTES.USER.ORDERS), className: `${themed.bgPrimary} border ${themed.border} ${themed.textPrimary} hover:opacity-80 transition-opacity`, weight: "medium", children: t("viewOrders") })] })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-10", align: "center", children: t("howItWorksTitle") }), _jsx(Grid, { className: "grid-cols-1 sm:grid-cols-2 xl:grid-cols-4", gap: "lg", children: STEPS.map(({ icon: Icon, title, text, color, bg }, index) => (_jsxs(Div, { className: `${themed.bgSecondary} rounded-xl border ${themed.border} p-6 relative`, children: [_jsx(Caption, { className: "absolute top-4 right-4", weight: "bold", children: String(index + 1).padStart(2, "0") }), _jsx(Row, { align: "center", justify: "center", className: `w-12 h-12 ${bg} mb-4`, rounded: "xl", children: _jsx(Icon, { className: `w-6 h-6 ${color}` }) }), _jsx(Heading, { level: 3, className: "mb-2", children: title }), _jsx(Text, { variant: "secondary", size: "sm", className: "leading-relaxed", children: text })] }, title))) })] }), _jsxs(Section, { layout: "flex-sm-row-between", gap: "md", border: "default", surface: "subtle", rounded: "xl", padding: "lg", children: [_jsxs(Div, { children: [_jsx(Heading, { level: 2, className: "mb-1", children: t("needHelpTitle") }), _jsx(Text, { variant: "secondary", size: "sm", children: t("needHelpText") })] }), _jsxs(Row, { gap: "3", className: "flex-shrink-0", children: [_jsx(TextLink, { href: String(ROUTES.PUBLIC.HELP), className: `${themed.textSecondary} hover:text-primary underline underline-offset-4 transition-colors`, size: "sm", children: t("helpCenter") }), _jsx(TextLink, { rounded: "lg", paddingX: "md", paddingY: "xs", href: String(ROUTES.PUBLIC.CONTACT), className: "bg-primary hover:bg-primary/90 text-white transition-colors", size: "sm", children: t("contactSupport") })] })] })] }) })] }));
51
51
  }
@@ -74,5 +74,5 @@ export function AddressesIndexListing({ onAdd, onEdit, onDelete, }) {
74
74
  },
75
75
  });
76
76
  return (_jsxs(Stack, { gap: "md", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by address, postcode or label...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, view: view, onViewChange: (v) => { if (v === "table")
77
- return; setView(v); }, onResetAll: resetAll, hasActiveState: hasActiveState }), _jsx(Div, { className: "sm:px-[1rem]", padding: "x-sm", children: isLoading ? (_jsx(Div, { layout: "grid", gap: "4", className: "sm:grid-cols-2", children: Array.from({ length: 4 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border border-[var(--appkit-color-border)] animate-pulse p-4 space-y-2", children: [_jsx(Div, { className: "h-4 w-1/3", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-3/4", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-1/2", surface: "subtle", rounded: "default" })] }, i))) })) : addresses.length === 0 ? (_jsx(Text, { paddingY: "xl", color: "muted", size: "sm", align: "center", children: table.get(TABLE_KEYS.QUERY) ? `No addresses matching "${table.get(TABLE_KEYS.QUERY)}"` : "No saved addresses." })) : (_jsx(AddressBook, { addresses: addresses, onEdit: onEdit, onDelete: onDelete, onAdd: onAdd })) }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: _jsx(AddressFilters, { table: pendingTable }) })] }));
77
+ return; setView(v); }, onResetAll: resetAll, hasActiveState: hasActiveState }), _jsx(Div, { className: "sm:px-[1rem]", padding: "x-sm", children: isLoading ? (_jsx(Div, { layout: "grid", gap: "4", className: "sm:grid-cols-2", children: Array.from({ length: 4 }).map((_, i) => (_jsxs(Div, { className: "rounded-xl border border-[var(--appkit-color-border)] animate-pulse p-4 space-y-2", children: [_jsx(Div, { className: "h-4 w-1/3", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-3/4", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-1/2", surface: "subtle", rounded: "default" })] }, i))) })) : addresses.length === 0 ? (_jsx(Text, { paddingY: "xl", color: "muted", size: "sm", align: "center", children: table.get(TABLE_KEYS.QUERY) ? `No addresses matching "${table.get(TABLE_KEYS.QUERY)}"` : "No saved addresses." })) : (_jsx(AddressBook, { addresses: addresses, onEdit: onEdit, onDelete: onDelete, onAdd: onAdd })) }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: _jsx(AddressFilters, { table: pendingTable }) })] }));
78
78
  }
@@ -200,7 +200,7 @@ export function AdminBlogEditorView({ postId, onSaved, onDeleted, embedded, ...r
200
200
  if (embedded) {
201
201
  return _jsx(Div, { className: `${__O.yAuto} ${__P.p4}`, children: formContent });
202
202
  }
203
- const previewSection = (_jsxs("div", { className: "rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-raised)] p-5 max-h-[calc(100vh-12rem)] overflow-y-auto", children: [_jsx(Row, { textSize: "xs", textWeight: "semibold", color: "muted", className: "mb-3 uppercase tracking-wide", align: "center", gap: "sm", children: _jsx(Span, { children: "Live preview" }) }), draft.coverImage ? (_jsx("img", { src: draft.coverImage, alt: "", className: "w-full rounded-md mb-4 object-cover max-h-64" })) : null, _jsx(Heading, { level: 1, className: "mb-1", size: "2xl", weight: "bold", children: draft.title || "Untitled post" }), _jsxs(Text, { className: "text-[var(--appkit-color-text-muted)] mb-4", size: "xs", children: [draft.authorName || "Anonymous", draft.category ? ` · ${draft.category}` : ""] }), draft.excerpt ? (_jsx(Text, { className: "italic text-[var(--appkit-color-text-secondary)] mb-4", children: draft.excerpt })) : null, _jsx(RichTextRenderer, { html: draft.content || "<em>No content yet…</em>" }), draft.tags.length > 0 ? (_jsx(Row, { wrap: true, gap: "xs", className: "mt-6", children: draft.tags.map((t) => (_jsxs(Span, { size: "xs", className: "bg-[var(--appkit-color-surface)] border border-[var(--appkit-color-border)]", rounded: "full", padding: "pill-xs", children: ["#", t] }, t))) })) : null] }, "preview"));
203
+ const previewSection = (_jsxs(Div, { className: "rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-raised)] p-5 max-h-[calc(100vh-12rem)] overflow-y-auto", children: [_jsx(Row, { textSize: "xs", textWeight: "semibold", color: "muted", className: "mb-3 uppercase tracking-wide", align: "center", gap: "sm", children: _jsx(Span, { children: "Live preview" }) }), draft.coverImage ? (_jsx("img", { src: draft.coverImage, alt: "", className: "w-full rounded-md mb-4 object-cover max-h-64" })) : null, _jsx(Heading, { level: 1, className: "mb-1", size: "2xl", weight: "bold", children: draft.title || "Untitled post" }), _jsxs(Text, { className: "text-[var(--appkit-color-text-muted)] mb-4", size: "xs", children: [draft.authorName || "Anonymous", draft.category ? ` · ${draft.category}` : ""] }), draft.excerpt ? (_jsx(Text, { className: "italic text-[var(--appkit-color-text-secondary)] mb-4", children: draft.excerpt })) : null, _jsx(RichTextRenderer, { html: draft.content || "<em>No content yet…</em>" }), draft.tags.length > 0 ? (_jsx(Row, { wrap: true, gap: "xs", className: "mt-6", children: draft.tags.map((t) => (_jsxs(Span, { size: "xs", className: "bg-[var(--appkit-color-surface)] border border-[var(--appkit-color-border)]", rounded: "full", padding: "pill-xs", children: ["#", t] }, t))) })) : null] }, "preview"));
204
204
  return (_jsx(StackedViewShell, { portal: "admin", ...rest, title: isEdit ? "Edit Post" : "New Blog Post", sections: [
205
205
  _jsxs(Div, { className: "lg:grid lg:grid-cols-[3fr_2fr] lg:gap-[1.5rem]", children: [_jsx(Div, { children: formContent }), _jsx(Div, { className: "mt-6 lg:mt-0 lg:sticky lg:top-4 lg:self-start", children: previewSection })] }, "split"),
206
206
  ] }));
@@ -8,6 +8,7 @@ import { Alert, Button, ConfirmDeleteModal, Div, Form, FormActions, Heading, Inp
8
8
  import { FieldInput } from "../../../ui/forms";
9
9
  import { apiClient } from "../../../http";
10
10
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
11
+ import { ROUTES } from "../../../next/routing/route-map";
11
12
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
12
13
  const __P = {
13
14
  p3: "p-3",
@@ -213,7 +214,7 @@ export function AdminCarouselEditorView({ slideId, onSaved, onDeleted, onCancel,
213
214
  return (_jsx(StackedViewShell, { portal: "admin", ...rest, title: isEdit ? "Edit Carousel Slide" : "New Carousel Slide", sections: [
214
215
  errorMsg ? _jsx(Alert, { variant: "error", children: errorMsg }, "err") : null,
215
216
  successMsg ? _jsx(Alert, { variant: "success", children: successMsg }, "ok") : null,
216
- _jsx(Form, { schema: carouselSlideSchema, onSubmit: (e) => e.preventDefault(), spacing: "lg", children: ({ setFieldError, clearErrors }) => (_jsxs(_Fragment, { children: [_jsxs(Div, { className: CLS_PANEL, children: [_jsx(Heading, { level: 3, className: CLS_SECTION_HEADING, children: "Slide info" }), _jsx(FieldInput, { name: "title", label: "Title", value: title, onChange: (v) => setTitle(v), required: true, placeholder: "e.g. Hot Wheels RLC Exclusives" }), _jsx(Toggle, { label: "Active (visible on homepage)", checked: active, onChange: setActive }), _jsx(Input, { label: "Display order", type: "number", value: order, onChange: (e) => setOrder(e.target.value), min: 0, placeholder: "1" }), _jsx(Select, { label: "Slide height", value: height, onChange: (e) => setHeight(e.target.value), options: HEIGHT_OPTIONS }), _jsx(Input, { label: "Autoplay delay (ms)", type: "number", value: autoplayDelayMs, onChange: (e) => setAutoplayDelayMs(e.target.value), min: 1000, max: 15000, placeholder: "4000", helperText: "How long this slide shows before auto-advancing. Default: 4000 ms." })] }), _jsxs(Div, { className: CLS_PANEL, children: [_jsx(Heading, { level: 3, className: CLS_SECTION_HEADING, children: "Background" }), _jsx(BackgroundEditor, { value: background, onChange: setBackground, prefix: "slide" })] }), _jsxs(Div, { className: CLS_PANEL, children: [_jsx(Heading, { level: 3, className: CLS_SECTION_HEADING, children: "Overlay text (optional)" }), _jsx(Text, { size: "sm", color: "muted", children: "Centred text layered over the background. Leave blank to use cards only." }), _jsx(Input, { label: "Heading", value: overlayTitle, onChange: (e) => setOverlayTitle(e.target.value), placeholder: "India's #1 Collectibles Marketplace" }), _jsx(Input, { label: "Subtitle", value: overlaySubtitle, onChange: (e) => setOverlaySubtitle(e.target.value), placeholder: "Pok\u00E9mon TCG \u00B7 Hot Wheels \u00B7 Beyblade X" }), _jsx(Input, { label: "Description", value: overlayDesc, onChange: (e) => setOverlayDesc(e.target.value), placeholder: "One sentence description..." }), _jsxs(Stack, { className: `${__P.p3}`, gap: "sm", rounded: "lg", border: "default", children: [_jsx(Text, { size: "sm", weight: "medium", children: "CTA button" }), _jsx(Input, { label: "Button text", value: overlayBtnText, onChange: (e) => setOverlayBtnText(e.target.value), placeholder: "Shop Now" }), _jsx(Input, { label: "Button link", value: overlayBtnLink, onChange: (e) => setOverlayBtnLink(e.target.value), placeholder: "/products" }), _jsx(Select, { label: "Variant", value: overlayBtnVariant, onChange: (e) => setOverlayBtnVariant(e.target.value), options: VARIANT_OPTIONS.filter((v) => ["primary", "secondary", "outline"].includes(v.value)) }), _jsx(Toggle, { label: "Open in new tab", checked: overlayBtnNewTab, onChange: setOverlayBtnNewTab })] })] }), _jsxs(Div, { className: CLS_PANEL, children: [_jsxs(Row, { className: CLS_ROW_BETWEEN, children: [_jsx(Heading, { level: 3, className: CLS_SECTION_HEADING, children: "Cards (0\u20132)" }), cards.length < 2 && (_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: handleAddCard, children: "+ Add card" }))] }), cards.length === 0 && (_jsx(Text, { size: "sm", color: "faint", children: "No cards \u2014 the overlay text covers the whole slide." })), cards.map((card, i) => (_jsx(CardEditor, { card: card, index: i, otherZones: occupiedZones.filter((z) => z !== card.zone), onChange: (updated) => setCards(cards.map((c, ci) => (ci === i ? updated : c))), onRemove: () => setCards(cards.filter((_, ci) => ci !== i)) }, card.id)))] }), _jsxs(FormActions, { children: [_jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: !title || saveMutation.isPending, onClick: () => {
217
+ _jsx(Form, { schema: carouselSlideSchema, onSubmit: (e) => e.preventDefault(), spacing: "lg", children: ({ setFieldError, clearErrors }) => (_jsxs(_Fragment, { children: [_jsxs(Div, { className: CLS_PANEL, children: [_jsx(Heading, { level: 3, className: CLS_SECTION_HEADING, children: "Slide info" }), _jsx(FieldInput, { name: "title", label: "Title", value: title, onChange: (v) => setTitle(v), required: true, placeholder: "e.g. Hot Wheels RLC Exclusives" }), _jsx(Toggle, { label: "Active (visible on homepage)", checked: active, onChange: setActive }), _jsx(Input, { label: "Display order", type: "number", value: order, onChange: (e) => setOrder(e.target.value), min: 0, placeholder: "1" }), _jsx(Select, { label: "Slide height", value: height, onChange: (e) => setHeight(e.target.value), options: HEIGHT_OPTIONS }), _jsx(Input, { label: "Autoplay delay (ms)", type: "number", value: autoplayDelayMs, onChange: (e) => setAutoplayDelayMs(e.target.value), min: 1000, max: 15000, placeholder: "4000", helperText: "How long this slide shows before auto-advancing. Default: 4000 ms." })] }), _jsxs(Div, { className: CLS_PANEL, children: [_jsx(Heading, { level: 3, className: CLS_SECTION_HEADING, children: "Background" }), _jsx(BackgroundEditor, { value: background, onChange: setBackground, prefix: "slide" })] }), _jsxs(Div, { className: CLS_PANEL, children: [_jsx(Heading, { level: 3, className: CLS_SECTION_HEADING, children: "Overlay text (optional)" }), _jsx(Text, { size: "sm", color: "muted", children: "Centred text layered over the background. Leave blank to use cards only." }), _jsx(Input, { label: "Heading", value: overlayTitle, onChange: (e) => setOverlayTitle(e.target.value), placeholder: "India's #1 Collectibles Marketplace" }), _jsx(Input, { label: "Subtitle", value: overlaySubtitle, onChange: (e) => setOverlaySubtitle(e.target.value), placeholder: "Pok\u00E9mon TCG \u00B7 Hot Wheels \u00B7 Beyblade X" }), _jsx(Input, { label: "Description", value: overlayDesc, onChange: (e) => setOverlayDesc(e.target.value), placeholder: "One sentence description..." }), _jsxs(Stack, { className: `${__P.p3}`, gap: "sm", rounded: "lg", border: "default", children: [_jsx(Text, { size: "sm", weight: "medium", children: "CTA button" }), _jsx(Input, { label: "Button text", value: overlayBtnText, onChange: (e) => setOverlayBtnText(e.target.value), placeholder: "Shop Now" }), _jsx(Input, { label: "Button link", value: overlayBtnLink, onChange: (e) => setOverlayBtnLink(e.target.value), placeholder: String(ROUTES.PUBLIC.PRODUCTS) }), _jsx(Select, { label: "Variant", value: overlayBtnVariant, onChange: (e) => setOverlayBtnVariant(e.target.value), options: VARIANT_OPTIONS.filter((v) => ["primary", "secondary", "outline"].includes(v.value)) }), _jsx(Toggle, { label: "Open in new tab", checked: overlayBtnNewTab, onChange: setOverlayBtnNewTab })] })] }), _jsxs(Div, { className: CLS_PANEL, children: [_jsxs(Row, { className: CLS_ROW_BETWEEN, children: [_jsx(Heading, { level: 3, className: CLS_SECTION_HEADING, children: "Cards (0\u20132)" }), cards.length < 2 && (_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: handleAddCard, children: "+ Add card" }))] }), cards.length === 0 && (_jsx(Text, { size: "sm", color: "faint", children: "No cards \u2014 the overlay text covers the whole slide." })), cards.map((card, i) => (_jsx(CardEditor, { card: card, index: i, otherZones: occupiedZones.filter((z) => z !== card.zone), onChange: (updated) => setCards(cards.map((c, ci) => (ci === i ? updated : c))), onRemove: () => setCards(cards.filter((_, ci) => ci !== i)) }, card.id)))] }), _jsxs(FormActions, { children: [_jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: !title || saveMutation.isPending, onClick: () => {
217
218
  clearErrors();
218
219
  if (!title.trim()) {
219
220
  setFieldError("title", "Title is required");
@@ -109,7 +109,7 @@ export function AdminCarouselView({ children, onBulkDelete, ...props }) {
109
109
  {
110
110
  key: "drag",
111
111
  header: "",
112
- render: (row) => (_jsx("div", { draggable: true, onDragStart: () => handleDragStart(row.id), onDragOver: (e) => e.preventDefault(), onDrop: () => handleDrop(row.id), className: "cursor-grab active:cursor-grabbing text-zinc-400 px-1 select-none", title: "Drag to reorder", children: "\u283F" })),
112
+ render: (row) => (_jsx(Div, { draggable: true, onDragStart: () => handleDragStart(row.id), onDragOver: (e) => e.preventDefault(), onDrop: () => handleDrop(row.id), className: "cursor-grab active:cursor-grabbing text-zinc-400 px-1 select-none", title: "Drag to reorder", children: "\u283F" })),
113
113
  },
114
114
  {
115
115
  key: "primary",
@@ -5,6 +5,7 @@ import React from "react";
5
5
  import { Button, Form, FormActions, Input, Select, SideDrawer, Toggle, useToast, } from "../../../ui";
6
6
  import { apiClient } from "../../../http";
7
7
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
8
+ import { ROUTES } from "../../../next/routing/route-map";
8
9
  // --- Constants ---------------------------------------------------------------
9
10
  const ICON_OPTIONS = [
10
11
  { label: "None", value: "" },
@@ -80,5 +81,5 @@ export function AdminNavEditorView({ open, onClose, onSaved, item, parentOptions
80
81
  return (_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: isEdit ? "Edit Nav Item" : "New Nav Item", children: _jsxs(Form, { onSubmit: (e) => {
81
82
  e.preventDefault();
82
83
  saveMutation.mutate();
83
- }, spacing: "md", padding: "md", children: [_jsx(Input, { label: "Label", value: label, onChange: (e) => setLabel(e.target.value), required: true, placeholder: "e.g. Products" }), _jsx(Input, { label: "URL / href", value: href, onChange: (e) => setHref(e.target.value), required: true, placeholder: "/products", helperText: "Use relative paths (e.g. /products) or full URLs." }), _jsx(Select, { label: "Icon (optional)", options: ICON_OPTIONS, value: icon, onValueChange: setIcon }), parentOptions.length > 0 && (_jsx(Select, { label: "Parent item (for nested nav)", options: parentSelectOptions, value: parentId, onValueChange: setParentId })), _jsx(Input, { label: "Order", value: String(order), onChange: (e) => setOrder(parseInt(e.target.value, 10) || 0), type: "number", min: 0, helperText: "Lower numbers appear first." }), _jsx(Toggle, { label: "Visible in navigation", checked: isVisible, onChange: setIsVisible }), _jsxs(FormActions, { align: "right", children: [_jsx(Button, { type: "button", variant: "secondary", onClick: onClose, children: "Cancel" }), _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: !canSave || saveMutation.isPending, children: isEdit ? "Save changes" : "Create item" })] })] }) }));
84
+ }, spacing: "md", padding: "md", children: [_jsx(Input, { label: "Label", value: label, onChange: (e) => setLabel(e.target.value), required: true, placeholder: "e.g. Products" }), _jsx(Input, { label: "URL / href", value: href, onChange: (e) => setHref(e.target.value), required: true, placeholder: String(ROUTES.PUBLIC.PRODUCTS), helperText: "Use relative paths (e.g. /products) or full URLs." }), _jsx(Select, { label: "Icon (optional)", options: ICON_OPTIONS, value: icon, onValueChange: setIcon }), parentOptions.length > 0 && (_jsx(Select, { label: "Parent item (for nested nav)", options: parentSelectOptions, value: parentId, onValueChange: setParentId })), _jsx(Input, { label: "Order", value: String(order), onChange: (e) => setOrder(parseInt(e.target.value, 10) || 0), type: "number", min: 0, helperText: "Lower numbers appear first." }), _jsx(Toggle, { label: "Visible in navigation", checked: isVisible, onChange: setIsVisible }), _jsxs(FormActions, { align: "right", children: [_jsx(Button, { type: "button", variant: "secondary", onClick: onClose, children: "Cancel" }), _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: !canSave || saveMutation.isPending, children: isEdit ? "Save changes" : "Create item" })] })] }) }));
84
85
  }
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { normalizeError } from "../../../errors/normalize";
4
- import { SIEVE_OP, Stack, sieveFilter } from "@mohasinac/appkit";
4
+ import { SIEVE_OP, Stack, sieveFilter, Div } from "@mohasinac/appkit";
5
5
  import { sortBy } from "@mohasinac/appkit";
6
6
  import React, { useState, useCallback } from "react";
7
7
  import { ListingLayout, Span, Text, Toggle, useToast } from "../../../ui";
@@ -89,7 +89,7 @@ export function AdminProductsView({ children, ...props }) {
89
89
  key: "flags",
90
90
  header: "Flags",
91
91
  className: "w-56",
92
- render: (row) => (_jsx("div", { className: "flex flex-wrap gap-x-3 gap-y-1", onClick: (e) => e.stopPropagation(), onKeyDown: (e) => e.stopPropagation(), role: "presentation", children: FLAG_DEFS.map(({ key, label }) => (_jsx(Toggle, { size: "sm", label: label, checked: !!row[key], onChange: (v) => {
92
+ render: (row) => (_jsx(Div, { className: "flex flex-wrap gap-x-3 gap-y-1", onClick: (e) => e.stopPropagation(), onKeyDown: (e) => e.stopPropagation(), role: "presentation", children: FLAG_DEFS.map(({ key, label }) => (_jsx(Toggle, { size: "sm", label: label, checked: !!row[key], onChange: (v) => {
93
93
  void handleToggle(row.id, key, v);
94
94
  } }, key))) })),
95
95
  };
@@ -9,10 +9,11 @@ import { CategoryInlineSelect } from "../../seller/components/CategoryInlineSele
9
9
  import { Button, Checkbox, ConfirmDeleteModal, Div, Form, FormActions, Input, Modal, Row, Select, Stack, Text, Textarea, useToast } from "../../../ui";
10
10
  import { apiClient } from "../../../http";
11
11
  import { ADMIN_ENDPOINTS, DEMO_ENDPOINTS } from "../../../constants";
12
+ import { ROUTES } from "../../../next/routing/route-map";
12
13
  import { useAdminSectionsListing } from "../hooks/useAdminSectionsListing";
13
14
  import { DataTable } from "./DataTable";
14
15
  import { SECTION_TYPE_OPTIONS, SUPPORTED_TYPED_BUILDERS, RESOURCE_SORT_OPTIONS, FAQ_CATEGORY_OPTIONS, DEFAULT_PRODUCTS_BUILDER, DEFAULT_AUCTIONS_BUILDER, DEFAULT_STATS_BUILDER, DEFAULT_PRE_ORDERS_BUILDER, DEFAULT_STORES_BUILDER, DEFAULT_EVENTS_BUILDER, DEFAULT_SOCIAL_FEED_BUILDER, DEFAULT_WELCOME_BUILDER, DEFAULT_TRUST_INDICATORS_BUILDER, DEFAULT_CATEGORIES_BUILDER, DEFAULT_BRANDS_BUILDER, DEFAULT_BANNER_BUILDER, DEFAULT_FEATURES_BUILDER, DEFAULT_REVIEWS_BUILDER, DEFAULT_WHATSAPP_BUILDER, DEFAULT_FAQ_BUILDER, DEFAULT_BLOG_BUILDER, DEFAULT_NEWSLETTER_BUILDER, DEFAULT_CAROUSEL_BUILDER, DEFAULT_CUSTOM_CARDS_BUILDER, DEFAULT_GOOGLE_REVIEWS_BUILDER, DEFAULT_FEATURED_BUNDLES_BUILDER, DEFAULT_PRIZE_DRAWS_BUILDER, DEFAULT_EVENT_RAFFLES_BUILDER, DEFAULT_COLLECTION_CARDS_BUILDER, } from "./sections/adminSectionsTypes";
15
- import { toStringValue, buildProductsConfig, buildAuctionsConfig, buildStatsConfig, buildPreOrdersConfig, buildStoresConfig, buildEventsConfig, buildSocialFeedConfig, buildWelcomeConfig, buildTrustIndicatorsConfig, buildCategoriesConfig, buildBrandsConfig, buildBannerConfig, buildFeaturesConfig, buildReviewsConfig, buildWhatsAppConfig, buildFAQConfig, buildBlogConfig, buildNewsletterConfig, buildCarouselConfig, buildCustomCardsConfig, buildGoogleReviewsConfig, buildFeaturedBundlesConfig, buildPrizeDrawsConfig, buildEventRafflesConfig, buildCollectionCardsConfig, parseProductsBuilder, parseAuctionsBuilder, parseStatsBuilder, parsePreOrdersBuilder, parseStoresBuilder, parseEventsBuilder, parseSocialFeedBuilder, parseWelcomeBuilder, parseTrustIndicatorsBuilder, parseCategoriesBuilder, parseBrandsBuilder, parseBannerBuilder, parseFeaturesBuilder, parseReviewsBuilder, parseWhatsAppBuilder, parseFAQBuilder, parseBlogBuilder, parseNewsletterBuilder, parseCarouselBuilder, parseCustomCardsBuilder, parseGoogleReviewsBuilder, parseFeaturedBundlesBuilder, parsePrizeDrawsBuilder, parseEventRafflesBuilder, parseCollectionCardsBuilder, } from "./sections/adminSectionsBuildParse";
16
+ import { toStringValue, buildProductsConfig, buildAuctionsConfig, buildStatsConfig, buildPreOrdersConfig, buildStoresConfig, buildEventsConfig, buildSocialFeedConfig, buildWelcomeConfig, buildTrustIndicatorsConfig, buildCategoriesConfig, buildBrandsConfig, buildBannerConfig, buildFeaturesConfig, buildReviewsConfig, buildWhatsAppConfig, buildFAQConfig, buildBlogConfig, buildNewsletterConfig, buildCarouselConfig, buildCustomCardsConfig, buildGoogleReviewsConfig, buildFeaturedBundlesConfig, buildPrizeDrawsConfig, buildEventRafflesConfig, buildCollectionCardsConfig, parseProductsBuilder, parseAuctionsBuilder, parseStatsBuilder, parsePreOrdersBuilder, parseStoresBuilder, parseEventsBuilder, parseSocialFeedBuilder, parseWelcomeBuilder, parseTrustIndicatorsBuilder, parseCategoriesBuilder, parseBrandsBuilder, parseBannerBuilder, parseFeaturesBuilder, parseReviewsBuilder, parseWhatsAppBuilder, parseFAQBuilder, parseBlogBuilder, parseNewsletterBuilder, parseCarouselBuilder, parseCustomCardsBuilder, parseGoogleReviewsBuilder, parseFeaturedBundlesBuilder, parsePrizeDrawsBuilder, parseEventRafflesBuilder, parseCollectionCardsBuilder } from "./sections/adminSectionsBuildParse";
16
17
  const __P = {
17
18
  p3: "p-3",
18
19
  p4: "p-4",
@@ -705,10 +706,10 @@ export function AdminSectionsView({ children }) {
705
706
  return (_jsxs(Div, { className: CLS_SECTION_PANEL, children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Blog Articles Builder" }), _jsx(Input, { label: "Section title", value: blogBuilder.title, onChange: (e) => setBlogBuilder((prev) => ({ ...prev, title: e.target.value })) }), _jsx(Select, { label: "Max articles", value: String(blogBuilder.maxArticles), onValueChange: (v) => setBlogBuilder((prev) => ({ ...prev, maxArticles: Number(v) })), options: [{ label: "3", value: "3" }, { label: "4", value: "4" }, { label: "6", value: "6" }] }), _jsx(Checkbox, { checked: blogBuilder.showReadTime, label: "Show read time", onChange: (e) => setBlogBuilder((prev) => ({ ...prev, showReadTime: e.target.checked })) }), _jsx(Checkbox, { checked: blogBuilder.showAuthor, label: "Show author", onChange: (e) => setBlogBuilder((prev) => ({ ...prev, showAuthor: e.target.checked })) }), _jsx(Checkbox, { checked: blogBuilder.showThumbnails, label: "Show thumbnails", onChange: (e) => setBlogBuilder((prev) => ({ ...prev, showThumbnails: e.target.checked })) })] }));
706
707
  }
707
708
  function renderNewsletterBuilder() {
708
- return (_jsxs(Div, { className: CLS_SECTION_PANEL, children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Newsletter Section Builder" }), _jsx(Input, { label: "Title", value: newsletterBuilder.title, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, title: e.target.value })) }), _jsx(Textarea, { label: "Description", value: newsletterBuilder.description, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, description: e.target.value })), rows: 2 }), _jsx(Input, { label: "Email placeholder", value: newsletterBuilder.placeholder, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, placeholder: e.target.value })) }), _jsx(Input, { label: "Button text", value: newsletterBuilder.buttonText, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, buttonText: e.target.value })) }), _jsx(Input, { label: "Privacy text", value: newsletterBuilder.privacyText, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, privacyText: e.target.value })) }), _jsx(Input, { label: "Privacy link", value: newsletterBuilder.privacyLink, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, privacyLink: e.target.value })), placeholder: "/privacy" })] }));
709
+ return (_jsxs(Div, { className: CLS_SECTION_PANEL, children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Newsletter Section Builder" }), _jsx(Input, { label: "Title", value: newsletterBuilder.title, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, title: e.target.value })) }), _jsx(Textarea, { label: "Description", value: newsletterBuilder.description, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, description: e.target.value })), rows: 2 }), _jsx(Input, { label: "Email placeholder", value: newsletterBuilder.placeholder, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, placeholder: e.target.value })) }), _jsx(Input, { label: "Button text", value: newsletterBuilder.buttonText, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, buttonText: e.target.value })) }), _jsx(Input, { label: "Privacy text", value: newsletterBuilder.privacyText, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, privacyText: e.target.value })) }), _jsx(Input, { label: "Privacy link", value: newsletterBuilder.privacyLink, onChange: (e) => setNewsletterBuilder((prev) => ({ ...prev, privacyLink: e.target.value })), placeholder: String(ROUTES.PUBLIC.PRIVACY) })] }));
709
710
  }
710
711
  function renderBannerBuilder() {
711
- return (_jsxs(Div, { className: CLS_SECTION_PANEL, children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Banner Section Builder" }), _jsx(Select, { label: "Height", value: bannerBuilder.height, onValueChange: (v) => setBannerBuilder((prev) => ({ ...prev, height: v })), options: [{ label: "Small (200px)", value: "sm" }, { label: "Medium (300px)", value: "md" }, { label: "Large (400px)", value: "lg" }, { label: "Extra Large (500px)", value: "xl" }] }), _jsx(Input, { label: "Background image URL", type: "url", value: bannerBuilder.backgroundImage, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, backgroundImage: e.target.value })), placeholder: "https://..." }), _jsx(Input, { label: "Background color (CSS token)", value: bannerBuilder.backgroundColor, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, backgroundColor: e.target.value })), placeholder: "var(--appkit-color-primary)" }), _jsx(Input, { label: "Gradient from (CSS token)", value: bannerBuilder.gradientFrom, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, gradientFrom: e.target.value })), placeholder: "var(--appkit-color-primary)" }), _jsx(Input, { label: "Gradient to (CSS token)", value: bannerBuilder.gradientTo, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, gradientTo: e.target.value })), placeholder: "var(--appkit-color-secondary)" }), _jsx(Input, { label: "Content title", value: bannerBuilder.contentTitle, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, contentTitle: e.target.value })) }), _jsx(Input, { label: "Content subtitle", value: bannerBuilder.contentSubtitle, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, contentSubtitle: e.target.value })) }), _jsx(Textarea, { label: "Content description", value: bannerBuilder.contentDescription, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, contentDescription: e.target.value })), rows: 2 }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { className: "tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Buttons (max 3)" }), bannerBuilder.buttons.map((btn, index) => (_jsxs(Stack, { rounded: "md", padding: "xs", border: "default", gap: "sm", children: [_jsxs(Row, { align: "center", justify: "between", children: [_jsxs(Text, { size: "xs", color: "muted", children: ["Button ", index + 1] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setBannerBuilder((prev) => ({ ...prev, buttons: prev.buttons.filter((_, i) => i !== index) })), children: "Remove" })] }), _jsx(Input, { label: "Text", value: btn.text, onChange: (e) => setBannerBuilder((prev) => { const next = [...prev.buttons]; next[index] = { ...next[index], text: e.target.value }; return { ...prev, buttons: next }; }) }), _jsx(Input, { label: "Link", value: btn.link, onChange: (e) => setBannerBuilder((prev) => { const next = [...prev.buttons]; next[index] = { ...next[index], link: e.target.value }; return { ...prev, buttons: next }; }) }), _jsx(Select, { label: "Variant", value: btn.variant, onValueChange: (v) => setBannerBuilder((prev) => { const next = [...prev.buttons]; next[index] = { ...next[index], variant: v }; return { ...prev, buttons: next }; }), options: [{ label: "Primary", value: "primary" }, { label: "Secondary", value: "secondary" }, { label: "Outline", value: "outline" }] })] }, `banner-btn-${index}`))), bannerBuilder.buttons.length < 3 ? (_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setBannerBuilder((prev) => ({ ...prev, buttons: [...prev.buttons, { text: "", link: "", variant: "primary" }] })), children: "+ Add button" })) : null] }), _jsx(Checkbox, { checked: bannerBuilder.clickable, label: "Make entire banner clickable", onChange: (e) => setBannerBuilder((prev) => ({ ...prev, clickable: e.target.checked })) }), bannerBuilder.clickable ? (_jsx(Input, { label: "Click link", value: bannerBuilder.clickLink, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, clickLink: e.target.value })), placeholder: "/products" })) : null] }));
712
+ return (_jsxs(Div, { className: CLS_SECTION_PANEL, children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Banner Section Builder" }), _jsx(Select, { label: "Height", value: bannerBuilder.height, onValueChange: (v) => setBannerBuilder((prev) => ({ ...prev, height: v })), options: [{ label: "Small (200px)", value: "sm" }, { label: "Medium (300px)", value: "md" }, { label: "Large (400px)", value: "lg" }, { label: "Extra Large (500px)", value: "xl" }] }), _jsx(Input, { label: "Background image URL", type: "url", value: bannerBuilder.backgroundImage, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, backgroundImage: e.target.value })), placeholder: "https://..." }), _jsx(Input, { label: "Background color (CSS token)", value: bannerBuilder.backgroundColor, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, backgroundColor: e.target.value })), placeholder: "var(--appkit-color-primary)" }), _jsx(Input, { label: "Gradient from (CSS token)", value: bannerBuilder.gradientFrom, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, gradientFrom: e.target.value })), placeholder: "var(--appkit-color-primary)" }), _jsx(Input, { label: "Gradient to (CSS token)", value: bannerBuilder.gradientTo, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, gradientTo: e.target.value })), placeholder: "var(--appkit-color-secondary)" }), _jsx(Input, { label: "Content title", value: bannerBuilder.contentTitle, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, contentTitle: e.target.value })) }), _jsx(Input, { label: "Content subtitle", value: bannerBuilder.contentSubtitle, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, contentSubtitle: e.target.value })) }), _jsx(Textarea, { label: "Content description", value: bannerBuilder.contentDescription, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, contentDescription: e.target.value })), rows: 2 }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { className: "tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Buttons (max 3)" }), bannerBuilder.buttons.map((btn, index) => (_jsxs(Stack, { rounded: "md", padding: "xs", border: "default", gap: "sm", children: [_jsxs(Row, { align: "center", justify: "between", children: [_jsxs(Text, { size: "xs", color: "muted", children: ["Button ", index + 1] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setBannerBuilder((prev) => ({ ...prev, buttons: prev.buttons.filter((_, i) => i !== index) })), children: "Remove" })] }), _jsx(Input, { label: "Text", value: btn.text, onChange: (e) => setBannerBuilder((prev) => { const next = [...prev.buttons]; next[index] = { ...next[index], text: e.target.value }; return { ...prev, buttons: next }; }) }), _jsx(Input, { label: "Link", value: btn.link, onChange: (e) => setBannerBuilder((prev) => { const next = [...prev.buttons]; next[index] = { ...next[index], link: e.target.value }; return { ...prev, buttons: next }; }) }), _jsx(Select, { label: "Variant", value: btn.variant, onValueChange: (v) => setBannerBuilder((prev) => { const next = [...prev.buttons]; next[index] = { ...next[index], variant: v }; return { ...prev, buttons: next }; }), options: [{ label: "Primary", value: "primary" }, { label: "Secondary", value: "secondary" }, { label: "Outline", value: "outline" }] })] }, `banner-btn-${index}`))), bannerBuilder.buttons.length < 3 ? (_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setBannerBuilder((prev) => ({ ...prev, buttons: [...prev.buttons, { text: "", link: "", variant: "primary" }] })), children: "+ Add button" })) : null] }), _jsx(Checkbox, { checked: bannerBuilder.clickable, label: "Make entire banner clickable", onChange: (e) => setBannerBuilder((prev) => ({ ...prev, clickable: e.target.checked })) }), bannerBuilder.clickable ? (_jsx(Input, { label: "Click link", value: bannerBuilder.clickLink, onChange: (e) => setBannerBuilder((prev) => ({ ...prev, clickLink: e.target.value })), placeholder: String(ROUTES.PUBLIC.PRODUCTS) })) : null] }));
712
713
  }
713
714
  function renderFeaturesBuilder() {
714
715
  return (_jsxs(Div, { className: CLS_SECTION_PANEL, children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Features Section Builder" }), _jsx(Input, { label: "Section title", value: featuresBuilder.title, onChange: (e) => setFeaturesBuilder((prev) => ({ ...prev, title: e.target.value })) }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { className: "tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Feature items" }), featuresBuilder.features.map((feature, index) => (_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Input, { value: feature, onChange: (e) => setFeaturesBuilder((prev) => { const next = [...prev.features]; next[index] = e.target.value; return { ...prev, features: next }; }), className: "flex-1" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setFeaturesBuilder((prev) => ({ ...prev, features: prev.features.filter((_, i) => i !== index) })), children: "\u2715" })] }, `feat-${index}`))), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setFeaturesBuilder((prev) => ({ ...prev, features: [...prev.features, ""] })), children: "+ Add feature" })] })] }));
@@ -723,7 +724,7 @@ export function AdminSectionsView({ children }) {
723
724
  return (_jsxs(Div, { className: CLS_SECTION_PANEL, children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "WhatsApp Community Builder" }), _jsx(Input, { label: "Title", value: whatsappBuilder.title, onChange: (e) => setWhatsappBuilder((prev) => ({ ...prev, title: e.target.value })) }), _jsx(Textarea, { label: "Description", value: whatsappBuilder.description, onChange: (e) => setWhatsappBuilder((prev) => ({ ...prev, description: e.target.value })), rows: 2 }), _jsx(Input, { label: "WhatsApp group link", type: "url", value: whatsappBuilder.groupLink, onChange: (e) => setWhatsappBuilder((prev) => ({ ...prev, groupLink: e.target.value })), placeholder: "https://chat.whatsapp.com/..." }), _jsx(Input, { label: "Member count", type: "number", min: 0, value: String(whatsappBuilder.memberCount), onChange: (e) => setWhatsappBuilder((prev) => ({ ...prev, memberCount: Math.max(0, Number(e.target.value) || 0) })) }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { className: "tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Benefits" }), whatsappBuilder.benefits.map((benefit, index) => (_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Input, { value: benefit, onChange: (e) => setWhatsappBuilder((prev) => { const next = [...prev.benefits]; next[index] = e.target.value; return { ...prev, benefits: next }; }), className: "flex-1" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setWhatsappBuilder((prev) => ({ ...prev, benefits: prev.benefits.filter((_, i) => i !== index) })), children: "\u2715" })] }, `wb-${index}`))), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setWhatsappBuilder((prev) => ({ ...prev, benefits: [...prev.benefits, ""] })), children: "+ Add benefit" })] }), _jsx(Input, { label: "Button text", value: whatsappBuilder.buttonText, onChange: (e) => setWhatsappBuilder((prev) => ({ ...prev, buttonText: e.target.value })) }), _jsx(Input, { label: "Testimonial (optional)", value: whatsappBuilder.testimonial, onChange: (e) => setWhatsappBuilder((prev) => ({ ...prev, testimonial: e.target.value })) })] }));
724
725
  }
725
726
  function renderWelcomeBuilder() {
726
- return (_jsxs(Div, { className: CLS_SECTION_PANEL, children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Welcome Section Builder" }), _jsx(Input, { label: "Headline (h1)", value: welcomeBuilder.h1, onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, h1: e.target.value })) }), _jsx(Input, { label: "Subtitle", value: welcomeBuilder.subtitle, onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, subtitle: e.target.value })) }), _jsx(Textarea, { label: "Description", value: welcomeBuilder.description, onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, description: e.target.value })), rows: 3 }), _jsx(Checkbox, { checked: welcomeBuilder.showCTA, label: "Show CTA button", onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, showCTA: e.target.checked })) }), welcomeBuilder.showCTA ? (_jsxs(_Fragment, { children: [_jsx(Input, { label: "CTA text", value: welcomeBuilder.ctaText, onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, ctaText: e.target.value })) }), _jsx(Input, { label: "CTA link", value: welcomeBuilder.ctaLink, onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, ctaLink: e.target.value })), placeholder: "/products" })] })) : null] }));
727
+ return (_jsxs(Div, { className: CLS_SECTION_PANEL, children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Welcome Section Builder" }), _jsx(Input, { label: "Headline (h1)", value: welcomeBuilder.h1, onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, h1: e.target.value })) }), _jsx(Input, { label: "Subtitle", value: welcomeBuilder.subtitle, onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, subtitle: e.target.value })) }), _jsx(Textarea, { label: "Description", value: welcomeBuilder.description, onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, description: e.target.value })), rows: 3 }), _jsx(Checkbox, { checked: welcomeBuilder.showCTA, label: "Show CTA button", onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, showCTA: e.target.checked })) }), welcomeBuilder.showCTA ? (_jsxs(_Fragment, { children: [_jsx(Input, { label: "CTA text", value: welcomeBuilder.ctaText, onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, ctaText: e.target.value })) }), _jsx(Input, { label: "CTA link", value: welcomeBuilder.ctaLink, onChange: (e) => setWelcomeBuilder((prev) => ({ ...prev, ctaLink: e.target.value })), placeholder: String(ROUTES.PUBLIC.PRODUCTS) })] })) : null] }));
727
728
  }
728
729
  function renderTrustIndicatorsBuilder() {
729
730
  return (_jsxs(Div, { className: CLS_SECTION_PANEL, children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Trust Indicators Builder" }), _jsx(Input, { label: "Section title", value: trustIndicatorsBuilder.title, onChange: (e) => setTrustIndicatorsBuilder((prev) => ({ ...prev, title: e.target.value })) }), trustIndicatorsBuilder.indicators.map((ind, index) => (_jsxs(Stack, { className: `${__P.p3}`, gap: "sm", rounded: "md", border: "default", children: [_jsxs(Row, { align: "center", justify: "between", children: [_jsxs(Text, { className: "tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: ["Indicator ", index + 1] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setTrustIndicatorsBuilder((prev) => ({ ...prev, indicators: prev.indicators.filter((_, i) => i !== index) })), children: "Remove" })] }), _jsx(Input, { label: "Icon (emoji or text)", value: ind.icon, onChange: (e) => setTrustIndicatorsBuilder((prev) => { const next = [...prev.indicators]; next[index] = { ...next[index], icon: e.target.value }; return { ...prev, indicators: next }; }) }), _jsx(Input, { label: "Title", value: ind.title, onChange: (e) => setTrustIndicatorsBuilder((prev) => { const next = [...prev.indicators]; next[index] = { ...next[index], title: e.target.value }; return { ...prev, indicators: next }; }) }), _jsx(Input, { label: "Description", value: ind.description, onChange: (e) => setTrustIndicatorsBuilder((prev) => { const next = [...prev.indicators]; next[index] = { ...next[index], description: e.target.value }; return { ...prev, indicators: next }; }) })] }, ind.id))), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setTrustIndicatorsBuilder((prev) => ({ ...prev, indicators: [...prev.indicators, { id: `ti-${Date.now()}`, icon: "✨", title: "", description: "" }] })), children: "+ Add indicator" })] }));
@@ -944,6 +945,12 @@ export function AdminSectionsView({ children }) {
944
945
  default: return null;
945
946
  }
946
947
  }
948
+ // React.useMemo must run unconditionally on every render — it was
949
+ // previously declared after the `hasChildren` early return below, which
950
+ // skips the hook call in passthrough mode, violating the Rules of Hooks.
951
+ const sectionOrderMap = React.useMemo(() => {
952
+ return new Map(sections.map((section) => [section.id, section.order]));
953
+ }, [sections]);
947
954
  // If children exist, render passthrough mode (detail view)
948
955
  if (hasChildren) {
949
956
  return _jsx(_Fragment, { children: children });
@@ -956,9 +963,6 @@ export function AdminSectionsView({ children }) {
956
963
  status: section.enabled ? "Active" : "Inactive",
957
964
  updatedAt: new Date(section.updatedAt).toLocaleDateString(),
958
965
  }));
959
- const sectionOrderMap = React.useMemo(() => {
960
- return new Map(sections.map((section) => [section.id, section.order]));
961
- }, [sections]);
962
966
  const hasReorderChanges = reorderDraft.some((item) => sectionOrderMap.get(item.id) !== item.order);
963
967
  const canUndoReorderChanges = reorderUndoStack.length > 0;
964
968
  return (_jsxs(_Fragment, { children: [_jsxs(Div, { paddingX: "x-sm-md", padding: "y-md", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "3", children: [_jsxs(Div, { children: [_jsx(Text, { size: "base", weight: "semibold", color: "primary", children: "Homepage Sections" }), _jsx(Text, { size: "sm", color: "muted", children: "Manage homepage sections and their display order" })] }), _jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setSeedResetOpen(true), children: "Reset seed data" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: () => setIsModalOpen(true), children: "Manage Sections" })] })] }), errorMessage && (_jsx(Div, { textSize: "sm", className: "mb-4 border border-error/20", color: "error", surface: "danger-surface", padding: "inline", rounded: "xl", children: errorMessage })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No sections found" })] }), _jsxs(Stack, { className: `mt-4 ${__P.p4}`, gap: "3", rounded: "xl", surface: "default", border: "default", children: [_jsxs(Row, { align: "center", justify: "between", gap: "3", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Reorder Sections" }), _jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: reindexDraft, disabled: reorderSections.isPending || reorderDraft.length === 0, children: "Reindex 1..N" }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: undoReorderChange, disabled: reorderSections.isPending || !canUndoReorderChanges, children: "Undo unsaved" }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: resetToServerOrder, disabled: reorderSections.isPending || !hasReorderChanges, children: "Reset to server" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: () => reorderSections.mutate(), disabled: !hasReorderChanges || reorderSections.isPending, children: reorderSections.isPending ? "Saving order..." : "Save order" })] })] }), reorderDraft.length === 0 ? (_jsx(Text, { size: "sm", color: "muted", children: "No sections to reorder." })) : (_jsx(Stack, { gap: "sm", children: reorderDraft.map((item, index) => (_jsxs(Div, { layout: "grid", gap: "2", align: "center", className: "grid-cols-[auto_1fr_auto_auto_auto]", rounded: "md", padding: "xs", border: "default", draggable: true, onDragStart: () => setDragIndex(index), onDragOver: (event) => event.preventDefault(), onDrop: () => handleReorderDrop(index), onDragEnd: () => setDragIndex(null), children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "\u2261" }), _jsxs(Text, { size: "sm", color: "primary", children: [item.type, " #", item.order] }), _jsx(Input, { type: "number", min: 1, max: reorderDraft.length, value: String(item.order), onChange: (event) => updateReorderItemOrder(index, Number(event.target.value) || 1), className: "w-24" }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => moveReorderItem(index, -1), disabled: index === 0, children: "Up" }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => moveReorderItem(index, 1), disabled: index === reorderDraft.length - 1, children: "Down" })] }, `reorder-${item.id}`))) }))] }), _jsx(ConfirmDeleteModal, { isOpen: seedResetOpen, onClose: () => setSeedResetOpen(false), onConfirm: () => resetSeed.mutate(), title: "Reset homepage sections seed data?", message: "This will reload the 19 default homepage sections from seed data. Any manual changes made in Firestore will be overwritten.", confirmText: "Reset seed", cancelText: "Cancel", isDeleting: resetSeed.isPending, variant: "danger" }), _jsx(Modal, { isOpen: isModalOpen, onClose: () => setIsModalOpen(false), title: "Manage Homepage Section", size: "lg", children: _jsxs(Form, { onSubmit: (event) => {