Initial Ladill Frontdesk release with deploy pipeline.
Visitor management app with SSO, kiosk, badges, reports, and Gitea CI deploy to frontdesk.ladill.com. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Organization;
|
||||
use App\Models\Visit;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class IcalFeedController extends Controller
|
||||
{
|
||||
public function __invoke(Request $request, Organization $organization): Response
|
||||
{
|
||||
$owner = (string) $request->query('owner');
|
||||
$token = (string) $request->query('token');
|
||||
|
||||
abort_unless($owner !== '' && $token !== '', 403);
|
||||
abort_unless(
|
||||
hash_equals(
|
||||
hash_hmac('sha256', "{$organization->id}:{$owner}", (string) config('app.key')),
|
||||
$token,
|
||||
),
|
||||
403,
|
||||
);
|
||||
|
||||
abort_unless($organization->owner_ref === $owner, 404);
|
||||
|
||||
$visits = Visit::owned($owner)
|
||||
->where('organization_id', $organization->id)
|
||||
->whereIn('status', [
|
||||
Visit::STATUS_SCHEDULED,
|
||||
Visit::STATUS_EXPECTED,
|
||||
Visit::STATUS_WAITING,
|
||||
])
|
||||
->whereNotNull('scheduled_at')
|
||||
->where('scheduled_at', '>=', now()->subDay())
|
||||
->with(['visitor', 'host'])
|
||||
->orderBy('scheduled_at')
|
||||
->limit(500)
|
||||
->get();
|
||||
|
||||
$lines = [
|
||||
'BEGIN:VCALENDAR',
|
||||
'VERSION:2.0',
|
||||
'PRODID:-//Ladill Frontdesk//EN',
|
||||
'CALSCALE:GREGORIAN',
|
||||
];
|
||||
|
||||
foreach ($visits as $visit) {
|
||||
$start = $visit->scheduled_at->utc()->format('Ymd\THis\Z');
|
||||
$end = $visit->scheduled_at->copy()->addHour()->utc()->format('Ymd\THis\Z');
|
||||
$summary = $this->escape('Visit: '.$visit->visitor->full_name);
|
||||
$description = $this->escape(trim(($visit->purpose ?? '').' Host: '.($visit->host?->name ?? '—')));
|
||||
|
||||
$lines[] = 'BEGIN:VEVENT';
|
||||
$lines[] = 'UID:frontdesk-visit-'.$visit->id.'@ladill.com';
|
||||
$lines[] = 'DTSTAMP:'.now()->utc()->format('Ymd\THis\Z');
|
||||
$lines[] = 'DTSTART:'.$start;
|
||||
$lines[] = 'DTEND:'.$end;
|
||||
$lines[] = 'SUMMARY:'.$summary;
|
||||
$lines[] = 'DESCRIPTION:'.$description;
|
||||
$lines[] = 'END:VEVENT';
|
||||
}
|
||||
|
||||
$lines[] = 'END:VCALENDAR';
|
||||
|
||||
return response(implode("\r\n", $lines), 200, [
|
||||
'Content-Type' => 'text/calendar; charset=utf-8',
|
||||
'Content-Disposition' => 'attachment; filename="frontdesk-visits.ics"',
|
||||
]);
|
||||
}
|
||||
|
||||
protected function escape(string $value): string
|
||||
{
|
||||
return str_replace(["\n", ',', ';'], ['\\n', '\\,', '\\;'], $value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user