11---
2- import { getCollection } from ' astro:content' ;
3- import BaseLayout from ' ../../layout/BaseLayout.astro' ;
4- import { formatDate } from ' ../../utils/utils' ;
5- import { Image } from ' astro:assets' ;
2+ import { getCollection } from " astro:content" ;
3+ import BaseLayout from " ../../layout/BaseLayout.astro" ;
4+ import { formatDate } from " ../../utils/utils" ;
5+ import { Image } from " astro:assets" ;
66import Icon from " ../../components/ui/icons/Icon.astro" ;
77
88const seo = {
9- title: ' Blog | CVD-Net' ,
10- description: ' Read the latest updates and insights from the CVD-Net project team.' ,
9+ title: " Blog | CVD-Net" ,
10+ description:
11+ " Read the latest updates and insights from the CVD-Net project team." ,
1112};
1213
1314// Fetch blog posts, sort by publish date (newest first)
14- const posts = (await getCollection (' blog' )).sort (
15- (a , b ) => b .data .publishDate .valueOf () - a .data .publishDate .valueOf ()
15+ const posts = (await getCollection (" blog" )).sort (
16+ (a , b ) => b .data .publishDate .valueOf () - a .data .publishDate .valueOf ()
1617);
1718---
19+
1820<BaseLayout seo ={ seo } >
19- <div class =" container mx-auto max-w-6xl px-4 py-12" >
20- <div class =" mx-auto max-w-4xl text-center mb-12" >
21- <h1 class =" mb-4 text-4xl font-bold text-slate-800 lg:text-5xl" >Blog</h1 >
22- <p class =" mb-8 text-lg text-slate-600 max-w-3xl mx-auto" >
23- Stay up-to-date with the latest news, updates, and insights from the CVD-Net project team.
24- </p >
25- </div >
21+ <div class =" container mx-auto max-w-6xl px-4 py-12" >
22+ <div class =" mx-auto mb-12 max-w-4xl text-center" >
23+ <h1 class =" mb-4 text-4xl font-bold text-slate-800 lg:text-5xl" >
24+ Blog
25+ </h1 >
26+ <p class =" mx-auto mb-8 max-w-3xl text-lg text-slate-600" >
27+ Stay up-to-date with the latest news, updates, and insights from
28+ the CVD-Net project team.
29+ </p >
30+ </div >
31+
32+ <div class =" grid gap-8 md:grid-cols-2 lg:grid-cols-3" >
33+ {
34+ posts .map ((post ) => (
35+ <div class = " group flex h-full flex-col overflow-hidden rounded-lg border border-slate-200 bg-white shadow-sm transition-all hover:shadow-md" >
36+ <div class = " relative aspect-video overflow-hidden" >
37+ { post .data .coverImage ? (
38+ <Image
39+ src = { post .data .coverImage }
40+ alt = { post .data .title }
41+ width = { 400 }
42+ height = { 225 }
43+ class = " h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
44+ />
45+ ) : (
46+ <div class = " flex h-full w-full items-center justify-center bg-slate-100" >
47+ <Icon
48+ name = " ph:file-text-duotone"
49+ size = " 64px"
50+ class = " text-slate-400"
51+ />
52+ </div >
53+ )}
54+ </div >
55+ <div class = " flex flex-1 flex-col p-6" >
56+ <div class = " mb-3 flex items-center gap-2" >
57+ <span class = " text-sm text-slate-500" >
58+ { formatDate (post .data .publishDate )}
59+ </span >
60+ { post .data .author && (
61+ <>
62+ <span class = " text-slate-300" >•</span >
63+ <span class = " text-sm text-slate-500" >
64+ { post .data .author }
65+ </span >
66+ </>
67+ )}
68+ </div >
69+
70+ <h2 class = " mb-2 text-2xl font-semibold text-slate-800" >
71+ { post .data .title }
72+ </h2 >
73+ <p class = " mb-4 flex-1 text-slate-600" >
74+ { post .data .description }
75+ </p >
76+
77+ <a
78+ href = { ` ${import .meta .env .BASE_URL }/blog/${post .slug } ` }
79+ class = " inline-flex items-center justify-center rounded-md bg-teal-600 px-4 py-2 text-sm font-medium text-white shadow transition-colors hover:bg-teal-700 focus:ring-2 focus:ring-teal-500/40 focus:outline-none"
80+ >
81+ Read more
82+ </a >
83+ </div >
84+ </div >
85+ ))
86+ }
87+ </div >
2688
27- <div class =" grid gap-8 md:grid-cols-2 lg:grid-cols-3" >
28- { posts .map ((post ) => (
29- <div class = " group flex flex-col h-full overflow-hidden rounded-lg border border-slate-200 bg-white shadow-sm transition-all hover:shadow-md" >
30- <div class = " relative aspect-video overflow-hidden" >
31- { post .data .coverImage ? (
32- <Image
33- src = { post .data .coverImage }
34- alt = { post .data .title }
35- width = { 400 }
36- height = { 225 }
37- class = " h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
38- />
39- ) : (
40- <div class = " flex h-full w-full items-center justify-center bg-slate-100" >
41- <Icon name = " ph:file-text-duotone" size = " 64px" class = " text-slate-400" />
42- </div >
43- )}
44- </div >
45- <div class = " flex flex-1 flex-col p-6" >
46- <div class = " flex items-center gap-2 mb-3" >
47- <span class = " text-sm text-slate-500" >
48- { formatDate (post .data .publishDate )}
49- </span >
50- { post .data .author && (
51- <>
52- <span class = " text-slate-300" >•</span >
53- <span class = " text-sm text-slate-500" >{ post .data .author } </span >
54- </>
55- )}
56- </div >
57-
58- <h2 class = " mb-2 text-2xl font-semibold text-slate-800" >{ post .data .title } </h2 >
59- <p class = " mb-4 flex-1 text-slate-600" >{ post .data .description } </p >
60-
61- <a
62- href = { ` /blog/${post .slug }/ ` }
63- class = " inline-flex items-center justify-center rounded-md bg-teal-600 px-4 py-2 text-sm font-medium text-white shadow transition-colors hover:bg-teal-700 focus:outline-none focus:ring-2 focus:ring-teal-500/40"
64- >
65- Read more
66- </a >
67- </div >
68- </div >
69- ))}
70- </div >
71-
72- { posts .length === 0 && (
73- <div class = " text-center py-16" >
74- <Icon name = " ph:newspaper-duotone" size = " 64px" class = " text-slate-300 mx-auto mb-4" />
75- <p class = " text-xl text-slate-600" >No blog posts found yet. Check back soon!</p >
76- </div >
77- )}
78- </div >
79- </BaseLayout >
89+ {
90+ posts .length === 0 && (
91+ <div class = " py-16 text-center" >
92+ <Icon
93+ name = " ph:newspaper-duotone"
94+ size = " 64px"
95+ class = " mx-auto mb-4 text-slate-300"
96+ />
97+ <p class = " text-xl text-slate-600" >
98+ No blog posts found yet. Check back soon!
99+ </p >
100+ </div >
101+ )
102+ }
103+ </div >
104+ </BaseLayout >
0 commit comments