@mohasinac/appkit 4.40.1 → 4.41.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.
Files changed (223) hide show
  1. package/dist/features/categories/repository/categories.repository.js +2 -2
  2. package/dist/features/shell/SectionForm.js +44 -5
  3. package/dist/features/tester/seed-data/_money-flows.js +65 -49
  4. package/dist/features/tester/seed-data/authored/admin__admin-detail-round-trips.js +6 -4
  5. package/dist/features/tester/seed-data/authored/admin__coupons.js +14 -13
  6. package/dist/features/tester/seed-data/authored/buying__bidding.js +154 -140
  7. package/dist/features/tester/seed-data/authored/buying__browsing-search.js +4 -4
  8. package/dist/features/tester/seed-data/authored/buying__buying-checkout.js +59 -56
  9. package/dist/features/tester/seed-data/authored/buying__buying-coupons.js +18 -18
  10. package/dist/features/tester/seed-data/authored/buying__cart.js +105 -79
  11. package/dist/features/tester/seed-data/authored/buying__image-tile-layout.js +6 -8
  12. package/dist/features/tester/seed-data/authored/buying__my-orders.js +13 -13
  13. package/dist/features/tester/seed-data/authored/buying__offers.js +6 -6
  14. package/dist/features/tester/seed-data/authored/buying__order-detail-actions.js +8 -7
  15. package/dist/features/tester/seed-data/authored/buying__product-detail.js +62 -56
  16. package/dist/features/tester/seed-data/authored/buying__return-request.js +6 -6
  17. package/dist/features/tester/seed-data/authored/buying__reviews-pagination.js +4 -4
  18. package/dist/features/tester/seed-data/authored/buying__reviews.js +1 -1
  19. package/dist/features/tester/seed-data/authored/buying__user-dashboard-extras.js +8 -8
  20. package/dist/features/tester/seed-data/authored/content-discovery__category-counts-and-rollup.js +1 -1
  21. package/dist/features/tester/seed-data/authored/content-discovery__coupons.js +29 -16
  22. package/dist/features/tester/seed-data/authored/content-discovery__event-detail-subroutes.js +9 -9
  23. package/dist/features/tester/seed-data/authored/content-discovery__events.js +69 -36
  24. package/dist/features/tester/seed-data/authored/content-discovery__notifications.js +1 -1
  25. package/dist/features/tester/seed-data/authored/cta-layout__checkout-bottom-bar.js +2 -2
  26. package/dist/features/tester/seed-data/authored/design-ux__back-to-top-button.js +2 -2
  27. package/dist/features/tester/seed-data/authored/design-ux__general-design.js +1 -1
  28. package/dist/features/tester/seed-data/authored/design-ux__status-badge-legibility.js +1 -1
  29. package/dist/features/tester/seed-data/authored/design-ux__sticky-cta-bar.js +3 -3
  30. package/dist/features/tester/seed-data/authored/index.js +0 -2
  31. package/dist/features/tester/seed-data/authored/page-wiring__data-loss.js +2 -2
  32. package/dist/features/tester/seed-data/authored/page-wiring__reachability.js +6 -4
  33. package/dist/features/tester/seed-data/authored/public-pages__auth-error-pages.js +2 -2
  34. package/dist/features/tester/seed-data/authored/public-pages__core-listing-pages.js +1 -1
  35. package/dist/features/tester/seed-data/authored/public-pages__stores-sellers-directories.js +8 -10
  36. package/dist/features/tester/seed-data/authored/selling__become-seller.js +2 -2
  37. package/dist/features/tester/seed-data/authored/selling__digital-content-delivery.js +2 -2
  38. package/dist/features/tester/seed-data/authored/selling__listing-a-product.js +2 -2
  39. package/dist/features/tester/seed-data/authored/selling__listing-edit-roundtrip.js +2 -2
  40. package/dist/features/tester/seed-data/authored/selling__listing-lifecycle.js +2 -2
  41. package/dist/features/tester/seed-data/authored/selling__seller-listing-types.js +2 -2
  42. package/dist/features/tester/seed-data/authored/seo__og-images.js +3 -4
  43. package/dist/features/tester/seed-data/authored/seo__page-metadata.js +6 -8
  44. package/dist/features/tester/seed-data/authored/seo__sitemap-and-robots.js +5 -5
  45. package/dist/features/tester/seed-data/index.d.ts +0 -10
  46. package/dist/features/tester/seed-data/index.js +0 -10
  47. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +75 -89
  48. package/dist/features/tester/seed-data/tester-responses-seed-data.js +5 -5
  49. package/dist/index.d.ts +0 -8
  50. package/dist/index.js +0 -21
  51. package/dist/seed/addresses-seed-data.js +0 -34
  52. package/dist/seed/index.d.ts +1 -1
  53. package/dist/seed/index.js +4 -3
  54. package/dist/seed/manifest.js +11 -12
  55. package/dist/seed/notifications-seed-data.js +4 -4
  56. package/dist/seed/stores-seed-data.js +7 -52
  57. package/dist/seed/users-seed-data.js +3 -83
  58. package/package.json +2 -2
  59. package/scripts/seed-cli.mjs +15 -20
  60. package/dist/_internal/server/features/classified/actions.d.ts +0 -12
  61. package/dist/_internal/server/features/classified/actions.js +0 -33
  62. package/dist/_internal/server/features/digital-code/actions.d.ts +0 -12
  63. package/dist/_internal/server/features/digital-code/actions.js +0 -33
  64. package/dist/_internal/server/features/homepage/data.d.ts +0 -18
  65. package/dist/_internal/server/features/homepage/data.js +0 -70
  66. package/dist/_internal/server/features/live/actions.d.ts +0 -6
  67. package/dist/_internal/server/features/live/actions.js +0 -27
  68. package/dist/_internal/server/features/messages/actions.d.ts +0 -6
  69. package/dist/_internal/server/features/messages/actions.js +0 -6
  70. package/dist/_internal/server/features/messages/data.d.ts +0 -10
  71. package/dist/_internal/server/features/messages/data.js +0 -24
  72. package/dist/_internal/server/features/messages/index.d.ts +0 -2
  73. package/dist/_internal/server/features/messages/index.js +0 -2
  74. package/dist/_internal/server/jobs/core/testerSandboxRefresh.d.ts +0 -12
  75. package/dist/_internal/server/jobs/core/testerSandboxRefresh.js +0 -112
  76. package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.d.ts +0 -2
  77. package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.js +0 -2
  78. package/dist/_internal/shared/features/homepage/section-gate.d.ts +0 -14
  79. package/dist/_internal/shared/features/homepage/section-gate.js +0 -51
  80. package/dist/_internal/shared/features/lottery/config-form.d.ts +0 -58
  81. package/dist/_internal/shared/features/lottery/config-form.js +0 -71
  82. package/dist/client/api/useFeatureFlags.d.ts +0 -22
  83. package/dist/client/api/useFeatureFlags.js +0 -27
  84. package/dist/features/account/address-validation.d.ts +0 -20
  85. package/dist/features/account/address-validation.js +0 -35
  86. package/dist/features/account/components/ChatList.d.ts +0 -14
  87. package/dist/features/account/components/ChatList.js +0 -9
  88. package/dist/features/account/components/ChatWindow.d.ts +0 -17
  89. package/dist/features/account/components/ChatWindow.js +0 -6
  90. package/dist/features/account/components/MessagesView.d.ts +0 -16
  91. package/dist/features/account/components/MessagesView.js +0 -5
  92. package/dist/features/account/components/UserOffersView.d.ts +0 -10
  93. package/dist/features/account/components/UserOffersView.js +0 -5
  94. package/dist/features/account/constants/addresses.d.ts +0 -13
  95. package/dist/features/account/constants/addresses.js +0 -43
  96. package/dist/features/account/hooks/useAddressForm.d.ts +0 -24
  97. package/dist/features/account/hooks/useAddressForm.js +0 -58
  98. package/dist/features/admin/actions/chat-actions.d.ts +0 -29
  99. package/dist/features/admin/actions/chat-actions.js +0 -101
  100. package/dist/features/admin/components/AdminFeatureFlagsView.d.ts +0 -9
  101. package/dist/features/admin/components/AdminFeatureFlagsView.js +0 -109
  102. package/dist/features/admin/components/AdminSiteView.d.ts +0 -10
  103. package/dist/features/admin/components/AdminSiteView.js +0 -52
  104. package/dist/features/admin/hooks/useChat.d.ts +0 -24
  105. package/dist/features/admin/hooks/useChat.js +0 -100
  106. package/dist/features/admin/permission-map.d.ts +0 -3
  107. package/dist/features/admin/permission-map.js +0 -26
  108. package/dist/features/admin/repository/chat.repository.d.ts +0 -50
  109. package/dist/features/admin/repository/chat.repository.js +0 -223
  110. package/dist/features/auth/actions/password-change-otp-actions.d.ts +0 -18
  111. package/dist/features/auth/actions/password-change-otp-actions.js +0 -88
  112. package/dist/features/auth/actions/realtime-token-actions.d.ts +0 -11
  113. package/dist/features/auth/actions/realtime-token-actions.js +0 -38
  114. package/dist/features/auth/password-change-otp.d.ts +0 -34
  115. package/dist/features/auth/password-change-otp.js +0 -56
  116. package/dist/features/classified/components/ClassifiedContactSellerPanel.d.ts +0 -12
  117. package/dist/features/classified/components/ClassifiedContactSellerPanel.js +0 -49
  118. package/dist/features/events/api/route.d.ts +0 -12
  119. package/dist/features/events/api/route.js +0 -90
  120. package/dist/features/faq/api/route.d.ts +0 -11
  121. package/dist/features/faq/api/route.js +0 -52
  122. package/dist/features/faq/hooks/useFAQs.d.ts +0 -22
  123. package/dist/features/faq/hooks/useFAQs.js +0 -41
  124. package/dist/features/media/upload/video-poster.test.d.ts +0 -1
  125. package/dist/features/media/upload/video-poster.test.js +0 -42
  126. package/dist/features/messages/actions/index.d.ts +0 -2
  127. package/dist/features/messages/actions/index.js +0 -2
  128. package/dist/features/messages/actions/messages-actions.d.ts +0 -15
  129. package/dist/features/messages/actions/messages-actions.js +0 -33
  130. package/dist/features/messages/actions/ping-rtdb.d.ts +0 -2
  131. package/dist/features/messages/actions/ping-rtdb.js +0 -26
  132. package/dist/features/messages/hooks/useConversation.d.ts +0 -22
  133. package/dist/features/messages/hooks/useConversation.js +0 -155
  134. package/dist/features/messages/hooks/useConversations.d.ts +0 -15
  135. package/dist/features/messages/hooks/useConversations.js +0 -104
  136. package/dist/features/messages/index.d.ts +0 -6
  137. package/dist/features/messages/index.js +0 -4
  138. package/dist/features/messages/realtime.d.ts +0 -32
  139. package/dist/features/messages/realtime.js +0 -39
  140. package/dist/features/messages/repository/conversations.repository.d.ts +0 -71
  141. package/dist/features/messages/repository/conversations.repository.js +0 -284
  142. package/dist/features/messages/schemas/firestore.d.ts +0 -34
  143. package/dist/features/messages/schemas/firestore.js +0 -16
  144. package/dist/features/messages/schemas/index.d.ts +0 -177
  145. package/dist/features/messages/schemas/index.js +0 -35
  146. package/dist/features/messages/server.d.ts +0 -6
  147. package/dist/features/messages/server.js +0 -6
  148. package/dist/features/products/components/MakeOfferForm.d.ts +0 -20
  149. package/dist/features/products/components/MakeOfferForm.js +0 -9
  150. package/dist/features/reviews/api/route.d.ts +0 -21
  151. package/dist/features/reviews/api/route.js +0 -174
  152. package/dist/features/seller/api/offers/route.d.ts +0 -17
  153. package/dist/features/seller/api/offers/route.js +0 -63
  154. package/dist/features/seller/components/SellerAuctionsView.d.ts +0 -9
  155. package/dist/features/seller/components/SellerAuctionsView.js +0 -113
  156. package/dist/features/seller/components/SellerOffersPanel.d.ts +0 -21
  157. package/dist/features/seller/components/SellerOffersPanel.js +0 -160
  158. package/dist/features/seller/components/SellerPreOrdersView.d.ts +0 -6
  159. package/dist/features/seller/components/SellerPreOrdersView.js +0 -148
  160. package/dist/features/seller/components/SellerPrizeDrawsView.d.ts +0 -6
  161. package/dist/features/seller/components/SellerPrizeDrawsView.js +0 -152
  162. package/dist/features/seller/permission-map.d.ts +0 -5
  163. package/dist/features/seller/permission-map.js +0 -17
  164. package/dist/features/shell/StepForm.d.ts +0 -80
  165. package/dist/features/shell/StepForm.js +0 -136
  166. package/dist/features/stores/api/route.d.ts +0 -12
  167. package/dist/features/stores/api/route.js +0 -110
  168. package/dist/features/tester/seed-data/authored/account-auth__testing-program--admin.d.ts +0 -2
  169. package/dist/features/tester/seed-data/authored/account-auth__testing-program--admin.js +0 -33
  170. package/dist/features/tester/seed-data/authored/account-auth__testing-program.d.ts +0 -2
  171. package/dist/features/tester/seed-data/authored/account-auth__testing-program.js +0 -138
  172. package/dist/features/tester/seed-data/bids-tester-seed-data.d.ts +0 -2
  173. package/dist/features/tester/seed-data/bids-tester-seed-data.js +0 -37
  174. package/dist/features/tester/seed-data/blog-tester-seed-data.d.ts +0 -2
  175. package/dist/features/tester/seed-data/blog-tester-seed-data.js +0 -40
  176. package/dist/features/tester/seed-data/carts-tester-seed-data.d.ts +0 -3
  177. package/dist/features/tester/seed-data/carts-tester-seed-data.js +0 -70
  178. package/dist/features/tester/seed-data/categories-tester-seed-data.d.ts +0 -2
  179. package/dist/features/tester/seed-data/categories-tester-seed-data.js +0 -218
  180. package/dist/features/tester/seed-data/coupons-tester-seed-data.d.ts +0 -2
  181. package/dist/features/tester/seed-data/coupons-tester-seed-data.js +0 -76
  182. package/dist/features/tester/seed-data/events-tester-seed-data.d.ts +0 -2
  183. package/dist/features/tester/seed-data/events-tester-seed-data.js +0 -193
  184. package/dist/features/tester/seed-data/offers-tester-seed-data.d.ts +0 -2
  185. package/dist/features/tester/seed-data/offers-tester-seed-data.js +0 -191
  186. package/dist/features/tester/seed-data/orders-tester-seed-data.d.ts +0 -2
  187. package/dist/features/tester/seed-data/orders-tester-seed-data.js +0 -329
  188. package/dist/features/tester/seed-data/products-tester-seed-data.d.ts +0 -2
  189. package/dist/features/tester/seed-data/products-tester-seed-data.js +0 -815
  190. package/dist/features/tester/seed-data/stores-tester-seed-data.d.ts +0 -2
  191. package/dist/features/tester/seed-data/stores-tester-seed-data.js +0 -79
  192. package/dist/features/wishlist/components/WishlistToggleButton.d.ts +0 -12
  193. package/dist/features/wishlist/components/WishlistToggleButton.js +0 -36
  194. package/dist/monitoring/analytics.d.ts +0 -80
  195. package/dist/monitoring/analytics.js +0 -176
  196. package/dist/next/middleware/pii-redactor.d.ts +0 -32
  197. package/dist/next/middleware/pii-redactor.js +0 -84
  198. package/dist/providers/db-firebase/realtime.d.ts +0 -42
  199. package/dist/providers/db-firebase/realtime.js +0 -138
  200. package/dist/security/rbac/Can.d.ts +0 -31
  201. package/dist/security/rbac/Can.js +0 -22
  202. package/dist/security/rbac/default-roles.d.ts +0 -2
  203. package/dist/security/rbac/default-roles.js +0 -83
  204. package/dist/security/rbac/hook.d.ts +0 -20
  205. package/dist/security/rbac/hook.js +0 -30
  206. package/dist/security/rbac/index.d.ts +0 -8
  207. package/dist/security/rbac/index.js +0 -6
  208. package/dist/security/rbac/middleware.d.ts +0 -51
  209. package/dist/security/rbac/middleware.js +0 -51
  210. package/dist/security/rbac/resolver.d.ts +0 -5
  211. package/dist/security/rbac/resolver.js +0 -38
  212. package/dist/security/rbac/server.d.ts +0 -24
  213. package/dist/security/rbac/server.js +0 -42
  214. package/dist/security/rbac/types.d.ts +0 -22
  215. package/dist/security/rbac/types.js +0 -2
  216. package/dist/seed/conversations-seed-data.d.ts +0 -2
  217. package/dist/seed/conversations-seed-data.js +0 -292
  218. package/dist/utils/filter.helper.d.ts +0 -18
  219. package/dist/utils/filter.helper.js +0 -21
  220. package/dist/utils/pagination.helper.d.ts +0 -23
  221. package/dist/utils/pagination.helper.js +0 -24
  222. package/dist/utils/search-tokens.d.ts +0 -2
  223. package/dist/utils/search-tokens.js +0 -21
@@ -1,160 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useCallback, useEffect, useState, useTransition } from "react";
4
- import { Alert, Badge, Button, Div, Heading, Input, LoginRequiredModal, Row, Spinner, Stack, Text } from "../../../ui";
5
- import { isAuthError } from "../../../utils/auth-error";
6
- import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
7
- import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
8
- import { normalizeError } from "../../../errors/normalize";
9
- function formatRupees(amount) {
10
- if (amount === undefined || amount === null)
11
- return "—";
12
- return `₹${amount.toLocaleString("en-IN")}`;
13
- }
14
- function relativeTime(date) {
15
- if (!date)
16
- return "";
17
- const d = date instanceof Date ? date : new Date(date);
18
- const diff = Date.now() - d.getTime();
19
- const mins = Math.floor(diff / 60000);
20
- if (mins < 60)
21
- return `${mins}m ago`;
22
- const hrs = Math.floor(diff / 3600000);
23
- if (hrs < 24)
24
- return `${hrs}h ago`;
25
- return `${Math.floor(diff / 86400000)}d ago`;
26
- }
27
- function expiresIn(expiresAt) {
28
- if (!expiresAt)
29
- return "";
30
- const exp = expiresAt instanceof Date ? expiresAt : new Date(expiresAt);
31
- const diff = exp.getTime() - Date.now();
32
- if (diff <= 0)
33
- return "Expired";
34
- const hrs = Math.floor(diff / 3600000);
35
- if (hrs < 1)
36
- return "< 1h left";
37
- if (hrs < 24)
38
- return `${hrs}h left`;
39
- return `${Math.floor(diff / 86400000)}d left`;
40
- }
41
- function statusVariant(status) {
42
- switch (status) {
43
- case "pending": return "warning";
44
- case "accepted": return "success";
45
- case "declined": return "danger";
46
- case "countered": return "info";
47
- case "expired": return "default";
48
- case "withdrawn": return "default";
49
- case "paid": return "success";
50
- default: return "default";
51
- }
52
- }
53
- const PLACEHOLDER_SELLER_NOTE = "Optional note to buyer";
54
- function OfferCard({ offer, onRespond, onUpdate, onNeedsLogin }) {
55
- const [uiState, setUiState] = useState("idle");
56
- const [counterInput, setCounterInput] = useState("");
57
- const [sellerNote, setSellerNote] = useState("");
58
- const [error, setError] = useState("");
59
- const [isPending, startTransition] = useTransition();
60
- const toAccepting = useCallback(() => setUiState("accepting"), []);
61
- const toCountering = useCallback(() => setUiState("countering"), []);
62
- const toDeclining = useCallback(() => setUiState("declining"), []);
63
- const toIdle = useCallback(() => setUiState("idle"), []);
64
- const isPendingOffer = offer.status === "pending";
65
- function submit(action) {
66
- setError("");
67
- startTransition(async () => {
68
- try {
69
- await onRespond(action);
70
- onUpdate(offer.id, {
71
- status: action.action === "accept"
72
- ? "accepted"
73
- : action.action === "decline"
74
- ? "declined"
75
- : "countered",
76
- });
77
- setUiState("idle");
78
- }
79
- catch (err) {
80
- void normalizeError(err);
81
- if (isAuthError(err)) {
82
- onNeedsLogin();
83
- }
84
- else {
85
- setError(err instanceof Error ? err.message : "Something went wrong.");
86
- }
87
- }
88
- });
89
- }
90
- function handleAccept() {
91
- submit({ action: "accept", offerId: offer.id, sellerNote: sellerNote || undefined });
92
- }
93
- function handleDecline() {
94
- submit({ action: "decline", offerId: offer.id, sellerNote: sellerNote || undefined });
95
- }
96
- function handleCounter() {
97
- const amount = parseInt(counterInput, 10);
98
- if (!amount || amount <= 0) {
99
- setError("Enter a valid counter amount.");
100
- return;
101
- }
102
- if (amount >= offer.listedPrice) {
103
- setError("Counter must be below the listed price.");
104
- return;
105
- }
106
- if (amount === offer.offerAmount) {
107
- setError("Counter must differ from the buyer's offer.");
108
- return;
109
- }
110
- submit({ action: "counter", offerId: offer.id, counterAmount: amount, sellerNote: sellerNote || undefined });
111
- }
112
- return (_jsxs(Stack, { surface: "card", padding: "sm", gap: "3", children: [_jsxs(Row, { align: "start", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: "truncate", color: "primary", size: "sm", weight: "semibold", children: offer.productTitle ?? "Unknown Product" }), _jsxs(Text, { className: "mt-0.5", color: "muted", size: "xs", children: [relativeTime(offer.createdAt), " \u00B7 ", isPendingOffer ? expiresIn(offer.expiresAt) : ""] })] }), _jsx(Badge, { variant: statusVariant(offer.status), size: "xs", className: "shrink-0 capitalize", children: offer.status })] }), _jsxs(Row, { wrap: true, gap: "md", children: [_jsxs(Div, { children: [_jsx(Text, { className: "tracking-wide", color: "faint", size: "xs", transform: "uppercase", children: "Listed" }), _jsx(Text, { size: "sm", weight: "medium", color: "muted", children: formatRupees(offer.listedPrice) })] }), _jsxs(Div, { children: [_jsx(Text, { className: "tracking-wide", color: "faint", size: "xs", transform: "uppercase", children: "Offered" }), _jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: formatRupees(offer.offerAmount) })] }), offer.counterAmount != null && (_jsxs(Div, { children: [_jsx(Text, { className: "tracking-wide", color: "faint", size: "xs", transform: "uppercase", children: "Your Counter" }), _jsx(Text, { className: "text-info", size: "sm", weight: "medium", children: formatRupees(offer.counterAmount) })] }))] }), offer.buyerNote && (_jsxs(Text, { className: "italic", color: "muted", size: "xs", children: ["\"", offer.buyerNote, "\""] })), isPendingOffer && uiState === "idle" && (_jsxs(Row, { wrap: true, gap: "sm", children: [_jsx(Button, { size: "sm", variant: "primary", onClick: toAccepting, disabled: isPending, children: "Accept" }), _jsx(Button, { size: "sm", variant: "ghost", onClick: toCountering, disabled: isPending, border: "strong", children: "Counter" }), _jsx(Button, { size: "sm", variant: "ghost", onClick: toDeclining, disabled: isPending, className: "text-error border border-error/20", children: "Decline" })] })), uiState === "accepting" && (_jsxs(Stack, { gap: "sm", children: [_jsx(Input, { placeholder: PLACEHOLDER_SELLER_NOTE, value: sellerNote, onChange: (e) => setSellerNote(e.target.value), disabled: isPending }), _jsxs(Row, { gap: "sm", children: [_jsx(Button, { size: "sm", variant: "primary", onClick: handleAccept, disabled: isPending, children: isPending ? "Accepting…" : "Confirm Accept" }), _jsx(Button, { size: "sm", variant: "ghost", onClick: toIdle, disabled: isPending, children: ACTIONS.STORE["cancel-form"].label })] })] })), uiState === "declining" && (_jsxs(Stack, { gap: "sm", children: [_jsx(Input, { placeholder: PLACEHOLDER_SELLER_NOTE, value: sellerNote, onChange: (e) => setSellerNote(e.target.value), disabled: isPending }), _jsxs(Row, { gap: "sm", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: handleDecline, disabled: isPending, className: "text-error border border-error/20", children: isPending ? "Declining…" : "Confirm Decline" }), _jsx(Button, { size: "sm", variant: "ghost", onClick: toIdle, disabled: isPending, children: ACTIONS.STORE["cancel-form"].label })] })] })), uiState === "countering" && (_jsxs(Stack, { gap: "sm", children: [_jsxs(Text, { size: "xs", color: "muted", children: ["Suggest a price between the buyer's offer (", formatRupees(offer.offerAmount), ") and your listed price (", formatRupees(offer.listedPrice), ")."] }), _jsx(Input, { type: "number", placeholder: "Your counter amount (\u20B9)", value: counterInput, onChange: (e) => setCounterInput(e.target.value), disabled: isPending }), _jsx(Input, { placeholder: PLACEHOLDER_SELLER_NOTE, value: sellerNote, onChange: (e) => setSellerNote(e.target.value), disabled: isPending }), _jsxs(Row, { gap: "sm", children: [_jsx(Button, { size: "sm", variant: "secondary", onClick: handleCounter, disabled: isPending, children: isPending ? "Sending…" : "Send Counter" }), _jsx(Button, { size: "sm", variant: "ghost", onClick: toIdle, disabled: isPending, children: ACTIONS.STORE["cancel-form"].label })] })] })), error && _jsx(Alert, { variant: "error", children: _jsx(Text, { size: "xs", children: error }) })] }));
113
- }
114
- export function SellerOffersPanel({ fetchEndpoint = SELLER_ENDPOINTS.OFFERS, onRespond, className = "", }) {
115
- const [offers, setOffers] = useState([]);
116
- const [loading, setLoading] = useState(true);
117
- const [fetchError, setFetchError] = useState("");
118
- const [showLoginModal, setShowLoginModal] = useState(false);
119
- const [statusFilter, setStatusFilter] = useState("all");
120
- const loadOffers = useCallback(async () => {
121
- setLoading(true);
122
- setFetchError("");
123
- try {
124
- const url = statusFilter === "all"
125
- ? fetchEndpoint
126
- : `${fetchEndpoint}?status=${statusFilter}`;
127
- const res = await fetch(url);
128
- if (!res.ok) {
129
- if (res.status === 401 || res.status === 403) {
130
- setShowLoginModal(true);
131
- return;
132
- }
133
- throw new Error(`Error ${res.status}`);
134
- }
135
- const json = (await res.json());
136
- setOffers(json.items ?? json.offers ?? []);
137
- }
138
- catch (err) {
139
- void normalizeError(err);
140
- setFetchError(err instanceof Error ? err.message : "Failed to load offers.");
141
- }
142
- finally {
143
- setLoading(false);
144
- }
145
- }, [fetchEndpoint, statusFilter]);
146
- useEffect(() => { void loadOffers(); }, [loadOffers]);
147
- function handleUpdate(id, patch) {
148
- setOffers((prev) => prev.map((o) => (o.id === id ? { ...o, ...patch } : o)));
149
- }
150
- const STATUS_FILTERS = [
151
- { value: "all", label: "All" },
152
- { value: "pending", label: "Pending" },
153
- { value: "countered", label: "Countered" },
154
- { value: "accepted", label: "Accepted" },
155
- { value: "declined", label: "Declined" },
156
- { value: "expired", label: "Expired" },
157
- ];
158
- const pending = offers.filter((o) => o.status === "pending").length;
159
- return (_jsxs(Stack, { className: `${className}`, gap: "md", 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(Row, { align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Div, { children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", color: "primary", children: "Offers Received" }), pending > 0 && (_jsxs(Text, { className: "text-warning mt-0.5", size: "xs", children: [pending, " pending offer", pending > 1 ? "s" : "", " awaiting your response"] }))] }), _jsx(Button, { size: "sm", variant: "ghost", onClick: loadOffers, disabled: loading, border: "strong", textSize: "xs", children: loading ? "Refreshing…" : ACTIONS.STORE["refresh-offers"].label })] }), _jsx(Row, { wrap: true, gap: "xs", children: STATUS_FILTERS.map((f) => (_jsx(Button, { size: "sm", variant: statusFilter === f.value ? "primary" : "ghost", onClick: () => setStatusFilter(f.value), className: "text-[length:var(--appkit-text-xs)] px-[var(--appkit-space-2)] py-[var(--appkit-space-1)]", children: f.label }, f.value))) }), fetchError && _jsx(Alert, { variant: "error", children: _jsx(Text, { size: "sm", children: fetchError }) }), loading && (_jsx(Row, { justify: "center", padding: "y-3xl", children: _jsx(Spinner, { size: "lg" }) })), !loading && offers.length === 0 && (_jsx(Div, { className: "text-center", padding: "y-3xl", children: _jsx(Text, { size: "sm", color: "faint", children: "No offers found" }) })), !loading && offers.length > 0 && (_jsx(Stack, { gap: "3", children: offers.map((offer) => (_jsx(OfferCard, { offer: offer, onRespond: onRespond, onUpdate: handleUpdate, onNeedsLogin: () => setShowLoginModal(true) }, offer.id))) }))] }));
160
- }
@@ -1,6 +0,0 @@
1
- import React from "react";
2
- import type { ListingLayoutProps } from "../../../ui";
3
- export interface SellerPreOrdersViewProps extends ListingLayoutProps {
4
- onDelete?: (id: string) => Promise<void>;
5
- }
6
- export declare function SellerPreOrdersView({ children, onDelete, ...props }: SellerPreOrdersViewProps): React.JSX.Element;
@@ -1,148 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { Row, SIEVE_OP, Stack, sieveFilter } from "@mohasinac/appkit/client";
4
- import { sortBy } from "@mohasinac/appkit/client";
5
- import React, { useState, useCallback } from "react";
6
- import { useEntityDelete } from "../../../react/hooks/useEntityDelete";
7
- import { Badge, ConfirmDeleteModal, Div, FilterChipGroup, ListingLayout, RowActionMenu, Span, Text } from "../../../ui";
8
- import { MediaImage } from "../../media/MediaImage";
9
- import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
10
- import { SELLER_PRE_ORDER_STATUS_TABS } from "../../admin/constants/filter-tabs";
11
- import { ROUTES } from "../../../constants";
12
- import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
13
- import { toRecordArray, toRelativeDate, toCurrency, toStringValue, } from "../../admin/hooks/useAdminListingData";
14
- import { DataListingView } from "../../admin/components/DataListingView";
15
- import { useActionDispatch } from "../../../react/hooks/use-action-dispatch";
16
- import { useAvailabilityScope } from "../../products/hooks/useAvailabilityScope";
17
- const PRE_ORDER_TYPES = ["pre-order"];
18
- const PRE_ORDER_COLUMNS = [
19
- {
20
- key: "thumbnail",
21
- header: "",
22
- className: "w-12",
23
- render: (row) => row.imageUrl ? (_jsx(Div, { className: "relative w-10 h-10 flex-shrink-0 border border-[var(--appkit-color-border)]", rounded: "lg", overflow: "hidden", children: _jsx(MediaImage, { src: row.imageUrl, alt: "", size: "thumbnail" }) })) : (_jsx(Row, { className: "w-10 h-10 bg-[var(--appkit-color-surface-raised)] border border-[var(--appkit-color-border)]", align: "center", justify: "center", rounded: "lg", children: _jsx(Span, { size: "xs", color: "faint", children: "\u2013" }) })),
24
- },
25
- {
26
- key: "primary",
27
- header: "Pre-order",
28
- render: (row) => (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { className: "text-[var(--appkit-color-text)] line-clamp-1", weight: "medium", children: row.primary }), _jsx(Span, { size: "xs", color: "muted", children: row.secondary })] })),
29
- },
30
- {
31
- key: "price",
32
- header: "Price",
33
- className: "w-28 text-right",
34
- render: (row) => (_jsx(Span, { size: "sm", weight: "medium", className: "text-[var(--appkit-color-text)]", children: row.price })),
35
- },
36
- {
37
- key: "status",
38
- header: "Status",
39
- className: "w-28",
40
- render: (row) => {
41
- // Real ProductStatus is draft|published|in_review|archived — "active"
42
- // fixed to "published"; "cancelled" is not a stored status value.
43
- const variant = row.status === "published"
44
- ? "success"
45
- : row.status === "draft"
46
- ? "default"
47
- : "warning";
48
- return _jsx(Badge, { variant: variant, children: row.status });
49
- },
50
- },
51
- {
52
- key: "deliveryDate",
53
- header: "Est. Delivery",
54
- className: "w-36",
55
- render: (row) => (_jsx(Span, { size: "xs", color: "muted", children: row.deliveryDate })),
56
- },
57
- {
58
- key: "updatedAt",
59
- header: "Updated",
60
- className: "w-28",
61
- render: (row) => (_jsx(Span, { size: "xs", color: "muted", children: row.updatedAt })),
62
- },
63
- ];
64
- export function SellerPreOrdersView({ children, onDelete, ...props }) {
65
- const dispatch = useActionDispatch();
66
- const [deleteTargetId, setDeleteTargetId] = useState(null);
67
- const { deletingId, handleDelete: performDelete } = useEntityDelete({
68
- endpoint: SELLER_ENDPOINTS.PRODUCT_BY_ID,
69
- deleteFn: onDelete,
70
- successMessage: "Pre-order deleted.",
71
- fetchOptions: { credentials: "include" },
72
- });
73
- const handleDelete = useCallback(async (id) => {
74
- await performDelete(id);
75
- setDeleteTargetId(null);
76
- }, [performDelete]);
77
- if (React.Children.count(children) > 0) {
78
- return (_jsx(ListingLayout, { portal: "seller", ...props, children: children }));
79
- }
80
- const scope = useAvailabilityScope(PRE_ORDER_TYPES);
81
- const config = {
82
- portal: "seller",
83
- title: "Pre-Orders",
84
- searchPlaceholder: "Search pre-orders by name…",
85
- emptyLabel: "No pre-orders listed yet",
86
- filterKeys: ["status"],
87
- defaultSort: sortBy("createdAt", "DESC"),
88
- queryKey: ["seller", "pre-orders", "listing"],
89
- endpoint: SELLER_ENDPOINTS.PRODUCTS,
90
- sortOptions: [
91
- { value: sortBy("createdAt", "DESC"), label: "Newest" },
92
- { value: sortBy("createdAt", "ASC"), label: "Oldest" },
93
- { value: "title", label: "Title A–Z" },
94
- { value: "preOrderDeliveryDate", label: "Delivery Soon" },
95
- ],
96
- columns: PRE_ORDER_COLUMNS,
97
- mapRows: (response) => toRecordArray(response.products).map((item, index) => {
98
- const priceRaw = typeof item.price === "number" ? item.price : 0;
99
- return {
100
- id: toStringValue(item.id, `preorder-${index}`),
101
- primary: toStringValue(item.title ?? item.name, "Untitled pre-order"),
102
- secondary: toStringValue(item.condition, ""),
103
- status: toStringValue(item.status, "draft"),
104
- price: priceRaw ? toCurrency(priceRaw) : "—",
105
- deliveryDate: item.preOrderDeliveryDate
106
- ? toRelativeDate(item.preOrderDeliveryDate)
107
- : "TBA",
108
- updatedAt: toRelativeDate(item.updatedAt ?? item.createdAt),
109
- imageUrl: toStringValue(item.mainImage ?? item.images?.[0], undefined),
110
- image: toStringValue(item.mainImage ?? item.images?.[0], undefined),
111
- };
112
- }),
113
- getTotal: (response, mappedRows) => typeof response.meta?.total === "number" ? response.meta.total : mappedRows.length,
114
- // No "Show closed" toggle here (unlike Auctions/Prize Draws): the public
115
- // PreOrdersIndexListing equivalent filters on stockQuantity>0, a range
116
- // filter, which cannot be combined with this view's title/
117
- // preOrderDeliveryDate/createdAt sort options without violating
118
- // Firestore's orderBy-must-match-the-range-field rule (confirmed by
119
- // appkit/scripts/audit-listing-indices.mjs QUERY_UNSATISFIABLE). Fixing
120
- // this properly would mean constraining sort choices per toggle state,
121
- // out of scope for this pass — left as a real gap, not silently broken.
122
- buildFilters: (state) => {
123
- const status = state.status && state.status !== "All" ? sieveFilter("status", SIEVE_OP.EQ, state.status) : null;
124
- return ["listingType==pre-order", status].filter(Boolean).join(",");
125
- },
126
- buildExtraParams: () => scope.extraParams,
127
- renderAboveContent: scope.renderAboveContent,
128
- rowHrefTemplate: String(ROUTES.STORE.PRE_ORDERS_EDIT("{id}")),
129
- renderRowActions: (row) => (_jsx(RowActionMenu, { actions: [
130
- {
131
- label: ACTIONS.STORE["edit-listing"].label,
132
- onClick: () => void dispatch({ type: "NAVIGATE", href: String(ROUTES.STORE.PRE_ORDERS_EDIT(row.id)) }),
133
- },
134
- ...(onDelete
135
- ? [
136
- {
137
- label: ACTIONS.STORE["delete-listing"].label,
138
- destructive: true,
139
- onClick: () => setDeleteTargetId(row.id),
140
- disabled: deletingId === row.id,
141
- },
142
- ]
143
- : []),
144
- ] })),
145
- renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsx(FilterChipGroup, { label: "Status", tabs: SELLER_PRE_ORDER_STATUS_TABS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) })),
146
- };
147
- return (_jsxs(_Fragment, { children: [_jsx(DataListingView, { config: config }), deleteTargetId && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Pre-Order", message: "Are you sure you want to delete this pre-order listing? This cannot be undone.", onConfirm: () => handleDelete(deleteTargetId), onClose: () => setDeleteTargetId(null), isDeleting: deletingId === deleteTargetId }))] }));
148
- }
@@ -1,6 +0,0 @@
1
- import React from "react";
2
- import type { ListingLayoutProps } from "../../../ui";
3
- export interface SellerPrizeDrawsViewProps extends ListingLayoutProps {
4
- onDelete?: (id: string) => Promise<void>;
5
- }
6
- export declare function SellerPrizeDrawsView({ children, onDelete, ...props }: SellerPrizeDrawsViewProps): React.JSX.Element;
@@ -1,152 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { Row, SIEVE_OP, Stack, sieveFilter } from "@mohasinac/appkit/client";
4
- import { sortBy } from "@mohasinac/appkit/client";
5
- import React, { useState, useCallback } from "react";
6
- import { useEntityDelete } from "../../../react/hooks/useEntityDelete";
7
- import { Badge, ConfirmDeleteModal, Div, FilterChipGroup, ListingLayout, RowActionMenu, Span, Text } from "../../../ui";
8
- import { MediaImage } from "../../media/MediaImage";
9
- import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
10
- import { SELLER_PRIZE_DRAW_STATUS_TABS } from "../../admin/constants/filter-tabs";
11
- import { ROUTES } from "../../../constants";
12
- import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
13
- import { toRecordArray, toRelativeDate, toCurrency, toStringValue, } from "../../admin/hooks/useAdminListingData";
14
- import { DataListingView } from "../../admin/components/DataListingView";
15
- import { useAvailabilityScope } from "../../products/hooks/useAvailabilityScope";
16
- const PRIZE_DRAW_TYPES = ["prize-draw"];
17
- import { useActionDispatch } from "../../../react/hooks/use-action-dispatch";
18
- // Real ProductStatus is draft|published|in_review|archived — "active"
19
- // fixed to "published"; "ended"/"cancelled" removed since status never
20
- // holds those values (ended is derived from prizeRevealWindowEnd, shown
21
- // via the "Show closed" toolbar toggle below).
22
- const STATUS_VARIANT = {
23
- published: "success",
24
- draft: "default",
25
- };
26
- const PRIZE_DRAW_COLUMNS = [
27
- {
28
- key: "thumbnail",
29
- header: "",
30
- className: "w-12",
31
- render: (row) => row.imageUrl ? (_jsx(Div, { className: "relative w-10 h-10 flex-shrink-0 border border-[var(--appkit-color-border)]", rounded: "lg", overflow: "hidden", children: _jsx(MediaImage, { src: row.imageUrl, alt: "", size: "thumbnail" }) })) : (_jsx(Row, { className: "w-10 h-10 bg-[var(--appkit-color-surface-raised)] border border-[var(--appkit-color-border)]", align: "center", justify: "center", rounded: "lg", children: _jsx(Span, { size: "xs", color: "faint", children: "\u2013" }) })),
32
- },
33
- {
34
- key: "primary",
35
- header: "Prize Draw",
36
- render: (row) => (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { className: "text-[var(--appkit-color-text)] line-clamp-1", weight: "medium", children: row.primary }), _jsx(Span, { size: "xs", color: "muted", children: row.secondary })] })),
37
- },
38
- {
39
- key: "entryFee",
40
- header: "Entry Fee",
41
- className: "w-28 text-right",
42
- render: (row) => (_jsx(Span, { size: "sm", weight: "medium", className: "text-[var(--appkit-color-text)]", children: row.entryFee })),
43
- },
44
- {
45
- key: "status",
46
- header: "Status",
47
- className: "w-28",
48
- render: (row) => (_jsx(Badge, { variant: STATUS_VARIANT[row.status] ?? "default", children: row.status })),
49
- },
50
- {
51
- key: "drawDate",
52
- header: "Draw Date",
53
- className: "w-32",
54
- render: (row) => (_jsx(Span, { size: "xs", color: "muted", children: row.drawDate })),
55
- },
56
- {
57
- key: "updatedAt",
58
- header: "Updated",
59
- className: "w-28",
60
- render: (row) => (_jsx(Span, { size: "xs", color: "muted", children: row.updatedAt })),
61
- },
62
- ];
63
- export function SellerPrizeDrawsView({ children, onDelete, ...props }) {
64
- const dispatch = useActionDispatch();
65
- // Independent of DataListingView's own internal useUrlTable() — see the
66
- // same pattern in SellerAuctionsView.tsx.
67
- const scope = useAvailabilityScope(PRIZE_DRAW_TYPES);
68
- const [deleteTargetId, setDeleteTargetId] = useState(null);
69
- const { deletingId, handleDelete: performDelete } = useEntityDelete({
70
- endpoint: SELLER_ENDPOINTS.PRODUCT_BY_ID,
71
- deleteFn: onDelete,
72
- successMessage: "Prize draw deleted.",
73
- fetchOptions: { credentials: "include" },
74
- });
75
- const handleDelete = useCallback(async (id) => {
76
- await performDelete(id);
77
- setDeleteTargetId(null);
78
- }, [performDelete]);
79
- if (React.Children.count(children) > 0) {
80
- return (_jsx(ListingLayout, { portal: "seller", ...props, children: children }));
81
- }
82
- const config = {
83
- portal: "seller",
84
- title: "Prize Draws",
85
- searchPlaceholder: "Search prize draws by name…",
86
- emptyLabel: "No prize draws listed yet",
87
- filterKeys: ["status"],
88
- defaultSort: sortBy("createdAt", "DESC"),
89
- queryKey: ["seller", "prize-draws", "listing"],
90
- endpoint: SELLER_ENDPOINTS.PRODUCTS,
91
- sortOptions: [
92
- { value: sortBy("createdAt", "DESC"), label: "Newest" },
93
- { value: sortBy("createdAt", "ASC"), label: "Oldest" },
94
- { value: "title", label: "Title A–Z" },
95
- { value: "prizeRevealWindowEnd", label: "Draw Date Soon" },
96
- ],
97
- columns: PRIZE_DRAW_COLUMNS,
98
- mapRows: (response) => toRecordArray(response.products).map((item, index) => {
99
- const priceRaw = typeof item.price === "number" ? item.price : 0;
100
- return {
101
- id: toStringValue(item.id, `prize-draw-${index}`),
102
- primary: toStringValue(item.title ?? item.name, "Untitled prize draw"),
103
- secondary: toStringValue(item.condition, ""),
104
- status: toStringValue(item.status, "draft"),
105
- entryFee: priceRaw ? toCurrency(priceRaw) : "Free",
106
- drawDate: item.prizeRevealWindowEnd
107
- ? toRelativeDate(item.prizeRevealWindowEnd)
108
- : "TBA",
109
- updatedAt: toRelativeDate(item.updatedAt ?? item.createdAt),
110
- imageUrl: toStringValue(item.mainImage ?? item.images?.[0], undefined),
111
- image: toStringValue(item.mainImage ?? item.images?.[0], undefined),
112
- };
113
- }),
114
- getTotal: (response, mappedRows) => typeof response.meta?.total === "number" ? response.meta.total : mappedRows.length,
115
- buildFilters: (state) => {
116
- const status = state.status && state.status !== "All" ? sieveFilter("status", SIEVE_OP.EQ, state.status) : null;
117
- // The hide-closed clause that used to live here tested the reveal
118
- // WINDOW END date, a different field from the reveal STATUS every other
119
- // surface reads — so a draw the seller had closed early still showed as
120
- // open here. It also pushed an inequality alongside an arbitrary sort
121
- // (Root Cause #59), which `audit-listing-indices` had been reporting as
122
- // QUERY_UNSATISFIABLE. The scope param now carries it, resolved from the
123
- // listing-type registry.
124
- return ["listingType==prize-draw", status].filter(Boolean).join(",");
125
- },
126
- buildExtraParams: () => scope.extraParams,
127
- renderAboveContent: scope.renderAboveContent,
128
- rowHrefTemplate: String(ROUTES.STORE.PRIZE_DRAWS_EDIT("{id}")),
129
- renderRowActions: (row) => (_jsx(RowActionMenu, { actions: [
130
- {
131
- label: ACTIONS.STORE["edit-listing"].label,
132
- onClick: () => void dispatch({ type: "NAVIGATE", href: String(ROUTES.STORE.PRIZE_DRAWS_EDIT(row.id)) }),
133
- },
134
- {
135
- label: "View Entries",
136
- onClick: () => void dispatch({ type: "NAVIGATE", href: String(ROUTES.STORE.PRIZE_DRAW_ENTRIES(row.id)) }),
137
- },
138
- ...(onDelete
139
- ? [
140
- {
141
- label: ACTIONS.STORE["delete-listing"].label,
142
- destructive: true,
143
- onClick: () => setDeleteTargetId(row.id),
144
- disabled: deletingId === row.id,
145
- },
146
- ]
147
- : []),
148
- ] })),
149
- renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsx(FilterChipGroup, { label: "Status", tabs: SELLER_PRIZE_DRAW_STATUS_TABS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) })),
150
- };
151
- return (_jsxs(_Fragment, { children: [_jsx(DataListingView, { config: config }), deleteTargetId && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Prize Draw", message: "Are you sure you want to delete this prize draw listing? This cannot be undone.", onConfirm: () => handleDelete(deleteTargetId), onClose: () => setDeleteTargetId(null), isDeleting: deletingId === deleteTargetId }))] }));
152
- }
@@ -1,5 +0,0 @@
1
- import type { Permission } from "../../security";
2
- /** Required permission for each store management route path */
3
- export declare const STORE_PAGE_PERMISSIONS: Record<string, Permission>;
4
- /** @deprecated Use STORE_PAGE_PERMISSIONS */
5
- export declare const SELLER_PAGE_PERMISSIONS: Record<string, string>;
@@ -1,17 +0,0 @@
1
- /** Required permission for each store management route path */
2
- export const STORE_PAGE_PERMISSIONS = {
3
- "/store": "seller:access",
4
- "/store/dashboard": "seller:analytics",
5
- "/store/products": "seller:products:read",
6
- "/store/products/new": "seller:products:write",
7
- "/store/products/[id]": "seller:products:write",
8
- "/store/orders": "seller:orders:read",
9
- "/store/orders/[id]": "seller:orders:read",
10
- "/store/analytics": "seller:analytics",
11
- "/store/coupons": "seller:coupons",
12
- "/store/storefront": "seller:store",
13
- "/store/payouts": "seller:payouts:read",
14
- "/store/shipping": "seller:shipping",
15
- };
16
- /** @deprecated Use STORE_PAGE_PERMISSIONS */
17
- export const SELLER_PAGE_PERMISSIONS = STORE_PAGE_PERMISSIONS;
@@ -1,80 +0,0 @@
1
- import { type ReactNode } from "react";
2
- import type { JsonValue } from "@mohasinac/appkit/client";
3
- import type { ZodTypeAny } from "zod";
4
- export interface StepDef<T extends object = Record<string, JsonValue>> {
5
- label: string;
6
- render: (props: {
7
- values: T;
8
- onChange: (partial: Partial<T>) => void;
9
- errors: Record<string, string>;
10
- }) => ReactNode;
11
- /** Returns an error message string if invalid, or null/undefined if valid. */
12
- validate?: (values: T) => string | null | undefined;
13
- /**
14
- * Schema field names this step owns — drives error→step attribution
15
- * (surfaced to the caller via `onValidationChange`'s `fieldToStepIndex`,
16
- * consumed by `<FormErrorSummary>`).
17
- */
18
- fields?: string[];
19
- /**
20
- * Per-step Zod schema. Runs live (on every value change, not just on
21
- * Next/Publish) via `onValidationChange`. Falls back to the whole-form
22
- * `schema` prop, then to a schema inherited from an ancestor `FormShell`
23
- * via `FormSchemaContext`, when omitted.
24
- */
25
- schema?: ZodTypeAny;
26
- }
27
- export interface StepFormProps<T extends object = Record<string, JsonValue>> {
28
- steps: StepDef<T>[];
29
- values: T;
30
- onChange: (partial: Partial<T>) => void;
31
- onComplete: () => void | Promise<void>;
32
- completeLabel?: string;
33
- isLoading?: boolean;
34
- /** localStorage key to persist current step (optional). */
35
- formId?: string;
36
- /** Current step index (0-based). Controlled from outside. */
37
- currentStep: number;
38
- onStepChange: (step: number) => void;
39
- /** Suppress the built-in action bar. Use FormShell's renderBottomBar instead. */
40
- hideActions?: boolean;
41
- /** Per-step error flags — when true, step button shows a red error badge */
42
- stepErrors?: boolean[];
43
- /**
44
- * Whole-form Zod schema, used by any step that doesn't declare its own
45
- * `StepDef.schema`. Falls back to an ancestor `FormShell`'s schema (via
46
- * `FormSchemaContext`) when omitted here too.
47
- */
48
- schema?: ZodTypeAny;
49
- /**
50
- * Fired whenever live validation recomputes — the current field-name→
51
- * message map plus a field-name→step-index map derived from `steps[].fields`.
52
- * The caller (which owns the single `FormShellContext.Provider` for the
53
- * surrounding form) composes these into its own context value so
54
- * `<FormErrorSummary>` and per-field inline errors both work, instead of
55
- * `StepForm` mounting a second, potentially-shadowing provider itself.
56
- */
57
- onValidationChange?: (fieldErrors: Record<string, string>, fieldToStepIndex: Record<string, number>) => void;
58
- }
59
- export interface StepFormActionsProps {
60
- currentStep: number;
61
- totalSteps: number;
62
- onNext: () => void;
63
- onPrev?: () => void;
64
- completeLabel?: string;
65
- isLoading?: boolean;
66
- disabled?: boolean;
67
- }
68
- /** Standalone step nav bar — use as `renderBottomBar` in FormShell. */
69
- export declare function StepFormActions({ currentStep, totalSteps, onNext, onPrev, completeLabel, isLoading, disabled, }: StepFormActionsProps): import("react").JSX.Element;
70
- /** Step indicator bar shown above step content. */
71
- export declare function StepIndicator({ steps, currentStep, onStepClick, stepErrors, }: {
72
- steps: {
73
- label: string;
74
- }[];
75
- currentStep: number;
76
- onStepClick?: (index: number) => void;
77
- /** True for each step that has a validation error — renders a red dot badge */
78
- stepErrors?: boolean[];
79
- }): import("react").JSX.Element;
80
- export declare function StepForm<T extends object = Record<string, JsonValue>>({ steps, values, onChange, onComplete, completeLabel, isLoading, formId, currentStep, onStepChange, hideActions, stepErrors, schema, onValidationChange, }: StepFormProps<T>): import("react").JSX.Element;