fix: media – FSK alle Einträge, Duplikate, Jahres-Filter, xREL Response-Struktur, xREL-Cover-Badge
This commit is contained in:
@@ -136,10 +136,11 @@ export default function Media({ toast, mobile }) {
|
||||
}
|
||||
|
||||
// ── Film-Karte ────────────────────────────────────────────────────────────────
|
||||
function MovieCard({ movie, favIds, onToggleFav, onOpenModal }) {
|
||||
const isFav = favIds.has(movie.id);
|
||||
const isTop = movie.rank != null && movie.rank <= 10;
|
||||
function MovieCard({ movie, favIds, xrelIds, onToggleFav, onOpenModal }) {
|
||||
const isFav = favIds.has(movie.id);
|
||||
const isTop = movie.rank != null && movie.rank <= 10;
|
||||
const fskStyle = FSK_COLOR(movie.fsk);
|
||||
const hasXrel = xrelIds?.has(movie.id);
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
@@ -177,6 +178,14 @@ function MovieCard({ movie, favIds, onToggleFav, onOpenModal }) {
|
||||
{movie.fsk}
|
||||
</div>
|
||||
)}
|
||||
{/* xREL-Badge */}
|
||||
{hasXrel && (
|
||||
<div style={{ position:'absolute', bottom:6, right:6, background:'rgba(78,205,196,0.9)',
|
||||
borderRadius:4, padding:'1px 5px', fontSize:9, color:'#000',
|
||||
fontWeight:900, fontFamily:"'Space Mono',monospace", lineHeight:1.5 }}>
|
||||
xREL
|
||||
</div>
|
||||
)}
|
||||
{/* Fav */}
|
||||
<button onClick={e => { e.stopPropagation(); onToggleFav(movie, isFav); }} style={{
|
||||
position:'absolute', top:5, right:5, background:'rgba(0,0,0,0.65)',
|
||||
@@ -241,14 +250,27 @@ function useFavIds() {
|
||||
|
||||
// ── Kino Grid – alle laufenden Filme ─────────────────────────────────────────
|
||||
function KinoGrid({ onOpenModal }) {
|
||||
const [movies, setMovies] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState('');
|
||||
const [favIds, toggleFav] = useFavIds();
|
||||
const [movies, setMovies] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState('');
|
||||
const [xrelIds, setXrelIds] = useState(new Set());
|
||||
const [favIds, toggleFav] = useFavIds();
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true); setError('');
|
||||
api('/tools/media/now-playing').then(setMovies).catch(e => setError(e.message)).finally(() => setLoading(false));
|
||||
api('/tools/media/now-playing')
|
||||
.then(list => {
|
||||
setMovies(list);
|
||||
// xREL-Batch-Check nach Laden
|
||||
api('/tools/media/xrel-check', {
|
||||
method: 'POST',
|
||||
body: { movies: list.map(m => ({ id: m.id, title: m.title, original_title: m.original_title, release_date: m.release_date })) }
|
||||
}).then(result => {
|
||||
setXrelIds(new Set(Object.entries(result).filter(([,v]) => v).map(([k]) => Number(k))));
|
||||
}).catch(() => {});
|
||||
})
|
||||
.catch(e => setError(e.message))
|
||||
.finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
const onToggle = async (movie, isFav) => {
|
||||
@@ -268,7 +290,7 @@ function KinoGrid({ onOpenModal }) {
|
||||
<>
|
||||
<div style={{ ...S.head, marginBottom:12 }}>★ TOP 10 – MEISTGESEHEN</div>
|
||||
<div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(130px,1fr))', gap:12, marginBottom:24 }}>
|
||||
{top10.map(m => <MovieCard key={m.id} movie={m} favIds={favIds} onToggleFav={onToggle} onOpenModal={onOpenModal} />)}
|
||||
{top10.map(m => <MovieCard key={m.id} movie={m} favIds={favIds} xrelIds={xrelIds} onToggleFav={onToggle} onOpenModal={onOpenModal} />)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
@@ -276,7 +298,7 @@ function KinoGrid({ onOpenModal }) {
|
||||
<>
|
||||
<div style={{ ...S.head, marginBottom:12 }}>WEITERE FILME IM KINO</div>
|
||||
<div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(130px,1fr))', gap:12 }}>
|
||||
{rest.map(m => <MovieCard key={m.id} movie={m} favIds={favIds} onToggleFav={onToggle} onOpenModal={onOpenModal} />)}
|
||||
{rest.map(m => <MovieCard key={m.id} movie={m} favIds={favIds} xrelIds={xrelIds} onToggleFav={onToggle} onOpenModal={onOpenModal} />)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
@@ -289,11 +311,24 @@ function DemnächstGrid({ onOpenModal }) {
|
||||
const [groups, setGroups] = useState({});
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState('');
|
||||
const [xrelIds, setXrelIds] = useState(new Set());
|
||||
const [favIds, toggleFav] = useFavIds();
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true); setError('');
|
||||
api('/tools/media/upcoming').then(setGroups).catch(e => setError(e.message)).finally(() => setLoading(false));
|
||||
api('/tools/media/upcoming')
|
||||
.then(grps => {
|
||||
setGroups(grps);
|
||||
const allMovies = Object.values(grps).flat();
|
||||
api('/tools/media/xrel-check', {
|
||||
method: 'POST',
|
||||
body: { movies: allMovies.map(m => ({ id: m.id, title: m.title, original_title: m.original_title, release_date: m.release_date })) }
|
||||
}).then(result => {
|
||||
setXrelIds(new Set(Object.entries(result).filter(([,v]) => v).map(([k]) => Number(k))));
|
||||
}).catch(() => {});
|
||||
})
|
||||
.catch(e => setError(e.message))
|
||||
.finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
const onToggle = async (movie, isFav) => {
|
||||
@@ -316,7 +351,7 @@ function DemnächstGrid({ onOpenModal }) {
|
||||
<span style={{ fontSize:9 }}>{movies.length} Film{movies.length!==1?'e':''}</span>
|
||||
</div>
|
||||
<div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(130px,1fr))', gap:12 }}>
|
||||
{movies.map(m => <MovieCard key={m.id} movie={m} favIds={favIds} onToggleFav={onToggle} onOpenModal={onOpenModal} />)}
|
||||
{movies.map(m => <MovieCard key={m.id} movie={m} favIds={favIds} xrelIds={xrelIds} onToggleFav={onToggle} onOpenModal={onOpenModal} />)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user