--- id: ML-169.10 title: "Fix: Missing optimistic UI for delete operations" status: To Do assignee: [] created_date: "2026-05-19 11:48" labels: - perf - fix - ux dependencies: [] references: - >- backlog/documents/doc-27 - Phase-4-Performance-Audit-Low-Hanging-Fruit-Findings.md modified_files: - lib/music_library_web/live_helpers/index_actions.ex - lib/music_library_web/live/collection_live/show.ex - lib/music_library_web/live/scrobbled_tracks_live/index.ex parent_task_id: ML-169 priority: medium ordinal: 31000 --- ## Description Add optimistic UI for delete operations so the UI removes items immediately without waiting for the database transaction. ## Problem All delete operations wait for the database transaction to complete before updating the UI. `stream_delete` is already used in some places, but the pattern is inconsistent. CollectionLive.Show deletes don't use `stream_delete` at all (they navigate away). ## Files - `lib/music_library_web/live_helpers/index_actions.ex:94-98` — `handle_delete` - `lib/music_library_web/live/collection_live/show.ex:381-385` — `handle_event("delete")` - `lib/music_library_web/live/scrobbled_tracks_live/index.ex:305-310` — `handle_event("delete")` ## Impact Adds unnecessary latency to delete operations that could feel instant. While delete failures are rare, the benefit of snappy UI is worth the minimal risk. ## Fix Use `stream_delete` immediately, then perform the DB operation async. If DB fails, re-insert the item and show error toast. ```elixir def handle_delete(socket, id) do record = Records.get_record!(id) socket = stream_delete(socket, :records, record) Task.start(fn -> Records.delete_record(record) end) {:noreply, socket} end ``` ## Acceptance Criteria - [ ] #1 Delete operations remove items from UI immediately (no DB wait) - [ ] #2 Database delete still executes successfully in background - [ ] #3 If DB delete fails, item is re-inserted into stream and error toast shown - [ ] #4 Existing delete confirmation modal still works correctly - [ ] #5 No orphaned UI state after failed delete