@rsuci/shared-form-components 1.0.0

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 (131) hide show
  1. package/README.md +152 -0
  2. package/dist/components/GroupRenderer.d.ts +19 -0
  3. package/dist/components/GroupRenderer.d.ts.map +1 -0
  4. package/dist/components/GroupRenderer.js +214 -0
  5. package/dist/components/IdDocInput.d.ts +20 -0
  6. package/dist/components/IdDocInput.d.ts.map +1 -0
  7. package/dist/components/IdDocInput.js +188 -0
  8. package/dist/components/VariableRenderer.d.ts +35 -0
  9. package/dist/components/VariableRenderer.d.ts.map +1 -0
  10. package/dist/components/VariableRenderer.js +83 -0
  11. package/dist/components/display/LabelDisplay.d.ts +14 -0
  12. package/dist/components/display/LabelDisplay.d.ts.map +1 -0
  13. package/dist/components/display/LabelDisplay.js +10 -0
  14. package/dist/components/display/PanelDisplay.d.ts +14 -0
  15. package/dist/components/display/PanelDisplay.d.ts.map +1 -0
  16. package/dist/components/display/PanelDisplay.js +10 -0
  17. package/dist/components/geographic/DepartementInput.d.ts +38 -0
  18. package/dist/components/geographic/DepartementInput.d.ts.map +1 -0
  19. package/dist/components/geographic/DepartementInput.js +30 -0
  20. package/dist/components/geographic/DistrictInput.d.ts +30 -0
  21. package/dist/components/geographic/DistrictInput.d.ts.map +1 -0
  22. package/dist/components/geographic/DistrictInput.js +26 -0
  23. package/dist/components/geographic/QuartierInput.d.ts +38 -0
  24. package/dist/components/geographic/QuartierInput.d.ts.map +1 -0
  25. package/dist/components/geographic/QuartierInput.js +30 -0
  26. package/dist/components/geographic/RegionInput.d.ts +38 -0
  27. package/dist/components/geographic/RegionInput.d.ts.map +1 -0
  28. package/dist/components/geographic/RegionInput.js +30 -0
  29. package/dist/components/geographic/SousPrefectureInput.d.ts +38 -0
  30. package/dist/components/geographic/SousPrefectureInput.d.ts.map +1 -0
  31. package/dist/components/geographic/SousPrefectureInput.js +30 -0
  32. package/dist/components/geographic/VillageInput.d.ts +38 -0
  33. package/dist/components/geographic/VillageInput.d.ts.map +1 -0
  34. package/dist/components/geographic/VillageInput.js +30 -0
  35. package/dist/components/index.d.ts +27 -0
  36. package/dist/components/index.d.ts.map +1 -0
  37. package/dist/components/index.js +33 -0
  38. package/dist/components/inputs/CheckboxInput.d.ts +19 -0
  39. package/dist/components/inputs/CheckboxInput.d.ts.map +1 -0
  40. package/dist/components/inputs/CheckboxInput.js +38 -0
  41. package/dist/components/inputs/ComboboxInput.d.ts +19 -0
  42. package/dist/components/inputs/ComboboxInput.d.ts.map +1 -0
  43. package/dist/components/inputs/ComboboxInput.js +21 -0
  44. package/dist/components/inputs/DatePicker.d.ts +19 -0
  45. package/dist/components/inputs/DatePicker.d.ts.map +1 -0
  46. package/dist/components/inputs/DatePicker.js +39 -0
  47. package/dist/components/inputs/GPSInput.d.ts +18 -0
  48. package/dist/components/inputs/GPSInput.d.ts.map +1 -0
  49. package/dist/components/inputs/GPSInput.js +44 -0
  50. package/dist/components/inputs/HourInput.d.ts +19 -0
  51. package/dist/components/inputs/HourInput.d.ts.map +1 -0
  52. package/dist/components/inputs/HourInput.js +20 -0
  53. package/dist/components/inputs/NumberInput.d.ts +20 -0
  54. package/dist/components/inputs/NumberInput.d.ts.map +1 -0
  55. package/dist/components/inputs/NumberInput.js +42 -0
  56. package/dist/components/inputs/PhoneInput.d.ts +19 -0
  57. package/dist/components/inputs/PhoneInput.d.ts.map +1 -0
  58. package/dist/components/inputs/PhoneInput.js +11 -0
  59. package/dist/components/inputs/RadioInput.d.ts +19 -0
  60. package/dist/components/inputs/RadioInput.d.ts.map +1 -0
  61. package/dist/components/inputs/RadioInput.js +19 -0
  62. package/dist/components/inputs/SelectInput.d.ts +19 -0
  63. package/dist/components/inputs/SelectInput.d.ts.map +1 -0
  64. package/dist/components/inputs/SelectInput.js +39 -0
  65. package/dist/components/inputs/StringInput.d.ts +19 -0
  66. package/dist/components/inputs/StringInput.d.ts.map +1 -0
  67. package/dist/components/inputs/StringInput.js +15 -0
  68. package/dist/components/roster/RosterCheckInput.d.ts +23 -0
  69. package/dist/components/roster/RosterCheckInput.d.ts.map +1 -0
  70. package/dist/components/roster/RosterCheckInput.js +111 -0
  71. package/dist/components/roster/RosterListInput.d.ts +23 -0
  72. package/dist/components/roster/RosterListInput.d.ts.map +1 -0
  73. package/dist/components/roster/RosterListInput.js +77 -0
  74. package/dist/components/roster/RosterPanel.d.ts +34 -0
  75. package/dist/components/roster/RosterPanel.d.ts.map +1 -0
  76. package/dist/components/roster/RosterPanel.js +40 -0
  77. package/dist/components/roster/index.d.ts +11 -0
  78. package/dist/components/roster/index.d.ts.map +1 -0
  79. package/dist/components/roster/index.js +8 -0
  80. package/dist/components/selectors/EnqueteInput.d.ts +29 -0
  81. package/dist/components/selectors/EnqueteInput.d.ts.map +1 -0
  82. package/dist/components/selectors/EnqueteInput.js +21 -0
  83. package/dist/components/selectors/MenageInput.d.ts +29 -0
  84. package/dist/components/selectors/MenageInput.d.ts.map +1 -0
  85. package/dist/components/selectors/MenageInput.js +21 -0
  86. package/dist/components/selectors/RSUInput.d.ts +24 -0
  87. package/dist/components/selectors/RSUInput.d.ts.map +1 -0
  88. package/dist/components/selectors/RSUInput.js +16 -0
  89. package/dist/components/wrappers/ImageUpload.d.ts +26 -0
  90. package/dist/components/wrappers/ImageUpload.d.ts.map +1 -0
  91. package/dist/components/wrappers/ImageUpload.js +60 -0
  92. package/dist/components/wrappers/PhotoCapture.d.ts +26 -0
  93. package/dist/components/wrappers/PhotoCapture.d.ts.map +1 -0
  94. package/dist/components/wrappers/PhotoCapture.js +137 -0
  95. package/dist/index.d.ts +41 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +62 -0
  98. package/dist/lib/condition-engine.d.ts +138 -0
  99. package/dist/lib/condition-engine.d.ts.map +1 -0
  100. package/dist/lib/condition-engine.js +584 -0
  101. package/dist/lib/index.d.ts +11 -0
  102. package/dist/lib/index.d.ts.map +1 -0
  103. package/dist/lib/index.js +10 -0
  104. package/dist/lib/utils/cn.d.ts +12 -0
  105. package/dist/lib/utils/cn.d.ts.map +1 -0
  106. package/dist/lib/utils/cn.js +14 -0
  107. package/dist/lib/utils/interpolateVariableLabel.d.ts +54 -0
  108. package/dist/lib/utils/interpolateVariableLabel.d.ts.map +1 -0
  109. package/dist/lib/utils/interpolateVariableLabel.js +152 -0
  110. package/dist/lib/utils/variableValueConverter.d.ts +76 -0
  111. package/dist/lib/utils/variableValueConverter.d.ts.map +1 -0
  112. package/dist/lib/utils/variableValueConverter.js +470 -0
  113. package/dist/types/enquete-service.d.ts +26 -0
  114. package/dist/types/enquete-service.d.ts.map +1 -0
  115. package/dist/types/enquete-service.js +5 -0
  116. package/dist/types/enquete.d.ts +338 -0
  117. package/dist/types/enquete.d.ts.map +1 -0
  118. package/dist/types/enquete.js +5 -0
  119. package/dist/types/form-renderer.d.ts +54 -0
  120. package/dist/types/form-renderer.d.ts.map +1 -0
  121. package/dist/types/form-renderer.js +5 -0
  122. package/dist/types/index.d.ts +8 -0
  123. package/dist/types/index.d.ts.map +1 -0
  124. package/dist/types/index.js +10 -0
  125. package/dist/types/menages.d.ts +40 -0
  126. package/dist/types/menages.d.ts.map +1 -0
  127. package/dist/types/menages.js +5 -0
  128. package/dist/types/services.d.ts +88 -0
  129. package/dist/types/services.d.ts.map +1 -0
  130. package/dist/types/services.js +5 -0
  131. package/package.json +42 -0
package/README.md ADDED
@@ -0,0 +1,152 @@
1
+ # @rsu/shared-form-components
2
+
3
+ Composants React partagés pour le rendu des formulaires d'enquête RSU v2.
4
+
5
+ ## 📦 Installation
6
+
7
+ ```bash
8
+ npm install @rsu/shared-form-components
9
+ ```
10
+
11
+ ## 🎯 Objectif
12
+
13
+ Ce package centralise tous les composants de rendu de formulaires pour :
14
+ - **Frontend Admin** (`rsu_app_frontend_v2`) : Gestion interne des enquêtes
15
+ - **Frontend Public** (`rsu_public_frontend_v2`) : Collecte de données par le public
16
+
17
+ ## 🚀 Utilisation
18
+
19
+ ### Exemple basique
20
+
21
+ ```typescript
22
+ import { FormRenderer } from '@rsu/shared-form-components';
23
+
24
+ function EnquetePage() {
25
+ const [enquete, setEnquete] = useState<EnqueteInstance>({...});
26
+
27
+ return (
28
+ <FormRenderer
29
+ enquete={enquete}
30
+ formulaire={formulaire}
31
+ disabled={false}
32
+ onSave={handleSave}
33
+ onComplete={handleComplete}
34
+ onCancel={handleCancel}
35
+ />
36
+ );
37
+ }
38
+ ```
39
+
40
+ ### Avec injection de dépendances (Frontend Admin)
41
+
42
+ ```typescript
43
+ import { FormRenderer, FormRendererServices } from '@rsu/shared-form-components';
44
+ import { menagesService, enquetesService } from '@/lib/api';
45
+ import DistrictSelector from '@/components/selectors/geographic/DistrictSelector';
46
+ // ... autres imports
47
+
48
+ const services: FormRendererServices = {
49
+ fetchMenages: () => menagesService.getAll(),
50
+ fetchEnquetes: (filter) => enquetesService.getFiltered(filter),
51
+ };
52
+
53
+ const geographicComponents = {
54
+ DistrictSelectorComponent: DistrictSelector,
55
+ RegionSelectorComponent: RegionSelector,
56
+ // ... autres composants
57
+ };
58
+
59
+ <FormRenderer
60
+ enquete={enquete}
61
+ formulaire={formulaire}
62
+ services={services}
63
+ geographicComponents={geographicComponents}
64
+ onSave={handleSave}
65
+ />
66
+ ```
67
+
68
+ ## 📋 Types supportés
69
+
70
+ ### Types de base
71
+ - STRING, TEXTE, NUMERIQUE, DATE, DATEHEURE, HOUR
72
+ - CHECKBOX, RADIO, LISTE, COMBOBOX, PHONE
73
+
74
+ ### Types avancés
75
+ - GPS, PHOTO, IMAGE
76
+ - LABEL, PANEL
77
+
78
+ ### Types géographiques
79
+ - DISTRICT, REGION, DEPARTEMENT, SOUSPREFECTURE, QUARTIER, VILLAGE, RSU
80
+
81
+ ### Types sélecteurs
82
+ - MENAGE, ENQUETE
83
+
84
+ ### Types rosters (⭐ avec rendu natif)
85
+ - ROSTERCHECK, ROSTERLIST
86
+
87
+ ### Types documents
88
+ - IDDOC
89
+
90
+ ## 🔧 Architecture
91
+
92
+ ### Injection de dépendances
93
+
94
+ Le package utilise le pattern d'injection de dépendances pour :
95
+ - **Services API** : `FormRendererServices` (optionnel)
96
+ - **Composants géographiques** : `GeographicComponents` (optionnel)
97
+
98
+ Cela permet :
99
+ - ✅ Utilisation avec différentes API
100
+ - ✅ Réutilisation de composants existants
101
+ - ✅ Flexibilité maximale
102
+
103
+ ### Support des rosters
104
+
105
+ Les rosters (ROSTERCHECK et ROSTERLIST) sont automatiquement supportés avec :
106
+ - Rendu des variables selon leur type natif (RADIO, COMBOBOX, etc.)
107
+ - Indépendance des variables entre panels
108
+ - Comportement conditionnel pour ROSTERCHECK (checkbox + masquage)
109
+
110
+ ## 📝 Changelog
111
+
112
+ ### v1.0.0 (2025-11-25)
113
+ - ✅ Extraction depuis rsu_app_frontend_v2
114
+ - ✅ Support rosters avec RosterPanel
115
+ - ✅ Indépendance variables entre panels
116
+ - ✅ Comportement conditionnel ROSTERCHECK
117
+ - ✅ Injection de dépendances pour services et composants géographiques
118
+ - ✅ 27 types de variables supportés
119
+
120
+ ## 🏗️ Développement
121
+
122
+ ### Build
123
+
124
+ ```bash
125
+ npm run build
126
+ ```
127
+
128
+ ### Watch mode
129
+
130
+ ```bash
131
+ npm run watch
132
+ ```
133
+
134
+ ### Tests
135
+
136
+ ```bash
137
+ npm test
138
+ npm run test:coverage
139
+ ```
140
+
141
+ ## 📚 Documentation technique
142
+
143
+ - Plan de mutualisation : `docs/mutualisation_FormRenderer.md`
144
+ - Refonte rosters : `docs/ROSTER_PANELS_FINAL.md`
145
+
146
+ ## 👥 Auteurs
147
+
148
+ RSU v2 Architecture Team
149
+
150
+ ## 📄 License
151
+
152
+ UNLICENSED - Usage interne uniquement
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Composant de rendu des groupes pour les formulaires d'enquête
3
+ * RSU v2 - Moteur de Rendu des Formulaires d'Enquête
4
+ */
5
+ import React from 'react';
6
+ import { GroupeFormulaire, EnqueteReponse, VariableValue, ValidationError, AutoAction } from '../types/enquete';
7
+ import { ConditionEngine } from '../lib/condition-engine';
8
+ interface GroupRendererProps {
9
+ groupe: GroupeFormulaire;
10
+ responses: Record<string, EnqueteReponse>;
11
+ conditionEngine: ConditionEngine;
12
+ onChange: (variableCode: string, value: VariableValue, iteration?: number) => void;
13
+ onValidation: (errors: ValidationError[]) => void;
14
+ onAutoAction?: (actions: AutoAction[]) => void;
15
+ disabled?: boolean;
16
+ }
17
+ declare const GroupRenderer: React.FC<GroupRendererProps>;
18
+ export default GroupRenderer;
19
+ //# sourceMappingURL=GroupRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GroupRenderer.d.ts","sourceRoot":"","sources":["../../src/components/GroupRenderer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,eAAe,EACf,UAAU,EACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,UAAU,kBAAkB;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnF,YAAY,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;IAClD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAiJD,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAkS/C,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Composant de rendu des groupes pour les formulaires d'enquête
3
+ * RSU v2 - Moteur de Rendu des Formulaires d'Enquête
4
+ */
5
+ 'use client';
6
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
+ import { useState, useEffect } from 'react';
8
+ import { Plus, Trash2, Users, AlertCircle } from 'lucide-react';
9
+ import VariableRenderer from './VariableRenderer';
10
+ // Composant pour gérer les groupes multiples
11
+ const MultipleGroupManager = ({ groupe, entries, onAddEntry, onRemoveEntry, children }) => {
12
+ const canAddEntry = entries.length < (groupe.configMultiple?.maxIterations || 50);
13
+ const canRemoveEntry = entries.length > (groupe.configMultiple?.minIterations || 1);
14
+ return (_jsxs("div", { className: "multiple-group-manager space-y-6", children: [_jsxs("div", { className: "flex items-center justify-between p-4 bg-blue-50 border border-blue-200 rounded-lg", children: [_jsxs("div", { className: "flex items-center space-x-3", children: [_jsx(Users, { className: "h-5 w-5 text-blue-600" }), _jsxs("div", { children: [_jsx("h3", { className: "font-medium text-blue-900", children: groupe.designation }), _jsxs("p", { className: "text-sm text-blue-700", children: [entries.length, " ", entries.length > 1 ? 'entrées' : 'entrée', groupe.configMultiple?.maxIterations && (_jsxs("span", { children: [" (max: ", groupe.configMultiple.maxIterations, ")"] }))] })] })] }), groupe.configMultiple?.allowManualControl && (_jsxs("button", { onClick: onAddEntry, disabled: !canAddEntry, className: `flex items-center px-3 py-2 text-sm font-medium rounded-lg transition-colors ${canAddEntry
15
+ ? 'bg-green-600 text-white hover:bg-green-700 focus:ring-2 focus:ring-green-500'
16
+ : 'bg-gray-300 text-gray-500 cursor-not-allowed'}`, children: [_jsx(Plus, { className: "h-4 w-4 mr-1" }), "Ajouter"] }))] }), _jsx("div", { className: "space-y-4", children: children })] }));
17
+ };
18
+ // Composant pour une entrée individuelle dans un groupe multiple
19
+ const MultipleGroupEntry = ({ groupe, iterationNumber, totalIterations, visibleVariables, responses, onChange, onRemove, canRemove, disabled }) => {
20
+ const entryTitle = groupe.configMultiple?.labelTemplate?.replace('{index}', iterationNumber.toString()) ||
21
+ `${groupe.designation} ${iterationNumber}`;
22
+ return (_jsxs("div", { className: "iteration-card bg-white border border-gray-200 rounded-lg p-4 shadow-sm", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("h4", { className: "text-lg font-medium text-gray-800 flex items-center", children: [_jsx("span", { className: "w-6 h-6 bg-blue-100 text-blue-800 rounded-full flex items-center justify-center text-sm font-semibold mr-2", children: iterationNumber }), entryTitle] }), groupe.configMultiple?.allowManualControl && canRemove && onRemove && (_jsx("button", { onClick: onRemove, disabled: disabled, className: "p-2 text-red-500 hover:text-red-700 hover:bg-red-50 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed", title: "Supprimer cette entr\u00E9e", children: _jsx(Trash2, { className: "h-4 w-4" }) }))] }), _jsx("div", { className: "variables-grid grid grid-cols-1 md:grid-cols-2 gap-4", children: visibleVariables.map(variable => {
23
+ const responseKey = `${variable.code}_${iterationNumber}`;
24
+ // Extraire les variables roster si c'est un type ROSTERCHECK ou ROSTERLIST
25
+ const rosterVariables = (variable.typeCode === 'ROSTERCHECK' || variable.typeCode === 'ROSTERLIST')
26
+ ? variable.rosterVariables
27
+ : undefined;
28
+ // 🔍 LOG: Vérifier la transmission des rosterVariables dans MultipleGroupEntry
29
+ if (variable.typeCode === 'ROSTERCHECK' || variable.typeCode === 'ROSTERLIST') {
30
+ console.log(`🔍 [GroupRenderer/MultipleGroupEntry] Variable ${variable.code}:`, {
31
+ typeCode: variable.typeCode,
32
+ rosterVariables: rosterVariables,
33
+ rosterVariablesType: typeof rosterVariables,
34
+ isArray: Array.isArray(rosterVariables),
35
+ length: Array.isArray(rosterVariables) ? rosterVariables.length : 'N/A'
36
+ });
37
+ }
38
+ return (_jsx(VariableRenderer, { variable: variable, value: responses[responseKey]?.valeur, onChange: (value) => onChange(responseKey, value, iterationNumber), numeroMembre: iterationNumber, disabled: disabled, rosterVariables: rosterVariables }, responseKey));
39
+ }) })] }));
40
+ };
41
+ // Composant principal GroupRenderer
42
+ const GroupRenderer = ({ groupe, responses, conditionEngine, onChange, onValidation, onAutoAction, disabled = false }) => {
43
+ const [multipleEntries, setMultipleEntries] = useState([1]);
44
+ const [validationErrors, setValidationErrors] = useState([]);
45
+ // Obtenir le nombre d'itérations depuis la variable de contrôle
46
+ const getIterationCount = () => {
47
+ if (!groupe.estMultiple || !groupe.configMultiple?.variableControle) {
48
+ return 1;
49
+ }
50
+ const controlValue = responses[groupe.configMultiple.variableControle]?.valeur;
51
+ if (!controlValue || controlValue < 1) {
52
+ return groupe.configMultiple.minIterations || 1;
53
+ }
54
+ return Math.min(controlValue, groupe.configMultiple.maxIterations || 50);
55
+ };
56
+ // Filtrer les variables visibles selon les conditions (avec support des nouvelles fonctions)
57
+ const getVisibleVariables = () => {
58
+ console.log('📋 [GroupRenderer] Filtering visible variables for group:', groupe.designation);
59
+ return groupe.variables.filter(variable => {
60
+ console.log(`📋 [GroupRenderer] Processing variable: ${variable.code} (${variable.designation})`);
61
+ console.log(`📋 [GroupRenderer] - estVisible: ${variable.estVisible}`);
62
+ console.log(`📋 [GroupRenderer] - conditionsAffichage: ${variable.conditionsAffichage}`);
63
+ if (!variable.conditionsAffichage) {
64
+ console.log(`📋 [GroupRenderer] - No condition, returning estVisible: ${variable.estVisible}`);
65
+ return variable.estVisible;
66
+ }
67
+ // Évaluer la condition avec le moteur étendu
68
+ const isVisible = conditionEngine.evaluate(variable.conditionsAffichage);
69
+ console.log(`📋 [GroupRenderer] - Condition evaluation result: ${isVisible}`);
70
+ const finalResult = variable.estVisible && isVisible;
71
+ console.log(`📋 [GroupRenderer] - Final visibility: ${finalResult} (estVisible: ${variable.estVisible} && condition: ${isVisible})`);
72
+ return finalResult;
73
+ });
74
+ };
75
+ const visibleVariables = getVisibleVariables();
76
+ // Mettre à jour le nombre d'itérations quand la variable de contrôle change
77
+ useEffect(() => {
78
+ if (groupe.estMultiple && groupe.configMultiple?.variableControle) {
79
+ const newCount = getIterationCount();
80
+ if (groupe.configMultiple.allowManualControl) {
81
+ // Pour les groupes avec contrôle manuel, ajuster le nombre d'entrées
82
+ if (newCount > multipleEntries.length) {
83
+ const additionalEntries = Array.from({ length: newCount - multipleEntries.length }, (_, i) => multipleEntries.length + i + 1);
84
+ setMultipleEntries([...multipleEntries, ...additionalEntries]);
85
+ }
86
+ else if (newCount < multipleEntries.length) {
87
+ setMultipleEntries(multipleEntries.slice(0, newCount));
88
+ }
89
+ }
90
+ else {
91
+ // Pour les groupes automatiques, générer les entrées
92
+ setMultipleEntries(Array.from({ length: newCount }, (_, i) => i + 1));
93
+ }
94
+ }
95
+ }, [responses[groupe.configMultiple?.variableControle || '']?.valeur, groupe]);
96
+ // Validation du groupe
97
+ useEffect(() => {
98
+ const errors = [];
99
+ visibleVariables.forEach(variable => {
100
+ if (variable.estObligatoire) {
101
+ if (groupe.estMultiple) {
102
+ // Valider toutes les itérations
103
+ multipleEntries.forEach(iterationNumber => {
104
+ const responseKey = `${variable.code}_${iterationNumber}`;
105
+ const response = responses[responseKey];
106
+ if (!response || isEmpty(response.valeur)) {
107
+ const entryLabel = groupe.configMultiple?.labelTemplate?.replace('{index}', iterationNumber.toString()) ||
108
+ `Entrée ${iterationNumber}`;
109
+ errors.push({
110
+ variableCode: responseKey,
111
+ message: `${variable.designation} est obligatoire (${entryLabel})`,
112
+ type: 'required'
113
+ });
114
+ }
115
+ });
116
+ }
117
+ else {
118
+ // Groupe simple
119
+ const response = responses[variable.code];
120
+ if (!response || isEmpty(response.valeur)) {
121
+ errors.push({
122
+ variableCode: variable.code,
123
+ message: `${variable.designation} est obligatoire`,
124
+ type: 'required'
125
+ });
126
+ }
127
+ }
128
+ }
129
+ });
130
+ setValidationErrors(errors);
131
+ onValidation(errors);
132
+ }, [responses, visibleVariables, multipleEntries, groupe, onValidation]);
133
+ // Exécuter les actions automatiques quand les réponses changent
134
+ useEffect(() => {
135
+ if (!onAutoAction)
136
+ return;
137
+ const executeAutoActions = () => {
138
+ const allActions = [];
139
+ // Parcourir toutes les variables pour détecter les actions automatiques
140
+ visibleVariables.forEach(variable => {
141
+ if (variable.conditionsAffichage && variable.conditionsAffichage.includes('setValeur(')) {
142
+ // Évaluer la condition pour déclencher les actions automatiques
143
+ conditionEngine.evaluate(variable.conditionsAffichage);
144
+ // Récupérer les actions générées
145
+ const actions = conditionEngine.getAutoActions();
146
+ allActions.push(...actions);
147
+ }
148
+ });
149
+ if (allActions.length > 0) {
150
+ onAutoAction(allActions);
151
+ conditionEngine.clearAutoActions(); // Nettoyer après exécution
152
+ }
153
+ };
154
+ // Exécuter avec un délai pour éviter les boucles infinies
155
+ const timeoutId = setTimeout(executeAutoActions, 100);
156
+ return () => clearTimeout(timeoutId);
157
+ }, [responses, visibleVariables, conditionEngine, onAutoAction]);
158
+ // Gestion des entrées multiples
159
+ const addEntry = () => {
160
+ if (!groupe.configMultiple?.allowManualControl)
161
+ return;
162
+ const maxIterations = groupe.configMultiple.maxIterations || 50;
163
+ if (multipleEntries.length < maxIterations) {
164
+ const newEntryNumber = Math.max(...multipleEntries) + 1;
165
+ setMultipleEntries([...multipleEntries, newEntryNumber]);
166
+ }
167
+ };
168
+ const removeEntry = (index) => {
169
+ if (!groupe.configMultiple?.allowManualControl)
170
+ return;
171
+ if (multipleEntries.length <= (groupe.configMultiple.minIterations || 1))
172
+ return;
173
+ const entryNumber = multipleEntries[index];
174
+ const newEntries = multipleEntries.filter((_, i) => i !== index);
175
+ setMultipleEntries(newEntries);
176
+ // Supprimer les réponses de cette itération
177
+ visibleVariables.forEach(variable => {
178
+ const responseKey = `${variable.code}_${entryNumber}`;
179
+ if (responses[responseKey]) {
180
+ onChange(responseKey, null, entryNumber);
181
+ }
182
+ });
183
+ };
184
+ const isEmpty = (value) => {
185
+ return value === null ||
186
+ value === undefined ||
187
+ value === '' ||
188
+ (Array.isArray(value) && value.length === 0);
189
+ };
190
+ // Vérifier si le groupe doit être affiché
191
+ const shouldShowGroup = !groupe.conditionsAffichage ||
192
+ conditionEngine.evaluate(groupe.conditionsAffichage);
193
+ if (!shouldShowGroup) {
194
+ return null;
195
+ }
196
+ // Affichage des erreurs de validation
197
+ const ErrorSummary = () => {
198
+ if (validationErrors.length === 0)
199
+ return null;
200
+ return (_jsxs("div", { className: "mb-4 p-3 bg-red-50 border border-red-200 rounded-lg", children: [_jsxs("div", { className: "flex items-center mb-2", children: [_jsx(AlertCircle, { className: "h-4 w-4 text-red-600 mr-2" }), _jsxs("h4", { className: "text-sm font-medium text-red-800", children: ["Erreurs de validation (", validationErrors.length, ")"] })] }), _jsxs("ul", { className: "text-sm text-red-700 space-y-1", children: [validationErrors.slice(0, 5).map((error, index) => (_jsxs("li", { children: ["\u2022 ", error.message] }, index))), validationErrors.length > 5 && (_jsxs("li", { className: "text-red-600 font-medium", children: ["... et ", validationErrors.length - 5, " autres erreurs"] }))] })] }));
201
+ };
202
+ if (groupe.estMultiple) {
203
+ return (_jsxs("div", { className: "group-renderer-multiple", children: [_jsx(ErrorSummary, {}), _jsx(MultipleGroupManager, { groupe: groupe, entries: multipleEntries, onAddEntry: addEntry, onRemoveEntry: removeEntry, children: multipleEntries.map((iterationNumber, index) => (_jsx(MultipleGroupEntry, { groupe: groupe, iterationNumber: iterationNumber, totalIterations: multipleEntries.length, visibleVariables: visibleVariables, responses: responses, onChange: onChange, onRemove: () => removeEntry(index), canRemove: multipleEntries.length > (groupe.configMultiple?.minIterations || 1), disabled: disabled }, iterationNumber))) })] }));
204
+ }
205
+ // Groupe simple
206
+ return (_jsxs("div", { className: "group-renderer-simple", children: [_jsxs("div", { className: "mb-6", children: [_jsx("h2", { className: "text-xl font-semibold text-gray-900 mb-2", children: groupe.designation }), visibleVariables.length > 0 && (_jsxs("p", { className: "text-gray-600 text-sm", children: [visibleVariables.length, " ", visibleVariables.length > 1 ? 'champs' : 'champ'] }))] }), _jsx(ErrorSummary, {}), _jsx("div", { className: "variables-container space-y-6", children: visibleVariables.map(variable => {
207
+ // Extraire les variables roster si c'est un type ROSTERCHECK ou ROSTERLIST
208
+ const rosterVariables = (variable.typeCode === 'ROSTERCHECK' || variable.typeCode === 'ROSTERLIST')
209
+ ? variable.rosterVariables
210
+ : undefined;
211
+ return (_jsx(VariableRenderer, { variable: variable, value: responses[variable.code]?.valeur, onChange: (value) => onChange(variable.code, value), disabled: disabled, rosterVariables: rosterVariables }, variable.code));
212
+ }) }), visibleVariables.length === 0 && (_jsx("div", { className: "text-center py-8 text-gray-500", children: _jsx("p", { children: "Aucun champ \u00E0 afficher dans ce groupe" }) }))] }));
213
+ };
214
+ export default GroupRenderer;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Composant IdDocInput - Capture et upload de documents d'identité
3
+ * RSU v2 - Moteur de Rendu des Formulaires d'Enquête
4
+ *
5
+ * Ce composant permet de capturer ou uploader un document d'identité
6
+ * (CNI, passeport, carte électorale, etc.) avec prévisualisation.
7
+ */
8
+ import React from 'react';
9
+ import { VariableFormulaire, VariableValue } from '../types/enquete';
10
+ export interface IdDocInputProps {
11
+ variable: VariableFormulaire;
12
+ value: VariableValue;
13
+ onChange: (value: VariableValue) => void;
14
+ onBlur?: () => void;
15
+ error?: string;
16
+ disabled?: boolean;
17
+ }
18
+ declare const IdDocInput: React.FC<IdDocInputProps>;
19
+ export default IdDocInput;
20
+ //# sourceMappingURL=IdDocInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IdDocInput.d.ts","sourceRoot":"","sources":["../../src/components/IdDocInput.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAIrE,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAuBD,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAkYzC,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Composant IdDocInput - Capture et upload de documents d'identité
3
+ * RSU v2 - Moteur de Rendu des Formulaires d'Enquête
4
+ *
5
+ * Ce composant permet de capturer ou uploader un document d'identité
6
+ * (CNI, passeport, carte électorale, etc.) avec prévisualisation.
7
+ */
8
+ 'use client';
9
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
+ import React, { useState, useEffect, useRef } from 'react';
11
+ import { AlertCircle, Camera, Upload, X, FileText, CreditCard } from 'lucide-react';
12
+ // Types de documents d'identité supportés
13
+ const DOC_TYPES = [
14
+ { code: 'CNI', label: 'Carte Nationale d\'Identité' },
15
+ { code: 'PASSEPORT', label: 'Passeport' },
16
+ { code: 'CARTE_ELECTEUR', label: 'Carte d\'Électeur' },
17
+ { code: 'PERMIS', label: 'Permis de Conduire' },
18
+ { code: 'AUTRE', label: 'Autre Document' }
19
+ ];
20
+ const IdDocInput = ({ variable, value, onChange, onBlur, error, disabled }) => {
21
+ const [preview, setPreview] = useState(null);
22
+ const [captureMode, setCaptureMode] = useState('upload');
23
+ const [stream, setStream] = useState(null);
24
+ const [isCapturing, setIsCapturing] = useState(false);
25
+ const fileInputRef = useRef(null);
26
+ const videoRef = useRef(null);
27
+ const canvasRef = useRef(null);
28
+ // Parser la valeur actuelle
29
+ const currentData = React.useMemo(() => {
30
+ if (!value)
31
+ return { docType: '' };
32
+ if (typeof value === 'string') {
33
+ try {
34
+ return JSON.parse(value);
35
+ }
36
+ catch {
37
+ return { docType: '' };
38
+ }
39
+ }
40
+ if (typeof value === 'object') {
41
+ return value;
42
+ }
43
+ return { docType: '' };
44
+ }, [value]);
45
+ // Mettre à jour l'aperçu quand la valeur change
46
+ useEffect(() => {
47
+ if (currentData.file) {
48
+ const reader = new FileReader();
49
+ reader.onload = (e) => setPreview(e.target?.result);
50
+ reader.readAsDataURL(currentData.file);
51
+ }
52
+ else {
53
+ setPreview(null);
54
+ if (fileInputRef.current) {
55
+ fileInputRef.current.value = '';
56
+ }
57
+ }
58
+ }, [currentData.file]);
59
+ // Nettoyer le stream quand le composant est démonté
60
+ useEffect(() => {
61
+ return () => {
62
+ if (stream) {
63
+ stream.getTracks().forEach(track => track.stop());
64
+ }
65
+ };
66
+ }, [stream]);
67
+ // Mettre à jour les données
68
+ const updateData = (updates) => {
69
+ const newData = { ...currentData, ...updates };
70
+ onChange(JSON.stringify(newData));
71
+ };
72
+ // Gérer la sélection de fichier
73
+ const handleFileSelect = (event) => {
74
+ if (disabled)
75
+ return;
76
+ const file = event.target.files?.[0];
77
+ if (!file)
78
+ return;
79
+ processFile(file);
80
+ };
81
+ // Traiter le fichier sélectionné
82
+ const processFile = (file) => {
83
+ // Validation de la taille
84
+ const maxSize = variable.proprietes?.maxFileSize || 10 * 1024 * 1024; // 10MB par défaut
85
+ if (file.size > maxSize) {
86
+ alert(`Fichier trop volumineux. Taille maximum: ${Math.round(maxSize / 1024 / 1024)}MB`);
87
+ return;
88
+ }
89
+ // Validation du type
90
+ const acceptedTypes = variable.proprietes?.acceptedTypes || [
91
+ 'image/jpeg', 'image/png', 'image/webp',
92
+ 'application/pdf'
93
+ ];
94
+ if (!acceptedTypes.includes(file.type)) {
95
+ alert(`Type de fichier non supporté. Types acceptés: ${acceptedTypes.join(', ')}`);
96
+ return;
97
+ }
98
+ // Sauvegarder le fichier
99
+ updateData({
100
+ file,
101
+ fileName: file.name,
102
+ fileSize: file.size,
103
+ fileType: file.type,
104
+ timestamp: new Date(),
105
+ source: captureMode === 'camera' ? 'camera' : 'upload'
106
+ });
107
+ };
108
+ // Démarrer la caméra
109
+ const startCamera = async () => {
110
+ if (disabled)
111
+ return;
112
+ try {
113
+ setIsCapturing(true);
114
+ const mediaStream = await navigator.mediaDevices.getUserMedia({
115
+ video: {
116
+ facingMode: 'environment' // Caméra arrière par défaut
117
+ }
118
+ });
119
+ setStream(mediaStream);
120
+ if (videoRef.current) {
121
+ videoRef.current.srcObject = mediaStream;
122
+ }
123
+ }
124
+ catch (error) {
125
+ console.error('Erreur accès caméra:', error);
126
+ alert('Impossible d\'accéder à la caméra. Vérifiez les permissions.');
127
+ setIsCapturing(false);
128
+ }
129
+ };
130
+ // Arrêter la caméra
131
+ const stopCamera = () => {
132
+ if (stream) {
133
+ stream.getTracks().forEach(track => track.stop());
134
+ setStream(null);
135
+ }
136
+ setIsCapturing(false);
137
+ };
138
+ // Capturer la photo
139
+ const capturePhoto = () => {
140
+ if (!videoRef.current || !canvasRef.current)
141
+ return;
142
+ const video = videoRef.current;
143
+ const canvas = canvasRef.current;
144
+ const context = canvas.getContext('2d');
145
+ if (!context)
146
+ return;
147
+ // Définir les dimensions du canvas
148
+ canvas.width = video.videoWidth;
149
+ canvas.height = video.videoHeight;
150
+ // Dessiner l'image du video sur le canvas
151
+ context.drawImage(video, 0, 0);
152
+ // Convertir en blob
153
+ canvas.toBlob((blob) => {
154
+ if (blob) {
155
+ const file = new File([blob], `iddoc_${Date.now()}.jpg`, { type: 'image/jpeg' });
156
+ processFile(file);
157
+ stopCamera();
158
+ }
159
+ }, 'image/jpeg', 0.9);
160
+ };
161
+ // Supprimer le document
162
+ const clearDocument = () => {
163
+ updateData({
164
+ file: undefined,
165
+ fileName: undefined,
166
+ fileSize: undefined,
167
+ fileType: undefined,
168
+ timestamp: undefined,
169
+ source: undefined
170
+ });
171
+ if (fileInputRef.current) {
172
+ fileInputRef.current.value = '';
173
+ }
174
+ };
175
+ return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "block text-sm font-medium text-gray-700", children: "Type de document" }), _jsxs("select", { value: currentData.docType || '', onChange: (e) => updateData({ docType: e.target.value }), onBlur: onBlur, disabled: disabled, className: `w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent text-gray-900 ${error ? 'border-red-500' : 'border-gray-300'} ${disabled ? 'bg-gray-100 cursor-not-allowed text-gray-500' : 'bg-white'}`, children: [_jsx("option", { value: "", children: "S\u00E9lectionner le type..." }), DOC_TYPES.map((docType) => (_jsx("option", { value: docType.code, children: docType.label }, docType.code)))] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "block text-sm font-medium text-gray-700", children: "Num\u00E9ro du document (optionnel)" }), _jsx("input", { type: "text", value: currentData.docNumber || '', onChange: (e) => updateData({ docNumber: e.target.value }), onBlur: onBlur, placeholder: "Ex: CI-123456789", disabled: disabled, className: `w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent text-gray-900 ${error ? 'border-red-500' : 'border-gray-300'} ${disabled ? 'bg-gray-100 cursor-not-allowed text-gray-500' : 'bg-white'}` })] }), _jsxs("div", { className: "space-y-3", children: [_jsx("label", { className: "block text-sm font-medium text-gray-700", children: "Image du document" }), _jsxs("div", { className: "flex space-x-2 mb-3", children: [_jsxs("button", { type: "button", onClick: () => {
176
+ setCaptureMode('upload');
177
+ stopCamera();
178
+ }, disabled: disabled, className: `flex items-center px-3 py-2 rounded-lg text-sm font-medium transition-colors ${captureMode === 'upload'
179
+ ? 'bg-blue-600 text-white'
180
+ : 'bg-gray-200 text-gray-700 hover:bg-gray-300'} ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`, children: [_jsx(Upload, { className: "w-4 h-4 mr-2" }), "Upload"] }), _jsxs("button", { type: "button", onClick: () => {
181
+ setCaptureMode('camera');
182
+ if (!isCapturing)
183
+ startCamera();
184
+ }, disabled: disabled, className: `flex items-center px-3 py-2 rounded-lg text-sm font-medium transition-colors ${captureMode === 'camera'
185
+ ? 'bg-blue-600 text-white'
186
+ : 'bg-gray-200 text-gray-700 hover:bg-gray-300'} ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`, children: [_jsx(Camera, { className: "w-4 h-4 mr-2" }), "Cam\u00E9ra"] })] }), captureMode === 'upload' && !preview && (_jsxs("div", { className: "relative", children: [_jsx("input", { ref: fileInputRef, type: "file", accept: "image/*,application/pdf", onChange: handleFileSelect, disabled: disabled, className: "absolute inset-0 w-full h-full opacity-0 cursor-pointer" }), _jsxs("div", { className: `flex flex-col items-center justify-center p-6 border-2 border-dashed rounded-lg ${error ? 'border-red-500' : 'border-gray-300'} ${disabled ? 'bg-gray-100 cursor-not-allowed' : 'bg-white hover:border-green-500 cursor-pointer'}`, children: [_jsx(CreditCard, { className: "w-10 h-10 text-gray-400 mb-2" }), _jsx("span", { className: "text-sm text-gray-600", children: "Cliquez ou glissez-d\u00E9posez" }), _jsx("span", { className: "text-xs text-gray-400 mt-1", children: "JPG, PNG, PDF - Max 10MB" })] })] })), captureMode === 'camera' && (_jsxs("div", { className: "space-y-3", children: [isCapturing && (_jsxs("div", { className: "relative", children: [_jsx("video", { ref: videoRef, autoPlay: true, playsInline: true, className: "w-full max-w-md mx-auto rounded-lg border border-gray-300" }), _jsxs("div", { className: "flex justify-center space-x-2 mt-2", children: [_jsxs("button", { type: "button", onClick: capturePhoto, disabled: disabled, className: "flex items-center px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 focus:ring-2 focus:ring-green-500 focus:ring-offset-2 disabled:opacity-50", children: [_jsx(Camera, { className: "w-4 h-4 mr-2" }), "Capturer"] }), _jsxs("button", { type: "button", onClick: stopCamera, disabled: disabled, className: "flex items-center px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 focus:ring-2 focus:ring-red-500 focus:ring-offset-2 disabled:opacity-50", children: [_jsx(X, { className: "w-4 h-4 mr-2" }), "Arr\u00EAter"] })] })] })), !isCapturing && !preview && (_jsxs("button", { type: "button", onClick: startCamera, disabled: disabled, className: "w-full flex items-center justify-center px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50", children: [_jsx(Camera, { className: "w-5 h-5 mr-2" }), "D\u00E9marrer la cam\u00E9ra"] }))] })), _jsx("canvas", { ref: canvasRef, style: { display: 'none' } }), preview && (_jsxs("div", { className: "relative", children: [currentData.fileType?.startsWith('image/') ? (_jsx("img", { src: preview, alt: "Aper\u00E7u du document", className: "w-full max-w-md mx-auto rounded-lg shadow-md border border-gray-200" })) : (_jsxs("div", { className: "flex items-center justify-center p-6 bg-gray-100 rounded-lg", children: [_jsx(FileText, { className: "w-10 h-10 text-gray-500 mr-3" }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium text-gray-700", children: currentData.fileName }), _jsx("p", { className: "text-xs text-gray-500", children: currentData.fileSize ? `${Math.round(currentData.fileSize / 1024)} KB` : '' })] })] })), _jsx("button", { type: "button", onClick: clearDocument, disabled: disabled, className: "absolute top-2 right-2 p-1 bg-red-500 text-white rounded-full hover:bg-red-600 focus:ring-2 focus:ring-red-500 focus:ring-offset-2 disabled:opacity-50", children: _jsx(X, { className: "w-4 h-4" }) })] })), currentData.fileName && (_jsxs("div", { className: "p-2 bg-green-50 border border-green-200 rounded text-sm", children: [_jsxs("div", { className: "flex items-center text-green-800", children: [_jsx(FileText, { className: "w-4 h-4 mr-2" }), _jsx("span", { className: "font-medium", children: currentData.fileName })] }), currentData.source && (_jsxs("p", { className: "text-xs text-green-600 mt-1", children: ["Source: ", currentData.source === 'camera' ? 'Caméra' : 'Upload'] }))] }))] }), error && (_jsxs("div", { className: "flex items-center space-x-1 text-red-600 text-sm", children: [_jsx(AlertCircle, { className: "h-4 w-4" }), _jsx("span", { children: error })] }))] }));
187
+ };
188
+ export default IdDocInput;
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import type { VariableFormulaire, VariableValue, EnqueteReponse } from '../types/enquete';
3
+ import type { MenageCompletDto } from '../types/menages';
4
+ import type { EnqueteCompletDto } from '../types/enquete-service';
5
+ export interface VariableRendererProps {
6
+ variable: VariableFormulaire;
7
+ value: VariableValue;
8
+ onChange: (value: VariableValue) => void;
9
+ onBlur?: () => void;
10
+ error?: string;
11
+ disabled?: boolean;
12
+ numeroMembre?: number;
13
+ valeurMin?: number;
14
+ onFillFormFromMenage?: (menageData: MenageCompletDto) => void;
15
+ onFillFormFromEnquete?: (enqueteData: EnqueteCompletDto) => void;
16
+ formulaireVariables?: VariableFormulaire[];
17
+ rosterVariables?: Array<{
18
+ code: string;
19
+ ordre: number;
20
+ designation?: string;
21
+ valeur?: string;
22
+ }>;
23
+ allResponses?: Record<string, EnqueteReponse>;
24
+ RosterCheckInput?: React.ComponentType<VariableRendererProps>;
25
+ RosterListInput?: React.ComponentType<VariableRendererProps>;
26
+ interpolateVariableLabel?: (label: string, responses: Record<string, EnqueteReponse>, numeroMembre?: number) => string;
27
+ services?: any;
28
+ geographicComponents?: any;
29
+ }
30
+ declare const GeographicFallback: React.FC<VariableRendererProps>;
31
+ declare const getVariableRenderer: (typeCode: string, RosterCheckInput?: React.ComponentType<VariableRendererProps>, RosterListInput?: React.ComponentType<VariableRendererProps>) => React.ComponentType<VariableRendererProps>;
32
+ declare const VariableRenderer: React.FC<VariableRendererProps>;
33
+ export default VariableRenderer;
34
+ export { getVariableRenderer, GeographicFallback };
35
+ //# sourceMappingURL=VariableRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VariableRenderer.d.ts","sourceRoot":"","sources":["../../src/components/VariableRenderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAgCxC,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9D,qBAAqB,CAAC,EAAE,CAAC,WAAW,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACjE,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC3C,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChG,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAG9C,gBAAgB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAC9D,eAAe,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAC7D,wBAAwB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAGvH,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,oBAAoB,CAAC,EAAE,GAAG,CAAC;CAC5B;AAGD,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAQvD,CAAC;AAGF,QAAA,MAAM,mBAAmB,GACvB,UAAU,MAAM,EAChB,mBAAmB,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAC7D,kBAAkB,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC,KAC3D,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAgD3C,CAAC;AAGF,QAAA,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA+FrD,CAAC;AAEF,eAAe,gBAAgB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,CAAC"}