52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
import { useNavigate } from 'react-router-dom'
|
|
import type { TmdbCastMember } from '../../api/tmdb'
|
|
|
|
interface Props {
|
|
crew: TmdbCastMember[] | null | undefined
|
|
}
|
|
|
|
const COMPOSER_JOBS = new Set([
|
|
'Original Music Composer',
|
|
'Music',
|
|
'Composer',
|
|
'Theme Song Performance',
|
|
])
|
|
|
|
/**
|
|
* "Theme by ..." line surfaced from TMDB credits.crew. Surfaces the
|
|
* composer(s) without burying them in the dense crew strip. Renders
|
|
* nothing when there's no composer credit.
|
|
*/
|
|
export default function ComposerBlock({ crew }: Props) {
|
|
const navigate = useNavigate()
|
|
if (!crew || crew.length === 0) return null
|
|
|
|
const seen = new Set<number>()
|
|
const composers: TmdbCastMember[] = []
|
|
for (const c of crew) {
|
|
if (!c.job || !COMPOSER_JOBS.has(c.job)) continue
|
|
if (seen.has(c.id)) continue
|
|
seen.add(c.id)
|
|
composers.push(c)
|
|
if (composers.length >= 3) break
|
|
}
|
|
if (composers.length === 0) return null
|
|
|
|
return (
|
|
<p className="text-[12.5px] text-text-3 leading-relaxed">
|
|
<span className="text-text-4 mr-1.5">Theme by</span>
|
|
{composers.map((c, i) => (
|
|
<span key={c.id}>
|
|
<button
|
|
onClick={() => navigate(`/person/${c.id}`)}
|
|
className="text-text-1 font-medium hover:text-accent transition focus-ring rounded"
|
|
>
|
|
{c.name}
|
|
</button>
|
|
{i < composers.length - 1 && <span className="text-text-5 mx-1.5">·</span>}
|
|
</span>
|
|
))}
|
|
</p>
|
|
)
|
|
}
|