Add virtual event sessions with Meet sync and platform-billed messaging.
Deploy Ladill Events / deploy (push) Successful in 41s
Deploy Ladill Events / deploy (push) Successful in 41s
Events can define hybrid/virtual sessions synced to Meet rooms; SMS and email use wallet-billed platform APIs instead of Termii and Laravel mail. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -711,6 +711,26 @@
|
||||
<p class="mt-6 text-center text-sm leading-relaxed text-slate-600">{{ $content['description'] }}</p>
|
||||
@endif
|
||||
|
||||
@php
|
||||
$evFormat = $content['format'] ?? 'in_person';
|
||||
$evVirtualSessions = collect($content['virtual_sessions'] ?? [])->filter(fn ($s) => is_array($s) && ! empty($s['join_url']));
|
||||
@endphp
|
||||
@if(in_array($evFormat, ['virtual', 'hybrid'], true) && $evVirtualSessions->isNotEmpty())
|
||||
<div class="mt-6 space-y-3">
|
||||
<h2 class="text-center text-sm font-bold text-slate-900">Virtual sessions</h2>
|
||||
@foreach($evVirtualSessions as $session)
|
||||
<a href="{{ $session['join_url'] }}" target="_blank" rel="noopener"
|
||||
class="block rounded-2xl border border-indigo-100 bg-white px-4 py-3 shadow-sm transition hover:border-indigo-300">
|
||||
<p class="font-semibold text-slate-900">{{ $session['title'] ?? 'Join session' }}</p>
|
||||
@if(!empty($session['scheduled_at']))
|
||||
<p class="mt-1 text-xs text-slate-500">{{ \App\Support\Qr\QrDateFormatter::forDisplay($session['scheduled_at']) }}</p>
|
||||
@endif
|
||||
<p class="mt-2 text-xs font-semibold text-indigo-600">Join virtual session →</p>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(! $evOpen)
|
||||
<div class="mt-6 rounded-2xl border border-amber-200 bg-amber-50 px-5 py-4 text-center text-sm font-medium text-amber-700">{{ $evMode === 'contributions' ? 'Contributions are currently closed.' : 'Registration is currently closed.' }}</div>
|
||||
@else
|
||||
|
||||
@@ -417,6 +417,51 @@
|
||||
</div>
|
||||
<input type="text" name="location" value="{{ old('location') }}" placeholder="Venue / location"
|
||||
class="rounded-xl border border-slate-200 px-3.5 py-2.5 text-sm placeholder:text-slate-400 focus:border-indigo-400 focus:outline-none focus:ring-1 focus:ring-indigo-400/30">
|
||||
|
||||
{{-- Event format + virtual sessions --}}
|
||||
<div x-data="{
|
||||
format: @js(old('format', $ed['format'] ?? 'in_person')),
|
||||
sessions: {{ Illuminate\Support\Js::from(old('virtual_sessions', $ed['virtual_sessions'] ?? [])) }},
|
||||
addSession() { this.sessions.push({ title: '', meet_room_type: 'town_hall', scheduled_at: '', duration_minutes: 60 }); },
|
||||
removeSession(i) { this.sessions.splice(i, 1); }
|
||||
}">
|
||||
<input type="hidden" name="format" :value="format">
|
||||
<p class="mb-2 text-xs font-semibold text-slate-600">Event format</p>
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
@foreach (['in_person' => 'In person', 'virtual' => 'Virtual', 'hybrid' => 'Hybrid'] as $value => $label)
|
||||
<button type="button" @click="format = '{{ $value }}'"
|
||||
:class="format === '{{ $value }}' ? 'border-indigo-500 bg-indigo-50 text-indigo-700' : 'border-slate-200 bg-white text-slate-600'"
|
||||
class="rounded-xl border px-3 py-2 text-xs font-medium">{{ $label }}</button>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div x-show="format === 'virtual' || format === 'hybrid'" x-cloak class="mt-4 space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<p class="text-xs font-semibold text-slate-600">Virtual sessions</p>
|
||||
<button type="button" @click="addSession()" class="text-xs font-semibold text-indigo-600">+ Add session</button>
|
||||
</div>
|
||||
<template x-for="(session, index) in sessions" :key="index">
|
||||
<div class="rounded-xl border border-slate-200 p-3 space-y-2">
|
||||
<input type="hidden" :name="'virtual_sessions[' + index + '][id]'" :value="session.id || ''">
|
||||
<input type="text" :name="'virtual_sessions[' + index + '][title]'" x-model="session.title" placeholder="Session title"
|
||||
class="w-full rounded-lg border border-slate-200 px-3 py-2 text-sm">
|
||||
<div class="grid gap-2 sm:grid-cols-3">
|
||||
<select :name="'virtual_sessions[' + index + '][meet_room_type]'" x-model="session.meet_room_type"
|
||||
class="rounded-lg border border-slate-200 px-3 py-2 text-sm">
|
||||
<option value="town_hall">Conference</option>
|
||||
<option value="webinar">Webinar</option>
|
||||
</select>
|
||||
<input type="date" :name="'virtual_sessions[' + index + '][scheduled_at]'" x-model="session.scheduled_at"
|
||||
class="rounded-lg border border-slate-200 px-3 py-2 text-sm">
|
||||
<input type="number" min="15" max="480" :name="'virtual_sessions[' + index + '][duration_minutes]'" x-model="session.duration_minutes"
|
||||
class="rounded-lg border border-slate-200 px-3 py-2 text-sm" placeholder="Minutes">
|
||||
</div>
|
||||
<button type="button" @click="removeSession(index)" class="text-xs text-red-600">Remove</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-3 sm:grid-cols-2">
|
||||
<input type="text" name="organizer" value="{{ old('organizer', $ed['organizer'] ?? '') }}" placeholder="Organizer name"
|
||||
class="rounded-xl border border-slate-200 px-3.5 py-2.5 text-sm placeholder:text-slate-400 focus:border-indigo-400 focus:outline-none focus:ring-1 focus:ring-indigo-400/30">
|
||||
|
||||
@@ -426,6 +426,52 @@
|
||||
</div>
|
||||
<input type="text" name="location" value="{{ $c['location'] ?? '' }}" placeholder="Venue / location"
|
||||
class="rounded-xl border border-slate-200 px-3.5 py-2.5 text-sm placeholder:text-slate-400 focus:border-indigo-400 focus:outline-none focus:ring-1 focus:ring-indigo-400/30">
|
||||
|
||||
<div x-data="{
|
||||
format: @js(old('format', $c['format'] ?? 'in_person')),
|
||||
sessions: {{ Illuminate\Support\Js::from(old('virtual_sessions', $c['virtual_sessions'] ?? [])) }},
|
||||
addSession() { this.sessions.push({ title: '', meet_room_type: 'town_hall', scheduled_at: '', duration_minutes: 60 }); },
|
||||
removeSession(i) { this.sessions.splice(i, 1); }
|
||||
}">
|
||||
<input type="hidden" name="format" :value="format">
|
||||
<p class="mb-2 text-xs font-semibold text-slate-600">Event format</p>
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
@foreach (['in_person' => 'In person', 'virtual' => 'Virtual', 'hybrid' => 'Hybrid'] as $value => $label)
|
||||
<button type="button" @click="format = '{{ $value }}'"
|
||||
:class="format === '{{ $value }}' ? 'border-indigo-500 bg-indigo-50 text-indigo-700' : 'border-slate-200 bg-white text-slate-600'"
|
||||
class="rounded-xl border px-3 py-2 text-xs font-medium">{{ $label }}</button>
|
||||
@endforeach
|
||||
</div>
|
||||
<div x-show="format === 'virtual' || format === 'hybrid'" x-cloak class="mt-4 space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<p class="text-xs font-semibold text-slate-600">Virtual sessions</p>
|
||||
<button type="button" @click="addSession()" class="text-xs font-semibold text-indigo-600">+ Add session</button>
|
||||
</div>
|
||||
<template x-for="(session, index) in sessions" :key="index">
|
||||
<div class="rounded-xl border border-slate-200 p-3 space-y-2">
|
||||
<input type="hidden" :name="'virtual_sessions[' + index + '][id]'" :value="session.id || ''">
|
||||
<input type="hidden" :name="'virtual_sessions[' + index + '][meet_room_uuid]'" :value="session.meet_room_uuid || ''">
|
||||
<input type="hidden" :name="'virtual_sessions[' + index + '][join_url]'" :value="session.join_url || ''">
|
||||
<input type="text" :name="'virtual_sessions[' + index + '][title]'" x-model="session.title" placeholder="Session title"
|
||||
class="w-full rounded-lg border border-slate-200 px-3 py-2 text-sm">
|
||||
<div class="grid gap-2 sm:grid-cols-3">
|
||||
<select :name="'virtual_sessions[' + index + '][meet_room_type]'" x-model="session.meet_room_type"
|
||||
class="rounded-lg border border-slate-200 px-3 py-2 text-sm">
|
||||
<option value="town_hall">Conference</option>
|
||||
<option value="webinar">Webinar</option>
|
||||
</select>
|
||||
<input type="date" :name="'virtual_sessions[' + index + '][scheduled_at]'" x-model="session.scheduled_at"
|
||||
class="rounded-lg border border-slate-200 px-3 py-2 text-sm">
|
||||
<input type="number" min="15" max="480" :name="'virtual_sessions[' + index + '][duration_minutes]'" x-model="session.duration_minutes"
|
||||
class="rounded-lg border border-slate-200 px-3 py-2 text-sm">
|
||||
</div>
|
||||
<p x-show="session.join_url" class="text-xs text-emerald-700">Join link ready</p>
|
||||
<button type="button" @click="removeSession(index)" class="text-xs text-red-600">Remove</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-3 sm:grid-cols-2">
|
||||
<input type="text" name="organizer" value="{{ $c['organizer'] ?? '' }}" placeholder="Organizer name"
|
||||
class="rounded-xl border border-slate-200 px-3.5 py-2.5 text-sm placeholder:text-slate-400 focus:border-indigo-400 focus:outline-none focus:ring-1 focus:ring-indigo-400/30">
|
||||
|
||||
Reference in New Issue
Block a user