@burdenoff/microfe-store 2026.510.113

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 (141) hide show
  1. package/README.md +217 -0
  2. package/dist/StoreAdminRoot.d.ts +22 -0
  3. package/dist/StoreAdminRoot.js +23 -0
  4. package/dist/StoreAdminRoot.js.map +1 -0
  5. package/dist/StoreAdminRoutes.d.ts +9 -0
  6. package/dist/StoreAdminRoutes.js +69 -0
  7. package/dist/StoreAdminRoutes.js.map +1 -0
  8. package/dist/StoreRoot.d.ts +31 -0
  9. package/dist/StoreRoot.js +139 -0
  10. package/dist/StoreRoot.js.map +1 -0
  11. package/dist/StoreRoutes.d.ts +12 -0
  12. package/dist/StoreRoutes.js +285 -0
  13. package/dist/StoreRoutes.js.map +1 -0
  14. package/dist/components/InstallAppModal.d.ts +26 -0
  15. package/dist/components/InstallAppModal.js +287 -0
  16. package/dist/components/InstallAppModal.js.map +1 -0
  17. package/dist/components/RouteGuards.d.ts +17 -0
  18. package/dist/components/RouteGuards.js +26 -0
  19. package/dist/components/RouteGuards.js.map +1 -0
  20. package/dist/components/cart/CartDrawer.d.ts +35 -0
  21. package/dist/components/cart/CartDrawer.js +162 -0
  22. package/dist/components/cart/CartDrawer.js.map +1 -0
  23. package/dist/components/index.d.ts +9 -0
  24. package/dist/components/index.js +3 -0
  25. package/dist/components/marketplace/ProductCard.d.ts +18 -0
  26. package/dist/components/marketplace/ProductCard.js +2 -0
  27. package/dist/dev/main.d.ts +1 -0
  28. package/dist/generated/global-operations.d.ts +2012 -0
  29. package/dist/generated/global-operations.js +1444 -0
  30. package/dist/generated/global-operations.js.map +1 -0
  31. package/dist/generated/global-types.d.ts +20856 -0
  32. package/dist/generated/global-types.js +14 -0
  33. package/dist/generated/global-types.js.map +1 -0
  34. package/dist/generated/wspace-operations.d.ts +1 -0
  35. package/dist/generated/wspace-types.d.ts +53362 -0
  36. package/dist/hooks/index.d.ts +12 -0
  37. package/dist/hooks/useBackendCart.d.ts +73 -0
  38. package/dist/hooks/useBackendCart.js +171 -0
  39. package/dist/hooks/useBackendCart.js.map +1 -0
  40. package/dist/hooks/useCart.d.ts +62 -0
  41. package/dist/hooks/useCart.js +90 -0
  42. package/dist/hooks/useCart.js.map +1 -0
  43. package/dist/hooks/useInstallations.d.ts +43 -0
  44. package/dist/hooks/useInstallations.js +140 -0
  45. package/dist/hooks/useInstallations.js.map +1 -0
  46. package/dist/hooks/useOrders.d.ts +40 -0
  47. package/dist/hooks/useOrders.js +73 -0
  48. package/dist/hooks/useOrders.js.map +1 -0
  49. package/dist/hooks/useProductSearch.d.ts +22 -0
  50. package/dist/hooks/useProductSearch.js +59 -0
  51. package/dist/hooks/useProductSearch.js.map +1 -0
  52. package/dist/hooks/useStoreGraphQL.d.ts +475 -0
  53. package/dist/hooks/useStoreGraphQL.js +751 -0
  54. package/dist/hooks/useStoreGraphQL.js.map +1 -0
  55. package/dist/hooks/useStoreGraphQLWithContext.d.ts +48 -0
  56. package/dist/hooks/useStoreGraphQLWithContext.js +39 -0
  57. package/dist/hooks/useStoreGraphQLWithContext.js.map +1 -0
  58. package/dist/hooks/useStorePermissions.d.ts +63 -0
  59. package/dist/hooks/useStorePermissions.js +88 -0
  60. package/dist/hooks/useStorePermissions.js.map +1 -0
  61. package/dist/index.d.ts +44 -0
  62. package/dist/index.js +13 -0
  63. package/dist/pages/AdminDashboardPage.d.ts +3 -0
  64. package/dist/pages/AdminDashboardPage.js +491 -0
  65. package/dist/pages/AdminDashboardPage.js.map +1 -0
  66. package/dist/pages/AdminReviewModerationPage.d.ts +3 -0
  67. package/dist/pages/AdminReviewModerationPage.js +247 -0
  68. package/dist/pages/AdminReviewModerationPage.js.map +1 -0
  69. package/dist/pages/AdminStoresPage.d.ts +3 -0
  70. package/dist/pages/AdminStoresPage.js +442 -0
  71. package/dist/pages/AdminStoresPage.js.map +1 -0
  72. package/dist/pages/AdminSubmissionsQueuePage.d.ts +3 -0
  73. package/dist/pages/AdminSubmissionsQueuePage.js +387 -0
  74. package/dist/pages/AdminSubmissionsQueuePage.js.map +1 -0
  75. package/dist/pages/AppDetailPage.d.ts +3 -0
  76. package/dist/pages/AppDetailPage.js +166 -0
  77. package/dist/pages/AppDetailPage.js.map +1 -0
  78. package/dist/pages/AppSettingsPage.d.ts +3 -0
  79. package/dist/pages/AppSettingsPage.js +100 -0
  80. package/dist/pages/AppSettingsPage.js.map +1 -0
  81. package/dist/pages/CartPage.d.ts +8 -0
  82. package/dist/pages/CartPage.js +259 -0
  83. package/dist/pages/CartPage.js.map +1 -0
  84. package/dist/pages/InstalledAppsPage.d.ts +8 -0
  85. package/dist/pages/InstalledAppsPage.js +290 -0
  86. package/dist/pages/InstalledAppsPage.js.map +1 -0
  87. package/dist/pages/MarketplaceHomePage.d.ts +3 -0
  88. package/dist/pages/MarketplaceHomePage.js +1118 -0
  89. package/dist/pages/MarketplaceHomePage.js.map +1 -0
  90. package/dist/pages/MyLicensesPage.d.ts +3 -0
  91. package/dist/pages/MyLicensesPage.js +146 -0
  92. package/dist/pages/MyLicensesPage.js.map +1 -0
  93. package/dist/pages/OrderConfirmationPage.d.ts +3 -0
  94. package/dist/pages/OrderConfirmationPage.js +178 -0
  95. package/dist/pages/OrderConfirmationPage.js.map +1 -0
  96. package/dist/pages/OrdersPage.d.ts +8 -0
  97. package/dist/pages/OrdersPage.js +358 -0
  98. package/dist/pages/OrdersPage.js.map +1 -0
  99. package/dist/pages/ProductCategoryPage.d.ts +3 -0
  100. package/dist/pages/ProductCategoryPage.js +83 -0
  101. package/dist/pages/ProductCategoryPage.js.map +1 -0
  102. package/dist/pages/ProductDetailPage.d.ts +8 -0
  103. package/dist/pages/ProductDetailPage.js +1205 -0
  104. package/dist/pages/ProductDetailPage.js.map +1 -0
  105. package/dist/pages/ProductReviewsPage.d.ts +3 -0
  106. package/dist/pages/ProductReviewsPage.js +86 -0
  107. package/dist/pages/ProductReviewsPage.js.map +1 -0
  108. package/dist/pages/PublisherDashboardPage.d.ts +3 -0
  109. package/dist/pages/PublisherDashboardPage.js +154 -0
  110. package/dist/pages/PublisherDashboardPage.js.map +1 -0
  111. package/dist/pages/PublisherRevenuePage.d.ts +3 -0
  112. package/dist/pages/PublisherRevenuePage.js +138 -0
  113. package/dist/pages/PublisherRevenuePage.js.map +1 -0
  114. package/dist/pages/PublisherSubmissionsPage.d.ts +3 -0
  115. package/dist/pages/PublisherSubmissionsPage.js +174 -0
  116. package/dist/pages/PublisherSubmissionsPage.js.map +1 -0
  117. package/dist/pages/PublisherSubmitPage.d.ts +3 -0
  118. package/dist/pages/PublisherSubmitPage.js +224 -0
  119. package/dist/pages/PublisherSubmitPage.js.map +1 -0
  120. package/dist/pages/SearchResultsPage.d.ts +3 -0
  121. package/dist/pages/SearchResultsPage.js +125 -0
  122. package/dist/pages/SearchResultsPage.js.map +1 -0
  123. package/dist/pages/StoresPage.d.ts +3 -0
  124. package/dist/pages/StoresPage.js +154 -0
  125. package/dist/pages/StoresPage.js.map +1 -0
  126. package/dist/providers/StoreProvider.d.ts +38 -0
  127. package/dist/providers/StoreProvider.js +51 -0
  128. package/dist/providers/StoreProvider.js.map +1 -0
  129. package/dist/store/storeStore.d.ts +69 -0
  130. package/dist/store/storeStore.js +68 -0
  131. package/dist/store/storeStore.js.map +1 -0
  132. package/dist/translations/en.d.ts +518 -0
  133. package/dist/translations/en.js +514 -0
  134. package/dist/translations/en.js.map +1 -0
  135. package/dist/types/index.d.ts +575 -0
  136. package/dist/utils/index.d.ts +67 -0
  137. package/dist/utils/index.js +114 -0
  138. package/dist/utils/index.js.map +1 -0
  139. package/dist/utils/nativeBridge.d.ts +2 -0
  140. package/dist/utils/nativeBridge.js +2 -0
  141. package/package.json +105 -0
@@ -0,0 +1,247 @@
1
+ import { useStore as e } from "../providers/StoreProvider.js";
2
+ import { useEffect as t, useRef as n, useState as r } from "react";
3
+ import { ArrowLeft as i, MessageSquareWarning as a, Search as o, X as s } from "lucide-react";
4
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
5
+ import { useNavigate as u } from "react-router-dom";
6
+ import { graphqlFetch as d } from "@burdenoff/fe-libs/shared/graphql";
7
+ //#region src/pages/AdminReviewModerationPage.tsx
8
+ var f = "query SearchProductsForModeration($query: String!) { searchProducts(query: $query, limit: 10) { id name slug } }", p = "query ProductReviewsForModeration($productId: String!) { productReviews(productId: $productId) { id userId rating title comment status helpful createdAt } }", m = "mutation RejectReview($id: ID!) { rejectReview(id: $id) { id status } }", h = () => {
9
+ let h = u(), { authToken: g } = e(), [_, v] = r(""), [y, b] = r([]), [x, S] = r(!1), [C, w] = r(!1), [T, E] = r(null), [D, O] = r([]), [k, A] = r(!1), [j, M] = r(null), [N, P] = r(null), F = n(null), I = n(null);
10
+ t(() => {
11
+ let e = (e) => {
12
+ I.current && !I.current.contains(e.target) && w(!1);
13
+ };
14
+ return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
15
+ }, []);
16
+ let L = (e) => {
17
+ if (v(e), E(null), O([]), M(null), F.current && clearTimeout(F.current), !e.trim()) {
18
+ b([]), w(!1);
19
+ return;
20
+ }
21
+ F.current = setTimeout(async () => {
22
+ S(!0);
23
+ try {
24
+ b((await d({
25
+ gateway: "global",
26
+ query: f,
27
+ variables: { query: e },
28
+ authToken: g || void 0
29
+ })).data?.searchProducts ?? []), w(!0);
30
+ } catch {
31
+ b([]);
32
+ } finally {
33
+ S(!1);
34
+ }
35
+ }, 300);
36
+ }, R = (e) => {
37
+ E(e), v(e.name), w(!1), z(e.id);
38
+ }, z = async (e) => {
39
+ A(!0), M(null);
40
+ try {
41
+ let t = await d({
42
+ gateway: "global",
43
+ query: p,
44
+ variables: { productId: e },
45
+ authToken: g || void 0
46
+ });
47
+ if (t.errors?.length) throw Error(t.errors[0]?.message ?? "Failed to fetch reviews");
48
+ O(t.data?.productReviews ?? []);
49
+ } catch (e) {
50
+ M(e instanceof Error ? e.message : "Failed to fetch reviews");
51
+ } finally {
52
+ A(!1);
53
+ }
54
+ }, B = async (e) => {
55
+ P(e), M(null);
56
+ try {
57
+ let t = await d({
58
+ gateway: "global",
59
+ query: m,
60
+ variables: { id: e },
61
+ authToken: g || void 0
62
+ });
63
+ if (t.errors?.length) throw Error(t.errors[0]?.message ?? "Failed to remove review");
64
+ O((t) => t.filter((t) => t.id !== e));
65
+ } catch (e) {
66
+ M(e instanceof Error ? e.message : "Failed to remove review");
67
+ } finally {
68
+ P(null);
69
+ }
70
+ };
71
+ return /* @__PURE__ */ l("div", {
72
+ className: "min-h-screen bg-surface-default",
73
+ children: [/* @__PURE__ */ c("header", {
74
+ className: "border-b border-border-default bg-surface-raised",
75
+ children: /* @__PURE__ */ l("div", {
76
+ className: "mx-auto max-w-7xl px-6 py-4",
77
+ children: [/* @__PURE__ */ l("div", {
78
+ className: "flex items-center gap-3",
79
+ children: [/* @__PURE__ */ l("button", {
80
+ type: "button",
81
+ onClick: () => h(-1),
82
+ "aria-label": "Go back",
83
+ className: "inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm text-text-secondary hover:bg-surface-hover hover:text-text-primary",
84
+ children: [/* @__PURE__ */ c(i, { className: "h-4 w-4" }), "Back"]
85
+ }), /* @__PURE__ */ l("div", {
86
+ className: "flex items-center gap-2",
87
+ children: [/* @__PURE__ */ c(a, { className: "h-5 w-5 text-text-primary" }), /* @__PURE__ */ c("h1", {
88
+ className: "text-xl font-semibold text-text-primary",
89
+ children: "Review Moderation"
90
+ })]
91
+ })]
92
+ }), /* @__PURE__ */ c("p", {
93
+ className: "mt-1 text-sm text-text-secondary",
94
+ children: "Review published content by product and remove anything that violates guidelines"
95
+ })]
96
+ })
97
+ }), /* @__PURE__ */ c("main", {
98
+ className: "mx-auto max-w-7xl px-6 py-6",
99
+ children: /* @__PURE__ */ l("div", {
100
+ className: "space-y-4",
101
+ children: [
102
+ /* @__PURE__ */ l("div", {
103
+ className: "rounded-lg border border-border-default bg-surface-raised p-4",
104
+ children: [/* @__PURE__ */ l("div", {
105
+ ref: I,
106
+ className: "relative",
107
+ children: [
108
+ /* @__PURE__ */ c("label", {
109
+ htmlFor: "admin-review-product-search",
110
+ className: "mb-1.5 block text-sm font-medium text-text-primary",
111
+ children: "Search product by name"
112
+ }),
113
+ /* @__PURE__ */ l("div", {
114
+ className: "relative flex items-center",
115
+ children: [
116
+ /* @__PURE__ */ c(o, { className: "pointer-events-none absolute left-3 h-4 w-4 text-text-secondary" }),
117
+ /* @__PURE__ */ c("input", {
118
+ id: "admin-review-product-search",
119
+ value: _,
120
+ onChange: (e) => L(e.target.value),
121
+ onFocus: () => y.length > 0 && w(!0),
122
+ placeholder: "Type a product name to search...",
123
+ autoComplete: "off",
124
+ className: "w-full rounded-md border border-border-default bg-surface-default py-2 pl-9 pr-3 text-sm text-text-primary outline-none focus:border-border-accent"
125
+ }),
126
+ x && /* @__PURE__ */ c("span", {
127
+ className: "absolute right-3 text-xs text-text-secondary",
128
+ children: "Searching…"
129
+ })
130
+ ]
131
+ }),
132
+ C && y.length > 0 && /* @__PURE__ */ c("ul", {
133
+ className: "absolute z-10 mt-1 w-full rounded-md border border-border-default bg-surface-raised shadow-lg",
134
+ children: y.map((e) => /* @__PURE__ */ c("li", { children: /* @__PURE__ */ l("button", {
135
+ type: "button",
136
+ onClick: () => R(e),
137
+ className: "w-full px-4 py-2.5 text-left text-sm hover:bg-surface-hover",
138
+ children: [/* @__PURE__ */ c("span", {
139
+ className: "font-medium text-text-primary",
140
+ children: e.name
141
+ }), /* @__PURE__ */ c("span", {
142
+ className: "ml-2 text-xs text-text-secondary",
143
+ children: e.slug
144
+ })]
145
+ }) }, e.id))
146
+ }),
147
+ C && !x && y.length === 0 && _.trim() && /* @__PURE__ */ l("div", {
148
+ className: "absolute z-10 mt-1 w-full rounded-md border border-border-default bg-surface-raised px-4 py-3 text-sm text-text-secondary shadow-lg",
149
+ children: [
150
+ "No products found for “",
151
+ _,
152
+ "”"
153
+ ]
154
+ })
155
+ ]
156
+ }), T && /* @__PURE__ */ l("p", {
157
+ className: "mt-2 text-xs text-text-secondary",
158
+ children: [
159
+ "Moderating:",
160
+ " ",
161
+ /* @__PURE__ */ c("span", {
162
+ className: "font-medium text-text-primary",
163
+ children: T.name
164
+ }),
165
+ /* @__PURE__ */ l("span", {
166
+ className: "ml-1 text-text-tertiary",
167
+ children: [
168
+ "(",
169
+ T.id,
170
+ ")"
171
+ ]
172
+ })
173
+ ]
174
+ })]
175
+ }),
176
+ j && /* @__PURE__ */ c("div", {
177
+ role: "alert",
178
+ className: "rounded-md border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger",
179
+ children: j
180
+ }),
181
+ k && /* @__PURE__ */ c("div", {
182
+ className: "rounded-lg border border-border-default bg-surface-raised p-10 text-center",
183
+ children: /* @__PURE__ */ c("p", {
184
+ className: "text-sm text-text-secondary",
185
+ children: "Loading reviews…"
186
+ })
187
+ }),
188
+ !k && T && D.length === 0 ? /* @__PURE__ */ l("div", {
189
+ className: "rounded-lg border border-border-default bg-surface-raised p-10 text-center",
190
+ children: [/* @__PURE__ */ c(a, { className: "mx-auto mb-2 h-8 w-8 text-text-secondary" }), /* @__PURE__ */ c("p", {
191
+ className: "text-sm text-text-secondary",
192
+ children: "No reviews found for this product."
193
+ })]
194
+ }) : /* @__PURE__ */ c("ul", {
195
+ className: "space-y-3",
196
+ children: D.map((e) => /* @__PURE__ */ c("li", {
197
+ className: "rounded-lg border border-border-default bg-surface-raised p-4",
198
+ children: /* @__PURE__ */ l("div", {
199
+ className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",
200
+ children: [/* @__PURE__ */ l("div", { children: [
201
+ /* @__PURE__ */ l("div", {
202
+ className: "flex items-center gap-2",
203
+ children: [/* @__PURE__ */ c("p", {
204
+ className: "font-medium text-text-primary",
205
+ children: e.title || "Untitled review"
206
+ }), /* @__PURE__ */ c("span", {
207
+ className: "rounded-full bg-surface-muted px-2 py-0.5 text-xs text-text-secondary",
208
+ children: e.status
209
+ })]
210
+ }),
211
+ /* @__PURE__ */ c("p", {
212
+ className: "mt-1 text-sm text-text-secondary",
213
+ children: e.comment || "No comment provided."
214
+ }),
215
+ /* @__PURE__ */ l("p", {
216
+ className: "mt-2 text-xs text-text-secondary",
217
+ children: [
218
+ "User ",
219
+ e.userId,
220
+ " • Rating ",
221
+ e.rating,
222
+ "/5 • Helpful ",
223
+ e.helpful
224
+ ]
225
+ })
226
+ ] }), /* @__PURE__ */ c("div", {
227
+ className: "flex items-center gap-2",
228
+ children: /* @__PURE__ */ l("button", {
229
+ type: "button",
230
+ onClick: () => B(e.id),
231
+ disabled: N === e.id,
232
+ className: "inline-flex items-center gap-1.5 rounded-md border border-border-danger px-3 py-1.5 text-sm font-medium text-text-danger hover:bg-surface-danger-muted disabled:cursor-not-allowed disabled:opacity-60",
233
+ children: [/* @__PURE__ */ c(s, { className: "h-4 w-4" }), " Remove"]
234
+ })
235
+ })]
236
+ })
237
+ }, e.id))
238
+ })
239
+ ]
240
+ })
241
+ })]
242
+ });
243
+ };
244
+ //#endregion
245
+ export { h as AdminReviewModerationPage };
246
+
247
+ //# sourceMappingURL=AdminReviewModerationPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminReviewModerationPage.js","names":[],"sources":["../../src/pages/AdminReviewModerationPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useState, useRef, useEffect } from 'react';\nimport { ArrowLeft, Search, X, MessageSquareWarning } from 'lucide-react';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useNavigate } from 'react-router-dom';\nimport { useStore } from '../providers/StoreProvider';\n\ntype ModerationReview = {\n id: string;\n userId: string;\n rating: number;\n title?: string | null;\n comment?: string | null;\n status: string;\n helpful: number;\n createdAt: string;\n};\n\ntype ProductSearchResult = {\n id: string;\n name: string;\n slug: string;\n};\n\nconst SEARCH_PRODUCTS_QUERY = `query SearchProductsForModeration($query: String!) { searchProducts(query: $query, limit: 10) { id name slug } }`;\nconst PRODUCT_REVIEWS_QUERY = `query ProductReviewsForModeration($productId: String!) { productReviews(productId: $productId) { id userId rating title comment status helpful createdAt } }`;\nconst REJECT_REVIEW_MUTATION = `mutation RejectReview($id: ID!) { rejectReview(id: $id) { id status } }`;\n\nexport const AdminReviewModerationPage: FC = () => {\n const navigate = useNavigate();\n const { authToken } = useStore();\n const [searchQuery, setSearchQuery] = useState('');\n const [searchResults, setSearchResults] = useState<ProductSearchResult[]>([]);\n const [searchLoading, setSearchLoading] = useState(false);\n const [showDropdown, setShowDropdown] = useState(false);\n const [selectedProduct, setSelectedProduct] = useState<ProductSearchResult | null>(null);\n const [reviews, setReviews] = useState<ModerationReview[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [actingId, setActingId] = useState<string | null>(null);\n const searchDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setShowDropdown(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n const handleSearchChange = (value: string) => {\n setSearchQuery(value);\n setSelectedProduct(null);\n setReviews([]);\n setError(null);\n\n if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);\n if (!value.trim()) {\n setSearchResults([]);\n setShowDropdown(false);\n return;\n }\n\n searchDebounceRef.current = setTimeout(async () => {\n setSearchLoading(true);\n try {\n const result = await graphqlFetch<{ searchProducts: ProductSearchResult[] }>({\n gateway: 'global',\n query: SEARCH_PRODUCTS_QUERY,\n variables: { query: value },\n authToken: authToken || undefined,\n });\n setSearchResults(result.data?.searchProducts ?? []);\n setShowDropdown(true);\n } catch {\n setSearchResults([]);\n } finally {\n setSearchLoading(false);\n }\n }, 300);\n };\n\n const selectProduct = (product: ProductSearchResult) => {\n setSelectedProduct(product);\n setSearchQuery(product.name);\n setShowDropdown(false);\n void loadReviews(product.id);\n };\n\n const loadReviews = async (productId: string) => {\n setLoading(true);\n setError(null);\n try {\n const result = await graphqlFetch<{ productReviews: ModerationReview[] }>({\n gateway: 'global',\n query: PRODUCT_REVIEWS_QUERY,\n variables: { productId },\n authToken: authToken || undefined,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Failed to fetch reviews');\n }\n\n setReviews(result.data?.productReviews ?? []);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to fetch reviews');\n } finally {\n setLoading(false);\n }\n };\n\n const removeReview = async (reviewId: string) => {\n setActingId(reviewId);\n setError(null);\n try {\n const result = await graphqlFetch({\n gateway: 'global',\n query: REJECT_REVIEW_MUTATION,\n variables: { id: reviewId },\n authToken: authToken || undefined,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Failed to remove review');\n }\n\n setReviews((prev) => prev.filter((review) => review.id !== reviewId));\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to remove review');\n } finally {\n setActingId(null);\n }\n };\n\n return (\n <div className=\"min-h-screen bg-surface-default\">\n <header className=\"border-b border-border-default bg-surface-raised\">\n <div className=\"mx-auto max-w-7xl px-6 py-4\">\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(-1)}\n aria-label=\"Go back\"\n className=\"inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm text-text-secondary hover:bg-surface-hover hover:text-text-primary\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back\n </button>\n <div className=\"flex items-center gap-2\">\n <MessageSquareWarning className=\"h-5 w-5 text-text-primary\" />\n <h1 className=\"text-xl font-semibold text-text-primary\">Review Moderation</h1>\n </div>\n </div>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Review published content by product and remove anything that violates guidelines\n </p>\n </div>\n </header>\n\n <main className=\"mx-auto max-w-7xl px-6 py-6\">\n <div className=\"space-y-4\">\n <div className=\"rounded-lg border border-border-default bg-surface-raised p-4\">\n <div ref={dropdownRef} className=\"relative\">\n <label\n htmlFor=\"admin-review-product-search\"\n className=\"mb-1.5 block text-sm font-medium text-text-primary\"\n >\n Search product by name\n </label>\n <div className=\"relative flex items-center\">\n <Search className=\"pointer-events-none absolute left-3 h-4 w-4 text-text-secondary\" />\n <input\n id=\"admin-review-product-search\"\n value={searchQuery}\n onChange={(e) => handleSearchChange(e.target.value)}\n onFocus={() => searchResults.length > 0 && setShowDropdown(true)}\n placeholder=\"Type a product name to search...\"\n autoComplete=\"off\"\n className=\"w-full rounded-md border border-border-default bg-surface-default py-2 pl-9 pr-3 text-sm text-text-primary outline-none focus:border-border-accent\"\n />\n {searchLoading && (\n <span className=\"absolute right-3 text-xs text-text-secondary\">Searching…</span>\n )}\n </div>\n\n {showDropdown && searchResults.length > 0 && (\n <ul className=\"absolute z-10 mt-1 w-full rounded-md border border-border-default bg-surface-raised shadow-lg\">\n {searchResults.map((product) => (\n <li key={product.id}>\n <button\n type=\"button\"\n onClick={() => selectProduct(product)}\n className=\"w-full px-4 py-2.5 text-left text-sm hover:bg-surface-hover\"\n >\n <span className=\"font-medium text-text-primary\">{product.name}</span>\n <span className=\"ml-2 text-xs text-text-secondary\">{product.slug}</span>\n </button>\n </li>\n ))}\n </ul>\n )}\n\n {showDropdown &&\n !searchLoading &&\n searchResults.length === 0 &&\n searchQuery.trim() && (\n <div className=\"absolute z-10 mt-1 w-full rounded-md border border-border-default bg-surface-raised px-4 py-3 text-sm text-text-secondary shadow-lg\">\n No products found for &ldquo;{searchQuery}&rdquo;\n </div>\n )}\n </div>\n\n {selectedProduct && (\n <p className=\"mt-2 text-xs text-text-secondary\">\n Moderating:{' '}\n <span className=\"font-medium text-text-primary\">{selectedProduct.name}</span>\n <span className=\"ml-1 text-text-tertiary\">({selectedProduct.id})</span>\n </p>\n )}\n </div>\n\n {error && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger\"\n >\n {error}\n </div>\n )}\n\n {loading && (\n <div className=\"rounded-lg border border-border-default bg-surface-raised p-10 text-center\">\n <p className=\"text-sm text-text-secondary\">Loading reviews…</p>\n </div>\n )}\n\n {!loading && selectedProduct && reviews.length === 0 ? (\n <div className=\"rounded-lg border border-border-default bg-surface-raised p-10 text-center\">\n <MessageSquareWarning className=\"mx-auto mb-2 h-8 w-8 text-text-secondary\" />\n <p className=\"text-sm text-text-secondary\">No reviews found for this product.</p>\n </div>\n ) : (\n <ul className=\"space-y-3\">\n {reviews.map((review) => (\n <li\n key={review.id}\n className=\"rounded-lg border border-border-default bg-surface-raised p-4\"\n >\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <div className=\"flex items-center gap-2\">\n <p className=\"font-medium text-text-primary\">\n {review.title || 'Untitled review'}\n </p>\n <span className=\"rounded-full bg-surface-muted px-2 py-0.5 text-xs text-text-secondary\">\n {review.status}\n </span>\n </div>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {review.comment || 'No comment provided.'}\n </p>\n <p className=\"mt-2 text-xs text-text-secondary\">\n User {review.userId} • Rating {review.rating}/5 • Helpful {review.helpful}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => removeReview(review.id)}\n disabled={actingId === review.id}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-danger px-3 py-1.5 text-sm font-medium text-text-danger hover:bg-surface-danger-muted disabled:cursor-not-allowed disabled:opacity-60\"\n >\n <X className=\"h-4 w-4\" /> Remove\n </button>\n </div>\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { FC } from 'react';
2
+
3
+ export declare const AdminStoresPage: FC;