@extends('layouts.app') @section('content') @php $dirClass = match($r->direction ?? '') { 'OUT' => 'ws-dir-out', 'IN' => 'ws-dir-in', default => 'ws-dir-int' }; $dispClass = match($r->disposition ?? '') { 'ANSWERED' => 'ws-disp-ans', 'NO ANSWER', 'BUSY', 'FAILED' => 'ws-disp-busy', default => 'ws-disp-no' }; $sentClass = match($r->sentiment ?? '') { 'positive' => 'ws-sent-pos', 'negative' => 'ws-sent-neg', default => 'ws-sent-neu' }; $durFmt = gmdate(($r->duration ?? 0) >= 3600 ? 'H:i:s' : 'i:s', (int)($r->duration ?? 0)); $aiTagsArr = $r->ai_tags ? (is_array($r->ai_tags) ? $r->ai_tags : (json_decode((string)$r->ai_tags, true) ?: [])) : []; @endphp {{-- ── BACK NAV ── --}} ← Back to Recordings / {{ Str::limit($filename, 60) }} {{-- ── PAGE HEADER ── --}}
Recording Workspace
{{ $r->direction ?: '—' }} {{ $r->disposition }} @if($r->sentiment) {{ ucfirst($r->sentiment) }} @endif
{{ $r->src_name ? $r->src_name.' ('.$r->src.')' : ($r->src ?? '—') }} → {{ $r->dst_name ? $r->dst_name.' ('.$r->dst.')' : ($r->dst ?? '—') }}
{{ \Illuminate\Support\Carbon::parse($r->calldate)->format('l, d F Y · H:i:s') }}  ·  Ext {{ $r->extension }}@if($r->extension_name) · {{ $r->extension_name }}@endif  ·  {{ $durFmt }}
@canAccess('recordings.email') @endcanAccess
@csrf @method('DELETE')
{{-- ── CALL INFO BAR ── --}}
@php $infoItems = [ 'Date / Time' => \Illuminate\Support\Carbon::parse($r->calldate)->format('Y-m-d H:i:s'), 'Extension' => $r->extension_name ? $r->extension.' · '.$r->extension_name : $r->extension, 'External Number' => $r->direction === 'OUT' ? ($r->dst_name ? $r->dst_name.' ('.$r->dst.')' : ($r->dst ?? '—')) : ($r->src_name ? $r->src_name.' ('.$r->src.')' : ($r->src ?? '—')), 'Duration' => $durFmt, 'Disposition' => $r->disposition, 'Sentiment' => ucfirst($r->sentiment ?? '—'), ]; @endphp @foreach($infoItems as $lbl => $val)
{{ $lbl }}
@if($lbl === 'Disposition') {{ $val }} @elseif($lbl === 'Sentiment' && $r->sentiment) {{ $val }} @else {{ $val }} @endif
@endforeach
@if(!$r->file_exists)
⚠ Audio file not found on disk — playback unavailable.
@endif {{-- ── FULL-WIDTH PLAYER ── --}}
{{ $filename }}
0:00 / 0:00
{{-- ── TWO-COLUMN BODY ── --}}
{{-- LEFT: Transcript / AI Summary / AI Tags ── --}}
{{-- Transcript pane --}}
@if($r->transcript) @php $lines = array_filter(explode("\n", trim((string)$r->transcript))); @endphp
@foreach($lines as $line) @php preg_match('/^\[(\d{2}:\d{2}[\.\d]*)\s*-->\s*[\d:.]+\]\s*(.*)$/', trim($line), $m); $ts = $m[1] ?? null; $text = $m[2] ?? trim($line); $isAgent = str_contains(strtolower($text), 'agent') || str_starts_with($text, 'A:') || str_starts_with($text, 'Agent'); @endphp
{{ $isAgent ? 'Agent' : 'Caller' }} @if($ts)▶ {{ $ts }}@endif
{{ $text }}
@endforeach
+ Edit raw transcript
@else
No transcript yet
Click Transcribe above to generate with Whisper AI.
@endif
{{-- AI Summary pane --}}
@if($r->summary)
AI Generated
{{ $r->summary }}
Edit summary
@else
No AI summary yet
@endif
{{-- AI Tags pane --}}
@forelse($aiTagsArr as $at) {{ $at }} @empty
No AI tags yet.
@endforelse
{{-- RIGHT: AI Summary snippet + Tags + Metadata + Call Details ── --}}
{{-- AI Summary (right sidebar snippet) --}} @if($r->summary)
AI Summary
{{ $r->summary }}
@endif {{-- Tags --}}
Tags
@foreach(array_filter(array_map('trim', explode(',', (string)($r->tags ?? '')))) as $t) {{ $t }} @endforeach
{{-- Metadata Form --}}
Metadata
@csrf
{{-- Call Details --}}
Call Details
@php $details = [ 'Filename' => $filename, 'Call Date' => $r->calldate, 'Source' => $r->src, 'Destination' => $r->dst, 'CallerID' => $r->clid ?? '—', 'Duration' => $durFmt, 'Bil Sec' => ($r->billsec ?? 0).'s', 'Disposition' => $r->disposition, 'Context' => $r->dcontext ?? '—', 'Unique ID' => $r->uniqueid ?? '—', ]; @endphp @foreach($details as $lbl => $val) @endforeach
{{ $lbl }}{{ $val }}
@push('plugin-scripts') @endpush @include('recordings._action_modals') @endsection