@rsuci/shared-form-components 1.0.78 → 1.0.80

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.
@@ -1 +1 @@
1
- {"version":3,"file":"IdDocInput.d.ts","sourceRoot":"","sources":["../../src/components/IdDocInput.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAKrE,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAuBD,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA8XzC,CAAC;AAEF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"IdDocInput.d.ts","sourceRoot":"","sources":["../../src/components/IdDocInput.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAKrE,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAuBD,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA+XzC,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -63,10 +63,11 @@ const IdDocInput = ({ variable, value, onChange, onBlur, error, disabled }) => {
63
63
  }
64
64
  };
65
65
  }, [stream]);
66
- // Mettre à jour les données
66
+ // Mettre à jour les données (sérialiser en JSON string comme DatePicker le fait pour les dates)
67
67
  const updateData = (updates) => {
68
68
  const newData = { ...currentData, ...updates };
69
- onChange(newData);
69
+ const serializedValue = VariableValueConverter.serialize(newData, variable.typeCode);
70
+ onChange(serializedValue);
70
71
  };
71
72
  // Gérer la sélection de fichier
72
73
  const handleFileSelect = async (event) => {
@@ -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;AAuuBD;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgBpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
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;AA0wBD;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgBpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -29,6 +29,18 @@ const FormRendererInner = () => {
29
29
  const { formulaire, enquete, config, callbacks, services, geographicComponents, navigation, validation, instances, responses, updateResponse, hasUnsavedChanges, isSubmitting, effectiveDisabled, currentGroup, currentInstance, groupesWithInstances } = context;
30
30
  const { mode, features } = config;
31
31
  const labels = config.labels || {};
32
+ // Map de fallback: variableCode → réponse (même stratégie que interpolateVariableLabel)
33
+ // Permet de trouver les réponses dont la clé utilise un suffixe _N (ex: S1_01_1)
34
+ // alors que le rendu cherche par code simple (ex: S1_01)
35
+ const responsesByVariableCode = useMemo(() => {
36
+ const map = new Map();
37
+ Object.values(responses).forEach((response) => {
38
+ if (response?.variableCode && !map.has(response.variableCode)) {
39
+ map.set(response.variableCode, response);
40
+ }
41
+ });
42
+ return map;
43
+ }, [responses]);
32
44
  // État local pour les modals et actions
33
45
  const [showCancelModal, setShowCancelModal] = useState(false);
34
46
  const [showValidationModal, setShowValidationModal] = useState(false);
@@ -118,9 +130,17 @@ const FormRendererInner = () => {
118
130
  }, [currentGroup, getFilteredVariables, isVariableVisible]);
119
131
  // Handler pour le changement de variable
120
132
  const handleVariableChange = useCallback((variable, value) => {
121
- const numeroMembre = currentGroup?.estMultiple
133
+ let numeroMembre = currentGroup?.estMultiple
122
134
  ? currentInstance?.numeroInstance
123
135
  : undefined;
136
+ // Pour les groupes non-multiples, préserver le numeroMembre existant du backend
137
+ // afin que la sauvegarde utilise la même clé que le chargement
138
+ if (numeroMembre === undefined) {
139
+ const existingResponse = responsesByVariableCode.get(variable.code);
140
+ if (existingResponse?.numeroMembre) {
141
+ numeroMembre = existingResponse.numeroMembre;
142
+ }
143
+ }
124
144
  updateResponse(variable.code, value, variable, numeroMembre);
125
145
  // Mettre à jour le contexte du ConditionEngine immédiatement avec la nouvelle valeur
126
146
  // avant de lancer la validation (sinon le contexte est en retard d'un cycle React)
@@ -143,7 +163,7 @@ const FormRendererInner = () => {
143
163
  // Réévaluer les validations des variables dépendantes
144
164
  const groupes = groupesWithInstances.length > 0 ? groupesWithInstances : formulaire?.groupes || [];
145
165
  revalidateDependents(variable.code, groupes, numeroMembre);
146
- }, [currentGroup, currentInstance, updateResponse, conditionEngine, validateConditionVariable, revalidateDependents, groupesWithInstances, formulaire?.groupes]);
166
+ }, [currentGroup, currentInstance, updateResponse, conditionEngine, validateConditionVariable, revalidateDependents, groupesWithInstances, formulaire?.groupes, responsesByVariableCode]);
147
167
  // Handler pour remplir le formulaire depuis les données d'une enquête sélectionnée
148
168
  const handleFillFormFromEnquete = useCallback((enqueteData) => {
149
169
  if (!enqueteData?.reponses)
@@ -364,7 +384,15 @@ const FormRendererInner = () => {
364
384
  const responseKey = currentGroup?.estMultiple && currentInstance?.numeroInstance
365
385
  ? `${variable.code}_${currentInstance.numeroInstance}`
366
386
  : variable.code;
367
- const currentValue = responses[responseKey]?.valeur;
387
+ let currentValue = responses[responseKey]?.valeur;
388
+ // Fallback: si pas trouvé par clé directe, chercher par variableCode
389
+ // (gère les groupes non-multiples où le backend stocke avec numero_membre)
390
+ if (currentValue === undefined) {
391
+ const fallbackResponse = responsesByVariableCode.get(variable.code);
392
+ if (fallbackResponse) {
393
+ currentValue = fallbackResponse.valeur;
394
+ }
395
+ }
368
396
  // Debug log pour tracer le flux de données géographiques
369
397
  if (['DISTRICT', 'REGION', 'DEPARTEMENT', 'SOUSPREFECTURE', 'QUARTIER'].includes(variable.typeCode)) {
370
398
  console.log('[FormRenderer] Variable géographique:', {
@@ -381,7 +409,11 @@ const FormRendererInner = () => {
381
409
  const rosterVariables = (variable.typeCode === 'ROSTERCHECK' || variable.typeCode === 'ROSTERLIST')
382
410
  ? variable.rosterVariables
383
411
  : undefined;
384
- return (_jsx(VariableRenderer, { variable: variable, value: currentValue, onChange: (value) => handleVariableChange(variable, value), disabled: effectiveDisabled, numeroMembre: currentGroup?.estMultiple ? currentInstance?.numeroInstance : undefined, conditionValidationError: getConditionErrorForVariable(variable.code, currentGroup?.estMultiple ? currentInstance?.numeroInstance : undefined), services: services, geographicComponents: geographicComponents, formulaireVariables: formulaire.variables, allResponses: responses, reponses: responses, interpolateVariableLabel: interpolateVariableLabel, rosterVariables: rosterVariables, RosterCheckInput: RosterCheckInput, RosterListInput: RosterListInput, onFillFormFromEnquete: handleFillFormFromEnquete }, variable.id));
412
+ return (_jsx(VariableRenderer, { variable: variable, value: currentValue, onChange: (value) => handleVariableChange(variable, value), disabled: effectiveDisabled, numeroMembre: currentGroup?.estMultiple
413
+ ? currentInstance?.numeroInstance
414
+ : responsesByVariableCode.get(variable.code)?.numeroMembre, conditionValidationError: getConditionErrorForVariable(variable.code, currentGroup?.estMultiple
415
+ ? currentInstance?.numeroInstance
416
+ : responsesByVariableCode.get(variable.code)?.numeroMembre), services: services, geographicComponents: geographicComponents, formulaireVariables: formulaire.variables, allResponses: responses, reponses: responses, interpolateVariableLabel: interpolateVariableLabel, rosterVariables: rosterVariables, RosterCheckInput: RosterCheckInput, RosterListInput: RosterListInput, onFillFormFromEnquete: handleFillFormFromEnquete }, variable.id));
385
417
  }) }), currentGroup?.estMultiple && currentGroup.instances && (_jsx("div", { className: "mt-6 pt-6 border-t", children: _jsx(GroupeInstanceTabs, { groupe: currentGroup, currentInstanceIndex: navigation.navigationState.instanceIndex, responses: responses, onInstanceChange: handleInstanceChange, onInstanceAdded: handleInstanceAdded, onInstanceRemoved: handleInstanceRemoved, disabled: effectiveDisabled }) }))] })] }), _jsx("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 p-4", children: _jsxs("div", { className: "flex flex-wrap justify-between items-center gap-2", children: [_jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsxs("button", { type: "button", onClick: handlePrevious, disabled: navigation.isFirstGroup || (!isConsultationMode && effectiveDisabled), className: `flex items-center px-4 py-2 rounded-lg font-medium transition-colors ${!navigation.isFirstGroup && (isConsultationMode || !effectiveDisabled)
386
418
  ? 'bg-orange-500 text-white hover:bg-orange-600'
387
419
  : 'bg-gray-100 text-gray-400 cursor-not-allowed'}`, children: [_jsx("svg", { className: "h-4 w-4 mr-2", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }), _jsx("span", { className: "hidden sm:inline", children: labels.previousButton || 'Précédent' }), _jsx("span", { className: "sm:hidden", children: "Pr\u00E9c." })] }), mode === 'admin' && features?.saveDraft && callbacks.onSaveDraft && (_jsx("button", { type: "button", onClick: handleSaveDraft, disabled: effectiveDisabled || isSavingDraft || isSubmitting || isSubmittingForm, className: `flex items-center px-4 py-2 rounded-lg font-medium transition-colors ${!effectiveDisabled && !isSavingDraft && !isSubmitting && !isSubmittingForm
@@ -1 +1 @@
1
- {"version":3,"file":"ImageUpload.d.ts","sourceRoot":"","sources":["../../../src/components/wrappers/ImageUpload.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,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,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;YACzB,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;CACpB;AAED,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAiG3C,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC;AACvB,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"ImageUpload.d.ts","sourceRoot":"","sources":["../../../src/components/wrappers/ImageUpload.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,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,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;YACzB,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;CACpB;AAED,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA4G3C,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC;AACvB,eAAe,WAAW,CAAC"}
@@ -7,14 +7,30 @@ const ImageUpload = ({ variable, value, onChange, error, disabled }) => {
7
7
  const [preview, setPreview] = useState(null);
8
8
  const fileInputRef = React.useRef(null);
9
9
  useEffect(() => {
10
- if (value && typeof value === 'object' && value.imageData) {
11
- setPreview(value.imageData);
10
+ if (value) {
11
+ // Gérer les deux formats : objet ou string JSON
12
+ let fileData = value;
13
+ if (typeof value === 'string') {
14
+ try {
15
+ fileData = JSON.parse(value);
16
+ }
17
+ catch {
18
+ fileData = null;
19
+ }
20
+ }
21
+ if (fileData && typeof fileData === 'object' && fileData.imageData) {
22
+ setPreview(fileData.imageData);
23
+ }
24
+ else {
25
+ setPreview(null);
26
+ if (fileInputRef.current)
27
+ fileInputRef.current.value = '';
28
+ }
12
29
  }
13
30
  else {
14
31
  setPreview(null);
15
- if (fileInputRef.current) {
32
+ if (fileInputRef.current)
16
33
  fileInputRef.current.value = '';
17
- }
18
34
  }
19
35
  }, [value]);
20
36
  const handleFileSelect = async (event) => {
@@ -37,14 +53,17 @@ const ImageUpload = ({ variable, value, onChange, error, disabled }) => {
37
53
  }
38
54
  // Convertir en base64
39
55
  const imageData = await VariableValueConverter.fileToBase64(file);
40
- onChange({
56
+ // Sérialiser en JSON string avant d'émettre (comme DatePicker le fait pour les dates)
57
+ const fileData = {
41
58
  imageData,
42
59
  name: file.name,
43
60
  size: file.size,
44
61
  type: file.type,
45
62
  timestamp: new Date(),
46
63
  source: 'upload'
47
- });
64
+ };
65
+ const serializedValue = VariableValueConverter.serialize(fileData, variable.typeCode);
66
+ onChange(serializedValue);
48
67
  };
49
68
  return (_jsxs("div", { className: "space-y-3", children: [_jsx("div", { className: "text-sm text-gray-600 mb-2", children: "\uD83D\uDCC1 Upload d'image uniquement" }), _jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", onChange: handleFileSelect, disabled: disabled, className: `w-full px-3 py-2 border border-dashed rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent text-gray-900 ${error ? 'border-red-500' : 'border-gray-300'} ${disabled ? 'bg-gray-100 cursor-not-allowed text-gray-500' : 'bg-white cursor-pointer hover:border-green-500'}` }), preview && (_jsxs("div", { className: "relative", children: [_jsx("img", { src: preview, alt: "Aper\u00E7u", className: "w-full max-w-xs mx-auto rounded-lg shadow-md" }), _jsx("button", { type: "button", onClick: () => {
50
69
  onChange(null);
@@ -1 +1 @@
1
- {"version":3,"file":"PhotoCapture.d.ts","sourceRoot":"","sources":["../../../src/components/wrappers/PhotoCapture.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,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,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;YACzB,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;CACpB;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAuP7C,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"PhotoCapture.d.ts","sourceRoot":"","sources":["../../../src/components/wrappers/PhotoCapture.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,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,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;YACzB,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;CACpB;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAkQ7C,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,eAAe,YAAY,CAAC"}
@@ -12,14 +12,30 @@ const PhotoCapture = ({ variable, value, onChange, error, disabled }) => {
12
12
  const videoRef = React.useRef(null);
13
13
  const canvasRef = React.useRef(null);
14
14
  useEffect(() => {
15
- if (value && typeof value === 'object' && value.imageData) {
16
- setPreview(value.imageData);
15
+ if (value) {
16
+ // Gérer les deux formats : objet ou string JSON
17
+ let fileData = value;
18
+ if (typeof value === 'string') {
19
+ try {
20
+ fileData = JSON.parse(value);
21
+ }
22
+ catch {
23
+ fileData = null;
24
+ }
25
+ }
26
+ if (fileData && typeof fileData === 'object' && fileData.imageData) {
27
+ setPreview(fileData.imageData);
28
+ }
29
+ else {
30
+ setPreview(null);
31
+ if (fileInputRef.current)
32
+ fileInputRef.current.value = '';
33
+ }
17
34
  }
18
35
  else {
19
36
  setPreview(null);
20
- if (fileInputRef.current) {
37
+ if (fileInputRef.current)
21
38
  fileInputRef.current.value = '';
22
- }
23
39
  }
24
40
  }, [value]);
25
41
  // Nettoyer le stream quand le composant est démonté
@@ -53,14 +69,17 @@ const PhotoCapture = ({ variable, value, onChange, error, disabled }) => {
53
69
  }
54
70
  // Convertir en base64
55
71
  const imageData = await VariableValueConverter.fileToBase64(file);
56
- onChange({
72
+ // Sérialiser en JSON string avant d'émettre (comme DatePicker le fait pour les dates)
73
+ const fileData = {
57
74
  imageData,
58
75
  name: file.name,
59
76
  size: file.size,
60
77
  type: file.type,
61
78
  timestamp: new Date(),
62
79
  source: captureMode === 'camera' ? 'camera' : 'upload'
63
- });
80
+ };
81
+ const serializedValue = VariableValueConverter.serialize(fileData, variable.typeCode);
82
+ onChange(serializedValue);
64
83
  };
65
84
  const startCamera = async () => {
66
85
  if (disabled)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsuci/shared-form-components",
3
- "version": "1.0.78",
3
+ "version": "1.0.80",
4
4
  "description": "Composants partagés de rendu de formulaires RSU v2 - Package local pour frontend Admin et Public",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",