type detail and shared ui

This commit is contained in:
2026-04-27 02:49:46 +03:00
parent 192cb92c1e
commit 906120e6e6
9 changed files with 15 additions and 15 deletions
+2 -2
View File
@@ -277,7 +277,7 @@ export default function DetailHero({
<RequestButton <RequestButton
tmdbId={Number(tmdbId)} tmdbId={Number(tmdbId)}
kind={item.Type === 'Movie' ? 'movie' : 'tv'} kind={item.Type === 'Movie' ? 'movie' : 'tv'}
tmdbData={tmdbData as any} tmdbData={tmdbData}
/> />
)} )}
@@ -337,7 +337,7 @@ export default function DetailHero({
tmdbId={tmdbId} tmdbId={tmdbId}
type={itemType === 'Series' ? 'tv' : 'movie'} type={itemType === 'Series' ? 'tv' : 'movie'}
ids={tmdbData?.external_ids} ids={tmdbData?.external_ids}
jellyfinExternalUrls={item.ExternalUrls as any} jellyfinExternalUrls={item.ExternalUrls}
/> />
{progress != null && progress > 0 && ( {progress != null && progress > 0 && (
+3 -3
View File
@@ -206,14 +206,14 @@ export default function DetailMainSections({
<div className="grid grid-cols-1 lg:grid-cols-2 gap-x-8 gap-y-10"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-x-8 gap-y-10">
{cast.length > 0 && ( {cast.length > 0 && (
<Section label="Cast" id="detail-cast"> <Section label="Cast" id="detail-cast">
<CastList cast={cast as any[]} fallbackPeople={item.People} /> <CastList cast={cast} fallbackPeople={item.People} />
</Section> </Section>
)} )}
{crew.length > 0 && ( {crew.length > 0 && (
<Section label="Crew"> <Section label="Crew">
<CrewGrid crew={crew as any[]} /> <CrewGrid crew={crew} />
<div className="mt-3"> <div className="mt-3">
<ComposerBlock crew={crew as any[]} /> <ComposerBlock crew={crew} />
</div> </div>
</Section> </Section>
)} )}
+1 -1
View File
@@ -10,7 +10,7 @@ interface Props {
} }
export default function VersionsSelector({ item, selectedSourceId, onChange }: Props) { export default function VersionsSelector({ item, selectedSourceId, onChange }: Props) {
const sources = (item.MediaSources || []) as any[] const sources = item.MediaSources || []
if (sources.length <= 1) return null if (sources.length <= 1) return null
return ( return (
+2 -2
View File
@@ -164,7 +164,7 @@ export default function RequestModal({ open, onClose, tmdbId, kind, tmdbData }:
monitored, monitored,
searchOnAdd, searchOnAdd,
title: match.title, title: match.title,
titleSlug: (match as any).titleSlug || '', titleSlug: match.titleSlug || '',
year: match.year || 0, year: match.year || 0,
images: match.images, images: match.images,
minimumAvailability: 'released', minimumAvailability: 'released',
@@ -195,7 +195,7 @@ export default function RequestModal({ open, onClose, tmdbId, kind, tmdbData }:
monitored, monitored,
searchOnAdd, searchOnAdd,
title: match.title, title: match.title,
titleSlug: (match as any).titleSlug || '', titleSlug: match.titleSlug || '',
year: match.year || 0, year: match.year || 0,
images: match.images, images: match.images,
seasons, seasons,
+1 -1
View File
@@ -273,7 +273,7 @@ function ListRowCard({ item, index }: { item: BaseItemDto; index: number }) {
const thumb = const thumb =
getBestImage(serverUrl, item, 'thumb', 240) || getBestImage(serverUrl, item, 'thumb', 240) ||
getBestImage(serverUrl, item, 'primary', 200) || getBestImage(serverUrl, item, 'primary', 200) ||
(item as any)._tmdbPoster || item._tmdbPoster ||
null null
const subtitle = [ const subtitle = [
item.ProductionYear, item.ProductionYear,
+1 -1
View File
@@ -113,7 +113,7 @@ function Mounted({ saved }: Props) {
} }
if (items.length === 0) return null if (items.length === 0) return null
const matched = items.filter(i => (i as any)._inLibrary).length const matched = items.filter(i => i._inLibrary).length
const subtitle = `${matched} of ${items.length} in your library · from Letterboxd` const subtitle = `${matched} of ${items.length} in your library · from Letterboxd`
return ( return (
+1 -1
View File
@@ -45,7 +45,7 @@ export default function PersonSpotlightRow({ personId, name, role, profilePath,
? (credits.crew || []).filter(c => c.job === 'Director') ? (credits.crew || []).filter(c => c.job === 'Director')
: (credits.cast || []) : (credits.cast || [])
// Drop trivia / archival appearances and ultra-deep cuts. // Drop trivia / archival appearances and ultra-deep cuts.
.filter(c => COMMERCIAL_DEPARTMENTS.includes((c as any).department || 'Acting')) .filter(c => COMMERCIAL_DEPARTMENTS.includes(c.department || 'Acting'))
// De-dupe by id (a director may have multiple crew credits on one film // De-dupe by id (a director may have multiple crew credits on one film
// when they're also writer; a cast member may appear twice for episodic // when they're also writer; a cast member may appear twice for episodic
+1 -1
View File
@@ -205,7 +205,7 @@ export default function QuickLookModal() {
<RequestButton <RequestButton
tmdbId={numericTmdb} tmdbId={numericTmdb}
kind={item.Type === 'Movie' ? 'movie' : 'tv'} kind={item.Type === 'Movie' ? 'movie' : 'tv'}
tmdbData={tmdbData as any} tmdbData={tmdbData}
/> />
)} )}
</div> </div>
+3 -3
View File
@@ -92,7 +92,7 @@ export default function SmartShelfWizard({ open, onClose }: Props) {
<Field label="Type"> <Field label="Type">
<Segmented <Segmented
value={draft.type} value={draft.type}
onChange={v => setDraft(d => ({ ...d, type: v as any }))} onChange={v => setDraft(d => ({ ...d, type: v }))}
options={[ options={[
{ value: 'any', label: 'Any' }, { value: 'any', label: 'Any' },
{ value: 'movie', label: 'Movies' }, { value: 'movie', label: 'Movies' },
@@ -155,7 +155,7 @@ export default function SmartShelfWizard({ open, onClose }: Props) {
<Field label="Watched"> <Field label="Watched">
<Segmented <Segmented
value={draft.watched} value={draft.watched}
onChange={v => setDraft(d => ({ ...d, watched: v as any }))} onChange={v => setDraft(d => ({ ...d, watched: v }))}
options={[ options={[
{ value: 'any', label: 'Any' }, { value: 'any', label: 'Any' },
{ value: 'unplayed', label: 'Unwatched' }, { value: 'unplayed', label: 'Unwatched' },
@@ -185,7 +185,7 @@ export default function SmartShelfWizard({ open, onClose }: Props) {
<Field label="Sort"> <Field label="Sort">
<Segmented <Segmented
value={draft.sortBy} value={draft.sortBy}
onChange={v => setDraft(d => ({ ...d, sortBy: v as any }))} onChange={v => setDraft(d => ({ ...d, sortBy: v }))}
options={[ options={[
{ value: 'random', label: 'Random' }, { value: 'random', label: 'Random' },
{ value: 'recent', label: 'Recent' }, { value: 'recent', label: 'Recent' },