Skip to content

Commit 5d8bd11

Browse files
Add videos page (#310)
Co-authored-by: Yoann Fleury <yoann.fleury@yahoo.com>
1 parent c39eef3 commit 5d8bd11

File tree

7 files changed

+186
-8
lines changed

7 files changed

+186
-8
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"@astrojs/sitemap": "3.4.2",
2323
"@astrojs/tailwind": "6.0.2",
2424
"@astrojs/vercel": "8.2.5",
25-
"@bearstudio/astro-typed-routes": "0.1.1",
25+
"@bearstudio/astro-typed-routes": "0.1.3",
2626
"@bearstudio/lunalink": "0.3.1",
2727
"@fontsource-variable/inter": "5.2.6",
2828
"@fontsource/tomorrow": "5.2.6",

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
import { lang } from "@/lib/lang";
3+
import { Image } from "astro:assets";
4+
import type { CollectionEntry } from "astro:content";
5+
import { IoLanguageSharp } from "react-icons/io5";
6+
7+
interface Props {
8+
talk: CollectionEntry<"talks">;
9+
}
10+
const { talk } = Astro.props;
11+
---
12+
13+
<a
14+
href={`https://www.youtube.com/embed/${talk.data.vod?.youtubeId}`}
15+
class="group relative z-10 flex h-full flex-col overflow-hidden rounded-lg bg-white/5 backdrop-blur-md transition duration-500 hover:bg-white/10"
16+
target="_blank"
17+
rel="noreferrer"
18+
>
19+
<div class="aspect-video">
20+
{
21+
talk.data.vod?.type === "youtube" && (
22+
<Image
23+
src={`https://img.youtube.com/vi/${talk.data.vod.youtubeId}/maxresdefault.jpg`}
24+
alt={talk.data.title}
25+
class="h-full w-full object-cover"
26+
width={480}
27+
height={320}
28+
/>
29+
)
30+
}
31+
</div>
32+
<div class="flex flex-1 flex-col justify-between p-4">
33+
<h3
34+
class="line-clamp-2 text-sm font-medium"
35+
lang={lang(talk.data.contentLanguage)}
36+
>
37+
{talk.data.title}
38+
</h3>
39+
<div
40+
class="mt-4 flex w-fit items-center gap-1.5 rounded-full border border-black/60 bg-black/40 px-2 py-0.5 text-2xs font-bold uppercase leading-none opacity-60 transition group-hover:opacity-100"
41+
>
42+
<IoLanguageSharp className="text-base" />
43+
<span>Talk in {talk.data.language}</span>
44+
</div>
45+
</div>
46+
</a>

src/content/menus.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
MdPodcasts,
1010
MdBadge,
1111
MdOutlineChildCare,
12+
MdOndemandVideo,
1213
MdMic,
1314
// MdBadge,
1415
// MdHandshake,
@@ -55,6 +56,13 @@ const MAIN_MENU: Array<{
5556
scope: "all",
5657
level: "primary",
5758
},
59+
{
60+
label: "Videos",
61+
href: "/resources/videos",
62+
icon: MdOndemandVideo,
63+
scope: "all",
64+
level: "secondary",
65+
},
5866
{
5967
label: "Community members",
6068
href: "/people",

src/lib/events.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,3 +411,7 @@ export function without<T extends CollectionEntry<"events">>(
411411
) {
412412
return events.filter((event) => event.data.status !== status);
413413
}
414+
415+
export function getTalksWithVOD() {
416+
return getCollection("talks", (talk) => talk.data.vod?.youtubeId);
417+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
import MainLayout from "@/layouts/MainLayout.astro";
3+
import MainPageTitle from "@/components/MainPageTitle/index.astro";
4+
import { SEO } from "astro-seo";
5+
import { getTalksWithVOD } from "@/lib/events";
6+
import VideoCard from "@/components/VideoCard/index.astro";
7+
import type { GetStaticPathsOptions } from "astro";
8+
import { isEmpty } from "remeda";
9+
import { cn } from "@/lib/utils-client";
10+
import { buttonVariants } from "@/components/ui/button";
11+
import { MdArrowBack, MdArrowForward } from "react-icons/md";
12+
import TiltedCard from "@/components/TiltedCard";
13+
14+
export async function getStaticPaths({ paginate }: GetStaticPathsOptions) {
15+
const allTalks = await getTalksWithVOD();
16+
return paginate(allTalks, { pageSize: 18 });
17+
}
18+
19+
const { page } = Astro.props;
20+
---
21+
22+
<MainLayout>
23+
<SEO
24+
slot="seo"
25+
title="Videos"
26+
description="Catch up on past Fork It! talks"
27+
noindex={isEmpty(page.data)}
28+
/>
29+
<div class="mx-auto w-full max-w-screen-sm px-4">
30+
<MainPageTitle
31+
title="Fork it! Vods"
32+
subtitle="Watch the community in action"
33+
blurImage
34+
/>
35+
</div>
36+
<div class="flex flex-1 flex-col">
37+
<div class="mx-auto flex w-full max-w-screen-lg flex-col gap-8 px-4 pb-40">
38+
{
39+
page.currentPage !== 1 && (
40+
<div class="flex items-center md:col-span-2">
41+
<h3 class="text-balance text-sm uppercase tracking-widest opacity-60">
42+
Page {page.currentPage}
43+
</h3>
44+
<div class="ml-auto flex gap-2">
45+
{!!page.url.prev && (
46+
<a
47+
href={page.url.prev}
48+
class={cn(
49+
buttonVariants({ size: "xs", variant: "secondary" }),
50+
"size-8 p-0",
51+
)}
52+
>
53+
<MdArrowBack className="size-4" />
54+
<span class="sr-only">Newer videos</span>
55+
</a>
56+
)}
57+
{!!page.url.next && (
58+
<a
59+
href={page.url.next}
60+
class={cn(
61+
buttonVariants({ size: "xs", variant: "secondary" }),
62+
"size-8 p-0",
63+
)}
64+
>
65+
<span class="sr-only">Older videos</span>
66+
<MdArrowForward className="size-4" />
67+
</a>
68+
)}
69+
</div>
70+
</div>
71+
)
72+
}
73+
74+
<section class="space-y-6">
75+
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
76+
{
77+
page.data.map((talk) => (
78+
<TiltedCard client:visible>
79+
<VideoCard talk={talk} />
80+
</TiltedCard>
81+
))
82+
}
83+
</div>
84+
</section>
85+
86+
<div class="flex items-center justify-between md:col-span-2">
87+
{
88+
!!page.url.prev && (
89+
<a
90+
href={page.url.prev}
91+
class={cn(buttonVariants({ variant: "secondary" }), "gap-2")}
92+
>
93+
<MdArrowBack />
94+
Newer <span class="max-xs:sr-only">videos</span>
95+
</a>
96+
)
97+
}
98+
{
99+
!!page.url.next && (
100+
<a
101+
href={page.url.next}
102+
class={cn(
103+
buttonVariants({ variant: "secondary" }),
104+
"ml-auto gap-2",
105+
)}
106+
>
107+
Older <span class="max-xs:sr-only">videos</span>
108+
<MdArrowForward />
109+
</a>
110+
)
111+
}
112+
</div>
113+
</div>
114+
</div>
115+
</MainLayout>

src/routes.gen.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const ROUTES_CONFIG = {
88
about: {},
99
"code-of-conduct": {},
1010
conferences: {
11-
"[...page]": {},
11+
":page": {},
1212
},
1313
events: {
1414
":id": {
@@ -92,7 +92,7 @@ const ROUTES_CONFIG = {
9292
},
9393
"llms.txt": {},
9494
news: {
95-
"[...page]": {},
95+
":page": {},
9696
article: {
9797
":id": {
9898
assets: {
@@ -127,6 +127,11 @@ const ROUTES_CONFIG = {
127127
},
128128
"rss.xml": {},
129129
},
130+
resources: {
131+
videos: {
132+
":page": {},
133+
},
134+
},
130135
} as const;
131136

132137
export const ROUTES = assignPaths(ROUTES_CONFIG);

0 commit comments

Comments
 (0)