Deploy Ladill Meet / deploy (push) Successful in 42s
Enforce invite-only room access, validate invite emails on create, assign attendee role for listener invitations, and add invite UI on the room show page. Redesign meetings, rooms, conferences, and webinars indexes to match the Events hero, stats cards, and icon list layout. Co-authored-by: Cursor <cursoragent@cursor.com>
74 lines
4.0 KiB
PHP
74 lines
4.0 KiB
PHP
<x-app-layout title="Invitations">
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<h1 class="text-xl font-semibold text-slate-900">Invitations</h1>
|
|
<p class="mt-1 text-sm text-slate-500">{{ $room->title }}</p>
|
|
</div>
|
|
@php
|
|
$backRoute = match (true) {
|
|
$room->isWebinar() => route('meet.webinars.show', $room),
|
|
$room->isConference() => route('meet.conferences.show', $room),
|
|
$room->isSpace() => route('meet.spaces.show', $room),
|
|
default => route('meet.rooms.show', $room),
|
|
};
|
|
$backLabel = match (true) {
|
|
$room->isWebinar() => 'webinar',
|
|
$room->isConference() => 'conference',
|
|
$room->isSpace() => 'room',
|
|
default => 'meeting',
|
|
};
|
|
@endphp
|
|
<a href="{{ $backRoute }}" class="text-sm text-indigo-600 hover:underline">← Back to {{ $backLabel }}</a>
|
|
</div>
|
|
|
|
<div class="mt-6 grid gap-6 lg:grid-cols-2">
|
|
<form method="POST" action="{{ route('meet.invitations.store', $room) }}" class="space-y-4 rounded-2xl border border-slate-200 bg-white p-6">
|
|
@csrf
|
|
<h2 class="font-medium text-slate-900">{{ $room->isSpace() ? 'Invite listeners' : 'Invite people' }}</h2>
|
|
<div>
|
|
<label class="block text-sm text-slate-700">Email addresses</label>
|
|
<textarea name="emails" rows="3" placeholder="{{ $room->isSpace() ? 'listener@example.com, guest@example.com' : 'one@example.com, two@example.com' }}" class="mt-1 w-full rounded-lg border-slate-300 text-sm"></textarea>
|
|
</div>
|
|
@if ($groups->isNotEmpty())
|
|
<div>
|
|
<label class="block text-sm text-slate-700">Contact group</label>
|
|
<select name="contact_group_id" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
|
<option value="">None</option>
|
|
@foreach ($groups as $group)
|
|
<option value="{{ $group->id }}">{{ $group->name }} ({{ $group->members_count }})</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
@endif
|
|
<button type="submit" class="btn-primary">Send invitations</button>
|
|
</form>
|
|
|
|
<form method="POST" action="{{ route('meet.invitations.bulk', $room) }}" enctype="multipart/form-data" class="space-y-4 rounded-2xl border border-slate-200 bg-white p-6">
|
|
@csrf
|
|
<h2 class="font-medium text-slate-900">Bulk import (CSV)</h2>
|
|
<p class="text-sm text-slate-500">Columns: email, name, role</p>
|
|
<input type="file" name="csv" accept=".csv,text/csv" class="text-sm">
|
|
<button type="submit" class="btn-primary">Import CSV</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="mt-6 rounded-2xl border border-slate-200 bg-white">
|
|
<ul class="divide-y divide-slate-100">
|
|
@forelse ($room->invitations as $invitation)
|
|
<li class="flex items-center justify-between px-6 py-4 text-sm">
|
|
<div>
|
|
<p class="font-medium text-slate-900">{{ $invitation->display_name ?? $invitation->email }}</p>
|
|
<p class="text-slate-500">{{ $invitation->email }} · {{ ucfirst($invitation->status) }}</p>
|
|
</div>
|
|
<div class="flex gap-3">
|
|
<form method="POST" action="{{ route('meet.invitations.resend', $invitation) }}">@csrf<button class="text-indigo-600 hover:underline">Resend</button></form>
|
|
<form method="POST" action="{{ route('meet.invitations.destroy', $invitation) }}">@csrf @method('DELETE')<button class="text-red-600 hover:underline">Remove</button></form>
|
|
</div>
|
|
</li>
|
|
@empty
|
|
<li class="px-6 py-8 text-center text-slate-500">No invitations yet.</li>
|
|
@endforelse
|
|
</ul>
|
|
</div>
|
|
</x-app-layout>
|