@burdenoff/microfe-assethandler 2026.826.2 → 2026.826.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.
Files changed (571) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +1 -1
  2. package/dist/assethandler/AssetHandlerRoot.js.map +1 -1
  3. package/dist/assethandler/AssetHandlerRoutes.js.map +1 -1
  4. package/dist/assethandler/components/ActivityTimeline.js.map +1 -1
  5. package/dist/assethandler/components/AttachmentsPanel.js.map +1 -1
  6. package/dist/assethandler/components/ChartCard.js.map +1 -1
  7. package/dist/assethandler/components/CommentsPanel.js.map +1 -1
  8. package/dist/assethandler/components/NotFoundState.js.map +1 -1
  9. package/dist/assethandler/components/Pagination.js.map +1 -1
  10. package/dist/assethandler/components/SectionHeader.js.map +1 -1
  11. package/dist/assethandler/components/StatTile.js.map +1 -1
  12. package/dist/assethandler/components/charts/BarsChart.js.map +1 -1
  13. package/dist/assethandler/components/charts/ChartParts.js.map +1 -1
  14. package/dist/assethandler/components/charts/DonutChart.js.map +1 -1
  15. package/dist/assethandler/components/charts/ProgressMeter.js.map +1 -1
  16. package/dist/assethandler/components/charts/RadialGauge.js.map +1 -1
  17. package/dist/assethandler/components/charts/Sparkline.js.map +1 -1
  18. package/dist/assethandler/components/charts/TrendChart.js.map +1 -1
  19. package/dist/assethandler/components/charts/chartTheme.js.map +1 -1
  20. package/dist/assethandler/hooks/useAssetHandlerNavigate.js.map +1 -1
  21. package/dist/assethandler/hooks/useCopy.js.map +1 -1
  22. package/dist/assethandler/hooks/useMaintenancePlans.js.map +1 -1
  23. package/dist/assethandler/ops/MaintenancePlanDialog.js.map +1 -1
  24. package/dist/assethandler/ops/NewWorkOrderDialog.js.map +1 -1
  25. package/dist/assethandler/ops/ScheduleMaintenanceDialog.js.map +1 -1
  26. package/dist/assethandler/pages/AiPredictionsPage.js.map +1 -1
  27. package/dist/assethandler/pages/AnalyticsPage.js.map +1 -1
  28. package/dist/assethandler/pages/AssetsAssetCategoriesPage.js.map +1 -1
  29. package/dist/assethandler/pages/AssetsAssetCheckInOutPage.js.map +1 -1
  30. package/dist/assethandler/pages/AssetsAssetCreatePage.js.map +1 -1
  31. package/dist/assethandler/pages/AssetsAssetDetailPage.js.map +1 -1
  32. package/dist/assethandler/pages/AssetsAssetListPage.js.map +1 -1
  33. package/dist/assethandler/pages/AssetsAssetTrackingPage.js.map +1 -1
  34. package/dist/assethandler/pages/CmdbBrowserPage.js.map +1 -1
  35. package/dist/assethandler/pages/DashboardPage.js.map +1 -1
  36. package/dist/assethandler/pages/DigitalTwinPage.js.map +1 -1
  37. package/dist/assethandler/pages/DiscoveryJobsPage.js.map +1 -1
  38. package/dist/assethandler/pages/EsgDashboardPage.js.map +1 -1
  39. package/dist/assethandler/pages/FinanceBudgetDetailPage.js.map +1 -1
  40. package/dist/assethandler/pages/FinanceFinanceHubPage.js.map +1 -1
  41. package/dist/assethandler/pages/FinanceInvoiceDetailPage.js.map +1 -1
  42. package/dist/assethandler/pages/IotDevicesPage.js.map +1 -1
  43. package/dist/assethandler/pages/ItilChangeDetailPage.js.map +1 -1
  44. package/dist/assethandler/pages/ItilChangeManagementPage.js.map +1 -1
  45. package/dist/assethandler/pages/ItilDialogs.js.map +1 -1
  46. package/dist/assethandler/pages/ItilIncidentDetailPage.js.map +1 -1
  47. package/dist/assethandler/pages/ItilIncidentManagementPage.js.map +1 -1
  48. package/dist/assethandler/pages/ItilItilhubPage.js.map +1 -1
  49. package/dist/assethandler/pages/ItilProblemDetailPage.js.map +1 -1
  50. package/dist/assethandler/pages/ItilProblemManagementPage.js.map +1 -1
  51. package/dist/assethandler/pages/KnowledgeBasePage.js.map +1 -1
  52. package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js.map +1 -1
  53. package/dist/assethandler/pages/MaintenanceMaintenancePlansPage.d.ts.map +1 -1
  54. package/dist/assethandler/pages/MaintenanceMaintenancePlansPage.js +1 -1
  55. package/dist/assethandler/pages/MaintenanceMaintenancePlansPage.js.map +1 -1
  56. package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js.map +1 -1
  57. package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js.map +1 -1
  58. package/dist/assethandler/pages/OperationsOperationsHubPage.js.map +1 -1
  59. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js.map +1 -1
  60. package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js.map +1 -1
  61. package/dist/assethandler/pages/ProvenancePage.js.map +1 -1
  62. package/dist/assethandler/pages/ReportsDashboardPage.js.map +1 -1
  63. package/dist/assethandler/pages/SamLicensesPage.js.map +1 -1
  64. package/dist/assethandler/pages/SecurityComplianceDetailPage.js.map +1 -1
  65. package/dist/assethandler/pages/SecurityPolicyDetailPage.js.map +1 -1
  66. package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js.map +1 -1
  67. package/dist/assethandler/pages/SecuritySecurityHubPage.js.map +1 -1
  68. package/dist/assethandler/pages/TransactionsTransactionDetailPage.js.map +1 -1
  69. package/dist/assethandler/pages/TransactionsTransactionListPage.js.map +1 -1
  70. package/dist/assethandler/providers/AssetHandlerProvider.js.map +1 -1
  71. package/dist/assethandler/store/assethandlerStore.js.map +1 -1
  72. package/dist/assethandler/utils/categoryPresentation.js.map +1 -1
  73. package/dist/assethandler/utils/cn.js.map +1 -1
  74. package/dist/assethandler/utils/csv.js.map +1 -1
  75. package/dist/assethandler/utils/i18n.js.map +1 -1
  76. package/dist/assethandler/utils/knowledgeBase.js.map +1 -1
  77. package/dist/assethandler/utils/meter.js.map +1 -1
  78. package/dist/assethandler/utils/money.js.map +1 -1
  79. package/dist/assethandler/utils/navigation.js.map +1 -1
  80. package/dist/assethandler/utils/printAssetTag.js.map +1 -1
  81. package/dist/assethandler/utils/toast.js.map +1 -1
  82. package/dist/node_modules/clsx/dist/clsx.js.map +1 -1
  83. package/dist/node_modules/d3-array/src/ascending.js.map +1 -1
  84. package/dist/node_modules/d3-array/src/bisect.js.map +1 -1
  85. package/dist/node_modules/d3-array/src/bisector.js.map +1 -1
  86. package/dist/node_modules/d3-array/src/descending.js.map +1 -1
  87. package/dist/node_modules/d3-array/src/max.js.map +1 -1
  88. package/dist/node_modules/d3-array/src/min.js.map +1 -1
  89. package/dist/node_modules/d3-array/src/number.js.map +1 -1
  90. package/dist/node_modules/d3-array/src/quantile.js.map +1 -1
  91. package/dist/node_modules/d3-array/src/quickselect.js.map +1 -1
  92. package/dist/node_modules/d3-array/src/range.js.map +1 -1
  93. package/dist/node_modules/d3-array/src/sort.js.map +1 -1
  94. package/dist/node_modules/d3-array/src/ticks.js.map +1 -1
  95. package/dist/node_modules/d3-color/src/color.js.map +1 -1
  96. package/dist/node_modules/d3-color/src/define.js.map +1 -1
  97. package/dist/node_modules/d3-format/src/defaultLocale.js.map +1 -1
  98. package/dist/node_modules/d3-format/src/exponent.js.map +1 -1
  99. package/dist/node_modules/d3-format/src/formatDecimal.js.map +1 -1
  100. package/dist/node_modules/d3-format/src/formatGroup.js.map +1 -1
  101. package/dist/node_modules/d3-format/src/formatNumerals.js.map +1 -1
  102. package/dist/node_modules/d3-format/src/formatPrefixAuto.js.map +1 -1
  103. package/dist/node_modules/d3-format/src/formatRounded.js.map +1 -1
  104. package/dist/node_modules/d3-format/src/formatSpecifier.js.map +1 -1
  105. package/dist/node_modules/d3-format/src/formatTrim.js.map +1 -1
  106. package/dist/node_modules/d3-format/src/formatTypes.js.map +1 -1
  107. package/dist/node_modules/d3-format/src/identity.js.map +1 -1
  108. package/dist/node_modules/d3-format/src/locale.js.map +1 -1
  109. package/dist/node_modules/d3-format/src/precisionFixed.js.map +1 -1
  110. package/dist/node_modules/d3-format/src/precisionPrefix.js.map +1 -1
  111. package/dist/node_modules/d3-format/src/precisionRound.js.map +1 -1
  112. package/dist/node_modules/d3-interpolate/src/array.js.map +1 -1
  113. package/dist/node_modules/d3-interpolate/src/basis.js.map +1 -1
  114. package/dist/node_modules/d3-interpolate/src/basisClosed.js.map +1 -1
  115. package/dist/node_modules/d3-interpolate/src/color.js.map +1 -1
  116. package/dist/node_modules/d3-interpolate/src/date.js.map +1 -1
  117. package/dist/node_modules/d3-interpolate/src/number.js.map +1 -1
  118. package/dist/node_modules/d3-interpolate/src/numberArray.js.map +1 -1
  119. package/dist/node_modules/d3-interpolate/src/object.js.map +1 -1
  120. package/dist/node_modules/d3-interpolate/src/piecewise.js.map +1 -1
  121. package/dist/node_modules/d3-interpolate/src/rgb.js.map +1 -1
  122. package/dist/node_modules/d3-interpolate/src/round.js.map +1 -1
  123. package/dist/node_modules/d3-interpolate/src/string.js.map +1 -1
  124. package/dist/node_modules/d3-interpolate/src/value.js.map +1 -1
  125. package/dist/node_modules/d3-path/src/path.js.map +1 -1
  126. package/dist/node_modules/d3-scale/src/band.js.map +1 -1
  127. package/dist/node_modules/d3-scale/src/constant.js.map +1 -1
  128. package/dist/node_modules/d3-scale/src/continuous.js.map +1 -1
  129. package/dist/node_modules/d3-scale/src/diverging.js.map +1 -1
  130. package/dist/node_modules/d3-scale/src/identity.js.map +1 -1
  131. package/dist/node_modules/d3-scale/src/init.js.map +1 -1
  132. package/dist/node_modules/d3-scale/src/linear.js.map +1 -1
  133. package/dist/node_modules/d3-scale/src/log.js.map +1 -1
  134. package/dist/node_modules/d3-scale/src/nice.js.map +1 -1
  135. package/dist/node_modules/d3-scale/src/number.js.map +1 -1
  136. package/dist/node_modules/d3-scale/src/ordinal.js.map +1 -1
  137. package/dist/node_modules/d3-scale/src/pow.js.map +1 -1
  138. package/dist/node_modules/d3-scale/src/quantile.js.map +1 -1
  139. package/dist/node_modules/d3-scale/src/quantize.js.map +1 -1
  140. package/dist/node_modules/d3-scale/src/radial.js.map +1 -1
  141. package/dist/node_modules/d3-scale/src/sequential.js.map +1 -1
  142. package/dist/node_modules/d3-scale/src/sequentialQuantile.js.map +1 -1
  143. package/dist/node_modules/d3-scale/src/symlog.js.map +1 -1
  144. package/dist/node_modules/d3-scale/src/threshold.js.map +1 -1
  145. package/dist/node_modules/d3-scale/src/tickFormat.js.map +1 -1
  146. package/dist/node_modules/d3-scale/src/time.js.map +1 -1
  147. package/dist/node_modules/d3-scale/src/utcTime.js.map +1 -1
  148. package/dist/node_modules/d3-shape/src/area.js.map +1 -1
  149. package/dist/node_modules/d3-shape/src/array.js.map +1 -1
  150. package/dist/node_modules/d3-shape/src/constant.js.map +1 -1
  151. package/dist/node_modules/d3-shape/src/curve/basis.js.map +1 -1
  152. package/dist/node_modules/d3-shape/src/curve/basisClosed.js.map +1 -1
  153. package/dist/node_modules/d3-shape/src/curve/basisOpen.js.map +1 -1
  154. package/dist/node_modules/d3-shape/src/curve/bump.js.map +1 -1
  155. package/dist/node_modules/d3-shape/src/curve/linear.js.map +1 -1
  156. package/dist/node_modules/d3-shape/src/curve/linearClosed.js.map +1 -1
  157. package/dist/node_modules/d3-shape/src/curve/monotone.js.map +1 -1
  158. package/dist/node_modules/d3-shape/src/curve/natural.js.map +1 -1
  159. package/dist/node_modules/d3-shape/src/curve/step.js.map +1 -1
  160. package/dist/node_modules/d3-shape/src/line.js.map +1 -1
  161. package/dist/node_modules/d3-shape/src/noop.js.map +1 -1
  162. package/dist/node_modules/d3-shape/src/offset/expand.js.map +1 -1
  163. package/dist/node_modules/d3-shape/src/offset/none.js.map +1 -1
  164. package/dist/node_modules/d3-shape/src/offset/silhouette.js.map +1 -1
  165. package/dist/node_modules/d3-shape/src/offset/wiggle.js.map +1 -1
  166. package/dist/node_modules/d3-shape/src/order/none.js.map +1 -1
  167. package/dist/node_modules/d3-shape/src/path.js.map +1 -1
  168. package/dist/node_modules/d3-shape/src/point.js.map +1 -1
  169. package/dist/node_modules/d3-shape/src/stack.js.map +1 -1
  170. package/dist/node_modules/d3-shape/src/symbol/circle.js.map +1 -1
  171. package/dist/node_modules/d3-shape/src/symbol/cross.js.map +1 -1
  172. package/dist/node_modules/d3-shape/src/symbol/diamond.js.map +1 -1
  173. package/dist/node_modules/d3-shape/src/symbol/square.js.map +1 -1
  174. package/dist/node_modules/d3-shape/src/symbol/star.js.map +1 -1
  175. package/dist/node_modules/d3-shape/src/symbol/triangle.js.map +1 -1
  176. package/dist/node_modules/d3-shape/src/symbol/wye.js.map +1 -1
  177. package/dist/node_modules/d3-shape/src/symbol.js.map +1 -1
  178. package/dist/node_modules/d3-time/src/day.js.map +1 -1
  179. package/dist/node_modules/d3-time/src/hour.js.map +1 -1
  180. package/dist/node_modules/d3-time/src/interval.js.map +1 -1
  181. package/dist/node_modules/d3-time/src/millisecond.js.map +1 -1
  182. package/dist/node_modules/d3-time/src/minute.js.map +1 -1
  183. package/dist/node_modules/d3-time/src/month.js.map +1 -1
  184. package/dist/node_modules/d3-time/src/second.js.map +1 -1
  185. package/dist/node_modules/d3-time/src/ticks.js.map +1 -1
  186. package/dist/node_modules/d3-time/src/week.js.map +1 -1
  187. package/dist/node_modules/d3-time/src/year.js.map +1 -1
  188. package/dist/node_modules/d3-time-format/src/defaultLocale.js.map +1 -1
  189. package/dist/node_modules/d3-time-format/src/locale.js.map +1 -1
  190. package/dist/node_modules/decimal.js-light/decimal.js.map +1 -1
  191. package/dist/node_modules/dijkstrajs/dijkstra.js.map +1 -1
  192. package/dist/node_modules/eventemitter3/index.js.map +1 -1
  193. package/dist/node_modules/fast-equals/dist/es/index.js.map +1 -1
  194. package/dist/node_modules/internmap/src/index.js.map +1 -1
  195. package/dist/node_modules/lodash/_DataView.js.map +1 -1
  196. package/dist/node_modules/lodash/_Hash.js.map +1 -1
  197. package/dist/node_modules/lodash/_ListCache.js.map +1 -1
  198. package/dist/node_modules/lodash/_Map.js.map +1 -1
  199. package/dist/node_modules/lodash/_MapCache.js.map +1 -1
  200. package/dist/node_modules/lodash/_Promise.js.map +1 -1
  201. package/dist/node_modules/lodash/_Set.js.map +1 -1
  202. package/dist/node_modules/lodash/_SetCache.js.map +1 -1
  203. package/dist/node_modules/lodash/_Stack.js +2 -1
  204. package/dist/node_modules/lodash/_Stack.js.map +1 -1
  205. package/dist/node_modules/lodash/_Symbol.js.map +1 -1
  206. package/dist/node_modules/lodash/_Uint8Array.js.map +1 -1
  207. package/dist/node_modules/lodash/_WeakMap.js.map +1 -1
  208. package/dist/node_modules/lodash/_apply.js.map +1 -1
  209. package/dist/node_modules/lodash/_arrayEvery.js.map +1 -1
  210. package/dist/node_modules/lodash/_arrayFilter.js.map +1 -1
  211. package/dist/node_modules/lodash/_arrayIncludes.js.map +1 -1
  212. package/dist/node_modules/lodash/_arrayIncludesWith.js.map +1 -1
  213. package/dist/node_modules/lodash/_arrayLikeKeys.js.map +1 -1
  214. package/dist/node_modules/lodash/_arrayMap.js.map +1 -1
  215. package/dist/node_modules/lodash/_arrayPush.js.map +1 -1
  216. package/dist/node_modules/lodash/_arraySome.js.map +1 -1
  217. package/dist/node_modules/lodash/_asciiToArray.js.map +1 -1
  218. package/dist/node_modules/lodash/_assocIndexOf.js.map +1 -1
  219. package/dist/node_modules/lodash/_baseAssignValue.js.map +1 -1
  220. package/dist/node_modules/lodash/_baseEach.js.map +1 -1
  221. package/dist/node_modules/lodash/_baseEvery.js.map +1 -1
  222. package/dist/node_modules/lodash/_baseExtremum.js.map +1 -1
  223. package/dist/node_modules/lodash/_baseFindIndex.js.map +1 -1
  224. package/dist/node_modules/lodash/_baseFlatten.js.map +1 -1
  225. package/dist/node_modules/lodash/_baseFor.js.map +1 -1
  226. package/dist/node_modules/lodash/_baseForOwn.js.map +1 -1
  227. package/dist/node_modules/lodash/_baseGet.js.map +1 -1
  228. package/dist/node_modules/lodash/_baseGetAllKeys.js.map +1 -1
  229. package/dist/node_modules/lodash/_baseGetTag.js.map +1 -1
  230. package/dist/node_modules/lodash/_baseGt.js.map +1 -1
  231. package/dist/node_modules/lodash/_baseHasIn.js.map +1 -1
  232. package/dist/node_modules/lodash/_baseIndexOf.js.map +1 -1
  233. package/dist/node_modules/lodash/_baseIsArguments.js.map +1 -1
  234. package/dist/node_modules/lodash/_baseIsEqual.js.map +1 -1
  235. package/dist/node_modules/lodash/_baseIsEqualDeep.js.map +1 -1
  236. package/dist/node_modules/lodash/_baseIsMatch.js.map +1 -1
  237. package/dist/node_modules/lodash/_baseIsNaN.js.map +1 -1
  238. package/dist/node_modules/lodash/_baseIsNative.js.map +1 -1
  239. package/dist/node_modules/lodash/_baseIsTypedArray.js.map +1 -1
  240. package/dist/node_modules/lodash/_baseIteratee.js.map +1 -1
  241. package/dist/node_modules/lodash/_baseKeys.js.map +1 -1
  242. package/dist/node_modules/lodash/_baseLt.js.map +1 -1
  243. package/dist/node_modules/lodash/_baseMap.js.map +1 -1
  244. package/dist/node_modules/lodash/_baseMatches.js.map +1 -1
  245. package/dist/node_modules/lodash/_baseMatchesProperty.js.map +1 -1
  246. package/dist/node_modules/lodash/_baseOrderBy.js.map +1 -1
  247. package/dist/node_modules/lodash/_baseProperty.js.map +1 -1
  248. package/dist/node_modules/lodash/_basePropertyDeep.js.map +1 -1
  249. package/dist/node_modules/lodash/_baseRange.js.map +1 -1
  250. package/dist/node_modules/lodash/_baseRest.js.map +1 -1
  251. package/dist/node_modules/lodash/_baseSetToString.js.map +1 -1
  252. package/dist/node_modules/lodash/_baseSlice.js.map +1 -1
  253. package/dist/node_modules/lodash/_baseSome.js.map +1 -1
  254. package/dist/node_modules/lodash/_baseSortBy.js.map +1 -1
  255. package/dist/node_modules/lodash/_baseTimes.js.map +1 -1
  256. package/dist/node_modules/lodash/_baseToString.js.map +1 -1
  257. package/dist/node_modules/lodash/_baseTrim.js.map +1 -1
  258. package/dist/node_modules/lodash/_baseUnary.js.map +1 -1
  259. package/dist/node_modules/lodash/_baseUniq.js.map +1 -1
  260. package/dist/node_modules/lodash/_cacheHas.js.map +1 -1
  261. package/dist/node_modules/lodash/_castPath.js.map +1 -1
  262. package/dist/node_modules/lodash/_castSlice.js.map +1 -1
  263. package/dist/node_modules/lodash/_compareAscending.js.map +1 -1
  264. package/dist/node_modules/lodash/_compareMultiple.js.map +1 -1
  265. package/dist/node_modules/lodash/_coreJsData.js.map +1 -1
  266. package/dist/node_modules/lodash/_createBaseEach.js.map +1 -1
  267. package/dist/node_modules/lodash/_createBaseFor.js.map +1 -1
  268. package/dist/node_modules/lodash/_createCaseFirst.js.map +1 -1
  269. package/dist/node_modules/lodash/_createFind.js.map +1 -1
  270. package/dist/node_modules/lodash/_createRange.js.map +1 -1
  271. package/dist/node_modules/lodash/_createSet.js.map +1 -1
  272. package/dist/node_modules/lodash/_defineProperty.js.map +1 -1
  273. package/dist/node_modules/lodash/_equalArrays.js.map +1 -1
  274. package/dist/node_modules/lodash/_equalByTag.js.map +1 -1
  275. package/dist/node_modules/lodash/_equalObjects.js.map +1 -1
  276. package/dist/node_modules/lodash/_freeGlobal.js.map +1 -1
  277. package/dist/node_modules/lodash/_getAllKeys.js.map +1 -1
  278. package/dist/node_modules/lodash/_getMapData.js.map +1 -1
  279. package/dist/node_modules/lodash/_getMatchData.js.map +1 -1
  280. package/dist/node_modules/lodash/_getNative.js.map +1 -1
  281. package/dist/node_modules/lodash/_getPrototype.js.map +1 -1
  282. package/dist/node_modules/lodash/_getRawTag.js.map +1 -1
  283. package/dist/node_modules/lodash/_getSymbols.js.map +1 -1
  284. package/dist/node_modules/lodash/_getTag.js.map +1 -1
  285. package/dist/node_modules/lodash/_getValue.js.map +1 -1
  286. package/dist/node_modules/lodash/_hasPath.js.map +1 -1
  287. package/dist/node_modules/lodash/_hasUnicode.js.map +1 -1
  288. package/dist/node_modules/lodash/_hashClear.js.map +1 -1
  289. package/dist/node_modules/lodash/_hashDelete.js.map +1 -1
  290. package/dist/node_modules/lodash/_hashGet.js.map +1 -1
  291. package/dist/node_modules/lodash/_hashHas.js.map +1 -1
  292. package/dist/node_modules/lodash/_hashSet.js.map +1 -1
  293. package/dist/node_modules/lodash/_isFlattenable.js.map +1 -1
  294. package/dist/node_modules/lodash/_isIndex.js.map +1 -1
  295. package/dist/node_modules/lodash/_isIterateeCall.js.map +1 -1
  296. package/dist/node_modules/lodash/_isKey.js.map +1 -1
  297. package/dist/node_modules/lodash/_isKeyable.js.map +1 -1
  298. package/dist/node_modules/lodash/_isMasked.js.map +1 -1
  299. package/dist/node_modules/lodash/_isPrototype.js.map +1 -1
  300. package/dist/node_modules/lodash/_isStrictComparable.js.map +1 -1
  301. package/dist/node_modules/lodash/_listCacheClear.js.map +1 -1
  302. package/dist/node_modules/lodash/_listCacheDelete.js.map +1 -1
  303. package/dist/node_modules/lodash/_listCacheGet.js.map +1 -1
  304. package/dist/node_modules/lodash/_listCacheHas.js.map +1 -1
  305. package/dist/node_modules/lodash/_listCacheSet.js.map +1 -1
  306. package/dist/node_modules/lodash/_mapCacheClear.js.map +1 -1
  307. package/dist/node_modules/lodash/_mapCacheDelete.js.map +1 -1
  308. package/dist/node_modules/lodash/_mapCacheGet.js.map +1 -1
  309. package/dist/node_modules/lodash/_mapCacheHas.js.map +1 -1
  310. package/dist/node_modules/lodash/_mapCacheSet.js.map +1 -1
  311. package/dist/node_modules/lodash/_mapToArray.js.map +1 -1
  312. package/dist/node_modules/lodash/_matchesStrictComparable.js.map +1 -1
  313. package/dist/node_modules/lodash/_memoizeCapped.js.map +1 -1
  314. package/dist/node_modules/lodash/_nativeCreate.js.map +1 -1
  315. package/dist/node_modules/lodash/_nativeKeys.js.map +1 -1
  316. package/dist/node_modules/lodash/_nodeUtil.js.map +1 -1
  317. package/dist/node_modules/lodash/_objectToString.js.map +1 -1
  318. package/dist/node_modules/lodash/_overArg.js.map +1 -1
  319. package/dist/node_modules/lodash/_overRest.js.map +1 -1
  320. package/dist/node_modules/lodash/_root.js.map +1 -1
  321. package/dist/node_modules/lodash/_setCacheAdd.js.map +1 -1
  322. package/dist/node_modules/lodash/_setCacheHas.js.map +1 -1
  323. package/dist/node_modules/lodash/_setToArray.js.map +1 -1
  324. package/dist/node_modules/lodash/_setToString.js.map +1 -1
  325. package/dist/node_modules/lodash/_shortOut.js.map +1 -1
  326. package/dist/node_modules/lodash/_stackClear.js.map +1 -1
  327. package/dist/node_modules/lodash/_stackDelete.js.map +1 -1
  328. package/dist/node_modules/lodash/_stackGet.js.map +1 -1
  329. package/dist/node_modules/lodash/_stackHas.js.map +1 -1
  330. package/dist/node_modules/lodash/_stackSet.js.map +1 -1
  331. package/dist/node_modules/lodash/_strictIndexOf.js.map +1 -1
  332. package/dist/node_modules/lodash/_stringToArray.js.map +1 -1
  333. package/dist/node_modules/lodash/_stringToPath.js.map +1 -1
  334. package/dist/node_modules/lodash/_toKey.js.map +1 -1
  335. package/dist/node_modules/lodash/_toSource.js.map +1 -1
  336. package/dist/node_modules/lodash/_trimmedEndIndex.js.map +1 -1
  337. package/dist/node_modules/lodash/_unicodeToArray.js.map +1 -1
  338. package/dist/node_modules/lodash/constant.js.map +1 -1
  339. package/dist/node_modules/lodash/debounce.js.map +1 -1
  340. package/dist/node_modules/lodash/eq.js.map +1 -1
  341. package/dist/node_modules/lodash/every.js.map +1 -1
  342. package/dist/node_modules/lodash/find.js.map +1 -1
  343. package/dist/node_modules/lodash/findIndex.js.map +1 -1
  344. package/dist/node_modules/lodash/flatMap.js.map +1 -1
  345. package/dist/node_modules/lodash/get.js.map +1 -1
  346. package/dist/node_modules/lodash/hasIn.js.map +1 -1
  347. package/dist/node_modules/lodash/identity.js.map +1 -1
  348. package/dist/node_modules/lodash/isArguments.js.map +1 -1
  349. package/dist/node_modules/lodash/isArray.js.map +1 -1
  350. package/dist/node_modules/lodash/isArrayLike.js.map +1 -1
  351. package/dist/node_modules/lodash/isBoolean.js.map +1 -1
  352. package/dist/node_modules/lodash/isBuffer.js.map +1 -1
  353. package/dist/node_modules/lodash/isEqual.js.map +1 -1
  354. package/dist/node_modules/lodash/isFunction.js.map +1 -1
  355. package/dist/node_modules/lodash/isLength.js.map +1 -1
  356. package/dist/node_modules/lodash/isNaN.js.map +1 -1
  357. package/dist/node_modules/lodash/isNil.js.map +1 -1
  358. package/dist/node_modules/lodash/isNumber.js.map +1 -1
  359. package/dist/node_modules/lodash/isObject.js.map +1 -1
  360. package/dist/node_modules/lodash/isObjectLike.js.map +1 -1
  361. package/dist/node_modules/lodash/isPlainObject.js.map +1 -1
  362. package/dist/node_modules/lodash/isString.js.map +1 -1
  363. package/dist/node_modules/lodash/isSymbol.js.map +1 -1
  364. package/dist/node_modules/lodash/isTypedArray.js.map +1 -1
  365. package/dist/node_modules/lodash/keys.js.map +1 -1
  366. package/dist/node_modules/lodash/last.js.map +1 -1
  367. package/dist/node_modules/lodash/map.js.map +1 -1
  368. package/dist/node_modules/lodash/mapValues.js.map +1 -1
  369. package/dist/node_modules/lodash/max.js.map +1 -1
  370. package/dist/node_modules/lodash/maxBy.js.map +1 -1
  371. package/dist/node_modules/lodash/memoize.js.map +1 -1
  372. package/dist/node_modules/lodash/min.js.map +1 -1
  373. package/dist/node_modules/lodash/minBy.js.map +1 -1
  374. package/dist/node_modules/lodash/noop.js.map +1 -1
  375. package/dist/node_modules/lodash/now.js.map +1 -1
  376. package/dist/node_modules/lodash/property.js.map +1 -1
  377. package/dist/node_modules/lodash/range.js.map +1 -1
  378. package/dist/node_modules/lodash/some.js.map +1 -1
  379. package/dist/node_modules/lodash/sortBy.js.map +1 -1
  380. package/dist/node_modules/lodash/stubArray.js.map +1 -1
  381. package/dist/node_modules/lodash/stubFalse.js.map +1 -1
  382. package/dist/node_modules/lodash/throttle.js.map +1 -1
  383. package/dist/node_modules/lodash/toFinite.js.map +1 -1
  384. package/dist/node_modules/lodash/toInteger.js.map +1 -1
  385. package/dist/node_modules/lodash/toNumber.js.map +1 -1
  386. package/dist/node_modules/lodash/toString.js.map +1 -1
  387. package/dist/node_modules/lodash/uniqBy.js.map +1 -1
  388. package/dist/node_modules/lodash/upperFirst.js.map +1 -1
  389. package/dist/node_modules/object-assign/index.js.map +1 -1
  390. package/dist/node_modules/prop-types/checkPropTypes.js.map +1 -1
  391. package/dist/node_modules/prop-types/factoryWithThrowingShims.js.map +1 -1
  392. package/dist/node_modules/prop-types/factoryWithTypeCheckers.js.map +1 -1
  393. package/dist/node_modules/prop-types/index.js.map +1 -1
  394. package/dist/node_modules/prop-types/lib/ReactPropTypesSecret.js.map +1 -1
  395. package/dist/node_modules/prop-types/lib/has.js.map +1 -1
  396. package/dist/node_modules/prop-types/node_modules/react-is/cjs/react-is.development.js.map +1 -1
  397. package/dist/node_modules/prop-types/node_modules/react-is/cjs/react-is.production.min.js.map +1 -1
  398. package/dist/node_modules/prop-types/node_modules/react-is/index.js.map +1 -1
  399. package/dist/node_modules/qrcode/lib/browser.js.map +1 -1
  400. package/dist/node_modules/qrcode/lib/can-promise.js.map +1 -1
  401. package/dist/node_modules/qrcode/lib/core/alignment-pattern.js.map +1 -1
  402. package/dist/node_modules/qrcode/lib/core/alphanumeric-data.js.map +1 -1
  403. package/dist/node_modules/qrcode/lib/core/bit-buffer.js.map +1 -1
  404. package/dist/node_modules/qrcode/lib/core/bit-matrix.js.map +1 -1
  405. package/dist/node_modules/qrcode/lib/core/byte-data.js.map +1 -1
  406. package/dist/node_modules/qrcode/lib/core/error-correction-code.js.map +1 -1
  407. package/dist/node_modules/qrcode/lib/core/error-correction-level.js.map +1 -1
  408. package/dist/node_modules/qrcode/lib/core/finder-pattern.js.map +1 -1
  409. package/dist/node_modules/qrcode/lib/core/format-info.js.map +1 -1
  410. package/dist/node_modules/qrcode/lib/core/galois-field.js.map +1 -1
  411. package/dist/node_modules/qrcode/lib/core/kanji-data.js.map +1 -1
  412. package/dist/node_modules/qrcode/lib/core/mask-pattern.js.map +1 -1
  413. package/dist/node_modules/qrcode/lib/core/mode.js.map +1 -1
  414. package/dist/node_modules/qrcode/lib/core/numeric-data.js.map +1 -1
  415. package/dist/node_modules/qrcode/lib/core/polynomial.js.map +1 -1
  416. package/dist/node_modules/qrcode/lib/core/qrcode.js.map +1 -1
  417. package/dist/node_modules/qrcode/lib/core/reed-solomon-encoder.js.map +1 -1
  418. package/dist/node_modules/qrcode/lib/core/regex.js +1 -1
  419. package/dist/node_modules/qrcode/lib/core/regex.js.map +1 -1
  420. package/dist/node_modules/qrcode/lib/core/segments.js.map +1 -1
  421. package/dist/node_modules/qrcode/lib/core/utils.js.map +1 -1
  422. package/dist/node_modules/qrcode/lib/core/version-check.js.map +1 -1
  423. package/dist/node_modules/qrcode/lib/core/version.js.map +1 -1
  424. package/dist/node_modules/qrcode/lib/renderer/canvas.js.map +1 -1
  425. package/dist/node_modules/qrcode/lib/renderer/svg-tag.js.map +1 -1
  426. package/dist/node_modules/qrcode/lib/renderer/utils.js.map +1 -1
  427. package/dist/node_modules/react-is/cjs/react-is.development.js.map +1 -1
  428. package/dist/node_modules/react-is/cjs/react-is.production.min.js.map +1 -1
  429. package/dist/node_modules/react-is/index.js.map +1 -1
  430. package/dist/node_modules/react-smooth/es6/Animate.js +2 -2
  431. package/dist/node_modules/react-smooth/es6/Animate.js.map +1 -1
  432. package/dist/node_modules/react-smooth/es6/AnimateManager.js.map +1 -1
  433. package/dist/node_modules/react-smooth/es6/configUpdate.js.map +1 -1
  434. package/dist/node_modules/react-smooth/es6/easing.js.map +1 -1
  435. package/dist/node_modules/react-smooth/es6/setRafTimeout.js.map +1 -1
  436. package/dist/node_modules/react-smooth/es6/util.js.map +1 -1
  437. package/dist/node_modules/recharts/es6/cartesian/Area.js +13 -13
  438. package/dist/node_modules/recharts/es6/cartesian/Area.js.map +1 -1
  439. package/dist/node_modules/recharts/es6/cartesian/Bar.js +9 -9
  440. package/dist/node_modules/recharts/es6/cartesian/Bar.js.map +1 -1
  441. package/dist/node_modules/recharts/es6/cartesian/Brush.js +12 -12
  442. package/dist/node_modules/recharts/es6/cartesian/Brush.js.map +1 -1
  443. package/dist/node_modules/recharts/es6/cartesian/CartesianAxis.js +7 -7
  444. package/dist/node_modules/recharts/es6/cartesian/CartesianAxis.js.map +1 -1
  445. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js +13 -13
  446. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js.map +1 -1
  447. package/dist/node_modules/recharts/es6/cartesian/ErrorBar.js +4 -4
  448. package/dist/node_modules/recharts/es6/cartesian/ErrorBar.js.map +1 -1
  449. package/dist/node_modules/recharts/es6/cartesian/Line.js +10 -10
  450. package/dist/node_modules/recharts/es6/cartesian/Line.js.map +1 -1
  451. package/dist/node_modules/recharts/es6/cartesian/ReferenceArea.js +3 -3
  452. package/dist/node_modules/recharts/es6/cartesian/ReferenceArea.js.map +1 -1
  453. package/dist/node_modules/recharts/es6/cartesian/ReferenceDot.js +3 -3
  454. package/dist/node_modules/recharts/es6/cartesian/ReferenceDot.js.map +1 -1
  455. package/dist/node_modules/recharts/es6/cartesian/ReferenceLine.js +4 -4
  456. package/dist/node_modules/recharts/es6/cartesian/ReferenceLine.js.map +1 -1
  457. package/dist/node_modules/recharts/es6/cartesian/XAxis.js +3 -3
  458. package/dist/node_modules/recharts/es6/cartesian/XAxis.js.map +1 -1
  459. package/dist/node_modules/recharts/es6/cartesian/YAxis.js +3 -3
  460. package/dist/node_modules/recharts/es6/cartesian/YAxis.js.map +1 -1
  461. package/dist/node_modules/recharts/es6/cartesian/getEquidistantTicks.js.map +1 -1
  462. package/dist/node_modules/recharts/es6/cartesian/getTicks.js.map +1 -1
  463. package/dist/node_modules/recharts/es6/chart/AccessibilityManager.js +1 -1
  464. package/dist/node_modules/recharts/es6/chart/AccessibilityManager.js.map +1 -1
  465. package/dist/node_modules/recharts/es6/chart/AreaChart.js.map +1 -1
  466. package/dist/node_modules/recharts/es6/chart/BarChart.js.map +1 -1
  467. package/dist/node_modules/recharts/es6/chart/LineChart.js.map +1 -1
  468. package/dist/node_modules/recharts/es6/chart/PieChart.js.map +1 -1
  469. package/dist/node_modules/recharts/es6/chart/RadialBarChart.js.map +1 -1
  470. package/dist/node_modules/recharts/es6/chart/generateCategoricalChart.js +22 -22
  471. package/dist/node_modules/recharts/es6/chart/generateCategoricalChart.js.map +1 -1
  472. package/dist/node_modules/recharts/es6/component/Cell.js.map +1 -1
  473. package/dist/node_modules/recharts/es6/component/Cursor.js +1 -1
  474. package/dist/node_modules/recharts/es6/component/Cursor.js.map +1 -1
  475. package/dist/node_modules/recharts/es6/component/DefaultLegendContent.js +11 -11
  476. package/dist/node_modules/recharts/es6/component/DefaultLegendContent.js.map +1 -1
  477. package/dist/node_modules/recharts/es6/component/DefaultTooltipContent.js +6 -6
  478. package/dist/node_modules/recharts/es6/component/DefaultTooltipContent.js.map +1 -1
  479. package/dist/node_modules/recharts/es6/component/Label.js +14 -14
  480. package/dist/node_modules/recharts/es6/component/Label.js.map +1 -1
  481. package/dist/node_modules/recharts/es6/component/LabelList.js +6 -6
  482. package/dist/node_modules/recharts/es6/component/LabelList.js.map +1 -1
  483. package/dist/node_modules/recharts/es6/component/Legend.js +5 -5
  484. package/dist/node_modules/recharts/es6/component/Legend.js.map +1 -1
  485. package/dist/node_modules/recharts/es6/component/ResponsiveContainer.js +3 -3
  486. package/dist/node_modules/recharts/es6/component/ResponsiveContainer.js.map +1 -1
  487. package/dist/node_modules/recharts/es6/component/Text.js +2 -2
  488. package/dist/node_modules/recharts/es6/component/Text.js.map +1 -1
  489. package/dist/node_modules/recharts/es6/component/Tooltip.js +3 -3
  490. package/dist/node_modules/recharts/es6/component/Tooltip.js.map +1 -1
  491. package/dist/node_modules/recharts/es6/component/TooltipBoundingBox.js +2 -2
  492. package/dist/node_modules/recharts/es6/component/TooltipBoundingBox.js.map +1 -1
  493. package/dist/node_modules/recharts/es6/container/Layer.js +2 -2
  494. package/dist/node_modules/recharts/es6/container/Layer.js.map +1 -1
  495. package/dist/node_modules/recharts/es6/container/Surface.js +2 -2
  496. package/dist/node_modules/recharts/es6/container/Surface.js.map +1 -1
  497. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js +2 -2
  498. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js.map +1 -1
  499. package/dist/node_modules/recharts/es6/polar/Pie.js +13 -13
  500. package/dist/node_modules/recharts/es6/polar/Pie.js.map +1 -1
  501. package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js +8 -8
  502. package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js.map +1 -1
  503. package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js +6 -6
  504. package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js.map +1 -1
  505. package/dist/node_modules/recharts/es6/polar/RadialBar.js +6 -6
  506. package/dist/node_modules/recharts/es6/polar/RadialBar.js.map +1 -1
  507. package/dist/node_modules/recharts/es6/shape/Cross.js +1 -1
  508. package/dist/node_modules/recharts/es6/shape/Cross.js.map +1 -1
  509. package/dist/node_modules/recharts/es6/shape/Curve.js +1 -1
  510. package/dist/node_modules/recharts/es6/shape/Curve.js.map +1 -1
  511. package/dist/node_modules/recharts/es6/shape/Dot.js +1 -1
  512. package/dist/node_modules/recharts/es6/shape/Dot.js.map +1 -1
  513. package/dist/node_modules/recharts/es6/shape/Polygon.js +4 -4
  514. package/dist/node_modules/recharts/es6/shape/Polygon.js.map +1 -1
  515. package/dist/node_modules/recharts/es6/shape/Rectangle.js +4 -4
  516. package/dist/node_modules/recharts/es6/shape/Rectangle.js.map +1 -1
  517. package/dist/node_modules/recharts/es6/shape/Sector.js +1 -1
  518. package/dist/node_modules/recharts/es6/shape/Sector.js.map +1 -1
  519. package/dist/node_modules/recharts/es6/shape/Symbols.js +1 -1
  520. package/dist/node_modules/recharts/es6/shape/Symbols.js.map +1 -1
  521. package/dist/node_modules/recharts/es6/shape/Trapezoid.js +4 -4
  522. package/dist/node_modules/recharts/es6/shape/Trapezoid.js.map +1 -1
  523. package/dist/node_modules/recharts/es6/util/ActiveShapeUtils.js +9 -9
  524. package/dist/node_modules/recharts/es6/util/ActiveShapeUtils.js.map +1 -1
  525. package/dist/node_modules/recharts/es6/util/BarUtils.js +1 -1
  526. package/dist/node_modules/recharts/es6/util/BarUtils.js.map +1 -1
  527. package/dist/node_modules/recharts/es6/util/CartesianUtils.js +1 -1
  528. package/dist/node_modules/recharts/es6/util/CartesianUtils.js.map +1 -1
  529. package/dist/node_modules/recharts/es6/util/ChartUtils.js.map +1 -1
  530. package/dist/node_modules/recharts/es6/util/CssPrefixUtils.js.map +1 -1
  531. package/dist/node_modules/recharts/es6/util/DOMUtils.js.map +1 -1
  532. package/dist/node_modules/recharts/es6/util/DataUtils.js.map +1 -1
  533. package/dist/node_modules/recharts/es6/util/DetectReferenceElementsDomain.js.map +1 -1
  534. package/dist/node_modules/recharts/es6/util/Events.js.map +1 -1
  535. package/dist/node_modules/recharts/es6/util/Global.js.map +1 -1
  536. package/dist/node_modules/recharts/es6/util/IfOverflowMatches.js.map +1 -1
  537. package/dist/node_modules/recharts/es6/util/LogUtils.js.map +1 -1
  538. package/dist/node_modules/recharts/es6/util/PolarUtils.js +1 -1
  539. package/dist/node_modules/recharts/es6/util/PolarUtils.js.map +1 -1
  540. package/dist/node_modules/recharts/es6/util/RadialBarUtils.js +1 -1
  541. package/dist/node_modules/recharts/es6/util/RadialBarUtils.js.map +1 -1
  542. package/dist/node_modules/recharts/es6/util/ReactUtils.js +1 -1
  543. package/dist/node_modules/recharts/es6/util/ReactUtils.js.map +1 -1
  544. package/dist/node_modules/recharts/es6/util/ReduceCSSCalc.js +1 -1
  545. package/dist/node_modules/recharts/es6/util/ReduceCSSCalc.js.map +1 -1
  546. package/dist/node_modules/recharts/es6/util/ShallowEqual.js.map +1 -1
  547. package/dist/node_modules/recharts/es6/util/TickUtils.js.map +1 -1
  548. package/dist/node_modules/recharts/es6/util/calculateViewBox.js.map +1 -1
  549. package/dist/node_modules/recharts/es6/util/cursor/getCursorPoints.js.map +1 -1
  550. package/dist/node_modules/recharts/es6/util/cursor/getCursorRectangle.js.map +1 -1
  551. package/dist/node_modules/recharts/es6/util/cursor/getRadialCursorPoints.js.map +1 -1
  552. package/dist/node_modules/recharts/es6/util/getEveryNthWithCondition.js.map +1 -1
  553. package/dist/node_modules/recharts/es6/util/getLegendProps.js.map +1 -1
  554. package/dist/node_modules/recharts/es6/util/isDomainSpecifiedByUser.js.map +1 -1
  555. package/dist/node_modules/recharts/es6/util/payload/getUniqPayload.js.map +1 -1
  556. package/dist/node_modules/recharts/es6/util/tooltip/translate.js.map +1 -1
  557. package/dist/node_modules/recharts/es6/util/types.js +1 -1
  558. package/dist/node_modules/recharts/es6/util/types.js.map +1 -1
  559. package/dist/node_modules/recharts-scale/es6/getNiceTickValues.js.map +1 -1
  560. package/dist/node_modules/recharts-scale/es6/util/arithmetic.js.map +1 -1
  561. package/dist/node_modules/recharts-scale/es6/util/utils.js.map +1 -1
  562. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1 -1
  563. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -1
  564. package/dist/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +1 -1
  565. package/dist/services/createSandboxAssistantTransport.js.map +1 -1
  566. package/dist/utils/pageContext.js.map +1 -1
  567. package/package.json +4 -4
  568. package/dist/generated/global-operations.d.ts +0 -2
  569. package/dist/generated/global-operations.d.ts.map +0 -1
  570. package/dist/generated/global-types.d.ts +0 -23527
  571. package/dist/generated/global-types.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ReportsDashboardPage.js","names":[],"sources":["../../../src/assethandler/pages/ReportsDashboardPage.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from 'react';\nimport { useAssetMoney } from '../providers/AssetHandlerProvider';\nimport {\n Button,\n GlassCard,\n GradientText,\n PagePurpose,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Download,\n Printer,\n FileBarChart2,\n Wallet,\n Wrench,\n Activity,\n DollarSign,\n TrendingDown,\n Percent,\n} from 'lucide-react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport {\n Pagination,\n usePagination,\n StatTile,\n ChartCard,\n BarsChart,\n DonutChart,\n type DonutSlice,\n} from '../components';\nimport { downloadCsv } from '../utils/csv';\nimport { cn } from '../utils/cn';\n\n// ─── Query result shapes ──────────────────────────────────────────\ninterface RegisterAsset {\n id: string;\n assetNumber: string;\n name: string;\n category: string;\n status: string;\n department?: string | null;\n purchaseValue?: number | null;\n currentValue?: number | null;\n accumulatedDepreciation?: number | null;\n totalCostOfOwnership?: number | null;\n purchaseDate?: string | null;\n}\n\ninterface FinancialSummary {\n totalAssetValue: number;\n totalDepreciation: number;\n totalMaintenanceSpend: number;\n budgetAllocated: number;\n budgetSpent: number;\n invoicesOutstanding: number;\n invoicesOutstandingCount: number;\n transactionExpense: number;\n}\n\ninterface MaintenanceLogRecord {\n id: string;\n assetId: string;\n title: string;\n type: string;\n status: string;\n priority: string;\n scheduledAt?: string | null;\n completedAt?: string | null;\n estimatedCost?: number | null;\n actualCost?: number | null;\n}\n\ninterface UtilizationReport {\n totalAssets: number;\n assignedAssets: number;\n unassignedAssets: number;\n idleAssets: number;\n overdueAssignments: number;\n byStatus: { status: string; count: number }[];\n}\n\nconst REPORTS_QUERY = gql`\n query AssetHandlerReports($registerFilter: AssetRegisterFilterInput) {\n assetRegister(filter: $registerFilter, pagination: { limit: 1000 }) {\n id\n assetNumber\n name\n category\n status\n department\n purchaseValue\n currentValue\n accumulatedDepreciation\n totalCostOfOwnership\n purchaseDate\n }\n financialSummary {\n totalAssetValue\n totalDepreciation\n totalMaintenanceSpend\n budgetAllocated\n budgetSpent\n invoicesOutstanding\n invoicesOutstandingCount\n transactionExpense\n }\n maintenanceLog(pagination: { limit: 1000 }) {\n id\n assetId\n title\n type\n status\n priority\n scheduledAt\n completedAt\n estimatedCost\n actualCost\n }\n utilizationReport {\n totalAssets\n assignedAssets\n unassignedAssets\n idleAssets\n overdueAssignments\n byStatus {\n status\n count\n }\n }\n }\n`;\n\ninterface ReportsResult {\n assetRegister: RegisterAsset[];\n financialSummary: FinancialSummary;\n maintenanceLog: MaintenanceLogRecord[];\n utilizationReport: UtilizationReport;\n}\n\nconst ASSET_STATUSES = ['ACTIVE', 'INACTIVE', 'MAINTENANCE', 'RETIRED', 'DISPOSED'] as const;\n\n// ─── Presentation helpers ─────────────────────────────────────────\ntype Tone = 'success' | 'warning' | 'error' | 'info' | 'neutral';\n\nconst PILL_TONE: Record<Tone, string> = {\n success: 'bg-status-success-subtle text-status-success-text',\n warning: 'bg-status-warning-subtle text-status-warning-text',\n error: 'bg-status-error-subtle text-status-error-text',\n info: 'bg-status-info-subtle text-status-info-text',\n neutral: 'bg-bg-sunken text-text-secondary',\n};\n\nfunction StatusPill({ tone, children }: { tone: Tone; children: ReactNode }) {\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium capitalize',\n PILL_TONE[tone]\n )}\n >\n {children}\n </span>\n );\n}\n\nconst assetStatusTone = (status: string): Tone => {\n const s = status.toLowerCase();\n if (s === 'active') return 'success';\n if (s === 'maintenance') return 'warning';\n if (s === 'retired' || s === 'disposed') return 'error';\n return 'neutral';\n};\n\nconst maintenanceStatusTone = (status: string): Tone => {\n const s = status.toLowerCase();\n if (s === 'completed') return 'success';\n if (s === 'in_progress' || s === 'scheduled') return 'info';\n if (s === 'overdue' || s === 'cancelled') return 'error';\n return 'neutral';\n};\n\nfunction SkeletonRows({ rows = 6, cols }: { rows?: number; cols: number }) {\n return (\n <>\n {Array.from({ length: rows }).map((_, r) => (\n <tr key={r} className=\"border-b border-border-seam/60\">\n {Array.from({ length: cols }).map((_, c) => (\n <td key={c} className=\"p-3\">\n <div className=\"h-4 w-full max-w-[120px] animate-pulse rounded bg-bg-sunken\" />\n </td>\n ))}\n </tr>\n ))}\n </>\n );\n}\n\nexport function ReportsDashboardPage() {\n const { format: money, compact: compactUsd } = useAssetMoney();\n const { assets } = useAssetHandlerStore();\n const [statusFilter, setStatusFilter] = useState<string>('all');\n\n const { data, loading } = useQuery<ReportsResult>(REPORTS_QUERY, {\n variables: {\n registerFilter: statusFilter === 'all' ? null : { status: statusFilter },\n },\n fetchPolicy: 'cache-and-network',\n errorPolicy: 'all',\n });\n\n const register = useMemo(() => data?.assetRegister ?? [], [data]);\n const maintenance = useMemo(() => data?.maintenanceLog ?? [], [data]);\n const summary = data?.financialSummary;\n const utilization = data?.utilizationReport;\n\n const assetNameById = useMemo(() => {\n const map = new Map<string, string>();\n for (const asset of assets) map.set(asset.id, asset.name);\n return map;\n }, [assets]);\n\n const registerPage = usePagination(register, { pageSize: 12, resetKey: statusFilter });\n const maintenancePage = usePagination(maintenance, { pageSize: 12 });\n\n // ─── Header KPI figures (real, from financialSummary) ───\n const totalAssetValue = summary?.totalAssetValue ?? 0;\n const totalDepreciation = summary?.totalDepreciation ?? 0;\n const depreciationPct =\n totalAssetValue + totalDepreciation > 0\n ? (totalDepreciation / (totalAssetValue + totalDepreciation)) * 100\n : 0;\n\n // ─── Chart aggregations (real data only) ───\n const categoryValue = useMemo(() => {\n const map = new Map<string, number>();\n for (const a of register) {\n const value = a.currentValue ?? a.purchaseValue ?? 0;\n if (value > 0) {\n const key = a.category.replace(/_/g, ' ');\n map.set(key, (map.get(key) ?? 0) + value);\n }\n }\n return Array.from(map, ([category, value]) => ({ category, value }))\n .sort((a, b) => b.value - a.value)\n .slice(0, 12);\n }, [register]);\n\n const statusSlices = useMemo<DonutSlice[]>(\n () =>\n (utilization?.byStatus ?? [])\n .map((s) => ({ name: s.status.toLowerCase(), value: s.count }))\n .filter((s) => s.value > 0),\n [utilization]\n );\n\n const coverageSlices = useMemo<DonutSlice[]>(() => {\n if (!utilization) return [];\n return [\n { name: 'Assigned', value: utilization.assignedAssets },\n { name: 'Unassigned', value: utilization.unassignedAssets },\n { name: 'Idle', value: utilization.idleAssets },\n ].filter((s) => s.value > 0);\n }, [utilization]);\n\n const valueSlices = useMemo<DonutSlice[]>(() => {\n const slices = [\n { name: 'Current value', value: totalAssetValue },\n { name: 'Accumulated depreciation', value: totalDepreciation },\n ].filter((s) => s.value > 0);\n return slices;\n }, [totalAssetValue, totalDepreciation]);\n\n const budgetBars = useMemo(() => {\n if (!summary) return [];\n return [\n { metric: 'Allocated', value: summary.budgetAllocated },\n { metric: 'Spent', value: summary.budgetSpent },\n ];\n }, [summary]);\n\n const maintenanceSpendByType = useMemo(() => {\n const map = new Map<string, number>();\n for (const m of maintenance) {\n const cost = m.actualCost ?? m.estimatedCost ?? 0;\n if (cost > 0) {\n const key = m.type.replace(/_/g, ' ');\n map.set(key, (map.get(key) ?? 0) + cost);\n }\n }\n return Array.from(map, (entry) => ({ type: entry[0], cost: entry[1] })).sort(\n (a, b) => b.cost - a.cost\n );\n }, [maintenance]);\n\n // ─── Exports (unchanged behaviour) ───\n const exportRegister = () => {\n downloadCsv(\n `asset-register-${new Date().toISOString().slice(0, 10)}`,\n [\n 'Asset Number',\n 'Name',\n 'Category',\n 'Status',\n 'Department',\n 'Purchase Value',\n 'Current Value',\n 'Accumulated Depreciation',\n 'Total Cost of Ownership',\n 'Purchase Date',\n ],\n register.map((a) => [\n a.assetNumber,\n a.name,\n a.category,\n a.status,\n a.department ?? '',\n a.purchaseValue ?? '',\n a.currentValue ?? '',\n a.accumulatedDepreciation ?? '',\n a.totalCostOfOwnership ?? '',\n a.purchaseDate ? new Date(a.purchaseDate).toISOString().slice(0, 10) : '',\n ])\n );\n };\n\n const exportMaintenance = () => {\n downloadCsv(\n `maintenance-log-${new Date().toISOString().slice(0, 10)}`,\n [\n 'Title',\n 'Asset',\n 'Type',\n 'Status',\n 'Priority',\n 'Scheduled',\n 'Completed',\n 'Estimated Cost',\n 'Actual Cost',\n ],\n maintenance.map((m) => [\n m.title,\n assetNameById.get(m.assetId) ?? m.assetId,\n m.type,\n m.status,\n m.priority,\n m.scheduledAt ? new Date(m.scheduledAt).toISOString().slice(0, 10) : '',\n m.completedAt ? new Date(m.completedAt).toISOString().slice(0, 10) : '',\n m.estimatedCost ?? '',\n m.actualCost ?? '',\n ])\n );\n };\n\n const exportFinancial = () => {\n if (!summary) return;\n downloadCsv(\n `financial-summary-${new Date().toISOString().slice(0, 10)}`,\n ['Metric', 'Value'],\n [\n ['Total asset value', summary.totalAssetValue],\n ['Total depreciation', summary.totalDepreciation],\n ['Total maintenance spend', summary.totalMaintenanceSpend],\n ['Budget allocated', summary.budgetAllocated],\n ['Budget spent', summary.budgetSpent],\n ['Invoices outstanding', summary.invoicesOutstanding],\n ['Invoices outstanding (count)', summary.invoicesOutstandingCount],\n ['Transaction expense', summary.transactionExpense],\n ]\n );\n };\n\n const exportUtilization = () => {\n if (!utilization) return;\n downloadCsv(\n `utilization-report-${new Date().toISOString().slice(0, 10)}`,\n ['Metric', 'Value'],\n [\n ['Total assets', utilization.totalAssets],\n ['Assigned assets', utilization.assignedAssets],\n ['Unassigned assets', utilization.unassignedAssets],\n ['Idle assets', utilization.idleAssets],\n ['Overdue assignments', utilization.overdueAssignments],\n ...utilization.byStatus.map((s): [string, number] => [`Status: ${s.status}`, s.count]),\n ]\n );\n };\n\n const registerLoading = loading && register.length === 0;\n const maintenanceLoading = loading && maintenance.length === 0;\n\n const registerActions = (\n <>\n <Button size=\"sm\" onClick={exportRegister} disabled={register.length === 0}>\n <Download className=\"mr-2 h-4 w-4\" />\n Export CSV\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => window.print()}>\n <Printer className=\"mr-2 h-4 w-4\" />\n Print\n </Button>\n </>\n );\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n {/* ─── Header with persistent finance KPI strip ─── */}\n <div className=\"flex flex-col gap-5 xl:flex-row xl:items-end xl:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold sm:text-3xl\">\n <GradientText>Reports</GradientText>\n </h1>\n <p className=\"mt-1 max-w-xl text-sm text-text-secondary\">\n Registers and summaries built from live asset, finance and maintenance data.\n </p>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-3\">\n <StatTile\n label=\"Total asset value\"\n value={totalAssetValue}\n format={(v) => money(v)}\n icon={DollarSign}\n hero\n />\n <StatTile\n label=\"Total depreciation\"\n value={totalDepreciation}\n format={(v) => money(v)}\n icon={TrendingDown}\n />\n <StatTile\n label=\"Depreciated\"\n value={depreciationPct}\n format={(v) => `${v.toFixed(2)}%`}\n icon={Percent}\n />\n </div>\n </div>\n\n <PagePurpose>\n Pull the numbers you need for audits, finance reviews and planning. Every register below is\n generated from live records — export any of them to CSV or print the page for sign-off.\n </PagePurpose>\n\n <Tabs defaultValue=\"register\">\n <TabsList className=\"max-w-full justify-start overflow-x-auto\">\n <TabsTrigger value=\"register\">\n <FileBarChart2 className=\"mr-1.5 h-4 w-4\" />\n Asset Register\n </TabsTrigger>\n <TabsTrigger value=\"financial\">\n <Wallet className=\"mr-1.5 h-4 w-4\" />\n Financial Summary\n </TabsTrigger>\n <TabsTrigger value=\"maintenance\">\n <Wrench className=\"mr-1.5 h-4 w-4\" />\n Maintenance Log\n </TabsTrigger>\n <TabsTrigger value=\"utilization\">\n <Activity className=\"mr-1.5 h-4 w-4\" />\n Utilization\n </TabsTrigger>\n </TabsList>\n\n {/* ─── Asset Register ─── */}\n <TabsContent value=\"register\" className=\"mt-4 space-y-4\">\n {categoryValue.length > 0 ? (\n <ChartCard\n title=\"Asset value by category\"\n subtitle=\"Current book value aggregated from the register\"\n >\n <BarsChart\n data={categoryValue}\n xKey=\"category\"\n series={[{ key: 'value', label: 'Current value' }]}\n orientation=\"horizontal\"\n height={Math.max(200, categoryValue.length * 34)}\n valueFormat={compactUsd}\n categoryWidth={128}\n ariaLabel=\"Current asset value by category\"\n />\n </ChartCard>\n ) : null}\n\n <GlassCard treatment=\"glass\" className=\"overflow-hidden border-border-seam\">\n <div className=\"flex flex-col gap-3 border-b border-border-seam p-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-center gap-3\">\n <h3 className=\"text-base font-semibold text-text-primary\">Asset Register</h3>\n <Select value={statusFilter} onValueChange={setStatusFilter}>\n <SelectTrigger className=\"h-8 w-40\">\n <SelectValue placeholder=\"Filter by status\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All statuses</SelectItem>\n {ASSET_STATUSES.map((status) => (\n <SelectItem key={status} value={status} className=\"capitalize\">\n {status.toLowerCase()}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-wrap gap-2\">{registerActions}</div>\n </div>\n\n {/* Desktop table */}\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full min-w-[860px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/50 text-left\">\n <th className=\"p-3 font-medium\">Asset</th>\n <th className=\"p-3 font-medium\">Category</th>\n <th className=\"p-3 font-medium\">Status</th>\n <th className=\"p-3 font-medium\">Department</th>\n <th className=\"p-3 text-right font-medium\">Purchase</th>\n <th className=\"p-3 text-right font-medium\">Current</th>\n <th className=\"p-3 text-right font-medium\">Depreciation</th>\n <th className=\"p-3 text-right font-medium\">TCO</th>\n </tr>\n </thead>\n <tbody>\n {registerLoading ? (\n <SkeletonRows cols={8} />\n ) : (\n registerPage.pageItems.map((a) => (\n <tr\n key={a.id}\n className=\"border-b border-border-seam/60 last:border-0 hover:bg-bg-sunken/40\"\n >\n <td className=\"p-3\">\n <p className=\"font-medium\">{a.name}</p>\n <p className=\"text-xs text-text-secondary\">{a.assetNumber}</p>\n </td>\n <td className=\"p-3 capitalize\">{a.category.replace(/_/g, ' ')}</td>\n <td className=\"p-3\">\n <StatusPill tone={assetStatusTone(a.status)}>\n {a.status.toLowerCase()}\n </StatusPill>\n </td>\n <td className=\"p-3\">{a.department || '—'}</td>\n <td className=\"p-3 text-right tabular-nums\">{money(a.purchaseValue)}</td>\n <td className=\"p-3 text-right tabular-nums\">{money(a.currentValue)}</td>\n <td className=\"p-3 text-right tabular-nums\">\n {money(a.accumulatedDepreciation)}\n </td>\n <td className=\"p-3 text-right tabular-nums\">\n {money(a.totalCostOfOwnership)}\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n\n {/* Mobile cards */}\n <div className=\"divide-y divide-border-seam/60 md:hidden\">\n {registerLoading ? (\n <div className=\"space-y-3 p-4\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-16 animate-pulse rounded bg-bg-sunken\" />\n ))}\n </div>\n ) : (\n registerPage.pageItems.map((a) => (\n <div key={a.id} className=\"p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium\">{a.name}</p>\n <p className=\"text-xs text-text-secondary\">{a.assetNumber}</p>\n </div>\n <StatusPill tone={assetStatusTone(a.status)}>\n {a.status.toLowerCase()}\n </StatusPill>\n </div>\n <div className=\"mt-2 grid grid-cols-2 gap-x-4 gap-y-1 text-xs text-text-secondary\">\n <span>Category</span>\n <span className=\"text-right capitalize text-text-primary\">\n {a.category.replace(/_/g, ' ')}\n </span>\n <span>Current value</span>\n <span className=\"text-right tabular-nums text-text-primary\">\n {money(a.currentValue)}\n </span>\n <span>Depreciation</span>\n <span className=\"text-right tabular-nums text-text-primary\">\n {money(a.accumulatedDepreciation)}\n </span>\n </div>\n </div>\n ))\n )}\n </div>\n\n {register.length === 0 && !loading ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No assets in the register\"\n description=\"Register assets with financial details and they will appear here.\"\n />\n ) : (\n <div className=\"px-3\">\n <Pagination\n page={registerPage.page}\n pageCount={registerPage.pageCount}\n rangeStart={registerPage.rangeStart}\n rangeEnd={registerPage.rangeEnd}\n totalItems={registerPage.totalItems}\n canPrev={registerPage.canPrev}\n canNext={registerPage.canNext}\n onPrev={registerPage.prevPage}\n onNext={registerPage.nextPage}\n itemLabel=\"assets\"\n />\n </div>\n )}\n </GlassCard>\n </TabsContent>\n\n {/* ─── Financial Summary ─── */}\n <TabsContent value=\"financial\" className=\"mt-4 space-y-4\">\n <div className=\"flex justify-end\">\n <Button size=\"sm\" onClick={exportFinancial} disabled={!summary}>\n <Download className=\"mr-2 h-4 w-4\" />\n Export CSV\n </Button>\n </div>\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatTile label=\"Total asset value\" value={totalAssetValue} format={(v) => money(v)} />\n <StatTile\n label=\"Total depreciation\"\n value={totalDepreciation}\n format={(v) => money(v)}\n />\n <StatTile\n label=\"Maintenance spend\"\n value={summary?.totalMaintenanceSpend ?? 0}\n format={(v) => money(v)}\n />\n <StatTile\n label=\"Transaction expense\"\n value={summary?.transactionExpense ?? 0}\n format={(v) => money(v)}\n />\n <StatTile\n label=\"Budget allocated\"\n value={summary?.budgetAllocated ?? 0}\n format={(v) => money(v)}\n />\n <StatTile\n label=\"Budget spent\"\n value={summary?.budgetSpent ?? 0}\n format={(v) => money(v)}\n />\n <StatTile\n label=\"Invoices outstanding\"\n value={summary?.invoicesOutstanding ?? 0}\n format={(v) => money(v)}\n />\n <StatTile label=\"Outstanding invoices\" value={summary?.invoicesOutstandingCount ?? 0} />\n </div>\n <div className=\"grid gap-4 lg:grid-cols-2\">\n {budgetBars.length > 0 && (summary?.budgetAllocated || summary?.budgetSpent) ? (\n <ChartCard title=\"Budget utilization\" subtitle=\"Allocated against spend\">\n <BarsChart\n data={budgetBars}\n xKey=\"metric\"\n series={[{ key: 'value', label: 'Amount' }]}\n orientation=\"horizontal\"\n height={200}\n valueFormat={compactUsd}\n categoryWidth={96}\n ariaLabel=\"Budget allocated versus spent\"\n />\n </ChartCard>\n ) : null}\n {valueSlices.length > 0 ? (\n <ChartCard\n title=\"Value vs depreciation\"\n subtitle=\"Current book value against accumulated depreciation\"\n >\n <DonutChart\n data={valueSlices}\n centerLabel=\"Original cost\"\n centerValue={totalAssetValue + totalDepreciation}\n valueFormat={(v) => money(v)}\n height={220}\n ariaLabel=\"Current value versus accumulated depreciation\"\n />\n </ChartCard>\n ) : null}\n </div>\n </TabsContent>\n\n {/* ─── Maintenance Log ─── */}\n <TabsContent value=\"maintenance\" className=\"mt-4 space-y-4\">\n <div className=\"flex justify-end\">\n <Button size=\"sm\" onClick={exportMaintenance} disabled={maintenance.length === 0}>\n <Download className=\"mr-2 h-4 w-4\" />\n Export CSV\n </Button>\n </div>\n\n {maintenanceSpendByType.length > 0 ? (\n <ChartCard\n title=\"Maintenance spend by type\"\n subtitle=\"Actual cost, falling back to estimates\"\n >\n <BarsChart\n data={maintenanceSpendByType}\n xKey=\"type\"\n series={[{ key: 'cost', label: 'Spend' }]}\n orientation=\"horizontal\"\n height={Math.max(180, maintenanceSpendByType.length * 34)}\n valueFormat={compactUsd}\n categoryWidth={128}\n ariaLabel=\"Maintenance spend by type\"\n />\n </ChartCard>\n ) : null}\n\n <GlassCard treatment=\"glass\" className=\"overflow-hidden border-border-seam\">\n {/* Desktop table */}\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full min-w-[720px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/50 text-left\">\n <th className=\"p-3 font-medium\">Work</th>\n <th className=\"p-3 font-medium\">Asset</th>\n <th className=\"p-3 font-medium\">Type</th>\n <th className=\"p-3 font-medium\">Status</th>\n <th className=\"p-3 font-medium\">Completed</th>\n <th className=\"p-3 text-right font-medium\">Actual Cost</th>\n </tr>\n </thead>\n <tbody>\n {maintenanceLoading ? (\n <SkeletonRows cols={6} />\n ) : (\n maintenancePage.pageItems.map((m) => (\n <tr\n key={m.id}\n className=\"border-b border-border-seam/60 last:border-0 hover:bg-bg-sunken/40\"\n >\n <td className=\"p-3 font-medium\">{m.title}</td>\n <td className=\"p-3\">{assetNameById.get(m.assetId) ?? m.assetId}</td>\n <td className=\"p-3 capitalize\">{m.type.replace(/_/g, ' ')}</td>\n <td className=\"p-3\">\n <StatusPill tone={maintenanceStatusTone(m.status)}>\n {m.status.replace(/_/g, ' ').toLowerCase()}\n </StatusPill>\n </td>\n <td className=\"p-3 text-xs text-text-secondary\">\n {m.completedAt ? new Date(m.completedAt).toLocaleDateString() : '—'}\n </td>\n <td className=\"p-3 text-right tabular-nums\">{money(m.actualCost)}</td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n\n {/* Mobile cards */}\n <div className=\"divide-y divide-border-seam/60 md:hidden\">\n {maintenanceLoading ? (\n <div className=\"space-y-3 p-4\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-16 animate-pulse rounded bg-bg-sunken\" />\n ))}\n </div>\n ) : (\n maintenancePage.pageItems.map((m) => (\n <div key={m.id} className=\"p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"min-w-0 flex-1 truncate font-medium\">{m.title}</p>\n <StatusPill tone={maintenanceStatusTone(m.status)}>\n {m.status.replace(/_/g, ' ').toLowerCase()}\n </StatusPill>\n </div>\n <div className=\"mt-2 flex flex-wrap items-center gap-2 text-xs text-text-secondary\">\n <span className=\"capitalize\">{m.type.replace(/_/g, ' ')}</span>\n <span>· {assetNameById.get(m.assetId) ?? m.assetId}</span>\n {m.actualCost != null ? (\n <span className=\"ml-auto tabular-nums text-text-primary\">\n {money(m.actualCost)}\n </span>\n ) : null}\n </div>\n </div>\n ))\n )}\n </div>\n\n {maintenance.length === 0 && !loading ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No maintenance records\"\n description=\"Logged maintenance work will appear here once scheduled or completed.\"\n />\n ) : (\n <div className=\"px-3\">\n <Pagination\n page={maintenancePage.page}\n pageCount={maintenancePage.pageCount}\n rangeStart={maintenancePage.rangeStart}\n rangeEnd={maintenancePage.rangeEnd}\n totalItems={maintenancePage.totalItems}\n canPrev={maintenancePage.canPrev}\n canNext={maintenancePage.canNext}\n onPrev={maintenancePage.prevPage}\n onNext={maintenancePage.nextPage}\n itemLabel=\"records\"\n />\n </div>\n )}\n </GlassCard>\n </TabsContent>\n\n {/* ─── Utilization ─── */}\n <TabsContent value=\"utilization\" className=\"mt-4 space-y-4\">\n <div className=\"flex justify-end\">\n <Button size=\"sm\" onClick={exportUtilization} disabled={!utilization}>\n <Download className=\"mr-2 h-4 w-4\" />\n Export CSV\n </Button>\n </div>\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-5\">\n <StatTile label=\"Total assets\" value={utilization?.totalAssets ?? 0} />\n <StatTile label=\"Assigned\" value={utilization?.assignedAssets ?? 0} />\n <StatTile label=\"Unassigned\" value={utilization?.unassignedAssets ?? 0} />\n <StatTile label=\"Idle\" value={utilization?.idleAssets ?? 0} />\n <StatTile\n label=\"Overdue assignments\"\n value={utilization?.overdueAssignments ?? 0}\n delta={utilization && utilization.overdueAssignments > 0 ? 'Attention' : undefined}\n deltaTone=\"negative\"\n />\n </div>\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <ChartCard title=\"Assets by status\" subtitle=\"Distribution across lifecycle states\">\n <DonutChart\n data={statusSlices}\n centerLabel=\"Assets\"\n centerValue={utilization?.totalAssets ?? 0}\n height={240}\n emptyLabel=\"No status data available.\"\n ariaLabel=\"Assets by status\"\n />\n </ChartCard>\n <ChartCard title=\"Assignment coverage\" subtitle=\"Assigned, unassigned and idle assets\">\n <DonutChart\n data={coverageSlices}\n centerLabel=\"Assets\"\n centerValue={utilization?.totalAssets ?? 0}\n height={240}\n emptyLabel=\"No coverage data available.\"\n ariaLabel=\"Assignment coverage\"\n />\n </ChartCard>\n </div>\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ReportsDashboardPage.js","names":[],"sources":["../../../src/assethandler/pages/ReportsDashboardPage.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from 'react';\nimport { useAssetMoney } from '../providers/AssetHandlerProvider';\nimport {\n Button,\n GlassCard,\n GradientText,\n PagePurpose,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Download,\n Printer,\n FileBarChart2,\n Wallet,\n Wrench,\n Activity,\n DollarSign,\n TrendingDown,\n Percent,\n} from 'lucide-react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport {\n Pagination,\n usePagination,\n StatTile,\n ChartCard,\n BarsChart,\n DonutChart,\n type DonutSlice,\n} from '../components';\nimport { downloadCsv } from '../utils/csv';\nimport { cn } from '../utils/cn';\n\n// ─── Query result shapes ──────────────────────────────────────────\ninterface RegisterAsset {\n id: string;\n assetNumber: string;\n name: string;\n category: string;\n status: string;\n department?: string | null;\n purchaseValue?: number | null;\n currentValue?: number | null;\n accumulatedDepreciation?: number | null;\n totalCostOfOwnership?: number | null;\n purchaseDate?: string | null;\n}\n\ninterface FinancialSummary {\n totalAssetValue: number;\n totalDepreciation: number;\n totalMaintenanceSpend: number;\n budgetAllocated: number;\n budgetSpent: number;\n invoicesOutstanding: number;\n invoicesOutstandingCount: number;\n transactionExpense: number;\n}\n\ninterface MaintenanceLogRecord {\n id: string;\n assetId: string;\n title: string;\n type: string;\n status: string;\n priority: string;\n scheduledAt?: string | null;\n completedAt?: string | null;\n estimatedCost?: number | null;\n actualCost?: number | null;\n}\n\ninterface UtilizationReport {\n totalAssets: number;\n assignedAssets: number;\n unassignedAssets: number;\n idleAssets: number;\n overdueAssignments: number;\n byStatus: { status: string; count: number }[];\n}\n\nconst REPORTS_QUERY = gql`\n query AssetHandlerReports($registerFilter: AssetRegisterFilterInput) {\n assetRegister(filter: $registerFilter, pagination: { limit: 1000 }) {\n id\n assetNumber\n name\n category\n status\n department\n purchaseValue\n currentValue\n accumulatedDepreciation\n totalCostOfOwnership\n purchaseDate\n }\n financialSummary {\n totalAssetValue\n totalDepreciation\n totalMaintenanceSpend\n budgetAllocated\n budgetSpent\n invoicesOutstanding\n invoicesOutstandingCount\n transactionExpense\n }\n maintenanceLog(pagination: { limit: 1000 }) {\n id\n assetId\n title\n type\n status\n priority\n scheduledAt\n completedAt\n estimatedCost\n actualCost\n }\n utilizationReport {\n totalAssets\n assignedAssets\n unassignedAssets\n idleAssets\n overdueAssignments\n byStatus {\n status\n count\n }\n }\n }\n`;\n\ninterface ReportsResult {\n assetRegister: RegisterAsset[];\n financialSummary: FinancialSummary;\n maintenanceLog: MaintenanceLogRecord[];\n utilizationReport: UtilizationReport;\n}\n\nconst ASSET_STATUSES = ['ACTIVE', 'INACTIVE', 'MAINTENANCE', 'RETIRED', 'DISPOSED'] as const;\n\n// ─── Presentation helpers ─────────────────────────────────────────\ntype Tone = 'success' | 'warning' | 'error' | 'info' | 'neutral';\n\nconst PILL_TONE: Record<Tone, string> = {\n success: 'bg-status-success-subtle text-status-success-text',\n warning: 'bg-status-warning-subtle text-status-warning-text',\n error: 'bg-status-error-subtle text-status-error-text',\n info: 'bg-status-info-subtle text-status-info-text',\n neutral: 'bg-bg-sunken text-text-secondary',\n};\n\nfunction StatusPill({ tone, children }: { tone: Tone; children: ReactNode }) {\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium capitalize',\n PILL_TONE[tone]\n )}\n >\n {children}\n </span>\n );\n}\n\nconst assetStatusTone = (status: string): Tone => {\n const s = status.toLowerCase();\n if (s === 'active') return 'success';\n if (s === 'maintenance') return 'warning';\n if (s === 'retired' || s === 'disposed') return 'error';\n return 'neutral';\n};\n\nconst maintenanceStatusTone = (status: string): Tone => {\n const s = status.toLowerCase();\n if (s === 'completed') return 'success';\n if (s === 'in_progress' || s === 'scheduled') return 'info';\n if (s === 'overdue' || s === 'cancelled') return 'error';\n return 'neutral';\n};\n\nfunction SkeletonRows({ rows = 6, cols }: { rows?: number; cols: number }) {\n return (\n <>\n {Array.from({ length: rows }).map((_, r) => (\n <tr key={r} className=\"border-b border-border-seam/60\">\n {Array.from({ length: cols }).map((_, c) => (\n <td key={c} className=\"p-3\">\n <div className=\"h-4 w-full max-w-[120px] animate-pulse rounded bg-bg-sunken\" />\n </td>\n ))}\n </tr>\n ))}\n </>\n );\n}\n\nexport function ReportsDashboardPage() {\n const { format: money, compact: compactUsd } = useAssetMoney();\n const { assets } = useAssetHandlerStore();\n const [statusFilter, setStatusFilter] = useState<string>('all');\n\n const { data, loading } = useQuery<ReportsResult>(REPORTS_QUERY, {\n variables: {\n registerFilter: statusFilter === 'all' ? null : { status: statusFilter },\n },\n fetchPolicy: 'cache-and-network',\n errorPolicy: 'all',\n });\n\n const register = useMemo(() => data?.assetRegister ?? [], [data]);\n const maintenance = useMemo(() => data?.maintenanceLog ?? [], [data]);\n const summary = data?.financialSummary;\n const utilization = data?.utilizationReport;\n\n const assetNameById = useMemo(() => {\n const map = new Map<string, string>();\n for (const asset of assets) map.set(asset.id, asset.name);\n return map;\n }, [assets]);\n\n const registerPage = usePagination(register, { pageSize: 12, resetKey: statusFilter });\n const maintenancePage = usePagination(maintenance, { pageSize: 12 });\n\n // ─── Header KPI figures (real, from financialSummary) ───\n const totalAssetValue = summary?.totalAssetValue ?? 0;\n const totalDepreciation = summary?.totalDepreciation ?? 0;\n const depreciationPct =\n totalAssetValue + totalDepreciation > 0\n ? (totalDepreciation / (totalAssetValue + totalDepreciation)) * 100\n : 0;\n\n // ─── Chart aggregations (real data only) ───\n const categoryValue = useMemo(() => {\n const map = new Map<string, number>();\n for (const a of register) {\n const value = a.currentValue ?? a.purchaseValue ?? 0;\n if (value > 0) {\n const key = a.category.replace(/_/g, ' ');\n map.set(key, (map.get(key) ?? 0) + value);\n }\n }\n return Array.from(map, ([category, value]) => ({ category, value }))\n .sort((a, b) => b.value - a.value)\n .slice(0, 12);\n }, [register]);\n\n const statusSlices = useMemo<DonutSlice[]>(\n () =>\n (utilization?.byStatus ?? [])\n .map((s) => ({ name: s.status.toLowerCase(), value: s.count }))\n .filter((s) => s.value > 0),\n [utilization]\n );\n\n const coverageSlices = useMemo<DonutSlice[]>(() => {\n if (!utilization) return [];\n return [\n { name: 'Assigned', value: utilization.assignedAssets },\n { name: 'Unassigned', value: utilization.unassignedAssets },\n { name: 'Idle', value: utilization.idleAssets },\n ].filter((s) => s.value > 0);\n }, [utilization]);\n\n const valueSlices = useMemo<DonutSlice[]>(() => {\n const slices = [\n { name: 'Current value', value: totalAssetValue },\n { name: 'Accumulated depreciation', value: totalDepreciation },\n ].filter((s) => s.value > 0);\n return slices;\n }, [totalAssetValue, totalDepreciation]);\n\n const budgetBars = useMemo(() => {\n if (!summary) return [];\n return [\n { metric: 'Allocated', value: summary.budgetAllocated },\n { metric: 'Spent', value: summary.budgetSpent },\n ];\n }, [summary]);\n\n const maintenanceSpendByType = useMemo(() => {\n const map = new Map<string, number>();\n for (const m of maintenance) {\n const cost = m.actualCost ?? m.estimatedCost ?? 0;\n if (cost > 0) {\n const key = m.type.replace(/_/g, ' ');\n map.set(key, (map.get(key) ?? 0) + cost);\n }\n }\n return Array.from(map, (entry) => ({ type: entry[0], cost: entry[1] })).sort(\n (a, b) => b.cost - a.cost\n );\n }, [maintenance]);\n\n // ─── Exports (unchanged behaviour) ───\n const exportRegister = () => {\n downloadCsv(\n `asset-register-${new Date().toISOString().slice(0, 10)}`,\n [\n 'Asset Number',\n 'Name',\n 'Category',\n 'Status',\n 'Department',\n 'Purchase Value',\n 'Current Value',\n 'Accumulated Depreciation',\n 'Total Cost of Ownership',\n 'Purchase Date',\n ],\n register.map((a) => [\n a.assetNumber,\n a.name,\n a.category,\n a.status,\n a.department ?? '',\n a.purchaseValue ?? '',\n a.currentValue ?? '',\n a.accumulatedDepreciation ?? '',\n a.totalCostOfOwnership ?? '',\n a.purchaseDate ? new Date(a.purchaseDate).toISOString().slice(0, 10) : '',\n ])\n );\n };\n\n const exportMaintenance = () => {\n downloadCsv(\n `maintenance-log-${new Date().toISOString().slice(0, 10)}`,\n [\n 'Title',\n 'Asset',\n 'Type',\n 'Status',\n 'Priority',\n 'Scheduled',\n 'Completed',\n 'Estimated Cost',\n 'Actual Cost',\n ],\n maintenance.map((m) => [\n m.title,\n assetNameById.get(m.assetId) ?? m.assetId,\n m.type,\n m.status,\n m.priority,\n m.scheduledAt ? new Date(m.scheduledAt).toISOString().slice(0, 10) : '',\n m.completedAt ? new Date(m.completedAt).toISOString().slice(0, 10) : '',\n m.estimatedCost ?? '',\n m.actualCost ?? '',\n ])\n );\n };\n\n const exportFinancial = () => {\n if (!summary) return;\n downloadCsv(\n `financial-summary-${new Date().toISOString().slice(0, 10)}`,\n ['Metric', 'Value'],\n [\n ['Total asset value', summary.totalAssetValue],\n ['Total depreciation', summary.totalDepreciation],\n ['Total maintenance spend', summary.totalMaintenanceSpend],\n ['Budget allocated', summary.budgetAllocated],\n ['Budget spent', summary.budgetSpent],\n ['Invoices outstanding', summary.invoicesOutstanding],\n ['Invoices outstanding (count)', summary.invoicesOutstandingCount],\n ['Transaction expense', summary.transactionExpense],\n ]\n );\n };\n\n const exportUtilization = () => {\n if (!utilization) return;\n downloadCsv(\n `utilization-report-${new Date().toISOString().slice(0, 10)}`,\n ['Metric', 'Value'],\n [\n ['Total assets', utilization.totalAssets],\n ['Assigned assets', utilization.assignedAssets],\n ['Unassigned assets', utilization.unassignedAssets],\n ['Idle assets', utilization.idleAssets],\n ['Overdue assignments', utilization.overdueAssignments],\n ...utilization.byStatus.map((s): [string, number] => [`Status: ${s.status}`, s.count]),\n ]\n );\n };\n\n const registerLoading = loading && register.length === 0;\n const maintenanceLoading = loading && maintenance.length === 0;\n\n const registerActions = (\n <>\n <Button size=\"sm\" onClick={exportRegister} disabled={register.length === 0}>\n <Download className=\"mr-2 h-4 w-4\" />\n Export CSV\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => window.print()}>\n <Printer className=\"mr-2 h-4 w-4\" />\n Print\n </Button>\n </>\n );\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n {/* ─── Header with persistent finance KPI strip ─── */}\n <div className=\"flex flex-col gap-5 xl:flex-row xl:items-end xl:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold sm:text-3xl\">\n <GradientText>Reports</GradientText>\n </h1>\n <p className=\"mt-1 max-w-xl text-sm text-text-secondary\">\n Registers and summaries built from live asset, finance and maintenance data.\n </p>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-3\">\n <StatTile\n label=\"Total asset value\"\n value={totalAssetValue}\n format={(v) => money(v)}\n icon={DollarSign}\n hero\n />\n <StatTile\n label=\"Total depreciation\"\n value={totalDepreciation}\n format={(v) => money(v)}\n icon={TrendingDown}\n />\n <StatTile\n label=\"Depreciated\"\n value={depreciationPct}\n format={(v) => `${v.toFixed(2)}%`}\n icon={Percent}\n />\n </div>\n </div>\n\n <PagePurpose>\n Pull the numbers you need for audits, finance reviews and planning. Every register below is\n generated from live records — export any of them to CSV or print the page for sign-off.\n </PagePurpose>\n\n <Tabs defaultValue=\"register\">\n <TabsList className=\"max-w-full justify-start overflow-x-auto\">\n <TabsTrigger value=\"register\">\n <FileBarChart2 className=\"mr-1.5 h-4 w-4\" />\n Asset Register\n </TabsTrigger>\n <TabsTrigger value=\"financial\">\n <Wallet className=\"mr-1.5 h-4 w-4\" />\n Financial Summary\n </TabsTrigger>\n <TabsTrigger value=\"maintenance\">\n <Wrench className=\"mr-1.5 h-4 w-4\" />\n Maintenance Log\n </TabsTrigger>\n <TabsTrigger value=\"utilization\">\n <Activity className=\"mr-1.5 h-4 w-4\" />\n Utilization\n </TabsTrigger>\n </TabsList>\n\n {/* ─── Asset Register ─── */}\n <TabsContent value=\"register\" className=\"mt-4 space-y-4\">\n {categoryValue.length > 0 ? (\n <ChartCard\n title=\"Asset value by category\"\n subtitle=\"Current book value aggregated from the register\"\n >\n <BarsChart\n data={categoryValue}\n xKey=\"category\"\n series={[{ key: 'value', label: 'Current value' }]}\n orientation=\"horizontal\"\n height={Math.max(200, categoryValue.length * 34)}\n valueFormat={compactUsd}\n categoryWidth={128}\n ariaLabel=\"Current asset value by category\"\n />\n </ChartCard>\n ) : null}\n\n <GlassCard treatment=\"glass\" className=\"overflow-hidden border-border-seam\">\n <div className=\"flex flex-col gap-3 border-b border-border-seam p-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-center gap-3\">\n <h3 className=\"text-base font-semibold text-text-primary\">Asset Register</h3>\n <Select value={statusFilter} onValueChange={setStatusFilter}>\n <SelectTrigger className=\"h-8 w-40\">\n <SelectValue placeholder=\"Filter by status\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All statuses</SelectItem>\n {ASSET_STATUSES.map((status) => (\n <SelectItem key={status} value={status} className=\"capitalize\">\n {status.toLowerCase()}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-wrap gap-2\">{registerActions}</div>\n </div>\n\n {/* Desktop table */}\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full min-w-[860px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/50 text-left\">\n <th className=\"p-3 font-medium\">Asset</th>\n <th className=\"p-3 font-medium\">Category</th>\n <th className=\"p-3 font-medium\">Status</th>\n <th className=\"p-3 font-medium\">Department</th>\n <th className=\"p-3 text-right font-medium\">Purchase</th>\n <th className=\"p-3 text-right font-medium\">Current</th>\n <th className=\"p-3 text-right font-medium\">Depreciation</th>\n <th className=\"p-3 text-right font-medium\">TCO</th>\n </tr>\n </thead>\n <tbody>\n {registerLoading ? (\n <SkeletonRows cols={8} />\n ) : (\n registerPage.pageItems.map((a) => (\n <tr\n key={a.id}\n className=\"border-b border-border-seam/60 last:border-0 hover:bg-bg-sunken/40\"\n >\n <td className=\"p-3\">\n <p className=\"font-medium\">{a.name}</p>\n <p className=\"text-xs text-text-secondary\">{a.assetNumber}</p>\n </td>\n <td className=\"p-3 capitalize\">{a.category.replace(/_/g, ' ')}</td>\n <td className=\"p-3\">\n <StatusPill tone={assetStatusTone(a.status)}>\n {a.status.toLowerCase()}\n </StatusPill>\n </td>\n <td className=\"p-3\">{a.department || '—'}</td>\n <td className=\"p-3 text-right tabular-nums\">{money(a.purchaseValue)}</td>\n <td className=\"p-3 text-right tabular-nums\">{money(a.currentValue)}</td>\n <td className=\"p-3 text-right tabular-nums\">\n {money(a.accumulatedDepreciation)}\n </td>\n <td className=\"p-3 text-right tabular-nums\">\n {money(a.totalCostOfOwnership)}\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n\n {/* Mobile cards */}\n <div className=\"divide-y divide-border-seam/60 md:hidden\">\n {registerLoading ? (\n <div className=\"space-y-3 p-4\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-16 animate-pulse rounded bg-bg-sunken\" />\n ))}\n </div>\n ) : (\n registerPage.pageItems.map((a) => (\n <div key={a.id} className=\"p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium\">{a.name}</p>\n <p className=\"text-xs text-text-secondary\">{a.assetNumber}</p>\n </div>\n <StatusPill tone={assetStatusTone(a.status)}>\n {a.status.toLowerCase()}\n </StatusPill>\n </div>\n <div className=\"mt-2 grid grid-cols-2 gap-x-4 gap-y-1 text-xs text-text-secondary\">\n <span>Category</span>\n <span className=\"text-right capitalize text-text-primary\">\n {a.category.replace(/_/g, ' ')}\n </span>\n <span>Current value</span>\n <span className=\"text-right tabular-nums text-text-primary\">\n {money(a.currentValue)}\n </span>\n <span>Depreciation</span>\n <span className=\"text-right tabular-nums text-text-primary\">\n {money(a.accumulatedDepreciation)}\n </span>\n </div>\n </div>\n ))\n )}\n </div>\n\n {register.length === 0 && !loading ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No assets in the register\"\n description=\"Register assets with financial details and they will appear here.\"\n />\n ) : (\n <div className=\"px-3\">\n <Pagination\n page={registerPage.page}\n pageCount={registerPage.pageCount}\n rangeStart={registerPage.rangeStart}\n rangeEnd={registerPage.rangeEnd}\n totalItems={registerPage.totalItems}\n canPrev={registerPage.canPrev}\n canNext={registerPage.canNext}\n onPrev={registerPage.prevPage}\n onNext={registerPage.nextPage}\n itemLabel=\"assets\"\n />\n </div>\n )}\n </GlassCard>\n </TabsContent>\n\n {/* ─── Financial Summary ─── */}\n <TabsContent value=\"financial\" className=\"mt-4 space-y-4\">\n <div className=\"flex justify-end\">\n <Button size=\"sm\" onClick={exportFinancial} disabled={!summary}>\n <Download className=\"mr-2 h-4 w-4\" />\n Export CSV\n </Button>\n </div>\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatTile label=\"Total asset value\" value={totalAssetValue} format={(v) => money(v)} />\n <StatTile\n label=\"Total depreciation\"\n value={totalDepreciation}\n format={(v) => money(v)}\n />\n <StatTile\n label=\"Maintenance spend\"\n value={summary?.totalMaintenanceSpend ?? 0}\n format={(v) => money(v)}\n />\n <StatTile\n label=\"Transaction expense\"\n value={summary?.transactionExpense ?? 0}\n format={(v) => money(v)}\n />\n <StatTile\n label=\"Budget allocated\"\n value={summary?.budgetAllocated ?? 0}\n format={(v) => money(v)}\n />\n <StatTile\n label=\"Budget spent\"\n value={summary?.budgetSpent ?? 0}\n format={(v) => money(v)}\n />\n <StatTile\n label=\"Invoices outstanding\"\n value={summary?.invoicesOutstanding ?? 0}\n format={(v) => money(v)}\n />\n <StatTile label=\"Outstanding invoices\" value={summary?.invoicesOutstandingCount ?? 0} />\n </div>\n <div className=\"grid gap-4 lg:grid-cols-2\">\n {budgetBars.length > 0 && (summary?.budgetAllocated || summary?.budgetSpent) ? (\n <ChartCard title=\"Budget utilization\" subtitle=\"Allocated against spend\">\n <BarsChart\n data={budgetBars}\n xKey=\"metric\"\n series={[{ key: 'value', label: 'Amount' }]}\n orientation=\"horizontal\"\n height={200}\n valueFormat={compactUsd}\n categoryWidth={96}\n ariaLabel=\"Budget allocated versus spent\"\n />\n </ChartCard>\n ) : null}\n {valueSlices.length > 0 ? (\n <ChartCard\n title=\"Value vs depreciation\"\n subtitle=\"Current book value against accumulated depreciation\"\n >\n <DonutChart\n data={valueSlices}\n centerLabel=\"Original cost\"\n centerValue={totalAssetValue + totalDepreciation}\n valueFormat={(v) => money(v)}\n height={220}\n ariaLabel=\"Current value versus accumulated depreciation\"\n />\n </ChartCard>\n ) : null}\n </div>\n </TabsContent>\n\n {/* ─── Maintenance Log ─── */}\n <TabsContent value=\"maintenance\" className=\"mt-4 space-y-4\">\n <div className=\"flex justify-end\">\n <Button size=\"sm\" onClick={exportMaintenance} disabled={maintenance.length === 0}>\n <Download className=\"mr-2 h-4 w-4\" />\n Export CSV\n </Button>\n </div>\n\n {maintenanceSpendByType.length > 0 ? (\n <ChartCard\n title=\"Maintenance spend by type\"\n subtitle=\"Actual cost, falling back to estimates\"\n >\n <BarsChart\n data={maintenanceSpendByType}\n xKey=\"type\"\n series={[{ key: 'cost', label: 'Spend' }]}\n orientation=\"horizontal\"\n height={Math.max(180, maintenanceSpendByType.length * 34)}\n valueFormat={compactUsd}\n categoryWidth={128}\n ariaLabel=\"Maintenance spend by type\"\n />\n </ChartCard>\n ) : null}\n\n <GlassCard treatment=\"glass\" className=\"overflow-hidden border-border-seam\">\n {/* Desktop table */}\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full min-w-[720px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/50 text-left\">\n <th className=\"p-3 font-medium\">Work</th>\n <th className=\"p-3 font-medium\">Asset</th>\n <th className=\"p-3 font-medium\">Type</th>\n <th className=\"p-3 font-medium\">Status</th>\n <th className=\"p-3 font-medium\">Completed</th>\n <th className=\"p-3 text-right font-medium\">Actual Cost</th>\n </tr>\n </thead>\n <tbody>\n {maintenanceLoading ? (\n <SkeletonRows cols={6} />\n ) : (\n maintenancePage.pageItems.map((m) => (\n <tr\n key={m.id}\n className=\"border-b border-border-seam/60 last:border-0 hover:bg-bg-sunken/40\"\n >\n <td className=\"p-3 font-medium\">{m.title}</td>\n <td className=\"p-3\">{assetNameById.get(m.assetId) ?? m.assetId}</td>\n <td className=\"p-3 capitalize\">{m.type.replace(/_/g, ' ')}</td>\n <td className=\"p-3\">\n <StatusPill tone={maintenanceStatusTone(m.status)}>\n {m.status.replace(/_/g, ' ').toLowerCase()}\n </StatusPill>\n </td>\n <td className=\"p-3 text-xs text-text-secondary\">\n {m.completedAt ? new Date(m.completedAt).toLocaleDateString() : '—'}\n </td>\n <td className=\"p-3 text-right tabular-nums\">{money(m.actualCost)}</td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n\n {/* Mobile cards */}\n <div className=\"divide-y divide-border-seam/60 md:hidden\">\n {maintenanceLoading ? (\n <div className=\"space-y-3 p-4\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-16 animate-pulse rounded bg-bg-sunken\" />\n ))}\n </div>\n ) : (\n maintenancePage.pageItems.map((m) => (\n <div key={m.id} className=\"p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"min-w-0 flex-1 truncate font-medium\">{m.title}</p>\n <StatusPill tone={maintenanceStatusTone(m.status)}>\n {m.status.replace(/_/g, ' ').toLowerCase()}\n </StatusPill>\n </div>\n <div className=\"mt-2 flex flex-wrap items-center gap-2 text-xs text-text-secondary\">\n <span className=\"capitalize\">{m.type.replace(/_/g, ' ')}</span>\n <span>· {assetNameById.get(m.assetId) ?? m.assetId}</span>\n {m.actualCost != null ? (\n <span className=\"ml-auto tabular-nums text-text-primary\">\n {money(m.actualCost)}\n </span>\n ) : null}\n </div>\n </div>\n ))\n )}\n </div>\n\n {maintenance.length === 0 && !loading ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No maintenance records\"\n description=\"Logged maintenance work will appear here once scheduled or completed.\"\n />\n ) : (\n <div className=\"px-3\">\n <Pagination\n page={maintenancePage.page}\n pageCount={maintenancePage.pageCount}\n rangeStart={maintenancePage.rangeStart}\n rangeEnd={maintenancePage.rangeEnd}\n totalItems={maintenancePage.totalItems}\n canPrev={maintenancePage.canPrev}\n canNext={maintenancePage.canNext}\n onPrev={maintenancePage.prevPage}\n onNext={maintenancePage.nextPage}\n itemLabel=\"records\"\n />\n </div>\n )}\n </GlassCard>\n </TabsContent>\n\n {/* ─── Utilization ─── */}\n <TabsContent value=\"utilization\" className=\"mt-4 space-y-4\">\n <div className=\"flex justify-end\">\n <Button size=\"sm\" onClick={exportUtilization} disabled={!utilization}>\n <Download className=\"mr-2 h-4 w-4\" />\n Export CSV\n </Button>\n </div>\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-5\">\n <StatTile label=\"Total assets\" value={utilization?.totalAssets ?? 0} />\n <StatTile label=\"Assigned\" value={utilization?.assignedAssets ?? 0} />\n <StatTile label=\"Unassigned\" value={utilization?.unassignedAssets ?? 0} />\n <StatTile label=\"Idle\" value={utilization?.idleAssets ?? 0} />\n <StatTile\n label=\"Overdue assignments\"\n value={utilization?.overdueAssignments ?? 0}\n delta={utilization && utilization.overdueAssignments > 0 ? 'Attention' : undefined}\n deltaTone=\"negative\"\n />\n </div>\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <ChartCard title=\"Assets by status\" subtitle=\"Distribution across lifecycle states\">\n <DonutChart\n data={statusSlices}\n centerLabel=\"Assets\"\n centerValue={utilization?.totalAssets ?? 0}\n height={240}\n emptyLabel=\"No status data available.\"\n ariaLabel=\"Assets by status\"\n />\n </ChartCard>\n <ChartCard title=\"Assignment coverage\" subtitle=\"Assigned, unassigned and idle assets\">\n <DonutChart\n data={coverageSlices}\n centerLabel=\"Assets\"\n centerValue={utilization?.totalAssets ?? 0}\n height={240}\n emptyLabel=\"No coverage data available.\"\n ariaLabel=\"Assignment coverage\"\n />\n </ChartCard>\n </div>\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SamLicensesPage.js","names":[],"sources":["../../../src/assethandler/pages/SamLicensesPage.tsx"],"sourcesContent":["import {\n KeyRound,\n Plus,\n Search,\n Pencil,\n Layers,\n UserCheck,\n UserPlus,\n ShieldCheck,\n} from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport {\n Button,\n GradientText,\n IllustratedEmptyState,\n GlassCard,\n PagePurpose,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n Pagination,\n usePagination,\n StatTile,\n ChartCard,\n DonutChart,\n BarsChart,\n ProgressMeter,\n} from '../components';\nimport { notify } from '../utils/toast';\nimport { cn } from '../utils/cn';\n\nconst SOFTWARE_ASSETS_QUERY = gql`\n query AssetHandlerSoftwareAssets {\n softwareAssets {\n id\n name\n vendor\n version\n licenseType\n seatsPurchased\n seatsUsed\n compliancePercent\n }\n }\n`;\n\nconst UPSERT_SOFTWARE_ASSET_MUTATION = gql`\n mutation AssetHandlerUpsertSoftwareAsset($input: UpsertSoftwareAssetInput!) {\n upsertSoftwareAsset(input: $input) {\n id\n name\n }\n }\n`;\n\ninterface SoftwareAsset {\n id: string;\n name: string;\n vendor: string;\n version: string;\n licenseType: string;\n seatsPurchased: number | null;\n seatsUsed: number | null;\n compliancePercent: number;\n}\n\ninterface UpsertSoftwareAssetResult {\n upsertSoftwareAsset: { id: string; name: string };\n}\n\nconst LICENSE_TYPES = [\n 'PERPETUAL',\n 'SUBSCRIPTION',\n 'CONCURRENT',\n 'NAMED_USER',\n 'OPEN_SOURCE',\n] as const;\n\nconst humanizeLicense = (value: string) =>\n value\n .toLowerCase()\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n\nfunction NewSoftwareAssetDialog({\n open,\n onOpenChange,\n onSaved,\n editing,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSaved: () => void;\n editing: SoftwareAsset | null;\n}) {\n const [name, setName] = useState('');\n const [vendor, setVendor] = useState('');\n const [version, setVersion] = useState('');\n const [licenseType, setLicenseType] = useState<(typeof LICENSE_TYPES)[number]>('SUBSCRIPTION');\n const [seatsPurchased, setSeatsPurchased] = useState('');\n const [seatsUsed, setSeatsUsed] = useState('');\n\n // Prime the form when opening in edit mode.\n const [primedId, setPrimedId] = useState<string | null>(null);\n if (open && editing && primedId !== editing.id) {\n setPrimedId(editing.id);\n setName(editing.name);\n setVendor(editing.vendor);\n setVersion(editing.version);\n setLicenseType(\n (LICENSE_TYPES as readonly string[]).includes(editing.licenseType)\n ? (editing.licenseType as (typeof LICENSE_TYPES)[number])\n : 'SUBSCRIPTION'\n );\n setSeatsPurchased(editing.seatsPurchased != null ? String(editing.seatsPurchased) : '');\n setSeatsUsed(editing.seatsUsed != null ? String(editing.seatsUsed) : '');\n }\n if (open && !editing && primedId !== null) {\n setPrimedId(null);\n }\n\n const reset = () => {\n setName('');\n setVendor('');\n setVersion('');\n setLicenseType('SUBSCRIPTION');\n setSeatsPurchased('');\n setSeatsUsed('');\n setPrimedId(null);\n };\n\n const [upsertAsset, { loading }] = useMutation<UpsertSoftwareAssetResult>(\n UPSERT_SOFTWARE_ASSET_MUTATION,\n {\n onCompleted: (data) => {\n notify.success('Software asset saved', `${data.upsertSoftwareAsset.name} is now tracked.`);\n reset();\n onOpenChange(false);\n onSaved();\n },\n onError: (error) => notify.error('Could not save software asset', error.message),\n }\n );\n\n const handleSubmit = () => {\n if (!name.trim() || !vendor.trim() || !version.trim()) {\n notify.warning('Missing details', 'Name, vendor and version are required.');\n return;\n }\n const optionalInt = (value: string): number | null => {\n const trimmed = value.trim();\n if (trimmed === '') return null;\n const parsed = Number(trimmed);\n return Number.isInteger(parsed) ? parsed : null;\n };\n void upsertAsset({\n variables: {\n input: {\n ...(editing ? { id: editing.id } : {}),\n name: name.trim(),\n vendor: vendor.trim(),\n version: version.trim(),\n licenseType,\n seatsPurchased: optionalInt(seatsPurchased),\n seatsUsed: optionalInt(seatsUsed),\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {editing ? 'Edit Software Asset' : 'New Software Asset'}\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {editing\n ? 'Update this software entitlement and its seat allocation.'\n : 'Register a software entitlement to track license compliance.'}\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Name *</Label>\n <Input value={name} onChange={(e) => setName(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Vendor *</Label>\n <Input value={vendor} onChange={(e) => setVendor(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Version *</Label>\n <Input\n placeholder=\"e.g., 2026.1\"\n value={version}\n onChange={(e) => setVersion(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>License Type</Label>\n <Select\n value={licenseType}\n onValueChange={(v) => setLicenseType(v as typeof licenseType)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {LICENSE_TYPES.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeLicense(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Seats Purchased</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n value={seatsPurchased}\n onChange={(e) => setSeatsPurchased(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Seats Used</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n value={seatsUsed}\n onChange={(e) => setSeatsUsed(e.target.value)}\n />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? 'Saving…' : editing ? 'Save changes' : 'Save asset'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// Compliance bar cell — green when within entitlement, red when over-used.\nfunction ComplianceCell({ asset }: { asset: SoftwareAsset }) {\n const purchased = asset.seatsPurchased ?? 0;\n const used = asset.seatsUsed ?? 0;\n const overUsed = purchased > 0 && used > purchased;\n return (\n <div className=\"min-w-[140px]\">\n <ProgressMeter\n value={Math.min(100, Math.max(0, asset.compliancePercent))}\n max={100}\n higherIsWorse={false}\n size=\"sm\"\n showValue={false}\n />\n <p\n className={cn(\n 'mt-1 text-xs font-medium tabular-nums',\n overUsed ? 'text-status-error-text' : 'text-text-secondary'\n )}\n >\n {asset.compliancePercent.toFixed(1)}%{overUsed ? ' · over-used' : ''}\n </p>\n </div>\n );\n}\n\nexport function SamLicensesPage() {\n const [dialogOpen, setDialogOpen] = useState(false);\n const [editing, setEditing] = useState<SoftwareAsset | null>(null);\n const [search, setSearch] = useState('');\n const [licenseFilter, setLicenseFilter] = useState<string>('all');\n const [sort, setSort] = useState<string>('compliance-asc');\n\n const { data, loading, refetch } = useQuery<{ softwareAssets: SoftwareAsset[] }>(\n SOFTWARE_ASSETS_QUERY,\n { fetchPolicy: 'cache-and-network' }\n );\n\n const softwareAssets = useMemo(() => data?.softwareAssets ?? [], [data]);\n\n // ─── KPI rollups (all real, derived from the fetched list) ───\n const kpis = useMemo(() => {\n let purchased = 0;\n let used = 0;\n for (const a of softwareAssets) {\n purchased += a.seatsPurchased ?? 0;\n used += a.seatsUsed ?? 0;\n }\n const available = Math.max(0, purchased - used);\n // Seats-weighted compliance (fallback to simple average).\n const totalWeight = softwareAssets.reduce((s, a) => s + (a.seatsPurchased ?? 0), 0);\n const compliance =\n totalWeight > 0\n ? softwareAssets.reduce((s, a) => s + a.compliancePercent * (a.seatsPurchased ?? 0), 0) /\n totalWeight\n : softwareAssets.length > 0\n ? softwareAssets.reduce((s, a) => s + a.compliancePercent, 0) / softwareAssets.length\n : 0;\n return { purchased, used, available, compliance };\n }, [softwareAssets]);\n\n const licenseTypeDonut = useMemo(() => {\n const counts = new Map<string, number>();\n for (const a of softwareAssets) counts.set(a.licenseType, (counts.get(a.licenseType) ?? 0) + 1);\n return [...counts.entries()].map(([type, value]) => ({\n name: humanizeLicense(type),\n value,\n }));\n }, [softwareAssets]);\n\n const seatsBars = useMemo(\n () =>\n [...softwareAssets]\n .sort((a, b) => (b.seatsPurchased ?? 0) - (a.seatsPurchased ?? 0))\n .slice(0, 6)\n .map((a) => ({\n name: a.name.length > 18 ? a.name.slice(0, 17) + '…' : a.name,\n purchased: a.seatsPurchased ?? 0,\n used: a.seatsUsed ?? 0,\n })),\n [softwareAssets]\n );\n\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n const rows = softwareAssets.filter((a) => {\n if (licenseFilter !== 'all' && a.licenseType !== licenseFilter) return false;\n if (!q) return true;\n return a.name.toLowerCase().includes(q) || a.vendor.toLowerCase().includes(q);\n });\n const sorted = [...rows];\n switch (sort) {\n case 'compliance-asc':\n sorted.sort((a, b) => a.compliancePercent - b.compliancePercent);\n break;\n case 'compliance-desc':\n sorted.sort((a, b) => b.compliancePercent - a.compliancePercent);\n break;\n case 'seats-desc':\n sorted.sort((a, b) => (b.seatsPurchased ?? 0) - (a.seatsPurchased ?? 0));\n break;\n case 'name-asc':\n sorted.sort((a, b) => a.name.localeCompare(b.name));\n break;\n default:\n break;\n }\n return sorted;\n }, [softwareAssets, search, licenseFilter, sort]);\n\n const pagination = usePagination(filtered, {\n pageSize: 12,\n resetKey: `${search}|${licenseFilter}|${sort}`,\n });\n\n const openCreate = () => {\n setEditing(null);\n setDialogOpen(true);\n };\n const openEdit = (asset: SoftwareAsset) => {\n setEditing(asset);\n setDialogOpen(true);\n };\n\n const hasCharts = softwareAssets.length > 0;\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <p className=\"text-xs font-semibold uppercase tracking-wider text-text-muted\">\n Software Asset Management (SAM / licenses)\n </p>\n <h1 className=\"flex items-center gap-2 text-2xl font-semibold\">\n <KeyRound className=\"h-6 w-6\" /> <GradientText>Software Asset Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Track entitlements against real usage and stay license-compliant.\n </p>\n </div>\n <Button className=\"w-full sm:w-auto\" onClick={openCreate}>\n <Plus className=\"mr-2 h-4 w-4\" />\n Add Software\n </Button>\n </div>\n <PagePurpose>\n Software Asset Management (SAM): track every software entitlement against actual usage so\n you stay license-compliant and stop paying for seats nobody uses. Spot over- and\n under-licensing here to avoid audit penalties and reclaim wasted spend.\n </PagePurpose>\n\n <NewSoftwareAssetDialog\n open={dialogOpen}\n onOpenChange={setDialogOpen}\n onSaved={() => void refetch()}\n editing={editing}\n />\n\n {/* ─── KPI rollups ─── */}\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-4\">\n <StatTile label=\"Total Licenses\" value={kpis.purchased} icon={Layers} hero />\n <StatTile label=\"Seats Used\" value={kpis.used} icon={UserCheck} />\n <StatTile label=\"Seats Available\" value={kpis.available} icon={UserPlus} />\n <StatTile\n label=\"Compliance\"\n value={kpis.compliance}\n format={(v) => `${v.toFixed(1)}%`}\n icon={ShieldCheck}\n deltaTone={kpis.compliance >= 90 ? 'positive' : 'negative'}\n />\n </div>\n\n {/* ─── Charts ─── */}\n {hasCharts ? (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <ChartCard title=\"Licenses by type\" subtitle=\"Entitlement mix\" icon={KeyRound}>\n <DonutChart\n data={licenseTypeDonut}\n height={240}\n centerLabel=\"products\"\n centerValue={softwareAssets.length}\n ariaLabel=\"Software assets by license type\"\n />\n </ChartCard>\n <ChartCard title=\"Seats: purchased vs used\" subtitle=\"Top products by entitlement\">\n <BarsChart\n data={seatsBars}\n xKey=\"name\"\n orientation=\"horizontal\"\n categoryWidth={120}\n height={240}\n series={[\n { key: 'purchased', label: 'Purchased' },\n { key: 'used', label: 'Used' },\n ]}\n ariaLabel=\"Seats purchased versus used per software product\"\n />\n </ChartCard>\n </div>\n ) : null}\n\n {/* ─── Filters ─── */}\n {softwareAssets.length > 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-center\">\n <div className=\"relative flex-1\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-muted\" />\n <Input\n className=\"pl-9\"\n placeholder=\"Search software or vendor…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n <Select value={licenseFilter} onValueChange={setLicenseFilter}>\n <SelectTrigger className=\"w-full sm:w-[170px]\">\n <SelectValue placeholder=\"License type\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All license types</SelectItem>\n {LICENSE_TYPES.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeLicense(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select value={sort} onValueChange={setSort}>\n <SelectTrigger className=\"w-full sm:w-[190px]\">\n <SelectValue placeholder=\"Sort\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"compliance-asc\">Compliance: low → high</SelectItem>\n <SelectItem value=\"compliance-desc\">Compliance: high → low</SelectItem>\n <SelectItem value=\"seats-desc\">Most seats</SelectItem>\n <SelectItem value=\"name-asc\">Name A–Z</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </GlassCard>\n ) : null}\n\n {/* ─── Loading / Empty ─── */}\n {loading && softwareAssets.length === 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"space-y-2 p-4\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n </GlassCard>\n ) : null}\n\n {!loading && softwareAssets.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No software assets found\"\n description=\"Register a software asset to start tracking license compliance.\"\n action={\n <Button onClick={openCreate}>\n <Plus className=\"mr-2 h-4 w-4\" />\n Add Software\n </Button>\n }\n />\n ) : null}\n\n {softwareAssets.length > 0 && filtered.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No matching software\"\n description=\"Adjust your search or filters to see software assets.\"\n />\n ) : null}\n\n {/* ─── Table (desktop) + card list (mobile) ─── */}\n {filtered.length > 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/50 text-xs uppercase tracking-wide text-text-secondary\">\n <th className=\"p-3 text-left font-semibold\">Software</th>\n <th className=\"p-3 text-left font-semibold\">Vendor</th>\n <th className=\"p-3 text-left font-semibold\">Version</th>\n <th className=\"p-3 text-left font-semibold\">License Type</th>\n <th className=\"p-3 text-right font-semibold\">Seats Purchased</th>\n <th className=\"p-3 text-right font-semibold\">Seats Used</th>\n <th className=\"p-3 text-left font-semibold\">Compliance</th>\n <th className=\"p-3 text-right font-semibold\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {pagination.pageItems.map((asset) => (\n <tr\n key={asset.id}\n className=\"cursor-pointer border-b border-border-seam hover:bg-bg-sunken/50\"\n onClick={() => openEdit(asset)}\n >\n <td className=\"max-w-[220px] truncate p-3 font-medium\" title={asset.name}>\n {asset.name}\n </td>\n <td className=\"p-3 text-text-secondary\">{asset.vendor}</td>\n <td className=\"p-3 text-text-secondary\">{asset.version}</td>\n <td className=\"p-3\">\n <span className=\"inline-flex items-center rounded-full bg-status-neutral-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-neutral-text\">\n {humanizeLicense(asset.licenseType)}\n </span>\n </td>\n <td className=\"p-3 text-right tabular-nums\">{asset.seatsPurchased ?? '—'}</td>\n <td className=\"p-3 text-right tabular-nums\">{asset.seatsUsed ?? '—'}</td>\n <td className=\"p-3\">\n <ComplianceCell asset={asset} />\n </td>\n <td className=\"p-3 text-right\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={(e) => {\n e.stopPropagation();\n openEdit(asset);\n }}\n >\n <Pencil className=\"mr-1 h-3.5 w-3.5\" />\n Edit\n </Button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Mobile card list */}\n <div className=\"divide-y divide-border-seam md:hidden\">\n {pagination.pageItems.map((asset) => (\n <div\n key={asset.id}\n className=\"cursor-pointer space-y-2 p-4\"\n onClick={() => openEdit(asset)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium\" title={asset.name}>\n {asset.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {asset.vendor} · v{asset.version}\n </p>\n </div>\n <span className=\"shrink-0 rounded-full bg-status-neutral-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-neutral-text\">\n {humanizeLicense(asset.licenseType)}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-3 text-xs text-text-secondary\">\n <span className=\"tabular-nums\">\n {asset.seatsUsed ?? 0} / {asset.seatsPurchased ?? '—'} seats\n </span>\n </div>\n <ComplianceCell asset={asset} />\n </div>\n ))}\n </div>\n\n <div className=\"px-3\">\n <Pagination\n page={pagination.page}\n pageCount={pagination.pageCount}\n rangeStart={pagination.rangeStart}\n rangeEnd={pagination.rangeEnd}\n totalItems={pagination.totalItems}\n canPrev={pagination.canPrev}\n canNext={pagination.canNext}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"software assets\"\n />\n </div>\n </GlassCard>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SamLicensesPage.js","names":[],"sources":["../../../src/assethandler/pages/SamLicensesPage.tsx"],"sourcesContent":["import {\n KeyRound,\n Plus,\n Search,\n Pencil,\n Layers,\n UserCheck,\n UserPlus,\n ShieldCheck,\n} from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport {\n Button,\n GradientText,\n IllustratedEmptyState,\n GlassCard,\n PagePurpose,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n Pagination,\n usePagination,\n StatTile,\n ChartCard,\n DonutChart,\n BarsChart,\n ProgressMeter,\n} from '../components';\nimport { notify } from '../utils/toast';\nimport { cn } from '../utils/cn';\n\nconst SOFTWARE_ASSETS_QUERY = gql`\n query AssetHandlerSoftwareAssets {\n softwareAssets {\n id\n name\n vendor\n version\n licenseType\n seatsPurchased\n seatsUsed\n compliancePercent\n }\n }\n`;\n\nconst UPSERT_SOFTWARE_ASSET_MUTATION = gql`\n mutation AssetHandlerUpsertSoftwareAsset($input: UpsertSoftwareAssetInput!) {\n upsertSoftwareAsset(input: $input) {\n id\n name\n }\n }\n`;\n\ninterface SoftwareAsset {\n id: string;\n name: string;\n vendor: string;\n version: string;\n licenseType: string;\n seatsPurchased: number | null;\n seatsUsed: number | null;\n compliancePercent: number;\n}\n\ninterface UpsertSoftwareAssetResult {\n upsertSoftwareAsset: { id: string; name: string };\n}\n\nconst LICENSE_TYPES = [\n 'PERPETUAL',\n 'SUBSCRIPTION',\n 'CONCURRENT',\n 'NAMED_USER',\n 'OPEN_SOURCE',\n] as const;\n\nconst humanizeLicense = (value: string) =>\n value\n .toLowerCase()\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n\nfunction NewSoftwareAssetDialog({\n open,\n onOpenChange,\n onSaved,\n editing,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSaved: () => void;\n editing: SoftwareAsset | null;\n}) {\n const [name, setName] = useState('');\n const [vendor, setVendor] = useState('');\n const [version, setVersion] = useState('');\n const [licenseType, setLicenseType] = useState<(typeof LICENSE_TYPES)[number]>('SUBSCRIPTION');\n const [seatsPurchased, setSeatsPurchased] = useState('');\n const [seatsUsed, setSeatsUsed] = useState('');\n\n // Prime the form when opening in edit mode.\n const [primedId, setPrimedId] = useState<string | null>(null);\n if (open && editing && primedId !== editing.id) {\n setPrimedId(editing.id);\n setName(editing.name);\n setVendor(editing.vendor);\n setVersion(editing.version);\n setLicenseType(\n (LICENSE_TYPES as readonly string[]).includes(editing.licenseType)\n ? (editing.licenseType as (typeof LICENSE_TYPES)[number])\n : 'SUBSCRIPTION'\n );\n setSeatsPurchased(editing.seatsPurchased != null ? String(editing.seatsPurchased) : '');\n setSeatsUsed(editing.seatsUsed != null ? String(editing.seatsUsed) : '');\n }\n if (open && !editing && primedId !== null) {\n setPrimedId(null);\n }\n\n const reset = () => {\n setName('');\n setVendor('');\n setVersion('');\n setLicenseType('SUBSCRIPTION');\n setSeatsPurchased('');\n setSeatsUsed('');\n setPrimedId(null);\n };\n\n const [upsertAsset, { loading }] = useMutation<UpsertSoftwareAssetResult>(\n UPSERT_SOFTWARE_ASSET_MUTATION,\n {\n onCompleted: (data) => {\n notify.success('Software asset saved', `${data.upsertSoftwareAsset.name} is now tracked.`);\n reset();\n onOpenChange(false);\n onSaved();\n },\n onError: (error) => notify.error('Could not save software asset', error.message),\n }\n );\n\n const handleSubmit = () => {\n if (!name.trim() || !vendor.trim() || !version.trim()) {\n notify.warning('Missing details', 'Name, vendor and version are required.');\n return;\n }\n const optionalInt = (value: string): number | null => {\n const trimmed = value.trim();\n if (trimmed === '') return null;\n const parsed = Number(trimmed);\n return Number.isInteger(parsed) ? parsed : null;\n };\n void upsertAsset({\n variables: {\n input: {\n ...(editing ? { id: editing.id } : {}),\n name: name.trim(),\n vendor: vendor.trim(),\n version: version.trim(),\n licenseType,\n seatsPurchased: optionalInt(seatsPurchased),\n seatsUsed: optionalInt(seatsUsed),\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {editing ? 'Edit Software Asset' : 'New Software Asset'}\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {editing\n ? 'Update this software entitlement and its seat allocation.'\n : 'Register a software entitlement to track license compliance.'}\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Name *</Label>\n <Input value={name} onChange={(e) => setName(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Vendor *</Label>\n <Input value={vendor} onChange={(e) => setVendor(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Version *</Label>\n <Input\n placeholder=\"e.g., 2026.1\"\n value={version}\n onChange={(e) => setVersion(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>License Type</Label>\n <Select\n value={licenseType}\n onValueChange={(v) => setLicenseType(v as typeof licenseType)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {LICENSE_TYPES.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeLicense(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Seats Purchased</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n value={seatsPurchased}\n onChange={(e) => setSeatsPurchased(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Seats Used</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n value={seatsUsed}\n onChange={(e) => setSeatsUsed(e.target.value)}\n />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? 'Saving…' : editing ? 'Save changes' : 'Save asset'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// Compliance bar cell — green when within entitlement, red when over-used.\nfunction ComplianceCell({ asset }: { asset: SoftwareAsset }) {\n const purchased = asset.seatsPurchased ?? 0;\n const used = asset.seatsUsed ?? 0;\n const overUsed = purchased > 0 && used > purchased;\n return (\n <div className=\"min-w-[140px]\">\n <ProgressMeter\n value={Math.min(100, Math.max(0, asset.compliancePercent))}\n max={100}\n higherIsWorse={false}\n size=\"sm\"\n showValue={false}\n />\n <p\n className={cn(\n 'mt-1 text-xs font-medium tabular-nums',\n overUsed ? 'text-status-error-text' : 'text-text-secondary'\n )}\n >\n {asset.compliancePercent.toFixed(1)}%{overUsed ? ' · over-used' : ''}\n </p>\n </div>\n );\n}\n\nexport function SamLicensesPage() {\n const [dialogOpen, setDialogOpen] = useState(false);\n const [editing, setEditing] = useState<SoftwareAsset | null>(null);\n const [search, setSearch] = useState('');\n const [licenseFilter, setLicenseFilter] = useState<string>('all');\n const [sort, setSort] = useState<string>('compliance-asc');\n\n const { data, loading, refetch } = useQuery<{ softwareAssets: SoftwareAsset[] }>(\n SOFTWARE_ASSETS_QUERY,\n { fetchPolicy: 'cache-and-network' }\n );\n\n const softwareAssets = useMemo(() => data?.softwareAssets ?? [], [data]);\n\n // ─── KPI rollups (all real, derived from the fetched list) ───\n const kpis = useMemo(() => {\n let purchased = 0;\n let used = 0;\n for (const a of softwareAssets) {\n purchased += a.seatsPurchased ?? 0;\n used += a.seatsUsed ?? 0;\n }\n const available = Math.max(0, purchased - used);\n // Seats-weighted compliance (fallback to simple average).\n const totalWeight = softwareAssets.reduce((s, a) => s + (a.seatsPurchased ?? 0), 0);\n const compliance =\n totalWeight > 0\n ? softwareAssets.reduce((s, a) => s + a.compliancePercent * (a.seatsPurchased ?? 0), 0) /\n totalWeight\n : softwareAssets.length > 0\n ? softwareAssets.reduce((s, a) => s + a.compliancePercent, 0) / softwareAssets.length\n : 0;\n return { purchased, used, available, compliance };\n }, [softwareAssets]);\n\n const licenseTypeDonut = useMemo(() => {\n const counts = new Map<string, number>();\n for (const a of softwareAssets) counts.set(a.licenseType, (counts.get(a.licenseType) ?? 0) + 1);\n return [...counts.entries()].map(([type, value]) => ({\n name: humanizeLicense(type),\n value,\n }));\n }, [softwareAssets]);\n\n const seatsBars = useMemo(\n () =>\n [...softwareAssets]\n .sort((a, b) => (b.seatsPurchased ?? 0) - (a.seatsPurchased ?? 0))\n .slice(0, 6)\n .map((a) => ({\n name: a.name.length > 18 ? a.name.slice(0, 17) + '…' : a.name,\n purchased: a.seatsPurchased ?? 0,\n used: a.seatsUsed ?? 0,\n })),\n [softwareAssets]\n );\n\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n const rows = softwareAssets.filter((a) => {\n if (licenseFilter !== 'all' && a.licenseType !== licenseFilter) return false;\n if (!q) return true;\n return a.name.toLowerCase().includes(q) || a.vendor.toLowerCase().includes(q);\n });\n const sorted = [...rows];\n switch (sort) {\n case 'compliance-asc':\n sorted.sort((a, b) => a.compliancePercent - b.compliancePercent);\n break;\n case 'compliance-desc':\n sorted.sort((a, b) => b.compliancePercent - a.compliancePercent);\n break;\n case 'seats-desc':\n sorted.sort((a, b) => (b.seatsPurchased ?? 0) - (a.seatsPurchased ?? 0));\n break;\n case 'name-asc':\n sorted.sort((a, b) => a.name.localeCompare(b.name));\n break;\n default:\n break;\n }\n return sorted;\n }, [softwareAssets, search, licenseFilter, sort]);\n\n const pagination = usePagination(filtered, {\n pageSize: 12,\n resetKey: `${search}|${licenseFilter}|${sort}`,\n });\n\n const openCreate = () => {\n setEditing(null);\n setDialogOpen(true);\n };\n const openEdit = (asset: SoftwareAsset) => {\n setEditing(asset);\n setDialogOpen(true);\n };\n\n const hasCharts = softwareAssets.length > 0;\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <p className=\"text-xs font-semibold uppercase tracking-wider text-text-muted\">\n Software Asset Management (SAM / licenses)\n </p>\n <h1 className=\"flex items-center gap-2 text-2xl font-semibold\">\n <KeyRound className=\"h-6 w-6\" /> <GradientText>Software Asset Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Track entitlements against real usage and stay license-compliant.\n </p>\n </div>\n <Button className=\"w-full sm:w-auto\" onClick={openCreate}>\n <Plus className=\"mr-2 h-4 w-4\" />\n Add Software\n </Button>\n </div>\n <PagePurpose>\n Software Asset Management (SAM): track every software entitlement against actual usage so\n you stay license-compliant and stop paying for seats nobody uses. Spot over- and\n under-licensing here to avoid audit penalties and reclaim wasted spend.\n </PagePurpose>\n\n <NewSoftwareAssetDialog\n open={dialogOpen}\n onOpenChange={setDialogOpen}\n onSaved={() => void refetch()}\n editing={editing}\n />\n\n {/* ─── KPI rollups ─── */}\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-4\">\n <StatTile label=\"Total Licenses\" value={kpis.purchased} icon={Layers} hero />\n <StatTile label=\"Seats Used\" value={kpis.used} icon={UserCheck} />\n <StatTile label=\"Seats Available\" value={kpis.available} icon={UserPlus} />\n <StatTile\n label=\"Compliance\"\n value={kpis.compliance}\n format={(v) => `${v.toFixed(1)}%`}\n icon={ShieldCheck}\n deltaTone={kpis.compliance >= 90 ? 'positive' : 'negative'}\n />\n </div>\n\n {/* ─── Charts ─── */}\n {hasCharts ? (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <ChartCard title=\"Licenses by type\" subtitle=\"Entitlement mix\" icon={KeyRound}>\n <DonutChart\n data={licenseTypeDonut}\n height={240}\n centerLabel=\"products\"\n centerValue={softwareAssets.length}\n ariaLabel=\"Software assets by license type\"\n />\n </ChartCard>\n <ChartCard title=\"Seats: purchased vs used\" subtitle=\"Top products by entitlement\">\n <BarsChart\n data={seatsBars}\n xKey=\"name\"\n orientation=\"horizontal\"\n categoryWidth={120}\n height={240}\n series={[\n { key: 'purchased', label: 'Purchased' },\n { key: 'used', label: 'Used' },\n ]}\n ariaLabel=\"Seats purchased versus used per software product\"\n />\n </ChartCard>\n </div>\n ) : null}\n\n {/* ─── Filters ─── */}\n {softwareAssets.length > 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-center\">\n <div className=\"relative flex-1\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-muted\" />\n <Input\n className=\"pl-9\"\n placeholder=\"Search software or vendor…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n <Select value={licenseFilter} onValueChange={setLicenseFilter}>\n <SelectTrigger className=\"w-full sm:w-[170px]\">\n <SelectValue placeholder=\"License type\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All license types</SelectItem>\n {LICENSE_TYPES.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeLicense(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select value={sort} onValueChange={setSort}>\n <SelectTrigger className=\"w-full sm:w-[190px]\">\n <SelectValue placeholder=\"Sort\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"compliance-asc\">Compliance: low → high</SelectItem>\n <SelectItem value=\"compliance-desc\">Compliance: high → low</SelectItem>\n <SelectItem value=\"seats-desc\">Most seats</SelectItem>\n <SelectItem value=\"name-asc\">Name A–Z</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </GlassCard>\n ) : null}\n\n {/* ─── Loading / Empty ─── */}\n {loading && softwareAssets.length === 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"space-y-2 p-4\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n </GlassCard>\n ) : null}\n\n {!loading && softwareAssets.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No software assets found\"\n description=\"Register a software asset to start tracking license compliance.\"\n action={\n <Button onClick={openCreate}>\n <Plus className=\"mr-2 h-4 w-4\" />\n Add Software\n </Button>\n }\n />\n ) : null}\n\n {softwareAssets.length > 0 && filtered.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No matching software\"\n description=\"Adjust your search or filters to see software assets.\"\n />\n ) : null}\n\n {/* ─── Table (desktop) + card list (mobile) ─── */}\n {filtered.length > 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/50 text-xs uppercase tracking-wide text-text-secondary\">\n <th className=\"p-3 text-left font-semibold\">Software</th>\n <th className=\"p-3 text-left font-semibold\">Vendor</th>\n <th className=\"p-3 text-left font-semibold\">Version</th>\n <th className=\"p-3 text-left font-semibold\">License Type</th>\n <th className=\"p-3 text-right font-semibold\">Seats Purchased</th>\n <th className=\"p-3 text-right font-semibold\">Seats Used</th>\n <th className=\"p-3 text-left font-semibold\">Compliance</th>\n <th className=\"p-3 text-right font-semibold\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {pagination.pageItems.map((asset) => (\n <tr\n key={asset.id}\n className=\"cursor-pointer border-b border-border-seam hover:bg-bg-sunken/50\"\n onClick={() => openEdit(asset)}\n >\n <td className=\"max-w-[220px] truncate p-3 font-medium\" title={asset.name}>\n {asset.name}\n </td>\n <td className=\"p-3 text-text-secondary\">{asset.vendor}</td>\n <td className=\"p-3 text-text-secondary\">{asset.version}</td>\n <td className=\"p-3\">\n <span className=\"inline-flex items-center rounded-full bg-status-neutral-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-neutral-text\">\n {humanizeLicense(asset.licenseType)}\n </span>\n </td>\n <td className=\"p-3 text-right tabular-nums\">{asset.seatsPurchased ?? '—'}</td>\n <td className=\"p-3 text-right tabular-nums\">{asset.seatsUsed ?? '—'}</td>\n <td className=\"p-3\">\n <ComplianceCell asset={asset} />\n </td>\n <td className=\"p-3 text-right\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={(e) => {\n e.stopPropagation();\n openEdit(asset);\n }}\n >\n <Pencil className=\"mr-1 h-3.5 w-3.5\" />\n Edit\n </Button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Mobile card list */}\n <div className=\"divide-y divide-border-seam md:hidden\">\n {pagination.pageItems.map((asset) => (\n <div\n key={asset.id}\n className=\"cursor-pointer space-y-2 p-4\"\n onClick={() => openEdit(asset)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium\" title={asset.name}>\n {asset.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {asset.vendor} · v{asset.version}\n </p>\n </div>\n <span className=\"shrink-0 rounded-full bg-status-neutral-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-neutral-text\">\n {humanizeLicense(asset.licenseType)}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-3 text-xs text-text-secondary\">\n <span className=\"tabular-nums\">\n {asset.seatsUsed ?? 0} / {asset.seatsPurchased ?? '—'} seats\n </span>\n </div>\n <ComplianceCell asset={asset} />\n </div>\n ))}\n </div>\n\n <div className=\"px-3\">\n <Pagination\n page={pagination.page}\n pageCount={pagination.pageCount}\n rangeStart={pagination.rangeStart}\n rangeEnd={pagination.rangeEnd}\n totalItems={pagination.totalItems}\n canPrev={pagination.canPrev}\n canNext={pagination.canNext}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"software assets\"\n />\n </div>\n </GlassCard>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SecurityComplianceDetailPage.js","names":[],"sources":["../../../src/assethandler/pages/SecurityComplianceDetailPage.tsx"],"sourcesContent":["import { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n GradientText,\n EmphasisPanel,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { ArrowLeft, Shield } from 'lucide-react';\nimport { useParams } from 'react-router';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { notify } from '../utils/toast';\nimport { AttachmentsPanel, CommentsPanel, ActivityTimeline, NotFoundState } from '../components';\n\nconst COMPLIANCE_QUERY = gql`\n query AssetHandlerComplianceFramework($id: ID!) {\n complianceFramework(id: $id) {\n id\n name\n version\n status\n score\n totalControls\n passedControls\n failedControls\n lastAssessment\n nextAssessment\n lastAssessedAt\n }\n }\n`;\n\ninterface ComplianceRecord {\n id: string;\n name: string;\n version: string;\n status: string;\n score: number;\n totalControls: number;\n passedControls: number;\n failedControls: number;\n lastAssessment: string;\n nextAssessment: string;\n lastAssessedAt?: string | null;\n}\n\ninterface ComplianceQueryResult {\n complianceFramework: ComplianceRecord | null;\n}\n\nconst RUN_ASSESSMENT_MUTATION = gql`\n mutation AssetHandlerRunComplianceAssessment($frameworkId: ID!) {\n runComplianceAssessment(frameworkId: $frameworkId) {\n id\n score\n lastAssessedAt\n }\n }\n`;\n\nexport function SecurityComplianceDetailPage() {\n const navigate = useAssetHandlerNavigate();\n const { frameworkId } = useParams<{ frameworkId: string }>();\n\n const { data, loading, refetch } = useQuery<ComplianceQueryResult>(COMPLIANCE_QUERY, {\n variables: { id: frameworkId ?? '' },\n skip: !frameworkId,\n fetchPolicy: 'cache-and-network',\n });\n\n const [runAssessment, { loading: running }] = useMutation(RUN_ASSESSMENT_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Assessment complete', 'The framework score has been refreshed.');\n void refetch();\n },\n onError: (error) => notify.error('Could not run assessment', error.message),\n });\n\n if (loading && !data) {\n return (\n <div className=\"space-y-3 p-6\">\n {Array.from({ length: 6 }).map((_, i) => (\n <div key={i} className=\"h-10 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n );\n }\n\n const raw = data?.complianceFramework;\n if (!raw) {\n return (\n <NotFoundState\n entityLabel=\"Framework\"\n description=\"This compliance framework may have been removed. Return to the security hub to find it.\"\n backLabel=\"Back to security\"\n onBack={() => navigate('/security/security-hub')}\n />\n );\n }\n\n const framework = { ...raw, status: raw.status.toLowerCase() };\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex items-center gap-4\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label=\"Go back\"\n onClick={() => navigate('/security/security-hub')}\n >\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <div>\n <div className=\"flex items-center gap-3\">\n <h1 className=\"text-2xl font-bold\">\n <GradientText>\n {framework.name} {framework.version}\n </GradientText>\n </h1>\n <Badge\n variant={\n framework.status === 'compliant'\n ? 'default'\n : framework.status === 'non_compliant'\n ? 'destructive'\n : 'secondary'\n }\n >\n {framework.status.replace('_', ' ')}\n </Badge>\n </div>\n <p className=\"text-sm text-text-secondary mt-1\">\n Compliance framework assessment details\n </p>\n </div>\n </div>\n <Button\n size=\"sm\"\n onClick={() => void runAssessment({ variables: { frameworkId: framework.id } })}\n disabled={running}\n >\n <Shield className=\"mr-2 h-4 w-4\" />\n {running ? 'Running…' : 'Run Assessment'}\n </Button>\n </div>\n\n <PagePurpose>\n See exactly how you measure up against a single compliance framework — your overall score,\n which controls pass or fail, and when the next assessment is due. Use it to close control\n gaps and stay audit-ready for standards like ISO 27001 or SOC 2.\n </PagePurpose>\n\n <div className=\"grid gap-4 md:grid-cols-4\">\n <EmphasisPanel className=\"text-center\">\n <p className=\"text-4xl font-bold tabular-nums\">{framework.score}%</p>\n <p className=\"text-xs text-text-secondary\">Overall Score</p>\n </EmphasisPanel>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <p className=\"text-4xl font-bold text-status-success-text\">\n {framework.passedControls}\n </p>\n <p className=\"text-xs text-text-secondary\">Passed</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <p className=\"text-4xl font-bold text-status-error-text\">{framework.failedControls}</p>\n <p className=\"text-xs text-text-secondary\">Failed</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <p className=\"text-4xl font-bold\">{framework.totalControls}</p>\n <p className=\"text-xs text-text-secondary\">Total Controls</p>\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Compliance Progress</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"h-4 rounded-full bg-bg-sunken overflow-hidden\">\n <div\n className={`h-full rounded-full ${framework.score >= 90 ? 'bg-status-success-bg' : framework.score >= 70 ? 'bg-status-warning-bg' : 'bg-status-error-bg'}`}\n style={{ width: `${framework.score}%` }}\n />\n </div>\n <div className=\"flex flex-wrap justify-between gap-2 mt-2 text-xs text-text-secondary\">\n <span>Last Assessment: {framework.lastAssessment}</span>\n {framework.lastAssessedAt ? (\n <span>Last Run: {new Date(framework.lastAssessedAt).toLocaleString()}</span>\n ) : null}\n <span>Next Assessment: {framework.nextAssessment}</span>\n </div>\n </CardContent>\n </Card>\n\n <Tabs defaultValue=\"attachments\">\n <TabsList>\n <TabsTrigger value=\"attachments\">Evidence</TabsTrigger>\n <TabsTrigger value=\"discussion\">Discussion</TabsTrigger>\n </TabsList>\n <TabsContent value=\"attachments\" className=\"mt-4\">\n <AttachmentsPanel\n entityType=\"assethandler-compliance-framework\"\n entityId={framework.id}\n />\n </TabsContent>\n <TabsContent value=\"discussion\" className=\"mt-4 space-y-6\">\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <CommentsPanel entityType=\"assethandler-compliance-framework\" entityId={framework.id} />\n <ActivityTimeline resourceId={framework.id} />\n </div>\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SecurityComplianceDetailPage.js","names":[],"sources":["../../../src/assethandler/pages/SecurityComplianceDetailPage.tsx"],"sourcesContent":["import { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n GradientText,\n EmphasisPanel,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { ArrowLeft, Shield } from 'lucide-react';\nimport { useParams } from 'react-router';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { notify } from '../utils/toast';\nimport { AttachmentsPanel, CommentsPanel, ActivityTimeline, NotFoundState } from '../components';\n\nconst COMPLIANCE_QUERY = gql`\n query AssetHandlerComplianceFramework($id: ID!) {\n complianceFramework(id: $id) {\n id\n name\n version\n status\n score\n totalControls\n passedControls\n failedControls\n lastAssessment\n nextAssessment\n lastAssessedAt\n }\n }\n`;\n\ninterface ComplianceRecord {\n id: string;\n name: string;\n version: string;\n status: string;\n score: number;\n totalControls: number;\n passedControls: number;\n failedControls: number;\n lastAssessment: string;\n nextAssessment: string;\n lastAssessedAt?: string | null;\n}\n\ninterface ComplianceQueryResult {\n complianceFramework: ComplianceRecord | null;\n}\n\nconst RUN_ASSESSMENT_MUTATION = gql`\n mutation AssetHandlerRunComplianceAssessment($frameworkId: ID!) {\n runComplianceAssessment(frameworkId: $frameworkId) {\n id\n score\n lastAssessedAt\n }\n }\n`;\n\nexport function SecurityComplianceDetailPage() {\n const navigate = useAssetHandlerNavigate();\n const { frameworkId } = useParams<{ frameworkId: string }>();\n\n const { data, loading, refetch } = useQuery<ComplianceQueryResult>(COMPLIANCE_QUERY, {\n variables: { id: frameworkId ?? '' },\n skip: !frameworkId,\n fetchPolicy: 'cache-and-network',\n });\n\n const [runAssessment, { loading: running }] = useMutation(RUN_ASSESSMENT_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Assessment complete', 'The framework score has been refreshed.');\n void refetch();\n },\n onError: (error) => notify.error('Could not run assessment', error.message),\n });\n\n if (loading && !data) {\n return (\n <div className=\"space-y-3 p-6\">\n {Array.from({ length: 6 }).map((_, i) => (\n <div key={i} className=\"h-10 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n );\n }\n\n const raw = data?.complianceFramework;\n if (!raw) {\n return (\n <NotFoundState\n entityLabel=\"Framework\"\n description=\"This compliance framework may have been removed. Return to the security hub to find it.\"\n backLabel=\"Back to security\"\n onBack={() => navigate('/security/security-hub')}\n />\n );\n }\n\n const framework = { ...raw, status: raw.status.toLowerCase() };\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex items-center gap-4\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label=\"Go back\"\n onClick={() => navigate('/security/security-hub')}\n >\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <div>\n <div className=\"flex items-center gap-3\">\n <h1 className=\"text-2xl font-bold\">\n <GradientText>\n {framework.name} {framework.version}\n </GradientText>\n </h1>\n <Badge\n variant={\n framework.status === 'compliant'\n ? 'default'\n : framework.status === 'non_compliant'\n ? 'destructive'\n : 'secondary'\n }\n >\n {framework.status.replace('_', ' ')}\n </Badge>\n </div>\n <p className=\"text-sm text-text-secondary mt-1\">\n Compliance framework assessment details\n </p>\n </div>\n </div>\n <Button\n size=\"sm\"\n onClick={() => void runAssessment({ variables: { frameworkId: framework.id } })}\n disabled={running}\n >\n <Shield className=\"mr-2 h-4 w-4\" />\n {running ? 'Running…' : 'Run Assessment'}\n </Button>\n </div>\n\n <PagePurpose>\n See exactly how you measure up against a single compliance framework — your overall score,\n which controls pass or fail, and when the next assessment is due. Use it to close control\n gaps and stay audit-ready for standards like ISO 27001 or SOC 2.\n </PagePurpose>\n\n <div className=\"grid gap-4 md:grid-cols-4\">\n <EmphasisPanel className=\"text-center\">\n <p className=\"text-4xl font-bold tabular-nums\">{framework.score}%</p>\n <p className=\"text-xs text-text-secondary\">Overall Score</p>\n </EmphasisPanel>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <p className=\"text-4xl font-bold text-status-success-text\">\n {framework.passedControls}\n </p>\n <p className=\"text-xs text-text-secondary\">Passed</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <p className=\"text-4xl font-bold text-status-error-text\">{framework.failedControls}</p>\n <p className=\"text-xs text-text-secondary\">Failed</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <p className=\"text-4xl font-bold\">{framework.totalControls}</p>\n <p className=\"text-xs text-text-secondary\">Total Controls</p>\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Compliance Progress</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"h-4 rounded-full bg-bg-sunken overflow-hidden\">\n <div\n className={`h-full rounded-full ${framework.score >= 90 ? 'bg-status-success-bg' : framework.score >= 70 ? 'bg-status-warning-bg' : 'bg-status-error-bg'}`}\n style={{ width: `${framework.score}%` }}\n />\n </div>\n <div className=\"flex flex-wrap justify-between gap-2 mt-2 text-xs text-text-secondary\">\n <span>Last Assessment: {framework.lastAssessment}</span>\n {framework.lastAssessedAt ? (\n <span>Last Run: {new Date(framework.lastAssessedAt).toLocaleString()}</span>\n ) : null}\n <span>Next Assessment: {framework.nextAssessment}</span>\n </div>\n </CardContent>\n </Card>\n\n <Tabs defaultValue=\"attachments\">\n <TabsList>\n <TabsTrigger value=\"attachments\">Evidence</TabsTrigger>\n <TabsTrigger value=\"discussion\">Discussion</TabsTrigger>\n </TabsList>\n <TabsContent value=\"attachments\" className=\"mt-4\">\n <AttachmentsPanel\n entityType=\"assethandler-compliance-framework\"\n entityId={framework.id}\n />\n </TabsContent>\n <TabsContent value=\"discussion\" className=\"mt-4 space-y-6\">\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <CommentsPanel entityType=\"assethandler-compliance-framework\" entityId={framework.id} />\n <ActivityTimeline resourceId={framework.id} />\n </div>\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAuBA,IAAM,IAAmB,CAAG;;;;;;;;;;;;;;;;GAoCtB,IAA0B,CAAG;;;;;;;;;AAUnC,SAAgB,IAA+B;CAC7C,IAAM,IAAW,EAAwB,GACnC,EAAE,mBAAgB,EAAmC,GAErD,EAAE,SAAM,YAAS,eAAY,EAAgC,GAAkB;EACnF,WAAW,EAAE,IAAI,KAAe,GAAG;EACnC,MAAM,CAAC;EACP,aAAa;CACf,CAAC,GAEK,CAAC,GAAe,EAAE,SAAS,OAAa,EAAY,GAAyB;EACjF,gBAAgB,CAAC,uBAAuB;EACxC,mBAAmB;GAEjB,AADA,EAAO,QAAQ,uBAAuB,yCAAyC,GAC/E,EAAa;EACf;EACA,UAAU,MAAU,EAAO,MAAM,4BAA4B,EAAM,OAAO;CAC5E,CAAC;CAED,IAAI,KAAW,CAAC,GACd,OACE,kBAAC,OAAD;EAAK,WAAU;YACZ,MAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,GAAG,MACjC,kBAAC,OAAD,EAAa,WAAU,8DAA+D,GAA5E,CAA4E,CACvF;CACE,CAAA;CAIT,IAAM,IAAM,GAAM;CAClB,IAAI,CAAC,GACH,OACE,kBAAC,GAAD;EACE,aAAY;EACZ,aAAY;EACZ,WAAU;EACV,cAAc,EAAS,wBAAwB;CAChD,CAAA;CAIL,IAAM,IAAY;EAAE,GAAG;EAAK,QAAQ,EAAI,OAAO,YAAY;CAAE;CAE7D,OACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,SAAQ;MACR,MAAK;MACL,cAAW;MACX,eAAe,EAAS,wBAAwB;gBAEhD,kBAAC,GAAD,EAAW,WAAU,UAAW,CAAA;KAC1B,CAAA,GACR,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBACZ,kBAAC,GAAD,EAAA,UAAA;QACG,EAAU;QAAK;QAAE,EAAU;OAChB,EAAA,CAAA;MACZ,CAAA,GACJ,kBAAC,GAAD;OACE,SACE,EAAU,WAAW,cACjB,YACA,EAAU,WAAW,kBACnB,gBACA;iBAGP,EAAU,OAAO,QAAQ,KAAK,GAAG;MAC7B,CAAA,CACJ;SACL,kBAAC,KAAD;MAAG,WAAU;gBAAmC;KAE7C,CAAA,CACA,EAAA,CAAA,CACF;QACL,kBAAC,GAAD;KACE,MAAK;KACL,eAAe,KAAK,EAAc,EAAE,WAAW,EAAE,aAAa,EAAU,GAAG,EAAE,CAAC;KAC9E,UAAU;eAHZ,CAKE,kBAAC,GAAD,EAAQ,WAAU,eAAgB,CAAA,GACjC,IAAU,aAAa,gBAClB;MACL;;GAEL,kBAAC,GAAD,EAAA,UAAa,wPAIA,CAAA;GAEb,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MAAe,WAAU;gBAAzB,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAb,CAAgD,EAAU,OAAM,GAAI;UACpE,kBAAC,KAAD;OAAG,WAAU;iBAA8B;MAAgB,CAAA,CAC9C;;KACf,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAU;MACV,CAAA,GACH,kBAAC,KAAD;OAAG,WAAU;iBAA8B;MAAS,CAAA,CACzC;QACT,CAAA;KACN,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,KAAD;OAAG,WAAU;iBAA6C,EAAU;MAAkB,CAAA,GACtF,kBAAC,KAAD;OAAG,WAAU;iBAA8B;MAAS,CAAA,CACzC;QACT,CAAA;KACN,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAsB,EAAU;MAAiB,CAAA,GAC9D,kBAAC,KAAD;OAAG,WAAU;iBAA8B;MAAiB,CAAA,CACjD;QACT,CAAA;IACH;;GAEL,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAW,sBAA8B,CAAA,EAC/B,CAAA,GACZ,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KACE,WAAW,uBAAuB,EAAU,SAAS,KAAK,yBAAyB,EAAU,SAAS,KAAK,yBAAyB;KACpI,OAAO,EAAE,OAAO,GAAG,EAAU,MAAM,GAAG;IACvC,CAAA;GACE,CAAA,GACL,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,QAAD,EAAA,UAAA,CAAM,qBAAkB,EAAU,cAAqB,EAAA,CAAA;KACtD,EAAU,iBACT,kBAAC,QAAD,EAAA,UAAA,CAAM,cAAW,IAAI,KAAK,EAAU,cAAc,EAAE,eAAe,CAAQ,EAAA,CAAA,IACzE;KACJ,kBAAC,QAAD,EAAA,UAAA,CAAM,qBAAkB,EAAU,cAAqB,EAAA,CAAA;IACpD;KACM,EAAA,CAAA,CACT,EAAA,CAAA;GAEN,kBAAC,GAAD;IAAM,cAAa;cAAnB;KACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAa,OAAM;gBAAc;KAAqB,CAAA,GACtD,kBAAC,GAAD;MAAa,OAAM;gBAAa;KAAuB,CAAA,CAC/C,EAAA,CAAA;KACV,kBAAC,GAAD;MAAa,OAAM;MAAc,WAAU;gBACzC,kBAAC,GAAD;OACE,YAAW;OACX,UAAU,EAAU;MACrB,CAAA;KACU,CAAA;KACb,kBAAC,GAAD;MAAa,OAAM;MAAa,WAAU;gBACxC,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAe,YAAW;QAAoC,UAAU,EAAU;OAAK,CAAA,GACvF,kBAAC,GAAD,EAAkB,YAAY,EAAU,GAAK,CAAA,CAC1C;;KACM,CAAA;IACT;;EACH;;AAET"}