mirror of
https://github.com/p-stream/p-stream.git
synced 2026-04-21 11:12:21 +00:00
clean up details modal
This commit is contained in:
parent
743f5ffabc
commit
ede3613112
6 changed files with 23 additions and 1177 deletions
|
|
@ -212,7 +212,8 @@
|
||||||
"season": "Season",
|
"season": "Season",
|
||||||
"episode": "Episode",
|
"episode": "Episode",
|
||||||
"airs": "Airs",
|
"airs": "Airs",
|
||||||
"endsAt": "Ends at {{time}}"
|
"endsAt": "Ends at {{time}}",
|
||||||
|
"trailer": "Trailer"
|
||||||
},
|
},
|
||||||
"migration": {
|
"migration": {
|
||||||
"loginRequired": "You must be logged in to migrate your data! Please go back and login to continue.",
|
"loginRequired": "You must be logged in to migrate your data! Please go back and login to continue.",
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ import { IconPatch } from "@/components/buttons/IconPatch";
|
||||||
import { Icon, Icons } from "@/components/Icon";
|
import { Icon, Icons } from "@/components/Icon";
|
||||||
import { MediaBookmarkButton } from "@/components/media/MediaBookmark";
|
import { MediaBookmarkButton } from "@/components/media/MediaBookmark";
|
||||||
|
|
||||||
import { DetailsHeaderProps } from "./types";
|
import { DetailsBodyProps } from "./types";
|
||||||
|
|
||||||
export function DetailsHeader({
|
export function DetailsBody({
|
||||||
data,
|
data,
|
||||||
onPlayClick,
|
onPlayClick,
|
||||||
onTrailerClick,
|
onTrailerClick,
|
||||||
|
|
@ -24,7 +24,7 @@ export function DetailsHeader({
|
||||||
releaseDate,
|
releaseDate,
|
||||||
seasons,
|
seasons,
|
||||||
imdbData,
|
imdbData,
|
||||||
}: DetailsHeaderProps) {
|
}: DetailsBodyProps) {
|
||||||
const [releaseInfo, setReleaseInfo] = useState<TraktReleaseResponse | null>(
|
const [releaseInfo, setReleaseInfo] = useState<TraktReleaseResponse | null>(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
@ -44,7 +44,7 @@ export function DetailsHeader({
|
||||||
}, [data.id]);
|
}, [data.id]);
|
||||||
|
|
||||||
const getQualityIndicator = () => {
|
const getQualityIndicator = () => {
|
||||||
if (!releaseInfo) return null;
|
if (!releaseInfo || data.type === "show") return null;
|
||||||
|
|
||||||
const hasDigitalRelease = !!releaseInfo.digital_release_date;
|
const hasDigitalRelease = !!releaseInfo.digital_release_date;
|
||||||
const hasTheatricalRelease = !!releaseInfo.theatrical_release_date;
|
const hasTheatricalRelease = !!releaseInfo.theatrical_release_date;
|
||||||
|
|
@ -176,17 +176,19 @@ export function DetailsHeader({
|
||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
<div className="flex items-center gap-1 flex-shrink-0">
|
<div className="flex items-center gap-1 flex-shrink-0">
|
||||||
<button
|
{imdbData?.trailer_url && (
|
||||||
type="button"
|
<button
|
||||||
onClick={onTrailerClick}
|
type="button"
|
||||||
className="p-2 opacity-75 transition-opacity duration-300 hover:scale-110 hover:cursor-pointer hover:opacity-95"
|
onClick={onTrailerClick}
|
||||||
title={t("details.trailer")}
|
className="p-2 opacity-75 transition-opacity duration-300 hover:scale-110 hover:cursor-pointer hover:opacity-95"
|
||||||
>
|
title={t("details.trailer")}
|
||||||
<IconPatch
|
>
|
||||||
icon={Icons.FILM}
|
<IconPatch
|
||||||
className="transition-transform duration-300 hover:scale-110 hover:cursor-pointer"
|
icon={Icons.FILM}
|
||||||
/>
|
className="transition-transform duration-300 hover:scale-110 hover:cursor-pointer"
|
||||||
</button>
|
/>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
<MediaBookmarkButton
|
<MediaBookmarkButton
|
||||||
media={{
|
media={{
|
||||||
id: data.id?.toString() || "",
|
id: data.id?.toString() || "",
|
||||||
|
|
@ -12,7 +12,7 @@ import { scrapeIMDb } from "@/utils/imdbScraper";
|
||||||
import { getTmdbLanguageCode } from "@/utils/language";
|
import { getTmdbLanguageCode } from "@/utils/language";
|
||||||
import { scrapeRottenTomatoes } from "@/utils/rottenTomatoesScraper";
|
import { scrapeRottenTomatoes } from "@/utils/rottenTomatoesScraper";
|
||||||
|
|
||||||
import { DetailsHeader } from "./DetailsHeader";
|
import { DetailsBody } from "./DetailsBody";
|
||||||
import { DetailsInfo } from "./DetailsInfo";
|
import { DetailsInfo } from "./DetailsInfo";
|
||||||
import { EpisodeCarousel } from "./EpisodeCarousel";
|
import { EpisodeCarousel } from "./EpisodeCarousel";
|
||||||
import { CastCarousel } from "./PeopleCarousel";
|
import { CastCarousel } from "./PeopleCarousel";
|
||||||
|
|
@ -205,7 +205,7 @@ export function DetailsContent({ data, minimal = false }: DetailsContentProps) {
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="px-6 pb-6 mt-[-70px] flex-grow relative z-30">
|
<div className="px-6 pb-6 mt-[-70px] flex-grow relative z-30">
|
||||||
<DetailsHeader
|
<DetailsBody
|
||||||
data={data}
|
data={data}
|
||||||
onPlayClick={handlePlayClick}
|
onPlayClick={handlePlayClick}
|
||||||
onTrailerClick={() => setShowTrailer(true)}
|
onTrailerClick={() => setShowTrailer(true)}
|
||||||
|
|
|
||||||
|
|
@ -6,29 +6,11 @@ import { getRTIcon } from "@/utils/rottenTomatoesScraper";
|
||||||
import { DetailsRatingsProps } from "./types";
|
import { DetailsRatingsProps } from "./types";
|
||||||
|
|
||||||
export function DetailsRatings({
|
export function DetailsRatings({
|
||||||
voteAverage,
|
|
||||||
voteCount,
|
|
||||||
imdbData,
|
|
||||||
rtData,
|
rtData,
|
||||||
mediaId,
|
mediaId,
|
||||||
mediaType,
|
mediaType,
|
||||||
imdbId,
|
imdbId,
|
||||||
}: DetailsRatingsProps) {
|
}: DetailsRatingsProps) {
|
||||||
const formatVoteCount = (count?: number) => {
|
|
||||||
if (!count) return "0";
|
|
||||||
if (count >= 1000) {
|
|
||||||
return `${Math.floor(count / 1000)}K+`;
|
|
||||||
}
|
|
||||||
return count.toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
const getRatingColor = (rating: number) => {
|
|
||||||
if (rating >= 8) return "bg-green-500";
|
|
||||||
if (rating >= 6) return "bg-yellow-500";
|
|
||||||
if (rating >= 4) return "bg-orange-500";
|
|
||||||
return "bg-red-500";
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
{/* External Links */}
|
{/* External Links */}
|
||||||
|
|
@ -90,27 +72,6 @@ export function DetailsRatings({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="pt-4">
|
|
||||||
{voteAverage !== undefined &&
|
|
||||||
voteCount !== undefined &&
|
|
||||||
voteCount > 0 && (
|
|
||||||
<>
|
|
||||||
{/* Rating Progress Bar */}
|
|
||||||
<div className="w-full h-2 bg-white/10 rounded-full overflow-hidden">
|
|
||||||
<div
|
|
||||||
className={`h-full ${getRatingColor(imdbData?.imdb_rating || voteAverage)} transition-all duration-500`}
|
|
||||||
style={{
|
|
||||||
width: `${((imdbData?.imdb_rating || voteAverage) / 10) * 100}%`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="text-white/60 text-[10px] text-right">
|
|
||||||
{formatVoteCount(imdbData?.votes || voteCount)}{" "}
|
|
||||||
{t("details.votes")}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -99,7 +99,7 @@ export interface EpisodeCarouselProps {
|
||||||
mediaTitle?: string;
|
mediaTitle?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DetailsHeaderProps {
|
export interface DetailsBodyProps {
|
||||||
data: DetailsContent;
|
data: DetailsContent;
|
||||||
onPlayClick: () => void;
|
onPlayClick: () => void;
|
||||||
onTrailerClick: () => void;
|
onTrailerClick: () => void;
|
||||||
|
|
@ -112,6 +112,7 @@ export interface DetailsHeaderProps {
|
||||||
imdbData?: {
|
imdbData?: {
|
||||||
rating: number;
|
rating: number;
|
||||||
votes: number;
|
votes: number;
|
||||||
|
trailer_url?: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue