@mohasinac/appkit 4.41.2 → 4.41.3

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.
@@ -17,6 +17,16 @@ import { apiClient } from "../../../http";
17
17
  const PAGE_SIZE = 50;
18
18
  const FILTER_KEYS = ["active"];
19
19
  const DEFAULT_SORT = "order";
20
+ function extractCarouselRows(response) {
21
+ if (Array.isArray(response))
22
+ return response;
23
+ if (!response || typeof response !== "object")
24
+ return undefined;
25
+ const obj = response;
26
+ if (Array.isArray(obj.data))
27
+ return obj.data;
28
+ return Array.isArray(obj.items) ? obj.items : undefined;
29
+ }
20
30
  export function AdminCarouselView({ children, onBulkDelete, ...props }) {
21
31
  const hasChildren = React.Children.count(children) > 0;
22
32
  const [draggingId, setDraggingId] = useState(null);
@@ -30,7 +40,7 @@ export function AdminCarouselView({ children, onBulkDelete, ...props }) {
30
40
  queryKey: ["admin", "carousel", "listing"],
31
41
  endpoint: `${HOMEPAGE_ENDPOINTS.CAROUSEL}?includeInactive=true`,
32
42
  mapRows: (response) => {
33
- const sourceItems = Array.isArray(response.data) ? response.data : response.items;
43
+ const sourceItems = extractCarouselRows(response);
34
44
  return toRecordArray(sourceItems)
35
45
  .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
36
46
  .map((item, index) => {
@@ -50,7 +60,13 @@ export function AdminCarouselView({ children, onBulkDelete, ...props }) {
50
60
  };
51
61
  });
52
62
  },
53
- getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
63
+ getTotal: (response, mappedRows) => {
64
+ if (Array.isArray(response) || !response || typeof response !== "object") {
65
+ return mappedRows.length;
66
+ }
67
+ const total = response.total;
68
+ return typeof total === "number" ? total : mappedRows.length;
69
+ },
54
70
  buildFilters: (filterState) => {
55
71
  const activeRaw = filterState.active;
56
72
  if (activeRaw === "true")
@@ -9,6 +9,24 @@ import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdmin
9
9
  import { DataListingView } from "./DataListingView";
10
10
  import { AdminCategoryEditorView } from "./AdminCategoryEditorView";
11
11
  import { ADMIN_BULK_ACTIONS, ROW_ACTION_META } from "../../products/constants/action-defs";
12
+ /** Rows, whichever of the three shapes the endpoint returns. */
13
+ function extractCategoryRows(response) {
14
+ if (Array.isArray(response))
15
+ return response;
16
+ if (!response || typeof response !== "object")
17
+ return undefined;
18
+ const obj = response;
19
+ if (Array.isArray(obj.data))
20
+ return obj.data;
21
+ return Array.isArray(obj.items) ? obj.items : undefined;
22
+ }
23
+ /** `total` only exists on the object shapes; a bare array has none. */
24
+ function extractCategoryTotal(response) {
25
+ if (Array.isArray(response) || !response || typeof response !== "object")
26
+ return undefined;
27
+ const total = response.total;
28
+ return typeof total === "number" ? total : undefined;
29
+ }
12
30
  const COLUMNS = [
13
31
  {
14
32
  key: "primary",
@@ -46,7 +64,7 @@ const ADMIN_CATEGORIES_CONFIG = {
46
64
  ],
47
65
  columns: COLUMNS,
48
66
  mapRows: (response) => {
49
- const sourceItems = Array.isArray(response.data) ? response.data : response.items;
67
+ const sourceItems = extractCategoryRows(response);
50
68
  return toRecordArray(sourceItems).map((item, index) => ({
51
69
  id: toStringValue(item.id, `category-${index}`),
52
70
  primary: toStringValue(item.name, "Untitled category"),
@@ -59,7 +77,7 @@ const ADMIN_CATEGORIES_CONFIG = {
59
77
  updatedAt: toRelativeDate(item.updatedAt ?? item.createdAt),
60
78
  }));
61
79
  },
62
- getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
80
+ getTotal: (response, mappedRows) => extractCategoryTotal(response) ?? mappedRows.length,
63
81
  buildFilters: (state) => {
64
82
  const parts = [];
65
83
  if (state.isActive)
@@ -38,7 +38,7 @@ function FeaturedBundleCard({ bundle, showSavingsBadge = true, onBuyNow, }) {
38
38
  const cover = bundle.display?.coverImage;
39
39
  const href = String(ROUTES.PUBLIC.BUNDLE_DETAIL?.(bundle.slug) ?? "#");
40
40
  const discount = computeBundleDiscount(bundle.bundlePrice, bundle.bundleOriginalTotal);
41
- return (_jsxs(Stack, { gap: "none", surface: "default", rounded: "xl", border: "default", children: [_jsxs(Link, { href: href, className: "group block p-[var(--appkit-space-3)] hover:no-underline", children: [_jsxs(Div, { className: `relative mb-2 aspect-square ${__O.hidden}`, rounded: "lg", surface: "subtle", children: [cover ? (_jsx(MediaImage, { src: cover, alt: bundle.name, size: "card", className: "transition-transform group-hover:scale-105" })) : (_jsx(Row, { textSize: "3xl", className: "h-full w-full", align: "center", justify: "center", children: PLACEHOLDER_EMOJI })), showSavingsBadge && discount && (_jsx(Badge, { variant: "success", className: "absolute left-2 top-2", children: BUNDLE_COPY.detail.discountBadge(discount.percent) }))] }), _jsx(Text, { className: "line-clamp-2", size: "sm", weight: "semibold", children: bundle.name }), _jsxs(Row, { gap: "sm", align: "center", className: "mt-1", wrap: true, children: [_jsx(Text, { size: "sm", weight: "bold", children: _jsx(GatedPrice, { label: "Sign in to see the bundle price", children: bundle.bundlePrice
41
+ return (_jsxs(Stack, { gap: "none", surface: "default", rounded: "xl", border: "default", children: [_jsxs(Link, { href: href, className: "group block p-[var(--appkit-space-3)] hover:no-underline", children: [_jsxs(Div, { className: `relative mb-2 aspect-square ${__O.hidden}`, rounded: "lg", surface: "subtle", children: [cover ? (_jsx(MediaImage, { src: cover, alt: bundle.name, size: "card", className: "transition-transform group-hover:scale-105" })) : (_jsx(Row, { textSize: "3xl", className: "h-full w-full", align: "center", justify: "center", children: PLACEHOLDER_EMOJI })), showSavingsBadge && discount && (_jsx(PricesOnly, { children: _jsx(Badge, { variant: "success", className: "absolute left-2 top-2", children: BUNDLE_COPY.detail.discountBadge(discount.percent) }) }))] }), _jsx(Text, { className: "line-clamp-2", size: "sm", weight: "semibold", children: bundle.name }), _jsxs(Row, { gap: "sm", align: "center", className: "mt-1", wrap: true, children: [_jsx(Text, { size: "sm", weight: "bold", children: _jsx(GatedPrice, { label: "Sign in to see the bundle price", children: bundle.bundlePrice
42
42
  ? formatCurrency(bundle.bundlePrice, "INR")
43
43
  : BUNDLE_COPY.featured.priceFallback }) }), discount && (_jsx(PricesOnly, { children: _jsx(Text, { size: "xs", color: "muted", className: "line-through", children: formatCurrency(discount.originalTotal, "INR") }) })), _jsxs(Text, { size: "xs", color: "muted", children: ["\u00B7 ", BUNDLE_COPY.featured.itemCount(memberCount)] }), stock !== "in_stock" && (_jsx(Badge, { variant: BUNDLE_STOCK_VARIANT[stock], children: BUNDLE_COPY.stockBadge.listVariantOutOfStock }))] })] }), onBuyNow && (_jsx(Div, { border: "subtle", className: `border-t ${__P.p3}`, padding: "t-xs", children: _jsx(BundleBuyNowCta, { bundleSlug: bundle.slug, outOfStock: stock === "out_of_stock", onBuyNow: onBuyNow, compact: true }) }))] }));
44
44
  }
@@ -10,7 +10,7 @@ const CLS_BUNDLE_PILL = "inline-flex items-center rounded-full bg-violet-600 px-
10
10
  const CLS_STOCK_OK = "bg-success-solid text-success-on-solid";
11
11
  // audit-content-alignment-ok: button label text, not page content — buttons are universally center-labeled
12
12
  const CLS_VIEW_BTN = "mt-2 w-full cursor-pointer rounded-md bg-violet-600 py-[var(--appkit-space-1-5)] text-center text-[length:var(--appkit-text-xs)] font-semibold text-white transition-colors hover:bg-violet-700 active:scale-[0.98]";
13
- import { BaseListingCard, Div, GatedPrice, Row, Span, Stack, Text, TextLink } from "../../../ui";
13
+ import { BaseListingCard, Div, GatedPrice, PricesOnly, Row, Span, Stack, Text, TextLink } from "../../../ui";
14
14
  import { MediaImage } from "../../media/MediaImage";
15
15
  import { computeBundleDiscount } from "../../../_internal/shared/features/categories/bundle-pricing";
16
16
  import { BUNDLE_COPY } from "../../../_internal/shared/features/categories/bundle-copy";
@@ -49,7 +49,7 @@ export function MarketplaceBundleCard({ bundle, className = "", variant = "grid"
49
49
  }
50
50
  router.push(String(detailHref));
51
51
  }, [detailHref, onNavigate, router]);
52
- return (_jsxs(BaseListingCard, { isSelected: isSelected, variant: variant, className: className, onMouseDown: !isSelected ? longPress.onMouseDown : undefined, onMouseUp: !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: !isSelected ? longPress.onTouchEnd : undefined, onTouchCancel: !isSelected ? longPress.onTouchCancel : undefined, children: [_jsxs(BaseListingCard.Hero, { aspect: "square", variant: variant, children: [_jsx(TextLink, { href: String(detailHref), className: "absolute inset-0 block", children: showCollage ? (_jsx(Div, { layout: "grid", className: `h-full w-full gap-[0.125rem] bg-[var(--appkit-color-surface-muted)] ${collageTiles.length === 2 ? "grid-cols-2 grid-rows-1" : "grid-cols-2 grid-rows-2"}`, children: collageTiles.map((tile, i) => (_jsxs(Div, { className: "relative overflow-hidden bg-[var(--appkit-color-surface-muted)]", children: [_jsx(MediaImage, { src: tile.imageURL, alt: tile.title ?? `${bundle.name} item ${i + 1}`, size: "card" }), i === collageTiles.length - 1 && overflow > 0 && (_jsxs(Row, { textWeight: "semibold", textSize: "sm", surface: "overlay-md", className: "absolute inset-0 text-white", align: "center", justify: "center", children: ["+", overflow] }))] }, `${tile.productId}-${i}`))) })) : cover ? (_jsx(Div, { className: "absolute inset-0 bg-[var(--appkit-color-surface-muted)]", children: _jsx(MediaImage, { src: cover, alt: bundle.name, size: "card" }) })) : (_jsx(Row, { className: "absolute inset-0 bg-[var(--appkit-color-surface-muted)]", align: "center", justify: "center", children: _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "xs", children: "No image" }) })) }), discount && (_jsx(Span, { size: "xs", weight: "bold", className: "absolute left-2 top-2 bg-success-solid text-success-on-solid", rounded: "full", padding: "pill-xs", children: BUNDLE_COPY.detail.discountBadge(discount.percent) })), _jsxs(Stack, { className: "absolute right-2 top-2", align: "end", gap: "xs", children: [_jsx(Span, { size: "xs", weight: "medium", className: CLS_BUNDLE_PILL, children: mergedLabels.bundleBadge }), _jsx(Span, { layout: "inline-flex", color: "inverse", className: `${stock === "out_of_stock" ? "bg-neutral-500 " : CLS_STOCK_OK}`, rounded: "full", padding: "pill-xs", size: "xs", weight: "medium", children: stock === "out_of_stock" ? mergedLabels.outOfStockBadge : mergedLabels.inStockBadge })] }), stock === "out_of_stock" && (_jsx(Row, { surface: "overlay-xs", className: "absolute inset-0", align: "center", justify: "center", children: _jsx(Span, { color: "inverse", size: "xs", weight: "bold", className: "bg-neutral-900/80 tracking-wider", rounded: "default", padding: "pill-md", transform: "uppercase", children: mergedLabels.outOfStockBadge }) })), onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (event) => {
52
+ return (_jsxs(BaseListingCard, { isSelected: isSelected, variant: variant, className: className, onMouseDown: !isSelected ? longPress.onMouseDown : undefined, onMouseUp: !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: !isSelected ? longPress.onTouchEnd : undefined, onTouchCancel: !isSelected ? longPress.onTouchCancel : undefined, children: [_jsxs(BaseListingCard.Hero, { aspect: "square", variant: variant, children: [_jsx(TextLink, { href: String(detailHref), className: "absolute inset-0 block", children: showCollage ? (_jsx(Div, { layout: "grid", className: `h-full w-full gap-[0.125rem] bg-[var(--appkit-color-surface-muted)] ${collageTiles.length === 2 ? "grid-cols-2 grid-rows-1" : "grid-cols-2 grid-rows-2"}`, children: collageTiles.map((tile, i) => (_jsxs(Div, { className: "relative overflow-hidden bg-[var(--appkit-color-surface-muted)]", children: [_jsx(MediaImage, { src: tile.imageURL, alt: tile.title ?? `${bundle.name} item ${i + 1}`, size: "card" }), i === collageTiles.length - 1 && overflow > 0 && (_jsxs(Row, { textWeight: "semibold", textSize: "sm", surface: "overlay-md", className: "absolute inset-0 text-white", align: "center", justify: "center", children: ["+", overflow] }))] }, `${tile.productId}-${i}`))) })) : cover ? (_jsx(Div, { className: "absolute inset-0 bg-[var(--appkit-color-surface-muted)]", children: _jsx(MediaImage, { src: cover, alt: bundle.name, size: "card" }) })) : (_jsx(Row, { className: "absolute inset-0 bg-[var(--appkit-color-surface-muted)]", align: "center", justify: "center", children: _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "xs", children: "No image" }) })) }), discount && (_jsx(PricesOnly, { children: _jsx(Span, { size: "xs", weight: "bold", className: "absolute left-2 top-2 bg-success-solid text-success-on-solid", rounded: "full", padding: "pill-xs", children: BUNDLE_COPY.detail.discountBadge(discount.percent) }) })), _jsxs(Stack, { className: "absolute right-2 top-2", align: "end", gap: "xs", children: [_jsx(Span, { size: "xs", weight: "medium", className: CLS_BUNDLE_PILL, children: mergedLabels.bundleBadge }), _jsx(Span, { layout: "inline-flex", color: "inverse", className: `${stock === "out_of_stock" ? "bg-neutral-500 " : CLS_STOCK_OK}`, rounded: "full", padding: "pill-xs", size: "xs", weight: "medium", children: stock === "out_of_stock" ? mergedLabels.outOfStockBadge : mergedLabels.inStockBadge })] }), stock === "out_of_stock" && (_jsx(Row, { surface: "overlay-xs", className: "absolute inset-0", align: "center", justify: "center", children: _jsx(Span, { color: "inverse", size: "xs", weight: "bold", className: "bg-neutral-900/80 tracking-wider", rounded: "default", padding: "pill-md", transform: "uppercase", children: mergedLabels.outOfStockBadge }) })), onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (event) => {
53
53
  event.stopPropagation();
54
54
  onSelect(bundle.id, !isSelected);
55
55
  }, className: selectable || isSelected
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohasinac/appkit",
3
- "version": "4.41.2",
3
+ "version": "4.41.3",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"