fix(faq): toggle worked server-side but click did nothing — nested forms

Filament pages wrap their content in an outer <form>. My inline
<form method="POST"> for the hint toggle + reset was nested inside
that outer form — invalid HTML, so browsers dropped my submit and
either did nothing or ran the outer Livewire form's handler.

Replaced both forms with plain <button type="button"> + onclick
fetch() POST + window.location.reload(). Controller now also returns
JSON when Accept: application/json (fetch sends that) instead of a
back() redirect.

The server-side flip was always correct — verified via a Feature
test that posts to /app/hints/toggle and asserts the user column
flipped from true → false.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-01 11:04:24 +00:00
parent 6dba81502b
commit 346fcf968f
2 changed files with 33 additions and 16 deletions
+6
View File
@@ -26,6 +26,9 @@ class HintController extends Controller
abort_unless($user, 401); abort_unless($user, 401);
$user->hints_enabled = ! $user->hints_enabled; $user->hints_enabled = ! $user->hints_enabled;
$user->save(); $user->save();
if ($request->expectsJson()) {
return response()->json(['ok' => true, 'hints_enabled' => (bool) $user->hints_enabled]);
}
return back(); return back();
} }
@@ -37,6 +40,9 @@ class HintController extends Controller
$user->dismissed_hints = []; $user->dismissed_hints = [];
$user->hints_enabled = true; $user->hints_enabled = true;
$user->save(); $user->save();
if ($request->expectsJson()) {
return response()->json(['ok' => true]);
}
return back(); return back();
} }
} }
@@ -306,23 +306,34 @@
<input type="text" class="faq-search" placeholder="{{ __('Caută în ghid...') }}" wire:model.live.debounce.300ms="search"> <input type="text" class="faq-search" placeholder="{{ __('Caută în ghid...') }}" wire:model.live.debounce.300ms="search">
<div class="faq-toggle"> <div class="faq-toggle">
<span class="faq-toggle-lbl">{{ __('Sugestii „?" pe pagini:') }}</span> <span class="faq-toggle-lbl">{{ __('Sugestii „?" pe pagini:') }}</span>
<form method="POST" action="{{ route('hints.toggle') }}" style="display:inline-flex;align-items:center;"> <button type="button"
@csrf class="faq-switch {{ $user?->hints_enabled ? 'on' : 'off' }}"
<button type="submit" class="faq-switch {{ $user?->hints_enabled ? 'on' : 'off' }}" title="{{ $user?->hints_enabled ? __('Click pentru a DEZACTIVA') : __('Click pentru a ACTIVA') }}"
title="{{ $user?->hints_enabled ? __('Click pentru a DEZACTIVA') : __('Click pentru a ACTIVA') }}" aria-label="{{ __('Toggle hints') }}"
aria-label="{{ __('Toggle hints') }}"> onclick="faqPostAction('{{ route('hints.toggle') }}')"></button>
</button> <span class="faq-switch-lbl {{ $user?->hints_enabled ? 'on' : 'off' }}">
<span class="faq-switch-lbl {{ $user?->hints_enabled ? 'on' : 'off' }}"> {{ $user?->hints_enabled ? __('ACTIVE') : __('DEZACTIV') }}
{{ $user?->hints_enabled ? __('ACTIVE') : __('DEZACTIV') }} </span>
</span> <button type="button"
</form> class="faq-btn-reset"
<form method="POST" action="{{ route('hints.reset') }}" style="display:inline;"> title="{{ __('Aduce înapoi hint-urile ascunse') }}"
@csrf onclick="faqPostAction('{{ route('hints.reset') }}')">
<button type="submit" class="faq-btn-reset" title="{{ __('Aduce înapoi hint-urile ascunse') }}"> {{ __('Resetează') }}
{{ __('Resetează') }} </button>
</button>
</form>
</div> </div>
<script>
function faqPostAction(url) {
fetch(url, {
method: 'POST',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
credentials: 'same-origin',
}).then(() => window.location.reload()).catch(() => window.location.reload());
}
</script>
</div> </div>
{{-- GRID --}} {{-- GRID --}}