Added videos page and all
This commit is contained in:
parent
762df56aea
commit
1db24083cb
|
@ -22,7 +22,7 @@ export default function PostPreview(props: Props): JSX.Element {
|
||||||
const { video } = props;
|
const { video } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={`/archives/videos/${video.uid}`} passHref>
|
<Link href={`/archives/videos/v/${video.uid}`} passHref>
|
||||||
<div className="drop-shadow-shade-xl cursor-pointer grid items-end hover:scale-[1.02] [--bg-opacity:0] hover:[--bg-opacity:0.5] [--play-opacity:0] hover:[--play-opacity:100] transition-transform">
|
<div className="drop-shadow-shade-xl cursor-pointer grid items-end hover:scale-[1.02] [--bg-opacity:0] hover:[--bg-opacity:0.5] [--play-opacity:0] hover:[--play-opacity:100] transition-transform">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<img
|
<img
|
||||||
|
|
|
@ -6,6 +6,7 @@ query getVideo($uid: String) {
|
||||||
uid
|
uid
|
||||||
title
|
title
|
||||||
description
|
description
|
||||||
|
gone
|
||||||
published_date {
|
published_date {
|
||||||
year
|
year
|
||||||
month
|
month
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
query getVideoChannel($channel: String) {
|
||||||
|
videoChannels(filters: { uid: { eq: $channel } } ) {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
uid
|
||||||
|
title
|
||||||
|
subscribers
|
||||||
|
videos (pagination:{limit: -1}) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
uid
|
||||||
|
title
|
||||||
|
views
|
||||||
|
duration
|
||||||
|
gone
|
||||||
|
categories {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
published_date {
|
||||||
|
year
|
||||||
|
month
|
||||||
|
day
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
query getVideoChannelsSlugs {
|
||||||
|
videoChannels(pagination: {limit: -1}) {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
uid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ query getVideosPreview {
|
||||||
title
|
title
|
||||||
views
|
views
|
||||||
duration
|
duration
|
||||||
|
gone
|
||||||
categories {
|
categories {
|
||||||
data {
|
data {
|
||||||
id
|
id
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
import AppLayout from "components/AppLayout";
|
||||||
|
import PanelHeader from "components/PanelComponents/PanelHeader";
|
||||||
|
import ReturnButton, {
|
||||||
|
ReturnButtonType,
|
||||||
|
} from "components/PanelComponents/ReturnButton";
|
||||||
|
import ContentPanel, {
|
||||||
|
ContentPanelWidthSizes,
|
||||||
|
} from "components/Panels/ContentPanel";
|
||||||
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
|
import VideoPreview from "components/Videos/VideoPreview";
|
||||||
|
import { GetVideoChannelQuery } from "graphql/generated";
|
||||||
|
import { getReadySdk } from "graphql/sdk";
|
||||||
|
import {
|
||||||
|
GetStaticPathsContext,
|
||||||
|
GetStaticPathsResult,
|
||||||
|
GetStaticPropsContext,
|
||||||
|
} from "next";
|
||||||
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
|
||||||
|
interface Props extends AppStaticProps {
|
||||||
|
channel: Exclude<
|
||||||
|
GetVideoChannelQuery["videoChannels"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Channel(props: Props): JSX.Element {
|
||||||
|
const { langui, channel } = props;
|
||||||
|
const subPanel = (
|
||||||
|
<SubPanel>
|
||||||
|
<ReturnButton
|
||||||
|
href="/archives/videos/"
|
||||||
|
title={"Videos"}
|
||||||
|
langui={langui}
|
||||||
|
displayOn={ReturnButtonType.desktop}
|
||||||
|
className="mb-10"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<PanelHeader
|
||||||
|
icon="movie"
|
||||||
|
title="Videos"
|
||||||
|
description={langui.archives_description}
|
||||||
|
/>
|
||||||
|
</SubPanel>
|
||||||
|
);
|
||||||
|
|
||||||
|
const contentPanel = (
|
||||||
|
<ContentPanel width={ContentPanelWidthSizes.large}>
|
||||||
|
<div className="mb-8">
|
||||||
|
<h1 className="text-3xl">{channel?.title}</h1>
|
||||||
|
<p>{channel?.subscribers.toLocaleString()} subscribers</p>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-8 items-start mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0">
|
||||||
|
{channel?.videos?.data.map((video) => (
|
||||||
|
<>{video.attributes && <VideoPreview video={video.attributes} />}</>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</ContentPanel>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<AppLayout
|
||||||
|
navTitle={langui.archives}
|
||||||
|
subPanel={subPanel}
|
||||||
|
contentPanel={contentPanel}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStaticProps(
|
||||||
|
context: GetStaticPropsContext
|
||||||
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
|
const sdk = getReadySdk();
|
||||||
|
const channel = await sdk.getVideoChannel({
|
||||||
|
channel: context.params?.uid?.toString() ?? "",
|
||||||
|
});
|
||||||
|
if (!channel.videoChannels?.data[0].attributes) return { notFound: true };
|
||||||
|
const props: Props = {
|
||||||
|
...(await getAppStaticProps(context)),
|
||||||
|
channel: channel.videoChannels?.data[0].attributes,
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
props: props,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStaticPaths(
|
||||||
|
context: GetStaticPathsContext
|
||||||
|
): Promise<GetStaticPathsResult> {
|
||||||
|
const sdk = getReadySdk();
|
||||||
|
const channels = await sdk.getVideoChannelsSlugs();
|
||||||
|
const paths: GetStaticPathsResult["paths"] = [];
|
||||||
|
if (channels.videoChannels?.data)
|
||||||
|
channels.videoChannels.data.map((channel) => {
|
||||||
|
context.locales?.map((local) => {
|
||||||
|
if (channel.attributes)
|
||||||
|
paths.push({
|
||||||
|
params: { uid: channel.attributes.uid },
|
||||||
|
locale: local,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
paths,
|
||||||
|
fallback: "blocking",
|
||||||
|
};
|
||||||
|
}
|
|
@ -39,7 +39,7 @@ export default function Videos(props: Props): JSX.Element {
|
||||||
|
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
<ContentPanel width={ContentPanelWidthSizes.large}>
|
<ContentPanel width={ContentPanelWidthSizes.large}>
|
||||||
<div className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0">
|
<div className="grid gap-8 items-start mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0">
|
||||||
{videos.map((video) => (
|
{videos.map((video) => (
|
||||||
<>{video.attributes && <VideoPreview video={video.attributes} />}</>
|
<>{video.attributes && <VideoPreview video={video.attributes} />}</>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -86,11 +86,23 @@ export default function Video(props: Props): JSX.Element {
|
||||||
id="video"
|
id="video"
|
||||||
className="w-full rounded-xl shadow-shade shadow-lg overflow-hidden"
|
className="w-full rounded-xl shadow-shade shadow-lg overflow-hidden"
|
||||||
>
|
>
|
||||||
<video
|
{video.gone ? (
|
||||||
className="w-full"
|
<video
|
||||||
src={getVideoFile(video.uid)}
|
className="w-full"
|
||||||
controls
|
src={getVideoFile(video.uid)}
|
||||||
></video>
|
controls
|
||||||
|
></video>
|
||||||
|
) : (
|
||||||
|
<iframe
|
||||||
|
src={`https://www.youtube-nocookie.com/embed/${video.uid}`}
|
||||||
|
className="w-full aspect-video"
|
||||||
|
title="YouTube video player"
|
||||||
|
frameBorder="0"
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||||
|
allowFullScreen
|
||||||
|
></iframe>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="p-6 mt-2">
|
<div className="p-6 mt-2">
|
||||||
<h1 className="text-2xl">{video.title}</h1>
|
<h1 className="text-2xl">{video.title}</h1>
|
||||||
<div className="flex flex-row flex-wrap gap-x-6 w-full">
|
<div className="flex flex-row flex-wrap gap-x-6 w-full">
|
||||||
|
@ -118,10 +130,13 @@ export default function Video(props: Props): JSX.Element {
|
||||||
: video.likes.toLocaleString()}
|
: video.likes.toLocaleString()}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<Button
|
<a
|
||||||
href=""
|
href={`https://youtu.be/${video.uid}`}
|
||||||
className="!py-0 !px-3"
|
target="_blank"
|
||||||
>{`View on ${video.source}`}</Button>
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<Button className="!py-0 !px-3">{`View on ${video.source}`}</Button>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -131,7 +146,7 @@ export default function Video(props: Props): JSX.Element {
|
||||||
<div className="w-[clamp(0px,100%,42rem)] grid place-items-center gap-4 text-center">
|
<div className="w-[clamp(0px,100%,42rem)] grid place-items-center gap-4 text-center">
|
||||||
<h2 className="text-2xl">{"Channel"}</h2>
|
<h2 className="text-2xl">{"Channel"}</h2>
|
||||||
<div>
|
<div>
|
||||||
<Button href="#">
|
<Button href={`/archives/videos/c/${video.channel.data.attributes.uid}`}>
|
||||||
<h3>{video.channel.data.attributes.title}</h3>
|
<h3>{video.channel.data.attributes.title}</h3>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
@ -184,7 +199,7 @@ export async function getStaticPaths(
|
||||||
context: GetStaticPathsContext
|
context: GetStaticPathsContext
|
||||||
): Promise<GetStaticPathsResult> {
|
): Promise<GetStaticPathsResult> {
|
||||||
const sdk = getReadySdk();
|
const sdk = getReadySdk();
|
||||||
const videos = await sdk.getVideo();
|
const videos = await sdk.getVideosSlugs();
|
||||||
const paths: GetStaticPathsResult["paths"] = [];
|
const paths: GetStaticPathsResult["paths"] = [];
|
||||||
if (videos.videos?.data)
|
if (videos.videos?.data)
|
||||||
videos.videos.data.map((video) => {
|
videos.videos.data.map((video) => {
|
Loading…
Reference in New Issue