mirror of
https://github.com/Dokploy/website
synced 2025-06-26 18:16:01 +00:00
feat: enhance blog post author display with Twitter links and default image
This commit is contained in:
@@ -167,17 +167,44 @@ export default async function BlogPostPage({ params }: Props) {
|
|||||||
<div className="flex items-center mb-6">
|
<div className="flex items-center mb-6">
|
||||||
{post.primary_author?.profile_image && (
|
{post.primary_author?.profile_image && (
|
||||||
<div className="relative h-12 w-12 rounded-full overflow-hidden mr-4">
|
<div className="relative h-12 w-12 rounded-full overflow-hidden mr-4">
|
||||||
<Image
|
{post.primary_author.twitter ? (
|
||||||
src={post.primary_author.profile_image}
|
<a
|
||||||
alt={post.primary_author.name}
|
href={`https://twitter.com/${post.primary_author.twitter}`}
|
||||||
fill
|
target="_blank"
|
||||||
className="object-cover"
|
rel="noopener noreferrer"
|
||||||
/>
|
className="block cursor-pointer transition-opacity hover:opacity-90"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={post.primary_author.profile_image}
|
||||||
|
alt={post.primary_author.name}
|
||||||
|
fill
|
||||||
|
className="object-cover"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<Image
|
||||||
|
src={post.primary_author.profile_image}
|
||||||
|
alt={post.primary_author.name}
|
||||||
|
fill
|
||||||
|
className="object-cover"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium">
|
<p className="font-medium">
|
||||||
{post.primary_author?.name || "Unknown Author"}
|
{post.primary_author?.twitter ? (
|
||||||
|
<a
|
||||||
|
href={`https://twitter.com/${post.primary_author.twitter}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="hover:text-primary transition-colors"
|
||||||
|
>
|
||||||
|
{post.primary_author.name || "Unknown Author"}
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
post.primary_author?.name || "Unknown Author"
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
{formattedDate} • {post.reading_time} min read
|
{formattedDate} • {post.reading_time} min read
|
||||||
|
|||||||
94
apps/website/app/[locale]/blog/components/BlogPostCard.tsx
Normal file
94
apps/website/app/[locale]/blog/components/BlogPostCard.tsx
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import type { Post } from "@/lib/ghost";
|
||||||
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
interface BlogPostCardProps {
|
||||||
|
post: Post;
|
||||||
|
locale: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BlogPostCard({ post, locale }: BlogPostCardProps) {
|
||||||
|
const formattedDate = new Date(post.published_at).toLocaleDateString(locale, {
|
||||||
|
year: "numeric",
|
||||||
|
month: "long",
|
||||||
|
day: "numeric",
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
href={`/blog/${post.slug}`}
|
||||||
|
className="group block hover:bg-muted p-4 rounded-lg"
|
||||||
|
>
|
||||||
|
<article className="flex gap-6 items-start">
|
||||||
|
{post.feature_image && (
|
||||||
|
<div className="relative h-32 w-48 shrink-0">
|
||||||
|
<Image
|
||||||
|
src={post.feature_image}
|
||||||
|
alt={post.title}
|
||||||
|
fill
|
||||||
|
className="object-cover rounded-lg"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<h2 className="text-xl font-semibold mb-2 group-hover:text-primary">
|
||||||
|
{post.title}
|
||||||
|
</h2>
|
||||||
|
<p className="text-muted-foreground line-clamp-2 mb-4">
|
||||||
|
{post.custom_excerpt || post.excerpt}
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center text-sm text-muted-foreground">
|
||||||
|
<div className="flex items-center">
|
||||||
|
{post.primary_author?.profile_image && (
|
||||||
|
<div className="relative h-6 w-6 rounded-full overflow-hidden mr-2">
|
||||||
|
{post.primary_author.twitter ? (
|
||||||
|
<a
|
||||||
|
href={`https://twitter.com/${post.primary_author.twitter}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="block cursor-pointer transition-opacity hover:opacity-90"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={post.primary_author.profile_image}
|
||||||
|
alt={post.primary_author.name}
|
||||||
|
fill
|
||||||
|
className="object-cover"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<Image
|
||||||
|
src={post.primary_author.profile_image}
|
||||||
|
alt={post.primary_author.name}
|
||||||
|
fill
|
||||||
|
className="object-cover"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{post.primary_author?.twitter ? (
|
||||||
|
<a
|
||||||
|
href={`https://twitter.com/${post.primary_author.twitter}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="hover:text-primary transition-colors"
|
||||||
|
>
|
||||||
|
{post.primary_author.name || "Unknown Author"}
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<span>{post.primary_author?.name || "Unknown Author"}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<span className="mx-2">in</span>
|
||||||
|
<span>{post.primary_tag?.name || "General"}</span>
|
||||||
|
<span className="mx-2">•</span>
|
||||||
|
<span>{post.reading_time} min read</span>
|
||||||
|
<span className="mx-2">•</span>
|
||||||
|
<span>{formattedDate}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -102,7 +102,7 @@ function BlogPostCard({ post, locale }: { post: Post; locale: string }) {
|
|||||||
className="group block hover:bg-muted p-4 rounded-lg"
|
className="group block hover:bg-muted p-4 rounded-lg"
|
||||||
>
|
>
|
||||||
<article className="flex gap-6 items-start">
|
<article className="flex gap-6 items-start">
|
||||||
{post.feature_image && (
|
{post.feature_image ? (
|
||||||
<div className="relative h-32 w-48 shrink-0">
|
<div className="relative h-32 w-48 shrink-0">
|
||||||
<Image
|
<Image
|
||||||
src={post.feature_image}
|
src={post.feature_image}
|
||||||
@@ -111,6 +111,15 @@ function BlogPostCard({ post, locale }: { post: Post; locale: string }) {
|
|||||||
className="object-cover rounded-lg"
|
className="object-cover rounded-lg"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="relative h-32 w-48 shrink-0">
|
||||||
|
<Image
|
||||||
|
src={"/default.jpg"}
|
||||||
|
alt="Default Image"
|
||||||
|
fill
|
||||||
|
className="object-cover rounded-lg"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<h2 className="text-xl font-semibold mb-2 group-hover:text-primary">
|
<h2 className="text-xl font-semibold mb-2 group-hover:text-primary">
|
||||||
@@ -123,15 +132,42 @@ function BlogPostCard({ post, locale }: { post: Post; locale: string }) {
|
|||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
{post.primary_author?.profile_image && (
|
{post.primary_author?.profile_image && (
|
||||||
<div className="relative h-6 w-6 rounded-full overflow-hidden mr-2">
|
<div className="relative h-6 w-6 rounded-full overflow-hidden mr-2">
|
||||||
<Image
|
{post.primary_author.twitter ? (
|
||||||
src={post.primary_author.profile_image}
|
<a
|
||||||
alt={post.primary_author.name}
|
href={`https://twitter.com/${post.primary_author.twitter}`}
|
||||||
fill
|
target="_blank"
|
||||||
className="object-cover"
|
rel="noopener noreferrer"
|
||||||
/>
|
className="block cursor-pointer transition-opacity hover:opacity-90"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={post.primary_author.profile_image}
|
||||||
|
alt={post.primary_author.name}
|
||||||
|
fill
|
||||||
|
className="object-cover"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<Image
|
||||||
|
src={post.primary_author.profile_image}
|
||||||
|
alt={post.primary_author.name}
|
||||||
|
fill
|
||||||
|
className="object-cover"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<span>{post.primary_author?.name || "Unknown Author"}</span>
|
{post.primary_author?.twitter ? (
|
||||||
|
<a
|
||||||
|
href={`https://twitter.com/${post.primary_author.twitter}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="hover:text-primary transition-colors"
|
||||||
|
>
|
||||||
|
{post.primary_author.name || "Unknown Author"}
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<span>{post.primary_author?.name || "Unknown Author"}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<span className="mx-2">in</span>
|
<span className="mx-2">in</span>
|
||||||
<span>{post.primary_tag?.name || "General"}</span>
|
<span>{post.primary_tag?.name || "General"}</span>
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ export interface Post {
|
|||||||
slug: string;
|
slug: string;
|
||||||
profile_image: string | null;
|
profile_image: string | null;
|
||||||
bio: string | null;
|
bio: string | null;
|
||||||
|
twitter: string | null;
|
||||||
};
|
};
|
||||||
authors?: Array<{
|
authors?: Array<{
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
BIN
apps/website/public/default.jpg
Normal file
BIN
apps/website/public/default.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
Reference in New Issue
Block a user