Deploy Ladill Events / deploy (push) Successful in 28s
Proxy registration transaction paths on Events, add a join button on the confirmation page, introduce speaker roster management, and replace the QR design wizard with merchant-style create/show flows. Co-authored-by: Cursor <cursoragent@cursor.com>
128 lines
3.8 KiB
PHP
128 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Events;
|
|
|
|
use App\Models\QrCode;
|
|
use Illuminate\Support\Collection;
|
|
|
|
class EventSpeakerService
|
|
{
|
|
public function __construct(private readonly EventProgrammeService $programmes) {}
|
|
|
|
public function linkedProgramme(QrCode $event): ?QrCode
|
|
{
|
|
if ($event->type !== QrCode::TYPE_EVENT) {
|
|
return null;
|
|
}
|
|
|
|
$programmeId = (int) ($event->content()['programme_qr_id'] ?? 0);
|
|
if ($programmeId <= 0) {
|
|
return null;
|
|
}
|
|
|
|
return QrCode::query()
|
|
->where('id', $programmeId)
|
|
->where('user_id', $event->user_id)
|
|
->where('type', QrCode::TYPE_ITINERARY)
|
|
->first();
|
|
}
|
|
|
|
/** @return list<array{name: string, email: string, role: string, bio: string, source: string}> */
|
|
public function rosterFor(QrCode $event): array
|
|
{
|
|
if ($event->type !== QrCode::TYPE_EVENT) {
|
|
return [];
|
|
}
|
|
|
|
$content = $event->content();
|
|
$roster = [];
|
|
|
|
foreach ((array) ($content['speakers'] ?? []) as $speaker) {
|
|
if (! is_array($speaker)) {
|
|
continue;
|
|
}
|
|
|
|
$name = trim((string) ($speaker['name'] ?? ''));
|
|
if ($name === '') {
|
|
continue;
|
|
}
|
|
|
|
$roster[] = [
|
|
'name' => $name,
|
|
'email' => trim((string) ($speaker['email'] ?? '')),
|
|
'role' => trim((string) ($speaker['role'] ?? '')),
|
|
'bio' => trim((string) ($speaker['bio'] ?? '')),
|
|
'source' => 'roster',
|
|
];
|
|
}
|
|
|
|
foreach ($this->programmeAssignments($event) as $assignment) {
|
|
$name = trim((string) ($assignment['name'] ?? ''));
|
|
if ($name === '') {
|
|
continue;
|
|
}
|
|
|
|
$exists = collect($roster)->contains(fn ($row) => strcasecmp($row['name'], $name) === 0);
|
|
if ($exists) {
|
|
continue;
|
|
}
|
|
|
|
$roster[] = [
|
|
'name' => $name,
|
|
'email' => '',
|
|
'role' => trim((string) ($assignment['session'] ?? '')),
|
|
'bio' => '',
|
|
'source' => 'programme',
|
|
];
|
|
}
|
|
|
|
return $roster;
|
|
}
|
|
|
|
/** @return list<array{name: string, session: string, day: string, time: string}> */
|
|
public function programmeAssignments(QrCode $event): array
|
|
{
|
|
$programme = $this->linkedProgramme($event);
|
|
$snapshot = $this->programmes->snapshot($programme);
|
|
if (! $snapshot) {
|
|
return [];
|
|
}
|
|
|
|
$assignments = [];
|
|
|
|
foreach ((array) ($snapshot['days'] ?? []) as $day) {
|
|
$dayLabel = trim((string) ($day['date'] ?? $day['label'] ?? ''));
|
|
foreach ((array) ($day['items'] ?? []) as $item) {
|
|
if (! is_array($item)) {
|
|
continue;
|
|
}
|
|
|
|
$host = trim((string) ($item['host'] ?? ''));
|
|
if ($host === '') {
|
|
continue;
|
|
}
|
|
|
|
$assignments[] = [
|
|
'name' => $host,
|
|
'session' => trim((string) ($item['title'] ?? '')),
|
|
'day' => $dayLabel,
|
|
'time' => trim((string) ($item['time'] ?? '')),
|
|
];
|
|
}
|
|
}
|
|
|
|
return $assignments;
|
|
}
|
|
|
|
/** @return Collection<int, QrCode> */
|
|
public function eventsForAccount(int $userId, ?string $search = null): Collection
|
|
{
|
|
return QrCode::query()
|
|
->where('user_id', $userId)
|
|
->where('type', QrCode::TYPE_EVENT)
|
|
->when($search !== null && $search !== '', fn ($q) => $q->where('label', 'like', "%{$search}%"))
|
|
->latest()
|
|
->get();
|
|
}
|
|
}
|