@mohasinac/appkit 2.7.9 → 2.7.10

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 (35) hide show
  1. package/dist/_internal/shared/config/index.d.ts +1 -1
  2. package/dist/_internal/shared/config/schema.d.ts +95 -1
  3. package/dist/client-entry.d.ts +1 -1
  4. package/dist/client.d.ts +3 -0
  5. package/dist/client.js +5 -0
  6. package/dist/features/account/components/UserOffersPanel.js +17 -5
  7. package/dist/features/auctions/components/AuctionDetailPageView.js +17 -1
  8. package/dist/features/auctions/components/PlaceBidFormClient.js +10 -5
  9. package/dist/features/categories/components/BundleBuyNowCta.js +13 -6
  10. package/dist/features/events/components/EventPollWidget.js +7 -1
  11. package/dist/features/events/components/SpinWheelView.js +12 -5
  12. package/dist/features/pre-orders/components/PreOrderActionsClient.js +10 -3
  13. package/dist/features/products/components/MakeOfferButton.js +16 -8
  14. package/dist/features/products/components/PrizeRevealModal.js +18 -5
  15. package/dist/features/products/components/ProductDetailPageView.js +23 -1
  16. package/dist/features/seller/components/SellerOffersPanel.js +17 -5
  17. package/dist/features/wishlist/components/WishlistToggleButton.js +26 -12
  18. package/dist/http/api-handler.js +7 -1
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.js +2 -0
  21. package/dist/server.d.ts +1 -0
  22. package/dist/server.js +2 -0
  23. package/dist/tailwind-utilities.css +1 -1
  24. package/dist/ui/components/BaseListingCard.js +8 -6
  25. package/dist/ui/components/Button.style.css +8 -5
  26. package/dist/ui/components/ListingLayout.style.css +19 -9
  27. package/dist/ui/components/LoginRequiredModal.d.ts +9 -0
  28. package/dist/ui/components/LoginRequiredModal.js +11 -0
  29. package/dist/ui/index.d.ts +2 -0
  30. package/dist/ui/index.js +1 -0
  31. package/dist/utils/auth-error.d.ts +8 -0
  32. package/dist/utils/auth-error.js +20 -0
  33. package/dist/utils/index.d.ts +1 -0
  34. package/dist/utils/index.js +1 -0
  35. package/package.json +1 -1
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useCallback, useEffect, useState, useTransition } from "react";
4
- import { Alert, Badge, Button, Div, Heading, Input, Spinner, Text } from "../../../ui";
4
+ import { Alert, Badge, Button, Div, Heading, Input, LoginRequiredModal, Spinner, Text } from "../../../ui";
5
+ import { isAuthError } from "../../../utils/auth-error";
5
6
  function formatRupees(amount) {
6
7
  if (amount === undefined || amount === null)
7
8
  return "—";
@@ -46,7 +47,7 @@ function statusVariant(status) {
46
47
  default: return "default";
47
48
  }
48
49
  }
49
- function OfferCard({ offer, onRespond, onUpdate }) {
50
+ function OfferCard({ offer, onRespond, onUpdate, onNeedsLogin }) {
50
51
  const [uiState, setUiState] = useState("idle");
51
52
  const [counterInput, setCounterInput] = useState("");
52
53
  const [sellerNote, setSellerNote] = useState("");
@@ -68,7 +69,12 @@ function OfferCard({ offer, onRespond, onUpdate }) {
68
69
  setUiState("idle");
69
70
  }
70
71
  catch (err) {
71
- setError(err instanceof Error ? err.message : "Something went wrong.");
72
+ if (isAuthError(err)) {
73
+ onNeedsLogin();
74
+ }
75
+ else {
76
+ setError(err instanceof Error ? err.message : "Something went wrong.");
77
+ }
72
78
  }
73
79
  });
74
80
  }
@@ -100,6 +106,7 @@ export function SellerOffersPanel({ fetchEndpoint = "/api/store/offers", onRespo
100
106
  const [offers, setOffers] = useState([]);
101
107
  const [loading, setLoading] = useState(true);
102
108
  const [fetchError, setFetchError] = useState("");
109
+ const [showLoginModal, setShowLoginModal] = useState(false);
103
110
  const [statusFilter, setStatusFilter] = useState("all");
104
111
  const loadOffers = useCallback(async () => {
105
112
  setLoading(true);
@@ -109,8 +116,13 @@ export function SellerOffersPanel({ fetchEndpoint = "/api/store/offers", onRespo
109
116
  ? fetchEndpoint
110
117
  : `${fetchEndpoint}?status=${statusFilter}`;
111
118
  const res = await fetch(url);
112
- if (!res.ok)
119
+ if (!res.ok) {
120
+ if (res.status === 401 || res.status === 403) {
121
+ setShowLoginModal(true);
122
+ return;
123
+ }
113
124
  throw new Error(`Error ${res.status}`);
125
+ }
114
126
  const json = (await res.json());
115
127
  setOffers(json.items ?? json.offers ?? []);
116
128
  }
@@ -134,5 +146,5 @@ export function SellerOffersPanel({ fetchEndpoint = "/api/store/offers", onRespo
134
146
  { value: "expired", label: "Expired" },
135
147
  ];
136
148
  const pending = offers.filter((o) => o.status === "pending").length;
137
- return (_jsxs(Div, { className: `space-y-4 ${className}`, children: [_jsxs(Div, { className: "flex items-center justify-between flex-wrap gap-2", children: [_jsxs(Div, { children: [_jsx(Heading, { level: 2, className: "text-lg font-semibold text-zinc-900 dark:text-zinc-100", children: "Offers Received" }), pending > 0 && (_jsxs(Text, { className: "text-xs text-amber-600 dark:text-amber-400 mt-0.5", children: [pending, " pending offer", pending > 1 ? "s" : "", " awaiting your response"] }))] }), _jsx(Button, { size: "sm", variant: "ghost", onClick: loadOffers, disabled: loading, className: "border border-zinc-300 dark:border-zinc-600 text-xs", children: loading ? "Refreshing…" : "Refresh" })] }), _jsx(Div, { className: "flex gap-1 flex-wrap", children: STATUS_FILTERS.map((f) => (_jsx(Button, { size: "sm", variant: statusFilter === f.value ? "primary" : "ghost", onClick: () => setStatusFilter(f.value), className: "text-xs px-2 py-1", children: f.label }, f.value))) }), fetchError && _jsx(Alert, { variant: "error", children: _jsx(Text, { className: "text-sm", children: fetchError }) }), loading && (_jsx(Div, { className: "flex justify-center py-12", children: _jsx(Spinner, { size: "lg" }) })), !loading && offers.length === 0 && (_jsx(Div, { className: "text-center py-12", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-500 text-sm", children: "No offers found" }) })), !loading && offers.length > 0 && (_jsx(Div, { className: "space-y-3", children: offers.map((offer) => (_jsx(OfferCard, { offer: offer, onRespond: onRespond, onUpdate: handleUpdate }, offer.id))) }))] }));
149
+ return (_jsxs(Div, { className: `space-y-4 ${className}`, children: [_jsx(LoginRequiredModal, { isOpen: showLoginModal, onClose: () => setShowLoginModal(false), message: "You need to be signed in to manage offers. Please log in or create an account to continue." }), _jsxs(Div, { className: "flex items-center justify-between flex-wrap gap-2", children: [_jsxs(Div, { children: [_jsx(Heading, { level: 2, className: "text-lg font-semibold text-zinc-900 dark:text-zinc-100", children: "Offers Received" }), pending > 0 && (_jsxs(Text, { className: "text-xs text-amber-600 dark:text-amber-400 mt-0.5", children: [pending, " pending offer", pending > 1 ? "s" : "", " awaiting your response"] }))] }), _jsx(Button, { size: "sm", variant: "ghost", onClick: loadOffers, disabled: loading, className: "border border-zinc-300 dark:border-zinc-600 text-xs", children: loading ? "Refreshing…" : "Refresh" })] }), _jsx(Div, { className: "flex gap-1 flex-wrap", children: STATUS_FILTERS.map((f) => (_jsx(Button, { size: "sm", variant: statusFilter === f.value ? "primary" : "ghost", onClick: () => setStatusFilter(f.value), className: "text-xs px-2 py-1", children: f.label }, f.value))) }), fetchError && _jsx(Alert, { variant: "error", children: _jsx(Text, { className: "text-sm", children: fetchError }) }), loading && (_jsx(Div, { className: "flex justify-center py-12", children: _jsx(Spinner, { size: "lg" }) })), !loading && offers.length === 0 && (_jsx(Div, { className: "text-center py-12", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-500 text-sm", children: "No offers found" }) })), !loading && offers.length > 0 && (_jsx(Div, { className: "space-y-3", children: offers.map((offer) => (_jsx(OfferCard, { offer: offer, onRespond: onRespond, onUpdate: handleUpdate, onNeedsLogin: () => setShowLoginModal(true) }, offer.id))) }))] }));
138
150
  }
@@ -1,5 +1,8 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Button } from "../../../ui";
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Button, LoginRequiredModal } from "../../../ui";
5
+ import { isAuthError } from "../../../utils/auth-error";
3
6
  const sizeClasses = {
4
7
  sm: "w-7 h-7",
5
8
  md: "w-9 h-9",
@@ -7,14 +10,25 @@ const sizeClasses = {
7
10
  };
8
11
  export function WishlistToggleButton({ inWishlist, isLoading = false, onToggle, addLabel, removeLabel, className = "", size = "md", }) {
9
12
  const label = inWishlist ? removeLabel : addLabel;
10
- return (_jsx(Button, { type: "button", onClick: onToggle, disabled: isLoading, "aria-label": label, title: label, className: `
11
- flex items-center justify-center rounded-full
12
- transition-all duration-150
13
- ${inWishlist
14
- ? "bg-rose-50 text-rose-500 hover:bg-rose-100"
15
- : "bg-white/80 text-zinc-400 hover:text-rose-400"}
16
- ${sizeClasses[size]}
17
- ${isLoading ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
18
- ${className}
19
- `, children: _jsx("svg", { className: "w-4/6 h-4/6", viewBox: "0 0 24 24", fill: inWishlist ? "currentColor" : "none", stroke: "currentColor", strokeWidth: 2, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" }) }) }));
13
+ const [showLoginModal, setShowLoginModal] = useState(false);
14
+ async function handleClick(e) {
15
+ try {
16
+ await onToggle(e);
17
+ }
18
+ catch (err) {
19
+ if (isAuthError(err)) {
20
+ setShowLoginModal(true);
21
+ }
22
+ }
23
+ }
24
+ return (_jsxs(_Fragment, { children: [_jsx(LoginRequiredModal, { isOpen: showLoginModal, onClose: () => setShowLoginModal(false), message: "You need to be signed in to save items to your wishlist. Please log in or create an account." }), _jsx(Button, { type: "button", onClick: handleClick, disabled: isLoading, "aria-label": label, title: label, className: `
25
+ flex items-center justify-center rounded-full
26
+ transition-all duration-150
27
+ ${inWishlist
28
+ ? "bg-rose-50 text-rose-500 hover:bg-rose-100"
29
+ : "bg-white/80 text-zinc-400 hover:text-rose-400"}
30
+ ${sizeClasses[size]}
31
+ ${isLoading ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
32
+ ${className}
33
+ `, children: _jsx("svg", { className: "w-4/6 h-4/6", viewBox: "0 0 24 24", fill: inWishlist ? "currentColor" : "none", stroke: "currentColor", strokeWidth: 2, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" }) }) })] }));
20
34
  }
@@ -34,7 +34,13 @@ async function getUserFromRequest(request) {
34
34
  if (!sessionCookie)
35
35
  return null;
36
36
  const providers = getProviders();
37
- const decoded = await providers.session.verifySession(sessionCookie);
37
+ let decoded;
38
+ try {
39
+ decoded = await providers.session.verifySession(sessionCookie);
40
+ }
41
+ catch {
42
+ throw new AuthenticationError(ERROR_MESSAGES.USER.NOT_AUTHENTICATED);
43
+ }
38
44
  const db = providers.db;
39
45
  if (!db) {
40
46
  throw new Error("Database provider is not registered");
package/dist/index.d.ts CHANGED
@@ -2931,6 +2931,9 @@ export { SlottedListingView, DetailViewShell, StackedViewShell } from "./ui/inde
2931
2931
  export { buildColumns, createColumnBuilder } from "./ui/index";
2932
2932
  export { renderBoolean, renderCurrency, renderCurrencyCompact, renderCount, renderNullable } from "./ui/index";
2933
2933
  export { Ol } from "./ui/index";
2934
+ export { LoginRequiredModal } from "./ui/components/LoginRequiredModal";
2935
+ export type { LoginRequiredModalProps } from "./ui/components/LoginRequiredModal";
2936
+ export { isAuthError } from "./utils/auth-error";
2934
2937
  export { API_ENDPOINTS, API_ROUTES, LOGS_ENDPOINTS, AUTH_ENDPOINTS, ACCOUNT_ENDPOINTS, NOTIFICATIONS_ENDPOINTS, ADMIN_ENDPOINTS, CHAT_ENDPOINTS, AUCTION_ENDPOINTS, BID_ENDPOINTS, CART_ENDPOINTS, CATEGORY_ENDPOINTS, CHECKOUT_ENDPOINTS, PAYMENT_ENDPOINTS, COPILOT_ENDPOINTS, CORPORATE_ENDPOINTS, EVENT_ENDPOINTS, FAQ_ENDPOINTS, HOMEPAGE_ENDPOINTS, LOYALTY_ENDPOINTS, MEDIA_ENDPOINTS, ORDER_ENDPOINTS, PREORDER_ENDPOINTS, PRODUCT_ENDPOINTS, REVIEW_ENDPOINTS, SEARCH_ENDPOINTS, SELLER_ENDPOINTS, BLOG_ENDPOINTS, WISHLIST_ENDPOINTS, DEMO_ENDPOINTS, COLLECTION_CACHE_PATHS, resolveEndpoint, resolveEndpointFn, ROUTES, PUBLIC_ROUTES, PROTECTED_ROUTES, AUTH_ROUTES, WISHLIST_MAX, HISTORY_MAX, CART_MAX_ITEMS, WISHLIST_DOC_ID, HISTORY_DOC_ID, WISHLIST_COLLECTION, HISTORY_COLLECTION, } from "./constants/index";
2935
2938
  export { WishlistFullError } from "./features/wishlist/server";
2936
2939
  export { useHistory, useHistoryMergeOnLogin, getGuestHistory, trackGuestHistory, removeGuestHistoryItem, clearGuestHistory, getGuestHistoryCount, type GuestHistoryItem, type GuestHistoryType, type UserHistoryItem, type HistoryProductType, type HistoryItemSnapshot, type TrackArgs as TrackHistoryArgs, } from "./features/history";
package/dist/index.js CHANGED
@@ -5362,6 +5362,8 @@ export { SlottedListingView, DetailViewShell, StackedViewShell } from "./ui/inde
5362
5362
  export { buildColumns, createColumnBuilder } from "./ui/index";
5363
5363
  export { renderBoolean, renderCurrency, renderCurrencyCompact, renderCount, renderNullable } from "./ui/index";
5364
5364
  export { Ol } from "./ui/index";
5365
+ export { LoginRequiredModal } from "./ui/components/LoginRequiredModal";
5366
+ export { isAuthError } from "./utils/auth-error";
5365
5367
  // -- Missing constants ----------------------------------------------------------
5366
5368
  export { API_ENDPOINTS, API_ROUTES, LOGS_ENDPOINTS, AUTH_ENDPOINTS, ACCOUNT_ENDPOINTS, NOTIFICATIONS_ENDPOINTS, ADMIN_ENDPOINTS, CHAT_ENDPOINTS, AUCTION_ENDPOINTS, BID_ENDPOINTS, CART_ENDPOINTS, CATEGORY_ENDPOINTS, CHECKOUT_ENDPOINTS, PAYMENT_ENDPOINTS, COPILOT_ENDPOINTS, CORPORATE_ENDPOINTS, EVENT_ENDPOINTS, FAQ_ENDPOINTS, HOMEPAGE_ENDPOINTS, LOYALTY_ENDPOINTS, MEDIA_ENDPOINTS, ORDER_ENDPOINTS, PREORDER_ENDPOINTS, PRODUCT_ENDPOINTS, REVIEW_ENDPOINTS, SEARCH_ENDPOINTS, SELLER_ENDPOINTS, BLOG_ENDPOINTS, WISHLIST_ENDPOINTS, DEMO_ENDPOINTS, COLLECTION_CACHE_PATHS, resolveEndpoint, resolveEndpointFn, ROUTES, PUBLIC_ROUTES, PROTECTED_ROUTES, AUTH_ROUTES, WISHLIST_MAX, HISTORY_MAX, CART_MAX_ITEMS, WISHLIST_DOC_ID, HISTORY_DOC_ID, WISHLIST_COLLECTION, HISTORY_COLLECTION, } from "./constants/index";
5367
5369
  // Wishlist server errors (server-only via tree-shake — class only, no firebase-admin at module scope)
package/dist/server.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export { isAuthError } from "./utils/auth-error";
1
2
  export { ADDRESS_FIXTURES } from "./seed/index";
2
3
  export { BID_FIXTURES } from "./seed/index";
3
4
  export { CART_FIXTURES } from "./seed/index";
package/dist/server.js CHANGED
@@ -1,4 +1,6 @@
1
1
  // Server-only public exports
2
+ // isAuthError - Pure util — detects auth errors from caught exceptions (usable in server actions).
3
+ export { isAuthError } from "./utils/auth-error";
2
4
  // [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3
5
  // ADDRESS_FIXTURES - Constant used across modules.
4
6
  export { ADDRESS_FIXTURES } from "./seed/index";