-
Notifications
You must be signed in to change notification settings - Fork 181
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
153 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
'use client'; | ||
|
||
import { motion } from 'framer-motion'; | ||
import { Calendar, Clock } from 'lucide-react'; | ||
import { Card, CardContent } from '@/components/ui/card'; | ||
import Link from 'next/link'; | ||
import { getRandomImage } from '@/components/blog/random-image'; | ||
|
||
interface BlogCardProps { | ||
href: string; | ||
title: string; | ||
description: string; | ||
date: string; | ||
readTime?: string; | ||
} | ||
|
||
export default function BlogCard({ href, title, description, date, readTime = '5 min read' }: BlogCardProps) { | ||
return ( | ||
<Link href={href} className="block size-full max-w-sm mx-auto"> | ||
<motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.5 }} className="h-full"> | ||
<Card className="overflow-hidden bg-white dark:bg-gray-800 hover:shadow-xl transition-all duration-300 group h-full flex flex-col"> | ||
<div className="relative h-48 overflow-hidden"> | ||
<img | ||
src={getRandomImage()} | ||
alt={title} | ||
className="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105" | ||
/> | ||
</div> | ||
|
||
<CardContent className="p-6 flex flex-col flex-grow"> | ||
<h2 className="text-xl font-semibold mb-3 text-gray-800 dark:text-gray-100 transition-transform duration-300 group-hover:translate-x-2"> | ||
{title} | ||
</h2> | ||
|
||
<p className="text-gray-600 dark:text-gray-300 mb-4 line-clamp-3 flex-grow">{description}</p> | ||
|
||
<div className="flex items-center space-x-4 text-sm text-gray-500 dark:text-gray-400 mt-auto"> | ||
<div className="flex items-center"> | ||
<Calendar className="w-4 h-4 mr-2" /> | ||
<span>{date}</span> | ||
</div> | ||
<div className="flex items-center"> | ||
<Clock className="w-4 h-4 mr-2" /> | ||
<span>{readTime}</span> | ||
</div> | ||
</div> | ||
</CardContent> | ||
</Card> | ||
</motion.div> | ||
</Link> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import BlogCard from '@/components/blog/blog-card'; | ||
import LatestBlogCard from '@/components/blog/latest-blog-card'; | ||
import { formatDate } from '@/lib/utils'; | ||
|
||
export function BlogPosts({ posts }) { | ||
const latestPost = posts[0]; | ||
return ( | ||
<div className="container space-y-10 py-6 md:py-10"> | ||
<section> | ||
<h2 className="mb-4 font-bold text-2xl">Latest Post</h2> | ||
<LatestBlogCard | ||
key={latestPost._id} | ||
title={latestPost.title} | ||
description={latestPost.description} | ||
date={formatDate(latestPost.date)} | ||
href={latestPost.slug} | ||
/> | ||
</section> | ||
|
||
<section> | ||
<h2 className="mb-4 font-bold text-2xl">Blog Posts</h2> | ||
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3"> | ||
{posts.slice(1).map((post) => ( | ||
<BlogCard key={post._id} title={post.title} description={post.description} date={formatDate(post.date)} href={post.slug} /> | ||
))} | ||
</div> | ||
</section> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
'use client'; | ||
|
||
import { motion } from 'framer-motion'; | ||
import { Calendar, Clock } from 'lucide-react'; | ||
import { Card, CardContent } from '@/components/ui/card'; | ||
import Link from 'next/link'; | ||
import { getRandomImage } from '@/components/blog/random-image'; | ||
|
||
interface LastBlogCardProps { | ||
href: string; | ||
title: string; | ||
description: string; | ||
date: string; | ||
readTime?: string; | ||
} | ||
|
||
export default function LatestBlogCard({ href, title, description, date, readTime = '8 min read' }: LastBlogCardProps) { | ||
return ( | ||
<Link href={href} className="block w-full"> | ||
<motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.5 }}> | ||
<Card className="overflow-hidden bg-white dark:bg-gray-800 hover:shadow-xl transition-all duration-300 group"> | ||
<CardContent className="p-0"> | ||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> | ||
<div className="relative h-64 md:h-full overflow-hidden"> | ||
<img | ||
src={getRandomImage()} | ||
alt={title} | ||
className="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105" | ||
/> | ||
</div> | ||
|
||
<div className="p-6 flex flex-col justify-between h-full"> | ||
<div className="py-10"> | ||
<h2 className="text-xl font-semibold mb-4 text-gray-800 dark:text-gray-100 transition-transform duration-300 group-hover:translate-x-2"> | ||
{title} | ||
</h2> | ||
|
||
<p className="text-gray-600 dark:text-gray-300 mt-6 line-clamp-3">{description}</p> | ||
</div> | ||
<div className="flex items-center space-x-4 text-sm text-gray-500 dark:text-gray-400 pb-10"> | ||
<div className="flex items-center"> | ||
<Calendar className="w-4 h-4 mr-2" /> | ||
<span>{date}</span> | ||
</div> | ||
<div className="flex items-center"> | ||
<Clock className="w-4 h-4 mr-2" /> | ||
<span>{readTime}</span> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</CardContent> | ||
</Card> | ||
</motion.div> | ||
</Link> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const imageList = [ | ||
'https://images.unsplash.com/photo-1616071906060-1f425a639465', | ||
'https://images.unsplash.com/photo-1643986149937-5d0b9306dba5', | ||
'https://images.unsplash.com/photo-1629140476584-f10ee7810d2c', | ||
'https://images.unsplash.com/photo-1608501712351-a4ca8dc996fb', | ||
'https://images.unsplash.com/photo-1495785870240-c8456d5aeda2', | ||
'https://images.unsplash.com/photo-1616071906060-1f425a639465', | ||
]; | ||
|
||
export const getRandomImage = () => { | ||
const randomIndex = Math.floor(Math.random() * imageList.length); | ||
return imageList[randomIndex]; | ||
}; |