@rsuci/shared-form-components 1.0.64 → 1.0.66
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/VariableRenderer.d.ts +1 -0
- package/dist/components/VariableRenderer.d.ts.map +1 -1
- package/dist/components/VariableRenderer.js +10 -3
- package/dist/components/form-renderer/FormRenderer.d.ts.map +1 -1
- package/dist/components/form-renderer/FormRenderer.js +57 -3
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +7 -0
- package/dist/components/inputs/CCInput.d.ts +23 -0
- package/dist/components/inputs/CCInput.d.ts.map +1 -0
- package/dist/components/inputs/CCInput.js +90 -0
- package/dist/components/inputs/CMUInput.d.ts +22 -0
- package/dist/components/inputs/CMUInput.d.ts.map +1 -0
- package/dist/components/inputs/CMUInput.js +45 -0
- package/dist/components/inputs/CNIInput.d.ts +24 -0
- package/dist/components/inputs/CNIInput.d.ts.map +1 -0
- package/dist/components/inputs/CNIInput.js +158 -0
- package/dist/components/inputs/ExtraitInput.d.ts +24 -0
- package/dist/components/inputs/ExtraitInput.d.ts.map +1 -0
- package/dist/components/inputs/ExtraitInput.js +115 -0
- package/dist/components/inputs/NNIInput.d.ts +22 -0
- package/dist/components/inputs/NNIInput.d.ts.map +1 -0
- package/dist/components/inputs/NNIInput.js +53 -0
- package/dist/components/inputs/PasseportInput.d.ts +23 -0
- package/dist/components/inputs/PasseportInput.d.ts.map +1 -0
- package/dist/components/inputs/PasseportInput.js +85 -0
- package/dist/hooks/useConditionValidation.d.ts +60 -0
- package/dist/hooks/useConditionValidation.d.ts.map +1 -0
- package/dist/hooks/useConditionValidation.js +209 -0
- package/dist/lib/condition-engine.d.ts +25 -1
- package/dist/lib/condition-engine.d.ts.map +1 -1
- package/dist/lib/condition-engine.js +138 -0
- package/dist/types/enquete.d.ts +14 -1
- package/dist/types/enquete.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composant ExtraitInput - Saisie d'Extrait de Naissance
|
|
3
|
+
* RSU v2 - Moteur de Rendu des Formulaires d'Enquête
|
|
4
|
+
*
|
|
5
|
+
* Format composé : numéro (3 chiffres) + date d'établissement + année registre (4 chiffres)
|
|
6
|
+
* Exemple affiché : "556 du 12/12/2020 du registre 2020"
|
|
7
|
+
* Stockage : JSON { numero, dateEtablissement, anneeRegistre }
|
|
8
|
+
*/
|
|
9
|
+
'use client';
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { useState, useCallback, useEffect } from 'react';
|
|
12
|
+
import { applyComponentStyle } from '../../utils/styleUtils';
|
|
13
|
+
import { isComponentReadonly, readonlyClasses } from '../../utils/componentStateUtils';
|
|
14
|
+
const parseExtraitValue = (value) => {
|
|
15
|
+
if (!value) {
|
|
16
|
+
return { numero: '', dateEtablissement: '', anneeRegistre: '' };
|
|
17
|
+
}
|
|
18
|
+
if (typeof value === 'string') {
|
|
19
|
+
try {
|
|
20
|
+
const parsed = JSON.parse(value);
|
|
21
|
+
return {
|
|
22
|
+
numero: parsed.numero || '',
|
|
23
|
+
dateEtablissement: parsed.dateEtablissement || '',
|
|
24
|
+
anneeRegistre: parsed.anneeRegistre || ''
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return { numero: '', dateEtablissement: '', anneeRegistre: '' };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === 'object' && value !== null) {
|
|
32
|
+
const obj = value;
|
|
33
|
+
return {
|
|
34
|
+
numero: obj.numero || '',
|
|
35
|
+
dateEtablissement: obj.dateEtablissement || '',
|
|
36
|
+
anneeRegistre: obj.anneeRegistre || ''
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return { numero: '', dateEtablissement: '', anneeRegistre: '' };
|
|
40
|
+
};
|
|
41
|
+
const formatDisplayValue = (data) => {
|
|
42
|
+
if (!data.numero && !data.dateEtablissement && !data.anneeRegistre) {
|
|
43
|
+
return '';
|
|
44
|
+
}
|
|
45
|
+
const parts = [];
|
|
46
|
+
if (data.numero) {
|
|
47
|
+
parts.push(data.numero);
|
|
48
|
+
}
|
|
49
|
+
if (data.dateEtablissement) {
|
|
50
|
+
const date = new Date(data.dateEtablissement);
|
|
51
|
+
if (!isNaN(date.getTime())) {
|
|
52
|
+
const dateStr = date.toLocaleDateString('fr-FR');
|
|
53
|
+
parts.push(`du ${dateStr}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (data.anneeRegistre) {
|
|
57
|
+
parts.push(`du registre ${data.anneeRegistre}`);
|
|
58
|
+
}
|
|
59
|
+
return parts.join(' ');
|
|
60
|
+
};
|
|
61
|
+
const ExtraitInput = ({ variable, value, onChange, onBlur, error, disabled, isConsultationMode = false }) => {
|
|
62
|
+
const [data, setData] = useState(() => parseExtraitValue(value));
|
|
63
|
+
const [localError, setLocalError] = useState(null);
|
|
64
|
+
const { textStyle, containerStyle } = applyComponentStyle(variable.componentStyle);
|
|
65
|
+
const isReadonly = isComponentReadonly(variable, isConsultationMode);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
setData(parseExtraitValue(value));
|
|
68
|
+
}, [value]);
|
|
69
|
+
const updateValue = useCallback((newData) => {
|
|
70
|
+
setData(newData);
|
|
71
|
+
onChange(JSON.stringify(newData));
|
|
72
|
+
}, [onChange]);
|
|
73
|
+
const handleNumeroChange = useCallback((e) => {
|
|
74
|
+
const digitsOnly = e.target.value.replace(/\D/g, '').slice(0, 3);
|
|
75
|
+
updateValue({ ...data, numero: digitsOnly });
|
|
76
|
+
}, [data, updateValue]);
|
|
77
|
+
const handleDateChange = useCallback((e) => {
|
|
78
|
+
updateValue({ ...data, dateEtablissement: e.target.value });
|
|
79
|
+
}, [data, updateValue]);
|
|
80
|
+
const handleAnneeChange = useCallback((e) => {
|
|
81
|
+
const digitsOnly = e.target.value.replace(/\D/g, '').slice(0, 4);
|
|
82
|
+
updateValue({ ...data, anneeRegistre: digitsOnly });
|
|
83
|
+
}, [data, updateValue]);
|
|
84
|
+
const handleBlur = useCallback(() => {
|
|
85
|
+
const errors = [];
|
|
86
|
+
if (data.numero && data.numero.length !== 3) {
|
|
87
|
+
errors.push('Le numéro doit contenir 3 chiffres');
|
|
88
|
+
}
|
|
89
|
+
if (data.anneeRegistre && data.anneeRegistre.length !== 4) {
|
|
90
|
+
errors.push("L'année du registre doit contenir 4 chiffres");
|
|
91
|
+
}
|
|
92
|
+
if (data.anneeRegistre && data.dateEtablissement) {
|
|
93
|
+
const dateYear = new Date(data.dateEtablissement).getFullYear();
|
|
94
|
+
const registreYear = parseInt(data.anneeRegistre, 10);
|
|
95
|
+
if (dateYear > registreYear) {
|
|
96
|
+
errors.push("L'année du registre ne peut pas être antérieure à la date d'établissement");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
setLocalError(errors.length > 0 ? errors.join('. ') : null);
|
|
100
|
+
onBlur?.();
|
|
101
|
+
}, [data, onBlur]);
|
|
102
|
+
const getInputClasses = (hasError = false) => {
|
|
103
|
+
const baseClasses = 'px-3 py-2 border rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent text-gray-900';
|
|
104
|
+
const errorClasses = hasError ? 'border-red-500' : 'border-gray-300';
|
|
105
|
+
if (disabled)
|
|
106
|
+
return `${baseClasses} ${errorClasses} bg-gray-100 cursor-not-allowed text-gray-500`;
|
|
107
|
+
if (isReadonly)
|
|
108
|
+
return `${baseClasses} ${errorClasses} ${readonlyClasses.readonly}`;
|
|
109
|
+
return `${baseClasses} ${errorClasses} bg-white`;
|
|
110
|
+
};
|
|
111
|
+
const displayError = error || localError;
|
|
112
|
+
const formattedValue = formatDisplayValue(data);
|
|
113
|
+
return (_jsxs("div", { style: containerStyle, className: "space-y-3", children: [_jsxs("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-3", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: "Num\u00E9ro" }), _jsx("input", { type: "text", inputMode: "numeric", value: data.numero, onChange: handleNumeroChange, onBlur: handleBlur, placeholder: disabled ? '' : '556', disabled: disabled, readOnly: isReadonly, style: textStyle, className: `${getInputClasses()} w-full font-mono`, maxLength: 3, autoComplete: "off" })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: "Date d'\u00E9tablissement" }), _jsx("input", { type: "date", value: data.dateEtablissement, onChange: handleDateChange, onBlur: handleBlur, disabled: disabled, readOnly: isReadonly, style: textStyle, className: `${getInputClasses()} w-full`, max: new Date().toISOString().split('T')[0] })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: "Ann\u00E9e du registre" }), _jsx("input", { type: "text", inputMode: "numeric", value: data.anneeRegistre, onChange: handleAnneeChange, onBlur: handleBlur, placeholder: disabled ? '' : '2020', disabled: disabled, readOnly: isReadonly, style: textStyle, className: `${getInputClasses()} w-full font-mono`, maxLength: 4, autoComplete: "off" })] })] }), formattedValue && (_jsx("div", { className: "p-2 bg-blue-50 border border-blue-200 rounded-lg", children: _jsxs("p", { className: "text-sm text-blue-800", children: [_jsx("span", { className: "font-medium", children: "Valeur :" }), " ", formattedValue] }) })), displayError && (_jsx("p", { className: "text-sm text-red-500", children: displayError }))] }));
|
|
114
|
+
};
|
|
115
|
+
export default ExtraitInput;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composant NNIInput - Saisie de Numéro National d'Identification
|
|
3
|
+
* RSU v2 - Moteur de Rendu des Formulaires d'Enquête
|
|
4
|
+
*
|
|
5
|
+
* Format : exactement 11 chiffres
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { VariableFormulaire, VariableValue } from '../../types/enquete';
|
|
9
|
+
export interface NNIInputProps {
|
|
10
|
+
variable: VariableFormulaire & {
|
|
11
|
+
typeCode: 'NNI';
|
|
12
|
+
};
|
|
13
|
+
value: VariableValue;
|
|
14
|
+
onChange: (value: VariableValue) => void;
|
|
15
|
+
onBlur?: () => void;
|
|
16
|
+
error?: string;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
isConsultationMode?: boolean;
|
|
19
|
+
}
|
|
20
|
+
declare const NNIInput: React.FC<NNIInputProps>;
|
|
21
|
+
export default NNIInput;
|
|
22
|
+
//# sourceMappingURL=NNIInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NNIInput.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/NNIInput.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAgC,MAAM,OAAO,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIxE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,kBAAkB,GAAG;QAAE,QAAQ,EAAE,KAAK,CAAA;KAAE,CAAC;IACnD,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,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAID,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA0ErC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composant NNIInput - Saisie de Numéro National d'Identification
|
|
3
|
+
* RSU v2 - Moteur de Rendu des Formulaires d'Enquête
|
|
4
|
+
*
|
|
5
|
+
* Format : exactement 11 chiffres
|
|
6
|
+
*/
|
|
7
|
+
'use client';
|
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { useState, useCallback } from 'react';
|
|
10
|
+
import { applyComponentStyle } from '../../utils/styleUtils';
|
|
11
|
+
import { isComponentReadonly, readonlyClasses } from '../../utils/componentStateUtils';
|
|
12
|
+
const NNI_REGEX = /^\d{11}$/;
|
|
13
|
+
const NNIInput = ({ variable, value, onChange, onBlur, error, disabled, isConsultationMode = false }) => {
|
|
14
|
+
const stringValue = value || '';
|
|
15
|
+
const [localError, setLocalError] = useState(null);
|
|
16
|
+
const { textStyle, containerStyle } = applyComponentStyle(variable.componentStyle);
|
|
17
|
+
const isReadonly = isComponentReadonly(variable, isConsultationMode);
|
|
18
|
+
const handleChange = useCallback((e) => {
|
|
19
|
+
const rawValue = e.target.value;
|
|
20
|
+
const digitsOnly = rawValue.replace(/\D/g, '').slice(0, 11);
|
|
21
|
+
onChange(digitsOnly);
|
|
22
|
+
if (digitsOnly.length > 0 && digitsOnly.length < 11) {
|
|
23
|
+
setLocalError(null);
|
|
24
|
+
}
|
|
25
|
+
else if (digitsOnly.length === 11) {
|
|
26
|
+
setLocalError(null);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
setLocalError(null);
|
|
30
|
+
}
|
|
31
|
+
}, [onChange]);
|
|
32
|
+
const handleBlur = useCallback(() => {
|
|
33
|
+
if (stringValue && stringValue.length > 0 && !NNI_REGEX.test(stringValue)) {
|
|
34
|
+
setLocalError(`Le NNI doit contenir exactement 11 chiffres (${stringValue.length}/11)`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
setLocalError(null);
|
|
38
|
+
}
|
|
39
|
+
onBlur?.();
|
|
40
|
+
}, [stringValue, onBlur]);
|
|
41
|
+
const getInputClasses = () => {
|
|
42
|
+
const baseClasses = 'w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent text-gray-900 font-mono';
|
|
43
|
+
const errorClasses = displayError ? 'border-red-500' : 'border-gray-300';
|
|
44
|
+
if (disabled)
|
|
45
|
+
return `${baseClasses} ${errorClasses} bg-gray-100 cursor-not-allowed text-gray-500`;
|
|
46
|
+
if (isReadonly)
|
|
47
|
+
return `${baseClasses} ${errorClasses} ${readonlyClasses.readonly}`;
|
|
48
|
+
return `${baseClasses} ${errorClasses} bg-white`;
|
|
49
|
+
};
|
|
50
|
+
const displayError = error || localError;
|
|
51
|
+
return (_jsxs("div", { style: containerStyle, children: [_jsx("input", { type: "text", inputMode: "numeric", value: stringValue, onChange: handleChange, onBlur: handleBlur, placeholder: disabled ? '' : '12345678901', disabled: disabled, readOnly: isReadonly, style: textStyle, className: getInputClasses(), maxLength: 11, autoComplete: "off", spellCheck: false }), stringValue && !displayError && (_jsxs("p", { className: "mt-1 text-xs text-gray-500", children: [stringValue.length, "/11 chiffres"] })), displayError && (_jsx("p", { className: "mt-1 text-sm text-red-500", children: displayError }))] }));
|
|
52
|
+
};
|
|
53
|
+
export default NNIInput;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composant PasseportInput - Saisie de Passeport Ivoirien
|
|
3
|
+
* RSU v2 - Moteur de Rendu des Formulaires d'Enquête
|
|
4
|
+
*
|
|
5
|
+
* Format : CCLLCCCCC (2 chiffres + 2 lettres majuscules + 5 chiffres)
|
|
6
|
+
* Exemple : 17AH48765
|
|
7
|
+
*/
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import { VariableFormulaire, VariableValue } from '../../types/enquete';
|
|
10
|
+
export interface PasseportInputProps {
|
|
11
|
+
variable: VariableFormulaire & {
|
|
12
|
+
typeCode: 'PASSEPORT';
|
|
13
|
+
};
|
|
14
|
+
value: VariableValue;
|
|
15
|
+
onChange: (value: VariableValue) => void;
|
|
16
|
+
onBlur?: () => void;
|
|
17
|
+
error?: string;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
isConsultationMode?: boolean;
|
|
20
|
+
}
|
|
21
|
+
declare const PasseportInput: React.FC<PasseportInputProps>;
|
|
22
|
+
export default PasseportInput;
|
|
23
|
+
//# sourceMappingURL=PasseportInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasseportInput.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/PasseportInput.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAgC,MAAM,OAAO,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIxE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,kBAAkB,GAAG;QAAE,QAAQ,EAAE,WAAW,CAAA;KAAE,CAAC;IACzD,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,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAwBD,QAAA,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAiFjD,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composant PasseportInput - Saisie de Passeport Ivoirien
|
|
3
|
+
* RSU v2 - Moteur de Rendu des Formulaires d'Enquête
|
|
4
|
+
*
|
|
5
|
+
* Format : CCLLCCCCC (2 chiffres + 2 lettres majuscules + 5 chiffres)
|
|
6
|
+
* Exemple : 17AH48765
|
|
7
|
+
*/
|
|
8
|
+
'use client';
|
|
9
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { useState, useCallback } from 'react';
|
|
11
|
+
import { applyComponentStyle } from '../../utils/styleUtils';
|
|
12
|
+
import { isComponentReadonly, readonlyClasses } from '../../utils/componentStateUtils';
|
|
13
|
+
const PASSEPORT_REGEX = /^\d{2}[A-Z]{2}\d{5}$/;
|
|
14
|
+
const applyPasseportMask = (value) => {
|
|
15
|
+
const upper = value.toUpperCase();
|
|
16
|
+
const result = [];
|
|
17
|
+
for (let i = 0; i < upper.length && result.length < 9; i++) {
|
|
18
|
+
const char = upper[i];
|
|
19
|
+
const pos = result.length;
|
|
20
|
+
if (pos < 2) {
|
|
21
|
+
if (/\d/.test(char))
|
|
22
|
+
result.push(char);
|
|
23
|
+
}
|
|
24
|
+
else if (pos < 4) {
|
|
25
|
+
if (/[A-Z]/.test(char))
|
|
26
|
+
result.push(char);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
if (/\d/.test(char))
|
|
30
|
+
result.push(char);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return result.join('');
|
|
34
|
+
};
|
|
35
|
+
const PasseportInput = ({ variable, value, onChange, onBlur, error, disabled, isConsultationMode = false }) => {
|
|
36
|
+
const stringValue = value || '';
|
|
37
|
+
const [localError, setLocalError] = useState(null);
|
|
38
|
+
const { textStyle, containerStyle } = applyComponentStyle(variable.componentStyle);
|
|
39
|
+
const isReadonly = isComponentReadonly(variable, isConsultationMode);
|
|
40
|
+
const handleChange = useCallback((e) => {
|
|
41
|
+
const rawValue = e.target.value;
|
|
42
|
+
const maskedValue = applyPasseportMask(rawValue);
|
|
43
|
+
onChange(maskedValue);
|
|
44
|
+
setLocalError(null);
|
|
45
|
+
}, [onChange]);
|
|
46
|
+
const handleBlur = useCallback(() => {
|
|
47
|
+
if (stringValue && stringValue.length > 0 && !PASSEPORT_REGEX.test(stringValue)) {
|
|
48
|
+
if (stringValue.length < 9) {
|
|
49
|
+
setLocalError(`Format incomplet (${stringValue.length}/9 caractères)`);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
setLocalError('Format attendu : 2 chiffres + 2 lettres + 5 chiffres (ex: 17AH48765)');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
setLocalError(null);
|
|
57
|
+
}
|
|
58
|
+
onBlur?.();
|
|
59
|
+
}, [stringValue, onBlur]);
|
|
60
|
+
const getInputClasses = () => {
|
|
61
|
+
const baseClasses = 'w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent text-gray-900 font-mono uppercase';
|
|
62
|
+
const errorClasses = displayError ? 'border-red-500' : 'border-gray-300';
|
|
63
|
+
if (disabled)
|
|
64
|
+
return `${baseClasses} ${errorClasses} bg-gray-100 cursor-not-allowed text-gray-500`;
|
|
65
|
+
if (isReadonly)
|
|
66
|
+
return `${baseClasses} ${errorClasses} ${readonlyClasses.readonly}`;
|
|
67
|
+
return `${baseClasses} ${errorClasses} bg-white`;
|
|
68
|
+
};
|
|
69
|
+
const displayError = error || localError;
|
|
70
|
+
const getHelperText = () => {
|
|
71
|
+
if (!stringValue)
|
|
72
|
+
return null;
|
|
73
|
+
const len = stringValue.length;
|
|
74
|
+
if (len < 2)
|
|
75
|
+
return 'Saisissez 2 chiffres';
|
|
76
|
+
if (len < 4)
|
|
77
|
+
return 'Saisissez 2 lettres';
|
|
78
|
+
if (len < 9)
|
|
79
|
+
return 'Saisissez 5 chiffres';
|
|
80
|
+
return null;
|
|
81
|
+
};
|
|
82
|
+
const helperText = getHelperText();
|
|
83
|
+
return (_jsxs("div", { style: containerStyle, children: [_jsx("input", { type: "text", value: stringValue, onChange: handleChange, onBlur: handleBlur, placeholder: disabled ? '' : '17AH48765', disabled: disabled, readOnly: isReadonly, style: textStyle, className: getInputClasses(), maxLength: 9, autoComplete: "off", spellCheck: false }), helperText && !displayError && (_jsx("p", { className: "mt-1 text-xs text-gray-500", children: helperText })), displayError && (_jsx("p", { className: "mt-1 text-sm text-red-500", children: displayError }))] }));
|
|
84
|
+
};
|
|
85
|
+
export default PasseportInput;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook de validation des conditions (ConditionEval) pour les formulaires d'enquête
|
|
3
|
+
* Gère l'évaluation des validations personnalisées via ConditionEval()
|
|
4
|
+
* RSU v2 - Package Partagé
|
|
5
|
+
*/
|
|
6
|
+
import { ConditionEngine } from '../lib/condition-engine';
|
|
7
|
+
import { EnqueteReponse, VariableFormulaire, GroupeFormulaire, ConditionValidationError } from '../types/enquete';
|
|
8
|
+
export interface UseConditionValidationOptions {
|
|
9
|
+
/** Délai de debounce pour l'évaluation (ms) */
|
|
10
|
+
debounceMs?: number;
|
|
11
|
+
/** Évaluer automatiquement sur changement de réponse */
|
|
12
|
+
evaluateOnChange?: boolean;
|
|
13
|
+
/** Mode debug (affiche les logs) */
|
|
14
|
+
debug?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface UseConditionValidationResult {
|
|
17
|
+
/** Map des erreurs de validation par variable (clé: variableCode ou variableCode_numeroMembre) */
|
|
18
|
+
validationErrors: Map<string, ConditionValidationError>;
|
|
19
|
+
/** Valide une variable individuelle et retourne l'erreur ou null */
|
|
20
|
+
validateVariable: (variable: VariableFormulaire, numeroMembre?: number) => ConditionValidationError | null;
|
|
21
|
+
/** Valide toutes les variables d'un groupe et retourne les erreurs */
|
|
22
|
+
validateGroup: (groupe: GroupeFormulaire, numeroMembre?: number) => ConditionValidationError[];
|
|
23
|
+
/** Valide toutes les variables de tous les groupes */
|
|
24
|
+
validateAll: (groupes: GroupeFormulaire[], instances?: Map<string, number[]>) => ConditionValidationError[];
|
|
25
|
+
/** Efface l'erreur pour une variable */
|
|
26
|
+
clearError: (variableCode: string, numeroMembre?: number) => void;
|
|
27
|
+
/** Efface toutes les erreurs */
|
|
28
|
+
clearAllErrors: () => void;
|
|
29
|
+
/** Indique s'il y a des erreurs */
|
|
30
|
+
hasErrors: boolean;
|
|
31
|
+
/** Récupère le message d'erreur pour une variable (ou null) */
|
|
32
|
+
getErrorForVariable: (variableCode: string, numeroMembre?: number) => string | null;
|
|
33
|
+
/** Réévalue les validations pour les variables dépendantes d'une variable modifiée */
|
|
34
|
+
revalidateDependents: (changedVariableCode: string, groupes: GroupeFormulaire[], numeroMembre?: number) => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Hook pour gérer la validation des conditions ConditionEval() dans les formulaires
|
|
38
|
+
*
|
|
39
|
+
* @param conditionEngine - Instance du moteur de conditions
|
|
40
|
+
* @param responses - Réponses actuelles du formulaire
|
|
41
|
+
* @param options - Options de configuration
|
|
42
|
+
* @returns Objet contenant les fonctions et état de validation
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* const {
|
|
47
|
+
* validationErrors,
|
|
48
|
+
* validateVariable,
|
|
49
|
+
* validateGroup,
|
|
50
|
+
* hasErrors,
|
|
51
|
+
* getErrorForVariable
|
|
52
|
+
* } = useConditionValidation(conditionEngine, responses, {
|
|
53
|
+
* evaluateOnChange: true,
|
|
54
|
+
* debug: true
|
|
55
|
+
* });
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function useConditionValidation(conditionEngine: ConditionEngine | null, responses: Record<string, EnqueteReponse>, options?: UseConditionValidationOptions): UseConditionValidationResult;
|
|
59
|
+
export default useConditionValidation;
|
|
60
|
+
//# sourceMappingURL=useConditionValidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useConditionValidation.d.ts","sourceRoot":"","sources":["../../src/hooks/useConditionValidation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EAEzB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,6BAA6B;IAC5C,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oCAAoC;IACpC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,4BAA4B;IAC3C,kGAAkG;IAClG,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IAExD,oEAAoE;IACpE,gBAAgB,EAAE,CAChB,QAAQ,EAAE,kBAAkB,EAC5B,YAAY,CAAC,EAAE,MAAM,KAClB,wBAAwB,GAAG,IAAI,CAAC;IAErC,sEAAsE;IACtE,aAAa,EAAE,CACb,MAAM,EAAE,gBAAgB,EACxB,YAAY,CAAC,EAAE,MAAM,KAClB,wBAAwB,EAAE,CAAC;IAEhC,sDAAsD;IACtD,WAAW,EAAE,CACX,OAAO,EAAE,gBAAgB,EAAE,EAC3B,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,KAC9B,wBAAwB,EAAE,CAAC;IAEhC,wCAAwC;IACxC,UAAU,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAElE,gCAAgC;IAChC,cAAc,EAAE,MAAM,IAAI,CAAC;IAE3B,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IAEnB,+DAA+D;IAC/D,mBAAmB,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAEpF,sFAAsF;IACtF,oBAAoB,EAAE,CACpB,mBAAmB,EAAE,MAAM,EAC3B,OAAO,EAAE,gBAAgB,EAAE,EAC3B,YAAY,CAAC,EAAE,MAAM,KAClB,IAAI,CAAC;CACX;AASD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,eAAe,GAAG,IAAI,EACvC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EACzC,OAAO,GAAE,6BAAkC,GAC1C,4BAA4B,CA+N9B;AAED,eAAe,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook de validation des conditions (ConditionEval) pour les formulaires d'enquête
|
|
3
|
+
* Gère l'évaluation des validations personnalisées via ConditionEval()
|
|
4
|
+
* RSU v2 - Package Partagé
|
|
5
|
+
*/
|
|
6
|
+
import { useState, useCallback, useMemo, useRef } from 'react';
|
|
7
|
+
/**
|
|
8
|
+
* Génère une clé unique pour une variable (avec ou sans numéro de membre)
|
|
9
|
+
*/
|
|
10
|
+
function getVariableKey(variableCode, numeroMembre) {
|
|
11
|
+
return numeroMembre ? `${variableCode}_${numeroMembre}` : variableCode;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Hook pour gérer la validation des conditions ConditionEval() dans les formulaires
|
|
15
|
+
*
|
|
16
|
+
* @param conditionEngine - Instance du moteur de conditions
|
|
17
|
+
* @param responses - Réponses actuelles du formulaire
|
|
18
|
+
* @param options - Options de configuration
|
|
19
|
+
* @returns Objet contenant les fonctions et état de validation
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* const {
|
|
24
|
+
* validationErrors,
|
|
25
|
+
* validateVariable,
|
|
26
|
+
* validateGroup,
|
|
27
|
+
* hasErrors,
|
|
28
|
+
* getErrorForVariable
|
|
29
|
+
* } = useConditionValidation(conditionEngine, responses, {
|
|
30
|
+
* evaluateOnChange: true,
|
|
31
|
+
* debug: true
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function useConditionValidation(conditionEngine, responses, options = {}) {
|
|
36
|
+
const { debounceMs = 0, evaluateOnChange = true, debug = false } = options;
|
|
37
|
+
// État des erreurs de validation
|
|
38
|
+
const [validationErrors, setValidationErrors] = useState(new Map());
|
|
39
|
+
// Ref pour le debounce
|
|
40
|
+
const debounceTimerRef = useRef(null);
|
|
41
|
+
// Fonction utilitaire pour logger en mode debug
|
|
42
|
+
const log = useCallback((message, data) => {
|
|
43
|
+
if (debug) {
|
|
44
|
+
console.log(`[ConditionValidation] ${message}`, data || '');
|
|
45
|
+
}
|
|
46
|
+
}, [debug]);
|
|
47
|
+
/**
|
|
48
|
+
* Valide une variable individuelle
|
|
49
|
+
*/
|
|
50
|
+
const validateVariable = useCallback((variable, numeroMembre) => {
|
|
51
|
+
if (!conditionEngine)
|
|
52
|
+
return null;
|
|
53
|
+
// Si pas de condition de validation, c'est valide
|
|
54
|
+
if (!variable.conditionsValidation || variable.conditionsValidation.trim() === '') {
|
|
55
|
+
// Effacer toute erreur existante
|
|
56
|
+
const key = getVariableKey(variable.code, numeroMembre);
|
|
57
|
+
setValidationErrors(prev => {
|
|
58
|
+
if (!prev.has(key))
|
|
59
|
+
return prev;
|
|
60
|
+
const next = new Map(prev);
|
|
61
|
+
next.delete(key);
|
|
62
|
+
return next;
|
|
63
|
+
});
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
log('Validation de la variable:', {
|
|
67
|
+
code: variable.code,
|
|
68
|
+
condition: variable.conditionsValidation,
|
|
69
|
+
numeroMembre
|
|
70
|
+
});
|
|
71
|
+
// Évaluer la condition
|
|
72
|
+
const result = conditionEngine.evaluateValidation(variable.conditionsValidation, variable.code, numeroMembre);
|
|
73
|
+
const key = getVariableKey(variable.code, numeroMembre);
|
|
74
|
+
if (!result.isValid) {
|
|
75
|
+
const error = {
|
|
76
|
+
variableCode: variable.code,
|
|
77
|
+
message: result.errorMessage || 'Données invalides',
|
|
78
|
+
condition: result.condition,
|
|
79
|
+
numeroMembre
|
|
80
|
+
};
|
|
81
|
+
log('Erreur de validation détectée:', error);
|
|
82
|
+
setValidationErrors(prev => {
|
|
83
|
+
const next = new Map(prev);
|
|
84
|
+
next.set(key, error);
|
|
85
|
+
return next;
|
|
86
|
+
});
|
|
87
|
+
return error;
|
|
88
|
+
}
|
|
89
|
+
// Valide: effacer l'erreur si elle existait
|
|
90
|
+
setValidationErrors(prev => {
|
|
91
|
+
if (!prev.has(key))
|
|
92
|
+
return prev;
|
|
93
|
+
const next = new Map(prev);
|
|
94
|
+
next.delete(key);
|
|
95
|
+
return next;
|
|
96
|
+
});
|
|
97
|
+
log('Variable validée avec succès:', variable.code);
|
|
98
|
+
return null;
|
|
99
|
+
}, [conditionEngine, log]);
|
|
100
|
+
/**
|
|
101
|
+
* Valide toutes les variables d'un groupe
|
|
102
|
+
*/
|
|
103
|
+
const validateGroup = useCallback((groupe, numeroMembre) => {
|
|
104
|
+
const errors = [];
|
|
105
|
+
for (const variable of groupe.variables) {
|
|
106
|
+
const error = validateVariable(variable, numeroMembre);
|
|
107
|
+
if (error) {
|
|
108
|
+
errors.push(error);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
log('Validation du groupe:', {
|
|
112
|
+
groupeCode: groupe.code,
|
|
113
|
+
nombreVariables: groupe.variables.length,
|
|
114
|
+
nombreErreurs: errors.length
|
|
115
|
+
});
|
|
116
|
+
return errors;
|
|
117
|
+
}, [validateVariable, log]);
|
|
118
|
+
/**
|
|
119
|
+
* Valide toutes les variables de tous les groupes
|
|
120
|
+
*/
|
|
121
|
+
const validateAll = useCallback((groupes, instances) => {
|
|
122
|
+
const allErrors = [];
|
|
123
|
+
for (const groupe of groupes) {
|
|
124
|
+
if (groupe.estMultiple && instances?.has(groupe.code)) {
|
|
125
|
+
// Groupe multiple: valider chaque instance
|
|
126
|
+
const instanceNumbers = instances.get(groupe.code) || [];
|
|
127
|
+
for (const instanceNum of instanceNumbers) {
|
|
128
|
+
const errors = validateGroup(groupe, instanceNum);
|
|
129
|
+
allErrors.push(...errors);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// Groupe simple
|
|
134
|
+
const errors = validateGroup(groupe);
|
|
135
|
+
allErrors.push(...errors);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
log('Validation complète:', {
|
|
139
|
+
totalGroupes: groupes.length,
|
|
140
|
+
totalErreurs: allErrors.length
|
|
141
|
+
});
|
|
142
|
+
return allErrors;
|
|
143
|
+
}, [validateGroup, log]);
|
|
144
|
+
/**
|
|
145
|
+
* Efface l'erreur pour une variable
|
|
146
|
+
*/
|
|
147
|
+
const clearError = useCallback((variableCode, numeroMembre) => {
|
|
148
|
+
const key = getVariableKey(variableCode, numeroMembre);
|
|
149
|
+
setValidationErrors(prev => {
|
|
150
|
+
if (!prev.has(key))
|
|
151
|
+
return prev;
|
|
152
|
+
const next = new Map(prev);
|
|
153
|
+
next.delete(key);
|
|
154
|
+
return next;
|
|
155
|
+
});
|
|
156
|
+
}, []);
|
|
157
|
+
/**
|
|
158
|
+
* Efface toutes les erreurs
|
|
159
|
+
*/
|
|
160
|
+
const clearAllErrors = useCallback(() => {
|
|
161
|
+
setValidationErrors(new Map());
|
|
162
|
+
}, []);
|
|
163
|
+
/**
|
|
164
|
+
* Récupère le message d'erreur pour une variable
|
|
165
|
+
*/
|
|
166
|
+
const getErrorForVariable = useCallback((variableCode, numeroMembre) => {
|
|
167
|
+
const key = getVariableKey(variableCode, numeroMembre);
|
|
168
|
+
const error = validationErrors.get(key);
|
|
169
|
+
return error ? error.message : null;
|
|
170
|
+
}, [validationErrors]);
|
|
171
|
+
/**
|
|
172
|
+
* Réévalue les validations pour les variables dépendantes
|
|
173
|
+
*/
|
|
174
|
+
const revalidateDependents = useCallback((changedVariableCode, groupes, numeroMembre) => {
|
|
175
|
+
if (!conditionEngine)
|
|
176
|
+
return;
|
|
177
|
+
log('Réévaluation des dépendants de:', changedVariableCode);
|
|
178
|
+
// Parcourir toutes les variables pour trouver celles qui dépendent de la variable modifiée
|
|
179
|
+
for (const groupe of groupes) {
|
|
180
|
+
for (const variable of groupe.variables) {
|
|
181
|
+
if (!variable.conditionsValidation)
|
|
182
|
+
continue;
|
|
183
|
+
// Vérifier si la condition référence la variable modifiée
|
|
184
|
+
if (variable.conditionsValidation.includes(`\${${changedVariableCode}}`)) {
|
|
185
|
+
log('Variable dépendante trouvée:', variable.code);
|
|
186
|
+
validateVariable(variable, numeroMembre);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}, [conditionEngine, validateVariable, log]);
|
|
191
|
+
/**
|
|
192
|
+
* Indicateur de présence d'erreurs
|
|
193
|
+
*/
|
|
194
|
+
const hasErrors = useMemo(() => {
|
|
195
|
+
return validationErrors.size > 0;
|
|
196
|
+
}, [validationErrors]);
|
|
197
|
+
return {
|
|
198
|
+
validationErrors,
|
|
199
|
+
validateVariable,
|
|
200
|
+
validateGroup,
|
|
201
|
+
validateAll,
|
|
202
|
+
clearError,
|
|
203
|
+
clearAllErrors,
|
|
204
|
+
hasErrors,
|
|
205
|
+
getErrorForVariable,
|
|
206
|
+
revalidateDependents
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
export default useConditionValidation;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Moteur d'évaluation des conditions complexes pour les formulaires d'enquête
|
|
3
3
|
* RSU v2 - Moteur de Rendu des Formulaires d'Enquête
|
|
4
4
|
*/
|
|
5
|
-
import { EnqueteReponse, VariableValue } from '../types/enquete';
|
|
5
|
+
import { EnqueteReponse, VariableValue, ValidationEvalResult } from '../types/enquete';
|
|
6
6
|
export interface AutoAction {
|
|
7
7
|
type: 'setValue';
|
|
8
8
|
targetVariable: string;
|
|
@@ -21,6 +21,8 @@ export declare class ConditionEngine {
|
|
|
21
21
|
private autoActions;
|
|
22
22
|
private conditionCache;
|
|
23
23
|
private maxCacheSize;
|
|
24
|
+
private static readonly FORBIDDEN_VALIDATION_FUNCTIONS;
|
|
25
|
+
private static readonly DEFAULT_VALIDATION_ERROR;
|
|
24
26
|
constructor(responses: Record<string, EnqueteReponse>);
|
|
25
27
|
/**
|
|
26
28
|
* Évalue une condition complexe
|
|
@@ -109,6 +111,28 @@ export declare class ConditionEngine {
|
|
|
109
111
|
* Vide la liste des actions automatiques
|
|
110
112
|
*/
|
|
111
113
|
clearAutoActions(): void;
|
|
114
|
+
/**
|
|
115
|
+
* Évalue une condition de validation ConditionEval()
|
|
116
|
+
* Syntaxe: ConditionEval(condition, errorMessage?)
|
|
117
|
+
*
|
|
118
|
+
* @param conditionValidation - Expression ConditionEval complète ou condition brute
|
|
119
|
+
* @param variableCode - Code de la variable à laquelle cette validation s'applique
|
|
120
|
+
* @param currentIteration - Numéro d'itération pour les groupes multiples
|
|
121
|
+
* @returns ValidationEvalResult avec isValid, errorMessage, variableCode, condition
|
|
122
|
+
*/
|
|
123
|
+
evaluateValidation(conditionValidation: string, variableCode: string, currentIteration?: number): ValidationEvalResult;
|
|
124
|
+
/**
|
|
125
|
+
* Évalue une expression ConditionEval(condition, errorMessage?)
|
|
126
|
+
*/
|
|
127
|
+
private evaluateConditionEval;
|
|
128
|
+
/**
|
|
129
|
+
* Vérifie si une expression contient des fonctions interdites pour la validation
|
|
130
|
+
*/
|
|
131
|
+
private containsForbiddenValidationFunction;
|
|
132
|
+
/**
|
|
133
|
+
* Parse un paramètre chaîne (gère les guillemets)
|
|
134
|
+
*/
|
|
135
|
+
private parseStringParam;
|
|
112
136
|
/**
|
|
113
137
|
* Construit le contexte d'évaluation à partir des réponses
|
|
114
138
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"condition-engine.d.ts","sourceRoot":"","sources":["../../src/lib/condition-engine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"condition-engine.d.ts","sourceRoot":"","sources":["../../src/lib/condition-engine.ts"],"names":[],"mappings":"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"}
|