2022-02-17 18:36:39 +01:00
|
|
|
import { getProviderFromId, MWMedia, MWMediaType } from "providers";
|
2022-02-07 23:22:35 +01:00
|
|
|
import { Link } from "react-router-dom";
|
2022-02-16 22:38:37 +01:00
|
|
|
import { Icon, Icons } from "components/Icon";
|
2022-02-07 23:22:35 +01:00
|
|
|
|
|
|
|
export interface MediaCardProps {
|
|
|
|
media: MWMedia;
|
|
|
|
watchedPercentage: Number;
|
2022-02-16 22:38:37 +01:00
|
|
|
linkable?: boolean;
|
2022-02-07 23:22:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-16 22:38:37 +01:00
|
|
|
export interface MediaMetaProps {
|
|
|
|
content: string[];
|
|
|
|
}
|
|
|
|
|
|
|
|
function MediaMeta(props: MediaMetaProps) {
|
2022-02-07 23:22:35 +01:00
|
|
|
return (
|
2022-02-16 22:38:37 +01:00
|
|
|
<p className="text-denim-700 text-xs font-semibold">
|
|
|
|
{props.content.map((item, index) => (
|
|
|
|
<span key={item}>
|
|
|
|
{index !== 0 ? (
|
|
|
|
<span className="mx-[0.6em] text-[1em]">●</span>
|
|
|
|
) : null}
|
|
|
|
{item}
|
|
|
|
</span>
|
|
|
|
))}
|
|
|
|
</p>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function MediaCardContent({
|
|
|
|
media,
|
|
|
|
linkable,
|
|
|
|
watchedPercentage,
|
|
|
|
}: MediaCardProps) {
|
2022-02-17 18:25:12 +01:00
|
|
|
const provider = getProviderFromId(media.providerId);
|
2022-02-16 22:38:37 +01:00
|
|
|
|
|
|
|
if (!provider) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<article
|
|
|
|
className={`bg-denim-300 group relative mb-4 flex overflow-hidden rounded py-4 px-5 ${
|
|
|
|
linkable ? "hover:bg-denim-400" : ""
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
{/* progress background */}
|
|
|
|
{watchedPercentage > 0 ? (
|
|
|
|
<div className="absolute top-0 left-0 right-0 bottom-0">
|
|
|
|
<div
|
|
|
|
className="bg-bink-300 relative h-full bg-opacity-30"
|
|
|
|
style={{
|
|
|
|
width: `${watchedPercentage}%`,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<div className="from-bink-400 absolute right-0 top-0 bottom-0 ml-auto w-40 bg-gradient-to-l to-transparent opacity-40" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
|
|
|
|
<div className="relative flex flex-1">
|
|
|
|
{/* card content */}
|
|
|
|
<div className="flex-1">
|
|
|
|
<h1 className="mb-1 font-bold text-white">{media.title}</h1>
|
2022-02-17 18:25:12 +01:00
|
|
|
<MediaMeta
|
|
|
|
content={[provider.displayName, media.mediaType, media.year]}
|
|
|
|
/>
|
2022-02-16 22:38:37 +01:00
|
|
|
</div>
|
|
|
|
|
|
|
|
{/* hoverable chevron */}
|
|
|
|
<div
|
|
|
|
className={`flex translate-x-3 items-center justify-end text-xl text-white opacity-0 transition-[opacity,transform] ${
|
|
|
|
linkable ? "group-hover:translate-x-0 group-hover:opacity-100" : ""
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
<Icon icon={Icons.CHEVRON_RIGHT} />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</article>
|
|
|
|
);
|
2022-02-07 23:22:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export function MediaCard(props: MediaCardProps) {
|
2022-02-16 22:38:37 +01:00
|
|
|
let link = "movie";
|
2022-02-17 18:25:12 +01:00
|
|
|
if (props.media.mediaType === MWMediaType.MOVIE) link = "series";
|
2022-02-07 23:22:35 +01:00
|
|
|
|
2022-02-16 22:38:37 +01:00
|
|
|
const content = <MediaCardContent {...props} />;
|
|
|
|
|
|
|
|
if (!props.linkable) return <span>{content}</span>;
|
|
|
|
return <Link to={`/media/${link}`}>{content}</Link>;
|
2022-02-07 23:22:35 +01:00
|
|
|
}
|