CluPilotCloud/resources/views/components/status/timeline.blade.php

39 lines
2.0 KiB
PHP

@props(['incident'])
{{--
An incident's updates, newest first — the convention every status page
follows, because the thing a reader wants first is how it ended.
Shared between the ongoing block at the top of the page and the archive at
the bottom: the same incident should not look like two different kinds of
record depending on whether it is over.
--}}
@php
$stageTone = [
'investigating' => 'bg-warning-bg text-warning border-warning-border',
'identified' => 'bg-info-bg text-info border-info-border',
'monitoring' => 'bg-info-bg text-info border-info-border',
'resolved' => 'bg-success-bg text-success border-success-border',
];
@endphp
<div class="divide-y divide-line">
@forelse ($incident->updates as $update)
<div class="flex flex-col gap-2 px-6 py-4 sm:flex-row sm:gap-5">
<div class="flex shrink-0 items-center gap-3 sm:w-44 sm:flex-col sm:items-start">
<span class="rounded-pill border px-2.5 py-0.5 font-mono text-[10px] font-medium uppercase tracking-[0.07em] {{ $stageTone[$update->status] ?? $stageTone['investigating'] }}">
{{ __("status.incident.stage.{$update->status}") }}
</span>
<time class="font-mono text-xs text-muted" datetime="{{ $update->created_at->toIso8601String() }}">
{{ $update->created_at->local()->isoFormat('DD.MM. HH:mm') }}
</time>
</div>
{{-- nl2br over a plain string, not raw HTML: an update is typed into
a textarea by an operator under time pressure, and the one page
that has to be trustworthy is not the place to start rendering
whatever was pasted into it. --}}
<p class="text-sm leading-relaxed text-body">{!! nl2br(e($update->body)) !!}</p>
</div>
@empty
<p class="px-6 py-4 text-sm text-muted">{{ __("status.incident.stage.investigating") }}</p>
@endforelse
</div>