@extends('layouts.app') @section('content') @php $albums = \App\Models\Album::query() ->with([ 'artist:id,name', 'sides:id,album_id,side_number,default_play_time_minutes', 'recordRestoreEvents:id,album_id,treated_on', 'treatments:id,album_id,treated_on,treatment_type', 'playLogs:id,album_id,cartridge_id,side_number,play_time_minutes,played_at', 'playLogs.cartridge:id,name,cartridge_type', ]) ->orderBy('title') ->get(); $albumCatalog = $albums->map(fn ($album) => [ 'id' => (int) $album->id, 'artist' => $album->artist?->name, 'title' => $album->title, 'format_size' => $album->format_size, 'play_speed' => (int) $album->play_speed, 'side_count' => (int) $album->side_count, 'storage_location' => $album->storage_location, ])->values(); $albumContexts = $albums->mapWithKeys(function ($album) { $restoreEvents = $album->recordRestoreEvents->sortByDesc('treated_on')->values(); $recordRestoreTreatments = $album->treatments ->where('treatment_type', 'Record Restore') ->sortByDesc('treated_on') ->values(); $lastRecordRestoreDate = collect([ optional($restoreEvents->first()?->treated_on)->toDateString(), optional($recordRestoreTreatments->first()?->treated_on)->toDateString(), ]) ->filter() ->sort() ->last(); $playsSinceLastRestore = $lastRecordRestoreDate ? $album->playLogs ->filter(fn ($playLog) => $playLog->played_at && $playLog->played_at->toDateString() >= $lastRecordRestoreDate) ->count() : $album->playLogs->count(); $needsTreatment = (bool) ($album->needs_treatment ?? false) || $playsSinceLastRestore >= 10; $byCartridge = $album->playLogs ->groupBy(fn ($playLog) => $playLog->cartridge_id ?: 'unknown') ->map(function ($plays, $key) { $first = $plays->first(); $cartridge = $first?->cartridge; return [ 'cartridge_id' => is_numeric($key) ? (int) $key : null, 'cartridge_name' => $cartridge?->name ?? 'Unknown', 'cartridge_type' => $cartridge?->cartridge_type, 'play_count' => $plays->count(), ]; }) ->values() ->all(); return [ (string) $album->id => [ 'album' => [ 'id' => (int) $album->id, 'artist' => $album->artist?->name, 'title' => $album->title, 'format_size' => $album->format_size, 'play_speed' => (int) $album->play_speed, 'side_count' => (int) $album->side_count, 'storage_location' => $album->storage_location, ], 'sides' => $album->sides ->sortBy('side_number') ->values() ->map(fn ($side) => [ 'side_number' => (int) $side->side_number, 'default_play_time_minutes' => $side->default_play_time_minutes !== null ? (float) $side->default_play_time_minutes : null, ]) ->all(), 'record_care' => [ 'relaxed' => !is_null($album->relaxed_date), 'relaxed_date' => $album->relaxed_date?->toDateString(), 'record_restored' => !is_null($lastRecordRestoreDate), 'lastRecordRestoreDate' => $lastRecordRestoreDate, 'last_record_restore_date' => $lastRecordRestoreDate, 'record_restore_count' => $restoreEvents->count() + $recordRestoreTreatments->count(), 'plays_since_last_restore' => $playsSinceLastRestore, 'needs_treatment' => $needsTreatment, ], 'album_usage' => [ 'estimated_prior_plays' => (int) ($album->estimated_prior_plays ?? 0), 'logged_plays' => $album->playLogs->count(), 'total_play_count' => (int) ($album->estimated_prior_plays ?? 0) + $album->playLogs->count(), 'by_cartridge' => $byCartridge, ], ], ]; }); $cartridgeUsageCatalog = \App\Models\Cartridge::query() ->with([ 'tonearm:id,name,turntable_id', 'playLogs.album.sides', 'serviceEvents' => fn ($query) => $query->orderByDesc('serviced_on'), ]) ->orderBy('name') ->get() ->mapWithKeys(function ($cartridge) { $latestService = $cartridge->serviceEvents->first(); $latestServiceDate = $latestService?->serviced_on; $resolveMinutes = function ($playLog) { if (!is_null($playLog->play_time_minutes)) { return (float) $playLog->play_time_minutes; } $side = $playLog->album?->sides?->firstWhere('side_number', $playLog->side_number); return $side && !is_null($side->default_play_time_minutes) ? (float) $side->default_play_time_minutes : 0.0; }; $totalMinutes = $cartridge->playLogs->sum(fn ($playLog) => $resolveMinutes($playLog)); $minutesSinceService = $cartridge->playLogs ->filter(function ($playLog) use ($latestServiceDate) { if (!$latestServiceDate) { return true; } if (!$playLog->played_at) { return false; } return $playLog->played_at >= $latestServiceDate; }) ->sum(fn ($playLog) => $resolveMinutes($playLog)); $threshold = (int) ($cartridge->retip_threshold_hours ?? 1000); $hoursSinceService = round($minutesSinceService / 60, 1); return [ (string) $cartridge->id => [ 'cartridge_id' => (int) $cartridge->id, 'cartridge_name' => $cartridge->name, 'cartridge_type' => $cartridge->cartridge_type, 'playback_role' => $cartridge->playback_role, 'tonearm_id' => $cartridge->tonearm?->id, 'tonearm_name' => $cartridge->tonearm?->name, 'turntable_id' => $cartridge->tonearm?->turntable_id, 'total_minutes' => (int) $totalMinutes, 'total_hours' => round($totalMinutes / 60, 1), 'hours_since_service' => $hoursSinceService, 'service_threshold_hours' => $threshold, 'remaining_hours' => round($threshold - $hoursSinceService, 1), 'last_serviced_on' => $latestServiceDate?->toDateString(), 'last_service_type' => $latestService?->service_type, ], ]; }); $recordRestoreSummary = app(\App\Services\RecordRestoreInventoryService::class)->getSummary(); $recordRestoreSummary['reorder_url'] = $recordRestoreSummary['reorder_url'] ?? 'https://recordrestore.au'; $lastUsedTurntableId = \App\Models\PlayLog::query() ->whereNotNull('turntable_id') ->orderByDesc('played_at') ->orderByDesc('id') ->value('turntable_id'); $turntableCatalog = \App\Models\Turntable::query() ->with([ 'tonearms' => function ($query) { $query->orderBy('name'); }, 'tonearms.cartridge', ]) ->orderByDesc('is_default_selection') ->orderBy('name') ->get() ->map(function ($turntable) { $tonearms = $turntable->tonearms ->map(function ($tonearm) { return [ 'id' => (int) $tonearm->id, 'name' => $tonearm->name, 'role' => $tonearm->role, 'cartridge_id' => $tonearm->cartridge?->id, 'cartridge_name' => $tonearm->cartridge?->name ?? 'No cartridge', 'cartridge_type' => $tonearm->cartridge?->cartridge_type, ]; }) ->values(); return [ 'id' => (int) $turntable->id, 'name' => $turntable->name, 'manufacturer' => $turntable->manufacturer, 'model' => $turntable->model, 'display_name' => trim(collect([$turntable->manufacturer, $turntable->model, $turntable->name])->filter()->join(' • ')), 'is_default_selection' => (bool) $turntable->is_default_selection, 'tonearms' => $tonearms, ]; }) ->filter(fn ($turntable) => count($turntable['tonearms']) > 0) ->values(); @endphp

Play Log Entry

Fast, low-friction play logging with record care visibility, cartridge usage tracking, and system-aware defaults.
Search Artist or Album
No matches found.
Selected Album
Side Played
Record Restore Alert
Only ml of Record Restore remaining.
Reorder Now
@endsection