added dates in the site
This commit is contained in:
parent
7a27e2b79e
commit
5bf1589b7a
5 changed files with 86 additions and 59 deletions
|
@ -4,8 +4,9 @@ import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { ArrowLeft } from "lucide-react";
|
import { ArrowLeft } from "lucide-react";
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import NotFound from "@/app/not-found";
|
import { notFound } from "next/navigation";
|
||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
|
||||||
async function getData(slug: string) {
|
async function getData(slug: string) {
|
||||||
const query = `
|
const query = `
|
||||||
|
@ -13,7 +14,8 @@ async function getData(slug: string) {
|
||||||
"currentSlug": slug.current,
|
"currentSlug": slug.current,
|
||||||
title,
|
title,
|
||||||
content,
|
content,
|
||||||
titleImage
|
titleImage,
|
||||||
|
_createdAt
|
||||||
}[0]`;
|
}[0]`;
|
||||||
|
|
||||||
const data = await client.fetch(query);
|
const data = await client.fetch(query);
|
||||||
|
@ -25,6 +27,7 @@ interface BlogSlugArticle {
|
||||||
title: string;
|
title: string;
|
||||||
content: any;
|
content: any;
|
||||||
titleImage: string;
|
titleImage: string;
|
||||||
|
_createdAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
|
@ -77,9 +80,11 @@ export default async function BlogSlugArticle({
|
||||||
const data: BlogSlugArticle = await getData(params.slug);
|
const data: BlogSlugArticle = await getData(params.slug);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return <NotFound />;
|
notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const formattedDate = format(new Date(data._createdAt), "MMMM d, yyyy");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className="max-w-5xl container mx-auto py-8 md:py-28 flex flex-col items-center px-4">
|
<section className="max-w-5xl container mx-auto py-8 md:py-28 flex flex-col items-center px-4">
|
||||||
|
@ -90,10 +95,10 @@ export default async function BlogSlugArticle({
|
||||||
<ArrowLeft className="mr-2" />
|
<ArrowLeft className="mr-2" />
|
||||||
Back to Blog
|
Back to Blog
|
||||||
</Link>
|
</Link>
|
||||||
<header className="text-start mb-12 w-full">
|
<header className="text-start mb-8 w-full">
|
||||||
{data.titleImage && (
|
{data.titleImage && (
|
||||||
<div className="mb-8">
|
<div className="mb-2">
|
||||||
<h1 className="text-3xl md:text-5xl mb-12 font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
|
<h1 className="text-3xl md:text-5xl mb-12 py-4 font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
|
||||||
{data.title}
|
{data.title}
|
||||||
</h1>
|
</h1>
|
||||||
<Image
|
<Image
|
||||||
|
@ -104,6 +109,9 @@ export default async function BlogSlugArticle({
|
||||||
priority
|
priority
|
||||||
className="w-full h-auto object-cover rounded-md"
|
className="w-full h-auto object-cover rounded-md"
|
||||||
/>
|
/>
|
||||||
|
<p className="mt-4 text-xl text-muted-foreground">
|
||||||
|
Uploaded at {formattedDate}
|
||||||
|
</p>{" "}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</header>
|
</header>
|
||||||
|
|
19
app/(root)/not-found.tsx
Normal file
19
app/(root)/not-found.tsx
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
const NotFound = () => {
|
||||||
|
return (
|
||||||
|
<section id="404error" className="flex-center flex-col wrapper container">
|
||||||
|
<h1 className="text-3xl md:text-5xl text-center">
|
||||||
|
<span className="text-red-500">404</span> Page not Found
|
||||||
|
</h1>
|
||||||
|
<p className="text-lg mt-3 text-muted-foreground">
|
||||||
|
Please return back to{" "}
|
||||||
|
<Link href="/" className="underline font-bold">
|
||||||
|
Home
|
||||||
|
</Link>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NotFound;
|
|
@ -1,19 +0,0 @@
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const NotFound = () => {
|
|
||||||
return (
|
|
||||||
<section id="404error" className="flex-center flex-col wrapper container">
|
|
||||||
<h1 className="text-3xl md:text-5xl text-center">
|
|
||||||
<span className="text-red-500">404</span> Page not Found
|
|
||||||
</h1>
|
|
||||||
<p className="text-lg mt-3 text-muted-foreground">
|
|
||||||
Please return back to{" "}
|
|
||||||
<Link href="/" className="underline font-bold">
|
|
||||||
Home
|
|
||||||
</Link>
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NotFound;
|
|
|
@ -12,12 +12,14 @@ import {
|
||||||
PaginationNext,
|
PaginationNext,
|
||||||
PaginationPrevious,
|
PaginationPrevious,
|
||||||
} from "@/components/ui/pagination";
|
} from "@/components/ui/pagination";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
|
||||||
interface BlogPostcard {
|
interface BlogPostcard {
|
||||||
title: string;
|
title: string;
|
||||||
smallDescription: string;
|
smallDescription: string;
|
||||||
currentSlug: string;
|
currentSlug: string;
|
||||||
titleImage: string;
|
titleImage: string;
|
||||||
|
_createdAt: string; // Add createdAt field
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BlogCardsProps {
|
interface BlogCardsProps {
|
||||||
|
@ -33,7 +35,8 @@ const BlogCards: React.FC<BlogCardsProps> = async ({ searchParams }) => {
|
||||||
title,
|
title,
|
||||||
smallDescription,
|
smallDescription,
|
||||||
"currentSlug": slug.current,
|
"currentSlug": slug.current,
|
||||||
titleImage
|
titleImage,
|
||||||
|
_createdAt
|
||||||
}[${(currentPage - 1) * cardsPerPage}...${currentPage * cardsPerPage}]`;
|
}[${(currentPage - 1) * cardsPerPage}...${currentPage * cardsPerPage}]`;
|
||||||
|
|
||||||
const posts: BlogPostcard[] = await client.fetch(query);
|
const posts: BlogPostcard[] = await client.fetch(query);
|
||||||
|
@ -47,7 +50,13 @@ const BlogCards: React.FC<BlogCardsProps> = async ({ searchParams }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className="grid max-w-6xl gap-4 mx-auto sm:grid-cols-2 lg:grid-cols-3">
|
<section className="grid max-w-6xl gap-4 mx-auto sm:grid-cols-2 lg:grid-cols-3">
|
||||||
{posts.map((post, idx) => (
|
{posts.map((post, idx) => {
|
||||||
|
const formattedDate = format(
|
||||||
|
new Date(post._createdAt),
|
||||||
|
"MMMM d, yyyy"
|
||||||
|
); // Format the date
|
||||||
|
|
||||||
|
return (
|
||||||
<Card
|
<Card
|
||||||
className="group h-full w-full rounded-lg border overflow-hidden"
|
className="group h-full w-full rounded-lg border overflow-hidden"
|
||||||
key={idx}
|
key={idx}
|
||||||
|
@ -75,10 +84,15 @@ const BlogCards: React.FC<BlogCardsProps> = async ({ searchParams }) => {
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
{post.smallDescription}
|
{post.smallDescription}
|
||||||
</p>
|
</p>
|
||||||
|
<p className="text-xs text-muted-foreground mt-2">
|
||||||
|
Published on: {formattedDate}{" "}
|
||||||
|
{/* Display the formatted date */}
|
||||||
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Link>
|
</Link>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</section>
|
</section>
|
||||||
<div className="flex-center mt-12">
|
<div className="flex-center mt-12">
|
||||||
{totalPages > 1 && (
|
{totalPages > 1 && (
|
||||||
|
|
|
@ -21,6 +21,11 @@ export default {
|
||||||
type: 'image',
|
type: 'image',
|
||||||
title: 'Title Image',
|
title: 'Title Image',
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// name: 'publishedAt',
|
||||||
|
// title: 'Published At',
|
||||||
|
// type: 'datetime',
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
name: 'smallDescription',
|
name: 'smallDescription',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
|
Loading…
Reference in a new issue