@burdenoff/microfe-ecoimpacthub 2026.720.3 → 2026.720.5
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.
- package/dist/_virtual/_rolldown/runtime.js +1 -1
- package/dist/ecoimpacthub/EcoImpactHubRoot.js.map +1 -1
- package/dist/ecoimpacthub/EcoImpactHubRoutes.js.map +1 -1
- package/dist/ecoimpacthub/components/DashboardCustomizerDialog.d.ts +11 -0
- package/dist/ecoimpacthub/components/DashboardCustomizerDialog.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/DashboardCustomizerDialog.js +182 -0
- package/dist/ecoimpacthub/components/DashboardCustomizerDialog.js.map +1 -0
- package/dist/ecoimpacthub/components/DataTable.js.map +1 -1
- package/dist/ecoimpacthub/components/EcoDiscussion.js.map +1 -1
- package/dist/ecoimpacthub/components/EcoTags.js.map +1 -1
- package/dist/ecoimpacthub/components/EmptyState.js.map +1 -1
- package/dist/ecoimpacthub/components/EvidenceUpload.js.map +1 -1
- package/dist/ecoimpacthub/components/FeatureFlagGate.js.map +1 -1
- package/dist/ecoimpacthub/components/FileLink.js.map +1 -1
- package/dist/ecoimpacthub/components/FilterTabs.js.map +1 -1
- package/dist/ecoimpacthub/components/MetricsCard.js.map +1 -1
- package/dist/ecoimpacthub/components/MiniBar.js.map +1 -1
- package/dist/ecoimpacthub/components/PageLayout.js.map +1 -1
- package/dist/ecoimpacthub/components/Pagination.js.map +1 -1
- package/dist/ecoimpacthub/components/StateViews.js.map +1 -1
- package/dist/ecoimpacthub/components/StatusBadge.js.map +1 -1
- package/dist/ecoimpacthub/components/Tabs.js.map +1 -1
- package/dist/ecoimpacthub/context/EcoImpactHubContext.js.map +1 -1
- package/dist/ecoimpacthub/hooks/index.d.ts +1 -0
- package/dist/ecoimpacthub/hooks/index.d.ts.map +1 -1
- package/dist/ecoimpacthub/hooks/index.js +1 -0
- package/dist/ecoimpacthub/hooks/useCursorPager.js.map +1 -1
- package/dist/ecoimpacthub/hooks/useDashboardLayout.d.ts +29 -0
- package/dist/ecoimpacthub/hooks/useDashboardLayout.d.ts.map +1 -0
- package/dist/ecoimpacthub/hooks/useDashboardLayout.js +95 -0
- package/dist/ecoimpacthub/hooks/useDashboardLayout.js.map +1 -0
- package/dist/ecoimpacthub/hooks/useEcoComments.js.map +1 -1
- package/dist/ecoimpacthub/hooks/useEcoFiles.js.map +1 -1
- package/dist/ecoimpacthub/hooks/useEcoImpactHubApi.js.map +1 -1
- package/dist/ecoimpacthub/hooks/useEcoTags.js.map +1 -1
- package/dist/ecoimpacthub/pages/DashboardPage.d.ts +7 -0
- package/dist/ecoimpacthub/pages/DashboardPage.d.ts.map +1 -1
- package/dist/ecoimpacthub/pages/DashboardPage.js +505 -447
- package/dist/ecoimpacthub/pages/DashboardPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/_shared/ConservationBadge.js.map +1 -1
- package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.js.map +1 -1
- package/dist/ecoimpacthub/pages/_shared/MethodBadge.js.map +1 -1
- package/dist/ecoimpacthub/pages/_shared/TaxonChip.js.map +1 -1
- package/dist/ecoimpacthub/pages/badges.js.map +1 -1
- package/dist/ecoimpacthub/pages/carbon/CarbonPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/carbonVisuals.js.map +1 -1
- package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.js.map +1 -1
- package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/observations/ObservationsPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/reports/ReportDetailPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/reports/ReportsPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/sites/SiteDetailPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/sites/SitesPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.js.map +1 -1
- package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/species/SpeciesPage.js.map +1 -1
- package/dist/ecoimpacthub/services/createSandboxAssistantTransport.d.ts.map +1 -1
- package/dist/ecoimpacthub/services/createSandboxAssistantTransport.js.map +1 -1
- package/dist/ecoimpacthub/types/index.d.ts.map +1 -1
- package/dist/ecoimpacthub/utils/cn.js.map +1 -1
- package/dist/ecoimpacthub/utils/formatters.js.map +1 -1
- package/dist/ecoimpacthub/utils/navigation.js.map +1 -1
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -1
- package/dist/node_modules/d3-array/src/ascending.js.map +1 -1
- package/dist/node_modules/d3-array/src/bisect.js.map +1 -1
- package/dist/node_modules/d3-array/src/bisector.js.map +1 -1
- package/dist/node_modules/d3-array/src/descending.js.map +1 -1
- package/dist/node_modules/d3-array/src/max.js.map +1 -1
- package/dist/node_modules/d3-array/src/min.js.map +1 -1
- package/dist/node_modules/d3-array/src/number.js.map +1 -1
- package/dist/node_modules/d3-array/src/quantile.js.map +1 -1
- package/dist/node_modules/d3-array/src/quickselect.js.map +1 -1
- package/dist/node_modules/d3-array/src/range.js.map +1 -1
- package/dist/node_modules/d3-array/src/sort.js.map +1 -1
- package/dist/node_modules/d3-array/src/ticks.js.map +1 -1
- package/dist/node_modules/d3-color/src/color.js.map +1 -1
- package/dist/node_modules/d3-color/src/define.js.map +1 -1
- package/dist/node_modules/d3-format/src/defaultLocale.js.map +1 -1
- package/dist/node_modules/d3-format/src/exponent.js.map +1 -1
- package/dist/node_modules/d3-format/src/formatDecimal.js.map +1 -1
- package/dist/node_modules/d3-format/src/formatGroup.js.map +1 -1
- package/dist/node_modules/d3-format/src/formatNumerals.js.map +1 -1
- package/dist/node_modules/d3-format/src/formatPrefixAuto.js.map +1 -1
- package/dist/node_modules/d3-format/src/formatRounded.js.map +1 -1
- package/dist/node_modules/d3-format/src/formatSpecifier.js.map +1 -1
- package/dist/node_modules/d3-format/src/formatTrim.js.map +1 -1
- package/dist/node_modules/d3-format/src/formatTypes.js.map +1 -1
- package/dist/node_modules/d3-format/src/identity.js.map +1 -1
- package/dist/node_modules/d3-format/src/locale.js.map +1 -1
- package/dist/node_modules/d3-format/src/precisionFixed.js.map +1 -1
- package/dist/node_modules/d3-format/src/precisionPrefix.js.map +1 -1
- package/dist/node_modules/d3-format/src/precisionRound.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/array.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/basis.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/basisClosed.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/color.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/date.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/number.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/numberArray.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/object.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/piecewise.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/rgb.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/round.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/string.js.map +1 -1
- package/dist/node_modules/d3-interpolate/src/value.js.map +1 -1
- package/dist/node_modules/d3-path/src/path.js.map +1 -1
- package/dist/node_modules/d3-scale/src/band.js.map +1 -1
- package/dist/node_modules/d3-scale/src/constant.js.map +1 -1
- package/dist/node_modules/d3-scale/src/continuous.js.map +1 -1
- package/dist/node_modules/d3-scale/src/diverging.js.map +1 -1
- package/dist/node_modules/d3-scale/src/identity.js.map +1 -1
- package/dist/node_modules/d3-scale/src/init.js.map +1 -1
- package/dist/node_modules/d3-scale/src/linear.js.map +1 -1
- package/dist/node_modules/d3-scale/src/log.js.map +1 -1
- package/dist/node_modules/d3-scale/src/nice.js.map +1 -1
- package/dist/node_modules/d3-scale/src/number.js.map +1 -1
- package/dist/node_modules/d3-scale/src/ordinal.js.map +1 -1
- package/dist/node_modules/d3-scale/src/pow.js.map +1 -1
- package/dist/node_modules/d3-scale/src/quantile.js.map +1 -1
- package/dist/node_modules/d3-scale/src/quantize.js.map +1 -1
- package/dist/node_modules/d3-scale/src/radial.js.map +1 -1
- package/dist/node_modules/d3-scale/src/sequential.js.map +1 -1
- package/dist/node_modules/d3-scale/src/sequentialQuantile.js.map +1 -1
- package/dist/node_modules/d3-scale/src/symlog.js.map +1 -1
- package/dist/node_modules/d3-scale/src/threshold.js.map +1 -1
- package/dist/node_modules/d3-scale/src/tickFormat.js.map +1 -1
- package/dist/node_modules/d3-scale/src/time.js.map +1 -1
- package/dist/node_modules/d3-scale/src/utcTime.js.map +1 -1
- package/dist/node_modules/d3-shape/src/area.js.map +1 -1
- package/dist/node_modules/d3-shape/src/array.js.map +1 -1
- package/dist/node_modules/d3-shape/src/constant.js.map +1 -1
- package/dist/node_modules/d3-shape/src/curve/basis.js.map +1 -1
- package/dist/node_modules/d3-shape/src/curve/basisClosed.js.map +1 -1
- package/dist/node_modules/d3-shape/src/curve/basisOpen.js.map +1 -1
- package/dist/node_modules/d3-shape/src/curve/bump.js.map +1 -1
- package/dist/node_modules/d3-shape/src/curve/linear.js.map +1 -1
- package/dist/node_modules/d3-shape/src/curve/linearClosed.js.map +1 -1
- package/dist/node_modules/d3-shape/src/curve/monotone.js.map +1 -1
- package/dist/node_modules/d3-shape/src/curve/natural.js.map +1 -1
- package/dist/node_modules/d3-shape/src/curve/step.js.map +1 -1
- package/dist/node_modules/d3-shape/src/line.js.map +1 -1
- package/dist/node_modules/d3-shape/src/noop.js.map +1 -1
- package/dist/node_modules/d3-shape/src/offset/expand.js.map +1 -1
- package/dist/node_modules/d3-shape/src/offset/none.js.map +1 -1
- package/dist/node_modules/d3-shape/src/offset/silhouette.js.map +1 -1
- package/dist/node_modules/d3-shape/src/offset/wiggle.js.map +1 -1
- package/dist/node_modules/d3-shape/src/order/none.js.map +1 -1
- package/dist/node_modules/d3-shape/src/path.js.map +1 -1
- package/dist/node_modules/d3-shape/src/point.js.map +1 -1
- package/dist/node_modules/d3-shape/src/stack.js.map +1 -1
- package/dist/node_modules/d3-shape/src/symbol/circle.js.map +1 -1
- package/dist/node_modules/d3-shape/src/symbol/cross.js.map +1 -1
- package/dist/node_modules/d3-shape/src/symbol/diamond.js.map +1 -1
- package/dist/node_modules/d3-shape/src/symbol/square.js.map +1 -1
- package/dist/node_modules/d3-shape/src/symbol/star.js.map +1 -1
- package/dist/node_modules/d3-shape/src/symbol/triangle.js.map +1 -1
- package/dist/node_modules/d3-shape/src/symbol/wye.js.map +1 -1
- package/dist/node_modules/d3-shape/src/symbol.js.map +1 -1
- package/dist/node_modules/d3-time/src/day.js.map +1 -1
- package/dist/node_modules/d3-time/src/hour.js.map +1 -1
- package/dist/node_modules/d3-time/src/interval.js.map +1 -1
- package/dist/node_modules/d3-time/src/millisecond.js.map +1 -1
- package/dist/node_modules/d3-time/src/minute.js.map +1 -1
- package/dist/node_modules/d3-time/src/month.js.map +1 -1
- package/dist/node_modules/d3-time/src/second.js.map +1 -1
- package/dist/node_modules/d3-time/src/ticks.js.map +1 -1
- package/dist/node_modules/d3-time/src/week.js.map +1 -1
- package/dist/node_modules/d3-time/src/year.js.map +1 -1
- package/dist/node_modules/d3-time-format/src/defaultLocale.js.map +1 -1
- package/dist/node_modules/d3-time-format/src/locale.js.map +1 -1
- package/dist/node_modules/decimal.js-light/decimal.js.map +1 -1
- package/dist/node_modules/eventemitter3/index.js.map +1 -1
- package/dist/node_modules/fast-equals/dist/es/index.js.map +1 -1
- package/dist/node_modules/internmap/src/index.js.map +1 -1
- package/dist/node_modules/lodash/_DataView.js.map +1 -1
- package/dist/node_modules/lodash/_Hash.js.map +1 -1
- package/dist/node_modules/lodash/_ListCache.js.map +1 -1
- package/dist/node_modules/lodash/_Map.js.map +1 -1
- package/dist/node_modules/lodash/_MapCache.js.map +1 -1
- package/dist/node_modules/lodash/_Promise.js.map +1 -1
- package/dist/node_modules/lodash/_Set.js.map +1 -1
- package/dist/node_modules/lodash/_SetCache.js.map +1 -1
- package/dist/node_modules/lodash/_Stack.js +2 -1
- package/dist/node_modules/lodash/_Stack.js.map +1 -1
- package/dist/node_modules/lodash/_Symbol.js.map +1 -1
- package/dist/node_modules/lodash/_Uint8Array.js.map +1 -1
- package/dist/node_modules/lodash/_WeakMap.js.map +1 -1
- package/dist/node_modules/lodash/_apply.js.map +1 -1
- package/dist/node_modules/lodash/_arrayEvery.js.map +1 -1
- package/dist/node_modules/lodash/_arrayFilter.js.map +1 -1
- package/dist/node_modules/lodash/_arrayIncludes.js.map +1 -1
- package/dist/node_modules/lodash/_arrayIncludesWith.js.map +1 -1
- package/dist/node_modules/lodash/_arrayLikeKeys.js.map +1 -1
- package/dist/node_modules/lodash/_arrayMap.js.map +1 -1
- package/dist/node_modules/lodash/_arrayPush.js.map +1 -1
- package/dist/node_modules/lodash/_arraySome.js.map +1 -1
- package/dist/node_modules/lodash/_asciiToArray.js.map +1 -1
- package/dist/node_modules/lodash/_assocIndexOf.js.map +1 -1
- package/dist/node_modules/lodash/_baseAssignValue.js.map +1 -1
- package/dist/node_modules/lodash/_baseEach.js.map +1 -1
- package/dist/node_modules/lodash/_baseEvery.js.map +1 -1
- package/dist/node_modules/lodash/_baseExtremum.js.map +1 -1
- package/dist/node_modules/lodash/_baseFindIndex.js.map +1 -1
- package/dist/node_modules/lodash/_baseFlatten.js.map +1 -1
- package/dist/node_modules/lodash/_baseFor.js.map +1 -1
- package/dist/node_modules/lodash/_baseForOwn.js.map +1 -1
- package/dist/node_modules/lodash/_baseGet.js.map +1 -1
- package/dist/node_modules/lodash/_baseGetAllKeys.js.map +1 -1
- package/dist/node_modules/lodash/_baseGetTag.js.map +1 -1
- package/dist/node_modules/lodash/_baseGt.js.map +1 -1
- package/dist/node_modules/lodash/_baseHasIn.js.map +1 -1
- package/dist/node_modules/lodash/_baseIndexOf.js.map +1 -1
- package/dist/node_modules/lodash/_baseIsArguments.js.map +1 -1
- package/dist/node_modules/lodash/_baseIsEqual.js.map +1 -1
- package/dist/node_modules/lodash/_baseIsEqualDeep.js.map +1 -1
- package/dist/node_modules/lodash/_baseIsMatch.js.map +1 -1
- package/dist/node_modules/lodash/_baseIsNaN.js.map +1 -1
- package/dist/node_modules/lodash/_baseIsNative.js.map +1 -1
- package/dist/node_modules/lodash/_baseIsTypedArray.js.map +1 -1
- package/dist/node_modules/lodash/_baseIteratee.js.map +1 -1
- package/dist/node_modules/lodash/_baseKeys.js.map +1 -1
- package/dist/node_modules/lodash/_baseLt.js.map +1 -1
- package/dist/node_modules/lodash/_baseMap.js.map +1 -1
- package/dist/node_modules/lodash/_baseMatches.js.map +1 -1
- package/dist/node_modules/lodash/_baseMatchesProperty.js.map +1 -1
- package/dist/node_modules/lodash/_baseOrderBy.js.map +1 -1
- package/dist/node_modules/lodash/_baseProperty.js.map +1 -1
- package/dist/node_modules/lodash/_basePropertyDeep.js.map +1 -1
- package/dist/node_modules/lodash/_baseRange.js.map +1 -1
- package/dist/node_modules/lodash/_baseRest.js.map +1 -1
- package/dist/node_modules/lodash/_baseSetToString.js.map +1 -1
- package/dist/node_modules/lodash/_baseSlice.js.map +1 -1
- package/dist/node_modules/lodash/_baseSome.js.map +1 -1
- package/dist/node_modules/lodash/_baseSortBy.js.map +1 -1
- package/dist/node_modules/lodash/_baseTimes.js.map +1 -1
- package/dist/node_modules/lodash/_baseToString.js.map +1 -1
- package/dist/node_modules/lodash/_baseTrim.js.map +1 -1
- package/dist/node_modules/lodash/_baseUnary.js.map +1 -1
- package/dist/node_modules/lodash/_baseUniq.js.map +1 -1
- package/dist/node_modules/lodash/_cacheHas.js.map +1 -1
- package/dist/node_modules/lodash/_castPath.js.map +1 -1
- package/dist/node_modules/lodash/_castSlice.js.map +1 -1
- package/dist/node_modules/lodash/_compareAscending.js.map +1 -1
- package/dist/node_modules/lodash/_compareMultiple.js.map +1 -1
- package/dist/node_modules/lodash/_coreJsData.js.map +1 -1
- package/dist/node_modules/lodash/_createBaseEach.js.map +1 -1
- package/dist/node_modules/lodash/_createBaseFor.js.map +1 -1
- package/dist/node_modules/lodash/_createCaseFirst.js.map +1 -1
- package/dist/node_modules/lodash/_createFind.js.map +1 -1
- package/dist/node_modules/lodash/_createRange.js.map +1 -1
- package/dist/node_modules/lodash/_createSet.js.map +1 -1
- package/dist/node_modules/lodash/_defineProperty.js.map +1 -1
- package/dist/node_modules/lodash/_equalArrays.js.map +1 -1
- package/dist/node_modules/lodash/_equalByTag.js.map +1 -1
- package/dist/node_modules/lodash/_equalObjects.js.map +1 -1
- package/dist/node_modules/lodash/_freeGlobal.js.map +1 -1
- package/dist/node_modules/lodash/_getAllKeys.js.map +1 -1
- package/dist/node_modules/lodash/_getMapData.js.map +1 -1
- package/dist/node_modules/lodash/_getMatchData.js.map +1 -1
- package/dist/node_modules/lodash/_getNative.js.map +1 -1
- package/dist/node_modules/lodash/_getPrototype.js.map +1 -1
- package/dist/node_modules/lodash/_getRawTag.js.map +1 -1
- package/dist/node_modules/lodash/_getSymbols.js.map +1 -1
- package/dist/node_modules/lodash/_getTag.js.map +1 -1
- package/dist/node_modules/lodash/_getValue.js.map +1 -1
- package/dist/node_modules/lodash/_hasPath.js.map +1 -1
- package/dist/node_modules/lodash/_hasUnicode.js.map +1 -1
- package/dist/node_modules/lodash/_hashClear.js.map +1 -1
- package/dist/node_modules/lodash/_hashDelete.js.map +1 -1
- package/dist/node_modules/lodash/_hashGet.js.map +1 -1
- package/dist/node_modules/lodash/_hashHas.js.map +1 -1
- package/dist/node_modules/lodash/_hashSet.js.map +1 -1
- package/dist/node_modules/lodash/_isFlattenable.js.map +1 -1
- package/dist/node_modules/lodash/_isIndex.js.map +1 -1
- package/dist/node_modules/lodash/_isIterateeCall.js.map +1 -1
- package/dist/node_modules/lodash/_isKey.js.map +1 -1
- package/dist/node_modules/lodash/_isKeyable.js.map +1 -1
- package/dist/node_modules/lodash/_isMasked.js.map +1 -1
- package/dist/node_modules/lodash/_isPrototype.js.map +1 -1
- package/dist/node_modules/lodash/_isStrictComparable.js.map +1 -1
- package/dist/node_modules/lodash/_listCacheClear.js.map +1 -1
- package/dist/node_modules/lodash/_listCacheDelete.js.map +1 -1
- package/dist/node_modules/lodash/_listCacheGet.js.map +1 -1
- package/dist/node_modules/lodash/_listCacheHas.js.map +1 -1
- package/dist/node_modules/lodash/_listCacheSet.js.map +1 -1
- package/dist/node_modules/lodash/_mapCacheClear.js.map +1 -1
- package/dist/node_modules/lodash/_mapCacheDelete.js.map +1 -1
- package/dist/node_modules/lodash/_mapCacheGet.js.map +1 -1
- package/dist/node_modules/lodash/_mapCacheHas.js.map +1 -1
- package/dist/node_modules/lodash/_mapCacheSet.js.map +1 -1
- package/dist/node_modules/lodash/_mapToArray.js.map +1 -1
- package/dist/node_modules/lodash/_matchesStrictComparable.js.map +1 -1
- package/dist/node_modules/lodash/_memoizeCapped.js.map +1 -1
- package/dist/node_modules/lodash/_nativeCreate.js.map +1 -1
- package/dist/node_modules/lodash/_nativeKeys.js.map +1 -1
- package/dist/node_modules/lodash/_nodeUtil.js.map +1 -1
- package/dist/node_modules/lodash/_objectToString.js.map +1 -1
- package/dist/node_modules/lodash/_overArg.js.map +1 -1
- package/dist/node_modules/lodash/_overRest.js.map +1 -1
- package/dist/node_modules/lodash/_root.js.map +1 -1
- package/dist/node_modules/lodash/_setCacheAdd.js.map +1 -1
- package/dist/node_modules/lodash/_setCacheHas.js.map +1 -1
- package/dist/node_modules/lodash/_setToArray.js.map +1 -1
- package/dist/node_modules/lodash/_setToString.js.map +1 -1
- package/dist/node_modules/lodash/_shortOut.js.map +1 -1
- package/dist/node_modules/lodash/_stackClear.js.map +1 -1
- package/dist/node_modules/lodash/_stackDelete.js.map +1 -1
- package/dist/node_modules/lodash/_stackGet.js.map +1 -1
- package/dist/node_modules/lodash/_stackHas.js.map +1 -1
- package/dist/node_modules/lodash/_stackSet.js.map +1 -1
- package/dist/node_modules/lodash/_strictIndexOf.js.map +1 -1
- package/dist/node_modules/lodash/_stringToArray.js.map +1 -1
- package/dist/node_modules/lodash/_stringToPath.js.map +1 -1
- package/dist/node_modules/lodash/_toKey.js.map +1 -1
- package/dist/node_modules/lodash/_toSource.js.map +1 -1
- package/dist/node_modules/lodash/_trimmedEndIndex.js.map +1 -1
- package/dist/node_modules/lodash/_unicodeToArray.js.map +1 -1
- package/dist/node_modules/lodash/constant.js.map +1 -1
- package/dist/node_modules/lodash/debounce.js.map +1 -1
- package/dist/node_modules/lodash/eq.js.map +1 -1
- package/dist/node_modules/lodash/every.js.map +1 -1
- package/dist/node_modules/lodash/find.js.map +1 -1
- package/dist/node_modules/lodash/findIndex.js.map +1 -1
- package/dist/node_modules/lodash/flatMap.js.map +1 -1
- package/dist/node_modules/lodash/get.js.map +1 -1
- package/dist/node_modules/lodash/hasIn.js.map +1 -1
- package/dist/node_modules/lodash/identity.js.map +1 -1
- package/dist/node_modules/lodash/isArguments.js.map +1 -1
- package/dist/node_modules/lodash/isArray.js.map +1 -1
- package/dist/node_modules/lodash/isArrayLike.js.map +1 -1
- package/dist/node_modules/lodash/isBoolean.js.map +1 -1
- package/dist/node_modules/lodash/isBuffer.js.map +1 -1
- package/dist/node_modules/lodash/isEqual.js.map +1 -1
- package/dist/node_modules/lodash/isFunction.js.map +1 -1
- package/dist/node_modules/lodash/isLength.js.map +1 -1
- package/dist/node_modules/lodash/isNaN.js.map +1 -1
- package/dist/node_modules/lodash/isNil.js.map +1 -1
- package/dist/node_modules/lodash/isNumber.js.map +1 -1
- package/dist/node_modules/lodash/isObject.js.map +1 -1
- package/dist/node_modules/lodash/isObjectLike.js.map +1 -1
- package/dist/node_modules/lodash/isPlainObject.js.map +1 -1
- package/dist/node_modules/lodash/isString.js.map +1 -1
- package/dist/node_modules/lodash/isSymbol.js.map +1 -1
- package/dist/node_modules/lodash/isTypedArray.js.map +1 -1
- package/dist/node_modules/lodash/keys.js.map +1 -1
- package/dist/node_modules/lodash/last.js.map +1 -1
- package/dist/node_modules/lodash/map.js.map +1 -1
- package/dist/node_modules/lodash/mapValues.js.map +1 -1
- package/dist/node_modules/lodash/max.js.map +1 -1
- package/dist/node_modules/lodash/memoize.js.map +1 -1
- package/dist/node_modules/lodash/min.js.map +1 -1
- package/dist/node_modules/lodash/noop.js.map +1 -1
- package/dist/node_modules/lodash/now.js.map +1 -1
- package/dist/node_modules/lodash/property.js.map +1 -1
- package/dist/node_modules/lodash/range.js.map +1 -1
- package/dist/node_modules/lodash/some.js.map +1 -1
- package/dist/node_modules/lodash/sortBy.js.map +1 -1
- package/dist/node_modules/lodash/stubArray.js.map +1 -1
- package/dist/node_modules/lodash/stubFalse.js.map +1 -1
- package/dist/node_modules/lodash/throttle.js.map +1 -1
- package/dist/node_modules/lodash/toFinite.js.map +1 -1
- package/dist/node_modules/lodash/toInteger.js.map +1 -1
- package/dist/node_modules/lodash/toNumber.js.map +1 -1
- package/dist/node_modules/lodash/toString.js.map +1 -1
- package/dist/node_modules/lodash/uniqBy.js.map +1 -1
- package/dist/node_modules/lodash/upperFirst.js.map +1 -1
- package/dist/node_modules/object-assign/index.js.map +1 -1
- package/dist/node_modules/prop-types/checkPropTypes.js.map +1 -1
- package/dist/node_modules/prop-types/factoryWithThrowingShims.js.map +1 -1
- package/dist/node_modules/prop-types/factoryWithTypeCheckers.js.map +1 -1
- package/dist/node_modules/prop-types/index.js.map +1 -1
- package/dist/node_modules/prop-types/lib/ReactPropTypesSecret.js.map +1 -1
- package/dist/node_modules/prop-types/lib/has.js.map +1 -1
- package/dist/node_modules/prop-types/node_modules/react-is/cjs/react-is.development.js.map +1 -1
- package/dist/node_modules/prop-types/node_modules/react-is/cjs/react-is.production.min.js.map +1 -1
- package/dist/node_modules/prop-types/node_modules/react-is/index.js.map +1 -1
- package/dist/node_modules/react-is/cjs/react-is.development.js.map +1 -1
- package/dist/node_modules/react-is/cjs/react-is.production.min.js.map +1 -1
- package/dist/node_modules/react-is/index.js.map +1 -1
- package/dist/node_modules/react-smooth/es6/Animate.js +2 -2
- package/dist/node_modules/react-smooth/es6/Animate.js.map +1 -1
- package/dist/node_modules/react-smooth/es6/AnimateManager.js.map +1 -1
- package/dist/node_modules/react-smooth/es6/configUpdate.js.map +1 -1
- package/dist/node_modules/react-smooth/es6/easing.js.map +1 -1
- package/dist/node_modules/react-smooth/es6/setRafTimeout.js.map +1 -1
- package/dist/node_modules/react-smooth/es6/util.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/Bar.js +9 -9
- package/dist/node_modules/recharts/es6/cartesian/Bar.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/Brush.js +12 -12
- package/dist/node_modules/recharts/es6/cartesian/Brush.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/CartesianAxis.js +7 -7
- package/dist/node_modules/recharts/es6/cartesian/CartesianAxis.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js +13 -13
- package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/ErrorBar.js +4 -4
- package/dist/node_modules/recharts/es6/cartesian/ErrorBar.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/ReferenceArea.js +3 -3
- package/dist/node_modules/recharts/es6/cartesian/ReferenceArea.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/ReferenceDot.js +3 -3
- package/dist/node_modules/recharts/es6/cartesian/ReferenceDot.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/ReferenceLine.js +4 -4
- package/dist/node_modules/recharts/es6/cartesian/ReferenceLine.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/XAxis.js +3 -3
- package/dist/node_modules/recharts/es6/cartesian/XAxis.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/YAxis.js +3 -3
- package/dist/node_modules/recharts/es6/cartesian/YAxis.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/getEquidistantTicks.js.map +1 -1
- package/dist/node_modules/recharts/es6/cartesian/getTicks.js.map +1 -1
- package/dist/node_modules/recharts/es6/chart/AccessibilityManager.js +1 -1
- package/dist/node_modules/recharts/es6/chart/AccessibilityManager.js.map +1 -1
- package/dist/node_modules/recharts/es6/chart/BarChart.js.map +1 -1
- package/dist/node_modules/recharts/es6/chart/generateCategoricalChart.js +22 -22
- package/dist/node_modules/recharts/es6/chart/generateCategoricalChart.js.map +1 -1
- package/dist/node_modules/recharts/es6/component/Cell.js.map +1 -1
- package/dist/node_modules/recharts/es6/component/Cursor.js +1 -1
- package/dist/node_modules/recharts/es6/component/Cursor.js.map +1 -1
- package/dist/node_modules/recharts/es6/component/DefaultLegendContent.js +11 -11
- package/dist/node_modules/recharts/es6/component/DefaultLegendContent.js.map +1 -1
- package/dist/node_modules/recharts/es6/component/DefaultTooltipContent.js +6 -6
- package/dist/node_modules/recharts/es6/component/DefaultTooltipContent.js.map +1 -1
- package/dist/node_modules/recharts/es6/component/Label.js +14 -14
- package/dist/node_modules/recharts/es6/component/Label.js.map +1 -1
- package/dist/node_modules/recharts/es6/component/LabelList.js +6 -6
- package/dist/node_modules/recharts/es6/component/LabelList.js.map +1 -1
- package/dist/node_modules/recharts/es6/component/Legend.js +5 -5
- package/dist/node_modules/recharts/es6/component/Legend.js.map +1 -1
- package/dist/node_modules/recharts/es6/component/ResponsiveContainer.js +3 -3
- package/dist/node_modules/recharts/es6/component/ResponsiveContainer.js.map +1 -1
- package/dist/node_modules/recharts/es6/component/Text.js +2 -2
- package/dist/node_modules/recharts/es6/component/Text.js.map +1 -1
- package/dist/node_modules/recharts/es6/component/Tooltip.js +3 -3
- package/dist/node_modules/recharts/es6/component/Tooltip.js.map +1 -1
- package/dist/node_modules/recharts/es6/component/TooltipBoundingBox.js +2 -2
- package/dist/node_modules/recharts/es6/component/TooltipBoundingBox.js.map +1 -1
- package/dist/node_modules/recharts/es6/container/Layer.js +2 -2
- package/dist/node_modules/recharts/es6/container/Layer.js.map +1 -1
- package/dist/node_modules/recharts/es6/container/Surface.js +2 -2
- package/dist/node_modules/recharts/es6/container/Surface.js.map +1 -1
- package/dist/node_modules/recharts/es6/context/chartLayoutContext.js +2 -2
- package/dist/node_modules/recharts/es6/context/chartLayoutContext.js.map +1 -1
- package/dist/node_modules/recharts/es6/shape/Cross.js +1 -1
- package/dist/node_modules/recharts/es6/shape/Cross.js.map +1 -1
- package/dist/node_modules/recharts/es6/shape/Curve.js +1 -1
- package/dist/node_modules/recharts/es6/shape/Curve.js.map +1 -1
- package/dist/node_modules/recharts/es6/shape/Dot.js +1 -1
- package/dist/node_modules/recharts/es6/shape/Dot.js.map +1 -1
- package/dist/node_modules/recharts/es6/shape/Rectangle.js +4 -4
- package/dist/node_modules/recharts/es6/shape/Rectangle.js.map +1 -1
- package/dist/node_modules/recharts/es6/shape/Sector.js +1 -1
- package/dist/node_modules/recharts/es6/shape/Sector.js.map +1 -1
- package/dist/node_modules/recharts/es6/shape/Symbols.js +1 -1
- package/dist/node_modules/recharts/es6/shape/Symbols.js.map +1 -1
- package/dist/node_modules/recharts/es6/shape/Trapezoid.js +4 -4
- package/dist/node_modules/recharts/es6/shape/Trapezoid.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/ActiveShapeUtils.js +9 -9
- package/dist/node_modules/recharts/es6/util/ActiveShapeUtils.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/BarUtils.js +1 -1
- package/dist/node_modules/recharts/es6/util/BarUtils.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/CartesianUtils.js +1 -1
- package/dist/node_modules/recharts/es6/util/CartesianUtils.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/ChartUtils.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/CssPrefixUtils.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/DOMUtils.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/DataUtils.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/DetectReferenceElementsDomain.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/Events.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/Global.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/IfOverflowMatches.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/LogUtils.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/PolarUtils.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/ReactUtils.js +1 -1
- package/dist/node_modules/recharts/es6/util/ReactUtils.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/ReduceCSSCalc.js +1 -1
- package/dist/node_modules/recharts/es6/util/ReduceCSSCalc.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/ShallowEqual.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/TickUtils.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/calculateViewBox.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/cursor/getCursorPoints.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/cursor/getCursorRectangle.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/cursor/getRadialCursorPoints.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/getEveryNthWithCondition.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/getLegendProps.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/isDomainSpecifiedByUser.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/payload/getUniqPayload.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/tooltip/translate.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/types.js +1 -1
- package/dist/node_modules/recharts/es6/util/types.js.map +1 -1
- package/dist/node_modules/recharts-scale/es6/getNiceTickValues.js.map +1 -1
- package/dist/node_modules/recharts-scale/es6/util/arithmetic.js.map +1 -1
- package/dist/node_modules/recharts-scale/es6/util/utils.js.map +1 -1
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1 -1
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -1
- package/dist/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarbonPage.js","names":[],"sources":["../../../../src/ecoimpacthub/pages/carbon/CarbonPage.tsx"],"sourcesContent":["/**\n * Carbon & Sustainability — the GHG accounting hub.\n * @module ecoimpacthub/pages/carbon\n *\n * A KPI strip of Scope 1/2/3 + total footprint (from `ecoCarbonTotalKg`) over a\n * three-tab workspace:\n * - Ledger — `ecoListCarbonEntries` (+ `ecoRecordCarbonEntry` / `ecoVerifyCarbonEntry`)\n * - Emission factors — `ecoListEmissionFactors` (+ `ecoCreateEmissionFactor`)\n * - Reduction targets — `ecoListReductionTargets` (+ `ecoCreateReductionTarget`,\n * `ecoSetReductionTargetStatus`)\n *\n * CO₂e (`co2eKg`) is computed server-side from `activityValue × factor`. No mock data.\n */\n\nimport { useMemo, useState, type ReactNode } from 'react';\nimport { Plus, Factory, Flame, Zap, Truck, Leaf, Target } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\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 { PageLayout } from '../../components/PageLayout';\nimport { MetricsCard } from '../../components/MetricsCard';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataTable, type Column } from '../../components/DataTable';\nimport { Tabs, type TabItem } from '../../components/Tabs';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Pagination } from '../../components/Pagination';\nimport { ScopeSplitBar, Meter, SCOPE_HUE } from '../carbonVisuals';\nimport {\n useEcoSites,\n useEcoCarbonTotals,\n useEcoCarbonEntries,\n useEcoRecordCarbonEntry,\n useEcoVerifyCarbonEntry,\n useEcoEmissionFactors,\n useEcoCreateEmissionFactor,\n useEcoReductionTargets,\n useEcoCreateReductionTarget,\n useEcoSetReductionTargetStatus,\n useCursorPager,\n} from '../../hooks';\nimport {\n formatCo2e,\n formatNumber,\n formatDate,\n formatEnumLabel,\n formatPercent,\n} from '../../utils/formatters';\nimport type {\n EcoCarbonEntry,\n EcoCarbonEntryStatus,\n EcoEmissionFactor,\n EcoEmissionScope,\n EcoReductionTarget,\n EcoReductionTargetStatus,\n} from '../../types';\n\ntype CarbonTab = 'ledger' | 'factors' | 'targets';\n\nconst SCOPES: EcoEmissionScope[] = ['SCOPE_1', 'SCOPE_2', 'SCOPE_3'];\nconst CARBON_STATUSES: EcoCarbonEntryStatus[] = ['DRAFT', 'RECORDED', 'VERIFIED', 'ADJUSTED'];\nconst TARGET_STATUSES: EcoReductionTargetStatus[] = [\n 'PROPOSED',\n 'ACTIVE',\n 'ACHIEVED',\n 'MISSED',\n 'RETIRED',\n];\n\nconst PAGE_SIZE = 25;\n\nconst today = (): string => new Date().toISOString().slice(0, 10);\n\ninterface EntryFormState {\n category: string;\n scope: EcoEmissionScope;\n activityValue: string;\n activityUnit: string;\n factorId: string;\n siteId: string;\n periodStart: string;\n notes: string;\n}\n\nconst EMPTY_ENTRY: EntryFormState = {\n category: '',\n scope: 'SCOPE_1',\n activityValue: '',\n activityUnit: '',\n factorId: '',\n siteId: '',\n periodStart: '',\n notes: '',\n};\n\ninterface FactorFormState {\n name: string;\n scope: EcoEmissionScope;\n activityUnit: string;\n factorKgco2e: string;\n source: string;\n validYear: string;\n}\n\nconst EMPTY_FACTOR: FactorFormState = {\n name: '',\n scope: 'SCOPE_1',\n activityUnit: '',\n factorKgco2e: '',\n source: '',\n validYear: '',\n};\n\ninterface TargetFormState {\n name: string;\n metric: string;\n baselineValue: string;\n baselineYear: string;\n targetValue: string;\n targetYear: string;\n unit: string;\n description: string;\n}\n\nconst EMPTY_TARGET: TargetFormState = {\n name: '',\n metric: '',\n baselineValue: '',\n baselineYear: '',\n targetValue: '',\n targetYear: '',\n unit: '',\n description: '',\n};\n\nconst clampPercent = (value: number): number => Math.max(0, Math.min(100, value));\n\n/** Reduction-target progress meter tint by lifecycle status (semantic tokens). */\nconst TARGET_METER_COLOR: Record<EcoReductionTargetStatus, string> = {\n PROPOSED: 'var(--color-text-tertiary)',\n ACTIVE: 'var(--color-action-primary-bg)',\n ACHIEVED: 'var(--color-status-success-text)',\n MISSED: 'var(--color-status-error-text)',\n RETIRED: 'var(--color-text-tertiary)',\n};\n\n/** KPI-card footer: this scope's share of the total footprint, tinted by scope. */\nconst renderScopeShare = (\n value: number | undefined,\n total: number | undefined,\n scope: EcoEmissionScope\n): ReactNode => {\n if (value == null || total == null || total <= 0) return undefined;\n const pct = (value / total) * 100;\n return (\n <div className=\"space-y-2\">\n <Meter value={pct} color={SCOPE_HUE[scope]} height={4} />\n <p className=\"text-xs tabular-nums text-text-tertiary\">{formatPercent(pct)} of total</p>\n </div>\n );\n};\n\nexport function CarbonPage() {\n const [activeTab, setActiveTab] = useState<CarbonTab>('ledger');\n\n // Ledger filters\n const [scope, setScope] = useState<EcoEmissionScope | 'ALL'>('ALL');\n const [entryStatus, setEntryStatus] = useState<EcoCarbonEntryStatus | 'ALL'>('ALL');\n const [ledgerSiteId, setLedgerSiteId] = useState<string>('ALL');\n const ledgerPager = useCursorPager();\n\n // Section filters\n const [factorScope, setFactorScope] = useState<EcoEmissionScope | 'ALL'>('ALL');\n const [targetStatus, setTargetStatus] = useState<EcoReductionTargetStatus | 'ALL'>('ALL');\n\n // Dialog + form state\n const [entryOpen, setEntryOpen] = useState(false);\n const [entryForm, setEntryForm] = useState<EntryFormState>(EMPTY_ENTRY);\n const [factorOpen, setFactorOpen] = useState(false);\n const [factorForm, setFactorForm] = useState<FactorFormState>(EMPTY_FACTOR);\n const [targetOpen, setTargetOpen] = useState(false);\n const [targetForm, setTargetForm] = useState<TargetFormState>(EMPTY_TARGET);\n const [formError, setFormError] = useState<string | null>(null);\n\n // Data\n const sites = useEcoSites({ pagination: { limit: 100, offset: 0 } });\n const siteMap = useMemo<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n for (const s of sites.data?.items ?? []) map[s.id] = s.name;\n return map;\n }, [sites.data]);\n\n const totals = useEcoCarbonTotals();\n\n const entries = useEcoCarbonEntries({\n scope: scope === 'ALL' ? undefined : scope,\n siteId: ledgerSiteId === 'ALL' ? undefined : ledgerSiteId,\n status: entryStatus === 'ALL' ? undefined : entryStatus,\n pagination: { limit: PAGE_SIZE, cursor: ledgerPager.cursor },\n });\n const entryRows = entries.data?.items ?? [];\n\n // Unfiltered factor list — feeds the \"record entry\" factor picker.\n const allFactors = useEcoEmissionFactors();\n const factors = useEcoEmissionFactors(factorScope === 'ALL' ? undefined : factorScope);\n const factorRows = factors.data?.items ?? [];\n\n const targets = useEcoReductionTargets(targetStatus === 'ALL' ? undefined : targetStatus);\n const targetRows = targets.data?.items ?? [];\n\n // Mutations\n const recordEntry = useEcoRecordCarbonEntry();\n const verifyEntry = useEcoVerifyCarbonEntry();\n const createFactor = useEcoCreateEmissionFactor();\n const createTarget = useEcoCreateReductionTarget();\n const setTargetStatusMut = useEcoSetReductionTargetStatus();\n\n const openEntry = () => {\n setEntryForm({ ...EMPTY_ENTRY, periodStart: today() });\n setFormError(null);\n setEntryOpen(true);\n };\n const openFactor = () => {\n setFactorForm(EMPTY_FACTOR);\n setFormError(null);\n setFactorOpen(true);\n };\n const openTarget = () => {\n setTargetForm(EMPTY_TARGET);\n setFormError(null);\n setTargetOpen(true);\n };\n\n const handleRecordEntry = async () => {\n if (!entryForm.category.trim() || !entryForm.activityValue || !entryForm.activityUnit.trim()) {\n setFormError('Category, activity value and unit are required.');\n return;\n }\n setFormError(null);\n try {\n await recordEntry.mutateAsync({\n category: entryForm.category.trim(),\n scope: entryForm.scope,\n activityValue: Number(entryForm.activityValue),\n activityUnit: entryForm.activityUnit.trim(),\n factorId: entryForm.factorId || null,\n siteId: entryForm.siteId || null,\n periodStart: new Date(entryForm.periodStart || today()).toISOString(),\n notes: entryForm.notes.trim() || null,\n });\n setEntryOpen(false);\n setEntryForm(EMPTY_ENTRY);\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to record carbon entry.');\n }\n };\n\n const handleCreateFactor = async () => {\n if (!factorForm.name.trim() || !factorForm.activityUnit.trim() || !factorForm.factorKgco2e) {\n setFormError('Name, activity unit and factor value are required.');\n return;\n }\n setFormError(null);\n try {\n await createFactor.mutateAsync({\n name: factorForm.name.trim(),\n scope: factorForm.scope,\n activityUnit: factorForm.activityUnit.trim(),\n factorKgco2e: Number(factorForm.factorKgco2e),\n source: factorForm.source.trim() || null,\n validYear: factorForm.validYear ? Number(factorForm.validYear) : null,\n });\n setFactorOpen(false);\n setFactorForm(EMPTY_FACTOR);\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to create emission factor.');\n }\n };\n\n const handleCreateTarget = async () => {\n if (\n !targetForm.name.trim() ||\n !targetForm.metric.trim() ||\n !targetForm.baselineValue ||\n !targetForm.baselineYear ||\n !targetForm.targetValue ||\n !targetForm.targetYear ||\n !targetForm.unit.trim()\n ) {\n setFormError('All fields except description are required.');\n return;\n }\n if (Number(targetForm.targetYear) <= Number(targetForm.baselineYear)) {\n setFormError('Target year must be later than the baseline year.');\n return;\n }\n setFormError(null);\n try {\n await createTarget.mutateAsync({\n name: targetForm.name.trim(),\n metric: targetForm.metric.trim(),\n baselineValue: Number(targetForm.baselineValue),\n baselineYear: Number(targetForm.baselineYear),\n targetValue: Number(targetForm.targetValue),\n targetYear: Number(targetForm.targetYear),\n unit: targetForm.unit.trim(),\n description: targetForm.description.trim() || null,\n });\n setTargetOpen(false);\n setTargetForm(EMPTY_TARGET);\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to create reduction target.');\n }\n };\n\n // ── Columns ───────────────────────────────────────────────────────────────\n const entryColumns: Column<EcoCarbonEntry>[] = [\n {\n key: 'category',\n header: 'Category',\n render: (e) => <span className=\"font-medium text-text-primary\">{e.category}</span>,\n },\n { key: 'scope', header: 'Scope', render: (e) => <StatusBadge status={e.scope} /> },\n {\n key: 'activity',\n header: 'Activity',\n align: 'right',\n hideOnMobile: true,\n sortValue: (e) => e.activityValue,\n render: (e) => (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(e.activityValue)} {e.activityUnit}\n </span>\n ),\n },\n {\n key: 'co2e',\n header: 'CO₂e',\n align: 'right',\n sortValue: (e) => e.co2eKg,\n render: (e) => (\n <span className=\"tabular-nums font-medium text-text-primary\">{formatCo2e(e.co2eKg)}</span>\n ),\n },\n { key: 'status', header: 'Status', render: (e) => <StatusBadge status={e.status} /> },\n {\n key: 'period',\n header: 'Period',\n align: 'right',\n hideOnMobile: true,\n render: (e) => <span className=\"text-text-tertiary\">{formatDate(e.periodStart)}</span>,\n },\n {\n key: 'factor',\n header: 'Factor',\n hideOnMobile: true,\n render: (e) => <span className=\"text-text-secondary\">{e.factor?.name ?? '—'}</span>,\n },\n {\n key: 'verify',\n header: '',\n align: 'right',\n render: (e) =>\n e.status !== 'VERIFIED' ? (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => verifyEntry.mutate(e.id)}\n disabled={verifyEntry.isPending}\n >\n Verify\n </Button>\n ) : null,\n },\n ];\n\n const factorColumns: Column<EcoEmissionFactor>[] = [\n {\n key: 'name',\n header: 'Factor',\n render: (f) => <span className=\"font-medium text-text-primary\">{f.name}</span>,\n },\n { key: 'scope', header: 'Scope', render: (f) => <StatusBadge status={f.scope} /> },\n {\n key: 'value',\n header: 'Emission factor',\n align: 'right',\n hideOnMobile: true,\n sortValue: (f) => f.factorKgco2e,\n render: (f) => (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(f.factorKgco2e)} kg/{f.activityUnit}\n </span>\n ),\n },\n {\n key: 'source',\n header: 'Source',\n hideOnMobile: true,\n render: (f) => <span className=\"text-text-secondary\">{f.source ?? '—'}</span>,\n },\n {\n key: 'validYear',\n header: 'Valid year',\n align: 'right',\n hideOnMobile: true,\n render: (f) => <span className=\"tabular-nums text-text-tertiary\">{f.validYear ?? '—'}</span>,\n },\n {\n key: 'active',\n header: 'Active',\n align: 'right',\n render: (f) => (f.isActive ? <StatusBadge status=\"OK\" /> : <StatusBadge status=\"Inactive\" />),\n },\n ];\n\n const targetColumns: Column<EcoReductionTarget>[] = [\n {\n key: 'name',\n header: 'Target',\n render: (t) => <span className=\"font-medium text-text-primary\">{t.name}</span>,\n },\n {\n key: 'metric',\n header: 'Metric',\n hideOnMobile: true,\n render: (t) => <span className=\"text-text-secondary\">{t.metric}</span>,\n },\n {\n key: 'baseline',\n header: 'Baseline',\n hideOnMobile: true,\n render: (t) => (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(t.baselineValue)} {t.unit} @{t.baselineYear}\n </span>\n ),\n },\n {\n key: 'target',\n header: 'Target',\n hideOnMobile: true,\n render: (t) => (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(t.targetValue)} {t.unit} @{t.targetYear}\n </span>\n ),\n },\n {\n key: 'reduction',\n header: 'Planned reduction',\n render: (t) => {\n const pct =\n t.baselineValue > 0\n ? clampPercent(((t.baselineValue - t.targetValue) / t.baselineValue) * 100)\n : 0;\n return (\n <div className=\"flex min-w-[10rem] items-center gap-3\">\n <Meter\n value={pct}\n color={TARGET_METER_COLOR[t.status] ?? 'var(--color-action-primary-bg)'}\n height={8}\n className=\"flex-1\"\n />\n <span className=\"w-11 shrink-0 text-right text-sm font-semibold tabular-nums text-text-primary\">\n {Math.round(pct)}%\n </span>\n </div>\n );\n },\n },\n { key: 'status', header: 'Status', render: (t) => <StatusBadge status={t.status} /> },\n {\n key: 'setStatus',\n header: '',\n align: 'right',\n render: (t) => (\n <Select\n value={t.status}\n onValueChange={(v) =>\n setTargetStatusMut.mutate({ id: t.id, status: v as EcoReductionTargetStatus })\n }\n >\n <SelectTrigger className=\"h-8 w-36\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TARGET_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ),\n },\n ];\n\n const tabs: TabItem<CarbonTab>[] = [\n { value: 'ledger', label: 'Ledger', icon: <Factory className=\"h-4 w-4\" /> },\n {\n value: 'factors',\n label: 'Emission factors',\n icon: <Leaf className=\"h-4 w-4\" />,\n count: factors.data?.items?.length,\n },\n {\n value: 'targets',\n label: 'Reduction targets',\n icon: <Target className=\"h-4 w-4\" />,\n count: targets.data?.items?.length,\n },\n ];\n\n const actionButton =\n activeTab === 'ledger' ? (\n <Button onClick={openEntry}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Record entry\n </Button>\n ) : activeTab === 'factors' ? (\n <Button onClick={openFactor}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New factor\n </Button>\n ) : (\n <Button onClick={openTarget}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New target\n </Button>\n );\n\n return (\n <PageLayout\n title=\"Carbon & Sustainability\"\n description=\"Carbon ledger, emission factors & science-based reduction targets — GHG Protocol Scope 1 / 2 / 3.\"\n actions={actionButton}\n >\n {/* KPI strip */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <MetricsCard\n icon={<Factory className=\"h-5 w-5\" />}\n value={totals.data ? formatCo2e(totals.data.total) : '—'}\n label=\"Total footprint\"\n featured\n footer={\n totals.data && totals.data.total > 0 ? (\n <div className=\"space-y-2\">\n <ScopeSplitBar\n scope1={totals.data.scope1}\n scope2={totals.data.scope2}\n scope3={totals.data.scope3}\n height={6}\n />\n <p className=\"text-xs text-text-tertiary\">Scope 1 · 2 · 3 split</p>\n </div>\n ) : undefined\n }\n />\n <MetricsCard\n icon={<Flame className=\"h-5 w-5\" />}\n value={totals.data ? formatCo2e(totals.data.scope1) : '—'}\n label=\"Scope 1 · Direct\"\n footer={renderScopeShare(totals.data?.scope1, totals.data?.total, 'SCOPE_1')}\n />\n <MetricsCard\n icon={<Zap className=\"h-5 w-5\" />}\n value={totals.data ? formatCo2e(totals.data.scope2) : '—'}\n label=\"Scope 2 · Purchased energy\"\n footer={renderScopeShare(totals.data?.scope2, totals.data?.total, 'SCOPE_2')}\n />\n <MetricsCard\n icon={<Truck className=\"h-5 w-5\" />}\n value={totals.data ? formatCo2e(totals.data.scope3) : '—'}\n label=\"Scope 3 · Value chain\"\n footer={renderScopeShare(totals.data?.scope3, totals.data?.total, 'SCOPE_3')}\n />\n </div>\n\n <div className=\"mt-6\">\n <Tabs items={tabs} value={activeTab} onChange={setActiveTab} />\n </div>\n\n {/* ── Ledger ─────────────────────────────────────────────────────────── */}\n {activeTab === 'ledger' && (\n <div className=\"mt-6\">\n <div className=\"mb-5 flex flex-wrap items-center gap-3\">\n <Select\n value={scope}\n onValueChange={(v) => {\n setScope(v as EcoEmissionScope | 'ALL');\n ledgerPager.reset();\n }}\n >\n <SelectTrigger className=\"w-40\">\n <SelectValue placeholder=\"All scopes\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All scopes</SelectItem>\n {SCOPES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select\n value={entryStatus}\n onValueChange={(v) => {\n setEntryStatus(v as EcoCarbonEntryStatus | 'ALL');\n ledgerPager.reset();\n }}\n >\n <SelectTrigger className=\"w-40\">\n <SelectValue placeholder=\"All statuses\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All statuses</SelectItem>\n {CARBON_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select\n value={ledgerSiteId}\n onValueChange={(v) => {\n setLedgerSiteId(v);\n ledgerPager.reset();\n }}\n >\n <SelectTrigger className=\"w-48\">\n <SelectValue placeholder=\"All sites\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All sites</SelectItem>\n {Object.entries(siteMap).map(([id, name]) => (\n <SelectItem key={id} value={id}>\n {name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {entries.isLoading ? (\n <LoadingView label=\"Loading carbon ledger…\" />\n ) : entries.isError ? (\n <ErrorView message=\"Couldn't load carbon entries.\" onRetry={() => entries.refetch()} />\n ) : entryRows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Factory className=\"h-10 w-10\" />}\n title=\"No carbon entries\"\n description={\n scope === 'ALL' && entryStatus === 'ALL' && ledgerSiteId === 'ALL'\n ? 'Record activity to build your Scope 1–3 emissions ledger.'\n : 'No entries match these filters.'\n }\n action={\n <Button onClick={openEntry}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Record entry\n </Button>\n }\n />\n ) : (\n <>\n <DataTable columns={entryColumns} rows={entryRows} rowKey={(e) => e.id} />\n <Pagination\n page={ledgerPager.page}\n pageSize={PAGE_SIZE}\n itemCount={entryRows.length}\n hasMore={entries.data?.pageInfo?.hasMore ?? false}\n onPageChange={(target) =>\n ledgerPager.onPageChange(target, entries.data?.pageInfo?.cursor)\n }\n />\n </>\n )}\n </div>\n )}\n\n {/* ── Emission factors ───────────────────────────────────────────────── */}\n {activeTab === 'factors' && (\n <div className=\"mt-6\">\n <div className=\"mb-5 flex flex-wrap items-center gap-3\">\n <Select\n value={factorScope}\n onValueChange={(v) => setFactorScope(v as EcoEmissionScope | 'ALL')}\n >\n <SelectTrigger className=\"w-40\">\n <SelectValue placeholder=\"All scopes\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All scopes</SelectItem>\n {SCOPES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {factors.isLoading ? (\n <LoadingView label=\"Loading emission factors…\" />\n ) : factors.isError ? (\n <ErrorView\n message=\"Couldn't load emission factors.\"\n onRetry={() => factors.refetch()}\n />\n ) : factorRows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Leaf className=\"h-10 w-10\" />}\n title=\"No emission factors\"\n description={\n factorScope === 'ALL'\n ? 'Add emission factors (kg CO₂e per activity unit) to convert activity into CO₂e.'\n : 'No emission factors match this scope.'\n }\n action={\n <Button onClick={openFactor}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New factor\n </Button>\n }\n />\n ) : (\n <DataTable columns={factorColumns} rows={factorRows} rowKey={(f) => f.id} />\n )}\n </div>\n )}\n\n {/* ── Reduction targets ──────────────────────────────────────────────── */}\n {activeTab === 'targets' && (\n <div className=\"mt-6\">\n <div className=\"mb-5 flex flex-wrap items-center gap-3\">\n <Select\n value={targetStatus}\n onValueChange={(v) => setTargetStatus(v as EcoReductionTargetStatus | 'ALL')}\n >\n <SelectTrigger className=\"w-44\">\n <SelectValue placeholder=\"All statuses\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All statuses</SelectItem>\n {TARGET_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {targets.isLoading ? (\n <LoadingView label=\"Loading reduction targets…\" />\n ) : targets.isError ? (\n <ErrorView\n message=\"Couldn't load reduction targets.\"\n onRetry={() => targets.refetch()}\n />\n ) : targetRows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Target className=\"h-10 w-10\" />}\n title=\"No reduction targets\"\n description={\n targetStatus === 'ALL'\n ? 'Set science-based reduction targets to track progress against a baseline.'\n : 'No targets match this status.'\n }\n action={\n <Button onClick={openTarget}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New target\n </Button>\n }\n />\n ) : (\n <DataTable columns={targetColumns} rows={targetRows} rowKey={(t) => t.id} />\n )}\n </div>\n )}\n\n {/* Record carbon entry dialog */}\n <ResponsiveDialog\n open={entryOpen}\n onOpenChange={(open) => {\n setEntryOpen(open);\n if (!open) {\n setEntryForm(EMPTY_ENTRY);\n setFormError(null);\n }\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Record carbon entry</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Log an activity — CO₂e is computed server-side from activity value × emission factor.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceCategory\">Category *</Label>\n <Input\n id=\"ceCategory\"\n value={entryForm.category}\n onChange={(e) => setEntryForm({ ...entryForm, category: e.target.value })}\n placeholder=\"Diesel generators\"\n />\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceScope\">Scope</Label>\n <Select\n value={entryForm.scope}\n onValueChange={(v) =>\n setEntryForm({ ...entryForm, scope: v as EcoEmissionScope })\n }\n >\n <SelectTrigger id=\"ceScope\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SCOPES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cePeriod\">Period start</Label>\n <Input\n id=\"cePeriod\"\n type=\"date\"\n value={entryForm.periodStart}\n onChange={(e) => setEntryForm({ ...entryForm, periodStart: e.target.value })}\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceValue\">Activity value *</Label>\n <Input\n id=\"ceValue\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={entryForm.activityValue}\n onChange={(e) => setEntryForm({ ...entryForm, activityValue: e.target.value })}\n placeholder=\"1200\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceUnit\">Activity unit *</Label>\n <Input\n id=\"ceUnit\"\n value={entryForm.activityUnit}\n onChange={(e) => setEntryForm({ ...entryForm, activityUnit: e.target.value })}\n placeholder=\"L, kWh, km\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceFactor\">Emission factor</Label>\n <Select\n value={entryForm.factorId}\n onValueChange={(v) => setEntryForm({ ...entryForm, factorId: v })}\n >\n <SelectTrigger id=\"ceFactor\">\n <SelectValue placeholder=\"Optional\" />\n </SelectTrigger>\n <SelectContent>\n {(allFactors.data?.items ?? []).map((f) => (\n <SelectItem key={f.id} value={f.id}>\n {f.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceSite\">Site</Label>\n <Select\n value={entryForm.siteId}\n onValueChange={(v) => setEntryForm({ ...entryForm, siteId: v })}\n >\n <SelectTrigger id=\"ceSite\">\n <SelectValue placeholder=\"Optional\" />\n </SelectTrigger>\n <SelectContent>\n {Object.entries(siteMap).map(([id, name]) => (\n <SelectItem key={id} value={id}>\n {name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceNotes\">Notes</Label>\n <Textarea\n id=\"ceNotes\"\n rows={2}\n value={entryForm.notes}\n onChange={(e) => setEntryForm({ ...entryForm, notes: e.target.value })}\n placeholder=\"Optional context about this entry.\"\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setEntryOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleRecordEntry} disabled={recordEntry.isPending}>\n {recordEntry.isPending ? 'Recording…' : 'Record entry'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* New emission factor dialog */}\n <ResponsiveDialog\n open={factorOpen}\n onOpenChange={(open) => {\n setFactorOpen(open);\n if (!open) {\n setFactorForm(EMPTY_FACTOR);\n setFormError(null);\n }\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New emission factor</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Define kg CO₂e per activity unit — used to convert ledger activity into CO₂e.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efName\">Name *</Label>\n <Input\n id=\"efName\"\n value={factorForm.name}\n onChange={(e) => setFactorForm({ ...factorForm, name: e.target.value })}\n placeholder=\"Diesel (stationary combustion)\"\n />\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efScope\">Scope</Label>\n <Select\n value={factorForm.scope}\n onValueChange={(v) =>\n setFactorForm({ ...factorForm, scope: v as EcoEmissionScope })\n }\n >\n <SelectTrigger id=\"efScope\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SCOPES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efUnit\">Activity unit *</Label>\n <Input\n id=\"efUnit\"\n value={factorForm.activityUnit}\n onChange={(e) => setFactorForm({ ...factorForm, activityUnit: e.target.value })}\n placeholder=\"kWh, L, km\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efFactor\">Factor (kg CO₂e / unit) *</Label>\n <Input\n id=\"efFactor\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={factorForm.factorKgco2e}\n onChange={(e) => setFactorForm({ ...factorForm, factorKgco2e: e.target.value })}\n placeholder=\"2.68\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efYear\">Valid year</Label>\n <Input\n id=\"efYear\"\n type=\"number\"\n step=\"1\"\n value={factorForm.validYear}\n onChange={(e) => setFactorForm({ ...factorForm, validYear: e.target.value })}\n placeholder=\"2026\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efSource\">Source</Label>\n <Input\n id=\"efSource\"\n value={factorForm.source}\n onChange={(e) => setFactorForm({ ...factorForm, source: e.target.value })}\n placeholder=\"DEFRA / IPCC / EPA\"\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setFactorOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleCreateFactor} disabled={createFactor.isPending}>\n {createFactor.isPending ? 'Creating…' : 'Create factor'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* New reduction target dialog */}\n <ResponsiveDialog\n open={targetOpen}\n onOpenChange={(open) => {\n setTargetOpen(open);\n if (!open) {\n setTargetForm(EMPTY_TARGET);\n setFormError(null);\n }\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New reduction target</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Commit to a measurable reduction from a baseline to a target year.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtName\">Name *</Label>\n <Input\n id=\"rtName\"\n value={targetForm.name}\n onChange={(e) => setTargetForm({ ...targetForm, name: e.target.value })}\n placeholder=\"Net-zero operations\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtMetric\">Metric *</Label>\n <Input\n id=\"rtMetric\"\n value={targetForm.metric}\n onChange={(e) => setTargetForm({ ...targetForm, metric: e.target.value })}\n placeholder=\"tCO2e/yr\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-3\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtBaseVal\">Baseline value *</Label>\n <Input\n id=\"rtBaseVal\"\n type=\"number\"\n step=\"any\"\n value={targetForm.baselineValue}\n onChange={(e) => setTargetForm({ ...targetForm, baselineValue: e.target.value })}\n placeholder=\"1000\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtBaseYear\">Baseline year *</Label>\n <Input\n id=\"rtBaseYear\"\n type=\"number\"\n step=\"1\"\n value={targetForm.baselineYear}\n onChange={(e) => setTargetForm({ ...targetForm, baselineYear: e.target.value })}\n placeholder=\"2024\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtUnit\">Unit *</Label>\n <Input\n id=\"rtUnit\"\n value={targetForm.unit}\n onChange={(e) => setTargetForm({ ...targetForm, unit: e.target.value })}\n placeholder=\"tCO2e\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtTargetVal\">Target value *</Label>\n <Input\n id=\"rtTargetVal\"\n type=\"number\"\n step=\"any\"\n value={targetForm.targetValue}\n onChange={(e) => setTargetForm({ ...targetForm, targetValue: e.target.value })}\n placeholder=\"0\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtTargetYear\">Target year *</Label>\n <Input\n id=\"rtTargetYear\"\n type=\"number\"\n step=\"1\"\n value={targetForm.targetYear}\n onChange={(e) => setTargetForm({ ...targetForm, targetYear: e.target.value })}\n placeholder=\"2030\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtDesc\">Description</Label>\n <Textarea\n id=\"rtDesc\"\n rows={2}\n value={targetForm.description}\n onChange={(e) => setTargetForm({ ...targetForm, description: e.target.value })}\n placeholder=\"Optional context about this target.\"\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setTargetOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleCreateTarget} disabled={createTarget.isPending}>\n {createTarget.isPending ? 'Creating…' : 'Create target'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CarbonPage.js","names":[],"sources":["../../../../src/ecoimpacthub/pages/carbon/CarbonPage.tsx"],"sourcesContent":["/**\n * Carbon & Sustainability — the GHG accounting hub.\n * @module ecoimpacthub/pages/carbon\n *\n * A KPI strip of Scope 1/2/3 + total footprint (from `ecoCarbonTotalKg`) over a\n * three-tab workspace:\n * - Ledger — `ecoListCarbonEntries` (+ `ecoRecordCarbonEntry` / `ecoVerifyCarbonEntry`)\n * - Emission factors — `ecoListEmissionFactors` (+ `ecoCreateEmissionFactor`)\n * - Reduction targets — `ecoListReductionTargets` (+ `ecoCreateReductionTarget`,\n * `ecoSetReductionTargetStatus`)\n *\n * CO₂e (`co2eKg`) is computed server-side from `activityValue × factor`. No mock data.\n */\n\nimport { useMemo, useState, type ReactNode } from 'react';\nimport { Plus, Factory, Flame, Zap, Truck, Leaf, Target } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\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 { PageLayout } from '../../components/PageLayout';\nimport { MetricsCard } from '../../components/MetricsCard';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataTable, type Column } from '../../components/DataTable';\nimport { Tabs, type TabItem } from '../../components/Tabs';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Pagination } from '../../components/Pagination';\nimport { ScopeSplitBar, Meter, SCOPE_HUE } from '../carbonVisuals';\nimport {\n useEcoSites,\n useEcoCarbonTotals,\n useEcoCarbonEntries,\n useEcoRecordCarbonEntry,\n useEcoVerifyCarbonEntry,\n useEcoEmissionFactors,\n useEcoCreateEmissionFactor,\n useEcoReductionTargets,\n useEcoCreateReductionTarget,\n useEcoSetReductionTargetStatus,\n useCursorPager,\n} from '../../hooks';\nimport {\n formatCo2e,\n formatNumber,\n formatDate,\n formatEnumLabel,\n formatPercent,\n} from '../../utils/formatters';\nimport type {\n EcoCarbonEntry,\n EcoCarbonEntryStatus,\n EcoEmissionFactor,\n EcoEmissionScope,\n EcoReductionTarget,\n EcoReductionTargetStatus,\n} from '../../types';\n\ntype CarbonTab = 'ledger' | 'factors' | 'targets';\n\nconst SCOPES: EcoEmissionScope[] = ['SCOPE_1', 'SCOPE_2', 'SCOPE_3'];\nconst CARBON_STATUSES: EcoCarbonEntryStatus[] = ['DRAFT', 'RECORDED', 'VERIFIED', 'ADJUSTED'];\nconst TARGET_STATUSES: EcoReductionTargetStatus[] = [\n 'PROPOSED',\n 'ACTIVE',\n 'ACHIEVED',\n 'MISSED',\n 'RETIRED',\n];\n\nconst PAGE_SIZE = 25;\n\nconst today = (): string => new Date().toISOString().slice(0, 10);\n\ninterface EntryFormState {\n category: string;\n scope: EcoEmissionScope;\n activityValue: string;\n activityUnit: string;\n factorId: string;\n siteId: string;\n periodStart: string;\n notes: string;\n}\n\nconst EMPTY_ENTRY: EntryFormState = {\n category: '',\n scope: 'SCOPE_1',\n activityValue: '',\n activityUnit: '',\n factorId: '',\n siteId: '',\n periodStart: '',\n notes: '',\n};\n\ninterface FactorFormState {\n name: string;\n scope: EcoEmissionScope;\n activityUnit: string;\n factorKgco2e: string;\n source: string;\n validYear: string;\n}\n\nconst EMPTY_FACTOR: FactorFormState = {\n name: '',\n scope: 'SCOPE_1',\n activityUnit: '',\n factorKgco2e: '',\n source: '',\n validYear: '',\n};\n\ninterface TargetFormState {\n name: string;\n metric: string;\n baselineValue: string;\n baselineYear: string;\n targetValue: string;\n targetYear: string;\n unit: string;\n description: string;\n}\n\nconst EMPTY_TARGET: TargetFormState = {\n name: '',\n metric: '',\n baselineValue: '',\n baselineYear: '',\n targetValue: '',\n targetYear: '',\n unit: '',\n description: '',\n};\n\nconst clampPercent = (value: number): number => Math.max(0, Math.min(100, value));\n\n/** Reduction-target progress meter tint by lifecycle status (semantic tokens). */\nconst TARGET_METER_COLOR: Record<EcoReductionTargetStatus, string> = {\n PROPOSED: 'var(--color-text-tertiary)',\n ACTIVE: 'var(--color-action-primary-bg)',\n ACHIEVED: 'var(--color-status-success-text)',\n MISSED: 'var(--color-status-error-text)',\n RETIRED: 'var(--color-text-tertiary)',\n};\n\n/** KPI-card footer: this scope's share of the total footprint, tinted by scope. */\nconst renderScopeShare = (\n value: number | undefined,\n total: number | undefined,\n scope: EcoEmissionScope\n): ReactNode => {\n if (value == null || total == null || total <= 0) return undefined;\n const pct = (value / total) * 100;\n return (\n <div className=\"space-y-2\">\n <Meter value={pct} color={SCOPE_HUE[scope]} height={4} />\n <p className=\"text-xs tabular-nums text-text-tertiary\">{formatPercent(pct)} of total</p>\n </div>\n );\n};\n\nexport function CarbonPage() {\n const [activeTab, setActiveTab] = useState<CarbonTab>('ledger');\n\n // Ledger filters\n const [scope, setScope] = useState<EcoEmissionScope | 'ALL'>('ALL');\n const [entryStatus, setEntryStatus] = useState<EcoCarbonEntryStatus | 'ALL'>('ALL');\n const [ledgerSiteId, setLedgerSiteId] = useState<string>('ALL');\n const ledgerPager = useCursorPager();\n\n // Section filters\n const [factorScope, setFactorScope] = useState<EcoEmissionScope | 'ALL'>('ALL');\n const [targetStatus, setTargetStatus] = useState<EcoReductionTargetStatus | 'ALL'>('ALL');\n\n // Dialog + form state\n const [entryOpen, setEntryOpen] = useState(false);\n const [entryForm, setEntryForm] = useState<EntryFormState>(EMPTY_ENTRY);\n const [factorOpen, setFactorOpen] = useState(false);\n const [factorForm, setFactorForm] = useState<FactorFormState>(EMPTY_FACTOR);\n const [targetOpen, setTargetOpen] = useState(false);\n const [targetForm, setTargetForm] = useState<TargetFormState>(EMPTY_TARGET);\n const [formError, setFormError] = useState<string | null>(null);\n\n // Data\n const sites = useEcoSites({ pagination: { limit: 100, offset: 0 } });\n const siteMap = useMemo<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n for (const s of sites.data?.items ?? []) map[s.id] = s.name;\n return map;\n }, [sites.data]);\n\n const totals = useEcoCarbonTotals();\n\n const entries = useEcoCarbonEntries({\n scope: scope === 'ALL' ? undefined : scope,\n siteId: ledgerSiteId === 'ALL' ? undefined : ledgerSiteId,\n status: entryStatus === 'ALL' ? undefined : entryStatus,\n pagination: { limit: PAGE_SIZE, cursor: ledgerPager.cursor },\n });\n const entryRows = entries.data?.items ?? [];\n\n // Unfiltered factor list — feeds the \"record entry\" factor picker.\n const allFactors = useEcoEmissionFactors();\n const factors = useEcoEmissionFactors(factorScope === 'ALL' ? undefined : factorScope);\n const factorRows = factors.data?.items ?? [];\n\n const targets = useEcoReductionTargets(targetStatus === 'ALL' ? undefined : targetStatus);\n const targetRows = targets.data?.items ?? [];\n\n // Mutations\n const recordEntry = useEcoRecordCarbonEntry();\n const verifyEntry = useEcoVerifyCarbonEntry();\n const createFactor = useEcoCreateEmissionFactor();\n const createTarget = useEcoCreateReductionTarget();\n const setTargetStatusMut = useEcoSetReductionTargetStatus();\n\n const openEntry = () => {\n setEntryForm({ ...EMPTY_ENTRY, periodStart: today() });\n setFormError(null);\n setEntryOpen(true);\n };\n const openFactor = () => {\n setFactorForm(EMPTY_FACTOR);\n setFormError(null);\n setFactorOpen(true);\n };\n const openTarget = () => {\n setTargetForm(EMPTY_TARGET);\n setFormError(null);\n setTargetOpen(true);\n };\n\n const handleRecordEntry = async () => {\n if (!entryForm.category.trim() || !entryForm.activityValue || !entryForm.activityUnit.trim()) {\n setFormError('Category, activity value and unit are required.');\n return;\n }\n setFormError(null);\n try {\n await recordEntry.mutateAsync({\n category: entryForm.category.trim(),\n scope: entryForm.scope,\n activityValue: Number(entryForm.activityValue),\n activityUnit: entryForm.activityUnit.trim(),\n factorId: entryForm.factorId || null,\n siteId: entryForm.siteId || null,\n periodStart: new Date(entryForm.periodStart || today()).toISOString(),\n notes: entryForm.notes.trim() || null,\n });\n setEntryOpen(false);\n setEntryForm(EMPTY_ENTRY);\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to record carbon entry.');\n }\n };\n\n const handleCreateFactor = async () => {\n if (!factorForm.name.trim() || !factorForm.activityUnit.trim() || !factorForm.factorKgco2e) {\n setFormError('Name, activity unit and factor value are required.');\n return;\n }\n setFormError(null);\n try {\n await createFactor.mutateAsync({\n name: factorForm.name.trim(),\n scope: factorForm.scope,\n activityUnit: factorForm.activityUnit.trim(),\n factorKgco2e: Number(factorForm.factorKgco2e),\n source: factorForm.source.trim() || null,\n validYear: factorForm.validYear ? Number(factorForm.validYear) : null,\n });\n setFactorOpen(false);\n setFactorForm(EMPTY_FACTOR);\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to create emission factor.');\n }\n };\n\n const handleCreateTarget = async () => {\n if (\n !targetForm.name.trim() ||\n !targetForm.metric.trim() ||\n !targetForm.baselineValue ||\n !targetForm.baselineYear ||\n !targetForm.targetValue ||\n !targetForm.targetYear ||\n !targetForm.unit.trim()\n ) {\n setFormError('All fields except description are required.');\n return;\n }\n if (Number(targetForm.targetYear) <= Number(targetForm.baselineYear)) {\n setFormError('Target year must be later than the baseline year.');\n return;\n }\n setFormError(null);\n try {\n await createTarget.mutateAsync({\n name: targetForm.name.trim(),\n metric: targetForm.metric.trim(),\n baselineValue: Number(targetForm.baselineValue),\n baselineYear: Number(targetForm.baselineYear),\n targetValue: Number(targetForm.targetValue),\n targetYear: Number(targetForm.targetYear),\n unit: targetForm.unit.trim(),\n description: targetForm.description.trim() || null,\n });\n setTargetOpen(false);\n setTargetForm(EMPTY_TARGET);\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to create reduction target.');\n }\n };\n\n // ── Columns ───────────────────────────────────────────────────────────────\n const entryColumns: Column<EcoCarbonEntry>[] = [\n {\n key: 'category',\n header: 'Category',\n render: (e) => <span className=\"font-medium text-text-primary\">{e.category}</span>,\n },\n { key: 'scope', header: 'Scope', render: (e) => <StatusBadge status={e.scope} /> },\n {\n key: 'activity',\n header: 'Activity',\n align: 'right',\n hideOnMobile: true,\n sortValue: (e) => e.activityValue,\n render: (e) => (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(e.activityValue)} {e.activityUnit}\n </span>\n ),\n },\n {\n key: 'co2e',\n header: 'CO₂e',\n align: 'right',\n sortValue: (e) => e.co2eKg,\n render: (e) => (\n <span className=\"tabular-nums font-medium text-text-primary\">{formatCo2e(e.co2eKg)}</span>\n ),\n },\n { key: 'status', header: 'Status', render: (e) => <StatusBadge status={e.status} /> },\n {\n key: 'period',\n header: 'Period',\n align: 'right',\n hideOnMobile: true,\n render: (e) => <span className=\"text-text-tertiary\">{formatDate(e.periodStart)}</span>,\n },\n {\n key: 'factor',\n header: 'Factor',\n hideOnMobile: true,\n render: (e) => <span className=\"text-text-secondary\">{e.factor?.name ?? '—'}</span>,\n },\n {\n key: 'verify',\n header: '',\n align: 'right',\n render: (e) =>\n e.status !== 'VERIFIED' ? (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => verifyEntry.mutate(e.id)}\n disabled={verifyEntry.isPending}\n >\n Verify\n </Button>\n ) : null,\n },\n ];\n\n const factorColumns: Column<EcoEmissionFactor>[] = [\n {\n key: 'name',\n header: 'Factor',\n render: (f) => <span className=\"font-medium text-text-primary\">{f.name}</span>,\n },\n { key: 'scope', header: 'Scope', render: (f) => <StatusBadge status={f.scope} /> },\n {\n key: 'value',\n header: 'Emission factor',\n align: 'right',\n hideOnMobile: true,\n sortValue: (f) => f.factorKgco2e,\n render: (f) => (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(f.factorKgco2e)} kg/{f.activityUnit}\n </span>\n ),\n },\n {\n key: 'source',\n header: 'Source',\n hideOnMobile: true,\n render: (f) => <span className=\"text-text-secondary\">{f.source ?? '—'}</span>,\n },\n {\n key: 'validYear',\n header: 'Valid year',\n align: 'right',\n hideOnMobile: true,\n render: (f) => <span className=\"tabular-nums text-text-tertiary\">{f.validYear ?? '—'}</span>,\n },\n {\n key: 'active',\n header: 'Active',\n align: 'right',\n render: (f) => (f.isActive ? <StatusBadge status=\"OK\" /> : <StatusBadge status=\"Inactive\" />),\n },\n ];\n\n const targetColumns: Column<EcoReductionTarget>[] = [\n {\n key: 'name',\n header: 'Target',\n render: (t) => <span className=\"font-medium text-text-primary\">{t.name}</span>,\n },\n {\n key: 'metric',\n header: 'Metric',\n hideOnMobile: true,\n render: (t) => <span className=\"text-text-secondary\">{t.metric}</span>,\n },\n {\n key: 'baseline',\n header: 'Baseline',\n hideOnMobile: true,\n render: (t) => (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(t.baselineValue)} {t.unit} @{t.baselineYear}\n </span>\n ),\n },\n {\n key: 'target',\n header: 'Target',\n hideOnMobile: true,\n render: (t) => (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(t.targetValue)} {t.unit} @{t.targetYear}\n </span>\n ),\n },\n {\n key: 'reduction',\n header: 'Planned reduction',\n render: (t) => {\n const pct =\n t.baselineValue > 0\n ? clampPercent(((t.baselineValue - t.targetValue) / t.baselineValue) * 100)\n : 0;\n return (\n <div className=\"flex min-w-[10rem] items-center gap-3\">\n <Meter\n value={pct}\n color={TARGET_METER_COLOR[t.status] ?? 'var(--color-action-primary-bg)'}\n height={8}\n className=\"flex-1\"\n />\n <span className=\"w-11 shrink-0 text-right text-sm font-semibold tabular-nums text-text-primary\">\n {Math.round(pct)}%\n </span>\n </div>\n );\n },\n },\n { key: 'status', header: 'Status', render: (t) => <StatusBadge status={t.status} /> },\n {\n key: 'setStatus',\n header: '',\n align: 'right',\n render: (t) => (\n <Select\n value={t.status}\n onValueChange={(v) =>\n setTargetStatusMut.mutate({ id: t.id, status: v as EcoReductionTargetStatus })\n }\n >\n <SelectTrigger className=\"h-8 w-36\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TARGET_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ),\n },\n ];\n\n const tabs: TabItem<CarbonTab>[] = [\n { value: 'ledger', label: 'Ledger', icon: <Factory className=\"h-4 w-4\" /> },\n {\n value: 'factors',\n label: 'Emission factors',\n icon: <Leaf className=\"h-4 w-4\" />,\n count: factors.data?.items?.length,\n },\n {\n value: 'targets',\n label: 'Reduction targets',\n icon: <Target className=\"h-4 w-4\" />,\n count: targets.data?.items?.length,\n },\n ];\n\n const actionButton =\n activeTab === 'ledger' ? (\n <Button onClick={openEntry}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Record entry\n </Button>\n ) : activeTab === 'factors' ? (\n <Button onClick={openFactor}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New factor\n </Button>\n ) : (\n <Button onClick={openTarget}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New target\n </Button>\n );\n\n return (\n <PageLayout\n title=\"Carbon & Sustainability\"\n description=\"Carbon ledger, emission factors & science-based reduction targets — GHG Protocol Scope 1 / 2 / 3.\"\n actions={actionButton}\n >\n {/* KPI strip */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <MetricsCard\n icon={<Factory className=\"h-5 w-5\" />}\n value={totals.data ? formatCo2e(totals.data.total) : '—'}\n label=\"Total footprint\"\n featured\n footer={\n totals.data && totals.data.total > 0 ? (\n <div className=\"space-y-2\">\n <ScopeSplitBar\n scope1={totals.data.scope1}\n scope2={totals.data.scope2}\n scope3={totals.data.scope3}\n height={6}\n />\n <p className=\"text-xs text-text-tertiary\">Scope 1 · 2 · 3 split</p>\n </div>\n ) : undefined\n }\n />\n <MetricsCard\n icon={<Flame className=\"h-5 w-5\" />}\n value={totals.data ? formatCo2e(totals.data.scope1) : '—'}\n label=\"Scope 1 · Direct\"\n footer={renderScopeShare(totals.data?.scope1, totals.data?.total, 'SCOPE_1')}\n />\n <MetricsCard\n icon={<Zap className=\"h-5 w-5\" />}\n value={totals.data ? formatCo2e(totals.data.scope2) : '—'}\n label=\"Scope 2 · Purchased energy\"\n footer={renderScopeShare(totals.data?.scope2, totals.data?.total, 'SCOPE_2')}\n />\n <MetricsCard\n icon={<Truck className=\"h-5 w-5\" />}\n value={totals.data ? formatCo2e(totals.data.scope3) : '—'}\n label=\"Scope 3 · Value chain\"\n footer={renderScopeShare(totals.data?.scope3, totals.data?.total, 'SCOPE_3')}\n />\n </div>\n\n <div className=\"mt-6\">\n <Tabs items={tabs} value={activeTab} onChange={setActiveTab} />\n </div>\n\n {/* ── Ledger ─────────────────────────────────────────────────────────── */}\n {activeTab === 'ledger' && (\n <div className=\"mt-6\">\n <div className=\"mb-5 flex flex-wrap items-center gap-3\">\n <Select\n value={scope}\n onValueChange={(v) => {\n setScope(v as EcoEmissionScope | 'ALL');\n ledgerPager.reset();\n }}\n >\n <SelectTrigger className=\"w-40\">\n <SelectValue placeholder=\"All scopes\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All scopes</SelectItem>\n {SCOPES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select\n value={entryStatus}\n onValueChange={(v) => {\n setEntryStatus(v as EcoCarbonEntryStatus | 'ALL');\n ledgerPager.reset();\n }}\n >\n <SelectTrigger className=\"w-40\">\n <SelectValue placeholder=\"All statuses\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All statuses</SelectItem>\n {CARBON_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select\n value={ledgerSiteId}\n onValueChange={(v) => {\n setLedgerSiteId(v);\n ledgerPager.reset();\n }}\n >\n <SelectTrigger className=\"w-48\">\n <SelectValue placeholder=\"All sites\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All sites</SelectItem>\n {Object.entries(siteMap).map(([id, name]) => (\n <SelectItem key={id} value={id}>\n {name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {entries.isLoading ? (\n <LoadingView label=\"Loading carbon ledger…\" />\n ) : entries.isError ? (\n <ErrorView message=\"Couldn't load carbon entries.\" onRetry={() => entries.refetch()} />\n ) : entryRows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Factory className=\"h-10 w-10\" />}\n title=\"No carbon entries\"\n description={\n scope === 'ALL' && entryStatus === 'ALL' && ledgerSiteId === 'ALL'\n ? 'Record activity to build your Scope 1–3 emissions ledger.'\n : 'No entries match these filters.'\n }\n action={\n <Button onClick={openEntry}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Record entry\n </Button>\n }\n />\n ) : (\n <>\n <DataTable columns={entryColumns} rows={entryRows} rowKey={(e) => e.id} />\n <Pagination\n page={ledgerPager.page}\n pageSize={PAGE_SIZE}\n itemCount={entryRows.length}\n hasMore={entries.data?.pageInfo?.hasMore ?? false}\n onPageChange={(target) =>\n ledgerPager.onPageChange(target, entries.data?.pageInfo?.cursor)\n }\n />\n </>\n )}\n </div>\n )}\n\n {/* ── Emission factors ───────────────────────────────────────────────── */}\n {activeTab === 'factors' && (\n <div className=\"mt-6\">\n <div className=\"mb-5 flex flex-wrap items-center gap-3\">\n <Select\n value={factorScope}\n onValueChange={(v) => setFactorScope(v as EcoEmissionScope | 'ALL')}\n >\n <SelectTrigger className=\"w-40\">\n <SelectValue placeholder=\"All scopes\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All scopes</SelectItem>\n {SCOPES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {factors.isLoading ? (\n <LoadingView label=\"Loading emission factors…\" />\n ) : factors.isError ? (\n <ErrorView\n message=\"Couldn't load emission factors.\"\n onRetry={() => factors.refetch()}\n />\n ) : factorRows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Leaf className=\"h-10 w-10\" />}\n title=\"No emission factors\"\n description={\n factorScope === 'ALL'\n ? 'Add emission factors (kg CO₂e per activity unit) to convert activity into CO₂e.'\n : 'No emission factors match this scope.'\n }\n action={\n <Button onClick={openFactor}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New factor\n </Button>\n }\n />\n ) : (\n <DataTable columns={factorColumns} rows={factorRows} rowKey={(f) => f.id} />\n )}\n </div>\n )}\n\n {/* ── Reduction targets ──────────────────────────────────────────────── */}\n {activeTab === 'targets' && (\n <div className=\"mt-6\">\n <div className=\"mb-5 flex flex-wrap items-center gap-3\">\n <Select\n value={targetStatus}\n onValueChange={(v) => setTargetStatus(v as EcoReductionTargetStatus | 'ALL')}\n >\n <SelectTrigger className=\"w-44\">\n <SelectValue placeholder=\"All statuses\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All statuses</SelectItem>\n {TARGET_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {targets.isLoading ? (\n <LoadingView label=\"Loading reduction targets…\" />\n ) : targets.isError ? (\n <ErrorView\n message=\"Couldn't load reduction targets.\"\n onRetry={() => targets.refetch()}\n />\n ) : targetRows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Target className=\"h-10 w-10\" />}\n title=\"No reduction targets\"\n description={\n targetStatus === 'ALL'\n ? 'Set science-based reduction targets to track progress against a baseline.'\n : 'No targets match this status.'\n }\n action={\n <Button onClick={openTarget}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New target\n </Button>\n }\n />\n ) : (\n <DataTable columns={targetColumns} rows={targetRows} rowKey={(t) => t.id} />\n )}\n </div>\n )}\n\n {/* Record carbon entry dialog */}\n <ResponsiveDialog\n open={entryOpen}\n onOpenChange={(open) => {\n setEntryOpen(open);\n if (!open) {\n setEntryForm(EMPTY_ENTRY);\n setFormError(null);\n }\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Record carbon entry</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Log an activity — CO₂e is computed server-side from activity value × emission factor.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceCategory\">Category *</Label>\n <Input\n id=\"ceCategory\"\n value={entryForm.category}\n onChange={(e) => setEntryForm({ ...entryForm, category: e.target.value })}\n placeholder=\"Diesel generators\"\n />\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceScope\">Scope</Label>\n <Select\n value={entryForm.scope}\n onValueChange={(v) =>\n setEntryForm({ ...entryForm, scope: v as EcoEmissionScope })\n }\n >\n <SelectTrigger id=\"ceScope\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SCOPES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cePeriod\">Period start</Label>\n <Input\n id=\"cePeriod\"\n type=\"date\"\n value={entryForm.periodStart}\n onChange={(e) => setEntryForm({ ...entryForm, periodStart: e.target.value })}\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceValue\">Activity value *</Label>\n <Input\n id=\"ceValue\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={entryForm.activityValue}\n onChange={(e) => setEntryForm({ ...entryForm, activityValue: e.target.value })}\n placeholder=\"1200\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceUnit\">Activity unit *</Label>\n <Input\n id=\"ceUnit\"\n value={entryForm.activityUnit}\n onChange={(e) => setEntryForm({ ...entryForm, activityUnit: e.target.value })}\n placeholder=\"L, kWh, km\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceFactor\">Emission factor</Label>\n <Select\n value={entryForm.factorId}\n onValueChange={(v) => setEntryForm({ ...entryForm, factorId: v })}\n >\n <SelectTrigger id=\"ceFactor\">\n <SelectValue placeholder=\"Optional\" />\n </SelectTrigger>\n <SelectContent>\n {(allFactors.data?.items ?? []).map((f) => (\n <SelectItem key={f.id} value={f.id}>\n {f.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceSite\">Site</Label>\n <Select\n value={entryForm.siteId}\n onValueChange={(v) => setEntryForm({ ...entryForm, siteId: v })}\n >\n <SelectTrigger id=\"ceSite\">\n <SelectValue placeholder=\"Optional\" />\n </SelectTrigger>\n <SelectContent>\n {Object.entries(siteMap).map(([id, name]) => (\n <SelectItem key={id} value={id}>\n {name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"ceNotes\">Notes</Label>\n <Textarea\n id=\"ceNotes\"\n rows={2}\n value={entryForm.notes}\n onChange={(e) => setEntryForm({ ...entryForm, notes: e.target.value })}\n placeholder=\"Optional context about this entry.\"\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setEntryOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleRecordEntry} disabled={recordEntry.isPending}>\n {recordEntry.isPending ? 'Recording…' : 'Record entry'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* New emission factor dialog */}\n <ResponsiveDialog\n open={factorOpen}\n onOpenChange={(open) => {\n setFactorOpen(open);\n if (!open) {\n setFactorForm(EMPTY_FACTOR);\n setFormError(null);\n }\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New emission factor</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Define kg CO₂e per activity unit — used to convert ledger activity into CO₂e.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efName\">Name *</Label>\n <Input\n id=\"efName\"\n value={factorForm.name}\n onChange={(e) => setFactorForm({ ...factorForm, name: e.target.value })}\n placeholder=\"Diesel (stationary combustion)\"\n />\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efScope\">Scope</Label>\n <Select\n value={factorForm.scope}\n onValueChange={(v) =>\n setFactorForm({ ...factorForm, scope: v as EcoEmissionScope })\n }\n >\n <SelectTrigger id=\"efScope\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SCOPES.map((s) => (\n <SelectItem key={s} value={s}>\n {formatEnumLabel(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efUnit\">Activity unit *</Label>\n <Input\n id=\"efUnit\"\n value={factorForm.activityUnit}\n onChange={(e) => setFactorForm({ ...factorForm, activityUnit: e.target.value })}\n placeholder=\"kWh, L, km\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efFactor\">Factor (kg CO₂e / unit) *</Label>\n <Input\n id=\"efFactor\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={factorForm.factorKgco2e}\n onChange={(e) => setFactorForm({ ...factorForm, factorKgco2e: e.target.value })}\n placeholder=\"2.68\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efYear\">Valid year</Label>\n <Input\n id=\"efYear\"\n type=\"number\"\n step=\"1\"\n value={factorForm.validYear}\n onChange={(e) => setFactorForm({ ...factorForm, validYear: e.target.value })}\n placeholder=\"2026\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"efSource\">Source</Label>\n <Input\n id=\"efSource\"\n value={factorForm.source}\n onChange={(e) => setFactorForm({ ...factorForm, source: e.target.value })}\n placeholder=\"DEFRA / IPCC / EPA\"\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setFactorOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleCreateFactor} disabled={createFactor.isPending}>\n {createFactor.isPending ? 'Creating…' : 'Create factor'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* New reduction target dialog */}\n <ResponsiveDialog\n open={targetOpen}\n onOpenChange={(open) => {\n setTargetOpen(open);\n if (!open) {\n setTargetForm(EMPTY_TARGET);\n setFormError(null);\n }\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New reduction target</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Commit to a measurable reduction from a baseline to a target year.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtName\">Name *</Label>\n <Input\n id=\"rtName\"\n value={targetForm.name}\n onChange={(e) => setTargetForm({ ...targetForm, name: e.target.value })}\n placeholder=\"Net-zero operations\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtMetric\">Metric *</Label>\n <Input\n id=\"rtMetric\"\n value={targetForm.metric}\n onChange={(e) => setTargetForm({ ...targetForm, metric: e.target.value })}\n placeholder=\"tCO2e/yr\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-3\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtBaseVal\">Baseline value *</Label>\n <Input\n id=\"rtBaseVal\"\n type=\"number\"\n step=\"any\"\n value={targetForm.baselineValue}\n onChange={(e) => setTargetForm({ ...targetForm, baselineValue: e.target.value })}\n placeholder=\"1000\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtBaseYear\">Baseline year *</Label>\n <Input\n id=\"rtBaseYear\"\n type=\"number\"\n step=\"1\"\n value={targetForm.baselineYear}\n onChange={(e) => setTargetForm({ ...targetForm, baselineYear: e.target.value })}\n placeholder=\"2024\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtUnit\">Unit *</Label>\n <Input\n id=\"rtUnit\"\n value={targetForm.unit}\n onChange={(e) => setTargetForm({ ...targetForm, unit: e.target.value })}\n placeholder=\"tCO2e\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtTargetVal\">Target value *</Label>\n <Input\n id=\"rtTargetVal\"\n type=\"number\"\n step=\"any\"\n value={targetForm.targetValue}\n onChange={(e) => setTargetForm({ ...targetForm, targetValue: e.target.value })}\n placeholder=\"0\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtTargetYear\">Target year *</Label>\n <Input\n id=\"rtTargetYear\"\n type=\"number\"\n step=\"1\"\n value={targetForm.targetYear}\n onChange={(e) => setTargetForm({ ...targetForm, targetYear: e.target.value })}\n placeholder=\"2030\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"rtDesc\">Description</Label>\n <Textarea\n id=\"rtDesc\"\n rows={2}\n value={targetForm.description}\n onChange={(e) => setTargetForm({ ...targetForm, description: e.target.value })}\n placeholder=\"Optional context about this target.\"\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setTargetOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleCreateTarget} disabled={createTarget.isPending}>\n {createTarget.isPending ? 'Creating…' : 'Create target'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carbonVisuals.js","names":[],"sources":["../../../src/ecoimpacthub/pages/carbonVisuals.tsx"],"sourcesContent":["/**\n * Shared carbon-scope visual helpers for the EcoImpactHub Dashboard & Carbon\n * pages.\n * @module ecoimpacthub/pages\n *\n * A single, on-brand emerald → teal scale so scope *magnitudes* read as one\n * cohesive system across the footprint chart, the featured KPI split bar and the\n * per-scope share meters. Categorical scope *tags* keep StatusBadge's semantic\n * colours (red / amber / blue) — these hues encode quantity only. All tokens\n * resolve to a green/teal family across every Boff theme, so nothing is a raw\n * colour. No mock data — every value passed in comes from the real `eco*`\n * aggregates.\n */\n\nimport type { FC } from 'react';\nimport { cn } from '../utils/cn';\nimport { formatCo2e } from '../utils/formatters';\nimport type { EcoEmissionScope } from '../types';\n\n/**\n * Graduated teal → emerald scale. Every token here resolves to a green/teal in\n * ALL Boff themes (accent-teal is always teal; chart-positive + success-text are\n * always the \"positive\" green), so the footprint palette never drifts to the\n * brand-variable blue/purple that `chart-1` / `action-primary-bg` can take.\n */\nexport const SCOPE_HUE: Record<EcoEmissionScope, string> = {\n SCOPE_1: 'var(--color-accent-teal)',\n SCOPE_2: 'var(--color-chart-positive)',\n SCOPE_3: 'var(--color-status-success-text)',\n};\n\nexport const SCOPE_LABEL: Record<EcoEmissionScope, string> = {\n SCOPE_1: 'Scope 1',\n SCOPE_2: 'Scope 2',\n SCOPE_3: 'Scope 3',\n};\n\nexport const SCOPE_ORDER: EcoEmissionScope[] = ['SCOPE_1', 'SCOPE_2', 'SCOPE_3'];\n\n// ── Meter ────────────────────────────────────────────────────────────────────\n\ninterface MeterProps {\n /** 0–100. */\n value: number;\n /** Fill colour — a semantic token `var(--color-*)` string. */\n color: string;\n className?: string;\n /** Height in px. */\n height?: number;\n}\n\n/**\n * A thin rounded progress meter whose fill colour is an arbitrary semantic\n * token (unlike the class-based {@link MiniBar}). Used for per-scope share and\n * reduction-target progress so the fill can be tinted by scope / status.\n */\nexport const Meter: FC<MeterProps> = ({ value, color, className, height = 6 }) => {\n const clamped = Math.max(0, Math.min(100, value));\n return (\n <div\n className={cn('w-full overflow-hidden rounded-full bg-bg-sunken', className)}\n style={{ height }}\n role=\"progressbar\"\n aria-valuenow={Math.round(clamped)}\n aria-valuemin={0}\n aria-valuemax={100}\n >\n <div\n className=\"h-full rounded-full transition-[width] duration-700 ease-out\"\n style={{ width: `${clamped}%`, backgroundColor: color }}\n />\n </div>\n );\n};\n\n// ── ScopeSplitBar ──────────────────────────────────────────────────────────────\n\ninterface ScopeSplitBarProps {\n scope1: number;\n scope2: number;\n scope3: number;\n className?: string;\n height?: number;\n}\n\n/** A single thin rounded meter that splits the total footprint into 3 scopes. */\nexport const ScopeSplitBar: FC<ScopeSplitBarProps> = ({\n scope1,\n scope2,\n scope3,\n className,\n height = 8,\n}) => {\n const segments: { scope: EcoEmissionScope; value: number }[] = [\n { scope: 'SCOPE_1', value: Math.max(0, scope1) },\n { scope: 'SCOPE_2', value: Math.max(0, scope2) },\n { scope: 'SCOPE_3', value: Math.max(0, scope3) },\n ];\n const total = segments.reduce((sum, s) => sum + s.value, 0);\n\n return (\n <div\n className={cn('flex w-full overflow-hidden rounded-full bg-bg-sunken', className)}\n style={{ height }}\n role=\"img\"\n aria-label={`Footprint split — Scope 1 ${formatCo2e(scope1)}, Scope 2 ${formatCo2e(\n scope2\n )}, Scope 3 ${formatCo2e(scope3)}`}\n >\n {total > 0 &&\n segments.map((seg) =>\n seg.value > 0 ? (\n <div\n key={seg.scope}\n className=\"h-full transition-[width] duration-700 ease-out first:rounded-l-full last:rounded-r-full\"\n style={{\n width: `${(seg.value / total) * 100}%`,\n backgroundColor: SCOPE_HUE[seg.scope],\n }}\n />\n ) : null\n )}\n </div>\n );\n};\n\n// ── ScopeLegend ────────────────────────────────────────────────────────────────\n\ninterface ScopeLegendProps {\n data: { scope: EcoEmissionScope; kg: number }[];\n className?: string;\n}\n\n/** Colour-swatch legend + per-scope value shown beneath the footprint chart. */\nexport const ScopeLegend: FC<ScopeLegendProps> = ({ data, className }) => (\n <div className={cn('flex flex-wrap items-center gap-x-6 gap-y-2', className)}>\n {SCOPE_ORDER.map((scope) => {\n const row = data.find((d) => d.scope === scope);\n return (\n <div key={scope} className=\"flex items-center gap-2\">\n <span\n aria-hidden=\"true\"\n className=\"size-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: SCOPE_HUE[scope] }}\n />\n <span className=\"text-xs font-medium text-text-secondary\">{SCOPE_LABEL[scope]}</span>\n <span className=\"text-xs tabular-nums text-text-tertiary\">\n {row ? formatCo2e(row.kg) : '—'}\n </span>\n </div>\n );\n })}\n </div>\n);\n"],"mappings":";;;;AAyBA,IAAa,IAA8C;CACzD,SAAS;CACT,SAAS;CACT,SAAS;
|
|
1
|
+
{"version":3,"file":"carbonVisuals.js","names":[],"sources":["../../../src/ecoimpacthub/pages/carbonVisuals.tsx"],"sourcesContent":["/**\n * Shared carbon-scope visual helpers for the EcoImpactHub Dashboard & Carbon\n * pages.\n * @module ecoimpacthub/pages\n *\n * A single, on-brand emerald → teal scale so scope *magnitudes* read as one\n * cohesive system across the footprint chart, the featured KPI split bar and the\n * per-scope share meters. Categorical scope *tags* keep StatusBadge's semantic\n * colours (red / amber / blue) — these hues encode quantity only. All tokens\n * resolve to a green/teal family across every Boff theme, so nothing is a raw\n * colour. No mock data — every value passed in comes from the real `eco*`\n * aggregates.\n */\n\nimport type { FC } from 'react';\nimport { cn } from '../utils/cn';\nimport { formatCo2e } from '../utils/formatters';\nimport type { EcoEmissionScope } from '../types';\n\n/**\n * Graduated teal → emerald scale. Every token here resolves to a green/teal in\n * ALL Boff themes (accent-teal is always teal; chart-positive + success-text are\n * always the \"positive\" green), so the footprint palette never drifts to the\n * brand-variable blue/purple that `chart-1` / `action-primary-bg` can take.\n */\nexport const SCOPE_HUE: Record<EcoEmissionScope, string> = {\n SCOPE_1: 'var(--color-accent-teal)',\n SCOPE_2: 'var(--color-chart-positive)',\n SCOPE_3: 'var(--color-status-success-text)',\n};\n\nexport const SCOPE_LABEL: Record<EcoEmissionScope, string> = {\n SCOPE_1: 'Scope 1',\n SCOPE_2: 'Scope 2',\n SCOPE_3: 'Scope 3',\n};\n\nexport const SCOPE_ORDER: EcoEmissionScope[] = ['SCOPE_1', 'SCOPE_2', 'SCOPE_3'];\n\n// ── Meter ────────────────────────────────────────────────────────────────────\n\ninterface MeterProps {\n /** 0–100. */\n value: number;\n /** Fill colour — a semantic token `var(--color-*)` string. */\n color: string;\n className?: string;\n /** Height in px. */\n height?: number;\n}\n\n/**\n * A thin rounded progress meter whose fill colour is an arbitrary semantic\n * token (unlike the class-based {@link MiniBar}). Used for per-scope share and\n * reduction-target progress so the fill can be tinted by scope / status.\n */\nexport const Meter: FC<MeterProps> = ({ value, color, className, height = 6 }) => {\n const clamped = Math.max(0, Math.min(100, value));\n return (\n <div\n className={cn('w-full overflow-hidden rounded-full bg-bg-sunken', className)}\n style={{ height }}\n role=\"progressbar\"\n aria-valuenow={Math.round(clamped)}\n aria-valuemin={0}\n aria-valuemax={100}\n >\n <div\n className=\"h-full rounded-full transition-[width] duration-700 ease-out\"\n style={{ width: `${clamped}%`, backgroundColor: color }}\n />\n </div>\n );\n};\n\n// ── ScopeSplitBar ──────────────────────────────────────────────────────────────\n\ninterface ScopeSplitBarProps {\n scope1: number;\n scope2: number;\n scope3: number;\n className?: string;\n height?: number;\n}\n\n/** A single thin rounded meter that splits the total footprint into 3 scopes. */\nexport const ScopeSplitBar: FC<ScopeSplitBarProps> = ({\n scope1,\n scope2,\n scope3,\n className,\n height = 8,\n}) => {\n const segments: { scope: EcoEmissionScope; value: number }[] = [\n { scope: 'SCOPE_1', value: Math.max(0, scope1) },\n { scope: 'SCOPE_2', value: Math.max(0, scope2) },\n { scope: 'SCOPE_3', value: Math.max(0, scope3) },\n ];\n const total = segments.reduce((sum, s) => sum + s.value, 0);\n\n return (\n <div\n className={cn('flex w-full overflow-hidden rounded-full bg-bg-sunken', className)}\n style={{ height }}\n role=\"img\"\n aria-label={`Footprint split — Scope 1 ${formatCo2e(scope1)}, Scope 2 ${formatCo2e(\n scope2\n )}, Scope 3 ${formatCo2e(scope3)}`}\n >\n {total > 0 &&\n segments.map((seg) =>\n seg.value > 0 ? (\n <div\n key={seg.scope}\n className=\"h-full transition-[width] duration-700 ease-out first:rounded-l-full last:rounded-r-full\"\n style={{\n width: `${(seg.value / total) * 100}%`,\n backgroundColor: SCOPE_HUE[seg.scope],\n }}\n />\n ) : null\n )}\n </div>\n );\n};\n\n// ── ScopeLegend ────────────────────────────────────────────────────────────────\n\ninterface ScopeLegendProps {\n data: { scope: EcoEmissionScope; kg: number }[];\n className?: string;\n}\n\n/** Colour-swatch legend + per-scope value shown beneath the footprint chart. */\nexport const ScopeLegend: FC<ScopeLegendProps> = ({ data, className }) => (\n <div className={cn('flex flex-wrap items-center gap-x-6 gap-y-2', className)}>\n {SCOPE_ORDER.map((scope) => {\n const row = data.find((d) => d.scope === scope);\n return (\n <div key={scope} className=\"flex items-center gap-2\">\n <span\n aria-hidden=\"true\"\n className=\"size-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: SCOPE_HUE[scope] }}\n />\n <span className=\"text-xs font-medium text-text-secondary\">{SCOPE_LABEL[scope]}</span>\n <span className=\"text-xs tabular-nums text-text-tertiary\">\n {row ? formatCo2e(row.kg) : '—'}\n </span>\n </div>\n );\n })}\n </div>\n);\n"],"mappings":";;;;AAyBA,IAAa,IAA8C;CACzD,SAAS;CACT,SAAS;CACT,SAAS;AACX,GAEa,IAAgD;CAC3D,SAAS;CACT,SAAS;CACT,SAAS;AACX,GAEa,IAAkC;CAAC;CAAW;CAAW;AAAS,GAmBlE,KAAyB,EAAE,UAAO,UAAO,cAAW,YAAS,QAAQ;CAChF,IAAM,IAAU,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,CAAK,CAAC;CAChD,OACE,kBAAC,OAAD;EACE,WAAW,EAAG,oDAAoD,CAAS;EAC3E,OAAO,EAAE,UAAO;EAChB,MAAK;EACL,iBAAe,KAAK,MAAM,CAAO;EACjC,iBAAe;EACf,iBAAe;YAEf,kBAAC,OAAD;GACE,WAAU;GACV,OAAO;IAAE,OAAO,GAAG,EAAQ;IAAI,iBAAiB;GAAM;EACvD,CAAA;CACE,CAAA;AAET,GAaa,KAAyC,EACpD,WACA,WACA,WACA,cACA,YAAS,QACL;CACJ,IAAM,IAAyD;EAC7D;GAAE,OAAO;GAAW,OAAO,KAAK,IAAI,GAAG,CAAM;EAAE;EAC/C;GAAE,OAAO;GAAW,OAAO,KAAK,IAAI,GAAG,CAAM;EAAE;EAC/C;GAAE,OAAO;GAAW,OAAO,KAAK,IAAI,GAAG,CAAM;EAAE;CACjD,GACM,IAAQ,EAAS,QAAQ,GAAK,MAAM,IAAM,EAAE,OAAO,CAAC;CAE1D,OACE,kBAAC,OAAD;EACE,WAAW,EAAG,yDAAyD,CAAS;EAChF,OAAO,EAAE,UAAO;EAChB,MAAK;EACL,cAAY,6BAA6B,EAAW,CAAM,EAAE,YAAY,EACtE,CACF,EAAE,YAAY,EAAW,CAAM;YAE9B,IAAQ,KACP,EAAS,KAAK,MACZ,EAAI,QAAQ,IACV,kBAAC,OAAD;GAEE,WAAU;GACV,OAAO;IACL,OAAO,GAAI,EAAI,QAAQ,IAAS,IAAI;IACpC,iBAAiB,EAAU,EAAI;GACjC;EACD,GANM,EAAI,KAMV,IACC,IACN;CACC,CAAA;AAET,GAUa,KAAqC,EAAE,SAAM,mBACxD,kBAAC,OAAD;CAAK,WAAW,EAAG,+CAA+C,CAAS;WACxE,EAAY,KAAK,MAAU;EAC1B,IAAM,IAAM,EAAK,MAAM,MAAM,EAAE,UAAU,CAAK;EAC9C,OACE,kBAAC,OAAD;GAAiB,WAAU;aAA3B;IACE,kBAAC,QAAD;KACE,eAAY;KACZ,WAAU;KACV,OAAO,EAAE,iBAAiB,EAAU,GAAO;IAC5C,CAAA;IACD,kBAAC,QAAD;KAAM,WAAU;eAA2C,EAAY;IAAa,CAAA;IACpF,kBAAC,QAAD;KAAM,WAAU;eACb,IAAM,EAAW,EAAI,EAAE,IAAI;IACxB,CAAA;GACH;KAVK,CAUL;CAET,CAAC;AACE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HabitatProjectDetailPage.js","names":[],"sources":["../../../../src/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.tsx"],"sourcesContent":["/**\n * Habitat project detail — overview, lifecycle-progress, transitions & activities.\n * @module ecoimpacthub/pages/habitat\n *\n * Reads `ecoHabitatProject` (+ nested activities); writes\n * `ecoTransitionHabitatProject`, `ecoLogRestorationActivity`. The hero is\n * balanced into three tidy cards — overview, lifecycle-progress (a status-derived\n * radial ring + stepper, since the schema has no numeric progress) and\n * advance-project. Tags are driven via the platform tag store (no eco-svc change).\n */\n\nimport { useMemo, useState, type ReactNode } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, ArrowRight, Plus, Sprout } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n GlassCard,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { DataTable, type Column } from '../../components/DataTable';\nimport { LoadingView, ErrorView, Section } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { EcoTags } from '../../components/EcoTags';\nimport { useEcoImpactHub } from '../../context';\nimport {\n useEcoHabitatProject,\n useEcoTransitionHabitatProject,\n useEcoLogRestorationActivity,\n useEcoSites,\n} from '../../hooks';\nimport { formatDate, formatDateTime, formatEnumLabel, formatNumber } from '../../utils/formatters';\nimport type {\n EcoHabitatProjectStatus,\n EcoRestorationActivity,\n EcoRestorationActivityType,\n} from '../../types';\nimport { ActivityTypeBadge, LifecycleBadge } from '../badges';\nimport { LifecycleProgress } from './LifecycleProgress';\n\n/** Allowed forward lifecycle transitions per current status. */\nconst NEXT_STATUSES: Record<EcoHabitatProjectStatus, EcoHabitatProjectStatus[]> = {\n PLANNED: ['IN_PROGRESS', 'ON_HOLD', 'CANCELLED'],\n IN_PROGRESS: ['MONITORING', 'ON_HOLD', 'COMPLETED', 'CANCELLED'],\n MONITORING: ['COMPLETED', 'IN_PROGRESS'],\n ON_HOLD: ['IN_PROGRESS', 'CANCELLED'],\n COMPLETED: [],\n CANCELLED: [],\n};\n\nconst ACTIVITY_TYPES: EcoRestorationActivityType[] = [\n 'PLANTING',\n 'INVASIVE_REMOVAL',\n 'REWILDING',\n 'WATER_MANAGEMENT',\n 'SOIL_REMEDIATION',\n 'COMMUNITY_ENGAGEMENT',\n 'SURVEY',\n];\n\n/** Local `YYYY-MM-DDTHH:mm` string for a datetime-local default of \"now\". */\nconst nowLocal = (): string => {\n const d = new Date();\n const local = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n return local.toISOString().slice(0, 16);\n};\n\ninterface ActivityFormState {\n type: EcoRestorationActivityType;\n summary: string;\n details: string;\n quantity: string;\n unit: string;\n performedAt: string;\n}\n\nconst emptyActivityForm = (): ActivityFormState => ({\n type: 'PLANTING',\n summary: '',\n details: '',\n quantity: '',\n unit: '',\n performedAt: nowLocal(),\n});\n\n/** A labelled key/value cell for the overview grid. */\nfunction Fact({ label, children }: { label: string; children: ReactNode }) {\n return (\n <div>\n <dt className=\"text-xs text-text-tertiary\">{label}</dt>\n <dd className=\"mt-1 text-sm text-text-primary\">{children}</dd>\n </div>\n );\n}\n\nexport function HabitatProjectDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useEcoImpactHub();\n const { data: project, isLoading, isError, refetch } = useEcoHabitatProject(id);\n const sites = useEcoSites({ pagination: { limit: 100, offset: 0 } });\n\n const transitionProject = useEcoTransitionHabitatProject();\n const logActivity = useEcoLogRestorationActivity();\n\n const [activityOpen, setActivityOpen] = useState(false);\n const [activityForm, setActivityForm] = useState<ActivityFormState>(emptyActivityForm);\n const [error, setError] = useState<string | null>(null);\n\n const projectSiteId = project?.siteId ?? null;\n const siteItems = sites.data?.items;\n const siteName = useMemo(\n () => (projectSiteId ? (siteItems?.find((s) => s.id === projectSiteId)?.name ?? null) : null),\n [projectSiteId, siteItems]\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"Habitat project\">\n <LoadingView />\n </PageLayout>\n );\n }\n if (isError || !project) {\n return (\n <PageLayout title=\"Habitat project\">\n <ErrorView message=\"This project could not be loaded.\" onRetry={() => refetch()} />\n </PageLayout>\n );\n }\n\n const activities = project.activities ?? [];\n const nextStatuses = NEXT_STATUSES[project.status];\n const timeline = [formatDate(project.startDate), formatDate(project.endDate)].join(' – ');\n const subtitle = [siteName, timeline].filter((v) => v && v !== '— – —').join(' · ');\n\n const handleTransition = async (status: EcoHabitatProjectStatus) => {\n if (!id) return;\n setError(null);\n try {\n await transitionProject.mutateAsync({ id, status });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to update project status.');\n }\n };\n\n const handleLogActivity = async () => {\n if (!id || !activityForm.summary.trim()) {\n setError('Activity summary is required.');\n return;\n }\n setError(null);\n try {\n await logActivity.mutateAsync({\n projectId: id,\n type: activityForm.type,\n summary: activityForm.summary.trim(),\n details: activityForm.details.trim() || null,\n quantity: activityForm.quantity ? Number(activityForm.quantity) : null,\n unit: activityForm.unit.trim() || null,\n performedAt: activityForm.performedAt\n ? new Date(activityForm.performedAt).toISOString()\n : new Date().toISOString(),\n });\n setActivityOpen(false);\n setActivityForm(emptyActivityForm());\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to log activity.');\n }\n };\n\n const activityColumns: Column<EcoRestorationActivity>[] = [\n {\n key: 'type',\n header: 'Type',\n render: (a) => <ActivityTypeBadge type={a.type} />,\n },\n {\n key: 'summary',\n header: 'Summary',\n render: (a) => (\n <div className=\"min-w-0\">\n <p className=\"text-text-primary\">{a.summary}</p>\n {a.details && (\n <p className=\"mt-0.5 max-w-md truncate text-xs text-text-tertiary\">{a.details}</p>\n )}\n </div>\n ),\n },\n {\n key: 'quantity',\n header: 'Quantity',\n align: 'right',\n hideOnMobile: true,\n sortValue: (a) => a.quantity ?? 0,\n render: (a) =>\n a.quantity != null ? (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(a.quantity)}\n {a.unit ? ` ${a.unit}` : ''}\n </span>\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n ),\n },\n {\n key: 'performedAt',\n header: 'Performed',\n align: 'right',\n hideOnMobile: true,\n sortValue: (a) => a.performedAt,\n render: (a) => <span className=\"text-text-tertiary\">{formatDateTime(a.performedAt)}</span>,\n },\n ];\n\n return (\n <PageLayout\n title={\n <span className=\"flex flex-wrap items-center gap-x-3 gap-y-2\">\n <span className=\"text-text-primary\">{project.name}</span>\n <LifecycleBadge status={project.status} />\n </span>\n }\n description={subtitle || undefined}\n actions={\n <Button variant=\"ghost\" onClick={() => navigateTo('habitat')}>\n <ArrowLeft className=\"mr-1.5 h-4 w-4\" /> Back\n </Button>\n }\n >\n {/* Hero — overview · lifecycle-progress · advance-project */}\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-4\">\n {/* Overview */}\n <GlassCard treatment=\"glass\" className=\"p-6 lg:col-span-2\">\n <dl className=\"grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-3\">\n <Fact label=\"Status\">\n <LifecycleBadge status={project.status} />\n </Fact>\n <Fact label=\"Target area\">\n <span className=\"tabular-nums\">\n {project.targetHectares != null\n ? `${formatNumber(project.targetHectares)} ha`\n : '—'}\n </span>\n </Fact>\n <Fact label=\"Budget\">\n <span className=\"tabular-nums\">\n {project.budgetAmount > 0\n ? `${formatNumber(project.budgetAmount)} ${project.currency}`\n : '—'}\n </span>\n </Fact>\n <Fact label=\"Start\">{formatDate(project.startDate)}</Fact>\n <Fact label=\"End\">{formatDate(project.endDate)}</Fact>\n <Fact label={project.completedAt ? 'Completed' : 'Site'}>\n {project.completedAt ? formatDate(project.completedAt) : (siteName ?? '—')}\n </Fact>\n {project.completedAt && <Fact label=\"Site\">{siteName ?? '—'}</Fact>}\n </dl>\n\n {project.description && (\n <p className=\"mt-5 rounded-lg bg-bg-sunken/60 p-3 text-sm text-text-secondary\">\n {project.description}\n </p>\n )}\n\n <div className=\"mt-5 border-t border-border-seam pt-4\">\n <EcoTags entityType=\"ecoimpacthub-habitat\" entityId={project.id} />\n </div>\n </GlassCard>\n\n {/* Lifecycle progress */}\n <GlassCard treatment=\"glass\" className=\"flex flex-col p-6\">\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-tertiary\">\n Lifecycle progress\n </p>\n <div className=\"flex flex-1 items-center justify-center\">\n <LifecycleProgress status={project.status} />\n </div>\n </GlassCard>\n\n {/* Advance project */}\n <GlassCard treatment=\"glass\" className=\"flex flex-col gap-3 p-6\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-tertiary\">\n Advance project\n </p>\n {nextStatuses.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n This project is {formatEnumLabel(project.status).toLowerCase()} — no further\n transitions.\n </p>\n ) : (\n nextStatuses.map((next) => (\n <Button\n key={next}\n variant=\"outline\"\n onClick={() => handleTransition(next)}\n disabled={transitionProject.isPending}\n className=\"justify-between\"\n >\n {formatEnumLabel(next)}\n <ArrowRight className=\"h-4 w-4 opacity-60\" />\n </Button>\n ))\n )}\n <Button className=\"mt-auto\" onClick={() => setActivityOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Log activity\n </Button>\n </GlassCard>\n </div>\n\n {error && <p className=\"mt-4 text-sm text-status-error-text\">{error}</p>}\n\n {/* Restoration activities */}\n <Section\n title=\"Restoration activities\"\n description=\"Work logged against this project — planting, removals, surveys & engagement.\"\n action={\n <Button size=\"sm\" onClick={() => setActivityOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Log activity\n </Button>\n }\n >\n {activities.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Sprout className=\"h-10 w-10\" />}\n title=\"No activities yet\"\n description=\"Log restoration work to build this project's field record.\"\n action={\n <Button size=\"sm\" onClick={() => setActivityOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Log activity\n </Button>\n }\n />\n ) : (\n <DataTable\n columns={activityColumns}\n rows={activities}\n rowKey={(a) => a.id}\n defaultSort={{ key: 'performedAt', dir: 'desc' }}\n />\n )}\n </Section>\n\n {/* Log activity dialog */}\n <ResponsiveDialog open={activityOpen} onOpenChange={setActivityOpen}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Log restoration activity</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Record a piece of work performed for {project.name}.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actType\">Type</Label>\n <Select\n value={activityForm.type}\n onValueChange={(v) =>\n setActivityForm({ ...activityForm, type: v as EcoRestorationActivityType })\n }\n >\n <SelectTrigger id=\"actType\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ACTIVITY_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {formatEnumLabel(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actPerformedAt\">Performed at</Label>\n <Input\n id=\"actPerformedAt\"\n type=\"datetime-local\"\n value={activityForm.performedAt}\n onChange={(e) =>\n setActivityForm({ ...activityForm, performedAt: e.target.value })\n }\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actSummary\">Summary *</Label>\n <Input\n id=\"actSummary\"\n value={activityForm.summary}\n onChange={(e) => setActivityForm({ ...activityForm, summary: e.target.value })}\n placeholder=\"Planted 500 mangrove saplings\"\n />\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actDetails\">Details</Label>\n <Textarea\n id=\"actDetails\"\n value={activityForm.details}\n onChange={(e) => setActivityForm({ ...activityForm, details: e.target.value })}\n placeholder=\"Optional notes about the work.\"\n rows={2}\n />\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actQuantity\">Quantity</Label>\n <Input\n id=\"actQuantity\"\n type=\"number\"\n step=\"any\"\n value={activityForm.quantity}\n onChange={(e) => setActivityForm({ ...activityForm, quantity: e.target.value })}\n placeholder=\"500\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actUnit\">Unit</Label>\n <Input\n id=\"actUnit\"\n value={activityForm.unit}\n onChange={(e) => setActivityForm({ ...activityForm, unit: e.target.value })}\n placeholder=\"saplings\"\n />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setActivityOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleLogActivity} disabled={logActivity.isPending}>\n {logActivity.isPending ? 'Logging…' : 'Log activity'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HabitatProjectDetailPage.js","names":[],"sources":["../../../../src/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.tsx"],"sourcesContent":["/**\n * Habitat project detail — overview, lifecycle-progress, transitions & activities.\n * @module ecoimpacthub/pages/habitat\n *\n * Reads `ecoHabitatProject` (+ nested activities); writes\n * `ecoTransitionHabitatProject`, `ecoLogRestorationActivity`. The hero is\n * balanced into three tidy cards — overview, lifecycle-progress (a status-derived\n * radial ring + stepper, since the schema has no numeric progress) and\n * advance-project. Tags are driven via the platform tag store (no eco-svc change).\n */\n\nimport { useMemo, useState, type ReactNode } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, ArrowRight, Plus, Sprout } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n GlassCard,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { DataTable, type Column } from '../../components/DataTable';\nimport { LoadingView, ErrorView, Section } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { EcoTags } from '../../components/EcoTags';\nimport { useEcoImpactHub } from '../../context';\nimport {\n useEcoHabitatProject,\n useEcoTransitionHabitatProject,\n useEcoLogRestorationActivity,\n useEcoSites,\n} from '../../hooks';\nimport { formatDate, formatDateTime, formatEnumLabel, formatNumber } from '../../utils/formatters';\nimport type {\n EcoHabitatProjectStatus,\n EcoRestorationActivity,\n EcoRestorationActivityType,\n} from '../../types';\nimport { ActivityTypeBadge, LifecycleBadge } from '../badges';\nimport { LifecycleProgress } from './LifecycleProgress';\n\n/** Allowed forward lifecycle transitions per current status. */\nconst NEXT_STATUSES: Record<EcoHabitatProjectStatus, EcoHabitatProjectStatus[]> = {\n PLANNED: ['IN_PROGRESS', 'ON_HOLD', 'CANCELLED'],\n IN_PROGRESS: ['MONITORING', 'ON_HOLD', 'COMPLETED', 'CANCELLED'],\n MONITORING: ['COMPLETED', 'IN_PROGRESS'],\n ON_HOLD: ['IN_PROGRESS', 'CANCELLED'],\n COMPLETED: [],\n CANCELLED: [],\n};\n\nconst ACTIVITY_TYPES: EcoRestorationActivityType[] = [\n 'PLANTING',\n 'INVASIVE_REMOVAL',\n 'REWILDING',\n 'WATER_MANAGEMENT',\n 'SOIL_REMEDIATION',\n 'COMMUNITY_ENGAGEMENT',\n 'SURVEY',\n];\n\n/** Local `YYYY-MM-DDTHH:mm` string for a datetime-local default of \"now\". */\nconst nowLocal = (): string => {\n const d = new Date();\n const local = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n return local.toISOString().slice(0, 16);\n};\n\ninterface ActivityFormState {\n type: EcoRestorationActivityType;\n summary: string;\n details: string;\n quantity: string;\n unit: string;\n performedAt: string;\n}\n\nconst emptyActivityForm = (): ActivityFormState => ({\n type: 'PLANTING',\n summary: '',\n details: '',\n quantity: '',\n unit: '',\n performedAt: nowLocal(),\n});\n\n/** A labelled key/value cell for the overview grid. */\nfunction Fact({ label, children }: { label: string; children: ReactNode }) {\n return (\n <div>\n <dt className=\"text-xs text-text-tertiary\">{label}</dt>\n <dd className=\"mt-1 text-sm text-text-primary\">{children}</dd>\n </div>\n );\n}\n\nexport function HabitatProjectDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useEcoImpactHub();\n const { data: project, isLoading, isError, refetch } = useEcoHabitatProject(id);\n const sites = useEcoSites({ pagination: { limit: 100, offset: 0 } });\n\n const transitionProject = useEcoTransitionHabitatProject();\n const logActivity = useEcoLogRestorationActivity();\n\n const [activityOpen, setActivityOpen] = useState(false);\n const [activityForm, setActivityForm] = useState<ActivityFormState>(emptyActivityForm);\n const [error, setError] = useState<string | null>(null);\n\n const projectSiteId = project?.siteId ?? null;\n const siteItems = sites.data?.items;\n const siteName = useMemo(\n () => (projectSiteId ? (siteItems?.find((s) => s.id === projectSiteId)?.name ?? null) : null),\n [projectSiteId, siteItems]\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"Habitat project\">\n <LoadingView />\n </PageLayout>\n );\n }\n if (isError || !project) {\n return (\n <PageLayout title=\"Habitat project\">\n <ErrorView message=\"This project could not be loaded.\" onRetry={() => refetch()} />\n </PageLayout>\n );\n }\n\n const activities = project.activities ?? [];\n const nextStatuses = NEXT_STATUSES[project.status];\n const timeline = [formatDate(project.startDate), formatDate(project.endDate)].join(' – ');\n const subtitle = [siteName, timeline].filter((v) => v && v !== '— – —').join(' · ');\n\n const handleTransition = async (status: EcoHabitatProjectStatus) => {\n if (!id) return;\n setError(null);\n try {\n await transitionProject.mutateAsync({ id, status });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to update project status.');\n }\n };\n\n const handleLogActivity = async () => {\n if (!id || !activityForm.summary.trim()) {\n setError('Activity summary is required.');\n return;\n }\n setError(null);\n try {\n await logActivity.mutateAsync({\n projectId: id,\n type: activityForm.type,\n summary: activityForm.summary.trim(),\n details: activityForm.details.trim() || null,\n quantity: activityForm.quantity ? Number(activityForm.quantity) : null,\n unit: activityForm.unit.trim() || null,\n performedAt: activityForm.performedAt\n ? new Date(activityForm.performedAt).toISOString()\n : new Date().toISOString(),\n });\n setActivityOpen(false);\n setActivityForm(emptyActivityForm());\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to log activity.');\n }\n };\n\n const activityColumns: Column<EcoRestorationActivity>[] = [\n {\n key: 'type',\n header: 'Type',\n render: (a) => <ActivityTypeBadge type={a.type} />,\n },\n {\n key: 'summary',\n header: 'Summary',\n render: (a) => (\n <div className=\"min-w-0\">\n <p className=\"text-text-primary\">{a.summary}</p>\n {a.details && (\n <p className=\"mt-0.5 max-w-md truncate text-xs text-text-tertiary\">{a.details}</p>\n )}\n </div>\n ),\n },\n {\n key: 'quantity',\n header: 'Quantity',\n align: 'right',\n hideOnMobile: true,\n sortValue: (a) => a.quantity ?? 0,\n render: (a) =>\n a.quantity != null ? (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(a.quantity)}\n {a.unit ? ` ${a.unit}` : ''}\n </span>\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n ),\n },\n {\n key: 'performedAt',\n header: 'Performed',\n align: 'right',\n hideOnMobile: true,\n sortValue: (a) => a.performedAt,\n render: (a) => <span className=\"text-text-tertiary\">{formatDateTime(a.performedAt)}</span>,\n },\n ];\n\n return (\n <PageLayout\n title={\n <span className=\"flex flex-wrap items-center gap-x-3 gap-y-2\">\n <span className=\"text-text-primary\">{project.name}</span>\n <LifecycleBadge status={project.status} />\n </span>\n }\n description={subtitle || undefined}\n actions={\n <Button variant=\"ghost\" onClick={() => navigateTo('habitat')}>\n <ArrowLeft className=\"mr-1.5 h-4 w-4\" /> Back\n </Button>\n }\n >\n {/* Hero — overview · lifecycle-progress · advance-project */}\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-4\">\n {/* Overview */}\n <GlassCard treatment=\"glass\" className=\"p-6 lg:col-span-2\">\n <dl className=\"grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-3\">\n <Fact label=\"Status\">\n <LifecycleBadge status={project.status} />\n </Fact>\n <Fact label=\"Target area\">\n <span className=\"tabular-nums\">\n {project.targetHectares != null\n ? `${formatNumber(project.targetHectares)} ha`\n : '—'}\n </span>\n </Fact>\n <Fact label=\"Budget\">\n <span className=\"tabular-nums\">\n {project.budgetAmount > 0\n ? `${formatNumber(project.budgetAmount)} ${project.currency}`\n : '—'}\n </span>\n </Fact>\n <Fact label=\"Start\">{formatDate(project.startDate)}</Fact>\n <Fact label=\"End\">{formatDate(project.endDate)}</Fact>\n <Fact label={project.completedAt ? 'Completed' : 'Site'}>\n {project.completedAt ? formatDate(project.completedAt) : (siteName ?? '—')}\n </Fact>\n {project.completedAt && <Fact label=\"Site\">{siteName ?? '—'}</Fact>}\n </dl>\n\n {project.description && (\n <p className=\"mt-5 rounded-lg bg-bg-sunken/60 p-3 text-sm text-text-secondary\">\n {project.description}\n </p>\n )}\n\n <div className=\"mt-5 border-t border-border-seam pt-4\">\n <EcoTags entityType=\"ecoimpacthub-habitat\" entityId={project.id} />\n </div>\n </GlassCard>\n\n {/* Lifecycle progress */}\n <GlassCard treatment=\"glass\" className=\"flex flex-col p-6\">\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-tertiary\">\n Lifecycle progress\n </p>\n <div className=\"flex flex-1 items-center justify-center\">\n <LifecycleProgress status={project.status} />\n </div>\n </GlassCard>\n\n {/* Advance project */}\n <GlassCard treatment=\"glass\" className=\"flex flex-col gap-3 p-6\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-tertiary\">\n Advance project\n </p>\n {nextStatuses.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n This project is {formatEnumLabel(project.status).toLowerCase()} — no further\n transitions.\n </p>\n ) : (\n nextStatuses.map((next) => (\n <Button\n key={next}\n variant=\"outline\"\n onClick={() => handleTransition(next)}\n disabled={transitionProject.isPending}\n className=\"justify-between\"\n >\n {formatEnumLabel(next)}\n <ArrowRight className=\"h-4 w-4 opacity-60\" />\n </Button>\n ))\n )}\n <Button className=\"mt-auto\" onClick={() => setActivityOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Log activity\n </Button>\n </GlassCard>\n </div>\n\n {error && <p className=\"mt-4 text-sm text-status-error-text\">{error}</p>}\n\n {/* Restoration activities */}\n <Section\n title=\"Restoration activities\"\n description=\"Work logged against this project — planting, removals, surveys & engagement.\"\n action={\n <Button size=\"sm\" onClick={() => setActivityOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Log activity\n </Button>\n }\n >\n {activities.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Sprout className=\"h-10 w-10\" />}\n title=\"No activities yet\"\n description=\"Log restoration work to build this project's field record.\"\n action={\n <Button size=\"sm\" onClick={() => setActivityOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Log activity\n </Button>\n }\n />\n ) : (\n <DataTable\n columns={activityColumns}\n rows={activities}\n rowKey={(a) => a.id}\n defaultSort={{ key: 'performedAt', dir: 'desc' }}\n />\n )}\n </Section>\n\n {/* Log activity dialog */}\n <ResponsiveDialog open={activityOpen} onOpenChange={setActivityOpen}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Log restoration activity</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Record a piece of work performed for {project.name}.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actType\">Type</Label>\n <Select\n value={activityForm.type}\n onValueChange={(v) =>\n setActivityForm({ ...activityForm, type: v as EcoRestorationActivityType })\n }\n >\n <SelectTrigger id=\"actType\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ACTIVITY_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {formatEnumLabel(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actPerformedAt\">Performed at</Label>\n <Input\n id=\"actPerformedAt\"\n type=\"datetime-local\"\n value={activityForm.performedAt}\n onChange={(e) =>\n setActivityForm({ ...activityForm, performedAt: e.target.value })\n }\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actSummary\">Summary *</Label>\n <Input\n id=\"actSummary\"\n value={activityForm.summary}\n onChange={(e) => setActivityForm({ ...activityForm, summary: e.target.value })}\n placeholder=\"Planted 500 mangrove saplings\"\n />\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actDetails\">Details</Label>\n <Textarea\n id=\"actDetails\"\n value={activityForm.details}\n onChange={(e) => setActivityForm({ ...activityForm, details: e.target.value })}\n placeholder=\"Optional notes about the work.\"\n rows={2}\n />\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actQuantity\">Quantity</Label>\n <Input\n id=\"actQuantity\"\n type=\"number\"\n step=\"any\"\n value={activityForm.quantity}\n onChange={(e) => setActivityForm({ ...activityForm, quantity: e.target.value })}\n placeholder=\"500\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"actUnit\">Unit</Label>\n <Input\n id=\"actUnit\"\n value={activityForm.unit}\n onChange={(e) => setActivityForm({ ...activityForm, unit: e.target.value })}\n placeholder=\"saplings\"\n />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setActivityOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleLogActivity} disabled={logActivity.isPending}>\n {logActivity.isPending ? 'Logging…' : 'Log activity'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|