# Machine Single Save Button + Link Versioning — Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Replace the machine page's auto-save-on-blur with a single "Enregistrer les modifications" button (matching composant/pièce/produit pages), and add versioning for machine link add/remove operations. **Architecture:** Frontend changes remove all `@blur` save triggers from MachineInfoCard, consolidate saves into a single `submitEdition()` method in the orchestrator composable, and add Save/Cancel buttons at the bottom of the page. MachineInfoCard exposes `saveFieldDefinitions()` via `defineExpose` so the parent can call it during submit. Backend changes extend `MachineAuditSubscriber`'s `onFlush` to detect link entity insertions/deletions and create audit entries on the parent machine. **Tech Stack:** Vue 3 / Nuxt 4, Symfony 8, Doctrine ORM, PHP 8.4 --- ## File Structure | Action | File | Responsibility | |--------|------|----------------| | Modify | `frontend/app/components/machine/MachineInfoCard.vue` | Remove blur-triggered saves, expose saveFieldDefinitions via defineExpose | | Modify | `frontend/app/components/machine/MachineCustomFieldDefEditor.vue` | Remove standalone save button | | Modify | `frontend/app/pages/machine/[id].vue` | Add Save/Cancel buttons, wire submitEdition via template ref | | Modify | `frontend/app/composables/useMachineDetailData.ts` | Add submitEdition, cancelEdition, saving, canSubmit | | Modify | `frontend/app/composables/useMachineDetailUpdates.ts` | Remove auto-save from handleMachineConstructeurChange | | Modify | `frontend/app/composables/useMachineDetailCustomFields.ts` | Add saveAllMachineCustomFields batch method | | Modify | `src/EventSubscriber/MachineAuditSubscriber.php` | Enrich snapshot with links + detect link changes in onFlush | --- ### Task 1: Remove blur-triggered saves from MachineInfoCard **Files:** - Modify: `frontend/app/components/machine/MachineInfoCard.vue` - [ ] **Step 1: Remove `@blur` from name input (line 17)** Replace: ```vue @input="$emit('update:machine-name', ($event.target as HTMLInputElement).value)" @blur="$emit('blur-field')" ``` With: ```vue @input="$emit('update:machine-name', ($event.target as HTMLInputElement).value)" ``` - [ ] **Step 2: Remove `$emit('blur-field')` from site select (line 31)** Replace: ```vue @change="$emit('update:machine-site-id', ($event.target as HTMLSelectElement).value); $emit('blur-field')" ``` With: ```vue @change="$emit('update:machine-site-id', ($event.target as HTMLSelectElement).value)" ``` - [ ] **Step 3: Remove `@blur` from reference input (line 57)** Replace: ```vue @input="$emit('update:machine-reference', ($event.target as HTMLInputElement).value)" @blur="$emit('blur-field')" ``` With: ```vue @input="$emit('update:machine-reference', ($event.target as HTMLInputElement).value)" ``` - [ ] **Step 4: Remove `@blur` from all custom field inputs** For each custom field input, remove the `@blur="$emit('update-custom-field', field)"` line: - text input (line 118) - number input (line 127) - select (line 135) - boolean checkbox (line 152) - date input (line 163) - [ ] **Step 5: Remove `@save` handler from MachineCustomFieldDefEditor usage (line 187)** Replace: ```vue ``` With: ```vue ``` - [ ] **Step 6: Remove unused emit declarations and add defineExpose** Replace the `defineEmits` block (lines 222-231): ```ts const emit = defineEmits<{ 'update:machine-name': [value: string] 'update:machine-reference': [value: string] 'update:machine-site-id': [value: string] 'update:constructeur-ids': [ids: unknown] 'blur-field': [] 'set-custom-field-value': [field: any, value: unknown] 'update-custom-field': [field: any] 'custom-fields-saved': [] }>() ``` With: ```ts const emit = defineEmits<{ 'update:machine-name': [value: string] 'update:machine-reference': [value: string] 'update:machine-site-id': [value: string] 'update:constructeur-ids': [ids: unknown] 'set-custom-field-value': [field: any, value: unknown] 'custom-fields-saved': [] }>() ``` Then, at the end of the `