@rsuci/shared-form-components 1.0.85 → 1.0.87
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/components/form-renderer/FormRenderer.d.ts.map +1 -1
- package/dist/components/form-renderer/FormRenderer.js +16 -7
- package/dist/components/form-renderer/GroupeInstanceTabs.d.ts +2 -2
- package/dist/components/form-renderer/GroupeInstanceTabs.d.ts.map +1 -1
- package/dist/components/form-renderer/GroupeInstanceTabs.js +4 -22
- package/dist/hooks/useFormInstances.js +8 -8
- package/dist/hooks/useFormRenderer.d.ts.map +1 -1
- package/dist/hooks/useFormRenderer.js +17 -0
- package/dist/hooks/useFormTree.d.ts.map +1 -1
- package/dist/hooks/useFormTree.js +4 -2
- package/dist/lib/__tests__/date-functions.test.js +32 -0
- package/dist/lib/__tests__/groupeInstanceManager.test.d.ts +6 -0
- package/dist/lib/__tests__/groupeInstanceManager.test.d.ts.map +1 -0
- package/dist/lib/__tests__/groupeInstanceManager.test.js +454 -0
- package/dist/lib/utils/date-functions.d.ts +1 -1
- package/dist/lib/utils/date-functions.d.ts.map +1 -1
- package/dist/lib/utils/date-functions.js +32 -1
- package/dist/lib/utils/groupeInstanceManager.d.ts +15 -4
- package/dist/lib/utils/groupeInstanceManager.d.ts.map +1 -1
- package/dist/lib/utils/groupeInstanceManager.js +102 -207
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormRenderer.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/FormRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAA4D,MAAM,OAAO,CAAC;AACjF,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,cAAc,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAsBlF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,yBAAyB;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAClD,oCAAoC;IACpC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,iCAAiC;IACjC,SAAS,EAAE,qBAAqB,CAAC;IACjC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,wCAAwC;IACxC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iCAAiC;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;
|
|
1
|
+
{"version":3,"file":"FormRenderer.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/FormRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAA4D,MAAM,OAAO,CAAC;AACjF,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,cAAc,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAsBlF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,yBAAyB;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAClD,oCAAoC;IACpC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,iCAAiC;IACjC,SAAS,EAAE,qBAAqB,CAAC;IACjC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,wCAAwC;IACxC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iCAAiC;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAwyBD;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgBpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -99,7 +99,10 @@ const FormRendererInner = () => {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
});
|
|
102
|
-
|
|
102
|
+
// Différer le reset après que React ait committé les state updates
|
|
103
|
+
requestAnimationFrame(() => {
|
|
104
|
+
isApplyingAutoActions.current = false;
|
|
105
|
+
});
|
|
103
106
|
}
|
|
104
107
|
}, [responses, currentGroup, currentInstance, evaluateAutoActionsForInstance, updateResponse]);
|
|
105
108
|
// Vérifier si une variable est visible
|
|
@@ -203,16 +206,22 @@ const FormRendererInner = () => {
|
|
|
203
206
|
navigation.changeInstance(instanceIndex);
|
|
204
207
|
};
|
|
205
208
|
// Handler pour l'ajout d'instance
|
|
206
|
-
const handleInstanceAdded = (instance) => {
|
|
207
|
-
|
|
209
|
+
const handleInstanceAdded = (instance, updatedGroupe) => {
|
|
210
|
+
// Mettre à jour le groupe via l'état React (pas de mutation directe)
|
|
211
|
+
instances.setGroupesWithInstances(prev => prev.map(g => g.code === updatedGroupe.code ? updatedGroupe : g));
|
|
212
|
+
navigation.updateTotalInstances(updatedGroupe.instances?.length || 1);
|
|
208
213
|
// Naviguer vers la nouvelle instance
|
|
209
|
-
if (
|
|
210
|
-
navigation.changeInstance(
|
|
214
|
+
if (updatedGroupe.instances) {
|
|
215
|
+
navigation.changeInstance(updatedGroupe.instances.length - 1);
|
|
211
216
|
}
|
|
212
217
|
};
|
|
213
218
|
// Handler pour la suppression d'instance
|
|
214
|
-
const handleInstanceRemoved = (instanceNumber) => {
|
|
215
|
-
|
|
219
|
+
const handleInstanceRemoved = (instanceNumber, updatedGroupe, updatedResponses) => {
|
|
220
|
+
// CRITIQUE : mettre à jour les réponses via l'état React
|
|
221
|
+
context.setResponses(updatedResponses);
|
|
222
|
+
// Mettre à jour le groupe via l'état React
|
|
223
|
+
instances.setGroupesWithInstances(prev => prev.map(g => g.code === updatedGroupe.code ? updatedGroupe : g));
|
|
224
|
+
navigation.updateTotalInstances(updatedGroupe.instances?.length || 1);
|
|
216
225
|
// Revenir à la première instance
|
|
217
226
|
navigation.changeInstance(0);
|
|
218
227
|
};
|
|
@@ -9,8 +9,8 @@ export interface GroupeInstanceTabsProps {
|
|
|
9
9
|
currentInstanceIndex: number;
|
|
10
10
|
responses: Record<string, EnqueteReponse>;
|
|
11
11
|
onInstanceChange: (instanceIndex: number) => void;
|
|
12
|
-
onInstanceAdded: (instance: GroupeInstance) => void;
|
|
13
|
-
onInstanceRemoved: (instanceNumber: number) => void;
|
|
12
|
+
onInstanceAdded: (instance: GroupeInstance, updatedGroupe: GroupeFormulaire) => void;
|
|
13
|
+
onInstanceRemoved: (instanceNumber: number, updatedGroupe: GroupeFormulaire, updatedResponses: Record<string, EnqueteReponse>) => void;
|
|
14
14
|
disabled?: boolean;
|
|
15
15
|
}
|
|
16
16
|
declare const GroupeInstanceTabs: React.FC<GroupeInstanceTabsProps>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GroupeInstanceTabs.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/GroupeInstanceTabs.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIvF,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,gBAAgB,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,gBAAgB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,eAAe,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"GroupeInstanceTabs.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/GroupeInstanceTabs.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIvF,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,gBAAgB,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,gBAAgB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,eAAe,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACrF,iBAAiB,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,IAAI,CAAC;IACvI,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAuQzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -26,12 +26,6 @@ const GroupeInstanceTabs = ({ groupe, currentInstanceIndex, responses, onInstanc
|
|
|
26
26
|
useEffect(() => {
|
|
27
27
|
const newMaxInstances = GroupeInstanceManager.getMaxInstances(groupe, responses);
|
|
28
28
|
if (newMaxInstances !== maxInstances) {
|
|
29
|
-
console.log('GroupeInstanceTabs - Changement de maxInstances détecté:', {
|
|
30
|
-
groupeCode: groupe.code,
|
|
31
|
-
oldMaxInstances: maxInstances,
|
|
32
|
-
newMaxInstances,
|
|
33
|
-
codeVariable: groupe.codeVariable
|
|
34
|
-
});
|
|
35
29
|
setForceUpdate(prev => prev + 1);
|
|
36
30
|
}
|
|
37
31
|
}, [responses, groupe.codeVariable, groupe.maxInstances]);
|
|
@@ -39,18 +33,6 @@ const GroupeInstanceTabs = ({ groupe, currentInstanceIndex, responses, onInstanc
|
|
|
39
33
|
// Le nombre d'onglets affichés = Math.max(maxInstances, instances existantes)
|
|
40
34
|
const minDisplayCount = Math.max(maxInstances, groupe.instances.length);
|
|
41
35
|
const displayedInstances = groupe.instances.slice(0, minDisplayCount);
|
|
42
|
-
console.log('GroupeInstanceTabs - Debug avec protection:', {
|
|
43
|
-
groupeCode: groupe.code,
|
|
44
|
-
codeVariable: groupe.codeVariable,
|
|
45
|
-
maxInstances,
|
|
46
|
-
totalInstances: groupe.instances.length,
|
|
47
|
-
minDisplayCount,
|
|
48
|
-
displayedInstances: displayedInstances.length,
|
|
49
|
-
canAdd: canAdd.canProceed,
|
|
50
|
-
canRemove: canRemove.canProceed,
|
|
51
|
-
canAddMessage: canAdd.constraints[0]?.message,
|
|
52
|
-
canRemoveMessage: canRemove.constraints[0]?.message
|
|
53
|
-
});
|
|
54
36
|
// Fonction pour déterminer l'état d'une instance
|
|
55
37
|
const getInstanceState = (instance) => {
|
|
56
38
|
const responseCount = Object.keys(instance.reponses).length;
|
|
@@ -109,8 +91,8 @@ const GroupeInstanceTabs = ({ groupe, currentInstanceIndex, responses, onInstanc
|
|
|
109
91
|
setError(null);
|
|
110
92
|
try {
|
|
111
93
|
const result = GroupeInstanceManager.addInstance(groupe, responses);
|
|
112
|
-
if (result.success && result.instance) {
|
|
113
|
-
onInstanceAdded(result.instance);
|
|
94
|
+
if (result.success && result.instance && result.updatedGroupe) {
|
|
95
|
+
onInstanceAdded(result.instance, result.updatedGroupe);
|
|
114
96
|
}
|
|
115
97
|
else {
|
|
116
98
|
setError(result.error || 'Erreur lors de l\'ajout de l\'instance');
|
|
@@ -143,8 +125,8 @@ const GroupeInstanceTabs = ({ groupe, currentInstanceIndex, responses, onInstanc
|
|
|
143
125
|
return;
|
|
144
126
|
}
|
|
145
127
|
const result = GroupeInstanceManager.removeInstance(groupe, currentInstance.numeroInstance, responses);
|
|
146
|
-
if (result.success) {
|
|
147
|
-
onInstanceRemoved(currentInstance.numeroInstance);
|
|
128
|
+
if (result.success && result.updatedGroupe && result.updatedResponses) {
|
|
129
|
+
onInstanceRemoved(currentInstance.numeroInstance, result.updatedGroupe, result.updatedResponses);
|
|
148
130
|
}
|
|
149
131
|
else {
|
|
150
132
|
setError(result.error || 'Erreur lors de la suppression de l\'instance');
|
|
@@ -81,16 +81,16 @@ export function useFormInstances(initialGroupes, initialResponses, options = {})
|
|
|
81
81
|
*/
|
|
82
82
|
const addInstance = useCallback((groupe, responses) => {
|
|
83
83
|
const result = GroupeInstanceManager.addInstance(groupe, responses);
|
|
84
|
-
if (result.success && result.instance) {
|
|
84
|
+
if (result.success && result.instance && result.updatedGroupe) {
|
|
85
85
|
log('Instance ajoutée:', {
|
|
86
86
|
groupeCode: groupe.code,
|
|
87
87
|
instanceNumber: result.instance.numeroInstance
|
|
88
88
|
});
|
|
89
|
-
// Mettre à jour les groupes
|
|
89
|
+
// Mettre à jour les groupes avec le nouveau groupe immutable
|
|
90
90
|
setGroupesWithInstances(prev => {
|
|
91
91
|
const updated = prev.map(g => {
|
|
92
|
-
if (g.code ===
|
|
93
|
-
return
|
|
92
|
+
if (g.code === result.updatedGroupe.code) {
|
|
93
|
+
return result.updatedGroupe;
|
|
94
94
|
}
|
|
95
95
|
return g;
|
|
96
96
|
});
|
|
@@ -110,16 +110,16 @@ export function useFormInstances(initialGroupes, initialResponses, options = {})
|
|
|
110
110
|
*/
|
|
111
111
|
const removeInstance = useCallback((groupe, instanceNumber, responses) => {
|
|
112
112
|
const result = GroupeInstanceManager.removeInstance(groupe, instanceNumber, responses);
|
|
113
|
-
if (result.success) {
|
|
113
|
+
if (result.success && result.updatedGroupe) {
|
|
114
114
|
log('Instance supprimée:', {
|
|
115
115
|
groupeCode: groupe.code,
|
|
116
116
|
instanceNumber
|
|
117
117
|
});
|
|
118
|
-
// Mettre à jour les groupes
|
|
118
|
+
// Mettre à jour les groupes avec le nouveau groupe immutable
|
|
119
119
|
setGroupesWithInstances(prev => {
|
|
120
120
|
const updated = prev.map(g => {
|
|
121
|
-
if (g.code ===
|
|
122
|
-
return
|
|
121
|
+
if (g.code === result.updatedGroupe.code) {
|
|
122
|
+
return result.updatedGroupe;
|
|
123
123
|
}
|
|
124
124
|
return g;
|
|
125
125
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormRenderer.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormRenderer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAqB,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAqB,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAoB,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"useFormRenderer.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormRenderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ import { useState, useCallback, useEffect, useMemo } from 'react';
|
|
|
7
7
|
import { useFormNavigation } from './useFormNavigation';
|
|
8
8
|
import { useFormValidation } from './useFormValidation';
|
|
9
9
|
import { useFormInstances } from './useFormInstances';
|
|
10
|
+
import { GroupeInstanceManager } from '../lib/utils/groupeInstanceManager';
|
|
10
11
|
/**
|
|
11
12
|
* Hook principal pour gérer un formulaire d'enquête
|
|
12
13
|
*
|
|
@@ -94,6 +95,20 @@ export function useFormRenderer(formulaire, enquete, options = { config: { mode:
|
|
|
94
95
|
// === Mise à jour des réponses ===
|
|
95
96
|
const updateResponse = useCallback((variableCode, value, variable, numeroMembre) => {
|
|
96
97
|
const responseKey = getResponseKey(variableCode, numeroMembre);
|
|
98
|
+
// Validation de la variable de contrôle : empêcher la réduction en-dessous des instances existantes
|
|
99
|
+
if (isControlVariable(variable) && value !== null && value !== '') {
|
|
100
|
+
const numericValue = typeof value === 'number' ? value : parseInt(String(value), 10);
|
|
101
|
+
if (!isNaN(numericValue)) {
|
|
102
|
+
const groupesMultiples = (instances.groupesWithInstances.length > 0
|
|
103
|
+
? instances.groupesWithInstances
|
|
104
|
+
: formulaire?.groupes || []).filter(g => g.estMultiple);
|
|
105
|
+
const validation = GroupeInstanceManager.canModifyControlVariable(variableCode, numericValue, groupesMultiples, responses);
|
|
106
|
+
if (!validation.canProceed) {
|
|
107
|
+
console.warn('[FormRenderer] Variable de contrôle rejetée:', validation.constraints[0]?.message);
|
|
108
|
+
return; // Rejeter le changement - l'input revient à la valeur précédente
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
97
112
|
const newResponse = {
|
|
98
113
|
variableId: variable.id,
|
|
99
114
|
variableCode: variableCode,
|
|
@@ -129,9 +144,11 @@ export function useFormRenderer(formulaire, enquete, options = { config: { mode:
|
|
|
129
144
|
setHasUnsavedChanges(true);
|
|
130
145
|
}, [
|
|
131
146
|
getResponseKey,
|
|
147
|
+
isControlVariable,
|
|
132
148
|
currentGroup,
|
|
133
149
|
currentInstance,
|
|
134
150
|
instances,
|
|
151
|
+
formulaire?.groupes,
|
|
135
152
|
responses,
|
|
136
153
|
onResponsesChange
|
|
137
154
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormTree.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormTree.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACvG,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE7F,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,kCAAkC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kEAAkE;IAClE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,2BAA2B;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IAEnB,kDAAkD;IAClD,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,kBAAkB,EAAE,CAAC;IAElE,mGAAmG;IACnG,8BAA8B,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,kBAAkB,EAAE,CAAC;IAErG,8DAA8D;IAC9D,sBAAsB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC;IAE5D,gGAAgG;IAChG,iCAAiC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC;IAE/F,+CAA+C;IAC/C,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAE9E,wEAAwE;IACxE,wBAAwB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAEjH,uEAAuE;IACvE,yBAAyB,EAAE,MAAM,MAAM,EAAE,CAAC;IAE1C,qCAAqC;IACrC,gBAAgB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC;IAE1E,kCAAkC;IAClC,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,cAAc,GAAG,SAAS,CAAC;IAElE,0CAA0C;IAC1C,UAAU,EAAE,SAAS,EAAE,CAAC;IAExB,6BAA6B;IAC7B,WAAW,EAAE,SAAS,EAAE,CAAC;IAEzB,6DAA6D;IAC7D,yBAAyB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;IAEvF,sDAAsD;IACtD,aAAa,EAAE,MAAM,IAAI,CAAC;IAE1B,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IAEpB,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAErD,+EAA+E;IAC/E,8BAA8B,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CAC9G;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EACzC,OAAO,GAAE,kBAAuB,GAC/B,iBAAiB,
|
|
1
|
+
{"version":3,"file":"useFormTree.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormTree.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACvG,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE7F,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,kCAAkC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kEAAkE;IAClE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,2BAA2B;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IAEnB,kDAAkD;IAClD,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,kBAAkB,EAAE,CAAC;IAElE,mGAAmG;IACnG,8BAA8B,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,kBAAkB,EAAE,CAAC;IAErG,8DAA8D;IAC9D,sBAAsB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC;IAE5D,gGAAgG;IAChG,iCAAiC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC;IAE/F,+CAA+C;IAC/C,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAE9E,wEAAwE;IACxE,wBAAwB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAEjH,uEAAuE;IACvE,yBAAyB,EAAE,MAAM,MAAM,EAAE,CAAC;IAE1C,qCAAqC;IACrC,gBAAgB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC;IAE1E,kCAAkC;IAClC,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,cAAc,GAAG,SAAS,CAAC;IAElE,0CAA0C;IAC1C,UAAU,EAAE,SAAS,EAAE,CAAC;IAExB,6BAA6B;IAC7B,WAAW,EAAE,SAAS,EAAE,CAAC;IAEzB,6DAA6D;IAC7D,yBAAyB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;IAEvF,sDAAsD;IACtD,aAAa,EAAE,MAAM,IAAI,CAAC;IAE1B,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IAEpB,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAErD,+EAA+E;IAC/E,8BAA8B,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CAC9G;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EACzC,OAAO,GAAE,kBAAuB,GAC/B,iBAAiB,CA2KnB;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -102,8 +102,10 @@ export function useFormTree(groupes, responses, options = {}) {
|
|
|
102
102
|
setUpdateCount(c => c + 1);
|
|
103
103
|
}, [formTree]);
|
|
104
104
|
// Méthodes pour les autoactions
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
// Note: pas de dépendance sur updateCount car formTree est une instance mutable
|
|
106
|
+
// dont l'état interne est toujours à jour. Ces callbacks sont appelés impérativement.
|
|
107
|
+
const executeAutoActions = useCallback(() => formTree.executeAutoActions(), [formTree]);
|
|
108
|
+
const evaluateAutoActionsForInstance = useCallback((groupeCode, instanceNumber) => formTree.evaluateAutoActionsForInstance(groupeCode, instanceNumber), [formTree]);
|
|
107
109
|
// Valeurs dérivées
|
|
108
110
|
const jumpErrors = useMemo(() => formTree.getJumpErrors(), [formTree, updateCount]);
|
|
109
111
|
const activeJumps = useMemo(() => formTree.getActiveJumps(), [formTree, updateCount]);
|
|
@@ -166,6 +166,38 @@ describe('date-functions', () => {
|
|
|
166
166
|
it('devrait retourner null pour une date invalide', () => {
|
|
167
167
|
expect(parseDateString('invalid')).toBe(null);
|
|
168
168
|
});
|
|
169
|
+
it('devrait parser une date DD/MM/YYYY', () => {
|
|
170
|
+
const result = parseDateString('13/05/2006');
|
|
171
|
+
expect(result).not.toBe(null);
|
|
172
|
+
expect(result.getDate()).toBe(13);
|
|
173
|
+
expect(result.getMonth()).toBe(4); // 0-indexé
|
|
174
|
+
expect(result.getFullYear()).toBe(2006);
|
|
175
|
+
});
|
|
176
|
+
it('devrait parser une date D/M/YYYY (chiffres simples)', () => {
|
|
177
|
+
const result = parseDateString('1/5/2006');
|
|
178
|
+
expect(result).not.toBe(null);
|
|
179
|
+
expect(result.getDate()).toBe(1);
|
|
180
|
+
expect(result.getMonth()).toBe(4);
|
|
181
|
+
expect(result.getFullYear()).toBe(2006);
|
|
182
|
+
});
|
|
183
|
+
it('devrait rejeter un mois > 12 en DD/MM/YYYY', () => {
|
|
184
|
+
expect(parseDateString('13/13/2006')).toBe(null);
|
|
185
|
+
});
|
|
186
|
+
it('devrait rejeter un jour invalide (31 février)', () => {
|
|
187
|
+
expect(parseDateString('31/02/2006')).toBe(null);
|
|
188
|
+
});
|
|
189
|
+
it('devrait parser DD/MM/YYYY HH:mm', () => {
|
|
190
|
+
const result = parseDateString('13/05/2006 14:30');
|
|
191
|
+
expect(result).not.toBe(null);
|
|
192
|
+
expect(result.getDate()).toBe(13);
|
|
193
|
+
expect(result.getMonth()).toBe(4);
|
|
194
|
+
expect(result.getFullYear()).toBe(2006);
|
|
195
|
+
expect(result.getHours()).toBe(14);
|
|
196
|
+
expect(result.getMinutes()).toBe(30);
|
|
197
|
+
});
|
|
198
|
+
it('devrait rejeter DD/MM/YYYY HH:mm avec heure invalide', () => {
|
|
199
|
+
expect(parseDateString('13/05/2006 25:00')).toBe(null);
|
|
200
|
+
});
|
|
169
201
|
});
|
|
170
202
|
describe('isValidDateUnit', () => {
|
|
171
203
|
it('devrait retourner true pour "d"', () => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groupeInstanceManager.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/groupeInstanceManager.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|