@rsuci/shared-form-components 1.0.123 → 1.0.125
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/form-renderer/FormRenderer.d.ts.map +1 -1
- package/dist/components/form-renderer/FormRenderer.js +49 -7
- package/dist/components/form-renderer/GroupeInstanceTabs.d.ts +2 -0
- package/dist/components/form-renderer/GroupeInstanceTabs.d.ts.map +1 -1
- package/dist/components/form-renderer/GroupeInstanceTabs.js +11 -2
- package/dist/hooks/useFormInstances.d.ts.map +1 -1
- package/dist/hooks/useFormInstances.js +48 -35
- package/dist/lib/utils/groupeInstanceManager.d.ts +29 -0
- package/dist/lib/utils/groupeInstanceManager.d.ts.map +1 -1
- package/dist/lib/utils/groupeInstanceManager.js +153 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormRenderer.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/FormRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAA4D,MAAM,OAAO,CAAC;AACjF,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,cAAc,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAuBlF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,yBAAyB;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAClD,oCAAoC;IACpC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,iCAAiC;IACjC,SAAS,EAAE,qBAAqB,CAAC;IACjC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,wCAAwC;IACxC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iCAAiC;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;
|
|
1
|
+
{"version":3,"file":"FormRenderer.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/FormRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAA4D,MAAM,OAAO,CAAC;AACjF,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,cAAc,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAuBlF;;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;AAmkCD;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgBpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -285,8 +285,23 @@ const FormRendererInner = () => {
|
|
|
285
285
|
};
|
|
286
286
|
// Handler pour l'ajout d'instance
|
|
287
287
|
const handleInstanceAdded = (instance, updatedGroupe) => {
|
|
288
|
-
//
|
|
289
|
-
|
|
288
|
+
// Cross-groupe : ajouter l'instance dans tous les groupes liés par la même codeVariable
|
|
289
|
+
const linkedGroups = GroupeInstanceManager.getLinkedGroups(updatedGroupe, instances.groupesWithInstances);
|
|
290
|
+
instances.setGroupesWithInstances(prev => prev.map(g => {
|
|
291
|
+
if (g.code === updatedGroupe.code)
|
|
292
|
+
return updatedGroupe;
|
|
293
|
+
// Ajouter l'instance dans les groupes liés
|
|
294
|
+
const isLinked = linkedGroups.some(lg => lg.code === g.code);
|
|
295
|
+
if (isLinked && g.estMultiple && g.instances) {
|
|
296
|
+
const alreadyExists = g.instances.some(i => i.numeroInstance === instance.numeroInstance);
|
|
297
|
+
if (!alreadyExists) {
|
|
298
|
+
const newInst = GroupeInstanceManager.createInstance(g, instance.numeroInstance);
|
|
299
|
+
const updatedInstances = [...g.instances, newInst];
|
|
300
|
+
return { ...g, instances: updatedInstances, instancesCount: updatedInstances.length };
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return g;
|
|
304
|
+
}));
|
|
290
305
|
navigation.updateTotalInstances(updatedGroupe.instances?.length || 1);
|
|
291
306
|
// Naviguer vers la nouvelle instance
|
|
292
307
|
if (updatedGroupe.instances) {
|
|
@@ -295,10 +310,37 @@ const FormRendererInner = () => {
|
|
|
295
310
|
};
|
|
296
311
|
// Handler pour la suppression d'instance
|
|
297
312
|
const handleInstanceRemoved = (instanceNumber, updatedGroupe, updatedResponses) => {
|
|
313
|
+
// Cross-groupe : supprimer l'instance dans tous les groupes liés + renuméroter
|
|
314
|
+
const originalGroupe = instances.groupesWithInstances.find(g => g.code === updatedGroupe.code);
|
|
315
|
+
const linkedGroups = GroupeInstanceManager.getLinkedGroups((originalGroupe || updatedGroupe), instances.groupesWithInstances);
|
|
316
|
+
let currentResponses = { ...updatedResponses };
|
|
317
|
+
instances.setGroupesWithInstances(prev => prev.map(g => {
|
|
318
|
+
if (g.code === updatedGroupe.code)
|
|
319
|
+
return updatedGroupe;
|
|
320
|
+
// Appliquer la suppression + renumérotation aux groupes liés
|
|
321
|
+
const isLinked = linkedGroups.some(lg => lg.code === g.code);
|
|
322
|
+
if (!isLinked || !g.estMultiple || !g.instances)
|
|
323
|
+
return g;
|
|
324
|
+
const hasInstance = g.instances.some(i => i.numeroInstance === instanceNumber);
|
|
325
|
+
if (!hasInstance)
|
|
326
|
+
return g;
|
|
327
|
+
// Filtrer l'instance supprimée
|
|
328
|
+
const filtered = g.instances.filter(i => i.numeroInstance !== instanceNumber);
|
|
329
|
+
// Nettoyer les réponses de l'instance supprimée pour ce groupe
|
|
330
|
+
const cleaned = {};
|
|
331
|
+
Object.entries(currentResponses).forEach(([key, resp]) => {
|
|
332
|
+
const belongsToGroup = g.variables.some(v => v.code === resp.variableCode);
|
|
333
|
+
if (belongsToGroup && resp.numeroMembre === instanceNumber)
|
|
334
|
+
return;
|
|
335
|
+
cleaned[key] = resp;
|
|
336
|
+
});
|
|
337
|
+
// Renuméroter
|
|
338
|
+
const { reorderedInstances, reorderedResponses } = GroupeInstanceManager.reorderInstances(filtered, cleaned, g);
|
|
339
|
+
currentResponses = reorderedResponses;
|
|
340
|
+
return { ...g, instances: reorderedInstances, instancesCount: reorderedInstances.length };
|
|
341
|
+
}));
|
|
298
342
|
// CRITIQUE : mettre à jour les réponses via l'état React
|
|
299
|
-
context.setResponses(
|
|
300
|
-
// Mettre à jour le groupe via l'état React
|
|
301
|
-
instances.setGroupesWithInstances(prev => prev.map(g => g.code === updatedGroupe.code ? updatedGroupe : g));
|
|
343
|
+
context.setResponses(currentResponses);
|
|
302
344
|
navigation.updateTotalInstances(updatedGroupe.instances?.length || 1);
|
|
303
345
|
// Revenir à la première instance
|
|
304
346
|
navigation.changeInstance(0);
|
|
@@ -625,7 +667,7 @@ const FormRendererInner = () => {
|
|
|
625
667
|
if (!formulaire || !formulaire.groupes || formulaire.groupes.length === 0) {
|
|
626
668
|
return (_jsx("div", { className: "min-h-screen bg-gray-50 flex items-center justify-center", children: _jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 p-8 text-center max-w-md", children: [_jsx("div", { className: "text-red-500 mb-4", children: _jsx("svg", { className: "w-12 h-12 mx-auto", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.268 18.5c-.77.833.192 2.5 1.732 2.5z" }) }) }), _jsx("h3", { className: "text-lg font-medium text-gray-900 mb-2", children: "Formulaire non configur\u00E9" }), _jsx("p", { className: "text-gray-600 mb-4", children: "Ce formulaire ne contient aucun groupe de variables." }), _jsx("button", { onClick: callbacks.onCancel, className: "inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", children: "Retour" })] }) }));
|
|
627
669
|
}
|
|
628
|
-
return (_jsxs("div", { className: "min-h-screen bg-gray-50", children: [_jsxs("div", { className: "max-w-4xl mx-auto px-4 py-6", children: [_jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 p-4 mb-6", children: [_jsx("h1", { className: "text-xl font-semibold text-gray-900 mb-4", children: formulaire.designation }), _jsx(FormProgress, { showPercentage: true })] }), _jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 mb-6", children: [_jsx("div", { className: "bg-green-600 px-6 py-4", children: _jsx("h2", { className: "text-xl font-bold text-white uppercase tracking-wide", children: currentGroup?.designation }) }), _jsxs("div", { className: "p-6", children: [currentGroup?.estMultiple && currentGroup.instances && (_jsx("div", { className: "mb-6", children: _jsx(GroupeInstanceTabs, { groupe: currentGroup, currentInstanceIndex: navigation.navigationState.instanceIndex, responses: responses, onInstanceChange: handleInstanceChange, onInstanceAdded: handleInstanceAdded, onInstanceRemoved: handleInstanceRemoved, disabled: effectiveDisabled }) })), _jsx("div", { className: "space-y-6", children: visibleVariables.map(variable => {
|
|
670
|
+
return (_jsxs("div", { className: "min-h-screen bg-gray-50", children: [_jsxs("div", { className: "max-w-4xl mx-auto px-4 py-6", children: [_jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 p-4 mb-6", children: [_jsx("h1", { className: "text-xl font-semibold text-gray-900 mb-4", children: formulaire.designation }), _jsx(FormProgress, { showPercentage: true })] }), _jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 mb-6", children: [_jsx("div", { className: "bg-green-600 px-6 py-4", children: _jsx("h2", { className: "text-xl font-bold text-white uppercase tracking-wide", children: currentGroup?.designation }) }), _jsxs("div", { className: "p-6", children: [currentGroup?.estMultiple && currentGroup.instances && (_jsx("div", { className: "mb-6", children: _jsx(GroupeInstanceTabs, { groupe: currentGroup, currentInstanceIndex: navigation.navigationState.instanceIndex, responses: responses, onInstanceChange: handleInstanceChange, onInstanceAdded: handleInstanceAdded, onInstanceRemoved: handleInstanceRemoved, disabled: effectiveDisabled, linkedGroups: GroupeInstanceManager.getLinkedGroups(currentGroup, groupesWithInstances) }) })), _jsx("div", { className: "space-y-6", children: visibleVariables.map(variable => {
|
|
629
671
|
const responseKey = currentGroup?.estMultiple && currentInstance?.numeroInstance
|
|
630
672
|
? `${variable.code}_${currentInstance.numeroInstance}`
|
|
631
673
|
: variable.code;
|
|
@@ -647,7 +689,7 @@ const FormRendererInner = () => {
|
|
|
647
689
|
: responsesByVariableCode.get(variable.code)?.numeroMembre, conditionValidationError: getConditionErrorForVariable(variable.code, currentGroup?.estMultiple
|
|
648
690
|
? currentInstance?.numeroInstance
|
|
649
691
|
: responsesByVariableCode.get(variable.code)?.numeroMembre), services: services, geographicComponents: geographicComponents, formulaireVariables: formulaire.variables, formulaireGroupes: groupesWithInstances.length > 0 ? groupesWithInstances : formulaire?.groupes, allResponses: responses, reponses: responses, interpolateVariableLabel: interpolateVariableLabel, rosterVariables: rosterVariables, RosterCheckInput: RosterCheckInput, RosterListInput: RosterListInput, onFillFormFromEnquete: handleFillFormFromEnquete }, variable.id));
|
|
650
|
-
}) }), 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)
|
|
692
|
+
}) }), 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, linkedGroups: GroupeInstanceManager.getLinkedGroups(currentGroup, groupesWithInstances) }) }))] })] }), _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)
|
|
651
693
|
? 'bg-orange-500 text-white hover:bg-orange-600'
|
|
652
694
|
: '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
|
|
653
695
|
? 'bg-yellow-500 text-white hover:bg-yellow-600'
|
|
@@ -12,6 +12,8 @@ export interface GroupeInstanceTabsProps {
|
|
|
12
12
|
onInstanceAdded: (instance: GroupeInstance, updatedGroupe: GroupeFormulaire) => void;
|
|
13
13
|
onInstanceRemoved: (instanceNumber: number, updatedGroupe: GroupeFormulaire, updatedResponses: Record<string, EnqueteReponse>) => void;
|
|
14
14
|
disabled?: boolean;
|
|
15
|
+
/** Groupes liés par la même variable de contrôle (pour warning cross-groupe) */
|
|
16
|
+
linkedGroups?: GroupeFormulaire[];
|
|
15
17
|
}
|
|
16
18
|
declare const GroupeInstanceTabs: React.FC<GroupeInstanceTabsProps>;
|
|
17
19
|
export default GroupeInstanceTabs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GroupeInstanceTabs.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/GroupeInstanceTabs.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIvF,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,gBAAgB,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,gBAAgB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,eAAe,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACrF,iBAAiB,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,IAAI,CAAC;IACvI,QAAQ,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"GroupeInstanceTabs.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/GroupeInstanceTabs.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIvF,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,gBAAgB,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,gBAAgB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,eAAe,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACrF,iBAAiB,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,IAAI,CAAC;IACvI,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gFAAgF;IAChF,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACnC;AAED,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAkRzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -8,7 +8,7 @@ import { useState, useEffect } from 'react';
|
|
|
8
8
|
import { Plus, Minus, AlertTriangle, Check, AlertCircle, AlertTriangle as ExclamationIcon } from 'lucide-react';
|
|
9
9
|
import { GroupeInstanceManager } from '../../lib/utils/groupeInstanceManager';
|
|
10
10
|
import ConfirmationModal from './ConfirmationModal';
|
|
11
|
-
const GroupeInstanceTabs = ({ groupe, currentInstanceIndex, responses, onInstanceChange, onInstanceAdded, onInstanceRemoved, disabled = false }) => {
|
|
11
|
+
const GroupeInstanceTabs = ({ groupe, currentInstanceIndex, responses, onInstanceChange, onInstanceAdded, onInstanceRemoved, disabled = false, linkedGroups }) => {
|
|
12
12
|
const [isProcessing, setIsProcessing] = useState(false);
|
|
13
13
|
const [error, setError] = useState(null);
|
|
14
14
|
const [forceUpdate, setForceUpdate] = useState(0);
|
|
@@ -151,6 +151,15 @@ const GroupeInstanceTabs = ({ groupe, currentInstanceIndex, responses, onInstanc
|
|
|
151
151
|
? 'bg-gray-100 text-gray-400 cursor-not-allowed'
|
|
152
152
|
: 'bg-green-500 text-white hover:bg-green-600 focus:ring-2 focus:ring-green-500 focus:ring-offset-2'}`, title: canAdd.canProceed ? 'Ajouter une instance' : canAdd.constraints[0]?.message, children: _jsx(Plus, { className: "h-4 w-4" }) }), _jsx("button", { type: "button", onClick: handleRemoveInstanceClick, disabled: disabled || isProcessing || !canRemove.canProceed, className: `p-2 rounded-lg transition-colors flex-shrink-0 ${disabled || isProcessing || !canRemove.canProceed
|
|
153
153
|
? 'bg-gray-100 text-gray-400 cursor-not-allowed'
|
|
154
|
-
: 'bg-red-500 text-white hover:bg-red-600 focus:ring-2 focus:ring-red-500 focus:ring-offset-2'}`, title: canRemove.canProceed ? 'Supprimer l\'instance courante' : canRemove.constraints[0]?.message, children: _jsx(Minus, { className: "h-4 w-4" }) }), isProcessing && (_jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2 border-blue-600 flex-shrink-0" }))] })] }), error && (_jsxs("div", { className: "mt-2 p-2 bg-red-50 border border-red-200 rounded-lg shadow-sm", children: [_jsxs("div", { className: "flex items-start space-x-2", children: [_jsx(AlertTriangle, { className: "h-4 w-4 text-red-500 flex-shrink-0 mt-0.5" }), _jsx("div", { className: "text-sm text-red-700", children: error })] }), _jsx("button", { onClick: () => setError(null), className: "absolute top-1 right-1 text-red-400 hover:text-red-600", children: "\u00D7" })] })), showDeleteConfirmation && (
|
|
154
|
+
: 'bg-red-500 text-white hover:bg-red-600 focus:ring-2 focus:ring-red-500 focus:ring-offset-2'}`, title: canRemove.canProceed ? 'Supprimer l\'instance courante' : canRemove.constraints[0]?.message, children: _jsx(Minus, { className: "h-4 w-4" }) }), isProcessing && (_jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2 border-blue-600 flex-shrink-0" }))] })] }), error && (_jsxs("div", { className: "mt-2 p-2 bg-red-50 border border-red-200 rounded-lg shadow-sm", children: [_jsxs("div", { className: "flex items-start space-x-2", children: [_jsx(AlertTriangle, { className: "h-4 w-4 text-red-500 flex-shrink-0 mt-0.5" }), _jsx("div", { className: "text-sm text-red-700", children: error })] }), _jsx("button", { onClick: () => setError(null), className: "absolute top-1 right-1 text-red-400 hover:text-red-600", children: "\u00D7" })] })), showDeleteConfirmation && (() => {
|
|
155
|
+
const instanceNum = groupe.instances?.[currentInstanceIndex]?.numeroInstance || currentInstanceIndex + 1;
|
|
156
|
+
const otherLinkedGroups = linkedGroups?.filter(g => g.code !== groupe.code) || [];
|
|
157
|
+
const hasLinkedGroups = otherLinkedGroups.length > 0;
|
|
158
|
+
const linkedGroupNames = otherLinkedGroups.map(g => g.designation).join(', ');
|
|
159
|
+
const message = hasLinkedGroups
|
|
160
|
+
? `La suppression de l'instance ${instanceNum} va également la supprimer dans les groupes suivants : ${linkedGroupNames}. Les instances restantes seront renumérotées. Cette action est irréversible.`
|
|
161
|
+
: `Êtes-vous sûr de vouloir supprimer l'instance ${instanceNum} ? Cette action est irréversible.`;
|
|
162
|
+
return (_jsx(ConfirmationModal, { isOpen: showDeleteConfirmation, title: "Confirmer la suppression", message: message, confirmText: "Supprimer", cancelText: "Annuler", onConfirm: handleConfirmRemoveInstance, onCancel: handleCancelRemoveInstance, type: "danger" }));
|
|
163
|
+
})()] }));
|
|
155
164
|
};
|
|
156
165
|
export default GroupeInstanceTabs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormInstances.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormInstances.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"useFormInstances.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormInstances.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,7 +33,7 @@ export function useFormInstances(initialGroupes, initialResponses, options = {})
|
|
|
33
33
|
const [groupesWithInstances, setGroupesWithInstances] = useState(() => {
|
|
34
34
|
if (!initialGroupes?.length)
|
|
35
35
|
return [];
|
|
36
|
-
|
|
36
|
+
const initialized = initialGroupes.map(groupe => {
|
|
37
37
|
if (groupe.estMultiple) {
|
|
38
38
|
GroupeInstanceManager.updateGroupeProperties(groupe, initialResponses);
|
|
39
39
|
if (!groupe.instances || groupe.instances.length === 0) {
|
|
@@ -45,6 +45,8 @@ export function useFormInstances(initialGroupes, initialResponses, options = {})
|
|
|
45
45
|
}
|
|
46
46
|
return groupe;
|
|
47
47
|
});
|
|
48
|
+
// Synchroniser le nombre d'instances entre groupes liés (même codeVariable)
|
|
49
|
+
return GroupeInstanceManager.syncLinkedGroupInstances(initialized, initialResponses);
|
|
48
50
|
});
|
|
49
51
|
// Index de l'instance active
|
|
50
52
|
const [currentInstanceIndex, setCurrentInstanceIndex] = useState(0);
|
|
@@ -90,60 +92,71 @@ export function useFormInstances(initialGroupes, initialResponses, options = {})
|
|
|
90
92
|
* Ajouter une instance à un groupe
|
|
91
93
|
*/
|
|
92
94
|
const addInstance = useCallback((groupe, responses) => {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
// Utiliser la version cross-groupe pour synchroniser tous les groupes liés
|
|
96
|
+
const crossResult = GroupeInstanceManager.addInstanceToLinkedGroups(groupe, groupesWithInstances, responses);
|
|
97
|
+
if (crossResult.success && crossResult.updatedGroupes.length > 0) {
|
|
98
|
+
log('Instance ajoutée (cross-groupe):', {
|
|
96
99
|
groupeCode: groupe.code,
|
|
97
|
-
|
|
100
|
+
newInstanceNumber: crossResult.newInstanceNumber,
|
|
101
|
+
linkedGroupsCount: crossResult.updatedGroupes.filter(g => g.estMultiple && g.codeVariable === groupe.codeVariable).length
|
|
98
102
|
});
|
|
99
|
-
|
|
100
|
-
setGroupesWithInstances(prev => {
|
|
101
|
-
const updated = prev.map(g => {
|
|
102
|
-
if (g.code === result.updatedGroupe.code) {
|
|
103
|
-
return result.updatedGroupe;
|
|
104
|
-
}
|
|
105
|
-
return g;
|
|
106
|
-
});
|
|
103
|
+
setGroupesWithInstances(() => {
|
|
107
104
|
if (onGroupesUpdated) {
|
|
108
|
-
onGroupesUpdated(
|
|
105
|
+
onGroupesUpdated(crossResult.updatedGroupes);
|
|
109
106
|
}
|
|
110
|
-
return
|
|
107
|
+
return crossResult.updatedGroupes;
|
|
111
108
|
});
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
// Trouver la nouvelle instance dans le groupe source pour le callback
|
|
110
|
+
const updatedSourceGroupe = crossResult.updatedGroupes.find(g => g.code === groupe.code);
|
|
111
|
+
const newInstance = updatedSourceGroupe?.instances?.find(i => i.numeroInstance === crossResult.newInstanceNumber);
|
|
112
|
+
if (onInstanceAdded && newInstance) {
|
|
113
|
+
onInstanceAdded(newInstance);
|
|
114
114
|
}
|
|
115
|
+
return {
|
|
116
|
+
success: true,
|
|
117
|
+
instance: newInstance,
|
|
118
|
+
updatedGroupe: updatedSourceGroupe
|
|
119
|
+
};
|
|
115
120
|
}
|
|
116
|
-
return
|
|
117
|
-
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
error: crossResult.error || 'Impossible d\'ajouter une instance'
|
|
124
|
+
};
|
|
125
|
+
}, [log, onInstanceAdded, onGroupesUpdated, groupesWithInstances]);
|
|
118
126
|
/**
|
|
119
127
|
* Supprimer une instance d'un groupe
|
|
120
128
|
*/
|
|
121
129
|
const removeInstance = useCallback((groupe, instanceNumber, responses) => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
130
|
+
// Utiliser la version cross-groupe pour synchroniser tous les groupes liés
|
|
131
|
+
const crossResult = GroupeInstanceManager.removeInstanceFromLinkedGroups(groupe, instanceNumber, groupesWithInstances, responses);
|
|
132
|
+
if (crossResult.success) {
|
|
133
|
+
log('Instance supprimée (cross-groupe):', {
|
|
125
134
|
groupeCode: groupe.code,
|
|
126
|
-
instanceNumber
|
|
135
|
+
instanceNumber,
|
|
136
|
+
linkedGroupsCount: GroupeInstanceManager.getLinkedGroups(groupe, groupesWithInstances).length
|
|
127
137
|
});
|
|
128
|
-
|
|
129
|
-
setGroupesWithInstances(prev => {
|
|
130
|
-
const updated = prev.map(g => {
|
|
131
|
-
if (g.code === result.updatedGroupe.code) {
|
|
132
|
-
return result.updatedGroupe;
|
|
133
|
-
}
|
|
134
|
-
return g;
|
|
135
|
-
});
|
|
138
|
+
setGroupesWithInstances(() => {
|
|
136
139
|
if (onGroupesUpdated) {
|
|
137
|
-
onGroupesUpdated(
|
|
140
|
+
onGroupesUpdated(crossResult.updatedGroupes);
|
|
138
141
|
}
|
|
139
|
-
return
|
|
142
|
+
return crossResult.updatedGroupes;
|
|
140
143
|
});
|
|
141
144
|
if (onInstanceRemoved) {
|
|
142
145
|
onInstanceRemoved(instanceNumber);
|
|
143
146
|
}
|
|
147
|
+
// Retourner les réponses mises à jour pour que le parent puisse les appliquer
|
|
148
|
+
const updatedSourceGroupe = crossResult.updatedGroupes.find(g => g.code === groupe.code);
|
|
149
|
+
return {
|
|
150
|
+
success: true,
|
|
151
|
+
updatedGroupe: updatedSourceGroupe,
|
|
152
|
+
updatedResponses: crossResult.updatedResponses
|
|
153
|
+
};
|
|
144
154
|
}
|
|
145
|
-
return
|
|
146
|
-
|
|
155
|
+
return {
|
|
156
|
+
success: false,
|
|
157
|
+
error: crossResult.error || 'Impossible de supprimer cette instance'
|
|
158
|
+
};
|
|
159
|
+
}, [log, onInstanceRemoved, onGroupesUpdated, groupesWithInstances]);
|
|
147
160
|
/**
|
|
148
161
|
* Changer d'instance active
|
|
149
162
|
*/
|
|
@@ -95,5 +95,34 @@ export declare class GroupeInstanceManager {
|
|
|
95
95
|
reorderedInstances: GroupeInstance[];
|
|
96
96
|
reorderedResponses: Record<string, EnqueteReponse>;
|
|
97
97
|
};
|
|
98
|
+
/**
|
|
99
|
+
* Trouve tous les groupes multiples liés par la même codeVariable
|
|
100
|
+
*/
|
|
101
|
+
static getLinkedGroups(groupe: GroupeFormulaire, allGroupes: GroupeFormulaire[]): GroupeFormulaire[];
|
|
102
|
+
/**
|
|
103
|
+
* Ajoute une instance dans TOUS les groupes liés par la même codeVariable
|
|
104
|
+
* Garantit la cohérence du nombre d'instances entre groupes liés
|
|
105
|
+
*/
|
|
106
|
+
static addInstanceToLinkedGroups(groupe: GroupeFormulaire, allGroupes: GroupeFormulaire[], responses: Record<string, EnqueteReponse>): {
|
|
107
|
+
success: boolean;
|
|
108
|
+
updatedGroupes: GroupeFormulaire[];
|
|
109
|
+
newInstanceNumber?: number;
|
|
110
|
+
error?: string;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Supprime une instance dans TOUS les groupes liés + renumérote
|
|
114
|
+
* Garantit la cohérence de la numérotation entre groupes liés
|
|
115
|
+
*/
|
|
116
|
+
static removeInstanceFromLinkedGroups(groupe: GroupeFormulaire, instanceNumber: number, allGroupes: GroupeFormulaire[], responses: Record<string, EnqueteReponse>): {
|
|
117
|
+
success: boolean;
|
|
118
|
+
updatedGroupes: GroupeFormulaire[];
|
|
119
|
+
updatedResponses: Record<string, EnqueteReponse>;
|
|
120
|
+
error?: string;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Synchronise le nombre d'instances entre groupes liés à l'initialisation
|
|
124
|
+
* Les groupes avec moins d'instances reçoivent les instances manquantes
|
|
125
|
+
*/
|
|
126
|
+
static syncLinkedGroupInstances(allGroupes: GroupeFormulaire[], responses: Record<string, EnqueteReponse>): GroupeFormulaire[];
|
|
98
127
|
}
|
|
99
128
|
//# sourceMappingURL=groupeInstanceManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groupeInstanceManager.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/groupeInstanceManager.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"groupeInstanceManager.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/groupeInstanceManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -498,4 +498,157 @@ export class GroupeInstanceManager {
|
|
|
498
498
|
});
|
|
499
499
|
return { reorderedInstances, reorderedResponses };
|
|
500
500
|
}
|
|
501
|
+
// ============ MÉTHODES CROSS-GROUPE ============
|
|
502
|
+
/**
|
|
503
|
+
* Trouve tous les groupes multiples liés par la même codeVariable
|
|
504
|
+
*/
|
|
505
|
+
static getLinkedGroups(groupe, allGroupes) {
|
|
506
|
+
if (!groupe.estMultiple || !groupe.codeVariable)
|
|
507
|
+
return [groupe];
|
|
508
|
+
return allGroupes.filter(g => g.estMultiple && g.codeVariable === groupe.codeVariable);
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Ajoute une instance dans TOUS les groupes liés par la même codeVariable
|
|
512
|
+
* Garantit la cohérence du nombre d'instances entre groupes liés
|
|
513
|
+
*/
|
|
514
|
+
static addInstanceToLinkedGroups(groupe, allGroupes, responses) {
|
|
515
|
+
const linkedGroups = this.getLinkedGroups(groupe, allGroupes);
|
|
516
|
+
// Valider que le groupe source peut ajouter
|
|
517
|
+
const validation = this.canAddInstance(groupe, responses);
|
|
518
|
+
if (!validation.canProceed) {
|
|
519
|
+
return {
|
|
520
|
+
success: false,
|
|
521
|
+
updatedGroupes: [],
|
|
522
|
+
error: validation.constraints[0]?.message || 'Impossible d\'ajouter une instance'
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
// Calculer le prochain numéro d'instance (max de tous les groupes liés + 1)
|
|
526
|
+
let maxInstanceNumber = 0;
|
|
527
|
+
for (const g of linkedGroups) {
|
|
528
|
+
const instances = g.instances || [];
|
|
529
|
+
for (const inst of instances) {
|
|
530
|
+
if (inst.numeroInstance > maxInstanceNumber) {
|
|
531
|
+
maxInstanceNumber = inst.numeroInstance;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
const newInstanceNumber = maxInstanceNumber + 1;
|
|
536
|
+
// Ajouter l'instance dans chaque groupe lié
|
|
537
|
+
const updatedGroupes = allGroupes.map(g => {
|
|
538
|
+
const isLinked = linkedGroups.some(lg => lg.code === g.code);
|
|
539
|
+
if (!isLinked)
|
|
540
|
+
return g;
|
|
541
|
+
const currentInstances = g.instances || [];
|
|
542
|
+
const newInstance = this.createInstance(g, newInstanceNumber);
|
|
543
|
+
const updatedInstances = [...currentInstances, newInstance];
|
|
544
|
+
return {
|
|
545
|
+
...g,
|
|
546
|
+
instances: updatedInstances,
|
|
547
|
+
instancesCount: updatedInstances.length
|
|
548
|
+
};
|
|
549
|
+
});
|
|
550
|
+
return {
|
|
551
|
+
success: true,
|
|
552
|
+
updatedGroupes,
|
|
553
|
+
newInstanceNumber
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Supprime une instance dans TOUS les groupes liés + renumérote
|
|
558
|
+
* Garantit la cohérence de la numérotation entre groupes liés
|
|
559
|
+
*/
|
|
560
|
+
static removeInstanceFromLinkedGroups(groupe, instanceNumber, allGroupes, responses) {
|
|
561
|
+
const linkedGroups = this.getLinkedGroups(groupe, allGroupes);
|
|
562
|
+
// Vérifier qu'au moins une instance reste après suppression
|
|
563
|
+
// (vérifier sur le groupe qui a le moins d'instances)
|
|
564
|
+
const minInstances = Math.min(...linkedGroups.map(g => g.instances?.length || 0));
|
|
565
|
+
if (minInstances <= 1) {
|
|
566
|
+
return {
|
|
567
|
+
success: false,
|
|
568
|
+
updatedGroupes: [],
|
|
569
|
+
updatedResponses: responses,
|
|
570
|
+
error: 'Au moins une instance doit être conservée'
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
// Appliquer la suppression + renumérotation pour chaque groupe lié
|
|
574
|
+
let currentResponses = { ...responses };
|
|
575
|
+
const updatedGroupes = allGroupes.map(g => {
|
|
576
|
+
const isLinked = linkedGroups.some(lg => lg.code === g.code);
|
|
577
|
+
if (!isLinked)
|
|
578
|
+
return g;
|
|
579
|
+
// Si cette instance n'existe pas dans ce groupe, ne rien faire
|
|
580
|
+
const hasInstance = g.instances?.some(i => i.numeroInstance === instanceNumber);
|
|
581
|
+
if (!hasInstance)
|
|
582
|
+
return g;
|
|
583
|
+
// Filtrer l'instance supprimée
|
|
584
|
+
const filteredInstances = (g.instances || []).filter(i => i.numeroInstance !== instanceNumber);
|
|
585
|
+
// Supprimer les réponses de l'instance supprimée pour ce groupe
|
|
586
|
+
const cleanedResponses = {};
|
|
587
|
+
Object.entries(currentResponses).forEach(([key, response]) => {
|
|
588
|
+
const belongsToGroup = g.variables.some(v => v.code === response.variableCode);
|
|
589
|
+
if (belongsToGroup && response.numeroMembre === instanceNumber) {
|
|
590
|
+
return; // Exclure
|
|
591
|
+
}
|
|
592
|
+
cleanedResponses[key] = response;
|
|
593
|
+
});
|
|
594
|
+
// Renuméroter les instances et réponses de ce groupe
|
|
595
|
+
const { reorderedInstances, reorderedResponses } = this.reorderInstances(filteredInstances, cleanedResponses, g);
|
|
596
|
+
// Mettre à jour les réponses courantes pour le prochain groupe
|
|
597
|
+
currentResponses = reorderedResponses;
|
|
598
|
+
return {
|
|
599
|
+
...g,
|
|
600
|
+
instances: reorderedInstances,
|
|
601
|
+
instancesCount: reorderedInstances.length
|
|
602
|
+
};
|
|
603
|
+
});
|
|
604
|
+
return {
|
|
605
|
+
success: true,
|
|
606
|
+
updatedGroupes,
|
|
607
|
+
updatedResponses: currentResponses
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Synchronise le nombre d'instances entre groupes liés à l'initialisation
|
|
612
|
+
* Les groupes avec moins d'instances reçoivent les instances manquantes
|
|
613
|
+
*/
|
|
614
|
+
static syncLinkedGroupInstances(allGroupes, responses) {
|
|
615
|
+
// Grouper par codeVariable
|
|
616
|
+
const groupsByControlVar = new Map();
|
|
617
|
+
for (const g of allGroupes) {
|
|
618
|
+
if (g.estMultiple && g.codeVariable) {
|
|
619
|
+
const existing = groupsByControlVar.get(g.codeVariable) || [];
|
|
620
|
+
existing.push(g);
|
|
621
|
+
groupsByControlVar.set(g.codeVariable, existing);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
// Pour chaque ensemble de groupes liés, synchroniser le nombre d'instances
|
|
625
|
+
const updatedGroupes = [...allGroupes];
|
|
626
|
+
for (const [, linkedGroups] of groupsByControlVar) {
|
|
627
|
+
if (linkedGroups.length <= 1)
|
|
628
|
+
continue;
|
|
629
|
+
// Trouver le max d'instances parmi les groupes liés
|
|
630
|
+
const maxCount = Math.max(...linkedGroups.map(g => g.instances?.length || 0));
|
|
631
|
+
if (maxCount <= 0)
|
|
632
|
+
continue;
|
|
633
|
+
// Ajouter les instances manquantes dans chaque groupe
|
|
634
|
+
for (const g of linkedGroups) {
|
|
635
|
+
const currentCount = g.instances?.length || 0;
|
|
636
|
+
if (currentCount < maxCount) {
|
|
637
|
+
const idx = updatedGroupes.findIndex(ug => ug.code === g.code);
|
|
638
|
+
if (idx === -1)
|
|
639
|
+
continue;
|
|
640
|
+
const instances = [...(updatedGroupes[idx].instances || [])];
|
|
641
|
+
for (let i = currentCount + 1; i <= maxCount; i++) {
|
|
642
|
+
instances.push(this.createInstance(g, i));
|
|
643
|
+
}
|
|
644
|
+
updatedGroupes[idx] = {
|
|
645
|
+
...updatedGroupes[idx],
|
|
646
|
+
instances,
|
|
647
|
+
instancesCount: instances.length
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return updatedGroupes;
|
|
653
|
+
}
|
|
501
654
|
}
|
package/package.json
CHANGED