@mohasinac/appkit 3.3.6 → 3.4.1
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/classified/ClassifiedDetailView.js +2 -1
- package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +2 -1
- package/dist/_internal/client/features/live/LiveItemDetailView.js +2 -1
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +1 -1
- package/dist/_internal/client/features/lottery/LotteryDetailView.js +2 -1
- package/dist/_internal/client/features/lottery/LotteryListView.js +2 -1
- package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.js +2 -1
- package/dist/_internal/server/features/checkout/actions.js +0 -1
- package/dist/_internal/server/features/lottery/actions.js +0 -2
- package/dist/_internal/server/features/reviews/actions.js +1 -1
- package/dist/features/about/components/FAQPageView.js +0 -2
- package/dist/features/about/components/FeesView.js +13 -1
- package/dist/features/about/components/HowCheckoutWorksView.js +17 -3
- package/dist/features/about/components/HowEmiWorksView.d.ts +3 -0
- package/dist/features/about/components/HowEmiWorksView.js +117 -0
- package/dist/features/about/components/PublicProfileView.js +1 -4
- package/dist/features/about/index.d.ts +2 -0
- package/dist/features/about/index.js +1 -0
- package/dist/features/account/components/BecomeSellerView.d.ts +1 -1
- package/dist/features/account/components/BecomeSellerView.js +1 -1
- package/dist/features/account/components/NotificationBell.js +1 -2
- package/dist/features/account/components/UserSupportView.js +0 -1
- package/dist/features/admin/components/AdminAdsView.js +3 -3
- package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
- package/dist/features/admin/components/AdminBundleEditorView.js +0 -4
- package/dist/features/admin/components/AdminCarouselEditorView.js +3 -3
- package/dist/features/admin/components/AdminCarouselView.js +3 -2
- package/dist/features/admin/components/AdminGuideHubView.js +2 -2
- package/dist/features/admin/components/AdminMediaView.js +2 -4
- package/dist/features/admin/components/AdminUserEditorView.d.ts +1 -1
- package/dist/features/admin/components/AdminUserEditorView.js +1 -1
- package/dist/features/admin/components/QuickActionsPanel.js +2 -2
- package/dist/features/auctions/components/AuctionDetailPageView.js +1 -1
- package/dist/features/blog/components/BlogFeaturedCard.js +2 -1
- package/dist/features/blog/components/BlogIndexListing.js +1 -1
- package/dist/features/blog/components/BlogListView.js +2 -1
- package/dist/features/blog/components/BlogPostForm.js +1 -1
- package/dist/features/blog/components/BlogPostView.js +2 -1
- package/dist/features/cart/components/CartDrawer.js +2 -1
- package/dist/features/categories/components/BrandDetailPageView.js +2 -1
- package/dist/features/categories/components/BundleCollage.js +2 -3
- package/dist/features/categories/components/CategoriesIndexListing.js +1 -5
- package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
- package/dist/features/categories/components/CategoryGrid.js +2 -1
- package/dist/features/categories/components/CategoryProductsView.d.ts +1 -1
- package/dist/features/categories/components/CategoryProductsView.js +1 -1
- package/dist/features/categories/components/ConcernCard.js +2 -1
- package/dist/features/collections/components/CollectionCard.js +2 -1
- package/dist/features/consultation/components/ConsultationForm.js +0 -1
- package/dist/features/contact/components/ContactInfoSidebar.js +2 -2
- package/dist/features/copilot/components/AdminCopilotView.js +0 -9
- package/dist/features/events/components/EventFormDrawer.d.ts +1 -1
- package/dist/features/events/components/EventFormDrawer.js +1 -1
- package/dist/features/events/components/EventPollWidget.js +2 -2
- package/dist/features/events/components/EventsIndexListing.js +1 -1
- package/dist/features/faq/actions/faq-actions.d.ts +2 -10
- package/dist/features/faq/actions/faq-actions.js +0 -4
- package/dist/features/homepage/components/AdSlot.js +2 -1
- package/dist/features/homepage/components/CustomCardsSection.js +2 -3
- package/dist/features/homepage/components/FeaturedBundlesSection.js +2 -3
- package/dist/features/homepage/components/GoogleReviewsSection.js +4 -3
- package/dist/features/homepage/components/HeroBanner.js +0 -1
- package/dist/features/homepage/components/SectionCarousel.d.ts +1 -1
- package/dist/features/homepage/components/SectionCarousel.js +1 -2
- package/dist/features/homepage/components/SocialFeedSection.js +2 -5
- package/dist/features/homepage/components/SocialPostCard.js +4 -3
- package/dist/features/media/MediaImage.d.ts +10 -1
- package/dist/features/media/MediaImage.js +6 -2
- package/dist/features/media/MediaPickerModal.js +2 -3
- package/dist/features/media/upload/MediaUploadList.js +2 -2
- package/dist/features/orders/components/OrdersList.js +2 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -0
- package/dist/features/products/api/route.js +1 -2
- package/dist/features/products/components/CompareOverlay.js +2 -3
- package/dist/features/products/components/CustomSectionTabContent.js +2 -2
- package/dist/features/products/components/FeatureBadge.js +0 -6
- package/dist/features/products/components/GroupSettingsPanel.js +2 -3
- package/dist/features/products/components/MarketplaceBundleCard.js +2 -1
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +2 -3
- package/dist/features/products/components/PrizeDrawCollage.js +2 -3
- package/dist/features/products/components/PrizeDrawEntryActions.d.ts +1 -1
- package/dist/features/products/components/PrizeDrawEntryActions.js +3 -3
- package/dist/features/products/components/PrizeRevealModal.js +3 -4
- package/dist/features/products/components/ProductDetailActions.d.ts +1 -1
- package/dist/features/products/components/ProductDetailActions.js +1 -1
- package/dist/features/products/components/ProductDetailPageView.d.ts +3 -1
- package/dist/features/products/components/ProductDetailPageView.js +3 -2
- package/dist/features/products/components/ProductFeatureBadges.d.ts +7 -1
- package/dist/features/products/components/ProductFeatureBadges.js +16 -3
- package/dist/features/products/components/ProductGradingTab.js +2 -2
- package/dist/features/products/components/ProductsIndexPageView.js +2 -2
- package/dist/features/products/components/SublistingCarouselSection.js +3 -4
- package/dist/features/promotions/components/CouponsIndexListing.d.ts +1 -1
- package/dist/features/promotions/components/CouponsIndexListing.js +1 -1
- package/dist/features/reviews/components/ReviewDetailShell.js +4 -3
- package/dist/features/reviews/components/ReviewModal.js +2 -1
- package/dist/features/reviews/components/ReviewsIndexListing.js +1 -1
- package/dist/features/reviews/components/ReviewsList.js +2 -1
- package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
- package/dist/features/search/components/SearchView.d.ts +1 -1
- package/dist/features/search/components/SearchView.js +1 -1
- package/dist/features/seller/components/SellerAddressesView.js +1 -5
- package/dist/features/seller/components/SellerPreOrdersView.js +3 -2
- package/dist/features/seller/components/SellerPrizeDrawsView.js +3 -2
- package/dist/features/seller/components/SellerProductsView.js +2 -1
- package/dist/features/seller/components/SellerSidebar.js +5 -4
- package/dist/features/shell/StepForm.js +1 -1
- package/dist/features/stores/components/InteractiveStoreCard.js +2 -3
- package/dist/features/stores/components/StoreAboutView.js +2 -2
- package/dist/features/stores/components/StoreCapabilitiesGuideView.js +2 -2
- package/dist/features/stores/components/StoreFinanceGuideView.js +2 -2
- package/dist/features/stores/components/StoreGuideHubView.js +2 -2
- package/dist/features/stores/components/StoreHeader.js +2 -1
- package/dist/features/stores/components/StoreListingsGuideView.js +2 -2
- package/dist/features/stores/components/StoreNavTabs.js +2 -2
- package/dist/features/stores/components/StoreOrdersGuideView.js +2 -2
- package/dist/features/stores/components/StoreSettingsGuideView.js +3 -3
- package/dist/features/wishlist/components/WishlistPage.js +2 -1
- package/dist/features/wishlist/components/WishlistView.js +0 -7
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/next/routing/route-map.d.ts +2 -0
- package/dist/next/routing/route-map.js +1 -0
- package/dist/seed/factories/product.factory.js +0 -32
- package/dist/seed/faq-seed-data.js +23 -4
- package/dist/styles.css +4 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/index.js +6 -458
- package/dist/ui/DataTable.js +0 -21
- package/dist/ui/components/Anchor.d.ts +3 -1
- package/dist/ui/components/Anchor.js +1 -0
- package/dist/ui/components/Avatar.style.css +3 -0
- package/dist/ui/components/Breadcrumb.js +2 -1
- package/dist/ui/components/FormActionBar.js +2 -1
- package/dist/ui/components/ListingLayout.d.ts +1 -1
- package/dist/ui/components/ListingLayout.js +1 -1
- package/dist/ui/components/Motion.js +1 -1
- package/dist/ui/components/QuickCreateModal.js +2 -1
- package/dist/ui/components/SlottedListingView.d.ts +1 -1
- package/dist/ui/components/SlottedListingView.js +1 -2
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import { normalizeError } from "../../../../errors/normalize";
|
|
|
4
4
|
import { useState } from "react";
|
|
5
5
|
import Link from "next/link";
|
|
6
6
|
import { Badge, Button, Container, Div, Heading, Row, Section, Stack, Text, } from "../../../../ui";
|
|
7
|
+
import { MediaImage } from "../../../../features/media/MediaImage";
|
|
7
8
|
import { ROUTES } from "../../../../next/routing/route-map";
|
|
8
9
|
import { formatCurrency } from "../../../../utils/number.formatter";
|
|
9
10
|
const __P = {
|
|
@@ -50,5 +51,5 @@ export function ClassifiedDetailView({ product, isLoading = false, onContactSell
|
|
|
50
51
|
setPending(false);
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
|
-
return (_jsx(Container, { children: _jsx(Section, { padding: "y-xl", children: _jsxs(Stack, { gap: "lg", children: [product.images.length > 0 && (_jsx(Div, { className:
|
|
54
|
+
return (_jsx(Container, { children: _jsx(Section, { padding: "y-xl", children: _jsxs(Stack, { gap: "lg", children: [product.images.length > 0 && (_jsx(Div, { className: `relative h-80 w-full ${__O.hidden} bg-muted`, rounded: "lg", children: _jsx(MediaImage, { src: product.mainImage || product.images[0], alt: product.title, size: "hero", objectFit: "contain" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Badge, { variant: "secondary", children: "Classified" }), meta?.negotiable && _jsx(Badge, { variant: "secondary", children: "Negotiable" }), meta?.acceptsShipping && _jsx(Badge, { variant: "secondary", children: "Shipping available" })] }), _jsx(Heading, { level: 1, weight: "bold", size: "2xl", children: product.title }), _jsx(Text, { className: "text-primary", size: "2xl", weight: "semibold", children: price }), location && (_jsx(Text, { className: "text-muted-foreground", size: "sm", children: location })), _jsx(Text, { className: "text-muted-foreground", children: product.description })] }), conversation ? (_jsxs(Div, { className: `border border-border bg-muted/40 ${__P.p4}`, rounded: "lg", children: [_jsx(Text, { className: "mb-2", weight: "medium", children: "Conversation started!" }), _jsx(Link, { href: ROUTES.USER.MESSAGES, className: "text-primary underline underline-offset-2", children: "Go to your messages \u2192" })] })) : (_jsxs(Stack, { gap: "sm", children: [error && (_jsx(Text, { className: "text-destructive", size: "sm", children: error })), _jsx(Button, { type: "button", variant: "primary", size: "lg", isLoading: pending, disabled: pending, onClick: handleContactSeller, className: "w-full", children: "Contact Seller" })] }))] }) }) }));
|
|
54
55
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Badge, Container, Div, Heading, Row, Section, Stack, Text, } from "../../../../ui";
|
|
4
|
+
import { MediaImage } from "../../../../features/media/MediaImage";
|
|
4
5
|
import { formatCurrency } from "../../../../utils/number.formatter";
|
|
5
6
|
import { CodeRevealPanel } from "./CodeRevealPanel";
|
|
6
7
|
const __P = {
|
|
@@ -16,5 +17,5 @@ export function DigitalCodeDetailView({ product, isLoading = false, orderId, fet
|
|
|
16
17
|
const meta = product.digitalCode;
|
|
17
18
|
const price = formatCurrency(product.price, product.currency ?? "INR");
|
|
18
19
|
const codesLeft = meta?.codesAvailable ?? 0;
|
|
19
|
-
return (_jsx(Container, { children: _jsx(Section, { padding: "y-xl", children: _jsxs(Stack, { gap: "lg", children: [product.images.length > 0 && (_jsx(Div, { className:
|
|
20
|
+
return (_jsx(Container, { children: _jsx(Section, { padding: "y-xl", children: _jsxs(Stack, { gap: "lg", children: [product.images.length > 0 && (_jsx(Div, { className: `relative h-80 w-full ${__O.hidden} bg-muted`, rounded: "lg", children: _jsx(MediaImage, { src: product.mainImage || product.images[0], alt: product.title, size: "hero", objectFit: "contain" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Badge, { variant: "secondary", children: "Digital Code" }), codesLeft > 0 ? (_jsxs(Badge, { variant: "active", children: [codesLeft, " available"] })) : (_jsx(Badge, { variant: "danger", children: "Sold out" }))] }), _jsx(Heading, { level: 1, weight: "bold", size: "2xl", children: product.title }), _jsx(Text, { className: "text-primary", size: "2xl", weight: "semibold", children: price }), _jsx(Text, { className: "text-muted-foreground", children: product.description })] }), orderId && fetchCode ? (_jsx(CodeRevealPanel, { orderId: orderId, redemptionInstructions: meta?.redemptionInstructions, fetchCode: fetchCode })) : (_jsxs(Div, { className: `border border-border bg-muted/40 ${__P.p4}`, rounded: "lg", children: [_jsx(Text, { className: "text-muted-foreground", size: "sm", children: "After purchase, return to your order to reveal the code instantly." }), meta?.redemptionInstructions && (_jsx(Text, { className: "mt-2", size: "sm", children: meta.redemptionInstructions }))] }))] }) }) }));
|
|
20
21
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Badge, Container, Div, Heading, Row, Section, Stack, Text, } from "../../../../ui";
|
|
4
|
+
import { MediaImage } from "../../../../features/media/MediaImage";
|
|
4
5
|
import { formatCurrency } from "../../../../utils/number.formatter";
|
|
5
6
|
const __P = {
|
|
6
7
|
p4: "p-4",
|
|
@@ -19,6 +20,6 @@ export function LiveItemDetailView({ product, isLoading = false, renderActions,
|
|
|
19
20
|
const price = formatCurrency(product.price, product.currency ?? "INR");
|
|
20
21
|
const jurisdictions = meta?.jurisdictionAllowed ?? [];
|
|
21
22
|
const transport = meta?.transport;
|
|
22
|
-
return (_jsx(Container, { children: _jsx(Section, { padding: "y-xl", children: _jsxs(Stack, { gap: "lg", children: [product.images.length > 0 && (_jsx(Div, { className:
|
|
23
|
+
return (_jsx(Container, { children: _jsx(Section, { padding: "y-xl", children: _jsxs(Stack, { gap: "lg", children: [product.images.length > 0 && (_jsx(Div, { className: `relative h-80 w-full ${__O.hidden} bg-muted`, rounded: "lg", children: _jsx(MediaImage, { src: product.mainImage || product.images[0], alt: product.title, size: "hero", objectFit: "contain" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Badge, { variant: "secondary", children: "Live Item" }), meta?.vendorVerified && (_jsx(Badge, { variant: "active", children: "Verified Seller" })), meta?.cites && (_jsxs(Badge, { variant: "warning", children: ["CITES: ", meta.cites] }))] }), _jsx(Heading, { level: 1, weight: "bold", size: "2xl", children: product.title }), meta?.species && (_jsxs(Text, { className: "italic text-muted-foreground", size: "sm", children: [meta.species, meta.sex && meta.sex !== "n/a" && ` · ${meta.sex}`, meta.ageMonths !== undefined && ` · ${meta.ageMonths}mo`] })), _jsx(Text, { className: "text-primary", size: "2xl", weight: "semibold", children: price }), _jsx(Text, { className: "text-muted-foreground", children: product.description })] }), jurisdictions.length > 0 && (_jsxs(Div, { className: CLS_WARN_BOX, children: [_jsx(Text, { className: CLS_WARN_TITLE, children: "Delivery restrictions" }), _jsxs(Text, { className: CLS_WARN_BODY, children: ["This item can only be shipped to: ", jurisdictions.join(", ")] })] })), transport && (_jsxs(Div, { textSize: "sm", className: `border border-border bg-muted/40 ${__P.p4}`, rounded: "lg", children: [_jsx(Text, { weight: "medium", children: "Transport" }), _jsxs(Text, { className: "text-muted-foreground", children: ["Method: ", transport.method, transport.handlingFeeInPaise !== undefined &&
|
|
23
24
|
` · Handling: ${formatCurrency(transport.handlingFeeInPaise, "INR")}`, transport.insuranceIncluded && " · Insurance included"] })] })), meta?.careInfo && (_jsxs(Div, { textSize: "sm", className: `border border-border bg-muted/40 ${__P.p4}`, rounded: "lg", children: [_jsx(Text, { weight: "medium", children: "Care information" }), _jsx(Text, { className: "mt-1 text-muted-foreground", children: meta.careInfo })] })), renderActions?.()] }) }) }));
|
|
24
25
|
}
|
|
@@ -79,7 +79,7 @@ export function LotteryAdminEditView({ eventId, initialData, onSubmit, }) {
|
|
|
79
79
|
: []),
|
|
80
80
|
];
|
|
81
81
|
const slotsWithIdx = slots.map((s, i) => ({ ...s, _idx: i }));
|
|
82
|
-
return (_jsx(Container, { children: _jsx(Section, { children: _jsx(Form, { onSubmit: (e) => e.preventDefault(), className: "space-y-6", children: ({
|
|
82
|
+
return (_jsx(Container, { children: _jsx(Section, { children: _jsx(Form, { onSubmit: (e) => e.preventDefault(), className: "space-y-6", children: ({ clearErrors }) => (_jsxs(Stack, { gap: "xl", children: [_jsx(Heading, { level: 1, size: "2xl", weight: "bold", children: eventId ? "Edit Lottery" : "Create Lottery" }), _jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", children: "Basic Info" }), _jsx(FieldInput, { name: "title", label: "Title", required: true, value: title, onChange: (v) => { setTitle(v); clearErrors(); } }), _jsx(FieldInput, { name: "description", label: "Description", value: description, onChange: (v) => { setDescription(v); clearErrors(); } })] }), _jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", children: "Configuration" }), _jsx(FieldSelect, { name: "pricingMode", label: "Pricing Mode", value: pricingMode, options: [
|
|
83
83
|
{ label: "Uniform (all slots same price)", value: "uniform" },
|
|
84
84
|
{ label: "Variable (per-slot pricing)", value: "variable" },
|
|
85
85
|
], onChange: (v) => setPricingMode(v) }), pricingMode === "uniform" && (_jsx(FieldInput, { name: "uniformPrice", label: "Price per Slot (\u20B9)", type: "number", value: uniformPrice, onChange: (v) => setUniformPrice(v) })), _jsx(FieldInput, { name: "drawWindowMinutes", label: "Draw Window (minutes)", type: "number", value: drawWindowMinutes, onChange: (v) => setDrawWindowMinutes(v) }), _jsx(FieldInput, { name: "maxPullsPerTx", label: "Max Pulls per Transaction", type: "number", value: maxPullsPerTx, onChange: (v) => setMaxPullsPerTx(v) }), _jsx(FieldInput, { name: "maxPullsPerUser", label: "Max Pulls per User", type: "number", value: maxPullsPerUser, onChange: (v) => setMaxPullsPerUser(v) })] }), _jsxs(Stack, { gap: "md", children: [_jsxs(Row, { align: "center", justify: "between", children: [_jsxs(Heading, { level: 2, size: "lg", weight: "semibold", children: ["Slots (", slots.length, ")"] }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: addSlot, disabled: slots.length >= 200, children: "+ Add Slot" })] }), _jsx(DataTable, { data: slotsWithIdx, columns: slotColumns, keyExtractor: (s) => String(s.slotNumber), emptyMessage: "No slots yet.", actions: (s) => slots.length > 1 ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeSlot(s._idx), "aria-label": `Remove slot ${s.slotNumber}`, children: "\u00D7" })) : null })] }), error && _jsx(Text, { className: "text-error", size: "sm", role: "alert", children: error }), _jsx(Button, { type: "submit", variant: "primary", isLoading: isPending, onClick: handleSubmit, className: "w-full sm:w-auto", children: isPending ? "Saving…" : eventId ? "Update Lottery" : "Create Lottery" })] })) }) }) }));
|
|
@@ -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 { MediaImage } from "../../../../features/media/MediaImage";
|
|
5
6
|
import { ROUTES } from "../../../../next/routing/route-map";
|
|
6
7
|
import { LotterySlotGrid } from "./LotterySlotGrid";
|
|
7
8
|
import { LotteryPullForm } from "./LotteryPullForm";
|
|
@@ -14,5 +15,5 @@ export function LotteryDetailView({ event, user, currentEntry }) {
|
|
|
14
15
|
const config = event.lotteryConfig;
|
|
15
16
|
const isActive = event.status === "active";
|
|
16
17
|
const isEnded = event.status === "ended" || event.status === "cancelled";
|
|
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(
|
|
18
|
+
return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { gap: "xl", children: [event.coverImageUrl ? (_jsx(Div, { rounded: "2xl", className: "relative overflow-hidden", style: { aspectRatio: "16/9", maxHeight: "16rem" }, children: _jsx(MediaImage, { src: event.coverImageUrl, alt: event.title, size: "hero" }) })) : (_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." }) }))] }) }) }));
|
|
18
19
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Stack, Row, Text, Heading, Badge, Card, Section, Container, Anchor, Div, Grid, } from "../../../../ui";
|
|
4
|
+
import { MediaImage } from "../../../../features/media/MediaImage";
|
|
4
5
|
/**
|
|
5
6
|
* Card grid of lotteries.
|
|
6
7
|
* Admin sees all statuses; public sees active only.
|
|
@@ -16,7 +17,7 @@ export function LotteryListView({ items, adminMode = false }) {
|
|
|
16
17
|
const claimed = event.lotteryConfig?.slots.filter((s) => s.isBooked).length ?? 0;
|
|
17
18
|
const total = event.lotteryConfig?.totalSlots ?? 0;
|
|
18
19
|
const slotsLeft = total - claimed;
|
|
19
|
-
return (_jsx(Anchor, { href: `/lottery/${event.id}`, tone: "brand", rounded: "2xl", className: "block focus:outline-none focus-visible:ring-2 focus-visible:ring-primary", "aria-label": `${event.title} lottery`, children: _jsxs(Card, { variant: "default", padding: "none", animate: "hoverLift", className: "overflow-hidden", children: [event.coverImageUrl ? (_jsx(Div, { className: "aspect-video overflow-hidden", children: _jsx(
|
|
20
|
+
return (_jsx(Anchor, { href: `/lottery/${event.id}`, tone: "brand", rounded: "2xl", className: "block focus:outline-none focus-visible:ring-2 focus-visible:ring-primary", "aria-label": `${event.title} lottery`, children: _jsxs(Card, { variant: "default", padding: "none", animate: "hoverLift", className: "overflow-hidden", children: [event.coverImageUrl ? (_jsx(Div, { className: "relative aspect-video overflow-hidden", children: _jsx(MediaImage, { src: event.coverImageUrl, alt: event.title, size: "card" }) })) : (_jsx(Div, { className: "aspect-video", surface: "muted", align: "center", justify: "center", children: _jsx(Text, { size: "3xl", children: "\uD83C\uDFB0" }) })), _jsxs(Stack, { gap: "xs", padding: "md", children: [_jsxs(Row, { gap: "xs", align: "center", wrap: true, children: [_jsx(Badge, { variant: event.status === "active"
|
|
20
21
|
? "success"
|
|
21
22
|
: event.status === "ended"
|
|
22
23
|
? "danger"
|
|
@@ -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 { MediaImage } from "../../../../features/media/MediaImage";
|
|
5
6
|
import { ROUTES } from "../../../../next/routing/route-map";
|
|
6
7
|
import { LotterySlotGrid } from "./LotterySlotGrid";
|
|
7
8
|
import { LotteryPullForm } from "./LotteryPullForm";
|
|
@@ -15,5 +16,5 @@ export function PrizeDrawLotteryDetailView({ product, user, currentEntry, }) {
|
|
|
15
16
|
: null);
|
|
16
17
|
const config = product.lotteryConfig;
|
|
17
18
|
const isActive = product.status === "published";
|
|
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(
|
|
19
|
+
return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { gap: "xl", children: [product.mainImage ? (_jsx(Div, { rounded: "2xl", className: "relative overflow-hidden", style: { aspectRatio: "16/9", maxHeight: "16rem" }, children: _jsx(MediaImage, { src: product.mainImage, alt: product.title, size: "hero" }) })) : (_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) })) }))] }) }) }));
|
|
19
20
|
}
|
|
@@ -712,7 +712,6 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
|
|
|
712
712
|
const siteSettings = await siteSettingsRepository.getSingleton();
|
|
713
713
|
const platformFeePercent = siteSettings?.commissions?.platformFeePercent ?? 5;
|
|
714
714
|
const gstPercent = siteSettings?.commissions?.gstPercent ?? 18;
|
|
715
|
-
const commissions = siteSettings?.commissions ?? CHECKOUT_DEFAULT_COMMISSIONS;
|
|
716
715
|
const isValid = await verifyPaymentSignatureWithKeys({
|
|
717
716
|
razorpay_order_id,
|
|
718
717
|
razorpay_payment_id,
|
|
@@ -55,8 +55,6 @@ export async function submitLotteryPullAction(input) {
|
|
|
55
55
|
// Product lottery — load via product repository (not implemented here; caller ensures correct source)
|
|
56
56
|
throw new ValidationError("Product lottery pull must go through the product lottery pull route.");
|
|
57
57
|
}
|
|
58
|
-
// Compute weights
|
|
59
|
-
const weightedSlots = assignSlotWeights(lotteryConfig);
|
|
60
58
|
// Check draw window
|
|
61
59
|
if (!isDrawWindowOpen(lotteryConfig)) {
|
|
62
60
|
throw new LotteryError("LOTTERY_FULL", "All slots have been claimed.");
|
|
@@ -36,7 +36,7 @@ export async function createReviewAction(input) {
|
|
|
36
36
|
}
|
|
37
37
|
export async function replyToReviewAction(input) {
|
|
38
38
|
return wrapAction(async () => {
|
|
39
|
-
|
|
39
|
+
await requireRoleUser(["seller", "admin"]);
|
|
40
40
|
const parsed = replyToReviewSchema.safeParse(input);
|
|
41
41
|
if (!parsed.success) {
|
|
42
42
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ROUTES } from "../../../constants";
|
|
3
|
-
import { PAGE_CONTAINER } from "../../../_internal/shared/styles/page";
|
|
4
3
|
import { FLEX_ROW } from "../../../_internal/shared/styles/themed";
|
|
5
4
|
import { Aside, Container, Details, Div, Heading, Nav, RichTextRenderer, Row, Section, Span, Stack, Summary, Text } from "../../../ui";
|
|
6
5
|
import { TextLink } from "../../../ui";
|
|
7
6
|
import { HelpCircle, ChevronRight } from "lucide-react";
|
|
8
7
|
export async function FAQPageView({ category, } = {}) {
|
|
9
|
-
const page = { container: PAGE_CONTAINER };
|
|
10
8
|
const flex = { row: FLEX_ROW };
|
|
11
9
|
const { getTranslations, getMessages } = await import("next-intl/server");
|
|
12
10
|
const t = await getTranslations("faqs");
|
|
@@ -53,6 +53,18 @@ export async function FeesView({} = {}) {
|
|
|
53
53
|
who: t("paidByBuyer"),
|
|
54
54
|
note: t("shippingFeeNote"),
|
|
55
55
|
},
|
|
56
|
+
{
|
|
57
|
+
category: t("emiSurchargeFeeTitle"),
|
|
58
|
+
rate: t("emiSurchargeFeeRate"),
|
|
59
|
+
who: t("paidByBuyer"),
|
|
60
|
+
note: t("emiSurchargeFeeNote"),
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
category: t("codHandlingFeeTitle"),
|
|
64
|
+
rate: t("codHandlingFeeRate"),
|
|
65
|
+
who: t("paidByBuyer"),
|
|
66
|
+
note: t("codHandlingFeeNote"),
|
|
67
|
+
},
|
|
56
68
|
];
|
|
57
69
|
const OFFER_PAYOUT_ROWS = [
|
|
58
70
|
{ label: t("grossSale"), example: "₹1,000" },
|
|
@@ -70,6 +82,6 @@ function renderFeeTableSection(t, themed, rows) {
|
|
|
70
82
|
function renderPayoutExampleSection(t, themed, rows) {
|
|
71
83
|
return (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-3", children: t("payoutExampleTitle") }), _jsx(Text, { variant: "secondary", className: "mb-6", children: t("payoutExampleSubtitle") }), _jsxs(Div, { className: `${__P.p5} max-w-sm`, border: "default", surface: "muted", rounded: "xl", children: [_jsx(Heading, { level: 3, className: "mb-4", size: "base", children: t("payoutExampleProduct") }), _jsx(Stack, { gap: "sm", children: rows.map((row, i) => (_jsxs(Row, { textWeight: "bold", textSize: "sm", className: `${row.highlight ? "border-t border-[var(--appkit-color-border)] mt-2" : ""}`, paddingY: row.highlight ? "t-xs" : undefined, justify: "between", children: [_jsx(Text, { className: row.highlight ? "font-bold" : "text-[var(--appkit-color-text-muted)]", children: row.label }), _jsx(Text, { className: row.highlight ? CLS_HIGHLIGHT : "", children: row.example })] }, i))) })] })] }));
|
|
72
84
|
}
|
|
73
|
-
function renderDisclaimerSection(t,
|
|
85
|
+
function renderDisclaimerSection(t, _themed) {
|
|
74
86
|
return (_jsxs(Section, { className: `${__P.p5}`, border: "default", surface: "subtle", rounded: "xl", children: [_jsx(Heading, { level: 3, className: "mb-2", size: "base", children: t("disclaimerTitle") }), _jsx(Caption, { className: "leading-relaxed", children: t("disclaimerText") })] }));
|
|
75
87
|
}
|
|
@@ -3,7 +3,7 @@ import { ROUTES } from "../../../constants";
|
|
|
3
3
|
import { PAGE_CONTAINER } from "../../../_internal/shared/styles/page";
|
|
4
4
|
import { Div, FlowDiagram, Heading, Row, Section, Stack, Text } from "../../../ui";
|
|
5
5
|
import { TextLink } from "../../../ui";
|
|
6
|
-
import { Smartphone, Banknote } from "lucide-react";
|
|
6
|
+
import { Wallet, Smartphone, Banknote, CalendarClock } from "lucide-react";
|
|
7
7
|
const __P = {
|
|
8
8
|
p5: "p-5",
|
|
9
9
|
p8: "p-8",
|
|
@@ -21,19 +21,33 @@ export async function HowCheckoutWorksView({} = {}) {
|
|
|
21
21
|
];
|
|
22
22
|
const PAYMENT_METHODS = [
|
|
23
23
|
{
|
|
24
|
-
icon:
|
|
24
|
+
icon: Wallet,
|
|
25
25
|
title: t("pm1Title"),
|
|
26
26
|
text: t("pm1Text"),
|
|
27
27
|
color: "bg-primary/5 border-primary/20 dark:bg-primary/10 dark:border-primary/30",
|
|
28
28
|
iconColor: "text-primary",
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
|
-
icon:
|
|
31
|
+
icon: Smartphone,
|
|
32
32
|
title: t("pm2Title"),
|
|
33
33
|
text: t("pm2Text"),
|
|
34
|
+
color: "bg-sky-50 border-sky-200 dark:bg-sky-900/20 dark:border-sky-700",
|
|
35
|
+
iconColor: "text-sky-600 dark:text-sky-400",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
icon: Banknote,
|
|
39
|
+
title: t("pm3Title"),
|
|
40
|
+
text: t("pm3Text"),
|
|
34
41
|
color: "bg-emerald-50 border-emerald-200 dark:bg-emerald-900/20 dark:border-emerald-700",
|
|
35
42
|
iconColor: "text-emerald-600 dark:text-emerald-400",
|
|
36
43
|
},
|
|
44
|
+
{
|
|
45
|
+
icon: CalendarClock,
|
|
46
|
+
title: t("pm4Title"),
|
|
47
|
+
text: t("pm4Text"),
|
|
48
|
+
color: "bg-violet-50 border-violet-200 dark:bg-violet-900/20 dark:border-violet-700",
|
|
49
|
+
iconColor: "text-violet-600 dark:text-violet-400",
|
|
50
|
+
},
|
|
37
51
|
];
|
|
38
52
|
const DIAGRAM_STEPS = [
|
|
39
53
|
{
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ROUTES } from "../../../constants";
|
|
3
|
+
import { PAGE_CONTAINER } from "../../../_internal/shared/styles/page";
|
|
4
|
+
import { THEMED_BG_PRIMARY, THEMED_BG_SECONDARY } from "../../../_internal/shared/styles/themed";
|
|
5
|
+
import { Alert, Caption, Div, FlowDiagram, Heading, Row, Section, Stack, Table, Tbody, Td, Text, Th, Thead, Tr } from "../../../ui";
|
|
6
|
+
import { TextLink } from "../../../ui";
|
|
7
|
+
import { CalendarClock, Wallet, TrendingUp, ShieldCheck } from "lucide-react";
|
|
8
|
+
const __P = {
|
|
9
|
+
p5: "p-5",
|
|
10
|
+
p8: "p-8",
|
|
11
|
+
};
|
|
12
|
+
const __O = {
|
|
13
|
+
xAuto: "overflow-x-auto",
|
|
14
|
+
};
|
|
15
|
+
export async function HowEmiWorksView({} = {}) {
|
|
16
|
+
const page = { container: PAGE_CONTAINER };
|
|
17
|
+
const themed = { bgPrimary: THEMED_BG_PRIMARY, bgSecondary: THEMED_BG_SECONDARY };
|
|
18
|
+
const { getTranslations } = await import("next-intl/server");
|
|
19
|
+
const t = await getTranslations("howEmiWorks");
|
|
20
|
+
const STEPS = [
|
|
21
|
+
{ number: 1, icon: "🛒", title: t("step1Title"), text: t("step1Text") },
|
|
22
|
+
{ number: 2, icon: "✅", title: t("step2Title"), text: t("step2Text") },
|
|
23
|
+
{ number: 3, icon: "💳", title: t("step3Title"), text: t("step3Text") },
|
|
24
|
+
{ number: 4, icon: "📅", title: t("step4Title"), text: t("step4Text") },
|
|
25
|
+
{ number: 5, icon: "🎉", title: t("step5Title"), text: t("step5Text") },
|
|
26
|
+
];
|
|
27
|
+
const INFO_CARDS = [
|
|
28
|
+
{
|
|
29
|
+
icon: Wallet,
|
|
30
|
+
title: t("infoCard1Title"),
|
|
31
|
+
text: t("infoCard1Text"),
|
|
32
|
+
color: "bg-primary/5 border-primary/20 dark:bg-primary/10 dark:border-primary/30",
|
|
33
|
+
iconColor: "text-primary",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
icon: CalendarClock,
|
|
37
|
+
title: t("infoCard2Title"),
|
|
38
|
+
text: t("infoCard2Text"),
|
|
39
|
+
color: "bg-emerald-50 border-emerald-200 dark:bg-emerald-900/20 dark:border-emerald-700",
|
|
40
|
+
iconColor: "text-emerald-600 dark:text-emerald-400",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
icon: TrendingUp,
|
|
44
|
+
title: t("infoCard3Title"),
|
|
45
|
+
text: t("infoCard3Text"),
|
|
46
|
+
color: "bg-sky-50 border-sky-200 dark:bg-sky-900/20 dark:border-sky-700",
|
|
47
|
+
iconColor: "text-sky-600 dark:text-sky-400",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
icon: ShieldCheck,
|
|
51
|
+
title: t("infoCard4Title"),
|
|
52
|
+
text: t("infoCard4Text"),
|
|
53
|
+
color: "bg-violet-50 border-violet-200 dark:bg-violet-900/20 dark:border-violet-700",
|
|
54
|
+
iconColor: "text-violet-600 dark:text-violet-400",
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
const EXAMPLE_ROWS = [
|
|
58
|
+
{ label: t("exampleOrderTotal"), example: "₹15,000" },
|
|
59
|
+
{ label: `${t("exampleToken")} (10%)`, example: "− ₹1,500" },
|
|
60
|
+
{ label: t("exampleRemaining"), example: "= ₹13,500" },
|
|
61
|
+
{ label: `${t("exampleSurcharge")} (1%/mo × 3mo)`, example: "+ ₹405" },
|
|
62
|
+
{ label: t("exampleMonthly"), example: "₹4,635 × 3", highlight: true },
|
|
63
|
+
];
|
|
64
|
+
const DIAGRAM_STEPS = [
|
|
65
|
+
{
|
|
66
|
+
emoji: "🛒",
|
|
67
|
+
circleClass: "bg-[var(--appkit-color-border-subtle)] border-2 border-[var(--appkit-color-border)]",
|
|
68
|
+
badge: t("step1Title"),
|
|
69
|
+
badgeClass: "bg-[var(--appkit-color-border-subtle)] text-[var(--appkit-color-text-muted)]",
|
|
70
|
+
desc: t("diagramStep1Desc"),
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
emoji: "✅",
|
|
74
|
+
circleClass: "bg-primary/10 dark:bg-primary/15 border-2 border-primary/30 dark:border-primary/40",
|
|
75
|
+
badge: t("step2Title"),
|
|
76
|
+
badgeClass: "bg-primary/10 dark:bg-primary/15 text-primary",
|
|
77
|
+
desc: t("diagramStep2Desc"),
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
emoji: "💳",
|
|
81
|
+
circleClass: "bg-violet-100 dark:bg-violet-900/40 border-2 border-violet-400 dark:border-violet-600",
|
|
82
|
+
badge: t("step3Title"),
|
|
83
|
+
badgeClass: "bg-violet-100 dark:bg-violet-900/40 text-violet-700 dark:text-violet-300",
|
|
84
|
+
desc: t("diagramStep3Desc"),
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
emoji: "📅",
|
|
88
|
+
circleClass: "bg-amber-100 dark:bg-amber-900/40 border-2 border-amber-300 dark:border-amber-600",
|
|
89
|
+
badge: t("step4Title"),
|
|
90
|
+
badgeClass: "bg-amber-100 dark:bg-amber-900/40 text-amber-700 dark:text-amber-300",
|
|
91
|
+
desc: t("diagramStep4Desc"),
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
emoji: "🎉",
|
|
95
|
+
circleClass: "bg-emerald-100 dark:bg-emerald-900/40 border-2 border-emerald-400 dark:border-emerald-600",
|
|
96
|
+
badge: t("step5Title"),
|
|
97
|
+
badgeClass: "bg-emerald-100 dark:bg-emerald-900/40 text-emerald-700 dark:text-emerald-300",
|
|
98
|
+
desc: t("diagramStep5Desc"),
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
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.md} 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 max-w-2xl mx-auto", children: t("subtitle") })] }) }), _jsxs(Stack, { gap: "14", className: `${page.container.md}`, padding: "content-banner", children: [renderEligibilityAlert(t), renderEmiSteps(t, STEPS), _jsx(Section, { children: _jsx(FlowDiagram, { title: `💳 ${t("diagramTitle")}`, titleClass: "text-primary", connectorClass: "bg-primary/20 dark:bg-primary/30", steps: DIAGRAM_STEPS, centered: true }) }), renderEmiInfoCards(INFO_CARDS), renderEmiExample(t, themed, EXAMPLE_ROWS), renderEmiCta(t)] })] }));
|
|
102
|
+
}
|
|
103
|
+
function renderEligibilityAlert(t) {
|
|
104
|
+
return (_jsx(Alert, { variant: "info", title: t("eligibilityTitle"), children: t("eligibilityText") }));
|
|
105
|
+
}
|
|
106
|
+
function renderEmiSteps(t, steps) {
|
|
107
|
+
return (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-8", align: "center", children: t("stepsTitle") }), _jsx(Stack, { gap: "5", children: steps.map(({ number, icon, title, text }) => (_jsxs(Row, { className: `${__P.p5}`, border: "default", surface: "muted", align: "start", gap: "md", rounded: "xl", children: [_jsx(Row, { align: "center", justify: "center", className: "flex-shrink-0 w-10 h-10 bg-primary/10 dark:bg-primary/15", rounded: "full", children: icon }), _jsxs(Div, { children: [_jsxs(Text, { className: "mb-0.5", weight: "semibold", children: [number, ". ", title] }), _jsx(Text, { variant: "secondary", className: "leading-relaxed", size: "sm", children: text })] })] }, number))) })] }));
|
|
108
|
+
}
|
|
109
|
+
function renderEmiInfoCards(cards) {
|
|
110
|
+
return (_jsx(Section, { children: _jsx(Div, { layout: "grid", gap: "5", className: "md:grid-cols-2", children: cards.map(({ icon: Icon, title, text, color, iconColor }) => (_jsxs(Div, { className: `border ${__P.p5} ${color}`, rounded: "xl", children: [_jsx(Row, { align: "center", justify: "center", className: "w-10 h-10 mb-3", surface: "default", rounded: "lg", children: _jsx(Icon, { className: `w-5 h-5 ${iconColor}` }) }), _jsx(Text, { className: "mb-1", weight: "semibold", children: title }), _jsx(Text, { variant: "secondary", className: "leading-relaxed", size: "sm", children: text })] }, title))) }) }));
|
|
111
|
+
}
|
|
112
|
+
function renderEmiExample(t, themed, rows) {
|
|
113
|
+
return (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-3", align: "center", children: t("exampleTitle") }), _jsx(Text, { variant: "secondary", className: "mb-8 max-w-xl mx-auto", align: "center", children: t("exampleSubtitle") }), _jsx(Div, { className: `${__O.xAuto}`, border: "default", rounded: "xl", children: _jsxs(Table, { size: "sm", children: [_jsx(Thead, { className: themed.bgSecondary, children: _jsxs(Tr, { children: [_jsx(Th, { className: "text-left", padding: "md", weight: "semibold", children: t("exampleColLine") }), _jsx(Th, { className: "text-right", padding: "md", weight: "semibold", children: t("exampleColAmount") })] }) }), _jsx(Tbody, { className: "divide-y divide-neutral-100 divide-[var(--appkit-color-border)]", children: rows.map((row, i) => (_jsxs(Tr, { className: `${themed.bgPrimary} ${row.highlight ? "font-bold" : ""}`, children: [_jsx(Td, { padding: "md", weight: row.highlight ? "bold" : "medium", children: row.label }), _jsx(Td, { className: `text-right ${row.highlight ? "text-primary" : ""}`, padding: "md", children: row.example })] }, i))) })] }) }), _jsx(Caption, { className: "mt-3 block", color: "muted", children: t("exampleNote") })] }));
|
|
114
|
+
}
|
|
115
|
+
function renderEmiCta(t) {
|
|
116
|
+
return (_jsxs(Section, { className: `${__P.p8} text-center`, border: "default", surface: "subtle", rounded: "2xl", children: [_jsx(Heading, { level: 2, className: "mb-3", children: t("ctaTitle") }), _jsx(Text, { variant: "secondary", className: "mb-6 max-w-lg mx-auto", children: t("ctaText") }), _jsxs(Row, { align: "center", justify: "center", gap: "md", wrap: true, children: [_jsx(TextLink, { href: String(ROUTES.PUBLIC.PRODUCTS), children: t("ctaBrowse") }), _jsx(TextLink, { href: String(ROUTES.PUBLIC.HOW_CHECKOUT_WORKS), variant: "muted", children: t("ctaCheckout") })] })] }));
|
|
117
|
+
}
|
|
@@ -108,7 +108,7 @@ function buildProfileStatItems(t, ctx) {
|
|
|
108
108
|
];
|
|
109
109
|
}
|
|
110
110
|
function renderProfileHero(t, ctx) {
|
|
111
|
-
const { displayName, photoURL, memberSince, isSeller, storeSlug,
|
|
111
|
+
const { displayName, photoURL, memberSince, isSeller, storeSlug, page } = ctx;
|
|
112
112
|
return (_jsx(Section, { color: "inverse", tone: "accent-banner", paddingY: "y-2-5xl", children: _jsx(Div, { className: `${page.container.md}`, children: _jsxs(Stack, { direction: "sm-row", wrap: true, align: "center", smAlign: "end", gap: "md", children: [_jsx(Row, { align: "center", justify: "center", className: `w-20 h-20 flex-shrink-0 ${__O.hidden}`, surface: "default", rounded: "full", children: photoURL ? _jsx(MediaImage, { src: photoURL, alt: displayName, size: "avatar", fallback: "\uD83D\uDC64" }) : _jsx(User, { className: "w-10 h-10 text-white/60" }) }), _jsxs(Stack, { gap: "xs", className: "text-center sm:text-left", children: [_jsxs(Row, { justify: "start", gap: "xs", wrap: true, children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-0", children: displayName }), isSeller && _jsx(Span, { color: "inverse", size: "xs", weight: "semibold", className: "bg-[white]/20", padding: "pill-sm", rounded: "full", children: t("roleSeller") })] }), _jsx(Text, { color: "inverse", variant: "none", size: "sm", children: memberSince })] }), isSeller && storeSlug && (_jsx(Div, { className: "sm:ml-auto", children: _jsxs(Link, { href: String(ROUTES.PUBLIC.STORE_DETAIL(storeSlug)), className: "inline-flex items-center gap-1.5 rounded-full border border-white/30 bg-white/10 hover:bg-white/20 px-4 py-2 text-sm font-medium text-white transition-colors", children: [_jsx(ExternalLink, { className: "w-3.5 h-3.5" }), t("visitStore")] }) }))] }) }) }));
|
|
113
113
|
}
|
|
114
114
|
function renderProfileStatsRow(flex, statItems) {
|
|
@@ -127,9 +127,6 @@ function renderStoreDescriptionSection(isSeller, storeSlug, storeDescription, st
|
|
|
127
127
|
function renderProfileListingsSection(t, products, storeSlug) {
|
|
128
128
|
return (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-4", children: t("listingsTitle") }), products.length === 0 ? (_jsxs(Div, { rounded: "2xl", padding: "3xl", className: "text-center", border: "default", surface: "subtle", children: [_jsx(ShoppingBag, { className: CLS_EMPTY_ICON }), _jsx(Text, { variant: "secondary", size: "sm", children: t("noListings") })] })) : (_jsx(Grid, { gap: "md", className: "grid-cols-2 sm:grid-cols-3 lg:grid-cols-4", children: products.slice(0, 8).map((p) => _jsx(ProductCard, { product: toProductItem(p), href: getProductHref(p) }, p.id)) })), products.length > 8 && storeSlug && (_jsx(Div, { className: "mt-4 text-center", children: _jsx(Link, { href: String(ROUTES.PUBLIC.STORE_PRODUCTS(storeSlug)), className: "text-sm font-medium text-primary hover:underline", children: t("viewAllListings", { count: products.length }) }) }))] }));
|
|
129
129
|
}
|
|
130
|
-
function renderProfileReviewsSection(t, reviews, storeSlug) {
|
|
131
|
-
return (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-4", children: t("reviewsReceivedTitle") }), reviews.length === 0 ? (_jsxs(Div, { rounded: "2xl", padding: "3xl", className: "text-center", border: "default", surface: "subtle", children: [_jsx(Star, { className: CLS_EMPTY_ICON }), _jsx(Text, { variant: "secondary", size: "sm", children: t("noReviewsReceived") })] })) : (_jsx(Grid, { gap: "md", className: "grid-cols-1 sm:grid-cols-2", children: reviews.slice(0, 6).map((review) => _jsx(ReviewCard, { review: review }, review.id)) })), reviews.length > 6 && storeSlug && (_jsx(Div, { className: "mt-4 text-center", children: _jsx(Link, { href: String(ROUTES.PUBLIC.STORE_REVIEWS(storeSlug)), className: "text-sm font-medium text-primary hover:underline", children: t("viewAllReviews", { count: reviews.length }) }) }))] }));
|
|
132
|
-
}
|
|
133
130
|
function renderAuthoredReviewsSection(t, reviews, displayName) {
|
|
134
131
|
return (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-4", children: t("reviewsAuthoredTitle", { name: displayName }) }), reviews.length === 0 ? (_jsxs(Div, { rounded: "2xl", padding: "3xl", className: "text-center", border: "default", surface: "subtle", children: [_jsx(Star, { className: CLS_EMPTY_ICON }), _jsx(Text, { variant: "secondary", size: "sm", children: t("noReviewsAuthored", { name: displayName }) })] })) : (_jsx(Grid, { gap: "md", className: "grid-cols-1 sm:grid-cols-2", children: reviews.slice(0, 6).map((review) => _jsx(ReviewCard, { review: review }, review.id)) }))] }));
|
|
135
132
|
}
|
|
@@ -10,6 +10,8 @@ export { ShippingPolicyView } from "./components/ShippingPolicyView";
|
|
|
10
10
|
export type { ShippingPolicyViewProps } from "./components/ShippingPolicyView";
|
|
11
11
|
export { HowCheckoutWorksView } from "./components/HowCheckoutWorksView";
|
|
12
12
|
export type { HowCheckoutWorksViewProps } from "./components/HowCheckoutWorksView";
|
|
13
|
+
export { HowEmiWorksView } from "./components/HowEmiWorksView";
|
|
14
|
+
export type { HowEmiWorksViewProps } from "./components/HowEmiWorksView";
|
|
13
15
|
export { HowOffersWorkView } from "./components/HowOffersWorkView";
|
|
14
16
|
export type { HowOffersWorkViewProps } from "./components/HowOffersWorkView";
|
|
15
17
|
export { HowOrdersWorkView } from "./components/HowOrdersWorkView";
|
|
@@ -4,6 +4,7 @@ export { FeesView } from "./components/FeesView";
|
|
|
4
4
|
export { SecurityPrivacyView } from "./components/SecurityPrivacyView";
|
|
5
5
|
export { ShippingPolicyView } from "./components/ShippingPolicyView";
|
|
6
6
|
export { HowCheckoutWorksView } from "./components/HowCheckoutWorksView";
|
|
7
|
+
export { HowEmiWorksView } from "./components/HowEmiWorksView";
|
|
7
8
|
export { HowOffersWorkView } from "./components/HowOffersWorkView";
|
|
8
9
|
export { HowOrdersWorkView } from "./components/HowOrdersWorkView";
|
|
9
10
|
export { HowReviewsWorkView } from "./components/HowReviewsWorkView";
|
|
@@ -14,4 +14,4 @@ export interface BecomeSellerViewProps {
|
|
|
14
14
|
isLoading?: boolean;
|
|
15
15
|
className?: string;
|
|
16
16
|
}
|
|
17
|
-
export declare function BecomeSellerView({ labels, renderGuide, renderSuccess, renderAlreadySeller, state, isLoading, className, }: BecomeSellerViewProps): React.JSX.Element;
|
|
17
|
+
export declare function BecomeSellerView({ labels, renderGuide, renderSuccess, renderAlreadySeller, state, isLoading: _isLoading, className, }: BecomeSellerViewProps): React.JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Div, Heading } from "../../../ui";
|
|
3
|
-
export function BecomeSellerView({ labels = {}, renderGuide, renderSuccess, renderAlreadySeller, state = "guide", isLoading = false, className = "", }) {
|
|
3
|
+
export function BecomeSellerView({ labels = {}, renderGuide, renderSuccess, renderAlreadySeller, state = "guide", isLoading: _isLoading = false, className = "", }) {
|
|
4
4
|
return (_jsxs(Div, { className: className, children: [labels.title && state === "guide" && (_jsx(Heading, { level: 1, className: "mb-6", size: "2xl", weight: "bold", children: labels.title })), state === "guide" && renderGuide?.(), state === "success" && renderSuccess?.(), state === "already-seller" && renderAlreadySeller?.()] }));
|
|
5
5
|
}
|
|
@@ -32,7 +32,7 @@ const DEFAULT_ICONS = {
|
|
|
32
32
|
export function NotificationBell({ limit = 10, viewAllHref, labels, icons, renderLink, onMarkAllReadSuccess, onMarkAllReadError, buttonClassName = "", dropdownClassName = "", hideOnMobile = true, }) {
|
|
33
33
|
const [isOpen, setIsOpen] = useState(false);
|
|
34
34
|
const dropdownRef = useRef(null);
|
|
35
|
-
const { showSuccess, showError } = useMessage();
|
|
35
|
+
const { showSuccess, showError: _showError } = useMessage();
|
|
36
36
|
const { showToast } = useToast();
|
|
37
37
|
const { notifications, unreadCount, isLoading, refetch, markRead, markAllRead, isMarkingAll, } = useNotifications(limit);
|
|
38
38
|
const notificationIcons = { ...DEFAULT_ICONS, ...icons };
|
|
@@ -55,7 +55,6 @@ export function NotificationBell({ limit = 10, viewAllHref, labels, icons, rende
|
|
|
55
55
|
}
|
|
56
56
|
}, [markRead, refetch, showToast]);
|
|
57
57
|
const emitSuccess = onMarkAllReadSuccess ?? showSuccess;
|
|
58
|
-
const emitError = onMarkAllReadError ?? showError;
|
|
59
58
|
const handleMarkAllRead = useCallback(async () => {
|
|
60
59
|
try {
|
|
61
60
|
await markAllRead(undefined);
|
|
@@ -16,7 +16,6 @@ const __O = {
|
|
|
16
16
|
yAuto: "overflow-y-auto",
|
|
17
17
|
};
|
|
18
18
|
// --- Constants ---------------------------------------------------------------
|
|
19
|
-
const CLS_INPUT = "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary-500";
|
|
20
19
|
const CATEGORY_OPTIONS = [
|
|
21
20
|
{ label: "Order Issue", value: "order_issue" },
|
|
22
21
|
{ label: "Billing / Payment", value: "billing_payment" },
|
|
@@ -4,7 +4,7 @@ import { normalizeError } from "../../../errors/normalize";
|
|
|
4
4
|
import { useApiMutation } from "@mohasinac/appkit/client";
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
7
|
-
import { Alert, Button, Div, Input, Label, Row, Select, Stack, StackedViewShell, Text } from "../../../ui";
|
|
7
|
+
import { Alert, Button, Div, Input, Label, Row, Select, Stack, StackedViewShell, Text, TextLink } from "../../../ui";
|
|
8
8
|
import { apiClient } from "../../../http";
|
|
9
9
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
10
10
|
import { DataTable } from "./DataTable";
|
|
@@ -117,7 +117,7 @@ export function AdminAdsView({ endpoint = ADMIN_ENDPOINTS.ADS, labels = {}, crea
|
|
|
117
117
|
render: (row) => {
|
|
118
118
|
const nextStatus = row.status === "active" ? "paused" : "active";
|
|
119
119
|
const cannotPublish = nextStatus === "active" && row.publishReady === false;
|
|
120
|
-
return (_jsxs(Row, { align: "center", gap: "sm", children: [renderEditLink ? renderEditLink(row) : (_jsx("
|
|
120
|
+
return (_jsxs(Row, { align: "center", gap: "sm", children: [renderEditLink ? renderEditLink(row) : (_jsx(TextLink, { variant: "bare", href: `/admin/ads/${row.id}/edit`, rounded: "md", paddingX: "sm", size: "xs", layout: "inline-flex", align: "center", className: "h-8 border border-neutral-200 border-[var(--appkit-color-border)]", children: "Edit" })), _jsx(Button, { size: "sm", variant: "outline", disabled: statusMutation.isPending || cannotPublish, onClick: () => statusMutation.mutate({ id: row.id, nextStatus }), children: row.status === "active" ? "Pause" : "Publish" })] }));
|
|
121
121
|
},
|
|
122
122
|
},
|
|
123
123
|
], [renderEditLink, statusMutation]);
|
|
@@ -156,7 +156,7 @@ export function AdminAdsView({ endpoint = ADMIN_ENDPOINTS.ADS, labels = {}, crea
|
|
|
156
156
|
settingsMutation.mutate(payload);
|
|
157
157
|
};
|
|
158
158
|
return (_jsx(StackedViewShell, { portal: "admin", ...rest, title: labels.title ?? "Ad Inventory", sections: [
|
|
159
|
-
_jsxs(Row, { align: "center", justify: "between", gap: "3", children: [_jsx(Text, { variant: "secondary", children: "Manage ad inventory, placement mapping, and publishing state." }), _jsx("
|
|
159
|
+
_jsxs(Row, { align: "center", justify: "between", gap: "3", children: [_jsx(Text, { variant: "secondary", children: "Manage ad inventory, placement mapping, and publishing state." }), _jsx(TextLink, { variant: "bare", href: createHref, rounded: "md", paddingX: "sm", size: "sm", weight: "medium", layout: "inline-flex", align: "center", className: "h-9 bg-neutral-900 text-white bg-[var(--appkit-color-surface)] dark:text-[var(--appkit-color-text)]", children: "New ad" })] }),
|
|
160
160
|
adsQuery.error ? (_jsx(Alert, { variant: "error", title: "Could not load ads", children: adsQuery.error instanceof Error ? adsQuery.error.message : "Unknown error" })) : null,
|
|
161
161
|
_jsx(AdsSettingsPanel, { adsenseClientId: adsenseClientId, setAdsenseClientId: setAdsenseClientId, thirdPartyScriptUrl: thirdPartyScriptUrl, setThirdPartyScriptUrl: setThirdPartyScriptUrl, consentRequired: consentRequired, setConsentRequired: setConsentRequired, serverCredentialIssues: serverCredentialIssues, localCredentialIssues: localCredentialIssues, credentialStatus: credentialStatus, providerCredentialsMasked: adsQuery.data?.providerCredentialsMasked, settingsMutation: settingsMutation, hasPendingCredentialInput: hasPendingCredentialInput, currentConsentRequired: Boolean(adsQuery.data?.consentRequired), settingsMessage: settingsMessage, onSave: saveSettings }),
|
|
162
162
|
_jsx(AdsFilterRow, { q: q, setQ: setQ, status: status, setStatus: setStatus, provider: provider, setProvider: setProvider, placement: placement, setPlacement: setPlacement, placements: placements, onPageReset: () => setPage(1) }),
|
|
@@ -5,7 +5,7 @@ import { useApiMutation } from "@mohasinac/appkit/client";
|
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { useQuery } from "@tanstack/react-query";
|
|
7
7
|
import { Button, ConfirmDeleteModal, Div, Heading, Input, RichTextEditor, RichTextRenderer, Row, Select, Span, Stack, StackedViewShell, TagInput, Text, Toggle, useToast } from "../../../ui";
|
|
8
|
-
import { ImageUpload, useMediaUpload } from "../../media";
|
|
8
|
+
import { ImageUpload, MediaImage, useMediaUpload } from "../../media";
|
|
9
9
|
import { apiClient } from "../../../http";
|
|
10
10
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
11
11
|
import { StepForm } from "../../shell";
|
|
@@ -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, { rounded: "lg", padding: "5", className: "border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-raised)] 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("
|
|
203
|
+
const previewSection = (_jsxs(Div, { rounded: "lg", padding: "5", className: "border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-raised)] 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(Div, { className: "relative h-64 w-full mb-4 overflow-hidden", rounded: "md", children: _jsx(MediaImage, { src: draft.coverImage, alt: "", size: "hero" }) })) : 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
|
] }));
|
|
@@ -51,10 +51,6 @@ const bundleFormSchema = z.object({
|
|
|
51
51
|
isActive: z.boolean(),
|
|
52
52
|
coverImage: z.string().optional().or(z.literal("")),
|
|
53
53
|
}).passthrough();
|
|
54
|
-
async function parseResponseError(res) {
|
|
55
|
-
const err = (await res.json().catch(() => null));
|
|
56
|
-
return err?.error?.message ?? `Create failed: ${res.status}`;
|
|
57
|
-
}
|
|
58
54
|
function bundleToForm(bundle) {
|
|
59
55
|
if (!bundle)
|
|
60
56
|
return EMPTY_FORM;
|