@burdenoff/microfe-movethewheels 2026.930.5 → 2026.1010.2

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 (375) hide show
  1. package/dist/MoveTheWheelsRoot.js +177 -102
  2. package/dist/MoveTheWheelsRoutes.js +55 -11
  3. package/dist/_virtual/_rolldown/runtime.js +1 -1
  4. package/dist/components/ContainerEvidencePicker.js +143 -0
  5. package/dist/components/FreeTimeAgreementForm.js +496 -0
  6. package/dist/components/ReturnInstructionForm.js +108 -0
  7. package/dist/components/ReuseControls.js +91 -0
  8. package/dist/components/ReusePermissionForm.js +114 -0
  9. package/dist/components/ReuseProposalForm.js +455 -0
  10. package/dist/components/ReuseSourceFields.js +78 -0
  11. package/dist/components/consolidation/ConsolidationHistory.js +244 -0
  12. package/dist/components/consolidation/ConsolidationLotEditor.js +133 -0
  13. package/dist/components/consolidation/ConsolidationManifestWorkbench.js +143 -0
  14. package/dist/components/consolidation/ConsolidationPlanForm.js +172 -0
  15. package/dist/components/consolidation/ConsolidationPlanWorkbench.js +321 -0
  16. package/dist/components/consolidation/ConsolidationReportForm.js +94 -0
  17. package/dist/components/consolidation/ConsolidationReportsWorkbench.js +195 -0
  18. package/dist/components/consolidation/ConsolidationSummary.js +76 -0
  19. package/dist/components/consolidation/OriginalConsolidationHistory.js +112 -0
  20. package/dist/components/freight-cost/FreightDraftForm.js +213 -0
  21. package/dist/components/freight-cost/FreightFields.js +70 -0
  22. package/dist/components/freight-cost/FreightFxEditor.js +90 -0
  23. package/dist/components/freight-cost/FreightHistory.js +164 -0
  24. package/dist/components/freight-cost/FreightLineEditor.js +191 -0
  25. package/dist/components/freight-cost/FreightScopeEditor.js +72 -0
  26. package/dist/components/freight-cost/FreightTotals.js +66 -0
  27. package/dist/components/logistics-procedure/ProcedureDecisionForm.js +197 -0
  28. package/dist/components/logistics-procedure/ProcedureFields.js +31 -0
  29. package/dist/components/logistics-procedure/ProcedureHistory.js +177 -0
  30. package/dist/components/logistics-procedure/ProcedurePolicyForm.js +227 -0
  31. package/dist/components/logistics-procedure/ProcedurePolicyWorkbench.js +155 -0
  32. package/dist/components/logistics-procedure/ProcedureReviewWorkbench.js +221 -0
  33. package/dist/components/logistics-procedure/ProcedureRunWorkbench.js +190 -0
  34. package/dist/components/logistics-procedure/ProcedureSubjectPicker.js +130 -0
  35. package/dist/components/pending-pick/PendingPickDraft.js +84 -0
  36. package/dist/components/pending-pick/PendingPickHistory.js +113 -0
  37. package/dist/components/pending-pick/PickCapture.js +166 -0
  38. package/dist/components/pending-pick/PickLineSelection.js +111 -0
  39. package/dist/components/stock-binding/StockAssessmentDraft.js +48 -0
  40. package/dist/components/stock-binding/StockAssessmentHistory.js +61 -0
  41. package/dist/components/stock-binding/StockAssessmentSummary.js +199 -0
  42. package/dist/components/stock-binding/StockFactForm.js +232 -0
  43. package/dist/components/stock-observation/StockIssueForm.js +148 -0
  44. package/dist/components/stock-observation/StockIssueHistory.js +116 -0
  45. package/dist/components/stock-observation/StockIssueReadPanel.js +70 -0
  46. package/dist/components/trip-utilization/TripReportForm.js +118 -0
  47. package/dist/components/trip-utilization/TripReportHistory.js +54 -0
  48. package/dist/components/trip-utilization/TripReportSummary.js +216 -0
  49. package/dist/components/trip-utilization/TripSegmentFields.js +166 -0
  50. package/dist/generated/consolidation-operations.d.ts +1060 -0
  51. package/dist/generated/container-condition-operations.d.ts +868 -0
  52. package/dist/generated/container-operations.d.ts +356 -0
  53. package/dist/generated/empty-reuse-operations.d.ts +1578 -0
  54. package/dist/generated/free-time-operations.d.ts +938 -0
  55. package/dist/generated/freight-cost-operations.d.ts +716 -0
  56. package/dist/generated/logistics-procedure-operations.d.ts +938 -0
  57. package/dist/generated/pending-pick-operations.d.ts +1969 -0
  58. package/dist/generated/stock-binding-operations.d.ts +930 -0
  59. package/dist/generated/stock-observation-operations.d.ts +476 -0
  60. package/dist/generated/trip-utilization-operations.d.ts +651 -0
  61. package/dist/generated/wspace-operations.d.ts +143 -50
  62. package/dist/hooks/useConsolidationAction.js +119 -0
  63. package/dist/hooks/useContainerCondition.js +105 -0
  64. package/dist/hooks/useContainerLifecycle.js +192 -0
  65. package/dist/hooks/useEmptyReuseAction.js +45 -0
  66. package/dist/hooks/useFreightRecoveryAction.js +117 -0
  67. package/dist/hooks/useMultiModalShipments.js +1 -1
  68. package/dist/hooks/useProcedureAction.js +119 -0
  69. package/dist/hooks/useProcedureSelection.js +53 -0
  70. package/dist/hooks/useReuseRecoveryAction.js +116 -0
  71. package/dist/movethewheels/components/ContainerEvidencePicker.d.ts +10 -0
  72. package/dist/movethewheels/components/FreeTimeAgreementForm.d.ts +14 -0
  73. package/dist/movethewheels/components/ReturnInstructionForm.d.ts +8 -0
  74. package/dist/movethewheels/components/ReuseControls.d.ts +42 -0
  75. package/dist/movethewheels/components/ReusePermissionForm.d.ts +9 -0
  76. package/dist/movethewheels/components/ReuseProposalForm.d.ts +11 -0
  77. package/dist/movethewheels/components/ReuseSourceFields.d.ts +9 -0
  78. package/dist/movethewheels/components/consolidation/ConsolidationHistory.d.ts +13 -0
  79. package/dist/movethewheels/components/consolidation/ConsolidationLotEditor.d.ts +6 -0
  80. package/dist/movethewheels/components/consolidation/ConsolidationManifestWorkbench.d.ts +8 -0
  81. package/dist/movethewheels/components/consolidation/ConsolidationPlanForm.d.ts +8 -0
  82. package/dist/movethewheels/components/consolidation/ConsolidationPlanWorkbench.d.ts +5 -0
  83. package/dist/movethewheels/components/consolidation/ConsolidationReportForm.d.ts +9 -0
  84. package/dist/movethewheels/components/consolidation/ConsolidationReportsWorkbench.d.ts +7 -0
  85. package/dist/movethewheels/components/consolidation/ConsolidationSummary.d.ts +6 -0
  86. package/dist/movethewheels/components/consolidation/OriginalConsolidationHistory.d.ts +8 -0
  87. package/dist/movethewheels/components/freight-cost/FreightDraftForm.d.ts +8 -0
  88. package/dist/movethewheels/components/freight-cost/FreightFields.d.ts +23 -0
  89. package/dist/movethewheels/components/freight-cost/FreightFxEditor.d.ts +6 -0
  90. package/dist/movethewheels/components/freight-cost/FreightHistory.d.ts +5 -0
  91. package/dist/movethewheels/components/freight-cost/FreightLineEditor.d.ts +8 -0
  92. package/dist/movethewheels/components/freight-cost/FreightScopeEditor.d.ts +6 -0
  93. package/dist/movethewheels/components/freight-cost/FreightTotals.d.ts +6 -0
  94. package/dist/movethewheels/components/logistics-procedure/ProcedureDecisionForm.d.ts +20 -0
  95. package/dist/movethewheels/components/logistics-procedure/ProcedureFields.d.ts +17 -0
  96. package/dist/movethewheels/components/logistics-procedure/ProcedureHistory.d.ts +7 -0
  97. package/dist/movethewheels/components/logistics-procedure/ProcedurePolicyForm.d.ts +10 -0
  98. package/dist/movethewheels/components/logistics-procedure/ProcedurePolicyWorkbench.d.ts +5 -0
  99. package/dist/movethewheels/components/logistics-procedure/ProcedureReviewWorkbench.d.ts +5 -0
  100. package/dist/movethewheels/components/logistics-procedure/ProcedureRunWorkbench.d.ts +6 -0
  101. package/dist/movethewheels/components/logistics-procedure/ProcedureSubjectPicker.d.ts +7 -0
  102. package/dist/movethewheels/components/pending-pick/PendingPickDraft.d.ts +16 -0
  103. package/dist/movethewheels/components/pending-pick/PendingPickHistory.d.ts +5 -0
  104. package/dist/movethewheels/components/pending-pick/PickCapture.d.ts +6 -0
  105. package/dist/movethewheels/components/pending-pick/PickLineSelection.d.ts +17 -0
  106. package/dist/movethewheels/components/stock-binding/StockAssessmentDraft.d.ts +13 -0
  107. package/dist/movethewheels/components/stock-binding/StockAssessmentHistory.d.ts +18 -0
  108. package/dist/movethewheels/components/stock-binding/StockAssessmentSummary.d.ts +9 -0
  109. package/dist/movethewheels/components/stock-binding/StockFactForm.d.ts +6 -0
  110. package/dist/movethewheels/components/stock-observation/StockIssueForm.d.ts +7 -0
  111. package/dist/movethewheels/components/stock-observation/StockIssueHistory.d.ts +7 -0
  112. package/dist/movethewheels/components/stock-observation/StockIssueReadPanel.d.ts +5 -0
  113. package/dist/movethewheels/components/trip-utilization/TripReportForm.d.ts +6 -0
  114. package/dist/movethewheels/components/trip-utilization/TripReportHistory.d.ts +14 -0
  115. package/dist/movethewheels/components/trip-utilization/TripReportSummary.d.ts +5 -0
  116. package/dist/movethewheels/components/trip-utilization/TripSegmentFields.d.ts +9 -0
  117. package/dist/movethewheels/hooks/useConsolidationAction.d.ts +19 -0
  118. package/dist/movethewheels/hooks/useContainerCondition.d.ts +21 -0
  119. package/dist/movethewheels/hooks/useContainerLifecycle.d.ts +40 -0
  120. package/dist/movethewheels/hooks/useEmptyReuseAction.d.ts +14 -0
  121. package/dist/movethewheels/hooks/useFreightRecoveryAction.d.ts +23 -0
  122. package/dist/movethewheels/hooks/useProcedureAction.d.ts +18 -0
  123. package/dist/movethewheels/hooks/useProcedureSelection.d.ts +51 -0
  124. package/dist/movethewheels/hooks/useReuseRecoveryAction.d.ts +18 -0
  125. package/dist/movethewheels/pages/ConsolidationPage.d.ts +1 -0
  126. package/dist/movethewheels/pages/ContainerConditionPage.d.ts +1 -0
  127. package/dist/movethewheels/pages/ContainersPage.d.ts +2 -0
  128. package/dist/movethewheels/pages/EmptyReusePage.d.ts +1 -0
  129. package/dist/movethewheels/pages/FreeTimePage.d.ts +1 -0
  130. package/dist/movethewheels/pages/FreightEstimatePage.d.ts +1 -0
  131. package/dist/movethewheels/pages/LogisticsProceduresPage.d.ts +1 -0
  132. package/dist/movethewheels/pages/PendingPickPage.d.ts +1 -0
  133. package/dist/movethewheels/pages/StockBindingPage.d.ts +1 -0
  134. package/dist/movethewheels/pages/StockObservationsPage.d.ts +1 -0
  135. package/dist/movethewheels/pages/TripUtilizationPage.d.ts +1 -0
  136. package/dist/movethewheels/utils/consolidationHistoryTarget.d.ts +12 -0
  137. package/dist/movethewheels/utils/consolidationInput.d.ts +15 -0
  138. package/dist/movethewheels/utils/consolidationLot.d.ts +3 -0
  139. package/dist/movethewheels/utils/consolidationPins.d.ts +20 -0
  140. package/dist/movethewheels/utils/consolidationRecovery.d.ts +5 -0
  141. package/dist/movethewheels/utils/consolidationReportHead.d.ts +5 -0
  142. package/dist/movethewheels/utils/freeTimeDate.d.ts +1 -0
  143. package/dist/movethewheels/utils/freightAcknowledgement.d.ts +2 -0
  144. package/dist/movethewheels/utils/freightDraft.d.ts +36 -0
  145. package/dist/movethewheels/utils/freightRecovery.d.ts +5 -0
  146. package/dist/movethewheels/utils/graphqlClient.d.ts +2 -1
  147. package/dist/movethewheels/utils/pendingPickDraft.d.ts +8 -0
  148. package/dist/movethewheels/utils/procedureInput.d.ts +18 -0
  149. package/dist/movethewheels/utils/procedureRecovery.d.ts +5 -0
  150. package/dist/movethewheels/utils/reuseAttempt.d.ts +7 -0
  151. package/dist/movethewheels/utils/reuseForm.d.ts +6 -0
  152. package/dist/movethewheels/utils/reuseRecovery.d.ts +26 -0
  153. package/dist/movethewheels/utils/stockBindingForm.d.ts +23 -0
  154. package/dist/movethewheels/utils/stockBindingLabels.d.ts +10 -0
  155. package/dist/movethewheels/utils/stockObservationForm.d.ts +5 -0
  156. package/dist/movethewheels/utils/tripDraftContext.d.ts +25 -0
  157. package/dist/movethewheels/utils/tripUtilizationForm.d.ts +6 -0
  158. package/dist/node_modules/@react-leaflet/core/lib/component.js +5 -5
  159. package/dist/node_modules/fast-equals/dist/es/index.js +87 -74
  160. package/dist/node_modules/leaflet/dist/leaflet-src.js +8 -5
  161. package/dist/node_modules/lodash/_Stack.js +2 -1
  162. package/dist/node_modules/lucide-react/dist/esm/icons/clipboard-list.js +35 -0
  163. package/dist/node_modules/lucide-react/dist/esm/icons/repeat-2.js +22 -0
  164. package/dist/node_modules/react-leaflet/lib/MapContainer.js +3 -3
  165. package/dist/node_modules/react-smooth/es6/Animate.js +2 -2
  166. package/dist/node_modules/recharts/es6/cartesian/Area.js +13 -13
  167. package/dist/node_modules/recharts/es6/cartesian/Bar.js +9 -9
  168. package/dist/node_modules/recharts/es6/cartesian/Brush.js +12 -12
  169. package/dist/node_modules/recharts/es6/cartesian/CartesianAxis.js +7 -7
  170. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js +13 -13
  171. package/dist/node_modules/recharts/es6/cartesian/ErrorBar.js +4 -4
  172. package/dist/node_modules/recharts/es6/cartesian/Line.js +10 -10
  173. package/dist/node_modules/recharts/es6/cartesian/ReferenceArea.js +3 -3
  174. package/dist/node_modules/recharts/es6/cartesian/ReferenceDot.js +3 -3
  175. package/dist/node_modules/recharts/es6/cartesian/ReferenceLine.js +4 -4
  176. package/dist/node_modules/recharts/es6/cartesian/XAxis.js +3 -3
  177. package/dist/node_modules/recharts/es6/cartesian/YAxis.js +3 -3
  178. package/dist/node_modules/recharts/es6/chart/AccessibilityManager.js +1 -1
  179. package/dist/node_modules/recharts/es6/chart/generateCategoricalChart.js +22 -22
  180. package/dist/node_modules/recharts/es6/component/Cursor.js +1 -1
  181. package/dist/node_modules/recharts/es6/component/DefaultLegendContent.js +11 -11
  182. package/dist/node_modules/recharts/es6/component/DefaultTooltipContent.js +6 -6
  183. package/dist/node_modules/recharts/es6/component/Label.js +14 -14
  184. package/dist/node_modules/recharts/es6/component/LabelList.js +6 -6
  185. package/dist/node_modules/recharts/es6/component/Legend.js +5 -5
  186. package/dist/node_modules/recharts/es6/component/ResponsiveContainer.js +3 -3
  187. package/dist/node_modules/recharts/es6/component/Text.js +2 -2
  188. package/dist/node_modules/recharts/es6/component/Tooltip.js +3 -3
  189. package/dist/node_modules/recharts/es6/component/TooltipBoundingBox.js +2 -2
  190. package/dist/node_modules/recharts/es6/container/Layer.js +2 -2
  191. package/dist/node_modules/recharts/es6/container/Surface.js +2 -2
  192. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js +2 -2
  193. package/dist/node_modules/recharts/es6/polar/Pie.js +13 -13
  194. package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js +8 -8
  195. package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js +6 -6
  196. package/dist/node_modules/recharts/es6/shape/Cross.js +1 -1
  197. package/dist/node_modules/recharts/es6/shape/Curve.js +1 -1
  198. package/dist/node_modules/recharts/es6/shape/Dot.js +1 -1
  199. package/dist/node_modules/recharts/es6/shape/Polygon.js +4 -4
  200. package/dist/node_modules/recharts/es6/shape/Rectangle.js +4 -4
  201. package/dist/node_modules/recharts/es6/shape/Sector.js +1 -1
  202. package/dist/node_modules/recharts/es6/shape/Symbols.js +1 -1
  203. package/dist/node_modules/recharts/es6/shape/Trapezoid.js +4 -4
  204. package/dist/node_modules/recharts/es6/util/ActiveShapeUtils.js +9 -9
  205. package/dist/node_modules/recharts/es6/util/BarUtils.js +1 -1
  206. package/dist/node_modules/recharts/es6/util/CartesianUtils.js +1 -1
  207. package/dist/node_modules/recharts/es6/util/PolarUtils.js +1 -1
  208. package/dist/node_modules/recharts/es6/util/ReactUtils.js +2 -2
  209. package/dist/node_modules/recharts/es6/util/ReduceCSSCalc.js +1 -1
  210. package/dist/node_modules/recharts/es6/util/types.js +1 -1
  211. package/dist/node_modules/{react-is → recharts/node_modules/react-is}/cjs/react-is.development.js +2 -2
  212. package/dist/node_modules/{react-is → recharts/node_modules/react-is}/cjs/react-is.production.min.js +2 -2
  213. package/dist/node_modules/{react-is → recharts/node_modules/react-is}/index.js +2 -2
  214. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +97 -18
  215. package/dist/node_modules/zustand/esm/middleware.js +2 -2
  216. package/dist/pages/ConsolidationPage.js +76 -0
  217. package/dist/pages/ContainerConditionPage.js +972 -0
  218. package/dist/pages/ContainersPage.js +522 -0
  219. package/dist/pages/EmptyReusePage.js +777 -0
  220. package/dist/pages/FreeTimePage.js +657 -0
  221. package/dist/pages/FreightEstimatePage.js +284 -0
  222. package/dist/pages/LogisticsProceduresPage.js +100 -0
  223. package/dist/pages/PendingPickPage.js +155 -0
  224. package/dist/pages/StockBindingPage.js +236 -0
  225. package/dist/pages/StockObservationsPage.js +168 -0
  226. package/dist/pages/TripUtilizationPage.js +227 -0
  227. package/dist/src/generated/consolidation-operations.js +505 -0
  228. package/dist/src/generated/container-condition-operations.js +208 -0
  229. package/dist/src/generated/container-operations.js +101 -0
  230. package/dist/src/generated/empty-reuse-operations.js +749 -0
  231. package/dist/src/generated/free-time-operations.js +235 -0
  232. package/dist/src/generated/freight-cost-operations.js +325 -0
  233. package/dist/src/generated/logistics-procedure-operations.js +362 -0
  234. package/dist/src/generated/pending-pick-operations.js +1128 -0
  235. package/dist/src/generated/stock-binding-operations.js +175 -0
  236. package/dist/src/generated/stock-observation-operations.js +93 -0
  237. package/dist/src/generated/trip-utilization-operations.js +140 -0
  238. package/dist/src/generated/wspace-operations.js +708 -0
  239. package/dist/utils/consolidationHistoryTarget.js +27 -0
  240. package/dist/utils/consolidationInput.js +21 -0
  241. package/dist/utils/consolidationLot.js +29 -0
  242. package/dist/utils/consolidationPins.js +13 -0
  243. package/dist/utils/consolidationRecovery.js +40 -0
  244. package/dist/utils/consolidationReportHead.js +18 -0
  245. package/dist/utils/freeTimeDate.js +26 -0
  246. package/dist/utils/freightAcknowledgement.js +8 -0
  247. package/dist/utils/freightDraft.js +125 -0
  248. package/dist/utils/freightRecovery.js +36 -0
  249. package/dist/utils/graphqlClient.js +28 -28
  250. package/dist/utils/pendingPickDraft.js +46 -0
  251. package/dist/utils/procedureInput.js +43 -0
  252. package/dist/utils/procedureRecovery.js +42 -0
  253. package/dist/utils/reuseAttempt.js +20 -0
  254. package/dist/utils/reuseForm.js +25 -0
  255. package/dist/utils/reuseRecovery.js +71 -0
  256. package/dist/utils/stockBindingForm.js +142 -0
  257. package/dist/utils/stockBindingLabels.js +23 -0
  258. package/dist/utils/stockObservationForm.js +55 -0
  259. package/dist/utils/tripDraftContext.js +19 -0
  260. package/dist/utils/tripUtilizationForm.js +60 -0
  261. package/package.json +20 -5
  262. package/src/generated/consolidation-operations.ts +1138 -0
  263. package/src/generated/container-condition-operations.ts +771 -0
  264. package/src/generated/container-operations.ts +376 -0
  265. package/src/generated/empty-reuse-operations.ts +1648 -0
  266. package/src/generated/free-time-operations.ts +814 -0
  267. package/src/generated/freight-cost-operations.ts +753 -0
  268. package/src/generated/logistics-procedure-operations.ts +1047 -0
  269. package/src/generated/pending-pick-operations.ts +1508 -0
  270. package/src/generated/stock-binding-operations.ts +631 -0
  271. package/src/generated/stock-observation-operations.ts +373 -0
  272. package/src/generated/trip-utilization-operations.ts +500 -0
  273. package/src/generated/wspace-operations.ts +116 -0
  274. package/src/movethewheels/MoveTheWheelsRoot.tsx +79 -0
  275. package/src/movethewheels/MoveTheWheelsRoutes.tsx +22 -0
  276. package/src/movethewheels/components/ContainerEvidencePicker.tsx +146 -0
  277. package/src/movethewheels/components/FreeTimeAgreementForm.tsx +483 -0
  278. package/src/movethewheels/components/ReturnInstructionForm.tsx +102 -0
  279. package/src/movethewheels/components/ReuseControls.tsx +138 -0
  280. package/src/movethewheels/components/ReusePermissionForm.tsx +123 -0
  281. package/src/movethewheels/components/ReuseProposalForm.tsx +484 -0
  282. package/src/movethewheels/components/ReuseSourceFields.tsx +80 -0
  283. package/src/movethewheels/components/consolidation/ConsolidationHistory.tsx +159 -0
  284. package/src/movethewheels/components/consolidation/ConsolidationLotEditor.tsx +144 -0
  285. package/src/movethewheels/components/consolidation/ConsolidationManifestWorkbench.tsx +168 -0
  286. package/src/movethewheels/components/consolidation/ConsolidationPlanForm.tsx +185 -0
  287. package/src/movethewheels/components/consolidation/ConsolidationPlanWorkbench.tsx +395 -0
  288. package/src/movethewheels/components/consolidation/ConsolidationReportForm.tsx +124 -0
  289. package/src/movethewheels/components/consolidation/ConsolidationReportsWorkbench.tsx +233 -0
  290. package/src/movethewheels/components/consolidation/ConsolidationSummary.tsx +84 -0
  291. package/src/movethewheels/components/consolidation/OriginalConsolidationHistory.tsx +133 -0
  292. package/src/movethewheels/components/freight-cost/FreightDraftForm.tsx +224 -0
  293. package/src/movethewheels/components/freight-cost/FreightFields.tsx +91 -0
  294. package/src/movethewheels/components/freight-cost/FreightFxEditor.tsx +98 -0
  295. package/src/movethewheels/components/freight-cost/FreightHistory.tsx +91 -0
  296. package/src/movethewheels/components/freight-cost/FreightLineEditor.tsx +192 -0
  297. package/src/movethewheels/components/freight-cost/FreightScopeEditor.tsx +64 -0
  298. package/src/movethewheels/components/freight-cost/FreightTotals.tsx +68 -0
  299. package/src/movethewheels/components/logistics-procedure/ProcedureDecisionForm.tsx +204 -0
  300. package/src/movethewheels/components/logistics-procedure/ProcedureFields.tsx +43 -0
  301. package/src/movethewheels/components/logistics-procedure/ProcedureHistory.tsx +102 -0
  302. package/src/movethewheels/components/logistics-procedure/ProcedurePolicyForm.tsx +226 -0
  303. package/src/movethewheels/components/logistics-procedure/ProcedurePolicyWorkbench.tsx +174 -0
  304. package/src/movethewheels/components/logistics-procedure/ProcedureReviewWorkbench.tsx +278 -0
  305. package/src/movethewheels/components/logistics-procedure/ProcedureRunWorkbench.tsx +292 -0
  306. package/src/movethewheels/components/logistics-procedure/ProcedureSubjectPicker.tsx +111 -0
  307. package/src/movethewheels/components/pending-pick/PendingPickDraft.tsx +82 -0
  308. package/src/movethewheels/components/pending-pick/PendingPickHistory.tsx +93 -0
  309. package/src/movethewheels/components/pending-pick/PickCapture.tsx +70 -0
  310. package/src/movethewheels/components/pending-pick/PickLineSelection.tsx +130 -0
  311. package/src/movethewheels/components/stock-binding/StockAssessmentDraft.tsx +52 -0
  312. package/src/movethewheels/components/stock-binding/StockAssessmentHistory.tsx +56 -0
  313. package/src/movethewheels/components/stock-binding/StockAssessmentSummary.tsx +108 -0
  314. package/src/movethewheels/components/stock-binding/StockFactForm.tsx +186 -0
  315. package/src/movethewheels/components/stock-observation/StockIssueForm.tsx +103 -0
  316. package/src/movethewheels/components/stock-observation/StockIssueHistory.tsx +96 -0
  317. package/src/movethewheels/components/stock-observation/StockIssueReadPanel.tsx +72 -0
  318. package/src/movethewheels/components/trip-utilization/TripReportForm.tsx +116 -0
  319. package/src/movethewheels/components/trip-utilization/TripReportHistory.tsx +51 -0
  320. package/src/movethewheels/components/trip-utilization/TripReportSummary.tsx +127 -0
  321. package/src/movethewheels/components/trip-utilization/TripSegmentFields.tsx +118 -0
  322. package/src/movethewheels/hooks/useConsolidationAction.ts +196 -0
  323. package/src/movethewheels/hooks/useContainerCondition.ts +129 -0
  324. package/src/movethewheels/hooks/useContainerLifecycle.ts +291 -0
  325. package/src/movethewheels/hooks/useEmptyReuseAction.ts +72 -0
  326. package/src/movethewheels/hooks/useFreightRecoveryAction.ts +201 -0
  327. package/src/movethewheels/hooks/useMultiModalShipments.ts +2 -1
  328. package/src/movethewheels/hooks/useProcedureAction.ts +196 -0
  329. package/src/movethewheels/hooks/useProcedureSelection.ts +75 -0
  330. package/src/movethewheels/hooks/useReuseRecoveryAction.ts +192 -0
  331. package/src/movethewheels/pages/ConsolidationPage.tsx +70 -0
  332. package/src/movethewheels/pages/ContainerConditionPage.tsx +959 -0
  333. package/src/movethewheels/pages/ContainersPage.tsx +490 -0
  334. package/src/movethewheels/pages/EmptyReusePage.tsx +823 -0
  335. package/src/movethewheels/pages/FreeTimePage.tsx +720 -0
  336. package/src/movethewheels/pages/FreightEstimatePage.tsx +353 -0
  337. package/src/movethewheels/pages/LogisticsProceduresPage.tsx +86 -0
  338. package/src/movethewheels/pages/PendingPickPage.tsx +226 -0
  339. package/src/movethewheels/pages/StockBindingPage.tsx +299 -0
  340. package/src/movethewheels/pages/StockObservationsPage.tsx +181 -0
  341. package/src/movethewheels/pages/TripUtilizationPage.tsx +315 -0
  342. package/src/movethewheels/utils/consolidationHistoryTarget.ts +39 -0
  343. package/src/movethewheels/utils/consolidationInput.ts +70 -0
  344. package/src/movethewheels/utils/consolidationLot.ts +24 -0
  345. package/src/movethewheels/utils/consolidationPins.ts +52 -0
  346. package/src/movethewheels/utils/consolidationRecovery.ts +88 -0
  347. package/src/movethewheels/utils/consolidationReportHead.ts +29 -0
  348. package/src/movethewheels/utils/freeTimeDate.ts +31 -0
  349. package/src/movethewheels/utils/freightAcknowledgement.ts +31 -0
  350. package/src/movethewheels/utils/freightDraft.ts +170 -0
  351. package/src/movethewheels/utils/freightRecovery.ts +79 -0
  352. package/src/movethewheels/utils/graphqlClient.ts +14 -5
  353. package/src/movethewheels/utils/pendingPickDraft.ts +61 -0
  354. package/src/movethewheels/utils/procedureInput.ts +98 -0
  355. package/src/movethewheels/utils/procedureRecovery.ts +92 -0
  356. package/src/movethewheels/utils/reuseAttempt.ts +29 -0
  357. package/src/movethewheels/utils/reuseForm.ts +30 -0
  358. package/src/movethewheels/utils/reuseRecovery.ts +151 -0
  359. package/src/movethewheels/utils/stockBindingForm.ts +209 -0
  360. package/src/movethewheels/utils/stockBindingLabels.ts +41 -0
  361. package/src/movethewheels/utils/stockObservationForm.ts +73 -0
  362. package/src/movethewheels/utils/tripDraftContext.ts +61 -0
  363. package/src/movethewheels/utils/tripUtilizationForm.ts +105 -0
  364. package/src/operations/condition/container-condition.graphql +41 -0
  365. package/src/operations/consolidation/consolidation.graphql +490 -0
  366. package/src/operations/container/container-lifecycle.graphql +80 -0
  367. package/src/operations/empty-reuse/empty-reuse.graphql +737 -0
  368. package/src/operations/free-time/free-time.graphql +47 -0
  369. package/src/operations/freight-cost/freight.graphql +6 -0
  370. package/src/operations/logistics-procedure/procedure.graphql +15 -0
  371. package/src/operations/pending-pick/pending-pick.graphql +1122 -0
  372. package/src/operations/stock-binding/stock-binding.graphql +160 -0
  373. package/src/operations/stock-observation/stock-observation.graphql +20 -0
  374. package/src/operations/trip-utilization/trip-utilization.graphql +126 -0
  375. package/src/operations/wspace/container-evidence.graphql +6 -0
@@ -0,0 +1,201 @@
1
+ import { useRef, useState } from 'react';
2
+ import { print, type DocumentNode } from 'graphql';
3
+ import { useConditionApi } from './useContainerCondition';
4
+ import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
5
+ import { matchesFreightAcknowledgement } from '../utils/freightAcknowledgement';
6
+ import {
7
+ SaveFreightCostsDocument,
8
+ type SaveFreightCostsMutation,
9
+ } from '../../generated/freight-cost-operations';
10
+ import {
11
+ reuseRecoveryScope,
12
+ reuseRecoveryContextKey,
13
+ sameReuseRecoveryScope,
14
+ type ReuseRecovery,
15
+ } from '../utils/reuseRecovery';
16
+ import {
17
+ decodeFreightRecovery,
18
+ encodeFreightRecovery,
19
+ FREIGHT_RECOVERY_STORAGE,
20
+ } from '../utils/freightRecovery';
21
+ const documents = [SaveFreightCostsDocument];
22
+ function loadRecovery(): { attempt: ReuseRecovery | null; blocked: boolean } {
23
+ try {
24
+ const raw = sessionStorage.getItem(FREIGHT_RECOVERY_STORAGE);
25
+ const attempt = decodeFreightRecovery(raw);
26
+ return { attempt, blocked: raw !== null && attempt === null };
27
+ } catch {
28
+ return { attempt: null, blocked: true };
29
+ }
30
+ }
31
+ /** F06 retains one unresolved request across entity/context remounts; it never sends automatically. */
32
+ export function useFreightRecoveryAction() {
33
+ const request = useConditionApi('SINGLE_ATTEMPT');
34
+ const context = useMoveTheWheels();
35
+ const scope = reuseRecoveryScope(
36
+ context.currentUser?.id,
37
+ context.workspaceId,
38
+ context.tenantId,
39
+ context.apiGatewayUrl,
40
+ context.workspaceToken
41
+ );
42
+ const [initial] = useState(loadRecovery);
43
+ const [pending, setPending] = useState<ReuseRecovery | null>(initial.attempt);
44
+ const [blocked, setBlocked] = useState(initial.blocked);
45
+ const pendingRef = useRef(pending);
46
+ const running = useRef(false);
47
+ const [busy, setBusy] = useState(false);
48
+ const contextKey = reuseRecoveryContextKey(scope);
49
+ const [feedback, setFeedback] = useState<{
50
+ scopeKey: string;
51
+ error: string | null;
52
+ notice: string | null;
53
+ }>({ scopeKey: contextKey, error: null, notice: null });
54
+ // Async callbacks retain their submitting context; a new context masks their feedback.
55
+ const setError = (error: string | null) =>
56
+ setFeedback({ scopeKey: contextKey, error, notice: null });
57
+ const setNotice = (notice: string | null) =>
58
+ setFeedback({ scopeKey: contextKey, error: null, notice });
59
+ const [revision, setRevision] = useState(0);
60
+ const retain = (attempt: ReuseRecovery | null, completed?: ReuseRecovery) => {
61
+ if (attempt) sessionStorage.setItem(FREIGHT_RECOVERY_STORAGE, encodeFreightRecovery(attempt));
62
+ else {
63
+ const saved = decodeFreightRecovery(sessionStorage.getItem(FREIGHT_RECOVERY_STORAGE));
64
+ // An older in-flight reply must not erase a subsequently retained attempt after a remount.
65
+ if (
66
+ !completed ||
67
+ (saved?.key === completed.key && sameReuseRecoveryScope(saved.scope, completed.scope))
68
+ )
69
+ sessionStorage.removeItem(FREIGHT_RECOVERY_STORAGE);
70
+ }
71
+ pendingRef.current = attempt;
72
+ setPending(attempt);
73
+ setBlocked(false);
74
+ };
75
+ const send = async (attempt: ReuseRecovery) => {
76
+ if (running.current) return null;
77
+ if (!sameReuseRecoveryScope(attempt.scope, scope)) {
78
+ setError(
79
+ 'Return to the original account, organization, workspace and project before retrying.'
80
+ );
81
+ return null;
82
+ }
83
+ const document = documents.find((item) => print(item) === attempt.operation);
84
+ if (!document) {
85
+ setError('The saved operation changed. Check history before abandoning this attempt.');
86
+ return null;
87
+ }
88
+ running.current = true;
89
+ setBusy(true);
90
+ setError(null);
91
+ setNotice(null);
92
+ try {
93
+ const result = await request<SaveFreightCostsMutation>(document, {
94
+ input: { ...attempt.input, idempotencyKey: attempt.key },
95
+ });
96
+ if (!matchesFreightAcknowledgement(result, attempt.input))
97
+ throw new Error(
98
+ 'The save reply could not be confirmed. Keep the original request and check history.'
99
+ );
100
+ // Clearing storage may fail after a known reply. Retain the same key rather than making a new intent.
101
+ retain(null, attempt);
102
+ setRevision((value) => value + 1);
103
+ setNotice(attempt.success);
104
+ return result;
105
+ } catch (failure) {
106
+ setError(
107
+ failure instanceof Error
108
+ ? failure.message
109
+ : 'Unable to save. Check history before retrying.'
110
+ );
111
+ return null;
112
+ } finally {
113
+ running.current = false;
114
+ setBusy(false);
115
+ }
116
+ };
117
+ const run = async (document: DocumentNode, input: Record<string, unknown>, success: string) => {
118
+ if (running.current || pendingRef.current || blocked) {
119
+ setError('Resolve the original request before starting another.');
120
+ return null;
121
+ }
122
+ if (!scope) {
123
+ setError('Wait for the current account and workspace session.');
124
+ return null;
125
+ }
126
+ const operation = print(document);
127
+ if (!documents.some((item) => print(item) === operation)) {
128
+ setError('Unsupported freight operation.');
129
+ return null;
130
+ }
131
+ try {
132
+ if (sessionStorage.getItem(FREIGHT_RECOVERY_STORAGE) !== null) {
133
+ setError(
134
+ 'A saved request is unresolved. Reload this page and check history before starting another.'
135
+ );
136
+ return null;
137
+ }
138
+ } catch {
139
+ setError('This browser cannot retain the request safely. Nothing was sent.');
140
+ return null;
141
+ }
142
+ const attempt: ReuseRecovery = {
143
+ version: 1,
144
+ scope,
145
+ operation,
146
+ input: structuredClone(input),
147
+ key: crypto.randomUUID(),
148
+ success,
149
+ };
150
+ try {
151
+ retain(attempt);
152
+ } catch {
153
+ setError('This browser cannot retain the request safely. Nothing was sent.');
154
+ return null;
155
+ }
156
+ return send(attempt);
157
+ };
158
+ const retryOriginal = async () => {
159
+ if (pendingRef.current) await send(pendingRef.current);
160
+ };
161
+ const discardAttempt = () => {
162
+ if (running.current) return;
163
+ try {
164
+ retain(null);
165
+ setError(null);
166
+ setNotice(null);
167
+ } catch {
168
+ setError('Unable to clear the saved attempt. Nothing was sent.');
169
+ }
170
+ };
171
+ return {
172
+ run,
173
+ retryOriginal,
174
+ discardAttempt,
175
+ refresh: () => setRevision((value) => value + 1),
176
+ busy,
177
+ error: feedback.scopeKey === contextKey ? feedback.error : null,
178
+ notice: feedback.scopeKey === contextKey ? feedback.notice : null,
179
+ revision,
180
+ uncertain: pending !== null || blocked,
181
+ recoveryInvalid: blocked,
182
+ canRetry: pending !== null && sameReuseRecoveryScope(pending.scope, scope),
183
+ originalContext: pending?.scope ?? null,
184
+ // A read target never changes the retained intent or grants access across contexts.
185
+ originalHistoryTarget:
186
+ pending &&
187
+ sameReuseRecoveryScope(pending.scope, scope) &&
188
+ typeof pending.input.shipmentId === 'string' &&
189
+ pending.input.shipmentId.trim().length > 0 &&
190
+ pending.input.shipmentId.length <= 200 &&
191
+ typeof pending.input.estimateReference === 'string' &&
192
+ pending.input.estimateReference.trim().length > 0 &&
193
+ pending.input.estimateReference.length <= 200
194
+ ? {
195
+ shipmentId: pending.input.shipmentId,
196
+ estimateReference: pending.input.estimateReference,
197
+ }
198
+ : null,
199
+ contextKey,
200
+ };
201
+ }
@@ -332,7 +332,8 @@ export function useMultiModalShipments(
332
332
  destination: input.destination,
333
333
  legs: input.legs.map(toApiLeg),
334
334
  },
335
- }
335
+ },
336
+ 'SINGLE_ATTEMPT'
336
337
  );
337
338
  const created = mapShipment(data.planMultiModalShipment);
338
339
  setShipments((previous) => [created, ...previous]);
@@ -0,0 +1,196 @@
1
+ import { useRef, useState } from 'react';
2
+ import { print, type DocumentNode } from 'graphql';
3
+ import { useConditionApi } from './useContainerCondition';
4
+ import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
5
+ import {
6
+ PublishProcedureDocument,
7
+ StartProcedureDocument,
8
+ RecordProcedureStepDocument,
9
+ RecordProcedureDeviationDocument,
10
+ RevokeProcedureDeviationDocument,
11
+ } from '../../generated/logistics-procedure-operations';
12
+ import { procedureAcknowledgement } from '../utils/procedureInput';
13
+ import {
14
+ reuseRecoveryScope,
15
+ reuseRecoveryContextKey,
16
+ sameReuseRecoveryScope,
17
+ type ReuseRecovery,
18
+ } from '../utils/reuseRecovery';
19
+ import {
20
+ decodeProcedureRecovery,
21
+ encodeProcedureRecovery,
22
+ PROCEDURE_RECOVERY_STORAGE,
23
+ } from '../utils/procedureRecovery';
24
+ const documents = [
25
+ PublishProcedureDocument,
26
+ StartProcedureDocument,
27
+ RecordProcedureStepDocument,
28
+ RecordProcedureDeviationDocument,
29
+ RevokeProcedureDeviationDocument,
30
+ ];
31
+ function loadRecovery(): { attempt: ReuseRecovery | null; blocked: boolean } {
32
+ try {
33
+ const raw = sessionStorage.getItem(PROCEDURE_RECOVERY_STORAGE);
34
+ const attempt = decodeProcedureRecovery(raw);
35
+ return { attempt, blocked: raw !== null && attempt === null };
36
+ } catch {
37
+ return { attempt: null, blocked: true };
38
+ }
39
+ }
40
+ /** F05 retains one unresolved request across entity/context remounts; it never sends automatically. */
41
+ export function useProcedureAction() {
42
+ const request = useConditionApi('SINGLE_ATTEMPT');
43
+ const context = useMoveTheWheels();
44
+ const scope = reuseRecoveryScope(
45
+ context.currentUser?.id,
46
+ context.workspaceId,
47
+ context.tenantId,
48
+ context.apiGatewayUrl,
49
+ context.workspaceToken
50
+ );
51
+ const [initial] = useState(loadRecovery);
52
+ const [pending, setPending] = useState<ReuseRecovery | null>(initial.attempt);
53
+ const [blocked, setBlocked] = useState(initial.blocked);
54
+ const pendingRef = useRef(pending);
55
+ const running = useRef(false);
56
+ const [busy, setBusy] = useState(false);
57
+ const contextKey = reuseRecoveryContextKey(scope);
58
+ const [feedback, setFeedback] = useState<{
59
+ scopeKey: string;
60
+ error: string | null;
61
+ notice: string | null;
62
+ }>({ scopeKey: contextKey, error: null, notice: null });
63
+ // Async callbacks retain their submitting context; a new context masks their feedback.
64
+ const setError = (error: string | null) =>
65
+ setFeedback({ scopeKey: contextKey, error, notice: null });
66
+ const setNotice = (notice: string | null) =>
67
+ setFeedback({ scopeKey: contextKey, error: null, notice });
68
+ const [revision, setRevision] = useState(0);
69
+ const retain = (attempt: ReuseRecovery | null, completed?: ReuseRecovery) => {
70
+ if (attempt)
71
+ sessionStorage.setItem(PROCEDURE_RECOVERY_STORAGE, encodeProcedureRecovery(attempt));
72
+ else {
73
+ const saved = decodeProcedureRecovery(sessionStorage.getItem(PROCEDURE_RECOVERY_STORAGE));
74
+ // An older in-flight reply must not erase a subsequently retained attempt after a remount.
75
+ if (
76
+ !completed ||
77
+ (saved?.key === completed.key && sameReuseRecoveryScope(saved.scope, completed.scope))
78
+ )
79
+ sessionStorage.removeItem(PROCEDURE_RECOVERY_STORAGE);
80
+ }
81
+ pendingRef.current = attempt;
82
+ setPending(attempt);
83
+ setBlocked(false);
84
+ };
85
+ const send = async (attempt: ReuseRecovery) => {
86
+ if (running.current) return null;
87
+ if (!sameReuseRecoveryScope(attempt.scope, scope)) {
88
+ setError(
89
+ 'Return to the original account, organization, workspace and project before retrying.'
90
+ );
91
+ return null;
92
+ }
93
+ const document = documents.find((item) => print(item) === attempt.operation);
94
+ if (!document) {
95
+ setError('The saved operation changed. Check history before abandoning this attempt.');
96
+ return null;
97
+ }
98
+ running.current = true;
99
+ setBusy(true);
100
+ setError(null);
101
+ setNotice(null);
102
+ try {
103
+ const result = await request<Record<string, unknown>>(document, {
104
+ input: { ...attempt.input, idempotencyKey: attempt.key },
105
+ });
106
+ if (!procedureAcknowledgement(result, attempt.input, attempt.scope.actorId))
107
+ throw new Error(
108
+ 'The save reply could not be confirmed. Keep the original request and check history.'
109
+ );
110
+ // Clearing storage may fail after a known reply. Retain the same key rather than making a new intent.
111
+ retain(null, attempt);
112
+ setRevision((value) => value + 1);
113
+ setNotice(attempt.success);
114
+ return result;
115
+ } catch (failure) {
116
+ setError(
117
+ failure instanceof Error
118
+ ? failure.message
119
+ : 'Unable to save. Check history before retrying.'
120
+ );
121
+ return null;
122
+ } finally {
123
+ running.current = false;
124
+ setBusy(false);
125
+ }
126
+ };
127
+ const run = async (document: DocumentNode, input: Record<string, unknown>, success: string) => {
128
+ if (running.current || pendingRef.current || blocked) {
129
+ setError('Resolve the original request before starting another.');
130
+ return null;
131
+ }
132
+ if (!scope) {
133
+ setError('Wait for the current account and workspace session.');
134
+ return null;
135
+ }
136
+ const operation = print(document);
137
+ if (!documents.some((item) => print(item) === operation)) {
138
+ setError('Unsupported procedure operation.');
139
+ return null;
140
+ }
141
+ try {
142
+ if (sessionStorage.getItem(PROCEDURE_RECOVERY_STORAGE) !== null) {
143
+ setError(
144
+ 'A saved request is unresolved. Reload this page and check history before starting another.'
145
+ );
146
+ return null;
147
+ }
148
+ } catch {
149
+ setError('This browser cannot retain the request safely. Nothing was sent.');
150
+ return null;
151
+ }
152
+ const attempt: ReuseRecovery = {
153
+ version: 1,
154
+ scope,
155
+ operation,
156
+ input: structuredClone(input),
157
+ key: crypto.randomUUID(),
158
+ success,
159
+ };
160
+ try {
161
+ retain(attempt);
162
+ } catch {
163
+ setError('This browser cannot retain the request safely. Nothing was sent.');
164
+ return null;
165
+ }
166
+ return send(attempt);
167
+ };
168
+ const retryOriginal = async () => {
169
+ if (pendingRef.current) await send(pendingRef.current);
170
+ };
171
+ const discardAttempt = () => {
172
+ if (running.current) return;
173
+ try {
174
+ retain(null);
175
+ setError(null);
176
+ setNotice(null);
177
+ } catch {
178
+ setError('Unable to clear the saved attempt. Nothing was sent.');
179
+ }
180
+ };
181
+ return {
182
+ run,
183
+ retryOriginal,
184
+ discardAttempt,
185
+ refresh: () => setRevision((value) => value + 1),
186
+ busy,
187
+ error: feedback.scopeKey === contextKey ? feedback.error : null,
188
+ notice: feedback.scopeKey === contextKey ? feedback.notice : null,
189
+ revision,
190
+ uncertain: pending !== null || blocked,
191
+ recoveryInvalid: blocked,
192
+ canRetry: pending !== null && sameReuseRecoveryScope(pending.scope, scope),
193
+ originalContext: pending?.scope ?? null,
194
+ contextKey,
195
+ };
196
+ }
@@ -0,0 +1,75 @@
1
+ import { useState } from 'react';
2
+ import {
3
+ ProcedureContainersDocument,
4
+ ProcedureCyclesDocument,
5
+ ProcedureProposalsDocument,
6
+ type ProcedureContainersQuery,
7
+ type ProcedureCyclesQuery,
8
+ type ProcedureProposalsQuery,
9
+ } from '../../generated/logistics-procedure-operations';
10
+ import { useConditionQuery } from './useContainerCondition';
11
+ export function useProcedureSelection(revision: number) {
12
+ const [containerId, setContainer] = useState(''),
13
+ [cycleId, setCycle] = useState(''),
14
+ [proposalId, setProposal] = useState('');
15
+ const [containerOffset, setContainerOffset] = useState(0),
16
+ [cycleOffset, setCycleOffset] = useState(0),
17
+ [proposalOffset, setProposalOffset] = useState(0);
18
+ const containers = useConditionQuery<ProcedureContainersQuery>(
19
+ ProcedureContainersDocument,
20
+ { pagination: { limit: 25, offset: containerOffset } },
21
+ revision
22
+ );
23
+ const cycles = useConditionQuery<ProcedureCyclesQuery>(
24
+ ProcedureCyclesDocument,
25
+ containerId ? { containerId, pagination: { limit: 25, offset: cycleOffset } } : null,
26
+ revision
27
+ );
28
+ const proposals = useConditionQuery<ProcedureProposalsQuery>(
29
+ ProcedureProposalsDocument,
30
+ cycleId ? { cycleId, pagination: { limit: 25, offset: proposalOffset } } : null,
31
+ revision
32
+ );
33
+ return {
34
+ containerId,
35
+ cycleId,
36
+ proposalId,
37
+ containerOffset,
38
+ cycleOffset,
39
+ proposalOffset,
40
+ containers,
41
+ cycles,
42
+ proposals,
43
+ cycle: cycles.data?.mtwContainerCyclePage.items.find((row) => row.id === cycleId) ?? null,
44
+ proposal:
45
+ proposals.data?.mtwReuseProposalPage.items.find((row) => row.id === proposalId) ?? null,
46
+ selectContainer: (value: string) => {
47
+ setContainer(value);
48
+ setCycle('');
49
+ setProposal('');
50
+ setCycleOffset(0);
51
+ setProposalOffset(0);
52
+ },
53
+ selectCycle: (value: string) => {
54
+ setCycle(value);
55
+ setProposal('');
56
+ setProposalOffset(0);
57
+ },
58
+ selectProposal: setProposal,
59
+ pageContainers: (offset: number) => {
60
+ setContainerOffset(offset);
61
+ setContainer('');
62
+ setCycle('');
63
+ setProposal('');
64
+ },
65
+ pageCycles: (offset: number) => {
66
+ setCycleOffset(offset);
67
+ setCycle('');
68
+ setProposal('');
69
+ },
70
+ pageProposals: (offset: number) => {
71
+ setProposalOffset(offset);
72
+ setProposal('');
73
+ },
74
+ };
75
+ }
@@ -0,0 +1,192 @@
1
+ import { useRef, useState } from 'react';
2
+ import { print, type DocumentNode } from 'graphql';
3
+ import { useConditionApi } from './useContainerCondition';
4
+ import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
5
+ import {
6
+ RecordReturnInstructionDocument,
7
+ RecordReuseProposalDocument,
8
+ RecordReuseApprovalDocument,
9
+ AcceptReuseReservationDocument,
10
+ TerminateReuseReservationDocument,
11
+ } from '../../generated/empty-reuse-operations';
12
+ import {
13
+ decodeReuseRecovery,
14
+ encodeReuseRecovery,
15
+ REUSE_RECOVERY_STORAGE,
16
+ reuseRecoveryScope,
17
+ reuseRecoveryContextKey,
18
+ sameReuseRecoveryScope,
19
+ type ReuseRecovery,
20
+ } from '../utils/reuseRecovery';
21
+ const documents = [
22
+ RecordReturnInstructionDocument,
23
+ RecordReuseProposalDocument,
24
+ RecordReuseApprovalDocument,
25
+ AcceptReuseReservationDocument,
26
+ TerminateReuseReservationDocument,
27
+ ];
28
+ function loadRecovery(): { attempt: ReuseRecovery | null; blocked: boolean } {
29
+ try {
30
+ const raw = sessionStorage.getItem(REUSE_RECOVERY_STORAGE);
31
+ const attempt = decodeReuseRecovery(raw, documents);
32
+ return { attempt, blocked: raw !== null && attempt === null };
33
+ } catch {
34
+ return { attempt: null, blocked: true };
35
+ }
36
+ }
37
+ /** F02 retains one unresolved request across entity/context remounts; it never sends automatically. */
38
+ export function useReuseRecoveryAction() {
39
+ const request = useConditionApi();
40
+ const context = useMoveTheWheels();
41
+ const scope = reuseRecoveryScope(
42
+ context.currentUser?.id,
43
+ context.workspaceId,
44
+ context.tenantId,
45
+ context.apiGatewayUrl,
46
+ context.workspaceToken
47
+ );
48
+ const [initial] = useState(loadRecovery);
49
+ const [pending, setPending] = useState<ReuseRecovery | null>(initial.attempt);
50
+ const [blocked, setBlocked] = useState(initial.blocked);
51
+ const pendingRef = useRef(pending);
52
+ const running = useRef(false);
53
+ const [busy, setBusy] = useState(false);
54
+ const contextKey = reuseRecoveryContextKey(scope);
55
+ const [feedback, setFeedback] = useState<{
56
+ scopeKey: string;
57
+ error: string | null;
58
+ notice: string | null;
59
+ }>({ scopeKey: contextKey, error: null, notice: null });
60
+ // Async callbacks retain their submitting context; a new context masks their feedback.
61
+ const setError = (error: string | null) =>
62
+ setFeedback({ scopeKey: contextKey, error, notice: null });
63
+ const setNotice = (notice: string | null) =>
64
+ setFeedback({ scopeKey: contextKey, error: null, notice });
65
+ const [revision, setRevision] = useState(0);
66
+ const retain = (attempt: ReuseRecovery | null, completed?: ReuseRecovery) => {
67
+ if (attempt) sessionStorage.setItem(REUSE_RECOVERY_STORAGE, encodeReuseRecovery(attempt));
68
+ else {
69
+ const saved = decodeReuseRecovery(sessionStorage.getItem(REUSE_RECOVERY_STORAGE), documents);
70
+ // An older in-flight reply must not erase a subsequently retained attempt after a remount.
71
+ if (
72
+ !completed ||
73
+ (saved?.key === completed.key && sameReuseRecoveryScope(saved.scope, completed.scope))
74
+ )
75
+ sessionStorage.removeItem(REUSE_RECOVERY_STORAGE);
76
+ }
77
+ pendingRef.current = attempt;
78
+ setPending(attempt);
79
+ setBlocked(false);
80
+ };
81
+ const send = async <T>(attempt: ReuseRecovery) => {
82
+ if (running.current) return null;
83
+ if (!sameReuseRecoveryScope(attempt.scope, scope)) {
84
+ setError(
85
+ 'Return to the original account, organization, workspace and project before retrying.'
86
+ );
87
+ return null;
88
+ }
89
+ const document = documents.find((item) => print(item) === attempt.operation);
90
+ if (!document) {
91
+ setError('The saved operation changed. Check history before abandoning this attempt.');
92
+ return null;
93
+ }
94
+ running.current = true;
95
+ setBusy(true);
96
+ setError(null);
97
+ setNotice(null);
98
+ try {
99
+ const result = await request<T>(document, {
100
+ input: { ...attempt.input, idempotencyKey: attempt.key },
101
+ });
102
+ // Clearing storage may fail after a known reply. Retain the same key rather than making a new intent.
103
+ retain(null, attempt);
104
+ setRevision((value) => value + 1);
105
+ setNotice(attempt.success);
106
+ return result;
107
+ } catch (failure) {
108
+ setError(
109
+ failure instanceof Error
110
+ ? failure.message
111
+ : 'Unable to save. Check history before retrying.'
112
+ );
113
+ return null;
114
+ } finally {
115
+ running.current = false;
116
+ setBusy(false);
117
+ }
118
+ };
119
+ const run = async <T>(
120
+ document: DocumentNode,
121
+ input: Record<string, unknown>,
122
+ success: string
123
+ ) => {
124
+ if (running.current || pendingRef.current || blocked) {
125
+ setError('Resolve the original request before starting another.');
126
+ return null;
127
+ }
128
+ if (!scope) {
129
+ setError('Wait for the current account and workspace session.');
130
+ return null;
131
+ }
132
+ const operation = print(document);
133
+ if (!documents.some((item) => print(item) === operation)) {
134
+ setError('Unsupported reuse operation.');
135
+ return null;
136
+ }
137
+ try {
138
+ if (sessionStorage.getItem(REUSE_RECOVERY_STORAGE) !== null) {
139
+ setError(
140
+ 'A saved request is unresolved. Reload this page and check history before starting another.'
141
+ );
142
+ return null;
143
+ }
144
+ } catch {
145
+ setError('This browser cannot retain the request safely. Nothing was sent.');
146
+ return null;
147
+ }
148
+ const attempt: ReuseRecovery = {
149
+ version: 1,
150
+ scope,
151
+ operation,
152
+ input: structuredClone(input),
153
+ key: crypto.randomUUID(),
154
+ success,
155
+ };
156
+ try {
157
+ retain(attempt);
158
+ } catch {
159
+ setError('This browser cannot retain the request safely. Nothing was sent.');
160
+ return null;
161
+ }
162
+ return send<T>(attempt);
163
+ };
164
+ const retryOriginal = async () => {
165
+ if (pendingRef.current) await send(pendingRef.current);
166
+ };
167
+ const discardAttempt = () => {
168
+ if (running.current) return;
169
+ try {
170
+ retain(null);
171
+ setError(null);
172
+ setNotice(null);
173
+ } catch {
174
+ setError('Unable to clear the saved attempt. Nothing was sent.');
175
+ }
176
+ };
177
+ return {
178
+ run,
179
+ retryOriginal,
180
+ discardAttempt,
181
+ refresh: () => setRevision((value) => value + 1),
182
+ busy,
183
+ error: feedback.scopeKey === contextKey ? feedback.error : null,
184
+ notice: feedback.scopeKey === contextKey ? feedback.notice : null,
185
+ revision,
186
+ uncertain: pending !== null || blocked,
187
+ recoveryInvalid: blocked,
188
+ canRetry: pending !== null && sameReuseRecoveryScope(pending.scope, scope),
189
+ originalContext: pending?.scope ?? null,
190
+ contextKey,
191
+ };
192
+ }