Fix modifier champ de type de source : formulaire inline Alpine.js

Le x-data était scopé au bouton seul, rien ne réagissait à open.
- x-data remonté sur le <li> (scope partagé avec le formulaire)
- Formulaire inline avec x-show="open" pour éditer nom/label/type/required/options
- Bouton bascule Modifier ↔ Annuler
- updateField() gère désormais options_raw comme storeField()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-05 19:08:14 +02:00
parent 77dd16143c
commit 156e20c763
2 changed files with 76 additions and 17 deletions
@@ -76,7 +76,15 @@ class SourceTypeController extends Controller
public function updateField(StoreSourceTypeFieldRequest $request, SourceType $sourceType, SourceTypeField $field): RedirectResponse public function updateField(StoreSourceTypeFieldRequest $request, SourceType $sourceType, SourceTypeField $field): RedirectResponse
{ {
abort_if($field->source_type_id !== $sourceType->id, 404); abort_if($field->source_type_id !== $sourceType->id, 404);
$field->update($request->validated()); $data = $request->validated();
if ($request->filled('options_raw')) {
$data['options'] = array_filter(array_map('trim', explode("\n", $request->input('options_raw'))));
} elseif ($request->input('type') !== 'select') {
$data['options'] = null;
}
$field->update($data);
return back()->with('success', 'Champ mis à jour.'); return back()->with('success', 'Champ mis à jour.');
} }
@@ -33,7 +33,13 @@
<ul id="fields-list" class="divide-y divide-gray-100 dark:divide-gray-700"> <ul id="fields-list" class="divide-y divide-gray-100 dark:divide-gray-700">
@foreach($sourceType->fields as $field) @foreach($sourceType->fields as $field)
<li class="px-6 py-3 flex items-center gap-4" data-id="{{ $field->id }}"> <li class="px-6 py-3" data-id="{{ $field->id }}"
x-data="{
open: false,
type: '{{ $field->type->value }}',
optionsRaw: {{ json_encode(collect($field->options ?? [])->join("\n")) }}
}">
<div class="flex items-center gap-4">
<span class="cursor-move text-gray-300 dark:text-gray-600 hover:text-gray-500 select-none"></span> <span class="cursor-move text-gray-300 dark:text-gray-600 hover:text-gray-500 select-none"></span>
<div class="flex-1 grid grid-cols-4 gap-3 text-sm"> <div class="flex-1 grid grid-cols-4 gap-3 text-sm">
<span class="font-mono text-indigo-700">{{ $field->name }}</span> <span class="font-mono text-indigo-700">{{ $field->name }}</span>
@@ -42,16 +48,61 @@
<span class="text-gray-400 dark:text-gray-500">{{ $field->required ? 'Obligatoire' : 'Optionnel' }}</span> <span class="text-gray-400 dark:text-gray-500">{{ $field->required ? 'Obligatoire' : 'Optionnel' }}</span>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<button type="button" <button type="button" @click="open = !open"
x-data="{ open: false }" class="text-xs text-gray-500 dark:text-gray-400 hover:text-indigo-600"
@click="open = !open" x-text="open ? 'Annuler' : 'Modifier'">Modifier</button>
class="text-xs text-gray-500 dark:text-gray-400 hover:text-indigo-600">Modifier</button>
<form method="POST" action="{{ route('admin.source-types.fields.destroy', [$sourceType, $field]) }}" <form method="POST" action="{{ route('admin.source-types.fields.destroy', [$sourceType, $field]) }}"
x-data @submit.prevent="if(confirm('Supprimer ce champ ?')) $el.submit()"> x-data @submit.prevent="if(confirm('Supprimer ce champ ?')) $el.submit()">
@csrf @method('DELETE') @csrf @method('DELETE')
<button type="submit" class="text-xs text-red-500 hover:text-red-700">Supprimer</button> <button type="submit" class="text-xs text-red-500 hover:text-red-700">Supprimer</button>
</form> </form>
</div> </div>
</div>
{{-- Formulaire d'édition inline --}}
<div x-show="open" x-cloak class="mt-3 pl-8 border-t border-gray-100 dark:border-gray-700 pt-3">
<form method="POST" action="{{ route('admin.source-types.fields.update', [$sourceType, $field]) }}">
@csrf @method('PUT')
<div class="grid grid-cols-2 gap-3">
<div>
<label class="block text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">Nom technique</label>
<input type="text" name="name" value="{{ $field->name }}" required
class="block w-full rounded-md border-gray-300 dark:border-gray-600 shadow-sm text-sm focus:border-indigo-500 focus:ring-indigo-500">
</div>
<div>
<label class="block text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">Libellé affiché</label>
<input type="text" name="label" value="{{ $field->label }}" required
class="block w-full rounded-md border-gray-300 dark:border-gray-600 shadow-sm text-sm focus:border-indigo-500 focus:ring-indigo-500">
</div>
<div>
<label class="block text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">Type</label>
<select name="type" x-model="type"
class="block w-full rounded-md border-gray-300 dark:border-gray-600 shadow-sm text-sm focus:border-indigo-500 focus:ring-indigo-500">
@foreach(\App\Enums\FieldType::cases() as $ft)
<option value="{{ $ft->value }}" {{ $field->type->value === $ft->value ? 'selected' : '' }}>{{ $ft->value }}</option>
@endforeach
</select>
<div x-show="type === 'select'" x-cloak class="mt-2">
<label class="block text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">Options (une par ligne)</label>
<textarea name="options_raw" rows="3" x-model="optionsRaw"
class="block w-full rounded-md border-gray-300 dark:border-gray-600 shadow-sm text-sm focus:border-indigo-500 focus:ring-indigo-500"></textarea>
</div>
</div>
<div class="flex items-end">
<label class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300">
<input type="checkbox" name="required" value="1" {{ $field->required ? 'checked' : '' }}
class="rounded border-gray-300 dark:border-gray-600 text-indigo-600 focus:ring-indigo-500">
Champ obligatoire
</label>
</div>
</div>
<div class="mt-3">
<button type="submit" class="px-3 py-1.5 bg-indigo-600 text-white text-xs rounded-md hover:bg-indigo-700">
Enregistrer
</button>
</div>
</form>
</div>
</li> </li>
@endforeach @endforeach
</ul> </ul>