whereIn('transcription_status', ['pending', 'processing']) ->orderBy('id') ->each(fn (Recording $recording) => $recording->recoverOrphanedTranscription()); $query = Recording::query()->latest(); if ($search = $request->string('q')->trim()->toString()) { $query->search($search); } $recordings = $query->paginate(20)->withQueryString(); return view('recordings.index', [ 'recordings' => $recordings, 'search' => $search ?? '', ]); } /** * Show the upload form. */ public function create(): View { return view('recordings.create'); } /** * Store a newly uploaded recording. */ public function store(StoreRecordingRequest $request, Mp3MetadataService $metadata): RedirectResponse { $file = $request->file('audio'); $path = $file->store('recordings', 'local'); $absolutePath = Storage::disk('local')->path($path); $tags = $metadata->extract($absolutePath); $title = $request->string('title')->trim()->toString() ?: ($tags['title'] ?? pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME)); $recording = Recording::create([ 'title' => $title, 'original_filename' => $file->getClientOriginalName(), 'file_path' => $path, 'duration_seconds' => $tags['duration_seconds'], 'recorded_at' => $tags['recorded_at'], 'artist' => $tags['artist'], 'album' => $tags['album'], 'file_size_bytes' => $file->getSize() ?: 0, 'transcription_status' => 'pending', ]); return redirect() ->route('recordings.show', $recording) ->with('success', 'Recording uploaded successfully.'); } /** * Display the specified recording. */ public function show(Recording $recording): View { $recording->recoverOrphanedTranscription(); $recording->refresh(); return view('recordings.show', compact('recording')); } /** * Remove the specified recording. */ public function destroy(Recording $recording): RedirectResponse { $recording->deleteFile(); $recording->delete(); return redirect() ->route('recordings.index') ->with('success', 'Recording deleted.'); } }