@rsuci/shared-form-components 1.0.132 → 1.0.134
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/inputs/GeographicCascadeInput.d.ts +4 -0
- package/dist/components/inputs/GeographicCascadeInput.d.ts.map +1 -1
- package/dist/components/inputs/GeographicCascadeInput.js +40 -97
- package/dist/components/inputs/SearchableSelect.d.ts +1 -0
- package/dist/components/inputs/SearchableSelect.d.ts.map +1 -1
- package/dist/components/inputs/SearchableSelect.js +20 -6
- package/dist/components/selectors/EnqueteInput.d.ts.map +1 -1
- package/dist/components/selectors/EnqueteInput.js +12 -21
- package/dist/components/selectors/MenageInput.d.ts.map +1 -1
- package/dist/components/selectors/MenageInput.js +12 -21
- package/dist/components/selectors/RSUInput.d.ts.map +1 -1
- package/dist/components/selectors/RSUInput.js +12 -20
- package/dist/types/services.d.ts +1 -1
- package/dist/types/services.d.ts.map +1 -1
- package/package.json +62 -62
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { GeographicItem, FetchFilter } from '../../types/services';
|
|
2
3
|
interface SelectDto {
|
|
3
4
|
id: number;
|
|
4
5
|
code: string;
|
|
@@ -13,6 +14,9 @@ interface GeographicCascadeInputProps {
|
|
|
13
14
|
required?: boolean;
|
|
14
15
|
className?: string;
|
|
15
16
|
isConsultationMode?: boolean;
|
|
17
|
+
services?: {
|
|
18
|
+
fetchGeographicData?: (entityType: string, parentId?: number, filter?: FetchFilter) => Promise<GeographicItem[]>;
|
|
19
|
+
};
|
|
16
20
|
}
|
|
17
21
|
export declare const GeographicCascadeInput: React.FC<GeographicCascadeInputProps>;
|
|
18
22
|
export default GeographicCascadeInput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GeographicCascadeInput.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/GeographicCascadeInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"GeographicCascadeInput.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/GeographicCascadeInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AASjF,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnE,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,2BAA2B;IACnC,QAAQ,EAAE,GAAG,CAAC;IACd,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,EAAE;QACT,mBAAmB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;KAClH,CAAC;CACH;AAID,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,2BAA2B,CAuOxE,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState, useCallback, useRef, useMemo } from 'react';
|
|
3
3
|
import SearchableSelect from './SearchableSelect';
|
|
4
|
-
import { extractVariableCode, resolveParentValue,
|
|
4
|
+
import { extractVariableCode, resolveParentValue, getParentLabel, requiresParent } from '../../utils/variableDependencyResolver';
|
|
5
5
|
import { isComponentReadonly } from '../../utils/componentStateUtils';
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const PAGE_SIZE = 50;
|
|
7
|
+
export const GeographicCascadeInput = ({ variable, value, onChange, reponses, disabled = false, required = false, className = '', isConsultationMode = false, services }) => {
|
|
8
8
|
const [items, setItems] = useState([]);
|
|
9
9
|
const [loading, setLoading] = useState(false);
|
|
10
10
|
const [loadingMore, setLoadingMore] = useState(false);
|
|
@@ -16,43 +16,12 @@ export const GeographicCascadeInput = ({ variable, value, onChange, reponses, di
|
|
|
16
16
|
const hasParentConfigured = !!extractVariableCode(variable);
|
|
17
17
|
const effectiveNeedsParent = needsParent && hasParentConfigured;
|
|
18
18
|
const parentValue = resolveParentValue(variable, reponses);
|
|
19
|
-
const
|
|
20
|
-
? (variable.valeur || 'CIV')
|
|
21
|
-
: undefined;
|
|
22
|
-
const baseEndpoint = getApiEndpoint(variable.typeCode, parentValue, countryCode, hasParentConfigured);
|
|
23
|
-
// Construire l'URL paginée avec recherche
|
|
24
|
-
const buildUrl = useCallback((p, search) => {
|
|
25
|
-
if (!baseEndpoint)
|
|
26
|
-
return null;
|
|
27
|
-
const url = new URL(baseEndpoint, window.location.origin);
|
|
28
|
-
url.searchParams.set('page', String(p));
|
|
29
|
-
url.searchParams.set('pageSize', String(PAGE_SIZE));
|
|
30
|
-
if (search)
|
|
31
|
-
url.searchParams.set('search', search);
|
|
32
|
-
return url.pathname + url.search;
|
|
33
|
-
}, [baseEndpoint]);
|
|
34
|
-
// Extraire les items depuis la réponse API (multi-format)
|
|
35
|
-
const parseResponse = (result) => {
|
|
36
|
-
// Format endpoint unifié : { data: { data: [...], totalCount, ... } }
|
|
37
|
-
if (result.data && typeof result.data === 'object' && !Array.isArray(result.data) && Array.isArray(result.data.data)) {
|
|
38
|
-
return result.data.data.map((item) => ({
|
|
39
|
-
id: item.id,
|
|
40
|
-
code: item.code,
|
|
41
|
-
designation: item.label || item.designation,
|
|
42
|
-
}));
|
|
43
|
-
}
|
|
44
|
-
// Format RSU API : { status: "SUCCESS", data: [...] }
|
|
45
|
-
if (result.status === 'SUCCESS' && Array.isArray(result.data)) {
|
|
46
|
-
return result.data;
|
|
47
|
-
}
|
|
48
|
-
if (Array.isArray(result))
|
|
49
|
-
return result;
|
|
50
|
-
if (result.data && Array.isArray(result.data))
|
|
51
|
-
return result.data;
|
|
52
|
-
throw new Error('Format de réponse invalide');
|
|
53
|
-
};
|
|
54
|
-
// Chargement initial + reset quand parent ou recherche change (debounce 300ms sur recherche)
|
|
19
|
+
const entityType = variable.typeCode;
|
|
55
20
|
useEffect(() => {
|
|
21
|
+
if (!services?.fetchGeographicData) {
|
|
22
|
+
setError('Service de chargement géographique non disponible');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
56
25
|
if (effectiveNeedsParent && !parentValue) {
|
|
57
26
|
setItems([]);
|
|
58
27
|
setLoading(false);
|
|
@@ -61,55 +30,41 @@ export const GeographicCascadeInput = ({ variable, value, onChange, reponses, di
|
|
|
61
30
|
setHasMore(true);
|
|
62
31
|
return;
|
|
63
32
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
33
|
+
setLoading(true);
|
|
34
|
+
setError(null);
|
|
35
|
+
setPage(1);
|
|
36
|
+
setHasMore(true);
|
|
37
|
+
services.fetchGeographicData(entityType, parentValue || undefined, { searchText: searchTerm || undefined, page: 1, pageSize: PAGE_SIZE })
|
|
38
|
+
.then(data => {
|
|
39
|
+
const mapped = data.map(item => ({
|
|
40
|
+
id: item.id,
|
|
41
|
+
code: item.code,
|
|
42
|
+
designation: item.designation,
|
|
43
|
+
}));
|
|
44
|
+
setItems(mapped);
|
|
45
|
+
setHasMore(mapped.length === PAGE_SIZE);
|
|
46
|
+
})
|
|
47
|
+
.catch(() => {
|
|
48
|
+
setError(`Erreur de chargement des ${variable.designation?.toLowerCase() || 'données'}`);
|
|
74
49
|
setItems([]);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const response = await fetch(url);
|
|
79
|
-
if (!response.ok)
|
|
80
|
-
throw new Error(`HTTP ${response.status}`);
|
|
81
|
-
const result = await response.json();
|
|
82
|
-
const data = parseResponse(result);
|
|
83
|
-
setItems(data);
|
|
84
|
-
setHasMore(data.length === PAGE_SIZE);
|
|
85
|
-
}
|
|
86
|
-
catch (err) {
|
|
87
|
-
setError(`Erreur de chargement des ${variable.designation?.toLowerCase() || 'données'}`);
|
|
88
|
-
setItems([]);
|
|
89
|
-
}
|
|
90
|
-
finally {
|
|
91
|
-
setLoading(false);
|
|
92
|
-
}
|
|
93
|
-
}, searchTerm ? 300 : 0);
|
|
94
|
-
return () => clearTimeout(timer);
|
|
95
|
-
}, [baseEndpoint, effectiveNeedsParent, parentValue, searchTerm, buildUrl]);
|
|
50
|
+
})
|
|
51
|
+
.finally(() => setLoading(false));
|
|
52
|
+
}, [entityType, effectiveNeedsParent, parentValue, searchTerm, services]);
|
|
96
53
|
const handleScrollEnd = useCallback(async () => {
|
|
97
|
-
if (!hasMore || loadingMore || loading)
|
|
54
|
+
if (!hasMore || loadingMore || loading || !services?.fetchGeographicData)
|
|
98
55
|
return;
|
|
99
56
|
const nextPage = page + 1;
|
|
100
|
-
const url = buildUrl(nextPage, searchTerm || undefined);
|
|
101
|
-
if (!url)
|
|
102
|
-
return;
|
|
103
57
|
setLoadingMore(true);
|
|
104
58
|
try {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
59
|
+
const data = await services.fetchGeographicData(entityType, parentValue || undefined, { searchText: searchTerm || undefined, page: nextPage, pageSize: PAGE_SIZE });
|
|
60
|
+
const mapped = data.map(item => ({
|
|
61
|
+
id: item.id,
|
|
62
|
+
code: item.code,
|
|
63
|
+
designation: item.designation,
|
|
64
|
+
}));
|
|
65
|
+
setItems(prev => [...prev, ...mapped]);
|
|
111
66
|
setPage(nextPage);
|
|
112
|
-
setHasMore(
|
|
67
|
+
setHasMore(mapped.length === PAGE_SIZE);
|
|
113
68
|
}
|
|
114
69
|
catch {
|
|
115
70
|
// Les données existantes restent affichées
|
|
@@ -117,34 +72,29 @@ export const GeographicCascadeInput = ({ variable, value, onChange, reponses, di
|
|
|
117
72
|
finally {
|
|
118
73
|
setLoadingMore(false);
|
|
119
74
|
}
|
|
120
|
-
}, [hasMore, loadingMore, loading, page, searchTerm,
|
|
75
|
+
}, [hasMore, loadingMore, loading, page, searchTerm, entityType, parentValue, services]);
|
|
121
76
|
const handleSearchChange = useCallback((term) => {
|
|
122
77
|
setSearchTerm(term);
|
|
123
78
|
}, []);
|
|
124
|
-
//
|
|
79
|
+
// Réinitialiser la valeur si le parent change
|
|
125
80
|
const previousParentRef = useRef(undefined);
|
|
126
81
|
useEffect(() => {
|
|
127
|
-
// Si un parent est requis (configuré) et que la valeur du parent a changé
|
|
128
82
|
if (effectiveNeedsParent) {
|
|
129
|
-
// Premier rendu : initialiser la référence sans réinitialiser
|
|
130
83
|
if (previousParentRef.current === undefined) {
|
|
131
84
|
previousParentRef.current = parentValue;
|
|
132
85
|
return;
|
|
133
86
|
}
|
|
134
|
-
// Si le parent a changé et qu'on a une valeur sélectionnée, la réinitialiser
|
|
135
87
|
if (parentValue !== previousParentRef.current && value) {
|
|
136
88
|
onChange(null);
|
|
137
89
|
}
|
|
138
90
|
previousParentRef.current = parentValue;
|
|
139
91
|
}
|
|
140
92
|
}, [parentValue, effectiveNeedsParent, value, onChange]);
|
|
141
|
-
// 7. Gérer le changement de valeur
|
|
142
93
|
const handleChange = (option) => {
|
|
143
94
|
if (!option) {
|
|
144
95
|
onChange(null);
|
|
145
96
|
return;
|
|
146
97
|
}
|
|
147
|
-
// Convertir SelectOption vers SelectDto
|
|
148
98
|
const selectDto = {
|
|
149
99
|
id: typeof option.id === 'string' ? parseInt(option.id, 10) : option.id,
|
|
150
100
|
code: option.code || '',
|
|
@@ -152,10 +102,8 @@ export const GeographicCascadeInput = ({ variable, value, onChange, reponses, di
|
|
|
152
102
|
};
|
|
153
103
|
onChange(selectDto);
|
|
154
104
|
};
|
|
155
|
-
// 8. Déterminer si le champ est désactivé (select ne supporte pas readonly, on utilise disabled)
|
|
156
105
|
const isReadonly = isComponentReadonly(variable, isConsultationMode);
|
|
157
106
|
const isDisabled = disabled || isReadonly || loading || (effectiveNeedsParent && !parentValue);
|
|
158
|
-
// 9. Déterminer le message du placeholder
|
|
159
107
|
const getPlaceholder = () => {
|
|
160
108
|
if (loading)
|
|
161
109
|
return 'Chargement...';
|
|
@@ -170,11 +118,9 @@ export const GeographicCascadeInput = ({ variable, value, onChange, reponses, di
|
|
|
170
118
|
const parsedValue = useMemo(() => {
|
|
171
119
|
if (!value)
|
|
172
120
|
return null;
|
|
173
|
-
// Si c'est déjà un objet avec les propriétés attendues
|
|
174
121
|
if (typeof value === 'object' && value !== null && 'id' in value) {
|
|
175
122
|
return value;
|
|
176
123
|
}
|
|
177
|
-
// Si c'est une chaîne JSON, la parser
|
|
178
124
|
if (typeof value === 'string') {
|
|
179
125
|
try {
|
|
180
126
|
const parsed = JSON.parse(value);
|
|
@@ -183,12 +129,11 @@ export const GeographicCascadeInput = ({ variable, value, onChange, reponses, di
|
|
|
183
129
|
}
|
|
184
130
|
}
|
|
185
131
|
catch {
|
|
186
|
-
// Ignorer les erreurs de parsing
|
|
132
|
+
// Ignorer les erreurs de parsing
|
|
187
133
|
}
|
|
188
134
|
}
|
|
189
135
|
return null;
|
|
190
136
|
}, [value]);
|
|
191
|
-
// Convertir les items en SelectOption, avec la valeur pré-sélectionnée en tête si absente
|
|
192
137
|
const options = useMemo(() => {
|
|
193
138
|
const mapped = items.map(item => ({
|
|
194
139
|
id: item.id,
|
|
@@ -200,15 +145,13 @@ export const GeographicCascadeInput = ({ variable, value, onChange, reponses, di
|
|
|
200
145
|
}
|
|
201
146
|
return mapped;
|
|
202
147
|
}, [items, parsedValue]);
|
|
203
|
-
// Convertir la valeur parsée en SelectOption
|
|
204
148
|
const currentValue = parsedValue ? {
|
|
205
149
|
id: parsedValue.id,
|
|
206
150
|
code: parsedValue.code,
|
|
207
151
|
designation: parsedValue.designation
|
|
208
152
|
} : null;
|
|
209
|
-
// 13. Rendu du composant
|
|
210
153
|
return (_jsxs("div", { className: "w-full", children: [_jsx(SearchableSelect, { options: options, value: currentValue, onChange: handleChange, placeholder: getPlaceholder(), searchPlaceholder: "Rechercher...", disabled: isDisabled, required: required, loading: loading, error: error || undefined, className: className, noOptionsMessage: effectiveNeedsParent && !parentValue
|
|
211
154
|
? `Veuillez d'abord sélectionner ${getParentLabel(variable.typeCode)}`
|
|
212
|
-
: `Aucun(e) ${variable.designation?.toLowerCase() || 'élément'} disponible`, formatOptionLabel: (option) => option.designation, onSearchChange: handleSearchChange, onScrollEnd: handleScrollEnd, loadingMore: loadingMore }), effectiveNeedsParent && !parentValue && !loading && !error && (_jsxs("p", { className: "mt-1 text-sm text-gray-500 flex items-center", children: [_jsx("svg", { className: "w-4 h-4 mr-1", fill: "currentColor", viewBox: "0 0 20 20", children: _jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clipRule: "evenodd" }) }), "Veuillez d'abord s\u00E9lectionner ", getParentLabel(variable.typeCode)] })), loading && (_jsxs("p", { className: "mt-1 text-sm text-blue-600 flex items-center", children: [_jsxs("svg", { className: "animate-spin h-4 w-4 mr-1", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }), "Chargement des donn\u00E9es..."] }))] }));
|
|
155
|
+
: `Aucun(e) ${variable.designation?.toLowerCase() || 'élément'} disponible`, formatOptionLabel: (option) => option.designation, onSearchChange: handleSearchChange, onScrollEnd: handleScrollEnd, loadingMore: loadingMore, debounceMs: 300 }), effectiveNeedsParent && !parentValue && !loading && !error && (_jsxs("p", { className: "mt-1 text-sm text-gray-500 flex items-center", children: [_jsx("svg", { className: "w-4 h-4 mr-1", fill: "currentColor", viewBox: "0 0 20 20", children: _jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clipRule: "evenodd" }) }), "Veuillez d'abord s\u00E9lectionner ", getParentLabel(variable.typeCode)] })), loading && (_jsxs("p", { className: "mt-1 text-sm text-blue-600 flex items-center", children: [_jsxs("svg", { className: "animate-spin h-4 w-4 mr-1", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }), "Chargement des donn\u00E9es..."] }))] }));
|
|
213
156
|
};
|
|
214
157
|
export default GeographicCascadeInput;
|
|
@@ -25,6 +25,7 @@ interface SearchableSelectProps {
|
|
|
25
25
|
onSearchChange?: (term: string) => void;
|
|
26
26
|
onScrollEnd?: () => void;
|
|
27
27
|
loadingMore?: boolean;
|
|
28
|
+
debounceMs?: number;
|
|
28
29
|
}
|
|
29
30
|
export declare const SearchableSelect: React.FC<SearchableSelectProps>;
|
|
30
31
|
export default SearchableSelect;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchableSelect.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/SearchableSelect.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"SearchableSelect.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/SearchableSelect.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAExE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,UAAU,qBAAqB;IAC7B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,MAAM,CAAC;IACrD,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA4O5D,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -3,12 +3,29 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
* Composant de sélection avec recherche intégrée
|
|
4
4
|
* Inspiré du design de production avec champ de filtre
|
|
5
5
|
*/
|
|
6
|
-
import { useState, useRef, useEffect } from 'react';
|
|
7
|
-
export const SearchableSelect = ({ options, value, onChange, placeholder = 'Sélectionner...', searchPlaceholder = 'Rechercher...', disabled = false, required = false, loading = false, error, className = '', noOptionsMessage = 'Aucune option disponible', formatOptionLabel, onSearchChange, onScrollEnd, loadingMore = false, }) => {
|
|
6
|
+
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
7
|
+
export const SearchableSelect = ({ options, value, onChange, placeholder = 'Sélectionner...', searchPlaceholder = 'Rechercher...', disabled = false, required = false, loading = false, error, className = '', noOptionsMessage = 'Aucune option disponible', formatOptionLabel, onSearchChange, onScrollEnd, loadingMore = false, debounceMs = 0, }) => {
|
|
8
8
|
const [isOpen, setIsOpen] = useState(false);
|
|
9
9
|
const [searchTerm, setSearchTerm] = useState('');
|
|
10
10
|
const dropdownRef = useRef(null);
|
|
11
11
|
const searchInputRef = useRef(null);
|
|
12
|
+
const debounceRef = useRef();
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
return () => { if (debounceRef.current)
|
|
15
|
+
clearTimeout(debounceRef.current); };
|
|
16
|
+
}, []);
|
|
17
|
+
const handleSearchInput = useCallback((val) => {
|
|
18
|
+
setSearchTerm(val);
|
|
19
|
+
if (!onSearchChange)
|
|
20
|
+
return;
|
|
21
|
+
if (debounceMs > 0) {
|
|
22
|
+
clearTimeout(debounceRef.current);
|
|
23
|
+
debounceRef.current = setTimeout(() => onSearchChange(val), debounceMs);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
onSearchChange(val);
|
|
27
|
+
}
|
|
28
|
+
}, [onSearchChange, debounceMs]);
|
|
12
29
|
// Fermer le dropdown quand on clique à l'extérieur
|
|
13
30
|
useEffect(() => {
|
|
14
31
|
const handleClickOutside = (event) => {
|
|
@@ -74,10 +91,7 @@ export const SearchableSelect = ({ options, value, onChange, placeholder = 'Sél
|
|
|
74
91
|
};
|
|
75
92
|
return (_jsxs("div", { className: `relative w-full ${className}`, ref: dropdownRef, children: [_jsx("button", { type: "button", onClick: toggleDropdown, disabled: disabled || loading, className: `w-full px-3 py-2 text-left border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors ${error ? 'border-red-300 bg-red-50' : 'border-gray-300'} ${disabled || loading
|
|
76
93
|
? 'bg-gray-100 cursor-not-allowed text-gray-500'
|
|
77
|
-
: 'bg-white text-gray-900 hover:border-gray-400'} ${isOpen ? 'ring-2 ring-blue-500 border-transparent' : ''}`, children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: value ? 'text-gray-900' : 'text-gray-500', children: loading ? 'Chargement...' : getSelectedLabel() }), _jsx("svg", { className: `w-5 h-5 text-gray-400 transition-transform ${isOpen ? 'transform rotate-180' : ''}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })] }) }), isOpen && !disabled && !loading && (_jsxs("div", { className: "absolute z-50 w-full mt-1 bg-white border border-gray-300 rounded-lg shadow-lg", children: [_jsx("div", { className: "p-2 border-b border-gray-200 bg-gray-50", children: _jsxs("div", { className: "relative", children: [_jsx("svg", { className: "absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }), _jsx("input", { ref: searchInputRef, type: "text", value: searchTerm, onChange: (e) => {
|
|
78
|
-
setSearchTerm(e.target.value);
|
|
79
|
-
onSearchChange?.(e.target.value);
|
|
80
|
-
}, placeholder: searchPlaceholder, className: "w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-transparent text-sm" })] }) }), _jsxs("div", { className: "overflow-y-auto", style: { maxHeight: '240px' }, onScroll: (e) => {
|
|
94
|
+
: 'bg-white text-gray-900 hover:border-gray-400'} ${isOpen ? 'ring-2 ring-blue-500 border-transparent' : ''}`, children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: value ? 'text-gray-900' : 'text-gray-500', children: loading ? 'Chargement...' : getSelectedLabel() }), _jsx("svg", { className: `w-5 h-5 text-gray-400 transition-transform ${isOpen ? 'transform rotate-180' : ''}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })] }) }), isOpen && !disabled && !loading && (_jsxs("div", { className: "absolute z-50 w-full mt-1 bg-white border border-gray-300 rounded-lg shadow-lg", children: [_jsx("div", { className: "p-2 border-b border-gray-200 bg-gray-50", children: _jsxs("div", { className: "relative", children: [_jsx("svg", { className: "absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }), _jsx("input", { ref: searchInputRef, type: "text", value: searchTerm, onChange: (e) => handleSearchInput(e.target.value), placeholder: searchPlaceholder, className: "w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-transparent text-sm" })] }) }), _jsxs("div", { className: "overflow-y-auto", style: { maxHeight: '240px' }, onScroll: (e) => {
|
|
81
95
|
if (!onScrollEnd)
|
|
82
96
|
return;
|
|
83
97
|
const { scrollTop, clientHeight, scrollHeight } = e.currentTarget;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnqueteInput.d.ts","sourceRoot":"","sources":["../../../src/components/selectors/EnqueteInput.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEtE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE;YACX,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC;KACH,CAAC;IACF,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,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,qBAAqB,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,KAAK,IAAI,CAAC;IACnD,mBAAmB,CAAC,EAAE,GAAG,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE;QACT,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACvE,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;KAC3D,CAAC;CACH;AAID,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"EnqueteInput.d.ts","sourceRoot":"","sources":["../../../src/components/selectors/EnqueteInput.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEtE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE;YACX,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC;KACH,CAAC;IACF,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,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,qBAAqB,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,KAAK,IAAI,CAAC;IACnD,mBAAmB,CAAC,EAAE,GAAG,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE;QACT,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACvE,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;KAC3D,CAAC;CACH;AAID,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA+G7C,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,eAAe,YAAY,CAAC"}
|
|
@@ -12,31 +12,22 @@ const EnqueteInput = ({ variable, value, onChange, error, disabled, onFillFormFr
|
|
|
12
12
|
const [loadingData, setLoadingData] = useState(false);
|
|
13
13
|
const [loadError, setLoadError] = useState(null);
|
|
14
14
|
const [searchTerm, setSearchTerm] = useState('');
|
|
15
|
-
// Chargement initial + reset sur changement de recherche (debounce 300ms)
|
|
16
15
|
useEffect(() => {
|
|
17
16
|
if (!services?.fetchEnquetes) {
|
|
18
17
|
setLoadError('Service de chargement des enquêtes non disponible');
|
|
19
18
|
return;
|
|
20
19
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
catch {
|
|
33
|
-
setLoadError('Erreur lors du chargement des enquêtes');
|
|
34
|
-
}
|
|
35
|
-
finally {
|
|
36
|
-
setLoading(false);
|
|
37
|
-
}
|
|
38
|
-
}, searchTerm ? 300 : 0);
|
|
39
|
-
return () => clearTimeout(timer);
|
|
20
|
+
setLoading(true);
|
|
21
|
+
setLoadError(null);
|
|
22
|
+
setPage(1);
|
|
23
|
+
setHasMore(true);
|
|
24
|
+
services.fetchEnquetes({ searchText: searchTerm || undefined, page: 1, pageSize: PAGE_SIZE })
|
|
25
|
+
.then(data => {
|
|
26
|
+
setEnquetes(data);
|
|
27
|
+
setHasMore(data.length === PAGE_SIZE);
|
|
28
|
+
})
|
|
29
|
+
.catch(() => setLoadError('Erreur lors du chargement des enquêtes'))
|
|
30
|
+
.finally(() => setLoading(false));
|
|
40
31
|
}, [searchTerm, services]);
|
|
41
32
|
const handleScrollEnd = useCallback(async () => {
|
|
42
33
|
if (!hasMore || loadingMore || loading || !services?.fetchEnquetes)
|
|
@@ -85,7 +76,7 @@ const EnqueteInput = ({ variable, value, onChange, error, disabled, onFillFormFr
|
|
|
85
76
|
}
|
|
86
77
|
}
|
|
87
78
|
};
|
|
88
|
-
return (_jsxs("div", { children: [_jsx(SearchableSelect, { options: options, value: selectedOption, onChange: handleChange, placeholder: "S\u00E9lectionner une enqu\u00EAte...", searchPlaceholder: "Rechercher une enqu\u00EAte...", disabled: disabled || loadingData, required: variable.estObligatoire, loading: loading, error: loadError || error, formatOptionLabel: (option) => option.designation, noOptionsMessage: loading ? 'Chargement...' : 'Aucune enquête trouvée', onSearchChange: setSearchTerm, onScrollEnd: handleScrollEnd, loadingMore: loadingMore }), loadingData && (_jsx("p", { className: "text-sm text-blue-600 mt-1", children: "Chargement des donn\u00E9es de l'enqu\u00EAte..." }))] }));
|
|
79
|
+
return (_jsxs("div", { children: [_jsx(SearchableSelect, { options: options, value: selectedOption, onChange: handleChange, placeholder: "S\u00E9lectionner une enqu\u00EAte...", searchPlaceholder: "Rechercher une enqu\u00EAte...", disabled: disabled || loadingData, required: variable.estObligatoire, loading: loading, error: loadError || error, formatOptionLabel: (option) => option.designation, noOptionsMessage: loading ? 'Chargement...' : 'Aucune enquête trouvée', onSearchChange: setSearchTerm, onScrollEnd: handleScrollEnd, loadingMore: loadingMore, debounceMs: 300 }), loadingData && (_jsx("p", { className: "text-sm text-blue-600 mt-1", children: "Chargement des donn\u00E9es de l'enqu\u00EAte..." }))] }));
|
|
89
80
|
};
|
|
90
81
|
export { EnqueteInput };
|
|
91
82
|
export default EnqueteInput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenageInput.d.ts","sourceRoot":"","sources":["../../../src/components/selectors/MenageInput.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAErE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE;YACX,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC;KACH,CAAC;IACF,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,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,mBAAmB,CAAC,EAAE,GAAG,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE;QACT,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;KACtE,CAAC;CACH;AAID,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,
|
|
1
|
+
{"version":3,"file":"MenageInput.d.ts","sourceRoot":"","sources":["../../../src/components/selectors/MenageInput.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAErE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE;YACX,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC;KACH,CAAC;IACF,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,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,mBAAmB,CAAC,EAAE,GAAG,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE;QACT,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;KACtE,CAAC;CACH;AAID,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAgG3C,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC;AACvB,eAAe,WAAW,CAAC"}
|
|
@@ -11,31 +11,22 @@ const MenageInput = ({ variable, value, onChange, error, disabled, onFillFormFro
|
|
|
11
11
|
const [loadingMore, setLoadingMore] = useState(false);
|
|
12
12
|
const [loadError, setLoadError] = useState(null);
|
|
13
13
|
const [searchTerm, setSearchTerm] = useState('');
|
|
14
|
-
// Chargement initial + reset sur changement de recherche (debounce 300ms)
|
|
15
14
|
useEffect(() => {
|
|
16
15
|
if (!services?.fetchMenages) {
|
|
17
16
|
setLoadError('Service de chargement des ménages non disponible');
|
|
18
17
|
return;
|
|
19
18
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
catch {
|
|
32
|
-
setLoadError('Erreur lors du chargement des ménages');
|
|
33
|
-
}
|
|
34
|
-
finally {
|
|
35
|
-
setLoading(false);
|
|
36
|
-
}
|
|
37
|
-
}, searchTerm ? 300 : 0);
|
|
38
|
-
return () => clearTimeout(timer);
|
|
19
|
+
setLoading(true);
|
|
20
|
+
setLoadError(null);
|
|
21
|
+
setPage(1);
|
|
22
|
+
setHasMore(true);
|
|
23
|
+
services.fetchMenages({ searchText: searchTerm || undefined, page: 1, pageSize: PAGE_SIZE })
|
|
24
|
+
.then(data => {
|
|
25
|
+
setMenages(data);
|
|
26
|
+
setHasMore(data.length === PAGE_SIZE);
|
|
27
|
+
})
|
|
28
|
+
.catch(() => setLoadError('Erreur lors du chargement des ménages'))
|
|
29
|
+
.finally(() => setLoading(false));
|
|
39
30
|
}, [searchTerm, services]);
|
|
40
31
|
const handleScrollEnd = useCallback(async () => {
|
|
41
32
|
if (!hasMore || loadingMore || loading || !services?.fetchMenages)
|
|
@@ -73,7 +64,7 @@ const MenageInput = ({ variable, value, onChange, error, disabled, onFillFormFro
|
|
|
73
64
|
// NOTE: onFillFormFromMenage n'est pas appelé automatiquement ici
|
|
74
65
|
// pour éviter les re-renders lors de la création d'une nouvelle enquête.
|
|
75
66
|
};
|
|
76
|
-
return (_jsx(SearchableSelect, { options: options, value: selectedOption, onChange: handleChange, placeholder: "S\u00E9lectionner un m\u00E9nage...", searchPlaceholder: "Rechercher un m\u00E9nage...", disabled: disabled, required: variable.estObligatoire, loading: loading, error: loadError || error, formatOptionLabel: (option) => option.designation, noOptionsMessage: loading ? 'Chargement...' : 'Aucun ménage trouvé', onSearchChange: setSearchTerm, onScrollEnd: handleScrollEnd, loadingMore: loadingMore }));
|
|
67
|
+
return (_jsx(SearchableSelect, { options: options, value: selectedOption, onChange: handleChange, placeholder: "S\u00E9lectionner un m\u00E9nage...", searchPlaceholder: "Rechercher un m\u00E9nage...", disabled: disabled, required: variable.estObligatoire, loading: loading, error: loadError || error, formatOptionLabel: (option) => option.designation, noOptionsMessage: loading ? 'Chargement...' : 'Aucun ménage trouvé', onSearchChange: setSearchTerm, onScrollEnd: handleScrollEnd, loadingMore: loadingMore, debounceMs: 300 }));
|
|
77
68
|
};
|
|
78
69
|
export { MenageInput };
|
|
79
70
|
export default MenageInput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RSUInput.d.ts","sourceRoot":"","sources":["../../../src/components/selectors/RSUInput.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEjE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE;YACX,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC;KACH,CAAC;IACF,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,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,QAAQ,CAAC,EAAE;QACT,eAAe,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;KACrE,CAAC;CACH;AAID,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,
|
|
1
|
+
{"version":3,"file":"RSUInput.d.ts","sourceRoot":"","sources":["../../../src/components/selectors/RSUInput.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEjE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE;YACX,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC;KACH,CAAC;IACF,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,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,QAAQ,CAAC,EAAE;QACT,eAAe,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;KACrE,CAAC;CACH;AAID,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAuFrC,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,eAAe,QAAQ,CAAC"}
|
|
@@ -16,25 +16,17 @@ const RSUInput = ({ variable, value, onChange, error, disabled, services }) => {
|
|
|
16
16
|
setLoadError('Service de chargement des structures non disponible');
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
catch {
|
|
31
|
-
setLoadError('Erreur lors du chargement des structures');
|
|
32
|
-
}
|
|
33
|
-
finally {
|
|
34
|
-
setLoading(false);
|
|
35
|
-
}
|
|
36
|
-
}, searchTerm ? 300 : 0);
|
|
37
|
-
return () => clearTimeout(timer);
|
|
19
|
+
setLoading(true);
|
|
20
|
+
setLoadError(null);
|
|
21
|
+
setPage(1);
|
|
22
|
+
setHasMore(true);
|
|
23
|
+
services.fetchStructures({ searchText: searchTerm || undefined, page: 1, pageSize: PAGE_SIZE })
|
|
24
|
+
.then(data => {
|
|
25
|
+
setStructures(data);
|
|
26
|
+
setHasMore(data.length === PAGE_SIZE);
|
|
27
|
+
})
|
|
28
|
+
.catch(() => setLoadError('Erreur lors du chargement des structures'))
|
|
29
|
+
.finally(() => setLoading(false));
|
|
38
30
|
}, [searchTerm, services]);
|
|
39
31
|
const handleScrollEnd = useCallback(async () => {
|
|
40
32
|
if (!hasMore || loadingMore || loading || !services?.fetchStructures)
|
|
@@ -65,7 +57,7 @@ const RSUInput = ({ variable, value, onChange, error, disabled, services }) => {
|
|
|
65
57
|
const newStructureId = option?.id;
|
|
66
58
|
onChange(newStructureId?.toString() || null);
|
|
67
59
|
};
|
|
68
|
-
return (_jsx(SearchableSelect, { options: options, value: selectedOption, onChange: handleChange, placeholder: "S\u00E9lectionner une structure RSU...", searchPlaceholder: "Rechercher une structure...", disabled: disabled, required: variable.estObligatoire, loading: loading, error: loadError || error, formatOptionLabel: (option) => option.designation, noOptionsMessage: loading ? 'Chargement...' : 'Aucune structure trouvée', onSearchChange: setSearchTerm, onScrollEnd: handleScrollEnd, loadingMore: loadingMore }));
|
|
60
|
+
return (_jsx(SearchableSelect, { options: options, value: selectedOption, onChange: handleChange, placeholder: "S\u00E9lectionner une structure RSU...", searchPlaceholder: "Rechercher une structure...", disabled: disabled, required: variable.estObligatoire, loading: loading, error: loadError || error, formatOptionLabel: (option) => option.designation, noOptionsMessage: loading ? 'Chargement...' : 'Aucune structure trouvée', onSearchChange: setSearchTerm, onScrollEnd: handleScrollEnd, loadingMore: loadingMore, debounceMs: 300 }));
|
|
69
61
|
};
|
|
70
62
|
export { RSUInput };
|
|
71
63
|
export default RSUInput;
|
package/dist/types/services.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export interface FormRendererServices {
|
|
|
34
34
|
fetchEnquetes?: (filter?: FetchFilter) => Promise<EnqueteCompletDto[]>;
|
|
35
35
|
fetchEnqueteDonnees?: (enqueteId: number) => Promise<any>;
|
|
36
36
|
fetchStructures?: (filter?: FetchFilter) => Promise<StructureDto[]>;
|
|
37
|
-
fetchGeographicData?: (
|
|
37
|
+
fetchGeographicData?: (entityType: string, parentId?: number, filter?: FetchFilter) => Promise<GeographicItem[]>;
|
|
38
38
|
forceUppercase?: boolean;
|
|
39
39
|
currentUser?: CurrentUserDto;
|
|
40
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/types/services.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAGD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,oBAAoB;IAEnC,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAGrE,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAGvE,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IAG1D,eAAe,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAGpE,mBAAmB,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/types/services.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@rsuci/shared-form-components",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Composants partagés de rendu de formulaires RSU v2 - Package local pour frontend Admin et Public",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"dist",
|
|
9
|
-
"README.md"
|
|
10
|
-
],
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "tsc",
|
|
13
|
-
"watch": "tsc --watch",
|
|
14
|
-
"test": "jest",
|
|
15
|
-
"test:coverage": "jest --coverage"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"rsu",
|
|
19
|
-
"formulaires",
|
|
20
|
-
"enquetes",
|
|
21
|
-
"react",
|
|
22
|
-
"typescript"
|
|
23
|
-
],
|
|
24
|
-
"author": "RSU v2 Architecture Team",
|
|
25
|
-
"license": "MIT",
|
|
26
|
-
"engines": {
|
|
27
|
-
"node": ">=24.0.0",
|
|
28
|
-
"npm": ">=11.0.0"
|
|
29
|
-
},
|
|
30
|
-
"peerDependencies": {
|
|
31
|
-
"lucide-react": "^0.263.0 || ^0.525.0",
|
|
32
|
-
"next": "^14.0.0 || ^15.0.0",
|
|
33
|
-
"react": "^18.0.0 || ^19.0.0",
|
|
34
|
-
"react-dom": "^18.0.0 || ^19.0.0"
|
|
35
|
-
},
|
|
36
|
-
"peerDependenciesMeta": {
|
|
37
|
-
"react-dom": {
|
|
38
|
-
"optional": true
|
|
39
|
-
},
|
|
40
|
-
"next": {
|
|
41
|
-
"optional": true
|
|
42
|
-
},
|
|
43
|
-
"lucide-react": {
|
|
44
|
-
"optional": true
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
"devDependencies": {
|
|
48
|
-
"@testing-library/jest-dom": "^6.0.0",
|
|
49
|
-
"@testing-library/react": "^14.0.0",
|
|
50
|
-
"@types/jest": "^30.0.0",
|
|
51
|
-
"@types/react": "^18.3.0",
|
|
52
|
-
"@types/react-dom": "^18.3.0",
|
|
53
|
-
"jest": "^29.0.0",
|
|
54
|
-
"jest-environment-jsdom": "^29.0.0",
|
|
55
|
-
"ts-jest": "^29.4.6",
|
|
56
|
-
"typescript": "^5.0.0"
|
|
57
|
-
},
|
|
58
|
-
"dependencies": {
|
|
59
|
-
"clsx": "^2.0.0",
|
|
60
|
-
"tailwind-merge": "^2.0.0"
|
|
61
|
-
}
|
|
62
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@rsuci/shared-form-components",
|
|
3
|
+
"version": "1.0.134",
|
|
4
|
+
"description": "Composants partagés de rendu de formulaires RSU v2 - Package local pour frontend Admin et Public",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"watch": "tsc --watch",
|
|
14
|
+
"test": "jest",
|
|
15
|
+
"test:coverage": "jest --coverage"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"rsu",
|
|
19
|
+
"formulaires",
|
|
20
|
+
"enquetes",
|
|
21
|
+
"react",
|
|
22
|
+
"typescript"
|
|
23
|
+
],
|
|
24
|
+
"author": "RSU v2 Architecture Team",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=24.0.0",
|
|
28
|
+
"npm": ">=11.0.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"lucide-react": "^0.263.0 || ^0.525.0",
|
|
32
|
+
"next": "^14.0.0 || ^15.0.0",
|
|
33
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
34
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"react-dom": {
|
|
38
|
+
"optional": true
|
|
39
|
+
},
|
|
40
|
+
"next": {
|
|
41
|
+
"optional": true
|
|
42
|
+
},
|
|
43
|
+
"lucide-react": {
|
|
44
|
+
"optional": true
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@testing-library/jest-dom": "^6.0.0",
|
|
49
|
+
"@testing-library/react": "^14.0.0",
|
|
50
|
+
"@types/jest": "^30.0.0",
|
|
51
|
+
"@types/react": "^18.3.0",
|
|
52
|
+
"@types/react-dom": "^18.3.0",
|
|
53
|
+
"jest": "^29.0.0",
|
|
54
|
+
"jest-environment-jsdom": "^29.0.0",
|
|
55
|
+
"ts-jest": "^29.4.6",
|
|
56
|
+
"typescript": "^5.0.0"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"clsx": "^2.0.0",
|
|
60
|
+
"tailwind-merge": "^2.0.0"
|
|
61
|
+
}
|
|
62
|
+
}
|