Standardize settings pages on shared centered card layout.
Deploy Ladill Meet / deploy (push) Successful in 43s

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-05 21:11:45 +00:00
co-authored by Cursor
parent 762aba0246
commit cbbcfbb68b
6 changed files with 190 additions and 142 deletions
@@ -0,0 +1,15 @@
@props(['title' => null, 'description' => null])
<div {{ $attributes->merge(['class' => 'rounded-xl border border-slate-200 bg-white shadow-sm']) }}>
@if ($title)
<div class="border-b border-slate-100 px-6 py-4">
<h2 class="text-base font-semibold text-slate-900">{{ $title }}</h2>
@if ($description)
<p class="mt-1 text-sm text-slate-500">{{ $description }}</p>
@endif
</div>
@endif
<div class="px-6 py-5">
{{ $slot }}
</div>
</div>
@@ -0,0 +1,11 @@
@props(['title' => 'Settings', 'description' => null])
<div {{ $attributes->merge(['class' => 'mx-auto max-w-3xl space-y-6']) }}>
<div>
<h1 class="text-2xl font-semibold text-slate-900">{{ $title }}</h1>
@if ($description)
<p class="mt-1 text-sm text-slate-500">{{ $description }}</p>
@endif
</div>
{{ $slot }}
</div>
@@ -1,13 +1,11 @@
<x-app-layout title="Calendar">
<div class="mx-auto max-w-xl">
<h1 class="text-xl font-semibold text-slate-900">Calendar integration</h1>
<p class="mt-1 text-sm text-slate-600">Sync scheduled meetings to your calendar</p>
<div class="mt-6 space-y-4">
<div class="flex items-center justify-between rounded-2xl border border-slate-200 bg-white p-6">
<x-settings.page title="Calendar integration" description="Sync scheduled meetings to your calendar.">
<x-settings.card title="Connections">
<ul class="space-y-3 text-sm">
<li class="flex flex-wrap items-center justify-between gap-3 rounded-xl border border-slate-100 bg-slate-50 px-4 py-3">
<div>
<h2 class="font-medium">Ladill Mail</h2>
<p class="text-sm text-slate-500">
<p class="font-semibold text-slate-900">Ladill Mail</p>
<p class="mt-0.5 text-slate-600">
@if ($mailConnected)
Connected events sync to your mailbox calendar
@elseif (! $mailConfigured)
@@ -20,29 +18,30 @@
@if ($mailConfigured && ! $mailConnected)
<form method="POST" action="{{ route('meet.settings.calendar.mail') }}">
@csrf
<button type="submit" class="btn-primary">Connect</button>
<button type="submit" class="btn-primary shrink-0 text-sm">Connect</button>
</form>
@endif
</div>
<div class="flex items-center justify-between rounded-2xl border border-slate-200 bg-white p-6">
</li>
<li class="flex flex-wrap items-center justify-between gap-3 rounded-xl border border-slate-100 bg-slate-50 px-4 py-3">
<div>
<h2 class="font-medium">Google Calendar</h2>
<p class="text-sm text-slate-500">{{ $googleConnected ? 'Connected' : 'Not connected' }}</p>
<p class="font-semibold text-slate-900">Google Calendar</p>
<p class="mt-0.5 text-slate-600">{{ $googleConnected ? 'Connected' : 'Not connected' }}</p>
</div>
@if ($googleAuthUrl && ! $googleConnected)
<a href="{{ route('meet.settings.calendar.connect', 'google') }}" class="btn-primary">Connect</a>
<a href="{{ route('meet.settings.calendar.connect', 'google') }}" class="btn-primary shrink-0 text-sm">Connect</a>
@endif
</div>
<div class="flex items-center justify-between rounded-2xl border border-slate-200 bg-white p-6">
</li>
<li class="flex flex-wrap items-center justify-between gap-3 rounded-xl border border-slate-100 bg-slate-50 px-4 py-3">
<div>
<h2 class="font-medium">Microsoft 365</h2>
<p class="text-sm text-slate-500">{{ $microsoftConnected ? 'Connected' : 'Not connected' }}</p>
<p class="font-semibold text-slate-900">Microsoft 365</p>
<p class="mt-0.5 text-slate-600">{{ $microsoftConnected ? 'Connected' : 'Not connected' }}</p>
</div>
@if ($microsoftAuthUrl && ! $microsoftConnected)
<a href="{{ route('meet.settings.calendar.connect', 'microsoft') }}" class="btn-primary">Connect</a>
<a href="{{ route('meet.settings.calendar.connect', 'microsoft') }}" class="btn-primary shrink-0 text-sm">Connect</a>
@endif
</div>
<p class="text-sm text-slate-500">Apple Calendar: use iCal download on each meeting detail page.</p>
</div>
</div>
</li>
</ul>
<p class="mt-4 text-sm text-slate-500">Apple Calendar: use iCal download on each meeting detail page.</p>
</x-settings.card>
</x-settings.page>
</x-app-layout>
+33 -13
View File
@@ -1,10 +1,10 @@
<x-app-layout title="Settings">
<div class="mx-auto max-w-2xl">
<h1 class="text-xl font-semibold text-slate-900">Organization settings</h1>
<form method="POST" action="{{ route('meet.settings.update') }}" enctype="multipart/form-data" class="mt-6 space-y-5 rounded-2xl border border-slate-200 bg-white p-6">
<x-settings.page title="Organization settings">
<form method="POST" action="{{ route('meet.settings.update') }}" enctype="multipart/form-data" class="space-y-6">
@csrf @method('PUT')
<x-settings.card title="Organization" description="Name, type, timezone, and logo for {{ $organization->name }}.">
<div class="space-y-5">
<div>
<label class="block text-sm font-medium text-slate-700">Organization name</label>
<input type="text" name="name" value="{{ old('name', $organization->name) }}" @disabled(! $canManage) required class="mt-1 w-full rounded-lg border-slate-300 text-sm">
@@ -36,21 +36,41 @@
<label class="mt-2 flex items-center gap-2 text-sm"><input type="checkbox" name="remove_logo" value="1"> Remove current logo</label>
@endif
</div>
<button type="submit" class="btn-primary">Save settings</button>
@endif
</div>
</x-settings.card>
</form>
@if ($isAdmin ?? false)
<div class="mt-6 rounded-2xl border border-slate-200 bg-white p-6">
<h2 class="text-sm font-semibold text-slate-900">Advanced</h2>
<ul class="mt-3 space-y-2 text-sm">
<li><a href="{{ route('meet.settings.security') }}" class="text-indigo-600 hover:text-indigo-800">Security policy</a></li>
<li><a href="{{ route('meet.settings.calendar') }}" class="text-indigo-600 hover:text-indigo-800">Calendar connections</a></li>
<li><a href="{{ route('meet.settings.webhooks') }}" class="text-indigo-600 hover:text-indigo-800">Webhooks</a></li>
</ul>
<x-settings.card title="Advanced" description="Security, calendar sync, and webhook integrations.">
<ul class="space-y-3 text-sm">
<li class="flex flex-wrap items-start justify-between gap-3 rounded-xl border border-slate-100 bg-slate-50 px-4 py-3">
<div>
<p class="font-semibold text-slate-900">Security policy</p>
<p class="mt-0.5 text-slate-600">Meeting access rules, recording defaults, and session timeouts.</p>
</div>
<a href="{{ route('meet.settings.security') }}" class="shrink-0 font-semibold text-indigo-600 hover:text-indigo-700">Configure</a>
</li>
<li class="flex flex-wrap items-start justify-between gap-3 rounded-xl border border-slate-100 bg-slate-50 px-4 py-3">
<div>
<p class="font-semibold text-slate-900">Calendar connections</p>
<p class="mt-0.5 text-slate-600">Sync scheduled meetings to Ladill Mail, Google Calendar, or Microsoft 365.</p>
</div>
<a href="{{ route('meet.settings.calendar') }}" class="shrink-0 font-semibold text-indigo-600 hover:text-indigo-700">Manage</a>
</li>
<li class="flex flex-wrap items-start justify-between gap-3 rounded-xl border border-slate-100 bg-slate-50 px-4 py-3">
<div>
<p class="font-semibold text-slate-900">Webhooks</p>
<p class="mt-0.5 text-slate-600">Notify sibling Ladill apps when meetings are created or updated.</p>
</div>
<a href="{{ route('meet.settings.webhooks') }}" class="shrink-0 font-semibold text-indigo-600 hover:text-indigo-700">Manage</a>
</li>
</ul>
</x-settings.card>
@endif
<p class="mt-4 text-sm text-slate-500">{{ $branchCount }} branch(es) configured.</p>
</div>
<p class="text-sm text-slate-500">{{ $branchCount }} branch(es) configured.</p>
</x-settings.page>
</x-app-layout>
@@ -1,10 +1,10 @@
<x-app-layout title="Security settings">
<div class="mx-auto max-w-xl">
<h1 class="text-xl font-semibold text-slate-900">Meeting security</h1>
<p class="mt-1 text-sm text-slate-600">Organization-wide defaults for {{ $organization->name }}</p>
<form method="POST" action="{{ route('meet.settings.security.update') }}" class="mt-6 space-y-4 rounded-2xl border border-slate-200 bg-white p-6">
<x-settings.page title="Meeting security" description="Organization-wide defaults for {{ $organization->name }}.">
<form method="POST" action="{{ route('meet.settings.security.update') }}">
@csrf @method('PUT')
<x-settings.card title="Policy defaults" description="Applied to new meetings unless overridden per meeting.">
<div class="space-y-4">
<label class="flex items-center gap-2 text-sm"><input type="checkbox" name="org_only" value="1" @checked($policy['org_only'] ?? false) class="rounded border-slate-300"> Ladill accounts only</label>
<label class="flex items-center gap-2 text-sm"><input type="checkbox" name="authenticated_only" value="1" @checked($policy['authenticated_only'] ?? false) class="rounded border-slate-300"> Authenticated users only</label>
<label class="flex items-center gap-2 text-sm"><input type="checkbox" name="recording_host_only" value="1" @checked($policy['recording_host_only'] ?? true) class="rounded border-slate-300"> Host-only recording</label>
@@ -17,7 +17,9 @@
<label class="block text-sm font-medium text-slate-700">Session idle timeout (minutes)</label>
<input type="number" name="session_idle_minutes" value="{{ $policy['session_idle_minutes'] ?? 120 }}" min="15" max="480" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
</div>
<button type="submit" class="btn-primary w-full">Save policy</button>
</form>
<button type="submit" class="btn-primary">Save policy</button>
</div>
</x-settings.card>
</form>
</x-settings.page>
</x-app-layout>
@@ -1,9 +1,7 @@
<x-app-layout title="Webhooks">
<div class="mx-auto max-w-xl">
<h1 class="text-xl font-semibold text-slate-900">Webhooks</h1>
<p class="mt-1 text-sm text-slate-600">Notify sibling Ladill apps when meetings change</p>
<form method="POST" action="{{ route('meet.settings.webhooks.store') }}" class="mt-6 space-y-4 rounded-2xl border border-slate-200 bg-white p-6">
<x-settings.page title="Webhooks" description="Notify sibling Ladill apps when meetings change.">
<x-settings.card title="Add endpoint">
<form method="POST" action="{{ route('meet.settings.webhooks.store') }}" class="space-y-4">
@csrf
<div>
<label class="block text-sm font-medium text-slate-700">Endpoint URL</label>
@@ -19,21 +17,24 @@
<label class="flex items-center gap-2 text-sm"><input type="checkbox" name="events[]" value="{{ $event }}" checked class="rounded border-slate-300"> {{ $event }}</label>
@endforeach
</fieldset>
<button type="submit" class="btn-primary w-full">Add endpoint</button>
<button type="submit" class="btn-primary">Add endpoint</button>
</form>
</x-settings.card>
<ul class="mt-6 divide-y divide-slate-100 rounded-2xl border border-slate-200 bg-white">
<x-settings.card title="Configured endpoints">
<ul class="-mx-6 divide-y divide-slate-100">
@forelse ($endpoints as $endpoint)
<li class="flex items-center justify-between px-6 py-4 text-sm">
<div>
<li class="flex items-center justify-between gap-4 px-6 py-4 text-sm">
<div class="min-w-0">
<p class="font-mono text-slate-900">{{ $endpoint->url }}</p>
<p class="text-slate-500">{{ implode(', ', $endpoint->events ?? []) }}</p>
</div>
<form method="POST" action="{{ route('meet.settings.webhooks.destroy', $endpoint) }}">@csrf @method('DELETE')<button class="text-red-600 hover:underline">Remove</button></form>
<form method="POST" action="{{ route('meet.settings.webhooks.destroy', $endpoint) }}">@csrf @method('DELETE')<button type="submit" class="shrink-0 text-red-600 hover:underline">Remove</button></form>
</li>
@empty
<li class="px-6 py-8 text-center text-slate-500">No webhook endpoints configured.</li>
@endforelse
</ul>
</div>
</x-settings.card>
</x-settings.page>
</x-app-layout>