69 lines
2.2 KiB
TypeScript
69 lines
2.2 KiB
TypeScript
import Link from "next/link";
|
|
import Image from "next/image";
|
|
import { urlFor } from "@/lib/sanityImage";
|
|
import type { SanityImageSource } from "@sanity/image-url";
|
|
|
|
export type BlogCardData = {
|
|
_id?: string;
|
|
title?: string;
|
|
subtitle?: string;
|
|
slug?: string;
|
|
author?: string;
|
|
publishDate?: string;
|
|
category?: string;
|
|
featuredImage?: SanityImageSource;
|
|
};
|
|
|
|
type Props = {
|
|
blog: BlogCardData;
|
|
className?: string;
|
|
};
|
|
|
|
function formatPublishDate(dateString?: string) {
|
|
if (!dateString) return null;
|
|
|
|
return new Intl.DateTimeFormat("en-US", {
|
|
month: "short",
|
|
day: "numeric",
|
|
year: "numeric",
|
|
}).format(new Date(dateString));
|
|
}
|
|
|
|
export function BlogCard({ blog, className = "" }: Props) {
|
|
const url = blog.slug ? `/blog/${blog.slug}` : "#";
|
|
const imageSrc = blog.featuredImage ? urlFor(blog.featuredImage).url() : null;
|
|
|
|
return (
|
|
<Link
|
|
href={url}
|
|
className={`group transition-color relative z-10 rounded-xl bg-lightbg shadow-lg ring-1 ring-lightline duration-300 ease-in-out hover:text-trptkblue hover:ring-lightline-hover dark:bg-darkbg dark:ring-darkline dark:hover:text-white dark:hover:ring-darkline-hover ${className}`}
|
|
>
|
|
<div className="relative aspect-square w-full overflow-hidden rounded-xl">
|
|
{imageSrc ? (
|
|
<Image
|
|
src={imageSrc}
|
|
alt={blog.title ? `Featured image for ${blog.title}` : "Blog post image"}
|
|
fill
|
|
className="object-cover"
|
|
sizes="(max-width: 560px) calc(100vw - 32px), 450px"
|
|
/>
|
|
) : (
|
|
<div className="absolute inset-0 bg-lightline-mid dark:bg-darkline-mid" />
|
|
)}
|
|
</div>
|
|
|
|
<div className="p-4 sm:p-5 sm:pb-15">
|
|
<div className="">
|
|
<h3 className="mb-2 break-words">{blog.title}</h3>
|
|
<h4 className="text-sm break-words text-lightsec dark:text-darksec">
|
|
{blog.subtitle || blog.category}
|
|
</h4>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="absolute right-4 bottom-4 left-4 hidden text-lightsec opacity-50 sm:right-5 sm:bottom-5 sm:left-5 sm:flex dark:text-darksec">
|
|
<span className="text-sm">{formatPublishDate(blog.publishDate)}</span>
|
|
</div>
|
|
</Link>
|
|
);
|
|
}
|