14 changed files with 200 additions and 42 deletions
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
import { Icon, Icons } from "@/components/Icon"; |
||||
|
||||
function Card(props: { children: React.ReactNode }) { |
||||
return <div className="px-6 py-8">{props.children}</div>; |
||||
} |
||||
|
||||
function Title(props: { children: React.ReactNode }) { |
||||
return ( |
||||
<h3 className="uppercase font-bold text-video-context-type-secondary text-sm pl-1 pb-2 border-b border-opacity-25 border-video-context-border mb-6"> |
||||
{props.children} |
||||
</h3> |
||||
); |
||||
} |
||||
|
||||
function Section(props: { children: React.ReactNode }) { |
||||
return <div className="my-5">{props.children}</div>; |
||||
} |
||||
|
||||
function Link(props: { onClick?: () => void; children: React.ReactNode }) { |
||||
return ( |
||||
<button |
||||
type="button" |
||||
className="flex justify-between items-center py-2 pl-3 pr-3 -ml-3 rounded hover:bg-video-context-border hover:bg-opacity-10 w-full" |
||||
style={{ width: "calc(100% + 1.5rem)" }} |
||||
onClick={props.onClick} |
||||
> |
||||
{props.children} |
||||
</button> |
||||
); |
||||
} |
||||
|
||||
function LinkTitle(props: { children: React.ReactNode }) { |
||||
return ( |
||||
<span className="text-video-context-type-main font-medium"> |
||||
{props.children} |
||||
</span> |
||||
); |
||||
} |
||||
|
||||
function LinkChevron(props: { children?: React.ReactNode }) { |
||||
return ( |
||||
<span className="text-white flex items-center font-medium"> |
||||
{props.children} |
||||
<Icon className="text-xl ml-1" icon={Icons.CHEVRON_RIGHT} /> |
||||
</span> |
||||
); |
||||
} |
||||
|
||||
export const Context = { |
||||
Card, |
||||
Title, |
||||
Section, |
||||
Link, |
||||
LinkTitle, |
||||
LinkChevron, |
||||
}; |
@ -0,0 +1,54 @@
@@ -0,0 +1,54 @@
|
||||
import { useHistory, useParams } from "react-router-dom"; |
||||
import { useAsync } from "react-use"; |
||||
|
||||
import { DetailedMeta, getMetaFromId } from "@/backend/metadata/getmeta"; |
||||
import { decodeTMDBId } from "@/backend/metadata/tmdb"; |
||||
import { MWMediaType } from "@/backend/metadata/types/mw"; |
||||
|
||||
export interface MetaPartProps { |
||||
onGetMeta?: (meta: DetailedMeta, episodeId?: string) => void; |
||||
} |
||||
|
||||
export function MetaPart(props: MetaPartProps) { |
||||
const params = useParams<{ |
||||
media: string; |
||||
episode?: string; |
||||
season?: string; |
||||
}>(); |
||||
const history = useHistory(); |
||||
|
||||
const { loading, error } = useAsync(async () => { |
||||
const data = decodeTMDBId(params.media); |
||||
if (!data) return; |
||||
|
||||
const meta = await getMetaFromId(data.type, data.id, params.season); |
||||
if (!meta) return; |
||||
|
||||
// replace link with new link if youre not already on the right link
|
||||
let epId = params.episode; |
||||
if (meta.meta.type === MWMediaType.SERIES) { |
||||
let ep = meta.meta.seasonData.episodes.find( |
||||
(v) => v.id === params.episode |
||||
); |
||||
if (!ep) ep = meta.meta.seasonData.episodes[0]; |
||||
epId = ep.id; |
||||
if ( |
||||
params.season !== meta.meta.seasonData.id || |
||||
params.episode !== ep.id |
||||
) { |
||||
history.replace( |
||||
`/media/${params.media}/${meta.meta.seasonData.id}/${ep.id}` |
||||
); |
||||
} |
||||
} |
||||
|
||||
props.onGetMeta?.(meta, epId); |
||||
}, []); |
||||
|
||||
return ( |
||||
<div className="flex items-center justify-center"> |
||||
{loading ? <p>loading meta...</p> : null} |
||||
{error ? <p>failed to load meta!</p> : null} |
||||
</div> |
||||
); |
||||
} |
Loading…
Reference in new issue