@agridea/suibi-module 0.1.0-preview.22 → 0.1.0-preview.277fb90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +10 -10
  2. package/dist/elements/browser/main.js +75 -72
  3. package/dist/elements/browser/styles.css +1 -1
  4. package/dist/elements/browser/suibi-module-latest.css +1 -1
  5. package/dist/elements/browser/suibi-module-latest.js +75 -72
  6. package/dist/elements/browser/{suibi-module.v0.1.0-preview.22.css → suibi-module.v0.1.0-preview.277fb90.css} +1 -1
  7. package/dist/elements/browser/suibi-module.v0.1.0-preview.277fb90.js +78 -0
  8. package/dist/elements/browser/suibi-theme-dark.css +1 -1
  9. package/dist/elements/browser/version.txt +1 -1
  10. package/dist/elements/browser/wc-global-utilities.css +1 -0
  11. package/dist/types/app/app.d.ts +4 -2
  12. package/dist/types/app/components/add-dashed-button/add-dashed-button.component.d.ts +9 -0
  13. package/dist/types/app/components/data-preview/data-preview.component.d.ts +4 -2
  14. package/dist/types/app/components/empty-state/empty-state.component.d.ts +12 -0
  15. package/dist/types/app/components/gauge-arc/gauge-arc.component.d.ts +49 -0
  16. package/dist/types/app/{header-bar.d.ts → components/header-bar/header-bar.component.d.ts} +4 -6
  17. package/dist/types/app/components/inline-table/inline-table.component.d.ts +137 -0
  18. package/dist/types/app/components/inline-table/inline-table.types.d.ts +203 -0
  19. package/dist/types/app/components/module-placeholder-page/module-placeholder-page.component.d.ts +6 -0
  20. package/dist/types/app/components/planning-result/planning-result.component.d.ts +46 -0
  21. package/dist/types/app/components/planning-result-row/planning-result-row.component.d.ts +34 -0
  22. package/dist/types/app/components/planning-trigger/planning-trigger.component.d.ts +13 -0
  23. package/dist/types/app/components/results-page/results-page.component.d.ts +13 -0
  24. package/dist/types/app/components/suissebilanz-dashboard/suissebilanz-dashboard.component.d.ts +32 -0
  25. package/dist/types/app/components/suissebilanz-dashboard/suissebilanz-metrics.service.d.ts +21 -0
  26. package/dist/types/app/components/suissebilanz-minibar/suissebilanz-minibar.component.d.ts +19 -0
  27. package/dist/types/app/components/validation-page/validation-page.component.d.ts +18 -0
  28. package/dist/types/app/components/welcome-page/metadata.types.d.ts +1 -1
  29. package/dist/types/app/components/welcome-page/welcome-page.component.d.ts +5 -3
  30. package/dist/types/app/components/workflow-stepper/workflow-stepper.component.d.ts +49 -0
  31. package/dist/types/app/core/data/naebi-data.service.d.ts +43 -28
  32. package/dist/types/app/core/error/global-error-handler.d.ts +2 -3
  33. package/dist/types/app/core/i18n/i18n.service.d.ts +5 -3
  34. package/dist/types/app/core/i18n/locales/fr.d.ts +2 -0
  35. package/dist/types/app/core/i18n/locales/it.d.ts +2 -0
  36. package/dist/types/app/core/master-data/master-data.service.d.ts +8 -1
  37. package/dist/types/app/core/metadata/suibi-metadata.types.d.ts +11 -1
  38. package/dist/types/app/core/navigation/navigation.service.d.ts +29 -1
  39. package/dist/types/app/core/planning/planning-balance.service.d.ts +38 -0
  40. package/dist/types/app/core/planning/planning-balance.types.d.ts +206 -0
  41. package/dist/types/app/core/planning/planning-balance.utils.d.ts +10 -0
  42. package/dist/types/app/core/utils/object.util.d.ts +26 -0
  43. package/dist/types/app/core/validation/capabilities.d.ts +5 -5
  44. package/dist/types/app/core/validation/global-validation.service.d.ts +19 -4
  45. package/dist/types/app/jsonforms/filters/code-list-filter-resolvers.d.ts +3 -0
  46. package/dist/types/app/jsonforms/registry/renderers.registry.d.ts +8 -0
  47. package/dist/types/app/jsonforms/renderers/controls/selects/animal-category/animal-category-select.renderer.d.ts +1 -1
  48. package/dist/types/app/jsonforms/renderers/controls/selects/code-list/code-list-select.renderer.d.ts +10 -4
  49. package/dist/types/app/jsonforms/renderers/layout/array/array-layout.renderer.d.ts +43 -0
  50. package/dist/types/app/jsonforms/renderers/layout/categorization/selected-category-categorization.renderer.d.ts +3 -0
  51. package/dist/types/app/jsonforms/renderers/layout/constraint/constraint-layout.renderer.d.ts +1 -0
  52. package/dist/types/app/jsonforms/renderers/layout/group/base-group.renderer.d.ts +2 -0
  53. package/dist/types/app/jsonforms/renderers/layout/group/module-toggle-group.renderer.d.ts +38 -0
  54. package/dist/types/app/nutrient-cycle/animal-stock/animal-stock-detail/animal-stock-detail.component.d.ts +21 -0
  55. package/dist/types/app/nutrient-cycle/animal-stock/{animal-stock-list.component.d.ts → animal-stock-list/animal-stock-list.component.d.ts} +6 -9
  56. package/dist/types/app/nutrient-cycle/animal-stock/{animal-stock-master-detail.component.d.ts → animal-stock-master-detail/animal-stock-master-detail.component.d.ts} +2 -3
  57. package/dist/types/app/nutrient-cycle/animal-stock/index.d.ts +3 -3
  58. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-master-detail/farm-manure-trading-master-detail.component.d.ts +19 -0
  59. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-table/farm-manure-trading-table.component.d.ts +34 -0
  60. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-table/farm-manure-trading-table.config.d.ts +24 -0
  61. package/dist/types/app/nutrient-cycle/farm-manure-trading/index.d.ts +3 -3
  62. package/dist/types/app/nutrient-cycle/farm-manure-trading/transaction-unit.util.d.ts +2 -0
  63. package/dist/types/app/nutrient-cycle/field-cultivation/arable-land-table/arable-land-table.component.d.ts +22 -0
  64. package/dist/types/app/nutrient-cycle/field-cultivation/arable-land-table/arable-land-table.config.d.ts +9 -0
  65. package/dist/types/app/nutrient-cycle/field-cultivation/crop-harvest-table/crop-harvest-table.component.d.ts +21 -0
  66. package/dist/types/app/nutrient-cycle/field-cultivation/crop-harvest-table/crop-harvest-table.config.d.ts +13 -0
  67. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-detail/field-cultivation-detail.component.d.ts +22 -0
  68. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-general/field-cultivation-general.component.d.ts +20 -0
  69. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-list/field-cultivation-list.component.d.ts +17 -0
  70. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-master-detail/field-cultivation-master-detail.component.d.ts +29 -0
  71. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation.types.d.ts +41 -0
  72. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation.util.d.ts +6 -0
  73. package/dist/types/app/nutrient-cycle/field-cultivation/fodder-cropland-table/fodder-cropland-table.component.d.ts +28 -0
  74. package/dist/types/app/nutrient-cycle/field-cultivation/fodder-cropland-table/fodder-cropland-table.config.d.ts +16 -0
  75. package/dist/types/app/nutrient-cycle/field-cultivation/index.d.ts +9 -0
  76. package/dist/types/app/nutrient-cycle/field-cultivation/special-crops-table/special-crops-table.component.d.ts +29 -0
  77. package/dist/types/app/nutrient-cycle/field-cultivation/special-crops-table/special-crops-table.config.d.ts +50 -0
  78. package/dist/types/app/nutrient-cycle/field-spreading/fertiliser-table/fertiliser-table.component.d.ts +43 -0
  79. package/dist/types/app/nutrient-cycle/field-spreading/fertiliser-table/fertiliser-table.config.d.ts +20 -0
  80. package/dist/types/app/nutrient-cycle/field-spreading/field-spreading.component.d.ts +16 -4
  81. package/dist/types/app/nutrient-cycle/field-spreading/field-spreading.types.d.ts +1 -0
  82. package/dist/types/app/nutrient-cycle/field-spreading/ingredient.util.d.ts +8 -0
  83. package/dist/types/app/nutrient-cycle/field-spreading/recycling-table/recycling-table.component.d.ts +31 -0
  84. package/dist/types/app/nutrient-cycle/field-spreading/recycling-table/recycling-table.config.d.ts +17 -0
  85. package/dist/types/app/nutrient-cycle/field-spreading/recycling-table/recycling-transaction-unit.util.d.ts +4 -0
  86. package/dist/types/app/nutrient-cycle/fodder/fodder-master-detail/fodder-master-detail.component.d.ts +25 -0
  87. package/dist/types/app/nutrient-cycle/fodder/fodder-table/fodder-table.component.d.ts +26 -0
  88. package/dist/types/app/nutrient-cycle/fodder/fodder-table/fodder-table.config.d.ts +9 -0
  89. package/dist/types/app/nutrient-cycle/fodder/fodder.types.d.ts +34 -0
  90. package/dist/types/app/nutrient-cycle/fodder/index.d.ts +3 -0
  91. package/dist/types/app/nutrient-cycle/fodder/ingredient.util.d.ts +8 -0
  92. package/dist/types/app/nutrient-cycle/fodder/transaction-unit.util.d.ts +2 -0
  93. package/dist/types/app/nutrient-cycle/lifetime-performance/index.d.ts +2 -0
  94. package/dist/types/app/nutrient-cycle/lifetime-performance/lifetime-performance-form.component.d.ts +1 -1
  95. package/dist/types/app/nutrient-cycle/storage/index.d.ts +4 -0
  96. package/dist/types/app/nutrient-cycle/storage/storage-detail/storage-detail.component.d.ts +30 -0
  97. package/dist/types/app/nutrient-cycle/storage/storage-general/storage-general.component.d.ts +29 -0
  98. package/dist/types/app/nutrient-cycle/storage/storage-list/storage-list.component.d.ts +23 -0
  99. package/dist/types/app/nutrient-cycle/storage/storage-master-detail/storage-master-detail.component.d.ts +32 -0
  100. package/dist/types/app/nutrient-cycle/storage/storage.types.d.ts +40 -0
  101. package/dist/types/environments/environment.d.ts +5 -0
  102. package/dist/types/shared/material-icons.d.ts +3 -3
  103. package/package.json +68 -17
  104. package/dist/elements/browser/suibi-module.v0.1.0-preview.22.js +0 -75
  105. package/dist/types/app/nutrient-cycle/animal-stock/animal-stock-detail.component.d.ts +0 -22
  106. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-detail.component.d.ts +0 -27
  107. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-list.component.d.ts +0 -22
  108. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-master-detail.component.d.ts +0 -26
  109. /package/dist/types/app/{core/validation/validation-errors-panel.d.ts → components/validation-errors-panel/validation-errors-panel.component.d.ts} +0 -0
@@ -0,0 +1,32 @@
1
+ import { SafeUrl } from '@angular/platform-browser';
2
+ import { PlanningBalanceService } from '../../core/planning/planning-balance.service';
3
+ import { GaugeStatus } from '../gauge-arc/gauge-arc.component';
4
+ import { SuisseBilanzMetricsService } from './suissebilanz-metrics.service';
5
+ /**
6
+ * Dashboard card displaying the 5 main SuisseBilanz metrics as semicircular
7
+ * SVG gauges. Derives all display data from `PlanningBalanceService` via
8
+ * computed signals — fully zoneless-safe, `OnPush`.
9
+ *
10
+ * Shows an empty-state panel when no planning result is available yet.
11
+ */
12
+ export declare class SuisseBilanzDashboardComponent {
13
+ readonly embedded: import("@angular/core").InputSignal<boolean>;
14
+ /** Shows the official PDF download link even when `embedded` (header hidden). */
15
+ readonly showPdfButton: import("@angular/core").InputSignal<boolean>;
16
+ protected readonly planning: PlanningBalanceService;
17
+ private readonly sanitizer;
18
+ protected readonly metricsService: SuisseBilanzMetricsService;
19
+ private readonly result;
20
+ protected readonly metrics: import("@angular/core").Signal<import("../gauge-arc/gauge-arc.component").GaugeMetric[]>;
21
+ /** Surface areas in ha, derived from the latest planning result. */
22
+ protected readonly surfaces: import("@angular/core").Signal<{
23
+ sau: number;
24
+ sfe: number;
25
+ to: number;
26
+ } | null>;
27
+ protected readonly officialPdfUrl: import("@angular/core").Signal<SafeUrl | null>;
28
+ private prevBlobUrl;
29
+ private readonly blobCleanup;
30
+ /** Maps a `GaugeStatus` to its Material icon name for the status badge. */
31
+ protected statusIcon(status: GaugeStatus): string;
32
+ }
@@ -0,0 +1,21 @@
1
+ import { GaugeMetric } from '../gauge-arc/gauge-arc.component';
2
+ /**
3
+ * Shared source of truth for all SuisseBilanz metric view-models.
4
+ *
5
+ * Both the full dashboard card and the slim minibar consume this service so
6
+ * the derivation logic lives in exactly one place. Metrics re-compute via
7
+ * `computed()` when either the planning result or the locale signal changes.
8
+ */
9
+ export declare class SuisseBilanzMetricsService {
10
+ private readonly planning;
11
+ private readonly i18n;
12
+ /** Wall-clock time of the most recent successful planning result. */
13
+ readonly lastUpdated: import("@angular/core").WritableSignal<Date | null>;
14
+ constructor();
15
+ /**
16
+ * Five gauge view-models for N avail., P₂O₅, K₂O, Mg and Rendement prairies.
17
+ * Returns placeholder 'empty' metrics until the first planning result arrives.
18
+ */
19
+ readonly metrics: import("@angular/core").Signal<GaugeMetric[]>;
20
+ private emptyMetric;
21
+ }
@@ -0,0 +1,19 @@
1
+ import { GaugeMetric, GaugeStatus } from '../gauge-arc/gauge-arc.component';
2
+ import { SuisseBilanzMetricsService } from '../suissebilanz-dashboard/suissebilanz-metrics.service';
3
+ /**
4
+ * Slim, always-visible metrics card placed above the workflow stepper.
5
+ *
6
+ * Shows the same 5 SuisseBilanz metrics as the full dashboard card but in a
7
+ * compact single-row layout: metric label → bold coloured value → thin
8
+ * progress bar. Shares all data logic via `SuisseBilanzMetricsService`.
9
+ */
10
+ export declare class SuisseBilanzMinibarComponent {
11
+ protected readonly metricsService: SuisseBilanzMetricsService;
12
+ /** Returns the status colour for a given metric status. */
13
+ protected statusColor(status: GaugeStatus): string;
14
+ /**
15
+ * Maps the metric value to a 0–100 fill percentage for the progress bar,
16
+ * clamped so bars never overflow the track.
17
+ */
18
+ protected fillPct(metric: GaugeMetric): number;
19
+ }
@@ -0,0 +1,18 @@
1
+ import { ErrorObject } from 'ajv';
2
+ import { PlanningBalanceService } from '../../core/planning/planning-balance.service';
3
+ /**
4
+ * Final submission step: review validation status and submit the planning balance.
5
+ */
6
+ export declare class ValidationPageComponent {
7
+ readonly showHeader: import("@angular/core").InputSignal<boolean>;
8
+ /** Navigation callback for validation error clicks — provided by App to keep routing logic centralised. */
9
+ readonly onErrorSelected: import("@angular/core").InputSignal<(error: ErrorObject) => void>;
10
+ /** Navigation callback triggered after a fresh successful planning submission. */
11
+ readonly onSubmitSuccess: import("@angular/core").InputSignal<() => void>;
12
+ protected readonly planning: PlanningBalanceService;
13
+ private readonly globalValidation;
14
+ private lastHandledSuccessRequestId;
15
+ constructor();
16
+ protected readonly validationErrors: import("@angular/core").Signal<import("../../../public-api").EnrichedValidationError[]>;
17
+ protected readonly errorCount: import("@angular/core").Signal<number>;
18
+ }
@@ -1 +1 @@
1
- export { DEFAULT_SUIBI_METADATA, type SubmissionStatus, type SuibiVersion, type SuibiMetadata } from '../../core/metadata/suibi-metadata.types';
1
+ export { DEFAULT_SUIBI_METADATA, DEFAULT_COMPUTATION_MODULES, type ComputationModules, type SubmissionStatus, type SuibiVersion, type SuibiMetadata } from '../../core/metadata/suibi-metadata.types';
@@ -1,9 +1,9 @@
1
- import { OnInit } from '@angular/core';
2
1
  import { JsonSchema, UISchemaElement } from '@jsonforms/core';
3
2
  import { SuibiMetadata } from '../../core/metadata/suibi-metadata.types';
4
- export declare class WelcomePageComponent implements OnInit {
3
+ export declare class WelcomePageComponent {
5
4
  private readonly i18n;
6
5
  private readonly metadataSvc;
6
+ private readonly naebi;
7
7
  startEvent: import("@angular/core").OutputEmitterRef<void>;
8
8
  metadataChange: import("@angular/core").OutputEmitterRef<SuibiMetadata>;
9
9
  private readonly baseSchema;
@@ -17,11 +17,13 @@ export declare class WelcomePageComponent implements OnInit {
17
17
  readonly localizedSchema: import("@angular/core").Signal<JsonSchema>;
18
18
  readonly localizedUi: import("@angular/core").Signal<UISchemaElement>;
19
19
  readonly jsonFormsData: import("@angular/core").Signal<{}>;
20
- ngOnInit(): void;
20
+ constructor();
21
21
  start(): void;
22
+ loadExampleData(): void;
22
23
  onMetadataChange(newValue: unknown): void;
23
24
  private normalizeJsonFormsPayload;
24
25
  private toMetadata;
26
+ private extractModules;
25
27
  private isSuibiVersion;
26
28
  private isSubmissionStatus;
27
29
  private isSameMetadata;
@@ -0,0 +1,49 @@
1
+ import { PageId } from '../../core/navigation/navigation.service';
2
+ /**
3
+ * WorkflowStepperComponent
4
+ * Horizontal navigation stepper for the main data-entry workflow.
5
+ *
6
+ * Design contract:
7
+ * - Uses mat-stepper as a header-only nav bar (step content is empty; content
8
+ * area is hidden via CSS so the stepper acts as a pure navigation indicator).
9
+ * - [selectedIndex] is driven by the currentPage input — no internal routing state.
10
+ * - Navigation is delegated back to App via the onNavigate callback, preserving
11
+ * the custom-element page-attribute reflection.
12
+ * - Error indicators: any page with at least one enriched validation error shows
13
+ * the error ring on its step circle. Requires STEPPER_GLOBAL_OPTIONS { showError: true }.
14
+ * - Non-workflow pages (e.g. data_preview): mat-stepper rejects out-of-bounds selectedIndex,
15
+ * so we clamp to 0; the no-active-step CSS class neutralises the visual active indicator,
16
+ * and onStepperClick delegates clicks for all headers (bypassing the stepper's
17
+ * "no-change" guard that suppresses selectedIndexChange for the currently selected step).
18
+ *
19
+ * Extension points:
20
+ * - Completed state: replace the hardcoded `false` on [completed] with a per-page
21
+ * computed once domain completion rules are defined (e.g. all required fields valid).
22
+ * - New pages: add an entry to WORKFLOW_STEPS and extend PageId.
23
+ */
24
+ export declare class WorkflowStepperComponent {
25
+ protected readonly steps: readonly {
26
+ readonly pageId: PageId;
27
+ readonly labelKey: string;
28
+ }[];
29
+ /**
30
+ * Current page from the parent. Controls which step circle is highlighted.
31
+ * Non-workflow pages (e.g. data_preview) use index 0 as a valid CDK fallback;
32
+ * the no-active-step CSS class removes the visual active indicator for those pages.
33
+ */
34
+ readonly currentPage: import("@angular/core").InputSignal<PageId>;
35
+ /**
36
+ * Navigation callback provided by App.
37
+ * Using a callback (instead of an output EventEmitter) matches the existing
38
+ * header-bar pattern and ensures the custom-element page-attribute is reflected.
39
+ */
40
+ readonly onNavigate: import("@angular/core").InputSignal<(page: PageId) => void>;
41
+ private readonly validationSvc;
42
+ private readonly workflowPage;
43
+ protected readonly pagesWithErrors: import("@angular/core").Signal<Set<PageId>>;
44
+ protected readonly isOnWorkflowPage: import("@angular/core").Signal<boolean>;
45
+ protected readonly clampedStepIndex: import("@angular/core").Signal<number>;
46
+ protected onSelectedIndexChange(index: number): void;
47
+ protected onStepperClick(event: MouseEvent): void;
48
+ private navigateTo;
49
+ }
@@ -29,10 +29,8 @@ export declare class NaebiDataService {
29
29
  hoursPerDay: number;
30
30
  };
31
31
  stall: {
32
- stableSystem: number;
33
- stableCapacity: number;
32
+ stableSystem: string;
34
33
  stableVentilationType: number;
35
- stableAirPurification: number;
36
34
  hasStableDeepLitter: boolean;
37
35
  hasStableManureBeltDrying: boolean;
38
36
  stableManureRemovalFrequency: number;
@@ -41,10 +39,6 @@ export declare class NaebiDataService {
41
39
  hasStableFeedingStationElevated: boolean;
42
40
  hasStableFloorSlopedUrineDrainage: boolean;
43
41
  hasYard: boolean;
44
- yardFeeding: number;
45
- yardFloorType: number;
46
- yardDays: number;
47
- yardHoursPerDay: number;
48
42
  };
49
43
  };
50
44
  hasImpexDerivedExcretion: boolean;
@@ -52,6 +46,7 @@ export declare class NaebiDataService {
52
46
  feeding: {
53
47
  fodderConsumption: number;
54
48
  concentratedFeedstuffConsumption: number;
49
+ concentratedFeedStuffConsumption: number;
55
50
  winterFeeding: {
56
51
  feedingRoutine: {
57
52
  typeOfFeedstuffProduct: string;
@@ -76,19 +71,14 @@ export declare class NaebiDataService {
76
71
  }[];
77
72
  storage: {
78
73
  stableStrawLitter: number;
79
- manureSupplyProportionStored: number;
80
74
  slurrySupplyProportionStored: number;
81
75
  createFacilitySpecificManureProduct: boolean;
82
76
  createFacilitySpecificSlurryProduct: boolean;
77
+ slurryTankQuantity: number;
83
78
  dilutionRatio: number;
84
- manurePit: {
85
- cover: number;
86
- manureFromAnimalStockStored: {
87
- manureDerivation: string;
88
- proportionStored: number;
89
- }[];
90
- }[];
79
+ manurePit: never[];
91
80
  slurryTank: {
81
+ descriptor: string;
92
82
  volumeInM3: number;
93
83
  depthInM: number;
94
84
  cover: number;
@@ -97,16 +87,7 @@ export declare class NaebiDataService {
97
87
  }[];
98
88
  };
99
89
  farmManureTrading: {
100
- supply: {
101
- quantity: number;
102
- typeOfManureRecyclingProduct: string;
103
- transactionUnit: string;
104
- ingredient: {
105
- quantity: number;
106
- molecularFormula: string;
107
- unit: string;
108
- }[];
109
- }[];
90
+ supply: never[];
110
91
  dispense: {
111
92
  quantity: number;
112
93
  typeOfManureRecyclingProduct: string;
@@ -115,6 +96,11 @@ export declare class NaebiDataService {
115
96
  zoologicalAnimal: string;
116
97
  percentageAllocation: number;
117
98
  }[];
99
+ ingredient: {
100
+ quantity: number;
101
+ molecularFormula: string;
102
+ unit: string;
103
+ }[];
118
104
  }[];
119
105
  };
120
106
  fieldSpreading: {
@@ -138,6 +124,7 @@ export declare class NaebiDataService {
138
124
  proportionAppliedOtherMonths: number;
139
125
  };
140
126
  fertiliser: {
127
+ descriptor: string;
141
128
  fertiliserProductCategory: string;
142
129
  quantity: number;
143
130
  transactionUnit: string;
@@ -159,8 +146,6 @@ export declare class NaebiDataService {
159
146
  }[];
160
147
  };
161
148
  lifetimePerformance: {
162
- dailyGain: number;
163
- liveWeight: number;
164
149
  milkProductionReport: number;
165
150
  };
166
151
  fodder: {
@@ -175,6 +160,12 @@ export declare class NaebiDataService {
175
160
  unit: string;
176
161
  }[];
177
162
  }[];
163
+ dispense: {
164
+ typeOfFeedstuffProduct: string;
165
+ quantity: number;
166
+ transactionUnit: string;
167
+ ingredient: never[];
168
+ }[];
178
169
  };
179
170
  cropFromNonFodderCropland: {
180
171
  typeOfFeedstuffProduct: string;
@@ -190,6 +181,17 @@ export declare class NaebiDataService {
190
181
  totalBalanceErrorMargin: number;
191
182
  };
192
183
  fieldCultivation: {
184
+ buildingZoneAreaSize: number;
185
+ outdoorVegetableMainCropAreaSize: number;
186
+ indoorVegetableMainCropAreaSize: number;
187
+ feedingOfCropHarvest: {
188
+ agronomicCropCategory: string;
189
+ effectiveYield: number;
190
+ }[];
191
+ dispenseOfCropHarvest: {
192
+ agronomicCropCategory: string;
193
+ effectiveYield: number;
194
+ }[];
193
195
  fodderCropland: ({
194
196
  agronomicCropCategory: string;
195
197
  isMainCrop: boolean;
@@ -208,18 +210,29 @@ export declare class NaebiDataService {
208
210
  isMainCrop: boolean;
209
211
  areaSize: number;
210
212
  yieldPerSquareMeasure: number;
213
+ hasLongTermYieldDivergence: boolean;
211
214
  }[];
212
215
  special: {
213
216
  agronomicCropCategory: string;
214
217
  userSpecificPlantName: string;
215
218
  isMainCrop: boolean;
216
219
  areaSize: number;
217
- yieldPerSquareMeasure: number;
220
+ requirementCorrection: {
221
+ quantity: number;
222
+ molecularFormula: string;
223
+ unit: string;
224
+ }[];
218
225
  }[];
219
226
  };
220
227
  generateReport: boolean;
221
228
  };
229
+ calculationVersion: {
230
+ version: string;
231
+ };
222
232
  }>;
233
+ private readonly _lastEmitted;
234
+ private readonly _dirty;
235
+ readonly dirty: import("@angular/core").Signal<boolean>;
223
236
  private readonly _calculationMode;
224
237
  readonly calculationMode: import("@angular/core").Signal<CalculationMode>;
225
238
  /**
@@ -227,6 +240,8 @@ export declare class NaebiDataService {
227
240
  * Silent no-op if value is structurally equal after normalization to avoid unnecessary updates.
228
241
  */
229
242
  setData(value: NaebiData): void;
243
+ /** Mark current data as saved (clears dirty state and updates snapshot). */
244
+ markSaved(): void;
230
245
  /**
231
246
  * Set calculation mode (SuiBi or ExBi).
232
247
  * Can affect which validation rules are active or which features are enabled.
@@ -1,6 +1,5 @@
1
- import { ErrorHandler, Injector } from '@angular/core';
1
+ import { ErrorHandler } from '@angular/core';
2
2
  export declare class GlobalErrorHandler implements ErrorHandler {
3
- private injector;
4
- constructor(injector: Injector);
3
+ private readonly injector;
5
4
  handleError(error: any): void;
6
5
  }
@@ -1,5 +1,5 @@
1
1
  import { PipeTransform, Signal } from '@angular/core';
2
- export type Locale = 'en' | 'de';
2
+ export type Locale = 'en' | 'de' | 'fr' | 'it';
3
3
  export type JsonFormsTranslator = (key: string, defaultMessage: string | undefined, context: unknown) => string;
4
4
  export declare class I18nService {
5
5
  private readonly _locale;
@@ -8,13 +8,15 @@ export declare class I18nService {
8
8
  readonly jsonFormsI18n: Signal<{
9
9
  locale: Locale;
10
10
  translate: JsonFormsTranslator;
11
+ translateError: (error: unknown, translate: JsonFormsTranslator) => string;
11
12
  }>;
12
13
  setLocale(locale: Locale): void;
14
+ /** Returns true if the given string is a supported locale key. */
15
+ isValidLocale(value: string): value is Locale;
13
16
  t(key: string, defaultMessage?: string): string;
14
17
  }
15
18
  export declare class TranslatePipe implements PipeTransform {
16
- private readonly i18n;
17
19
  private readonly cache;
18
- constructor(i18n: I18nService);
20
+ private readonly i18n;
19
21
  transform(key: string, defaultMessage?: string): Signal<string>;
20
22
  }
@@ -0,0 +1,2 @@
1
+ export declare const frTranslations: Record<string, string>;
2
+ export type FrTranslationKeys = keyof typeof frTranslations;
@@ -0,0 +1,2 @@
1
+ export declare const itTranslations: Record<string, string>;
2
+ export type ItTranslationKeys = keyof typeof itTranslations;
@@ -1,7 +1,9 @@
1
1
  import { Locale } from '../i18n/i18n.service';
2
- type MasterDataKeyField = 'id' | 'code';
2
+ /** The property name of the primary key in a master-data catalog entry. */
3
+ type MasterDataKeyField = string;
3
4
  interface MasterDataCatalog {
4
5
  entries: any[];
6
+ /** Property name to use as the lookup key; 'id' entries are coerced to Number. */
5
7
  key: MasterDataKeyField;
6
8
  }
7
9
  declare const MASTER_DATA: Record<string, MasterDataCatalog>;
@@ -21,5 +23,10 @@ export declare class MasterDataService {
21
23
  resolveUtilisation(id: number | string | null | undefined, locale?: Locale): string;
22
24
  resolveManureProduct(code: string | null | undefined, locale?: Locale): string;
23
25
  resolveZoologicalAnimal(code: string | null | undefined, locale?: Locale): string;
26
+ resolveCultivationCategory(code: string | null | undefined, locale?: Locale): string;
27
+ resolveAgronomicCropCategory(code: string | null | undefined, locale?: Locale): string;
28
+ resolveFeedstuffProduct(code: string | null | undefined, locale?: Locale): string;
29
+ resolveCover(id: number | string | null | undefined, locale?: Locale): string;
30
+ resolveMixingFrequency(id: number | string | null | undefined, locale?: Locale): string;
24
31
  }
25
32
  export {};
@@ -1,8 +1,18 @@
1
- export type SuibiVersion = '1.19' | '1.20';
1
+ export type SuibiVersion = 'v2.0';
2
2
  export type SubmissionStatus = 'draft' | 'submitted' | 'final';
3
+ /** Which computation modules are active for this dossier. */
4
+ export interface ComputationModules {
5
+ suisseBilanz: boolean;
6
+ gmf: boolean;
7
+ nh3: boolean;
8
+ impex: boolean;
9
+ linear: boolean;
10
+ }
11
+ export declare const DEFAULT_COMPUTATION_MODULES: ComputationModules;
3
12
  export interface SuibiMetadata {
4
13
  title: string;
5
14
  suibiVersion: SuibiVersion;
6
15
  status: SubmissionStatus;
16
+ modules: ComputationModules;
7
17
  }
8
18
  export declare const DEFAULT_SUIBI_METADATA: SuibiMetadata;
@@ -1,8 +1,13 @@
1
- export type PageId = 'welcome' | 'animal_stock' | 'data_preview' | 'storage' | 'field_spreading' | 'farm_manure_trading';
1
+ export type PageId = 'welcome' | 'animal_stock' | 'data_preview' | 'storage' | 'field_spreading' | 'farm_manure_trading' | 'fodder' | 'field_cultivation' | 'validation' | 'results';
2
2
  export type AnimalStockCategory = 'base' | 'formOfDetention' | 'feeding';
3
3
  export type FarmManureTradingMode = 'supply' | 'dispense';
4
4
  export type FarmManureTradingCategory = 'general' | 'derivation' | 'ingredients';
5
+ export type FodderMode = 'supply' | 'dispense' | 'non_fodder_cropland';
6
+ export type FodderCategory = 'general' | 'ingredients';
5
7
  export type FieldSpreadingCategory = 'general' | 'fertiliser' | 'recycling';
8
+ export type FieldCultivationTab = 'general' | 'fodderCropland' | 'arableLand' | 'special';
9
+ export type StorageTab = 'manure' | 'slurry';
10
+ export type StorageEntryType = 'manure_pit' | 'slurry_tank';
6
11
  /**
7
12
  * NavigationService
8
13
  * Global reactive store for application routing and deep-link state.
@@ -38,6 +43,21 @@ export declare class NavigationService {
38
43
  mode: FarmManureTradingMode;
39
44
  index: number;
40
45
  } | null>;
46
+ /** Selected fodder detail context (mode + index) */
47
+ readonly selectedFodderDetail: import("@angular/core").WritableSignal<{
48
+ mode: FodderMode;
49
+ index: number;
50
+ } | null>;
51
+ /** Selected field cultivation detail context (tab + index) */
52
+ readonly selectedFieldCultivationDetail: import("@angular/core").WritableSignal<{
53
+ tab: Exclude<FieldCultivationTab, "general">;
54
+ index: number;
55
+ } | null>;
56
+ /** Selected storage detail context (type + index) */
57
+ readonly selectedStorageDetail: import("@angular/core").WritableSignal<{
58
+ type: StorageEntryType;
59
+ index: number;
60
+ } | null>;
41
61
  /** True if currently viewing animal stock detail (not list) */
42
62
  readonly isAnimalStockDetailView: import("@angular/core").Signal<boolean>;
43
63
  /** True if currently on animal stock page (list or detail) */
@@ -58,10 +78,18 @@ export declare class NavigationService {
58
78
  navigateToAnimalStockDetail(index: number, category?: AnimalStockCategory): void;
59
79
  navigateToFarmManureTradingDetail(mode: FarmManureTradingMode, index: number, category?: FarmManureTradingCategory): void;
60
80
  navigateToFarmManureTradingList(): void;
81
+ navigateToFodderDetail(mode: FodderMode, index: number, category?: FodderCategory): void;
82
+ navigateToFodderList(): void;
61
83
  navigateToFieldSpreading(category?: FieldSpreadingCategory): void;
84
+ navigateToFieldCultivationDetail(tab: Exclude<FieldCultivationTab, 'general'>, index: number): void;
85
+ navigateToFieldCultivationList(tab?: FieldCultivationTab): void;
86
+ navigateToStorageDetail(type: StorageEntryType, index: number): void;
87
+ navigateToStorageList(tab?: StorageTab): void;
62
88
  /**
63
89
  * Set active category/tab for current page (without changing page/entry).
64
90
  * Generic method supporting any page's categorization navigation.
91
+ * No-op when page and category are already the same values to prevent
92
+ * unnecessary signal emissions that re-trigger the tab index computed.
65
93
  */
66
94
  setCategory(page: PageId, category: string): void;
67
95
  /**
@@ -0,0 +1,38 @@
1
+ import { NaebiData } from '../data/naebi-data.service';
2
+ import type { PlanningBalanceResponse } from './planning-balance.types';
3
+ export type { PlanningBalanceResponse } from './planning-balance.types';
4
+ /** Which backend to target for planning requests. */
5
+ export type PlanningEndpoint = 'ebilanz' | 'blw';
6
+ /**
7
+ * Sends NAEBI data to a planning endpoint and exposes the result as a
8
+ * signal-based resource. Call `runPlanning(data, endpoint)` to trigger a request.
9
+ *
10
+ * The ID counter ensures each call re-fetches even if the payload hasn't changed.
11
+ */
12
+ export declare class PlanningBalanceService {
13
+ private readonly http;
14
+ private readonly metadataSvc;
15
+ private readonly _value;
16
+ private readonly _error;
17
+ private readonly _isLoading;
18
+ private readonly _selectedEndpoint;
19
+ private readonly _lastStartedRequestId;
20
+ private readonly _lastCompletedRequestId;
21
+ private readonly _lastSuccessfulRequestId;
22
+ private _nextId;
23
+ private activeRequestId;
24
+ private activeRequestSub;
25
+ readonly planningResource: {
26
+ value: import("@angular/core").Signal<PlanningBalanceResponse | undefined>;
27
+ error: import("@angular/core").Signal<unknown>;
28
+ isLoading: import("@angular/core").Signal<boolean>;
29
+ hasValue: import("@angular/core").Signal<boolean>;
30
+ lastStartedRequestId: import("@angular/core").Signal<number>;
31
+ lastCompletedRequestId: import("@angular/core").Signal<number>;
32
+ lastSuccessfulRequestId: import("@angular/core").Signal<number>;
33
+ };
34
+ readonly selectedEndpoint: import("@angular/core").Signal<PlanningEndpoint>;
35
+ setSelectedEndpoint(endpoint: PlanningEndpoint): void;
36
+ /** Fire a new planning-balance request with the current NAEBI data payload. */
37
+ runPlanning(data: NaebiData, endpoint?: PlanningEndpoint): void;
38
+ }