@ixo/editor 3.0.0-beta.2 → 3.0.0-beta.4

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.
@@ -7759,7 +7759,7 @@ var ClaimsListSheet = ({
7759
7759
  setSurveyError(null);
7760
7760
  fetchClaims();
7761
7761
  };
7762
- const getClaimStatus3 = (paymentsStatus) => {
7762
+ const getClaimStatus2 = (paymentsStatus) => {
7763
7763
  if (!paymentsStatus) {
7764
7764
  return "pending";
7765
7765
  }
@@ -7815,7 +7815,7 @@ var ClaimsListSheet = ({
7815
7815
  }
7816
7816
  },
7817
7817
  /* @__PURE__ */ React63.createElement(Stack40, { gap: "md", h: "100%" }, /* @__PURE__ */ React63.createElement(BaseButton, { onClick: handleNewClaim, fullWidth: true }, "New Claim"), loading ? /* @__PURE__ */ React63.createElement(Stack40, { align: "center", justify: "center", style: { flex: 1 } }, /* @__PURE__ */ React63.createElement(Loader5, { size: "lg" }), /* @__PURE__ */ React63.createElement(Text39, { size: "sm", c: "dimmed" }, "Loading claims...")) : error ? /* @__PURE__ */ React63.createElement(Alert7, { color: "red", title: "Failed to load claims", icon: /* @__PURE__ */ React63.createElement(IconAlertCircle2, { size: 18 }) }, /* @__PURE__ */ React63.createElement(Text39, { size: "sm" }, error)) : claims.length === 0 ? /* @__PURE__ */ React63.createElement(Stack40, { align: "center", justify: "center", style: { flex: 1 } }, /* @__PURE__ */ React63.createElement(Text39, { size: "sm", c: "dimmed", ta: "center" }, 'No claims found. Click "New Claim" to submit your first claim.')) : /* @__PURE__ */ React63.createElement(Stack40, { gap: "xs" }, claims.map((claim) => {
7818
- const status = getClaimStatus3(claim.paymentsStatus);
7818
+ const status = getClaimStatus2(claim.paymentsStatus);
7819
7819
  return /* @__PURE__ */ React63.createElement(ListItemContainer, { key: claim.claimId, isChecked: false }, /* @__PURE__ */ React63.createElement(Stack40, { gap: 4, style: { flex: 1 } }, /* @__PURE__ */ React63.createElement(Text39, { size: "sm", fw: 500 }, "Claim #", claim.claimId), /* @__PURE__ */ React63.createElement(Text39, { size: "xs", c: "dimmed" }, "Submitted: ", formatDate(claim.submissionDate))), /* @__PURE__ */ React63.createElement(Text39, { size: "xs", fw: 500, c: getStatusColor5(status) }, status.toUpperCase()));
7820
7820
  })))
7821
7821
  ),
@@ -8783,6 +8783,89 @@ import { Group as Group21, Stack as Stack49, Text as Text49 } from "@mantine/cor
8783
8783
  // src/mantine/blocks/evaluator/flow/ClaimsList.tsx
8784
8784
  import React72, { useState as useState30, useEffect as useEffect27, useCallback as useCallback28, useMemo as useMemo31 } from "react";
8785
8785
  import { Paper as Paper7, CloseButton as CloseButton2, Title as Title5, Loader as Loader11, Stack as Stack48, Text as Text48, ActionIcon as ActionIcon8, Alert as Alert11, Badge as Badge8, Group as Group20, Button as Button8, Divider as Divider7, Tabs, ScrollArea, Box as Box24, Select as Select3 } from "@mantine/core";
8786
+
8787
+ // src/mantine/utils/claimStatus.ts
8788
+ var STATUS_META = {
8789
+ pending: { label: "Pending", color: "yellow", isTerminal: false },
8790
+ approved: { label: "Approved", color: "green", isTerminal: true },
8791
+ rejected: { label: "Rejected", color: "red", isTerminal: true },
8792
+ disputed: { label: "Disputed", color: "orange", isTerminal: false },
8793
+ invalidated: { label: "Invalidated", color: "gray", isTerminal: true },
8794
+ unknown: { label: "Unknown", color: "gray", isTerminal: false }
8795
+ };
8796
+ function asStatusInfo(key) {
8797
+ return { key, ...STATUS_META[key] };
8798
+ }
8799
+ function parseEnumStatus(value) {
8800
+ const numeric = typeof value === "number" ? value : Number(value);
8801
+ if (!Number.isFinite(numeric)) return null;
8802
+ switch (numeric) {
8803
+ case 0:
8804
+ return "pending";
8805
+ case 1:
8806
+ return "approved";
8807
+ case 2:
8808
+ return "rejected";
8809
+ case 3:
8810
+ return "disputed";
8811
+ case 4:
8812
+ return "invalidated";
8813
+ case -1:
8814
+ return "unknown";
8815
+ default:
8816
+ return null;
8817
+ }
8818
+ }
8819
+ function parseStringStatus(value) {
8820
+ const normalized = String(value || "").trim().toLowerCase();
8821
+ switch (normalized) {
8822
+ case "pending":
8823
+ return "pending";
8824
+ case "approved":
8825
+ return "approved";
8826
+ case "rejected":
8827
+ return "rejected";
8828
+ case "disputed":
8829
+ return "disputed";
8830
+ case "invalidated":
8831
+ return "invalidated";
8832
+ case "unknown":
8833
+ return "unknown";
8834
+ default:
8835
+ return null;
8836
+ }
8837
+ }
8838
+ function getClaimStatusInfo(claim) {
8839
+ const evaluationStatusKey = parseEnumStatus(claim?.evaluationByClaimId?.status);
8840
+ if (evaluationStatusKey) {
8841
+ return asStatusInfo(evaluationStatusKey);
8842
+ }
8843
+ const directEnumStatusKey = parseEnumStatus(claim?.status);
8844
+ if (directEnumStatusKey) {
8845
+ return asStatusInfo(directEnumStatusKey);
8846
+ }
8847
+ const directStringStatusKey = parseStringStatus(claim?.status);
8848
+ if (directStringStatusKey) {
8849
+ return asStatusInfo(directStringStatusKey);
8850
+ }
8851
+ const paymentsStatus = claim?.paymentsStatus;
8852
+ if (paymentsStatus?.approval === "PAID") {
8853
+ return asStatusInfo("approved");
8854
+ }
8855
+ if (paymentsStatus?.rejection === "PAID") {
8856
+ return asStatusInfo("rejected");
8857
+ }
8858
+ if (paymentsStatus?.evaluation === "PAID" || paymentsStatus?.submission === "PAID") {
8859
+ return asStatusInfo("pending");
8860
+ }
8861
+ return asStatusInfo("pending");
8862
+ }
8863
+ function isClaimEvaluated(claim) {
8864
+ const status = getClaimStatusInfo(claim);
8865
+ return status.key === "approved" || status.key === "rejected" || status.key === "invalidated";
8866
+ }
8867
+
8868
+ // src/mantine/blocks/evaluator/flow/ClaimsList.tsx
8786
8869
  import { IconAlertCircle as IconAlertCircle6, IconArrowRight as IconArrowRight2, IconRefresh, IconArrowLeft as IconArrowLeft3, IconFileText as IconFileText4, IconRobot as IconRobot3, IconChecklist as IconChecklist3 } from "@tabler/icons-react";
8787
8870
  import { Survey as Survey5, SurveyModel as SurveyModel5 } from "@ixo/surveys";
8788
8871
 
@@ -9558,19 +9641,7 @@ var ClaimsList = ({ collectionId, collectionName, deedId, adminAddress, onEvalua
9558
9641
  }, [selectedClaim, handlers, deedId, collectionId, adminAddress, evaluationResult, handleBackToList, onEvaluationComplete, editor, buildPaymentCoin]);
9559
9642
  const isClaimAlreadyEvaluated = useMemo31(() => {
9560
9643
  if (!selectedClaim) return false;
9561
- if ("status" in selectedClaim && selectedClaim.status) {
9562
- const status = String(selectedClaim.status).toLowerCase();
9563
- if (status === "approved" || status === "rejected") {
9564
- return true;
9565
- }
9566
- }
9567
- if ("paymentsStatus" in selectedClaim && selectedClaim.paymentsStatus) {
9568
- const paymentsStatus = selectedClaim.paymentsStatus;
9569
- if (paymentsStatus.approval === "PAID" || paymentsStatus.rejection === "PAID") {
9570
- return true;
9571
- }
9572
- }
9573
- return false;
9644
+ return isClaimEvaluated(selectedClaim);
9574
9645
  }, [selectedClaim]);
9575
9646
  return /* @__PURE__ */ React72.createElement(
9576
9647
  Paper7,
@@ -9691,35 +9762,7 @@ var ClaimListItem = ({ claim, onViewClaim }) => {
9691
9762
  };
9692
9763
  fetchUserProfile();
9693
9764
  }, [claim.agentDid]);
9694
- const getClaimStatus3 = (claim2) => {
9695
- if ("status" in claim2 && claim2.status) {
9696
- const status = String(claim2.status).toLowerCase();
9697
- switch (status) {
9698
- case "approved":
9699
- return { status: "Approved", color: "green" };
9700
- case "rejected":
9701
- return { status: "Rejected", color: "red" };
9702
- case "pending":
9703
- return { status: "Pending", color: "yellow" };
9704
- default:
9705
- return { status: "Unknown", color: "gray" };
9706
- }
9707
- }
9708
- if ("paymentsStatus" in claim2 && claim2.paymentsStatus) {
9709
- const paymentsStatus = claim2.paymentsStatus;
9710
- if (paymentsStatus.approval === "PAID") {
9711
- return { status: "Approved", color: "green" };
9712
- }
9713
- if (paymentsStatus.rejection === "PAID") {
9714
- return { status: "Rejected", color: "red" };
9715
- }
9716
- if (paymentsStatus.evaluation === "PAID" || paymentsStatus.submission === "PAID") {
9717
- return { status: "Pending", color: "yellow" };
9718
- }
9719
- }
9720
- return { status: "Pending", color: "yellow" };
9721
- };
9722
- const claimStatus = getClaimStatus3(claim);
9765
+ const claimStatus = getClaimStatusInfo(claim);
9723
9766
  const displayName = userProfile?.displayname || (claim.agentAddress ? `${claim.agentAddress.slice(0, 12)}...` : "Unknown");
9724
9767
  return /* @__PURE__ */ React72.createElement(
9725
9768
  "div",
@@ -9735,7 +9778,7 @@ var ClaimListItem = ({ claim, onViewClaim }) => {
9735
9778
  tabIndex: 0,
9736
9779
  style: { cursor: "pointer" }
9737
9780
  },
9738
- /* @__PURE__ */ React72.createElement(ListItemContainer, { isChecked: false }, /* @__PURE__ */ React72.createElement(Stack48, { gap: 4, style: { flex: 1 } }, /* @__PURE__ */ React72.createElement(Text48, { size: "sm", fw: 500 }, "Claim #", claim.claimId), /* @__PURE__ */ React72.createElement(Text48, { size: "xs", c: "dimmed" }, "Submitted: ", formatDate(claim.submissionDate || claim.submittedAt)), claim.agentDid && /* @__PURE__ */ React72.createElement(Group20, { gap: 4 }, /* @__PURE__ */ React72.createElement(Text48, { size: "xs", c: "dimmed" }, "Agent: ", loadingProfile ? "Loading..." : displayName), userProfile?.verified && /* @__PURE__ */ React72.createElement(Text48, { size: "xs", c: "blue", fw: 600, title: "Verified user" }, "\u2713"))), /* @__PURE__ */ React72.createElement(Stack48, { gap: 4, align: "flex-end" }, /* @__PURE__ */ React72.createElement(Badge8, { color: claimStatus.color, size: "sm" }, claimStatus.status), /* @__PURE__ */ React72.createElement(ActionIcon8, { variant: "subtle", size: "sm" }, /* @__PURE__ */ React72.createElement(IconArrowRight2, { size: 16 }))))
9781
+ /* @__PURE__ */ React72.createElement(ListItemContainer, { isChecked: false }, /* @__PURE__ */ React72.createElement(Stack48, { gap: 4, style: { flex: 1 } }, /* @__PURE__ */ React72.createElement(Text48, { size: "sm", fw: 500 }, "Claim #", claim.claimId), /* @__PURE__ */ React72.createElement(Text48, { size: "xs", c: "dimmed" }, "Submitted: ", formatDate(claim.submissionDate || claim.submittedAt)), claim.agentDid && /* @__PURE__ */ React72.createElement(Group20, { gap: 4 }, /* @__PURE__ */ React72.createElement(Text48, { size: "xs", c: "dimmed" }, "Agent: ", loadingProfile ? "Loading..." : displayName), userProfile?.verified && /* @__PURE__ */ React72.createElement(Text48, { size: "xs", c: "blue", fw: 600, title: "Verified user" }, "\u2713"))), /* @__PURE__ */ React72.createElement(Stack48, { gap: 4, align: "flex-end" }, /* @__PURE__ */ React72.createElement(Badge8, { color: claimStatus.color, size: "sm" }, claimStatus.label), /* @__PURE__ */ React72.createElement(ActionIcon8, { variant: "subtle", size: "sm" }, /* @__PURE__ */ React72.createElement(IconArrowRight2, { size: 16 }))))
9739
9782
  );
9740
9783
  };
9741
9784
 
@@ -25140,7 +25183,7 @@ var ACTION_COMMITMENT_PANEL_ID = "action-template-commitment-panel";
25140
25183
  var ActionTemplateView = ({ editor, block }) => {
25141
25184
  const panelId = `${ACTION_TEMPLATE_PANEL_ID}-${block.id}`;
25142
25185
  const assignmentPanelId = `${ACTION_ASSIGNMENT_PANEL_ID}-${block.id}`;
25143
- const { closePanel } = usePanelStore();
25186
+ const { closePanel, activePanel } = usePanelStore();
25144
25187
  const panelContent = useMemo85(() => /* @__PURE__ */ React237.createElement(TemplateConfig17, { editor, block }), [editor, block]);
25145
25188
  const assignmentPanelContent = useMemo85(
25146
25189
  () => /* @__PURE__ */ React237.createElement(
@@ -25161,6 +25204,7 @@ var ActionTemplateView = ({ editor, block }) => {
25161
25204
  [editor, block, closePanel]
25162
25205
  );
25163
25206
  const { open: openCommitment } = usePanel(commitmentPanelId, commitmentPanelContent);
25207
+ const isPanelOpenForBlock = activePanel === panelId || activePanel === assignmentPanelId || activePanel === commitmentPanelId;
25164
25208
  const actionType = block.props.actionType || "";
25165
25209
  const dueDate = block.props.ttlAbsoluteDueDate;
25166
25210
  const dueDateDisplay = dueDate ? formatDate(dueDate) : "";
@@ -25171,8 +25215,10 @@ var ActionTemplateView = ({ editor, block }) => {
25171
25215
  onClick: open,
25172
25216
  style: {
25173
25217
  padding: 20,
25174
- borderColor: "var(--mantine-color-accent-5, #2aeab3)",
25175
- background: "rgba(255, 255, 255, 0.02)"
25218
+ borderColor: isPanelOpenForBlock ? "#2AEAB3" : "var(--mantine-color-neutralColor-6)",
25219
+ background: "rgba(255, 255, 255, 0.02)",
25220
+ boxShadow: "none",
25221
+ transition: "border-color 140ms ease"
25176
25222
  }
25177
25223
  },
25178
25224
  /* @__PURE__ */ React237.createElement(Group85, { wrap: "nowrap", gap: 24, align: "center", style: { width: "100%" } }, /* @__PURE__ */ React237.createElement(Group85, { wrap: "nowrap", gap: 16, align: "center", style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React237.createElement(Box45, { style: { flexShrink: 0, width: 32, height: 32, display: "flex", alignItems: "center", justifyContent: "center" } }, getIcon("bolt", block.props.icon, "white", 24)), /* @__PURE__ */ React237.createElement(Stack155, { gap: 0, style: { flex: 1, minWidth: 0, overflow: "hidden" } }, /* @__PURE__ */ React237.createElement(Text132, { fw: 500, size: "md", c: "white", truncate: true, contentEditable: false, style: { letterSpacing: "0.16px", lineHeight: 1.5 } }, block.props.title || "Title of the action"), /* @__PURE__ */ React237.createElement(Text132, { size: "sm", c: "dimmed", truncate: true, contentEditable: false, style: { letterSpacing: "0.14px" } }, subtitle))), /* @__PURE__ */ React237.createElement(Stack155, { gap: 2, align: "flex-end", style: { flexShrink: 0, minWidth: 100 } }, /* @__PURE__ */ React237.createElement(Text132, { fw: 500, size: "md", c: "white", style: { letterSpacing: "0.16px", lineHeight: 1.5, textAlign: "right" } }, "Pending"), /* @__PURE__ */ React237.createElement(Group85, { gap: 4, justify: "flex-end" }, /* @__PURE__ */ React237.createElement(CommitmentDisplay, { block, onClick: openCommitment }), /* @__PURE__ */ React237.createElement(AssignmentDisplay, { onClick: openAssignment, block }))))
@@ -25219,7 +25265,7 @@ var ActionFlowView = ({ editor, block, isDisabled }) => {
25219
25265
  const disabled = isDisabled?.isDisabled === "disable";
25220
25266
  const [runtime] = useNodeRuntime(editor, block.id);
25221
25267
  const panelId = `action-flow-panel-${block.id}`;
25222
- const { closePanel } = usePanelStore();
25268
+ const { closePanel, activePanel } = usePanelStore();
25223
25269
  const actionType = block.props.actionType || "";
25224
25270
  const actionTypeUI = actionType ? getActionTypeUI(actionType) : void 0;
25225
25271
  const FlowDetailComponent = actionTypeUI?.flowDetailComponent;
@@ -25262,14 +25308,17 @@ var ActionFlowView = ({ editor, block, isDisabled }) => {
25262
25308
  [editor, block, closePanel]
25263
25309
  );
25264
25310
  const { open: openCommitment } = usePanel(commitmentPanelId, commitmentPanelContent);
25311
+ const isPanelOpenForBlock = activePanel === panelId || activePanel === commitmentPanelId;
25265
25312
  return /* @__PURE__ */ React238.createElement(
25266
25313
  BaseContainer,
25267
25314
  {
25268
25315
  onClick: open,
25269
25316
  style: {
25270
25317
  padding: 20,
25271
- borderColor: "var(--mantine-color-accent-5, #2aeab3)",
25272
- background: "rgba(255, 255, 255, 0.02)"
25318
+ borderColor: isPanelOpenForBlock ? "#2AEAB3" : "var(--mantine-color-neutralColor-6)",
25319
+ background: "rgba(255, 255, 255, 0.02)",
25320
+ boxShadow: "none",
25321
+ transition: "border-color 140ms ease"
25273
25322
  }
25274
25323
  },
25275
25324
  /* @__PURE__ */ React238.createElement(Group86, { wrap: "nowrap", gap: 24, align: "center", style: { width: "100%" } }, /* @__PURE__ */ React238.createElement(Group86, { wrap: "nowrap", gap: 16, align: "center", style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React238.createElement(Box46, { style: { flexShrink: 0, width: 32, height: 32, display: "flex", alignItems: "center", justifyContent: "center" } }, getIcon("bolt", block.props.icon, "white", 24)), /* @__PURE__ */ React238.createElement(Stack156, { gap: 0, style: { flex: 1, minWidth: 0, overflow: "hidden" } }, /* @__PURE__ */ React238.createElement(Text133, { fw: 500, size: "md", c: "white", truncate: true, contentEditable: false, style: { letterSpacing: "0.16px", lineHeight: 1.5 } }, block.props.title || "Title of the action"), /* @__PURE__ */ React238.createElement(Text133, { size: "sm", c: "dimmed", truncate: true, contentEditable: false, style: { letterSpacing: "0.14px" } }, dueDateDisplay || block.props.description || "Due Date"))), /* @__PURE__ */ React238.createElement(Stack156, { gap: 2, align: "flex-end", style: { flexShrink: 0, minWidth: 100 } }, /* @__PURE__ */ React238.createElement(Badge39, { size: "sm", variant: "light", color: getStatusColor4(runtimeState) }, statusLabel), /* @__PURE__ */ React238.createElement(Group86, { gap: 4, justify: "flex-end" }, /* @__PURE__ */ React238.createElement(CommitmentDisplay, { block, onClick: openCommitment }), /* @__PURE__ */ React238.createElement(AssignmentDisplay, { block, onClick: open }))))
@@ -27100,6 +27149,8 @@ var ClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime, isDisabl
27100
27149
  const [submitting, setSubmitting] = useState97(false);
27101
27150
  const [error, setError] = useState97(null);
27102
27151
  const [profilesByDid, setProfilesByDid] = useState97({});
27152
+ const [isServiceAgentAuthorized, setIsServiceAgentAuthorized] = useState97(false);
27153
+ const [authChecking, setAuthChecking] = useState97(true);
27103
27154
  const surveyModel = useMemo94(() => {
27104
27155
  if (!surveyJson) return null;
27105
27156
  const model = new SurveyModel10(surveyJson);
@@ -27171,6 +27222,50 @@ var ClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime, isDisabl
27171
27222
  mounted = false;
27172
27223
  };
27173
27224
  }, [claims, handlers, profilesByDid]);
27225
+ useEffect79(() => {
27226
+ let mounted = true;
27227
+ const checkServiceAgentAuthorization = async () => {
27228
+ if (!deedDid || !collectionId || !adminAddress || !actorDid) {
27229
+ if (mounted) {
27230
+ setIsServiceAgentAuthorized(false);
27231
+ setAuthChecking(false);
27232
+ }
27233
+ return;
27234
+ }
27235
+ if (typeof handlers.getUserRoles !== "function") {
27236
+ if (mounted) {
27237
+ setIsServiceAgentAuthorized(false);
27238
+ setAuthChecking(false);
27239
+ }
27240
+ return;
27241
+ }
27242
+ setAuthChecking(true);
27243
+ try {
27244
+ const roles = await handlers.getUserRoles({
27245
+ userAddress: actorDid,
27246
+ adminAddress,
27247
+ deedDid,
27248
+ collectionIds: [collectionId]
27249
+ });
27250
+ const role = roles?.find((r) => r.collectionId === collectionId)?.role || null;
27251
+ if (mounted) {
27252
+ setIsServiceAgentAuthorized(role === "SA" /* ServiceProvider */);
27253
+ }
27254
+ } catch {
27255
+ if (mounted) {
27256
+ setIsServiceAgentAuthorized(false);
27257
+ }
27258
+ } finally {
27259
+ if (mounted) {
27260
+ setAuthChecking(false);
27261
+ }
27262
+ }
27263
+ };
27264
+ checkServiceAgentAuthorization();
27265
+ return () => {
27266
+ mounted = false;
27267
+ };
27268
+ }, [handlers, actorDid, adminAddress, deedDid, collectionId]);
27174
27269
  const startSurvey = useCallback79(async () => {
27175
27270
  if (!deedDid) return;
27176
27271
  setLoadingSurvey(true);
@@ -27192,6 +27287,10 @@ var ClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime, isDisabl
27192
27287
  }, [handlers, deedDid]);
27193
27288
  const handleSurveyComplete = useCallback79(
27194
27289
  async (sender) => {
27290
+ if (authChecking || !isServiceAgentAuthorized) {
27291
+ setError("You need service agent authorization for this collection to submit claims.");
27292
+ return;
27293
+ }
27195
27294
  if (!adminAddress) {
27196
27295
  setError("Admin address could not be resolved for this collection");
27197
27296
  return;
@@ -27283,7 +27382,9 @@ var ClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime, isDisabl
27283
27382
  services,
27284
27383
  ucanManager,
27285
27384
  updateRuntime,
27286
- verifySignature
27385
+ verifySignature,
27386
+ authChecking,
27387
+ isServiceAgentAuthorized
27287
27388
  ]
27288
27389
  );
27289
27390
  useEffect79(() => {
@@ -27293,14 +27394,16 @@ var ClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime, isDisabl
27293
27394
  surveyModel.onComplete.remove(handleSurveyComplete);
27294
27395
  };
27295
27396
  }, [surveyModel, handleSurveyComplete]);
27296
- const getClaimStatus3 = (claim) => {
27297
- const payments = claim.paymentsStatus;
27298
- if (payments?.approval === "PAID") return { label: "Approved", color: "green" };
27299
- if (payments?.rejection === "PAID") return { label: "Rejected", color: "red" };
27300
- return { label: "Pending", color: "yellow" };
27301
- };
27302
- return /* @__PURE__ */ React247.createElement(Stack165, { gap: "md" }, /* @__PURE__ */ React247.createElement(Stack165, { gap: 2 }, /* @__PURE__ */ React247.createElement(Text140, { fw: 600 }, block?.props?.title || "Claim Action"), /* @__PURE__ */ React247.createElement(Text140, { size: "sm", c: "dimmed" }, block?.props?.description || "Submit a claim using the deed survey template.")), !deedDid || !collectionId ? /* @__PURE__ */ React247.createElement(Alert43, { color: "yellow", styles: actionAlertStyles }, "Configure DID and claim collection in template mode before running this action.") : /* @__PURE__ */ React247.createElement(React247.Fragment, null, /* @__PURE__ */ React247.createElement(Text140, { size: "xs", c: "dimmed" }, "Collection: ", collectionId), /* @__PURE__ */ React247.createElement(Button45, { leftSection: loadingSurvey ? /* @__PURE__ */ React247.createElement(Loader42, { size: 14 }) : /* @__PURE__ */ React247.createElement(IconPlayerPlay4, { size: 14 }), onClick: startSurvey, disabled: isDisabled || loadingSurvey || submitting }, loadingSurvey ? "Loading Survey..." : "Start New Claim"), loadingClaims ? /* @__PURE__ */ React247.createElement(Text140, { size: "xs", c: "dimmed" }, "Loading your claims...") : claims.length === 0 ? /* @__PURE__ */ React247.createElement(Text140, { size: "sm", c: "dimmed" }, "No claims submitted for this collection yet.") : /* @__PURE__ */ React247.createElement(Stack165, { gap: "xs" }, /* @__PURE__ */ React247.createElement(Text140, { size: "sm", fw: 600 }, "Your Claims"), claims.map((claim) => {
27303
- const status = getClaimStatus3(claim);
27397
+ return /* @__PURE__ */ React247.createElement(Stack165, { gap: "md" }, /* @__PURE__ */ React247.createElement(Stack165, { gap: 2 }, /* @__PURE__ */ React247.createElement(Text140, { fw: 600 }, block?.props?.title || "Claim Action"), /* @__PURE__ */ React247.createElement(Text140, { size: "sm", c: "dimmed" }, block?.props?.description || "Submit a claim using the deed survey template.")), !deedDid || !collectionId ? /* @__PURE__ */ React247.createElement(Alert43, { color: "yellow", styles: actionAlertStyles }, "Configure DID and claim collection in template mode before running this action.") : /* @__PURE__ */ React247.createElement(React247.Fragment, null, /* @__PURE__ */ React247.createElement(Text140, { size: "xs", c: "dimmed" }, "Collection: ", collectionId), /* @__PURE__ */ React247.createElement(
27398
+ Button45,
27399
+ {
27400
+ leftSection: loadingSurvey ? /* @__PURE__ */ React247.createElement(Loader42, { size: 14 }) : /* @__PURE__ */ React247.createElement(IconPlayerPlay4, { size: 14 }),
27401
+ onClick: startSurvey,
27402
+ disabled: isDisabled || loadingSurvey || submitting || authChecking || !isServiceAgentAuthorized || !adminAddress
27403
+ },
27404
+ loadingSurvey ? "Loading Survey..." : "Start New Claim"
27405
+ ), !authChecking && !isServiceAgentAuthorized && /* @__PURE__ */ React247.createElement(Alert43, { color: "yellow", styles: actionAlertStyles }, "You need service agent authorization for this collection to submit claims."), loadingClaims ? /* @__PURE__ */ React247.createElement(Text140, { size: "xs", c: "dimmed" }, "Loading your claims...") : claims.length === 0 ? /* @__PURE__ */ React247.createElement(Text140, { size: "sm", c: "dimmed" }, "No claims submitted for this collection yet.") : /* @__PURE__ */ React247.createElement(Stack165, { gap: "xs" }, /* @__PURE__ */ React247.createElement(Text140, { size: "sm", fw: 600 }, "Your Claims"), claims.map((claim) => {
27406
+ const status = getClaimStatusInfo(claim);
27304
27407
  const profile = profilesByDid[claim.agentDid];
27305
27408
  const displayName = profile?.displayname || claim.agentDid || claim.agentAddress;
27306
27409
  const avatarLabel = (profile?.displayname || claim.agentDid || claim.agentAddress || "?")[0]?.toUpperCase();
@@ -27325,7 +27428,7 @@ var ClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime, isDisabl
27325
27428
  }
27326
27429
  },
27327
27430
  profile?.avatarUrl ? null : avatarLabel
27328
- ), /* @__PURE__ */ React247.createElement(Stack165, { gap: 0, style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React247.createElement(Text140, { fw: 500, size: "md", truncate: true, style: { lineHeight: 1.5 } }, displayName), /* @__PURE__ */ React247.createElement(Text140, { size: "xs", c: "dimmed", truncate: true }, truncateAddress2(claim.agentAddress)))), /* @__PURE__ */ React247.createElement(Stack165, { gap: 0, align: "flex-end", style: { flexShrink: 0, minWidth: 80 } }, /* @__PURE__ */ React247.createElement(Text140, { fw: 500, size: "md", c: status.color === "green" ? "green" : status.color === "red" ? "red" : void 0, style: { lineHeight: 1.5 } }, status.color === "green" && /* @__PURE__ */ React247.createElement(IconCheck18, { size: 14, style: { verticalAlign: "middle", marginRight: 2 } }), status.label), /* @__PURE__ */ React247.createElement(Text140, { size: "xs", c: "dimmed" }, getTimeAgo2(claim.submissionDate || ""))));
27431
+ ), /* @__PURE__ */ React247.createElement(Stack165, { gap: 0, style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React247.createElement(Text140, { fw: 500, size: "md", truncate: true, style: { lineHeight: 1.5 } }, displayName), /* @__PURE__ */ React247.createElement(Text140, { size: "xs", c: "dimmed", truncate: true }, truncateAddress2(claim.agentAddress)))), /* @__PURE__ */ React247.createElement(Stack165, { gap: 0, align: "flex-end", style: { flexShrink: 0, minWidth: 80 } }, /* @__PURE__ */ React247.createElement(Text140, { fw: 500, size: "md", c: status.color, style: { lineHeight: 1.5 } }, status.key === "approved" && /* @__PURE__ */ React247.createElement(IconCheck18, { size: 14, style: { verticalAlign: "middle", marginRight: 2 } }), status.label), /* @__PURE__ */ React247.createElement(Text140, { size: "xs", c: "dimmed" }, getTimeAgo2(claim.submissionDate || ""))));
27329
27432
  }))), surveyModel && !loadingSurvey && /* @__PURE__ */ React247.createElement(Survey10, { model: surveyModel }), submitting && /* @__PURE__ */ React247.createElement(Group91, { gap: "xs" }, /* @__PURE__ */ React247.createElement(Loader42, { size: "xs" }), /* @__PURE__ */ React247.createElement(Text140, { size: "xs", c: "dimmed" }, "Submitting claim...")), error && /* @__PURE__ */ React247.createElement(Alert43, { color: "red", styles: actionAlertStyles }, error), runtime.error?.message && /* @__PURE__ */ React247.createElement(Alert43, { color: "red", styles: actionAlertStyles }, runtime.error.message));
27330
27433
  };
27331
27434
 
@@ -27481,12 +27584,6 @@ function truncateId(value, start = 8, end = 6) {
27481
27584
  if (value.length <= start + end + 3) return value;
27482
27585
  return `${value.slice(0, start)}...${value.slice(-end)}`;
27483
27586
  }
27484
- function getClaimStatus2(claim) {
27485
- const payments = claim.paymentsStatus;
27486
- if (payments?.approval === "PAID") return { label: "Approved", color: "green" };
27487
- if (payments?.rejection === "PAID") return { label: "Rejected", color: "red" };
27488
- return { label: "Pending", color: "yellow" };
27489
- }
27490
27587
  var EvaluateClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime, isDisabled }) => {
27491
27588
  const handlers = useBlocknoteHandlers();
27492
27589
  const services = useMemo96(() => buildServicesFromHandlers(handlers), [handlers]);
@@ -27542,7 +27639,7 @@ var EvaluateClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime,
27542
27639
  const filteredClaims = useMemo96(() => {
27543
27640
  if (activeFilter === "all") return claims;
27544
27641
  return claims.filter((claim) => {
27545
- const status = getClaimStatus2(claim).label.toLowerCase();
27642
+ const status = getClaimStatusInfo(claim).key;
27546
27643
  return status === activeFilter;
27547
27644
  });
27548
27645
  }, [claims, activeFilter]);
@@ -27727,8 +27824,7 @@ var EvaluateClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime,
27727
27824
  }, [selectedClaim, loadClaimDetail]);
27728
27825
  const isClaimAlreadyEvaluated = useMemo96(() => {
27729
27826
  if (!selectedClaim) return false;
27730
- const status = getClaimStatus2(selectedClaim).label;
27731
- return status === "Approved" || status === "Rejected";
27827
+ return isClaimEvaluated(selectedClaim);
27732
27828
  }, [selectedClaim]);
27733
27829
  const addPaymentRow = useCallback81(() => {
27734
27830
  setPaymentRows((prev) => [...prev, createPaymentRow2()]);
@@ -27769,7 +27865,7 @@ var EvaluateClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime,
27769
27865
  }
27770
27866
  setSubmitting(true);
27771
27867
  setError(null);
27772
- updateRuntime({ state: "running", error: void 0 });
27868
+ updateRuntime({ state: "running" });
27773
27869
  try {
27774
27870
  const capabilityId = deedDid;
27775
27871
  const outcome = await executeNode({
@@ -27842,8 +27938,7 @@ var EvaluateClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime,
27842
27938
  const message = err instanceof Error ? err.message : "Failed to evaluate claim";
27843
27939
  setError(message);
27844
27940
  updateRuntime({
27845
- state: "failed",
27846
- error: { message, at: Date.now() }
27941
+ state: "failed"
27847
27942
  });
27848
27943
  } finally {
27849
27944
  setSubmitting(false);
@@ -27874,7 +27969,7 @@ var EvaluateClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime,
27874
27969
  ]
27875
27970
  );
27876
27971
  if (selectedClaim) {
27877
- const claimStatus = getClaimStatus2(selectedClaim);
27972
+ const claimStatus = getClaimStatusInfo(selectedClaim);
27878
27973
  const selectedClaimProfile = profilesByDid[selectedClaim.agentDid];
27879
27974
  const selectedDisplayName = selectedClaimProfile?.displayname || selectedClaim.agentDid || selectedClaim.agentAddress;
27880
27975
  const selectedAvatarLabel = (selectedClaimProfile?.displayname || selectedClaim.agentDid || selectedClaim.agentAddress || "?")[0]?.toUpperCase();
@@ -27899,7 +27994,7 @@ var EvaluateClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime,
27899
27994
  }
27900
27995
  },
27901
27996
  selectedClaimProfile?.avatarUrl ? null : selectedAvatarLabel
27902
- ), /* @__PURE__ */ React249.createElement(Stack167, { gap: 0, style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React249.createElement(Text141, { fw: 500, size: "md", truncate: true }, selectedDisplayName), /* @__PURE__ */ React249.createElement(Text141, { size: "xs", c: "dimmed", truncate: true }, truncateAddress3(selectedClaim.agentAddress))), /* @__PURE__ */ React249.createElement(Stack167, { gap: 0, align: "flex-end", style: { flexShrink: 0 } }, /* @__PURE__ */ React249.createElement(Text141, { fw: 500, size: "md", c: claimStatus.color === "green" ? "green" : claimStatus.color === "red" ? "red" : void 0 }, claimStatus.color === "green" && /* @__PURE__ */ React249.createElement(IconCheck19, { size: 14, style: { verticalAlign: "middle", marginRight: 4 } }), claimStatus.label), /* @__PURE__ */ React249.createElement(Text141, { size: "xs", c: "dimmed" }, getTimeAgo3(selectedClaim.submissionDate || "")))), /* @__PURE__ */ React249.createElement(
27997
+ ), /* @__PURE__ */ React249.createElement(Stack167, { gap: 0, style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React249.createElement(Text141, { fw: 500, size: "md", truncate: true }, selectedDisplayName), /* @__PURE__ */ React249.createElement(Text141, { size: "xs", c: "dimmed", truncate: true }, truncateAddress3(selectedClaim.agentAddress))), /* @__PURE__ */ React249.createElement(Stack167, { gap: 0, align: "flex-end", style: { flexShrink: 0 } }, /* @__PURE__ */ React249.createElement(Text141, { fw: 500, size: "md", c: claimStatus.color }, claimStatus.key === "approved" && /* @__PURE__ */ React249.createElement(IconCheck19, { size: 14, style: { verticalAlign: "middle", marginRight: 4 } }), claimStatus.label), /* @__PURE__ */ React249.createElement(Text141, { size: "xs", c: "dimmed" }, getTimeAgo3(selectedClaim.submissionDate || "")))), /* @__PURE__ */ React249.createElement(
27903
27998
  Box49,
27904
27999
  {
27905
28000
  p: "sm",
@@ -27996,7 +28091,7 @@ var EvaluateClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime,
27996
28091
  }
27997
28092
  },
27998
28093
  "Reject"
27999
- )), error && /* @__PURE__ */ React249.createElement(Alert45, { color: "red", styles: actionAlertStyles }, error), runtime.error?.message && /* @__PURE__ */ React249.createElement(Alert45, { color: "red", styles: actionAlertStyles }, runtime.error.message));
28094
+ )), error && /* @__PURE__ */ React249.createElement(Alert45, { color: "red", styles: actionAlertStyles }, error));
28000
28095
  }
28001
28096
  const filterTabs = [
28002
28097
  { value: "all", label: "All" },
@@ -28019,7 +28114,7 @@ var EvaluateClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime,
28019
28114
  },
28020
28115
  /* @__PURE__ */ React249.createElement(Text141, { size: "sm", fw: 500, c: activeFilter === tab.value ? "white" : "dimmed" }, tab.label)
28021
28116
  ))), /* @__PURE__ */ React249.createElement(ActionIcon34, { variant: "subtle", color: "gray", size: "sm" }, /* @__PURE__ */ React249.createElement(IconFilter2, { size: 16 }))), loadingClaims && /* @__PURE__ */ React249.createElement(Group92, { gap: "xs", justify: "center", py: "md" }, /* @__PURE__ */ React249.createElement(Loader44, { size: "xs" }), /* @__PURE__ */ React249.createElement(Text141, { size: "xs", c: "dimmed" }, "Loading claims...")), !loadingClaims && filteredClaims.length === 0 && /* @__PURE__ */ React249.createElement(Text141, { size: "sm", c: "dimmed", ta: "center", py: "md" }, claims.length === 0 ? "No claims available for this collection." : `No ${activeFilter} claims found.`), filteredClaims.length > 0 && /* @__PURE__ */ React249.createElement(Stack167, { gap: 12 }, filteredClaims.map((claim) => {
28022
- const status = getClaimStatus2(claim);
28117
+ const status = getClaimStatusInfo(claim);
28023
28118
  const profile = profilesByDid[claim.agentDid];
28024
28119
  const displayName = profile?.displayname || claim.agentDid || claim.agentAddress;
28025
28120
  const avatarLabel = (profile?.displayname || claim.agentDid || claim.agentAddress || "?")[0]?.toUpperCase();
@@ -28044,7 +28139,7 @@ var EvaluateClaimFlowDetail = ({ inputs, editor, block, runtime, updateRuntime,
28044
28139
  }
28045
28140
  },
28046
28141
  profile?.avatarUrl ? null : avatarLabel
28047
- ), /* @__PURE__ */ React249.createElement(Stack167, { gap: 0, style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React249.createElement(Text141, { fw: 500, size: "md", truncate: true, style: { lineHeight: 1.5 } }, displayName), /* @__PURE__ */ React249.createElement(Text141, { size: "xs", c: "dimmed", truncate: true }, truncateAddress3(claim.agentAddress)))), /* @__PURE__ */ React249.createElement(Stack167, { gap: 0, align: "flex-end", style: { flexShrink: 0, minWidth: 80 } }, /* @__PURE__ */ React249.createElement(Text141, { fw: 500, size: "md", c: status.color === "green" ? "green" : status.color === "red" ? "red" : void 0, style: { lineHeight: 1.5 } }, status.color === "green" && /* @__PURE__ */ React249.createElement(IconCheck19, { size: 14, style: { verticalAlign: "middle", marginRight: 2 } }), status.label), /* @__PURE__ */ React249.createElement(Text141, { size: "xs", c: "dimmed" }, getTimeAgo3(claim.submissionDate || ""))));
28142
+ ), /* @__PURE__ */ React249.createElement(Stack167, { gap: 0, style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React249.createElement(Text141, { fw: 500, size: "md", truncate: true, style: { lineHeight: 1.5 } }, displayName), /* @__PURE__ */ React249.createElement(Text141, { size: "xs", c: "dimmed", truncate: true }, truncateAddress3(claim.agentAddress)))), /* @__PURE__ */ React249.createElement(Stack167, { gap: 0, align: "flex-end", style: { flexShrink: 0, minWidth: 80 } }, /* @__PURE__ */ React249.createElement(Text141, { fw: 500, size: "md", c: status.color, style: { lineHeight: 1.5 } }, status.key === "approved" && /* @__PURE__ */ React249.createElement(IconCheck19, { size: 14, style: { verticalAlign: "middle", marginRight: 2 } }), status.label), /* @__PURE__ */ React249.createElement(Text141, { size: "xs", c: "dimmed" }, getTimeAgo3(claim.submissionDate || ""))));
28048
28143
  }))), error && /* @__PURE__ */ React249.createElement(Alert45, { color: "red", styles: actionAlertStyles }, error), runtime.error?.message && /* @__PURE__ */ React249.createElement(Alert45, { color: "red", styles: actionAlertStyles }, runtime.error.message));
28049
28144
  };
28050
28145
 
@@ -28130,6 +28225,49 @@ var FormSubmitConfig = ({ inputs, onInputsChange }) => {
28130
28225
  import React251, { useCallback as useCallback83, useEffect as useEffect83, useMemo as useMemo97, useState as useState101 } from "react";
28131
28226
  import { Alert as Alert46, Loader as Loader45, Stack as Stack169, Text as Text143 } from "@mantine/core";
28132
28227
  import { Survey as Survey12, SurveyModel as SurveyModel12 } from "@ixo/surveys";
28228
+ function parsePrimarySkill(rawSkill) {
28229
+ const coerce = (candidate) => {
28230
+ if (!candidate || typeof candidate !== "object") return null;
28231
+ const cid = String(candidate.cid || "").trim();
28232
+ const name = String(candidate.name || "").trim();
28233
+ if (!cid) return null;
28234
+ return name ? { cid, name } : { cid };
28235
+ };
28236
+ if (!rawSkill) return null;
28237
+ if (typeof rawSkill === "object") {
28238
+ if (Array.isArray(rawSkill)) {
28239
+ for (const entry of rawSkill) {
28240
+ const skill = coerce(entry);
28241
+ if (skill) return skill;
28242
+ }
28243
+ return null;
28244
+ }
28245
+ return coerce(rawSkill);
28246
+ }
28247
+ if (typeof rawSkill === "string") {
28248
+ const trimmed = rawSkill.trim();
28249
+ if (!trimmed) return null;
28250
+ try {
28251
+ const parsed = JSON.parse(trimmed);
28252
+ return parsePrimarySkill(parsed);
28253
+ } catch {
28254
+ return null;
28255
+ }
28256
+ }
28257
+ return null;
28258
+ }
28259
+ function buildCompanionPrompt(params) {
28260
+ const answersJson = JSON.stringify(params.answers || {}, null, 2);
28261
+ return [
28262
+ "Use the skill with this form context.",
28263
+ `Skill name: ${params.skill.name || "(not provided)"}`,
28264
+ `Skill CID: ${params.skill.cid}`,
28265
+ `Action block title: ${params.blockTitle || "Form Submit Action"}`,
28266
+ `Action block description: ${params.blockDescription || "Complete the form to execute this action."}`,
28267
+ `Form answers JSON:
28268
+ ${answersJson}`
28269
+ ].join("\n");
28270
+ }
28133
28271
  var FormSubmitFlowDetail = ({ inputs, editor, block, runtime, updateRuntime, isDisabled }) => {
28134
28272
  const handlers = useBlocknoteHandlers();
28135
28273
  const services = useMemo97(() => buildServicesFromHandlers(handlers), [handlers]);
@@ -28198,6 +28336,18 @@ var FormSubmitFlowDetail = ({ inputs, editor, block, runtime, updateRuntime, isD
28198
28336
  setError(null);
28199
28337
  updateRuntime({ state: "running", error: void 0 });
28200
28338
  try {
28339
+ const skill = parsePrimarySkill(block?.props?.skill);
28340
+ if (skill && typeof handlers?.askCompanion === "function") {
28341
+ const prompt = buildCompanionPrompt({
28342
+ skill,
28343
+ blockTitle: String(block?.props?.title || ""),
28344
+ blockDescription: String(block?.props?.description || ""),
28345
+ answers: sender.data || {}
28346
+ });
28347
+ handlers.askCompanion(prompt).catch((askError) => {
28348
+ console.error("askCompanion failed during form submit execution", askError);
28349
+ });
28350
+ }
28201
28351
  const outcome = await executeNode({
28202
28352
  node: flowNode,
28203
28353
  actorDid,
@@ -28345,6 +28495,9 @@ var ActionBlockSpec = createReactBlockSpec21(
28345
28495
  requiresConfirmation: {
28346
28496
  default: ""
28347
28497
  },
28498
+ skill: {
28499
+ default: ""
28500
+ },
28348
28501
  conditions: {
28349
28502
  default: ""
28350
28503
  },
@@ -32165,4 +32318,4 @@ export {
32165
32318
  getExtraSlashMenuItems,
32166
32319
  useCreateIxoEditor
32167
32320
  };
32168
- //# sourceMappingURL=chunk-HHEGZUQF.mjs.map
32321
+ //# sourceMappingURL=chunk-36GMPLM6.mjs.map