Use backdrop image as background for modal.

This commit is contained in:
SergeantPanda 2025-08-04 18:24:45 -05:00
parent d917a3a915
commit b19efd2f75

View file

@ -343,224 +343,251 @@ const VODModal = ({ vod, opened, onClose }) => {
size="xl"
centered
>
<Stack spacing="md">
{loadingDetails && (
<Group spacing="xs" mb={8}>
<Loader size="xs" />
<Text size="xs" color="dimmed">Loading additional details...</Text>
</Group>
)}
{/* Backdrop image if available */}
<Box style={{ position: 'relative', minHeight: 400 }}>
{/* Backdrop image as background */}
{displayVOD.backdrop_path && displayVOD.backdrop_path.length > 0 && (
<Box style={{ position: 'relative', height: 200, borderRadius: '8px', overflow: 'hidden' }}>
<>
<Image
src={displayVOD.backdrop_path[0]}
height={200}
alt={`${displayVOD.name} backdrop`}
fit="cover"
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
objectFit: 'cover',
zIndex: 0,
borderRadius: 8,
filter: 'blur(2px) brightness(0.5)'
}}
/>
</Box>
)}
{/* Movie poster and basic info */}
<Flex gap="md">
{/* Use movie_image or logo */}
{(displayVOD.movie_image || displayVOD.logo?.url) ? (
<Box style={{ flexShrink: 0 }}>
<Image
src={displayVOD.movie_image || displayVOD.logo.url}
width={200}
height={300}
alt={displayVOD.name}
fit="contain"
style={{ borderRadius: '8px' }}
/>
</Box>
) : (
{/* Overlay for readability */}
<Box
style={{
width: 200,
height: 300,
backgroundColor: '#404040',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '8px',
flexShrink: 0
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
background: 'linear-gradient(180deg, rgba(24,24,27,0.85) 60%, rgba(24,24,27,1) 100%)',
zIndex: 1,
borderRadius: 8
}}
>
<Play size={48} color="#666" />
</Box>
)}
<Stack spacing="md" style={{ flex: 1 }}>
<Title order={3}>{displayVOD.name}</Title>
{/* Original name if different */}
{displayVOD.o_name && displayVOD.o_name !== displayVOD.name && (
<Text size="sm" color="dimmed" style={{ fontStyle: 'italic' }}>
Original: {displayVOD.o_name}
</Text>
/>
</>
)}
{/* Modal content above backdrop */}
<Box style={{ position: 'relative', zIndex: 2 }}>
<Stack spacing="md">
{loadingDetails && (
<Group spacing="xs" mb={8}>
<Loader size="xs" />
<Text size="xs" color="dimmed">Loading additional details...</Text>
</Group>
)}
<Group spacing="md">
{displayVOD.year && <Badge color="blue">{displayVOD.year}</Badge>}
{displayVOD.duration && <Badge color="gray">{formatDuration(displayVOD.duration)}</Badge>}
{displayVOD.rating && <Badge color="yellow">{displayVOD.rating}</Badge>}
{displayVOD.age && <Badge color="orange">{displayVOD.age}</Badge>}
<Badge color="green">Movie</Badge>
</Group>
{/* Release date */}
{displayVOD.release_date && (
<Text size="sm" color="dimmed">
<strong>Release Date:</strong> {displayVOD.release_date}
</Text>
)}
{displayVOD.genre && (
<Text size="sm" color="dimmed">
<strong>Genre:</strong> {displayVOD.genre}
</Text>
)}
{displayVOD.director && (
<Text size="sm" color="dimmed">
<strong>Director:</strong> {displayVOD.director}
</Text>
)}
{displayVOD.actors && (
<Text size="sm" color="dimmed">
<strong>Cast:</strong> {displayVOD.actors}
</Text>
)}
{displayVOD.country && (
<Text size="sm" color="dimmed">
<strong>Country:</strong> {displayVOD.country}
</Text>
)}
{/* Description */}
{displayVOD.description && (
<Box>
<Text size="sm" weight={500} mb={8}>Description</Text>
<Text size="sm">
{displayVOD.description}
</Text>
</Box>
)}
{/* Watch Trailer button at top */}
{displayVOD.youtube_trailer && (
<Button
component="a"
href={displayVOD.youtube_trailer}
target="_blank"
rel="noopener noreferrer"
variant="outline"
color="red"
style={{ marginTop: 'auto', alignSelf: 'flex-start' }}
>
Watch Trailer on YouTube
</Button>
)}
{/* Removed Play Movie button from here */}
</Stack>
</Flex>
{/* Provider Information & Play Button Row */}
{(vod?.m3u_account || true) && (
<Group spacing="md" align="center" mt="md">
{vod?.m3u_account && (
<Box>
<Text size="sm" weight={500} mb={8}>IPTV Provider</Text>
<Group spacing="md">
<Badge color="blue" variant="light">
{vod.m3u_account.name}
</Badge>
{vod.m3u_account.account_type && (
<Badge color="gray" variant="outline" size="xs">
{vod.m3u_account.account_type === 'XC' ? 'Xtream Codes' : 'Standard M3U'}
</Badge>
)}
</Group>
</Box>
)}
<Button
leftSection={<Play size={16} />}
variant="filled"
color="blue"
size="md"
onClick={handlePlayVOD}
style={{ alignSelf: 'flex-start' }}
>
Play Movie
{vod?.m3u_account && (
<span style={{ fontWeight: 400, fontSize: 12, marginLeft: 8 }}>
{`(via ${vod.m3u_account.name}${displayVOD.bitrate ? `, ~${displayVOD.bitrate} kbps` : ''})`}
</span>
{/* Movie poster and basic info */}
<Flex gap="md">
{/* Use movie_image or logo */}
{(displayVOD.movie_image || displayVOD.logo?.url) ? (
<Box style={{ flexShrink: 0 }}>
<Image
src={displayVOD.movie_image || displayVOD.logo.url}
width={200}
height={300}
alt={displayVOD.name}
fit="contain"
style={{ borderRadius: '8px' }}
/>
</Box>
) : (
<Box
style={{
width: 200,
height: 300,
backgroundColor: '#404040',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '8px',
flexShrink: 0
}}
>
<Play size={48} color="#666" />
</Box>
)}
</Button>
</Group>
)}
{/* Technical Details */}
{(displayVOD.bitrate || displayVOD.video || displayVOD.audio) && (
<Stack spacing={4} mt="xs">
<Text size="sm" weight={500}>Technical Details:</Text>
{displayVOD.bitrate && displayVOD.bitrate > 0 && (
<Text size="xs" color="dimmed">
<strong>Bitrate:</strong> {displayVOD.bitrate} kbps
</Text>
<Stack spacing="md" style={{ flex: 1 }}>
<Title order={3}>{displayVOD.name}</Title>
{/* Original name if different */}
{displayVOD.o_name && displayVOD.o_name !== displayVOD.name && (
<Text size="sm" color="dimmed" style={{ fontStyle: 'italic' }}>
Original: {displayVOD.o_name}
</Text>
)}
<Group spacing="md">
{displayVOD.year && <Badge color="blue">{displayVOD.year}</Badge>}
{displayVOD.duration && <Badge color="gray">{formatDuration(displayVOD.duration)}</Badge>}
{displayVOD.rating && <Badge color="yellow">{displayVOD.rating}</Badge>}
{displayVOD.age && <Badge color="orange">{displayVOD.age}</Badge>}
<Badge color="green">Movie</Badge>
</Group>
{/* Release date */}
{displayVOD.release_date && (
<Text size="sm" color="dimmed">
<strong>Release Date:</strong> {displayVOD.release_date}
</Text>
)}
{displayVOD.genre && (
<Text size="sm" color="dimmed">
<strong>Genre:</strong> {displayVOD.genre}
</Text>
)}
{displayVOD.director && (
<Text size="sm" color="dimmed">
<strong>Director:</strong> {displayVOD.director}
</Text>
)}
{displayVOD.actors && (
<Text size="sm" color="dimmed">
<strong>Cast:</strong> {displayVOD.actors}
</Text>
)}
{displayVOD.country && (
<Text size="sm" color="dimmed">
<strong>Country:</strong> {displayVOD.country}
</Text>
)}
{/* Description */}
{displayVOD.description && (
<Box>
<Text size="sm" weight={500} mb={8}>Description</Text>
<Text size="sm">
{displayVOD.description}
</Text>
</Box>
)}
{/* Watch Trailer button at top */}
{displayVOD.youtube_trailer && (
<Button
component="a"
href={displayVOD.youtube_trailer}
target="_blank"
rel="noopener noreferrer"
variant="outline"
color="red"
style={{ marginTop: 'auto', alignSelf: 'flex-start' }}
>
Watch Trailer on YouTube
</Button>
)}
{/* Removed Play Movie button from here */}
</Stack>
</Flex>
{/* Provider Information & Play Button Row */}
{(vod?.m3u_account || true) && (
<Group spacing="md" align="center" mt="md">
{vod?.m3u_account && (
<Box>
<Text size="sm" weight={500} mb={8}>IPTV Provider</Text>
<Group spacing="md">
<Badge color="blue" variant="light">
{vod.m3u_account.name}
</Badge>
{vod.m3u_account.account_type && (
<Badge color="gray" variant="outline" size="xs">
{vod.m3u_account.account_type === 'XC' ? 'Xtream Codes' : 'Standard M3U'}
</Badge>
)}
</Group>
</Box>
)}
<Button
leftSection={<Play size={16} />}
variant="filled"
color="blue"
size="md"
onClick={handlePlayVOD}
style={{ alignSelf: 'flex-start' }}
>
Play Movie
{vod?.m3u_account && (
<span style={{ fontWeight: 400, fontSize: 12, marginLeft: 8 }}>
{`(via ${vod.m3u_account.name}${displayVOD.bitrate ? `, ~${displayVOD.bitrate} kbps` : ''})`}
</span>
)}
</Button>
</Group>
)}
{displayVOD.video && Object.keys(displayVOD.video).length > 0 && (
<Text size="xs" color="dimmed">
<strong>Video:</strong>{' '}
{displayVOD.video.codec_long_name || displayVOD.video.codec_name}
{displayVOD.video.profile ? ` (${displayVOD.video.profile})` : ''}
{displayVOD.video.width && displayVOD.video.height
? `, ${displayVOD.video.width}x${displayVOD.video.height}`
: ''}
{displayVOD.video.display_aspect_ratio
? `, Aspect Ratio: ${displayVOD.video.display_aspect_ratio}`
: ''}
{displayVOD.video.bit_rate
? `, Bitrate: ${Math.round(Number(displayVOD.video.bit_rate) / 1000)} kbps`
: ''}
{displayVOD.video.r_frame_rate
? `, Frame Rate: ${displayVOD.video.r_frame_rate.replace('/', '/')} fps`
: ''}
{displayVOD.video.tags?.encoder
? `, Encoder: ${displayVOD.video.tags.encoder}`
: ''}
</Text>
)}
{displayVOD.audio && Object.keys(displayVOD.audio).length > 0 && (
<Text size="xs" color="dimmed">
<strong>Audio:</strong>{' '}
{displayVOD.audio.codec_long_name || displayVOD.audio.codec_name}
{displayVOD.audio.profile ? ` (${displayVOD.audio.profile})` : ''}
{displayVOD.audio.channel_layout
? `, Channels: ${displayVOD.audio.channel_layout}`
: displayVOD.audio.channels
? `, Channels: ${displayVOD.audio.channels}`
: ''}
{displayVOD.audio.sample_rate
? `, Sample Rate: ${displayVOD.audio.sample_rate} Hz`
: ''}
{displayVOD.audio.bit_rate
? `, Bitrate: ${Math.round(Number(displayVOD.audio.bit_rate) / 1000)} kbps`
: ''}
{displayVOD.audio.tags?.handler_name
? `, Handler: ${displayVOD.audio.tags.handler_name}`
: ''}
</Text>
{/* Technical Details */}
{(displayVOD.bitrate || displayVOD.video || displayVOD.audio) && (
<Stack spacing={4} mt="xs">
<Text size="sm" weight={500}>Technical Details:</Text>
{displayVOD.bitrate && displayVOD.bitrate > 0 && (
<Text size="xs" color="dimmed">
<strong>Bitrate:</strong> {displayVOD.bitrate} kbps
</Text>
)}
{displayVOD.video && Object.keys(displayVOD.video).length > 0 && (
<Text size="xs" color="dimmed">
<strong>Video:</strong>{' '}
{displayVOD.video.codec_long_name || displayVOD.video.codec_name}
{displayVOD.video.profile ? ` (${displayVOD.video.profile})` : ''}
{displayVOD.video.width && displayVOD.video.height
? `, ${displayVOD.video.width}x${displayVOD.video.height}`
: ''}
{displayVOD.video.display_aspect_ratio
? `, Aspect Ratio: ${displayVOD.video.display_aspect_ratio}`
: ''}
{displayVOD.video.bit_rate
? `, Bitrate: ${Math.round(Number(displayVOD.video.bit_rate) / 1000)} kbps`
: ''}
{displayVOD.video.r_frame_rate
? `, Frame Rate: ${displayVOD.video.r_frame_rate.replace('/', '/')} fps`
: ''}
{displayVOD.video.tags?.encoder
? `, Encoder: ${displayVOD.video.tags.encoder}`
: ''}
</Text>
)}
{displayVOD.audio && Object.keys(displayVOD.audio).length > 0 && (
<Text size="xs" color="dimmed">
<strong>Audio:</strong>{' '}
{displayVOD.audio.codec_long_name || displayVOD.audio.codec_name}
{displayVOD.audio.profile ? ` (${displayVOD.audio.profile})` : ''}
{displayVOD.audio.channel_layout
? `, Channels: ${displayVOD.audio.channel_layout}`
: displayVOD.audio.channels
? `, Channels: ${displayVOD.audio.channels}`
: ''}
{displayVOD.audio.sample_rate
? `, Sample Rate: ${displayVOD.audio.sample_rate} Hz`
: ''}
{displayVOD.audio.bit_rate
? `, Bitrate: ${Math.round(Number(displayVOD.audio.bit_rate) / 1000)} kbps`
: ''}
{displayVOD.audio.tags?.handler_name
? `, Handler: ${displayVOD.audio.tags.handler_name}`
: ''}
</Text>
)}
</Stack>
)}
{/* YouTube trailer if available */}
</Stack>
)}
{/* YouTube trailer if available */}
</Stack>
</Box>
</Box>
</Modal>
);
};