feat: alle Erscheinungsdaten im Modal (Kinostart DE/US, Web, Retail, Blu-ray)

This commit is contained in:
2026-06-11 10:09:50 +02:00
parent 71c411a350
commit 8d99ceba04
2 changed files with 36 additions and 21 deletions

View File

@@ -66,24 +66,27 @@ function extractFSK(rd) {
return null; return null;
} }
const RELEASE_TYPE_LABEL = { 2:'Kino (limited)', 3:'Kinostart', 4:'Web', 5:'Retail', 6:'TV' };
function extractReleaseDates(rd) { function extractReleaseDates(rd) {
const out = {}; if (!rd?.results) return [];
// DE Kinostart (type 3) const PRIORITY = ['DE','US','GB','FR','AT','CH'];
const de = rd?.results?.find(r => r.iso_3166_1 === 'DE'); const entries = [];
if (de) { for (const country of PRIORITY) {
const theatrical = de.release_dates.find(r => r.type === 3); const c = rd.results.find(r => r.iso_3166_1 === country);
if (theatrical?.release_date) out.de_cinema = theatrical.release_date.slice(0,10); if (!c) continue;
for (const r of c.release_dates) {
if (!r.release_date) continue;
if (!RELEASE_TYPE_LABEL[r.type]) continue; // Premiere+TV überspringen
entries.push({
country,
label: `${RELEASE_TYPE_LABEL[r.type]} (${country})`,
date: r.release_date.slice(0, 10),
});
} }
// US Kinostart (type 3)
const us = rd?.results?.find(r => r.iso_3166_1 === 'US');
if (us) {
const theatrical = us.release_dates.find(r => r.type === 3);
if (theatrical?.release_date) out.us_cinema = theatrical.release_date.slice(0,10);
// US Digital (type 4)
const digital = us.release_dates.find(r => r.type === 4);
if (digital?.release_date) out.us_digital = digital.release_date.slice(0,10);
} }
return out; entries.sort((a, b) => a.date.localeCompare(b.date));
return entries;
} }
async function fetchAllPages(path, maxPages = 3) { async function fetchAllPages(path, maxPages = 3) {
const first = await tmdb(path, { page: 1 }); const first = await tmdb(path, { page: 1 });

View File

@@ -580,11 +580,7 @@ function MovieModal({ tmdbId, onClose, mobile, onHasXrel }) {
{detail.vote_average > 0 && <Badge bg="rgba(255,230,109,0.15)" color="#ffe66d"> {detail.vote_average.toFixed(1)}</Badge>} {detail.vote_average > 0 && <Badge bg="rgba(255,230,109,0.15)" color="#ffe66d"> {detail.vote_average.toFixed(1)}</Badge>}
{detail.runtime > 0 && <Badge bg="rgba(255,255,255,0.07)" color="rgba(255,255,255,0.7)"> {detail.runtime} Min</Badge>} {detail.runtime > 0 && <Badge bg="rgba(255,255,255,0.07)" color="rgba(255,255,255,0.7)"> {detail.runtime} Min</Badge>}
{fskStyle && <Badge bg={fskStyle.bg} color={fskStyle.color}>FSK {detail.fsk}</Badge>} {fskStyle && <Badge bg={fskStyle.bg} color={fskStyle.color}>FSK {detail.fsk}</Badge>}
{detail.release_dates?.de_cinema {detail.release_date && <Badge bg="rgba(255,255,255,0.07)" color="rgba(255,255,255,0.55)">🇩🇪 {fmtDE(detail.release_date)}</Badge>}
? <Badge bg="rgba(255,255,255,0.07)" color="rgba(255,255,255,0.55)">🇩🇪 Kino {fmtDE(detail.release_dates.de_cinema)}</Badge>
: detail.release_date && <Badge bg="rgba(255,255,255,0.07)" color="rgba(255,255,255,0.55)">🇩🇪 {fmtDE(detail.release_date)}</Badge>}
{detail.release_dates?.us_cinema && <Badge bg="rgba(255,255,255,0.07)" color="rgba(255,255,255,0.5)">🇺🇸 Kino {fmtDE(detail.release_dates.us_cinema)}</Badge>}
{detail.release_dates?.us_digital && <Badge bg="rgba(78,205,196,0.1)" color="#4ecdc4">💻 Digital {fmtDE(detail.release_dates.us_digital)}</Badge>}
{detail.countries?.length > 0 && <Badge bg="rgba(255,255,255,0.07)" color="rgba(255,255,255,0.4)">🌍 {detail.countries.slice(0,2).join(' · ')}</Badge>} {detail.countries?.length > 0 && <Badge bg="rgba(255,255,255,0.07)" color="rgba(255,255,255,0.4)">🌍 {detail.countries.slice(0,2).join(' · ')}</Badge>}
</div> </div>
{detail.genres?.length > 0 && ( {detail.genres?.length > 0 && (
@@ -598,6 +594,22 @@ function MovieModal({ tmdbId, onClose, mobile, onHasXrel }) {
</div> </div>
</div> </div>
{detail.release_dates?.length > 0 && (
<div style={{ marginTop:16 }}>
<div style={{ ...S.head, marginBottom:8 }}>ERSCHEINUNGSDATEN</div>
<div style={{ display:'flex', flexDirection:'column', gap:4 }}>
{detail.release_dates.map((r, i) => (
<div key={i} style={{ display:'flex', justifyContent:'space-between', alignItems:'center',
fontSize:11, fontFamily:'monospace', padding:'3px 0',
borderBottom:'1px solid rgba(255,255,255,0.05)' }}>
<span style={{ color:'rgba(255,255,255,0.5)' }}>{r.label}</span>
<span style={{ color:'rgba(255,255,255,0.8)', fontWeight:600 }}>{fmtDE(r.date)}</span>
</div>
))}
</div>
</div>
)}
{detail.overview && ( {detail.overview && (
<div style={{ marginTop:18 }}> <div style={{ marginTop:18 }}>
<div style={{ ...S.head, marginBottom:6 }}>HANDLUNG</div> <div style={{ ...S.head, marginBottom:6 }}>HANDLUNG</div>