From 119dd20743bba777a131779f7fd22a90005b4a89 Mon Sep 17 00:00:00 2001 From: Myron Blair Date: Mon, 27 Jul 2026 18:28:37 -0500 Subject: [PATCH] Use branded StreamHoard placeholder for missing movie/show artwork AlbumArt was music-only until now; movies and series grids/detail views still showed a broken-image icon when poster_url/backdrop_url was empty. Reused the same component (movies library grid, series grid + resume strip, show detail backdrop, movie detail modal backdrop) instead of duplicating the placeholder logic. --- frontend/src/components/AlbumArt.jsx | 4 ++-- frontend/src/components/MovieCard.jsx | 9 ++------- frontend/src/components/MovieDetailModal.jsx | 7 ++----- frontend/src/pages/ShowDetail.jsx | 3 ++- frontend/src/pages/Shows.jsx | 5 +++-- 5 files changed, 11 insertions(+), 17 deletions(-) diff --git a/frontend/src/components/AlbumArt.jsx b/frontend/src/components/AlbumArt.jsx index 92bb9d7..7f2023f 100644 --- a/frontend/src/components/AlbumArt.jsx +++ b/frontend/src/components/AlbumArt.jsx @@ -1,9 +1,9 @@ // Shows real album art when a URL is available; otherwise a branded placeholder instead of an // empty box. Once musicbrainz enrichment (or a manual edit) sets album_art_url, callers just // pass the new url and this swaps over automatically — no separate "loaded" state to manage. -export default function AlbumArt({ url, size = "lg", className = "" }) { +export default function AlbumArt({ url, size = "lg", className = "", loading }) { if (url) { - return ; + return ; } const small = size === "sm"; return ( diff --git a/frontend/src/components/MovieCard.jsx b/frontend/src/components/MovieCard.jsx index d624513..b06d791 100644 --- a/frontend/src/components/MovieCard.jsx +++ b/frontend/src/components/MovieCard.jsx @@ -1,4 +1,5 @@ import { Play } from "lucide-react"; +import AlbumArt from "./AlbumArt"; export const MovieCard = ({ movie, onClick, progress }) => { const pct = progress?.duration_seconds @@ -10,13 +11,7 @@ export const MovieCard = ({ movie, onClick, progress }) => { className="group relative shrink-0 w-[180px] md:w-[220px] aspect-[2/3] overflow-hidden bg-[#0F0F0F] transition-all duration-300 hover:scale-105 hover:z-10 focus:outline-none focus:ring-2 focus:ring-[#D9381E]" data-testid={`movie-card-${movie.id}`} > - {movie.title} { e.currentTarget.style.opacity = 0.3; }} - /> +

diff --git a/frontend/src/components/MovieDetailModal.jsx b/frontend/src/components/MovieDetailModal.jsx index 01d8b26..65c0945 100644 --- a/frontend/src/components/MovieDetailModal.jsx +++ b/frontend/src/components/MovieDetailModal.jsx @@ -3,6 +3,7 @@ import { useEffect, useState } from "react"; import api from "../lib/api"; import { useNavigate } from "react-router-dom"; import { toast } from "sonner"; +import AlbumArt from "./AlbumArt"; export const MovieDetailModal = ({ movie, open, onClose, onWatchlistChange }) => { const nav = useNavigate(); @@ -64,11 +65,7 @@ export const MovieDetailModal = ({ movie, open, onClose, onWatchlistChange }) =>
- {movie.title} +

diff --git a/frontend/src/pages/ShowDetail.jsx b/frontend/src/pages/ShowDetail.jsx index 6871b2a..3007241 100644 --- a/frontend/src/pages/ShowDetail.jsx +++ b/frontend/src/pages/ShowDetail.jsx @@ -2,6 +2,7 @@ import { useEffect, useState, useMemo } from "react"; import { useParams, useNavigate } from "react-router-dom"; import api from "../lib/api"; import { Play, ArrowLeft } from "lucide-react"; +import AlbumArt from "../components/AlbumArt"; export default function ShowDetail() { const { id } = useParams(); @@ -27,7 +28,7 @@ export default function ShowDetail() { return (
- +