create post completed

This commit is contained in:
libertyoms
2025-04-21 20:59:37 +02:00
parent 629da1b7e7
commit a8c6b5297b
21 changed files with 1973 additions and 37 deletions

View File

@ -0,0 +1,40 @@
import React from "react";
import { auth } from "@/auth";
import { redirect } from "next/navigation";
import CreatePostForm from "@/components/CreatePostForm";
import type { Metadata } from "next";
// Metadata for the page, preventing search engine indexing
export const metadata: Metadata = {
title: "Create New TechTalk Post | OMS",
description: "Create a new blog post for OMS TechTalk.",
robots: { index: false, follow: false }, // Don't index the creation page
};
// Page component to render the creation form
export default async function CreateTechTalkPage() {
const session = await auth();
// Protect the route: Redirect if not logged in
if (!session?.user) {
// Redirect to sign-in page, passing the current page as callbackUrl
// This ensures the user returns here after successful login
const callbackUrl = encodeURIComponent("/tech-talk/create");
redirect(`/api/auth/signin?callbackUrl=${callbackUrl}`);
}
// Render the page content if the user is authenticated
return (
<div className="bg-background text-foreground">
<div className="container mx-auto px-4 py-16 sm:py-20 lg:py-24">
<div className="max-w-3xl mx-auto bg-card p-6 sm:p-8 rounded-lg border border-border shadow-md">
<h1 className="text-3xl md:text-4xl font-bold mb-8 text-center text-primary">
Create New TechTalk Post
</h1>
{/* Render the form component */}
<CreatePostForm />
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,124 @@
import React from "react";
import BlogPostCard from "@/components/BlogPostCard";
import { prisma } from "@/lib/prisma"; // Import Prisma client
import { auth } from "@/auth"; // Import auth to check session
import Button from "@/components/ui/Button"; // Import Button component
import type { Metadata } from "next";
interface Post {
id: string;
slug: string;
title: string;
content: string;
excerpt?: string | null;
imageUrl?: string | null;
published: boolean;
authorId: string;
createdAt: Date;
updatedAt: Date;
tags?: string[];
}
// --- Fetch Posts ---
async function getPublishedPosts() {
try {
const posts = await prisma.post.findMany({
where: { published: true },
orderBy: { createdAt: "desc" },
// select needed fields if not all
});
return posts;
} catch (error) {
console.error("Failed to fetch posts:", error);
return []; // Return empty array on error
}
}
// --- SEO Metadata ---
export const metadata: Metadata = {
title: "OMS TechTalk | Insights & Innovation",
description:
"Explore the latest insights, trends, and discussions on technology, innovation, and digital transformation from the experts at Owethu Managed Services (OMS).",
alternates: {
canonical: "/tech-talk",
},
openGraph: {
title: "OMS TechTalk | Insights & Innovation",
description: "Stay updated with tech insights from OMS.",
url: "https://oms.africa/tech-talk",
images: [
{
url: "/og-image-techtalk.jpg",
width: 1200,
height: 630,
alt: "OMS TechTalk Banner",
},
],
},
twitter: {
card: "summary_large_image",
title: "OMS TechTalk | Insights & Innovation",
description: "Tech insights and articles from Owethu Managed Services.",
images: ["/og-image-techtalk.jpg"],
},
};
// --- Page Component ---
const TechTalkPage = async () => {
const posts = await getPublishedPosts();
const session = await auth(); // Get session info
return (
<div className="bg-background text-foreground">
<div className="container mx-auto px-4 py-16 sm:py-20 lg:py-24">
{/* Page Header */}
<div className="text-center mb-12 md:mb-16">
<h1 className="text-4xl md:text-5xl font-bold mb-4 text-primary">
OMS TechTalk
</h1>
<p className="text-lg md:text-xl text-muted-foreground max-w-2xl mx-auto">
Insights, trends, and discussions on the latest in technology,
innovation, and digital transformation from the experts at OMS.
</p>
{/* Conditionally render Create Post button */}
{session?.user && (
<div className="mt-8">
<Button href="/tech-talk/create" variant="primary">
Create New Post
</Button>
</div>
)}
</div>
{/* Blog Post Grid */}
{posts.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8 md:gap-10">
{posts.map((post: Post) => (
<BlogPostCard
key={post.id} // Use post ID as key
slug={post.slug}
title={post.title}
excerpt={post.excerpt ?? post.content.substring(0, 150) + "..."}
// Use imageUrl from DB or a default placeholder
imageUrl={post.imageUrl ?? "/posts/default-placeholder.jpg"} // Provide a default image
author={"OMS Team"} // Replace with actual author logic if available (e.g., post.user.name)
date={new Date(post.createdAt).toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
})}
/>
))}
</div>
) : (
<p className="text-center text-muted-foreground">
No posts published yet. Check back soon!
</p>
)}
{/* TODO: Add Pagination component here if needed */}
</div>
</div>
);
};
export default TechTalkPage;

View File

@ -4,7 +4,7 @@ import { PacmanLoader } from "react-spinners";
const Loading = () => {
return (
<div className="flex items-center justify-center h-screen">
<PacmanLoader />
<PacmanLoader color="#e1c44a" />
</div>
);
};