Files
2026-07-27 14:17:30 +01:00

58 lines
5.9 KiB
PHP

<x-layouts.app :title="isset($record) ? __('Edit menu') : __('Create menu')">
@php($initialItems = old('items_json', json_encode($record->items ?? [], JSON_UNESCAPED_SLASHES)))
<div class="mx-auto max-w-6xl space-y-6" x-data="menuEditor(@js(json_decode($initialItems ?: '[]', true) ?: []))">
<div>
<p class="text-sm font-medium text-orange-600">Reusable navigation</p>
<h1 class="text-3xl font-semibold">{{ isset($record) ? 'Edit' : 'Create' }} menu</h1>
<p class="mt-2 text-sm text-zinc-500">Edit links once. Every header and footer assigned to this menu location updates automatically.</p>
</div>
<form method="POST" action="{{ isset($record) ? route('administration.menus.update', $record) : route('administration.menus.store') }}" class="space-y-6">
@csrf
@isset($record) @method('PUT') @endisset
<section class="grid gap-5 rounded-2xl border border-zinc-200 bg-white p-6 shadow-sm md:grid-cols-2 dark:border-zinc-700 dark:bg-zinc-900">
<label class="block"><span class="text-sm font-medium">Menu name</span><input type="text" name="name" value="{{ old('name', $record->name ?? '') }}" required class="mt-2 w-full rounded-xl border-zinc-300 dark:border-zinc-700 dark:bg-zinc-950"></label>
<label class="block"><span class="text-sm font-medium">Menu location</span><select name="location" required class="mt-2 w-full rounded-xl border-zinc-300 dark:border-zinc-700 dark:bg-zinc-950">@foreach($locations as $value => $label)<option value="{{ $value }}" @selected(old('location', $record->location ?? 'primary') === $value)>{{ $label }}</option>@endforeach</select></label>
<label class="flex items-center gap-3 md:col-span-2"><input type="checkbox" name="enabled" value="1" @checked(old('enabled', $record->enabled ?? true)) class="rounded"><span class="font-medium">Menu enabled</span></label>
</section>
<section class="rounded-2xl border border-zinc-200 bg-white p-6 shadow-sm dark:border-zinc-700 dark:bg-zinc-900">
<div class="mb-5 flex items-center justify-between gap-4"><div><h2 class="text-lg font-semibold">Menu items</h2><p class="text-sm text-zinc-500">Relative paths such as <code>/blog</code>, anchors and full external URLs are supported.</p></div><button type="button" @click="addItem()" class="rounded-lg bg-zinc-900 px-4 py-2 text-sm font-medium text-white dark:bg-white dark:text-zinc-900">Add link</button></div>
<input type="hidden" name="items_json" :value="JSON.stringify(items)">
@error('items_json')<p class="mb-4 text-sm text-red-600">{{ $message }}</p>@enderror
<div class="space-y-4">
<template x-for="(item, index) in items" :key="item._key">
<article class="rounded-xl border border-zinc-200 p-5 dark:border-zinc-700">
<div class="mb-4 flex flex-wrap items-center justify-between gap-3"><strong x-text="item.label || `Link ${index + 1}`"></strong><div class="flex gap-2"><button type="button" @click="move(index,-1)" :disabled="index===0" class="rounded border px-3 py-1 disabled:opacity-30">↑</button><button type="button" @click="move(index,1)" :disabled="index===items.length-1" class="rounded border px-3 py-1 disabled:opacity-30">↓</button><button type="button" @click="removeItem(index)" class="rounded border border-red-400 px-3 py-1 text-red-600">Remove</button></div></div>
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
<label><span class="text-sm font-medium">Label</span><input type="text" x-model="item.label" class="mt-2 w-full rounded-lg border-zinc-300 dark:border-zinc-700 dark:bg-zinc-950"></label>
<label class="lg:col-span-2"><span class="text-sm font-medium">URL or path</span><input type="text" x-model="item.url" placeholder="/, /blog, #contact or https://…" class="mt-2 w-full rounded-lg border-zinc-300 dark:border-zinc-700 dark:bg-zinc-950"></label>
<label><span class="text-sm font-medium">Open in</span><select x-model="item.target" class="mt-2 w-full rounded-lg border-zinc-300 dark:border-zinc-700 dark:bg-zinc-950"><option value="">Same window</option><option value="_blank">New window</option></select></label>
<label class="flex items-center gap-3"><input type="checkbox" x-model="item.enabled" class="rounded"><span class="text-sm font-medium">Visible</span></label>
</div>
</article>
</template>
<div x-show="items.length===0" class="rounded-xl border border-dashed border-zinc-300 p-10 text-center text-sm text-zinc-500 dark:border-zinc-700">This menu has no links. Add the first link above.</div>
</div>
</section>
<div class="flex justify-end gap-3"><a href="{{ route('administration.menus.index') }}" class="rounded-lg border px-4 py-2">Cancel</a><flux:button type="submit" variant="primary">Save menu</flux:button></div>
</form>
</div>
@push('scripts')
<script>
function menuEditor(initialItems) {
return {
items: (initialItems || []).map(item => ({_key: crypto.randomUUID(), enabled: item.enabled !== false, label: item.label || '', url: item.url || '', target: item.target || ''})),
addItem() { this.items.push({_key: crypto.randomUUID(), enabled: true, label: 'New link', url: '/', target: ''}); },
removeItem(index) { if (confirm('Remove this menu item?')) this.items.splice(index, 1); },
move(index, direction) { const target=index+direction; if(target<0||target>=this.items.length)return; [this.items[index],this.items[target]]=[this.items[target],this.items[index]]; },
};
}
</script>
@endpush
</x-layouts.app>