@open-mercato/core 0.4.5-develop-636d33c995 → 0.4.5-develop-3d8e759e45

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 (211) hide show
  1. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js +17 -2
  2. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
  3. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +15 -0
  4. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  5. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +30 -0
  6. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  7. package/dist/modules/catalog/inbox-actions.js +51 -0
  8. package/dist/modules/catalog/inbox-actions.js.map +7 -0
  9. package/dist/modules/catalog/lib/messageObjectPreviews.js +146 -0
  10. package/dist/modules/catalog/lib/messageObjectPreviews.js.map +7 -0
  11. package/dist/modules/catalog/message-objects.js +95 -0
  12. package/dist/modules/catalog/message-objects.js.map +7 -0
  13. package/dist/modules/currencies/backend/currencies/[id]/page.js +21 -0
  14. package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
  15. package/dist/modules/currencies/lib/messageObjectPreviews.js +51 -0
  16. package/dist/modules/currencies/lib/messageObjectPreviews.js.map +7 -0
  17. package/dist/modules/currencies/message-objects.js +41 -0
  18. package/dist/modules/currencies/message-objects.js.map +7 -0
  19. package/dist/modules/customers/backend/customers/companies/[id]/page.js +20 -0
  20. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  21. package/dist/modules/customers/backend/customers/deals/[id]/page.js +12 -1
  22. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  23. package/dist/modules/customers/backend/customers/people/[id]/page.js +20 -0
  24. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  25. package/dist/modules/customers/components/detail/CompanyHighlights.js +18 -14
  26. package/dist/modules/customers/components/detail/CompanyHighlights.js.map +2 -2
  27. package/dist/modules/customers/components/detail/PersonHighlights.js +18 -14
  28. package/dist/modules/customers/components/detail/PersonHighlights.js.map +2 -2
  29. package/dist/modules/customers/inbox-actions.js +230 -0
  30. package/dist/modules/customers/inbox-actions.js.map +7 -0
  31. package/dist/modules/customers/lib/messageObjectPreviews.js +41 -5
  32. package/dist/modules/customers/lib/messageObjectPreviews.js.map +2 -2
  33. package/dist/modules/customers/message-objects.js +31 -11
  34. package/dist/modules/customers/message-objects.js.map +2 -2
  35. package/dist/modules/inbox_ops/api/emails/[id]/route.js +40 -1
  36. package/dist/modules/inbox_ops/api/emails/[id]/route.js.map +2 -2
  37. package/dist/modules/inbox_ops/api/extract/route.js +87 -0
  38. package/dist/modules/inbox_ops/api/extract/route.js.map +7 -0
  39. package/dist/modules/inbox_ops/api/proposals/[id]/translate/route.js +6 -1
  40. package/dist/modules/inbox_ops/api/proposals/[id]/translate/route.js.map +2 -2
  41. package/dist/modules/inbox_ops/api/proposals/counts/route.js.map +2 -2
  42. package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +40 -14
  43. package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
  44. package/dist/modules/inbox_ops/backend/inbox-ops/log/page.meta.js +2 -2
  45. package/dist/modules/inbox_ops/backend/inbox-ops/log/page.meta.js.map +2 -2
  46. package/dist/modules/inbox_ops/backend/inbox-ops/page.js +161 -79
  47. package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
  48. package/dist/modules/inbox_ops/backend/inbox-ops/page.meta.js +2 -2
  49. package/dist/modules/inbox_ops/backend/inbox-ops/page.meta.js.map +2 -2
  50. package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.js +109 -62
  51. package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.js.map +3 -3
  52. package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.meta.js +2 -2
  53. package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.meta.js.map +2 -2
  54. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +36 -14
  55. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
  56. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.meta.js +2 -2
  57. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.meta.js.map +2 -2
  58. package/dist/modules/inbox_ops/components/proposals/ActionCard.js +65 -10
  59. package/dist/modules/inbox_ops/components/proposals/ActionCard.js.map +2 -2
  60. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +58 -10
  61. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
  62. package/dist/modules/inbox_ops/lib/constants.js.map +2 -2
  63. package/dist/modules/inbox_ops/lib/contactValidation.js +40 -0
  64. package/dist/modules/inbox_ops/lib/contactValidation.js.map +7 -0
  65. package/dist/modules/inbox_ops/lib/executionEngine.js +31 -826
  66. package/dist/modules/inbox_ops/lib/executionEngine.js.map +3 -3
  67. package/dist/modules/inbox_ops/lib/executionHelpers.js +368 -0
  68. package/dist/modules/inbox_ops/lib/executionHelpers.js.map +7 -0
  69. package/dist/modules/inbox_ops/lib/extractionPrompt.js +28 -35
  70. package/dist/modules/inbox_ops/lib/extractionPrompt.js.map +3 -3
  71. package/dist/modules/inbox_ops/lib/inbox-actions-generated.d.js +1 -0
  72. package/dist/modules/inbox_ops/lib/inbox-actions-generated.d.js.map +7 -0
  73. package/dist/modules/inbox_ops/lib/translationProvider.js +15 -10
  74. package/dist/modules/inbox_ops/lib/translationProvider.js.map +2 -2
  75. package/dist/modules/inbox_ops/subscribers/extractionWorker.js +16 -16
  76. package/dist/modules/inbox_ops/subscribers/extractionWorker.js.map +2 -2
  77. package/dist/modules/messages/commands/messages.js +3 -0
  78. package/dist/modules/messages/commands/messages.js.map +2 -2
  79. package/dist/modules/messages/components/message-detail/panels/objects-panel.js +6 -1
  80. package/dist/modules/messages/components/message-detail/panels/objects-panel.js.map +2 -2
  81. package/dist/modules/messages/components/message-detail/panels/thread-panel.js +4 -1
  82. package/dist/modules/messages/components/message-detail/panels/thread-panel.js.map +2 -2
  83. package/dist/modules/messages/frontend/messages/view/[token]/page.js +1 -0
  84. package/dist/modules/messages/frontend/messages/view/[token]/page.js.map +2 -2
  85. package/dist/modules/resources/backend/resources/resources/[id]/page.js +24 -7
  86. package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
  87. package/dist/modules/resources/lib/messageObjectPreviews.js +43 -0
  88. package/dist/modules/resources/lib/messageObjectPreviews.js.map +7 -0
  89. package/dist/modules/resources/message-objects.js +37 -0
  90. package/dist/modules/resources/message-objects.js.map +7 -0
  91. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +19 -0
  92. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
  93. package/dist/modules/sales/backend/sales/documents/[id]/page.js +23 -2
  94. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  95. package/dist/modules/sales/backend/sales/quotes/[id]/page.js +1 -1
  96. package/dist/modules/sales/backend/sales/quotes/[id]/page.js.map +2 -2
  97. package/dist/modules/sales/inbox-actions.js +278 -0
  98. package/dist/modules/sales/inbox-actions.js.map +7 -0
  99. package/dist/modules/sales/lib/messageObjectPreviews.js +49 -4
  100. package/dist/modules/sales/lib/messageObjectPreviews.js.map +2 -2
  101. package/dist/modules/sales/message-objects.js +44 -2
  102. package/dist/modules/sales/message-objects.js.map +2 -2
  103. package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js +59 -30
  104. package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js.map +2 -2
  105. package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js +1 -1
  106. package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js.map +1 -1
  107. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +8 -30
  108. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  109. package/dist/modules/staff/backend/staff/my-availability/page.js +13 -0
  110. package/dist/modules/staff/backend/staff/my-availability/page.js.map +2 -2
  111. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +8 -31
  112. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  113. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +32 -10
  114. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  115. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js +14 -1
  116. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js.map +2 -2
  117. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +14 -1
  118. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  119. package/dist/modules/staff/components/TeamForm.js +4 -2
  120. package/dist/modules/staff/components/TeamForm.js.map +2 -2
  121. package/dist/modules/staff/components/TeamRoleForm.js +4 -2
  122. package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
  123. package/dist/modules/staff/lib/messageObjectPreviews.js +111 -2
  124. package/dist/modules/staff/lib/messageObjectPreviews.js.map +2 -2
  125. package/dist/modules/staff/message-objects.js +79 -8
  126. package/dist/modules/staff/message-objects.js.map +2 -2
  127. package/jest.config.cjs +1 -0
  128. package/jest.mocks/inbox-actions.generated.js +5 -0
  129. package/package.json +2 -2
  130. package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +19 -5
  131. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +14 -0
  132. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +40 -0
  133. package/src/modules/catalog/inbox-actions.ts +60 -0
  134. package/src/modules/catalog/lib/messageObjectPreviews.ts +176 -0
  135. package/src/modules/catalog/message-objects.ts +102 -0
  136. package/src/modules/currencies/backend/currencies/[id]/page.tsx +20 -0
  137. package/src/modules/currencies/lib/messageObjectPreviews.ts +65 -0
  138. package/src/modules/currencies/message-objects.ts +40 -0
  139. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +19 -0
  140. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +13 -0
  141. package/src/modules/customers/backend/customers/people/[id]/page.tsx +19 -0
  142. package/src/modules/customers/components/detail/CompanyHighlights.tsx +14 -9
  143. package/src/modules/customers/components/detail/PersonHighlights.tsx +14 -9
  144. package/src/modules/customers/inbox-actions.ts +285 -0
  145. package/src/modules/customers/lib/messageObjectPreviews.ts +43 -3
  146. package/src/modules/customers/message-objects.ts +31 -11
  147. package/src/modules/inbox_ops/api/emails/[id]/route.ts +44 -0
  148. package/src/modules/inbox_ops/api/extract/route.ts +94 -0
  149. package/src/modules/inbox_ops/api/proposals/[id]/translate/route.ts +6 -1
  150. package/src/modules/inbox_ops/api/proposals/counts/route.ts +2 -0
  151. package/src/modules/inbox_ops/backend/inbox-ops/log/page.meta.ts +2 -2
  152. package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +43 -13
  153. package/src/modules/inbox_ops/backend/inbox-ops/page.meta.ts +2 -2
  154. package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +176 -81
  155. package/src/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.meta.ts +2 -2
  156. package/src/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.tsx +122 -68
  157. package/src/modules/inbox_ops/backend/inbox-ops/settings/page.meta.ts +2 -2
  158. package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +36 -14
  159. package/src/modules/inbox_ops/components/proposals/ActionCard.tsx +91 -7
  160. package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +64 -12
  161. package/src/modules/inbox_ops/lib/constants.ts +9 -0
  162. package/src/modules/inbox_ops/lib/contactValidation.ts +54 -0
  163. package/src/modules/inbox_ops/lib/executionEngine.ts +47 -1060
  164. package/src/modules/inbox_ops/lib/executionHelpers.ts +527 -0
  165. package/src/modules/inbox_ops/lib/extractionPrompt.ts +45 -34
  166. package/src/modules/inbox_ops/lib/inbox-actions-generated.d.ts +11 -0
  167. package/src/modules/inbox_ops/lib/translationProvider.ts +16 -10
  168. package/src/modules/inbox_ops/subscribers/extractionWorker.ts +16 -18
  169. package/src/modules/messages/commands/messages.ts +4 -0
  170. package/src/modules/messages/components/message-detail/panels/objects-panel.tsx +8 -1
  171. package/src/modules/messages/components/message-detail/panels/thread-panel.tsx +3 -0
  172. package/src/modules/messages/frontend/messages/view/[token]/page.tsx +1 -0
  173. package/src/modules/resources/backend/resources/resources/[id]/page.tsx +20 -4
  174. package/src/modules/resources/lib/messageObjectPreviews.ts +55 -0
  175. package/src/modules/resources/message-objects.ts +36 -0
  176. package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +18 -0
  177. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +23 -0
  178. package/src/modules/sales/backend/sales/quotes/[id]/page.tsx +1 -1
  179. package/src/modules/sales/inbox-actions.ts +359 -0
  180. package/src/modules/sales/lib/messageObjectPreviews.ts +54 -4
  181. package/src/modules/sales/message-objects.ts +44 -2
  182. package/src/modules/sales/widgets/messages/SalesDocumentMessageDetail.tsx +72 -34
  183. package/src/modules/sales/widgets/messages/SalesDocumentMessagePreview.tsx +1 -1
  184. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +7 -29
  185. package/src/modules/staff/backend/staff/my-availability/page.tsx +14 -0
  186. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +8 -30
  187. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +28 -7
  188. package/src/modules/staff/backend/staff/team-roles/[id]/edit/page.tsx +12 -0
  189. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +12 -0
  190. package/src/modules/staff/components/TeamForm.tsx +3 -0
  191. package/src/modules/staff/components/TeamRoleForm.tsx +3 -0
  192. package/src/modules/staff/lib/messageObjectPreviews.ts +133 -2
  193. package/src/modules/staff/message-objects.ts +79 -8
  194. package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js +0 -51
  195. package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js.map +0 -7
  196. package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js +0 -35
  197. package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js.map +0 -7
  198. package/dist/modules/customers/widgets/messages/index.js +0 -7
  199. package/dist/modules/customers/widgets/messages/index.js.map +0 -7
  200. package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js +0 -51
  201. package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js.map +0 -7
  202. package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js +0 -34
  203. package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js.map +0 -7
  204. package/dist/modules/staff/widgets/messages/index.js +0 -7
  205. package/dist/modules/staff/widgets/messages/index.js.map +0 -7
  206. package/src/modules/customers/widgets/messages/CustomerMessageObjectDetail.tsx +0 -57
  207. package/src/modules/customers/widgets/messages/CustomerMessageObjectPreview.tsx +0 -49
  208. package/src/modules/customers/widgets/messages/index.ts +0 -2
  209. package/src/modules/staff/widgets/messages/StaffMessageObjectDetail.tsx +0 -57
  210. package/src/modules/staff/widgets/messages/StaffMessageObjectPreview.tsx +0 -44
  211. package/src/modules/staff/widgets/messages/index.ts +0 -2
@@ -6,28 +6,50 @@ import { Page, PageBody } from "@open-mercato/ui/backend/Page";
6
6
  import { Button } from "@open-mercato/ui/primitives/button";
7
7
  import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
8
8
  import { flash } from "@open-mercato/ui/backend/FlashMessages";
9
+ import { LoadingMessage, ErrorMessage } from "@open-mercato/ui/backend/detail";
9
10
  import { useT } from "@open-mercato/shared/lib/i18n/context";
11
+ import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuardedMutation";
10
12
  import { ArrowLeft, Copy, CheckCircle } from "lucide-react";
11
13
  const LANGUAGE_KEYS = ["en", "de", "es", "pl"];
12
14
  function InboxSettingsPage() {
13
15
  const t = useT();
16
+ const { runMutation } = useGuardedMutation({
17
+ contextId: "inbox-ops-settings"
18
+ });
14
19
  const languageOptions = LANGUAGE_KEYS.map((key) => ({
15
20
  value: key,
16
21
  label: t(`inbox_ops.settings.language_${key}`, key)
17
22
  }));
18
23
  const [settings, setSettings] = React.useState(null);
19
24
  const [isLoading, setIsLoading] = React.useState(true);
25
+ const [error, setError] = React.useState(null);
20
26
  const [copied, setCopied] = React.useState(false);
21
27
  const [isSavingLanguage, setIsSavingLanguage] = React.useState(false);
22
28
  React.useEffect(() => {
29
+ let cancelled = false;
23
30
  async function load() {
24
31
  setIsLoading(true);
25
- const result = await apiCall("/api/inbox_ops/settings");
26
- if (result?.ok && result.result?.settings) setSettings(result.result.settings);
27
- setIsLoading(false);
32
+ setError(null);
33
+ try {
34
+ const result = await apiCall("/api/inbox_ops/settings");
35
+ if (!cancelled) {
36
+ if (result?.ok && result.result?.settings) {
37
+ setSettings(result.result.settings);
38
+ } else {
39
+ setError(t("inbox_ops.settings.load_failed", "Failed to load settings"));
40
+ }
41
+ }
42
+ } catch {
43
+ if (!cancelled) setError(t("inbox_ops.settings.load_failed", "Failed to load settings"));
44
+ } finally {
45
+ if (!cancelled) setIsLoading(false);
46
+ }
28
47
  }
29
48
  load();
30
- }, []);
49
+ return () => {
50
+ cancelled = true;
51
+ };
52
+ }, [t]);
31
53
  const handleCopy = React.useCallback(() => {
32
54
  if (settings?.inboxAddress) {
33
55
  navigator.clipboard.writeText(settings.inboxAddress);
@@ -38,9 +60,12 @@ function InboxSettingsPage() {
38
60
  const handleLanguageChange = React.useCallback(async (event) => {
39
61
  const workingLanguage = event.target.value;
40
62
  setIsSavingLanguage(true);
41
- const result = await apiCall("/api/inbox_ops/settings", {
42
- method: "PATCH",
43
- body: JSON.stringify({ workingLanguage })
63
+ const result = await runMutation({
64
+ operation: () => apiCall("/api/inbox_ops/settings", {
65
+ method: "PATCH",
66
+ body: JSON.stringify({ workingLanguage })
67
+ }),
68
+ context: {}
44
69
  });
45
70
  if (result?.ok && result.result?.ok) {
46
71
  setSettings((prev) => prev ? { ...prev, workingLanguage: result.result.settings.workingLanguage } : prev);
@@ -49,22 +74,19 @@ function InboxSettingsPage() {
49
74
  flash(t("inbox_ops.settings.language_save_failed", "Failed to update working language"), "error");
50
75
  }
51
76
  setIsSavingLanguage(false);
52
- }, [t]);
77
+ }, [t, runMutation]);
53
78
  return /* @__PURE__ */ jsxs(Page, { children: [
54
79
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 px-3 py-3 md:px-6 md:py-4", children: [
55
- /* @__PURE__ */ jsx(Link, { href: "/backend/inbox-ops", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", children: /* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4" }) }) }),
80
+ /* @__PURE__ */ jsx(Link, { href: "/backend/inbox-ops", children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", children: /* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4" }) }) }),
56
81
  /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold", children: t("inbox_ops.settings.title", "Inbox Settings") })
57
82
  ] }),
58
- /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx("div", { className: "max-w-lg", children: isLoading ? /* @__PURE__ */ jsxs("div", { className: "animate-pulse space-y-4", children: [
59
- /* @__PURE__ */ jsx("div", { className: "h-6 bg-muted rounded w-1/3" }),
60
- /* @__PURE__ */ jsx("div", { className: "h-12 bg-muted rounded" })
61
- ] }) : settings ? /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
83
+ /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx("div", { className: "max-w-lg", children: isLoading ? /* @__PURE__ */ jsx(LoadingMessage, { label: t("inbox_ops.settings.loading", "Loading settings...") }) : error ? /* @__PURE__ */ jsx(ErrorMessage, { label: error }) : settings ? /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
62
84
  /* @__PURE__ */ jsxs("div", { children: [
63
85
  /* @__PURE__ */ jsx("label", { className: "text-sm font-medium text-foreground", children: t("inbox_ops.settings.forwarding_address", "Forwarding Address") }),
64
86
  /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: t("inbox_ops.settings.forwarding_hint", "Forward email threads to this address to create proposals") }),
65
87
  /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
66
88
  /* @__PURE__ */ jsx("div", { className: "flex-1 bg-muted rounded-lg px-4 py-3", children: /* @__PURE__ */ jsx("code", { className: "text-sm font-mono", children: settings.inboxAddress }) }),
67
- /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className: "h-11 md:h-9", onClick: handleCopy, children: [
89
+ /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "h-11 md:h-9", onClick: handleCopy, children: [
68
90
  copied ? /* @__PURE__ */ jsx(CheckCircle, { className: "h-4 w-4 text-green-600" }) : /* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" }),
69
91
  /* @__PURE__ */ jsx("span", { className: "ml-1", children: copied ? t("inbox_ops.settings.copied", "Copied") : t("inbox_ops.settings.copy", "Copy") })
70
92
  ] })
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { ArrowLeft, Copy, CheckCircle } from 'lucide-react'\n\nconst LANGUAGE_KEYS = ['en', 'de', 'es', 'pl'] as const\n\nexport default function InboxSettingsPage() {\n const t = useT()\n\n const languageOptions = LANGUAGE_KEYS.map((key) => ({\n value: key,\n label: t(`inbox_ops.settings.language_${key}` as never, key),\n }))\n const [settings, setSettings] = React.useState<{ inboxAddress?: string; isActive?: boolean; workingLanguage?: string } | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [copied, setCopied] = React.useState(false)\n const [isSavingLanguage, setIsSavingLanguage] = React.useState(false)\n\n React.useEffect(() => {\n async function load() {\n setIsLoading(true)\n const result = await apiCall<{ settings: { inboxAddress?: string; isActive?: boolean; workingLanguage?: string } | null }>('/api/inbox_ops/settings')\n if (result?.ok && result.result?.settings) setSettings(result.result.settings)\n setIsLoading(false)\n }\n load()\n }, [])\n\n const handleCopy = React.useCallback(() => {\n if (settings?.inboxAddress) {\n navigator.clipboard.writeText(settings.inboxAddress)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n }\n }, [settings])\n\n const handleLanguageChange = React.useCallback(async (event: React.ChangeEvent<HTMLSelectElement>) => {\n const workingLanguage = event.target.value\n setIsSavingLanguage(true)\n const result = await apiCall<{ ok: boolean; settings: { workingLanguage: string } }>('/api/inbox_ops/settings', {\n method: 'PATCH',\n body: JSON.stringify({ workingLanguage }),\n })\n if (result?.ok && result.result?.ok) {\n setSettings((prev) => prev ? { ...prev, workingLanguage: result.result!.settings.workingLanguage } : prev)\n flash(t('inbox_ops.settings.language_saved', 'Working language updated'), 'success')\n } else {\n flash(t('inbox_ops.settings.language_save_failed', 'Failed to update working language'), 'error')\n }\n setIsSavingLanguage(false)\n }, [t])\n\n return (\n <Page>\n <div className=\"flex items-center gap-3 px-3 py-3 md:px-6 md:py-4\">\n <Link href=\"/backend/inbox-ops\">\n <Button variant=\"ghost\" size=\"sm\"><ArrowLeft className=\"h-4 w-4\" /></Button>\n </Link>\n <h1 className=\"text-lg font-semibold\">{t('inbox_ops.settings.title', 'Inbox Settings')}</h1>\n </div>\n\n <PageBody>\n <div className=\"max-w-lg\">\n {isLoading ? (\n <div className=\"animate-pulse space-y-4\">\n <div className=\"h-6 bg-muted rounded w-1/3\" />\n <div className=\"h-12 bg-muted rounded\" />\n </div>\n ) : settings ? (\n <div className=\"space-y-6\">\n <div>\n <label className=\"text-sm font-medium text-foreground\">\n {t('inbox_ops.settings.forwarding_address', 'Forwarding Address')}\n </label>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {t('inbox_ops.settings.forwarding_hint', 'Forward email threads to this address to create proposals')}\n </p>\n <div className=\"mt-2 flex items-center gap-2\">\n <div className=\"flex-1 bg-muted rounded-lg px-4 py-3\">\n <code className=\"text-sm font-mono\">{settings.inboxAddress}</code>\n </div>\n <Button variant=\"outline\" size=\"sm\" className=\"h-11 md:h-9\" onClick={handleCopy}>\n {copied ? <CheckCircle className=\"h-4 w-4 text-green-600\" /> : <Copy className=\"h-4 w-4\" />}\n <span className=\"ml-1\">{copied ? t('inbox_ops.settings.copied', 'Copied') : t('inbox_ops.settings.copy', 'Copy')}</span>\n </Button>\n </div>\n </div>\n\n <div>\n <label className=\"text-sm font-medium text-foreground\">{t('inbox_ops.settings.status', 'Status')}</label>\n <div className=\"mt-1\">\n <span className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${\n settings.isActive ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'\n }`}>\n {settings.isActive ? t('inbox_ops.settings.active', 'Active') : t('inbox_ops.settings.inactive', 'Inactive')}\n </span>\n </div>\n </div>\n\n <div>\n <label htmlFor=\"working-language\" className=\"text-sm font-medium text-foreground\">\n {t('inbox_ops.settings.working_language', 'Working Language')}\n </label>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {t('inbox_ops.settings.working_language_hint', 'AI summaries and action descriptions will be generated in this language')}\n </p>\n <select\n id=\"working-language\"\n className=\"mt-2 block w-full sm:w-[200px] h-11 md:h-9 rounded-md border border-input bg-background px-3 text-sm\"\n value={settings.workingLanguage || 'en'}\n onChange={handleLanguageChange}\n disabled={isSavingLanguage}\n >\n {languageOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('inbox_ops.settings.not_found', 'No inbox settings found. Settings are created when a new tenant is provisioned.')}</p>\n )}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { ArrowLeft, Copy, CheckCircle } from 'lucide-react'\n\nconst LANGUAGE_KEYS = ['en', 'de', 'es', 'pl'] as const\n\nexport default function InboxSettingsPage() {\n const t = useT()\n const { runMutation } = useGuardedMutation<Record<string, unknown>>({\n contextId: 'inbox-ops-settings',\n })\n\n const languageOptions = LANGUAGE_KEYS.map((key) => ({\n value: key,\n label: t(`inbox_ops.settings.language_${key}` as never, key),\n }))\n const [settings, setSettings] = React.useState<{ inboxAddress?: string; isActive?: boolean; workingLanguage?: string } | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [copied, setCopied] = React.useState(false)\n const [isSavingLanguage, setIsSavingLanguage] = React.useState(false)\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setIsLoading(true)\n setError(null)\n try {\n const result = await apiCall<{ settings: { inboxAddress?: string; isActive?: boolean; workingLanguage?: string } | null }>('/api/inbox_ops/settings')\n if (!cancelled) {\n if (result?.ok && result.result?.settings) {\n setSettings(result.result.settings)\n } else {\n setError(t('inbox_ops.settings.load_failed', 'Failed to load settings'))\n }\n }\n } catch {\n if (!cancelled) setError(t('inbox_ops.settings.load_failed', 'Failed to load settings'))\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [t])\n\n const handleCopy = React.useCallback(() => {\n if (settings?.inboxAddress) {\n navigator.clipboard.writeText(settings.inboxAddress)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n }\n }, [settings])\n\n const handleLanguageChange = React.useCallback(async (event: React.ChangeEvent<HTMLSelectElement>) => {\n const workingLanguage = event.target.value\n setIsSavingLanguage(true)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean; settings: { workingLanguage: string } }>('/api/inbox_ops/settings', {\n method: 'PATCH',\n body: JSON.stringify({ workingLanguage }),\n }),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n setSettings((prev) => prev ? { ...prev, workingLanguage: result.result!.settings.workingLanguage } : prev)\n flash(t('inbox_ops.settings.language_saved', 'Working language updated'), 'success')\n } else {\n flash(t('inbox_ops.settings.language_save_failed', 'Failed to update working language'), 'error')\n }\n setIsSavingLanguage(false)\n }, [t, runMutation])\n\n return (\n <Page>\n <div className=\"flex items-center gap-3 px-3 py-3 md:px-6 md:py-4\">\n <Link href=\"/backend/inbox-ops\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\"><ArrowLeft className=\"h-4 w-4\" /></Button>\n </Link>\n <h1 className=\"text-lg font-semibold\">{t('inbox_ops.settings.title', 'Inbox Settings')}</h1>\n </div>\n\n <PageBody>\n <div className=\"max-w-lg\">\n {isLoading ? (\n <LoadingMessage label={t('inbox_ops.settings.loading', 'Loading settings...')} />\n ) : error ? (\n <ErrorMessage label={error} />\n ) : settings ? (\n <div className=\"space-y-6\">\n <div>\n <label className=\"text-sm font-medium text-foreground\">\n {t('inbox_ops.settings.forwarding_address', 'Forwarding Address')}\n </label>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {t('inbox_ops.settings.forwarding_hint', 'Forward email threads to this address to create proposals')}\n </p>\n <div className=\"mt-2 flex items-center gap-2\">\n <div className=\"flex-1 bg-muted rounded-lg px-4 py-3\">\n <code className=\"text-sm font-mono\">{settings.inboxAddress}</code>\n </div>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"h-11 md:h-9\" onClick={handleCopy}>\n {copied ? <CheckCircle className=\"h-4 w-4 text-green-600\" /> : <Copy className=\"h-4 w-4\" />}\n <span className=\"ml-1\">{copied ? t('inbox_ops.settings.copied', 'Copied') : t('inbox_ops.settings.copy', 'Copy')}</span>\n </Button>\n </div>\n </div>\n\n <div>\n <label className=\"text-sm font-medium text-foreground\">{t('inbox_ops.settings.status', 'Status')}</label>\n <div className=\"mt-1\">\n <span className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${\n settings.isActive ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'\n }`}>\n {settings.isActive ? t('inbox_ops.settings.active', 'Active') : t('inbox_ops.settings.inactive', 'Inactive')}\n </span>\n </div>\n </div>\n\n <div>\n <label htmlFor=\"working-language\" className=\"text-sm font-medium text-foreground\">\n {t('inbox_ops.settings.working_language', 'Working Language')}\n </label>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {t('inbox_ops.settings.working_language_hint', 'AI summaries and action descriptions will be generated in this language')}\n </p>\n <select\n id=\"working-language\"\n className=\"mt-2 block w-full sm:w-[200px] h-11 md:h-9 rounded-md border border-input bg-background px-3 text-sm\"\n value={settings.workingLanguage || 'en'}\n onChange={handleLanguageChange}\n disabled={isSavingLanguage}\n >\n {languageOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('inbox_ops.settings.not_found', 'No inbox settings found. Settings are created when a new tenant is provisioned.')}</p>\n )}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -3,11 +3,11 @@ const metadata = {
3
3
  requireFeatures: ["inbox_ops.settings.manage"],
4
4
  pageTitle: "Inbox Settings",
5
5
  pageTitleKey: "inbox_ops.nav.settings",
6
- pageGroup: "InboxOps",
6
+ pageGroup: "AI Inbox Actions",
7
7
  pageGroupKey: "inbox_ops.nav.group",
8
8
  navHidden: true,
9
9
  breadcrumb: [
10
- { label: "InboxOps", labelKey: "inbox_ops.nav.group", href: "/backend/inbox-ops" },
10
+ { label: "AI Inbox Actions", labelKey: "inbox_ops.nav.group", href: "/backend/inbox-ops" },
11
11
  { label: "Settings", labelKey: "inbox_ops.nav.settings" }
12
12
  ]
13
13
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/inbox_ops/backend/inbox-ops/settings/page.meta.ts"],
4
- "sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['inbox_ops.settings.manage'],\n pageTitle: 'Inbox Settings',\n pageTitleKey: 'inbox_ops.nav.settings',\n pageGroup: 'InboxOps',\n pageGroupKey: 'inbox_ops.nav.group',\n navHidden: true,\n breadcrumb: [\n { label: 'InboxOps', labelKey: 'inbox_ops.nav.group', href: '/backend/inbox-ops' },\n { label: 'Settings', labelKey: 'inbox_ops.nav.settings' },\n ],\n}\n"],
5
- "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,2BAA2B;AAAA,EAC7C,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,YAAY;AAAA,IACV,EAAE,OAAO,YAAY,UAAU,uBAAuB,MAAM,qBAAqB;AAAA,IACjF,EAAE,OAAO,YAAY,UAAU,yBAAyB;AAAA,EAC1D;AACF;",
4
+ "sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['inbox_ops.settings.manage'],\n pageTitle: 'Inbox Settings',\n pageTitleKey: 'inbox_ops.nav.settings',\n pageGroup: 'AI Inbox Actions',\n pageGroupKey: 'inbox_ops.nav.group',\n navHidden: true,\n breadcrumb: [\n { label: 'AI Inbox Actions', labelKey: 'inbox_ops.nav.group', href: '/backend/inbox-ops' },\n { label: 'Settings', labelKey: 'inbox_ops.nav.settings' },\n ],\n}\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,2BAA2B;AAAA,EAC7C,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,YAAY;AAAA,IACV,EAAE,OAAO,oBAAoB,UAAU,uBAAuB,MAAM,qBAAqB;AAAA,IACzF,EAAE,OAAO,YAAY,UAAU,yBAAyB;AAAA,EAC1D;AACF;",
6
6
  "names": []
7
7
  }
@@ -17,6 +17,44 @@ import {
17
17
  Activity,
18
18
  ShoppingBag
19
19
  } from "lucide-react";
20
+ import { hasContactNameIssue } from "../../lib/contactValidation.js";
21
+ function useDiscrepancyDescriptions() {
22
+ const t = useT();
23
+ const translations = {
24
+ "inbox_ops.discrepancy.desc.no_channel": t("inbox_ops.discrepancy.desc.no_channel", "No sales channel available. Create a channel in Sales settings before accepting this order."),
25
+ "inbox_ops.discrepancy.desc.no_currency": t("inbox_ops.discrepancy.desc.no_currency", "No currency could be resolved for this order. Set a currency code or configure a sales channel with a default currency."),
26
+ "inbox_ops.discrepancy.desc.product_not_matched": t("inbox_ops.discrepancy.desc.product_not_matched", "Product could not be matched to any catalog product"),
27
+ "inbox_ops.discrepancy.desc.no_matching_contact": t("inbox_ops.discrepancy.desc.no_matching_contact", "No matching contact found"),
28
+ "inbox_ops.discrepancy.desc.draft_reply_no_contact": t("inbox_ops.discrepancy.desc.draft_reply_no_contact", "Draft reply target has no matching contact. Create the contact first."),
29
+ "inbox_ops.discrepancy.desc.duplicate_order_reference": t("inbox_ops.discrepancy.desc.duplicate_order_reference", "An order with this customer reference already exists")
30
+ };
31
+ return (description, foundValue) => {
32
+ const translated = translations[description];
33
+ if (!translated) return description;
34
+ if (foundValue && (description === "inbox_ops.discrepancy.desc.product_not_matched" || description === "inbox_ops.discrepancy.desc.no_matching_contact")) {
35
+ return `${translated}: ${foundValue}`;
36
+ }
37
+ return translated;
38
+ };
39
+ }
40
+ function useActionDescriptionResolver() {
41
+ const t = useT();
42
+ return (description, payload) => {
43
+ if (!description.startsWith("inbox_ops.action.desc.")) return description;
44
+ const name = payload.name || payload.contactName || "";
45
+ const email = payload.email || payload.emailAddress || "";
46
+ const title = payload.title || "";
47
+ const toName = payload.toName || payload.to || "";
48
+ const subject = payload.subject || "";
49
+ const translations = {
50
+ "inbox_ops.action.desc.create_contact": t("inbox_ops.action.desc.create_contact", "Create contact for {name} ({email})").replace("{name}", name).replace("{email}", email),
51
+ "inbox_ops.action.desc.link_contact": t("inbox_ops.action.desc.link_contact", "Link {name} ({email}) to existing contact").replace("{name}", name).replace("{email}", email),
52
+ "inbox_ops.action.desc.create_product": t("inbox_ops.action.desc.create_product", 'Create catalog product "{title}"').replace("{title}", title),
53
+ "inbox_ops.action.desc.draft_reply": t("inbox_ops.action.desc.draft_reply", "Draft reply to {toName}: {subject}").replace("{toName}", toName).replace("{subject}", subject)
54
+ };
55
+ return translations[description] || description;
56
+ };
57
+ }
20
58
  const ACTION_TYPE_ICONS = {
21
59
  create_order: Package,
22
60
  create_quote: FileText,
@@ -157,14 +195,16 @@ function ActionCard({
157
195
  onReject,
158
196
  onRetry,
159
197
  onEdit,
160
- translatedDescription
198
+ translatedDescription,
199
+ resolveDiscrepancyDescription
161
200
  }) {
162
201
  const t = useT();
163
202
  const Icon = ACTION_TYPE_ICONS[action.actionType] || Package;
164
203
  const label = actionTypeLabels[action.actionType] || action.actionType;
204
+ const resolveActionDescription = useActionDescriptionResolver();
165
205
  const actionDiscrepancies = discrepancies.filter((d) => d.actionId === action.id && !d.resolved);
166
206
  const hasBlockingDiscrepancies = actionDiscrepancies.some((d) => d.severity === "error");
167
- const displayDescription = translatedDescription || action.description;
207
+ const displayDescription = translatedDescription || resolveActionDescription(action.description, action.payload);
168
208
  if (action.status === "executed") {
169
209
  return /* @__PURE__ */ jsxs("div", { className: "border rounded-lg p-3 md:p-4 bg-green-50 dark:bg-green-950/20", children: [
170
210
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
@@ -173,8 +213,7 @@ function ActionCard({
173
213
  ] }),
174
214
  /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: displayDescription }),
175
215
  action.createdEntityId && /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxs("span", { className: "text-xs text-green-600", children: [
176
- "Created ",
177
- action.createdEntityType,
216
+ t("inbox_ops.action.created_entity", "Created {type}").replace("{type}", action.createdEntityType || ""),
178
217
  " \xB7 ",
179
218
  action.executedAt && new Date(action.executedAt).toLocaleString()
180
219
  ] }) })
@@ -203,6 +242,7 @@ function ActionCard({
203
242
  /* @__PURE__ */ jsxs(
204
243
  Button,
205
244
  {
245
+ type: "button",
206
246
  size: "sm",
207
247
  className: "h-11 md:h-9",
208
248
  onClick: () => onRetry(action.id),
@@ -215,6 +255,7 @@ function ActionCard({
215
255
  /* @__PURE__ */ jsxs(
216
256
  Button,
217
257
  {
258
+ type: "button",
218
259
  variant: "outline",
219
260
  size: "sm",
220
261
  className: "h-11 md:h-9",
@@ -228,6 +269,7 @@ function ActionCard({
228
269
  /* @__PURE__ */ jsxs(
229
270
  Button,
230
271
  {
272
+ type: "button",
231
273
  variant: "outline",
232
274
  size: "sm",
233
275
  className: "h-11 md:h-9",
@@ -241,6 +283,7 @@ function ActionCard({
241
283
  ] })
242
284
  ] });
243
285
  }
286
+ const hasNameIssue = hasContactNameIssue(action);
244
287
  return /* @__PURE__ */ jsxs("div", { className: "border rounded-lg p-3 md:p-4", children: [
245
288
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
246
289
  /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5 text-primary flex-shrink-0" }),
@@ -253,28 +296,35 @@ function ActionCard({
253
296
  actionDiscrepancies.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-3 space-y-1", children: actionDiscrepancies.map((d) => /* @__PURE__ */ jsxs("div", { className: `flex items-start gap-2 text-xs rounded px-2 py-1.5 ${d.severity === "error" ? "bg-red-50 text-red-700 dark:bg-red-950/20" : "bg-yellow-50 text-yellow-700 dark:bg-yellow-950/20"}`, children: [
254
297
  /* @__PURE__ */ jsx(AlertTriangle, { className: "h-3 w-3 mt-0.5 flex-shrink-0" }),
255
298
  /* @__PURE__ */ jsxs("div", { children: [
256
- /* @__PURE__ */ jsx("span", { children: d.description }),
299
+ /* @__PURE__ */ jsx("span", { children: resolveDiscrepancyDescription ? resolveDiscrepancyDescription(d.description, d.foundValue) : d.description }),
257
300
  (d.expectedValue || d.foundValue) && /* @__PURE__ */ jsxs("div", { className: "mt-0.5 text-[11px] opacity-80", children: [
258
301
  d.expectedValue && /* @__PURE__ */ jsxs("span", { children: [
259
- "Expected: ",
302
+ t("inbox_ops.discrepancy.expected", "Expected"),
303
+ ": ",
260
304
  d.expectedValue
261
305
  ] }),
262
306
  d.expectedValue && d.foundValue && /* @__PURE__ */ jsx("span", { children: " \xB7 " }),
263
307
  d.foundValue && /* @__PURE__ */ jsxs("span", { children: [
264
- "Found: ",
308
+ t("inbox_ops.discrepancy.found", "Found"),
309
+ ": ",
265
310
  d.foundValue
266
311
  ] })
267
312
  ] })
268
313
  ] })
269
314
  ] }, d.id)) }),
315
+ hasNameIssue && /* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-start gap-2 text-xs rounded px-2 py-1.5 bg-amber-50 text-amber-700 dark:bg-amber-950/20 dark:text-amber-300", children: [
316
+ /* @__PURE__ */ jsx(AlertTriangle, { className: "h-3 w-3 mt-0.5 flex-shrink-0" }),
317
+ /* @__PURE__ */ jsx("span", { children: action.actionType === "link_contact" ? t("inbox_ops.contact.link_name_missing_warning", "Contact name is missing. Please edit and provide a name before accepting.") : t("inbox_ops.contact.name_missing_warning", "First and last name could not be extracted. Please edit before accepting.") })
318
+ ] }),
270
319
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
271
- /* @__PURE__ */ jsx("div", { title: hasBlockingDiscrepancies ? t("inbox_ops.action.accept_blocked", "Resolve errors before accepting") : void 0, children: /* @__PURE__ */ jsxs(
320
+ /* @__PURE__ */ jsx("div", { title: hasNameIssue ? action.actionType === "link_contact" ? t("inbox_ops.contact.link_name_missing_warning", "Contact name is missing. Please edit and provide a name before accepting.") : t("inbox_ops.contact.name_missing_warning", "First and last name could not be extracted. Please edit before accepting.") : hasBlockingDiscrepancies ? t("inbox_ops.action.accept_blocked", "Resolve errors before accepting") : void 0, children: /* @__PURE__ */ jsxs(
272
321
  Button,
273
322
  {
323
+ type: "button",
274
324
  size: "sm",
275
325
  className: "h-11 md:h-9",
276
326
  onClick: () => onAccept(action.id),
277
- disabled: hasBlockingDiscrepancies,
327
+ disabled: hasBlockingDiscrepancies || hasNameIssue,
278
328
  children: [
279
329
  /* @__PURE__ */ jsx(CheckCircle, { className: "h-4 w-4 mr-1" }),
280
330
  t("inbox_ops.action.accept", "Accept")
@@ -284,6 +334,7 @@ function ActionCard({
284
334
  /* @__PURE__ */ jsxs(
285
335
  Button,
286
336
  {
337
+ type: "button",
287
338
  variant: "outline",
288
339
  size: "sm",
289
340
  className: "h-11 md:h-9",
@@ -297,6 +348,7 @@ function ActionCard({
297
348
  /* @__PURE__ */ jsxs(
298
349
  Button,
299
350
  {
351
+ type: "button",
300
352
  variant: "outline",
301
353
  size: "sm",
302
354
  className: "h-11 md:h-9",
@@ -313,6 +365,9 @@ function ActionCard({
313
365
  export {
314
366
  ActionCard,
315
367
  ConfidenceBadge,
316
- useActionTypeLabels
368
+ hasContactNameIssue,
369
+ useActionDescriptionResolver,
370
+ useActionTypeLabels,
371
+ useDiscrepancyDescriptions
317
372
  };
318
373
  //# sourceMappingURL=ActionCard.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/inbox_ops/components/proposals/ActionCard.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n CheckCircle,\n XCircle,\n Pencil,\n AlertTriangle,\n RefreshCw,\n Package,\n FileText,\n MessageSquare,\n Truck,\n UserPlus,\n Link2,\n Activity,\n ShoppingBag,\n} from 'lucide-react'\nimport type { ActionDetail, DiscrepancyDetail } from './types'\n\nconst ACTION_TYPE_ICONS: Record<string, React.ElementType> = {\n create_order: Package,\n create_quote: FileText,\n update_order: Package,\n update_shipment: Truck,\n create_contact: UserPlus,\n create_product: ShoppingBag,\n link_contact: Link2,\n log_activity: Activity,\n draft_reply: MessageSquare,\n}\n\nexport function useActionTypeLabels(): Record<string, string> {\n const t = useT()\n return {\n create_order: t('inbox_ops.action_type.create_order', 'Create Sales Order'),\n create_quote: t('inbox_ops.action_type.create_quote', 'Create Quote'),\n update_order: t('inbox_ops.action_type.update_order', 'Update Order'),\n update_shipment: t('inbox_ops.action_type.update_shipment', 'Update Shipment'),\n create_contact: t('inbox_ops.action_type.create_contact', 'Create Contact'),\n create_product: t('inbox_ops.action_type.create_product', 'Create Product'),\n link_contact: t('inbox_ops.action_type.link_contact', 'Link Contact'),\n log_activity: t('inbox_ops.action_type.log_activity', 'Log Activity'),\n draft_reply: t('inbox_ops.action_type.draft_reply', 'Draft Reply'),\n }\n}\n\nexport function ConfidenceBadge({ value }: { value: string }) {\n const num = parseFloat(value)\n const pct = Math.round(num * 100)\n const color = num >= 0.8 ? 'text-green-600' : num >= 0.6 ? 'text-yellow-600' : 'text-red-600'\n const bgColor = num >= 0.8 ? 'bg-green-200' : num >= 0.6 ? 'bg-yellow-200' : 'bg-red-200'\n const width = Math.round(num * 100)\n return (\n <div className=\"flex items-center gap-2\">\n <span className={`text-sm font-medium ${color}`}>{pct}%</span>\n <div className=\"w-24 h-2 bg-muted rounded-full overflow-hidden\">\n <div className={`h-full ${bgColor} rounded-full`} style={{ width: `${width}%` }} />\n </div>\n </div>\n )\n}\n\nfunction OrderPreview({ payload }: { payload: Record<string, unknown> }) {\n const t = useT()\n const lineItems = (payload.lineItems as Record<string, unknown>[]) || []\n const customerName = (payload.customerName as string) || ''\n const currencyCode = (payload.currencyCode as string) || ''\n const notes = (payload.notes as string) || ''\n const deliveryDate = (payload.requestedDeliveryDate as string) || ''\n\n return (\n <div className=\"mt-2 space-y-2 text-xs\">\n {customerName && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.customer', 'Customer')}:</span>\n <span>{customerName}</span>\n {typeof payload.customerEmail === 'string' && <span className=\"text-muted-foreground\">({payload.customerEmail})</span>}\n </div>\n )}\n {lineItems.length > 0 && (\n <div className=\"border rounded overflow-hidden\">\n <table className=\"w-full text-xs\">\n <thead>\n <tr className=\"bg-muted/50\">\n <th className=\"text-left px-2 py-1 font-medium\">{t('inbox_ops.preview.product', 'Product')}</th>\n <th className=\"text-right px-2 py-1 font-medium\">{t('inbox_ops.preview.qty', 'Qty')}</th>\n <th className=\"text-right px-2 py-1 font-medium\">{t('inbox_ops.preview.price', 'Price')}</th>\n </tr>\n </thead>\n <tbody>\n {lineItems.map((item, index) => (\n <tr key={index} className=\"border-t\">\n <td className=\"px-2 py-1\">{(item.productName as string) || '\u2014'}</td>\n <td className=\"px-2 py-1 text-right\">{String(item.quantity ?? '')}</td>\n <td className=\"px-2 py-1 text-right\">{item.unitPrice ? `${item.unitPrice} ${currencyCode}` : '\u2014'}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n {(deliveryDate || notes) && (\n <div className=\"flex flex-wrap gap-3\">\n {deliveryDate && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.delivery', 'Delivery')}:</span>\n <span>{deliveryDate}</span>\n </div>\n )}\n {notes && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.notes', 'Notes')}:</span>\n <span className=\"truncate max-w-[200px]\">{notes}</span>\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n\nfunction ProductPreview({ payload }: { payload: Record<string, unknown> }) {\n const t = useT()\n const title = (payload.title as string) || ''\n const sku = (payload.sku as string) || ''\n const unitPrice = (payload.unitPrice as string) || ''\n const currencyCode = (payload.currencyCode as string) || ''\n const kind = (payload.kind as string) || 'product'\n\n return (\n <div className=\"mt-2 space-y-1 text-xs\">\n {title && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.product_title', 'Title')}:</span>\n <span className=\"font-medium\">{title}</span>\n </div>\n )}\n <div className=\"flex flex-wrap gap-3\">\n {sku && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.sku', 'SKU')}:</span>\n <span>{sku}</span>\n </div>\n )}\n {unitPrice && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.price', 'Price')}:</span>\n <span>{unitPrice}{currencyCode ? ` ${currencyCode}` : ''}</span>\n </div>\n )}\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.edit_dialog.kind', 'Kind')}:</span>\n <span>{kind}</span>\n </div>\n </div>\n </div>\n )\n}\n\nexport function ActionCard({\n action,\n discrepancies,\n actionTypeLabels,\n onAccept,\n onReject,\n onRetry,\n onEdit,\n translatedDescription,\n}: {\n action: ActionDetail\n discrepancies: DiscrepancyDetail[]\n actionTypeLabels: Record<string, string>\n onAccept: (id: string) => void\n onReject: (id: string) => void\n onRetry: (id: string) => void\n onEdit: (action: ActionDetail) => void\n translatedDescription?: string\n}) {\n const t = useT()\n const Icon = ACTION_TYPE_ICONS[action.actionType] || Package\n const label = actionTypeLabels[action.actionType] || action.actionType\n\n const actionDiscrepancies = discrepancies.filter((d) => d.actionId === action.id && !d.resolved)\n const hasBlockingDiscrepancies = actionDiscrepancies.some((d) => d.severity === 'error')\n const displayDescription = translatedDescription || action.description\n\n if (action.status === 'executed') {\n return (\n <div className=\"border rounded-lg p-3 md:p-4 bg-green-50 dark:bg-green-950/20\">\n <div className=\"flex items-center gap-2 mb-2\">\n <CheckCircle className=\"h-5 w-5 text-green-600 flex-shrink-0\" />\n <span className=\"text-sm font-medium\">{label}</span>\n </div>\n <p className=\"text-sm text-muted-foreground\">{displayDescription}</p>\n {action.createdEntityId && (\n <div className=\"mt-2\">\n <span className=\"text-xs text-green-600\">\n Created {action.createdEntityType} \u00B7 {action.executedAt && new Date(action.executedAt).toLocaleString()}\n </span>\n </div>\n )}\n </div>\n )\n }\n\n if (action.status === 'rejected') {\n return (\n <div className=\"border rounded-lg p-3 md:p-4 bg-muted/50 opacity-60\">\n <div className=\"flex items-center gap-2 mb-2\">\n <XCircle className=\"h-5 w-5 text-muted-foreground flex-shrink-0\" />\n <span className=\"text-sm font-medium line-through\">{label}</span>\n <span className=\"text-xs text-muted-foreground\">{t('inbox_ops.status.rejected', 'Rejected')}</span>\n </div>\n <p className=\"text-sm text-muted-foreground\">{displayDescription}</p>\n </div>\n )\n }\n\n if (action.status === 'failed') {\n return (\n <div className=\"border rounded-lg p-3 md:p-4 bg-red-50 dark:bg-red-950/20\">\n <div className=\"flex items-center gap-2 mb-2\">\n <AlertTriangle className=\"h-5 w-5 text-red-600 flex-shrink-0\" />\n <span className=\"text-sm font-medium\">{label}</span>\n <span className=\"text-xs text-red-600\">{t('inbox_ops.extraction_failed', 'Failed')}</span>\n </div>\n <p className=\"text-sm text-muted-foreground\">{displayDescription}</p>\n {action.executionError && (\n <p className=\"text-xs text-red-600 mt-1\">{action.executionError}</p>\n )}\n <div className=\"mt-3 flex items-center gap-2\">\n <Button\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onRetry(action.id)}\n >\n <RefreshCw className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.retry', 'Retry')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onEdit(action)}\n >\n <Pencil className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.edit', 'Edit')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onReject(action.id)}\n >\n <XCircle className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.reject', 'Reject')}\n </Button>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"border rounded-lg p-3 md:p-4\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Icon className=\"h-5 w-5 text-primary flex-shrink-0\" />\n <span className=\"text-sm font-medium\">{label}</span>\n <ConfidenceBadge value={action.confidence} />\n </div>\n <p className=\"text-sm text-foreground/80 mb-2\">{displayDescription}</p>\n\n {(action.actionType === 'create_order' || action.actionType === 'create_quote') && (\n <OrderPreview payload={action.payload} />\n )}\n\n {action.actionType === 'create_product' && (\n <ProductPreview payload={action.payload} />\n )}\n\n {actionDiscrepancies.length > 0 && (\n <div className=\"mb-3 space-y-1\">\n {actionDiscrepancies.map((d) => (\n <div key={d.id} className={`flex items-start gap-2 text-xs rounded px-2 py-1.5 ${\n d.severity === 'error' ? 'bg-red-50 text-red-700 dark:bg-red-950/20' : 'bg-yellow-50 text-yellow-700 dark:bg-yellow-950/20'\n }`}>\n <AlertTriangle className=\"h-3 w-3 mt-0.5 flex-shrink-0\" />\n <div>\n <span>{d.description}</span>\n {(d.expectedValue || d.foundValue) && (\n <div className=\"mt-0.5 text-[11px] opacity-80\">\n {d.expectedValue && <span>Expected: {d.expectedValue}</span>}\n {d.expectedValue && d.foundValue && <span> \u00B7 </span>}\n {d.foundValue && <span>Found: {d.foundValue}</span>}\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n <div className=\"flex items-center gap-2\">\n <div title={hasBlockingDiscrepancies ? t('inbox_ops.action.accept_blocked', 'Resolve errors before accepting') : undefined}>\n <Button\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onAccept(action.id)}\n disabled={hasBlockingDiscrepancies}\n >\n <CheckCircle className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.accept', 'Accept')}\n </Button>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onEdit(action)}\n >\n <Pencil className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.edit', 'Edit')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onReject(action.id)}\n >\n <XCircle className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.reject', 'Reject')}\n </Button>\n </div>\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n CheckCircle,\n XCircle,\n Pencil,\n AlertTriangle,\n RefreshCw,\n Package,\n FileText,\n MessageSquare,\n Truck,\n UserPlus,\n Link2,\n Activity,\n ShoppingBag,\n} from 'lucide-react'\nimport type { ActionDetail, DiscrepancyDetail } from './types'\nimport { hasContactNameIssue } from '../../lib/contactValidation'\n\nexport { hasContactNameIssue }\n\n/**\n * Resolves discrepancy description i18n keys stored in the database.\n * Falls back to the raw description string for legacy data or LLM-generated descriptions.\n */\nexport function useDiscrepancyDescriptions(): (description: string, foundValue?: string | null) => string {\n const t = useT()\n const translations: Record<string, string> = {\n 'inbox_ops.discrepancy.desc.no_channel': t('inbox_ops.discrepancy.desc.no_channel', 'No sales channel available. Create a channel in Sales settings before accepting this order.'),\n 'inbox_ops.discrepancy.desc.no_currency': t('inbox_ops.discrepancy.desc.no_currency', 'No currency could be resolved for this order. Set a currency code or configure a sales channel with a default currency.'),\n 'inbox_ops.discrepancy.desc.product_not_matched': t('inbox_ops.discrepancy.desc.product_not_matched', 'Product could not be matched to any catalog product'),\n 'inbox_ops.discrepancy.desc.no_matching_contact': t('inbox_ops.discrepancy.desc.no_matching_contact', 'No matching contact found'),\n 'inbox_ops.discrepancy.desc.draft_reply_no_contact': t('inbox_ops.discrepancy.desc.draft_reply_no_contact', 'Draft reply target has no matching contact. Create the contact first.'),\n 'inbox_ops.discrepancy.desc.duplicate_order_reference': t('inbox_ops.discrepancy.desc.duplicate_order_reference', 'An order with this customer reference already exists'),\n }\n return (description: string, foundValue?: string | null) => {\n const translated = translations[description]\n if (!translated) return description\n if (foundValue && (description === 'inbox_ops.discrepancy.desc.product_not_matched' || description === 'inbox_ops.discrepancy.desc.no_matching_contact')) {\n return `${translated}: ${foundValue}`\n }\n return translated\n }\n}\n\n/**\n * Resolves action description i18n keys stored in the database.\n * Auto-generated actions store keys like `inbox_ops.action.desc.create_contact`;\n * LLM-generated actions store plain text which is returned as-is.\n */\nexport function useActionDescriptionResolver(): (description: string, payload: Record<string, unknown>) => string {\n const t = useT()\n return (description: string, payload: Record<string, unknown>) => {\n if (!description.startsWith('inbox_ops.action.desc.')) return description\n const name = (payload.name as string) || (payload.contactName as string) || ''\n const email = (payload.email as string) || (payload.emailAddress as string) || ''\n const title = (payload.title as string) || ''\n const toName = (payload.toName as string) || (payload.to as string) || ''\n const subject = (payload.subject as string) || ''\n const translations: Record<string, string> = {\n 'inbox_ops.action.desc.create_contact': t('inbox_ops.action.desc.create_contact', 'Create contact for {name} ({email})')\n .replace('{name}', name).replace('{email}', email),\n 'inbox_ops.action.desc.link_contact': t('inbox_ops.action.desc.link_contact', 'Link {name} ({email}) to existing contact')\n .replace('{name}', name).replace('{email}', email),\n 'inbox_ops.action.desc.create_product': t('inbox_ops.action.desc.create_product', 'Create catalog product \"{title}\"')\n .replace('{title}', title),\n 'inbox_ops.action.desc.draft_reply': t('inbox_ops.action.desc.draft_reply', 'Draft reply to {toName}: {subject}')\n .replace('{toName}', toName).replace('{subject}', subject),\n }\n return translations[description] || description\n }\n}\n\nconst ACTION_TYPE_ICONS: Record<string, React.ElementType> = {\n create_order: Package,\n create_quote: FileText,\n update_order: Package,\n update_shipment: Truck,\n create_contact: UserPlus,\n create_product: ShoppingBag,\n link_contact: Link2,\n log_activity: Activity,\n draft_reply: MessageSquare,\n}\n\nexport function useActionTypeLabels(): Record<string, string> {\n const t = useT()\n return {\n create_order: t('inbox_ops.action_type.create_order', 'Create Sales Order'),\n create_quote: t('inbox_ops.action_type.create_quote', 'Create Quote'),\n update_order: t('inbox_ops.action_type.update_order', 'Update Order'),\n update_shipment: t('inbox_ops.action_type.update_shipment', 'Update Shipment'),\n create_contact: t('inbox_ops.action_type.create_contact', 'Create Contact'),\n create_product: t('inbox_ops.action_type.create_product', 'Create Product'),\n link_contact: t('inbox_ops.action_type.link_contact', 'Link Contact'),\n log_activity: t('inbox_ops.action_type.log_activity', 'Log Activity'),\n draft_reply: t('inbox_ops.action_type.draft_reply', 'Draft Reply'),\n }\n}\n\nexport function ConfidenceBadge({ value }: { value: string }) {\n const num = parseFloat(value)\n const pct = Math.round(num * 100)\n const color = num >= 0.8 ? 'text-green-600' : num >= 0.6 ? 'text-yellow-600' : 'text-red-600'\n const bgColor = num >= 0.8 ? 'bg-green-200' : num >= 0.6 ? 'bg-yellow-200' : 'bg-red-200'\n const width = Math.round(num * 100)\n return (\n <div className=\"flex items-center gap-2\">\n <span className={`text-sm font-medium ${color}`}>{pct}%</span>\n <div className=\"w-24 h-2 bg-muted rounded-full overflow-hidden\">\n <div className={`h-full ${bgColor} rounded-full`} style={{ width: `${width}%` }} />\n </div>\n </div>\n )\n}\n\nfunction OrderPreview({ payload }: { payload: Record<string, unknown> }) {\n const t = useT()\n const lineItems = (payload.lineItems as Record<string, unknown>[]) || []\n const customerName = (payload.customerName as string) || ''\n const currencyCode = (payload.currencyCode as string) || ''\n const notes = (payload.notes as string) || ''\n const deliveryDate = (payload.requestedDeliveryDate as string) || ''\n\n return (\n <div className=\"mt-2 space-y-2 text-xs\">\n {customerName && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.customer', 'Customer')}:</span>\n <span>{customerName}</span>\n {typeof payload.customerEmail === 'string' && <span className=\"text-muted-foreground\">({payload.customerEmail})</span>}\n </div>\n )}\n {lineItems.length > 0 && (\n <div className=\"border rounded overflow-hidden\">\n <table className=\"w-full text-xs\">\n <thead>\n <tr className=\"bg-muted/50\">\n <th className=\"text-left px-2 py-1 font-medium\">{t('inbox_ops.preview.product', 'Product')}</th>\n <th className=\"text-right px-2 py-1 font-medium\">{t('inbox_ops.preview.qty', 'Qty')}</th>\n <th className=\"text-right px-2 py-1 font-medium\">{t('inbox_ops.preview.price', 'Price')}</th>\n </tr>\n </thead>\n <tbody>\n {lineItems.map((item, index) => (\n <tr key={index} className=\"border-t\">\n <td className=\"px-2 py-1\">{(item.productName as string) || '\u2014'}</td>\n <td className=\"px-2 py-1 text-right\">{String(item.quantity ?? '')}</td>\n <td className=\"px-2 py-1 text-right\">{item.unitPrice ? `${item.unitPrice} ${currencyCode}` : '\u2014'}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n {(deliveryDate || notes) && (\n <div className=\"flex flex-wrap gap-3\">\n {deliveryDate && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.delivery', 'Delivery')}:</span>\n <span>{deliveryDate}</span>\n </div>\n )}\n {notes && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.notes', 'Notes')}:</span>\n <span className=\"truncate max-w-[200px]\">{notes}</span>\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n\nfunction ProductPreview({ payload }: { payload: Record<string, unknown> }) {\n const t = useT()\n const title = (payload.title as string) || ''\n const sku = (payload.sku as string) || ''\n const unitPrice = (payload.unitPrice as string) || ''\n const currencyCode = (payload.currencyCode as string) || ''\n const kind = (payload.kind as string) || 'product'\n\n return (\n <div className=\"mt-2 space-y-1 text-xs\">\n {title && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.product_title', 'Title')}:</span>\n <span className=\"font-medium\">{title}</span>\n </div>\n )}\n <div className=\"flex flex-wrap gap-3\">\n {sku && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.sku', 'SKU')}:</span>\n <span>{sku}</span>\n </div>\n )}\n {unitPrice && (\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.preview.price', 'Price')}:</span>\n <span>{unitPrice}{currencyCode ? ` ${currencyCode}` : ''}</span>\n </div>\n )}\n <div className=\"flex gap-1\">\n <span className=\"text-muted-foreground\">{t('inbox_ops.edit_dialog.kind', 'Kind')}:</span>\n <span>{kind}</span>\n </div>\n </div>\n </div>\n )\n}\n\nexport function ActionCard({\n action,\n discrepancies,\n actionTypeLabels,\n onAccept,\n onReject,\n onRetry,\n onEdit,\n translatedDescription,\n resolveDiscrepancyDescription,\n}: {\n action: ActionDetail\n discrepancies: DiscrepancyDetail[]\n actionTypeLabels: Record<string, string>\n onAccept: (id: string) => void\n onReject: (id: string) => void\n onRetry: (id: string) => void\n onEdit: (action: ActionDetail) => void\n translatedDescription?: string\n resolveDiscrepancyDescription?: (description: string, foundValue?: string | null) => string\n}) {\n const t = useT()\n const Icon = ACTION_TYPE_ICONS[action.actionType] || Package\n const label = actionTypeLabels[action.actionType] || action.actionType\n const resolveActionDescription = useActionDescriptionResolver()\n\n const actionDiscrepancies = discrepancies.filter((d) => d.actionId === action.id && !d.resolved)\n const hasBlockingDiscrepancies = actionDiscrepancies.some((d) => d.severity === 'error')\n const displayDescription = translatedDescription || resolveActionDescription(action.description, action.payload)\n\n if (action.status === 'executed') {\n return (\n <div className=\"border rounded-lg p-3 md:p-4 bg-green-50 dark:bg-green-950/20\">\n <div className=\"flex items-center gap-2 mb-2\">\n <CheckCircle className=\"h-5 w-5 text-green-600 flex-shrink-0\" />\n <span className=\"text-sm font-medium\">{label}</span>\n </div>\n <p className=\"text-sm text-muted-foreground\">{displayDescription}</p>\n {action.createdEntityId && (\n <div className=\"mt-2\">\n <span className=\"text-xs text-green-600\">\n {t('inbox_ops.action.created_entity', 'Created {type}').replace('{type}', action.createdEntityType || '')} \u00B7 {action.executedAt && new Date(action.executedAt).toLocaleString()}\n </span>\n </div>\n )}\n </div>\n )\n }\n\n if (action.status === 'rejected') {\n return (\n <div className=\"border rounded-lg p-3 md:p-4 bg-muted/50 opacity-60\">\n <div className=\"flex items-center gap-2 mb-2\">\n <XCircle className=\"h-5 w-5 text-muted-foreground flex-shrink-0\" />\n <span className=\"text-sm font-medium line-through\">{label}</span>\n <span className=\"text-xs text-muted-foreground\">{t('inbox_ops.status.rejected', 'Rejected')}</span>\n </div>\n <p className=\"text-sm text-muted-foreground\">{displayDescription}</p>\n </div>\n )\n }\n\n if (action.status === 'failed') {\n return (\n <div className=\"border rounded-lg p-3 md:p-4 bg-red-50 dark:bg-red-950/20\">\n <div className=\"flex items-center gap-2 mb-2\">\n <AlertTriangle className=\"h-5 w-5 text-red-600 flex-shrink-0\" />\n <span className=\"text-sm font-medium\">{label}</span>\n <span className=\"text-xs text-red-600\">{t('inbox_ops.extraction_failed', 'Failed')}</span>\n </div>\n <p className=\"text-sm text-muted-foreground\">{displayDescription}</p>\n {action.executionError && (\n <p className=\"text-xs text-red-600 mt-1\">{action.executionError}</p>\n )}\n <div className=\"mt-3 flex items-center gap-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onRetry(action.id)}\n >\n <RefreshCw className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.retry', 'Retry')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onEdit(action)}\n >\n <Pencil className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.edit', 'Edit')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onReject(action.id)}\n >\n <XCircle className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.reject', 'Reject')}\n </Button>\n </div>\n </div>\n )\n }\n\n const hasNameIssue = hasContactNameIssue(action)\n\n return (\n <div className=\"border rounded-lg p-3 md:p-4\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Icon className=\"h-5 w-5 text-primary flex-shrink-0\" />\n <span className=\"text-sm font-medium\">{label}</span>\n <ConfidenceBadge value={action.confidence} />\n </div>\n <p className=\"text-sm text-foreground/80 mb-2\">{displayDescription}</p>\n\n {(action.actionType === 'create_order' || action.actionType === 'create_quote') && (\n <OrderPreview payload={action.payload} />\n )}\n\n {action.actionType === 'create_product' && (\n <ProductPreview payload={action.payload} />\n )}\n\n {actionDiscrepancies.length > 0 && (\n <div className=\"mb-3 space-y-1\">\n {actionDiscrepancies.map((d) => (\n <div key={d.id} className={`flex items-start gap-2 text-xs rounded px-2 py-1.5 ${\n d.severity === 'error' ? 'bg-red-50 text-red-700 dark:bg-red-950/20' : 'bg-yellow-50 text-yellow-700 dark:bg-yellow-950/20'\n }`}>\n <AlertTriangle className=\"h-3 w-3 mt-0.5 flex-shrink-0\" />\n <div>\n <span>{resolveDiscrepancyDescription ? resolveDiscrepancyDescription(d.description, d.foundValue) : d.description}</span>\n {(d.expectedValue || d.foundValue) && (\n <div className=\"mt-0.5 text-[11px] opacity-80\">\n {d.expectedValue && <span>{t('inbox_ops.discrepancy.expected', 'Expected')}: {d.expectedValue}</span>}\n {d.expectedValue && d.foundValue && <span> \u00B7 </span>}\n {d.foundValue && <span>{t('inbox_ops.discrepancy.found', 'Found')}: {d.foundValue}</span>}\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {hasNameIssue && (\n <div className=\"mb-3 flex items-start gap-2 text-xs rounded px-2 py-1.5 bg-amber-50 text-amber-700 dark:bg-amber-950/20 dark:text-amber-300\">\n <AlertTriangle className=\"h-3 w-3 mt-0.5 flex-shrink-0\" />\n <span>{action.actionType === 'link_contact'\n ? t('inbox_ops.contact.link_name_missing_warning', 'Contact name is missing. Please edit and provide a name before accepting.')\n : t('inbox_ops.contact.name_missing_warning', 'First and last name could not be extracted. Please edit before accepting.')\n }</span>\n </div>\n )}\n\n <div className=\"flex items-center gap-2\">\n <div title={\n hasNameIssue\n ? action.actionType === 'link_contact'\n ? t('inbox_ops.contact.link_name_missing_warning', 'Contact name is missing. Please edit and provide a name before accepting.')\n : t('inbox_ops.contact.name_missing_warning', 'First and last name could not be extracted. Please edit before accepting.')\n : hasBlockingDiscrepancies\n ? t('inbox_ops.action.accept_blocked', 'Resolve errors before accepting')\n : undefined\n }>\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onAccept(action.id)}\n disabled={hasBlockingDiscrepancies || hasNameIssue}\n >\n <CheckCircle className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.accept', 'Accept')}\n </Button>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onEdit(action)}\n >\n <Pencil className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.edit', 'Edit')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-11 md:h-9\"\n onClick={() => onReject(action.id)}\n >\n <XCircle className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.reject', 'Reject')}\n </Button>\n </div>\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }