11import Image from 'next/image' ;
22import { notFound } from 'next/navigation' ;
33import groq from 'groq' ;
4+ import { getTranslations } from 'next-intl/server' ;
45import { client } from '@/client' ;
56
67type SocialLink = {
@@ -41,24 +42,24 @@ function plainTextFromPortableText(value: any): string {
4142
4243const query = groq `
4344 *[_type=="post" && slug.current==$slug][0]{
44- title,
45+ " title": coalesce(title[$locale], title.en, title) ,
4546 publishedAt,
4647 "mainImage": mainImage.asset->url,
4748 "categories": categories[]->title,
4849 tags,
4950 resourceLink,
5051
5152 "author": author->{
52- name,
53- company,
54- jobTitle,
55- city,
56- bio,
53+ " name": coalesce(name[$locale], name.en, name) ,
54+ " company": coalesce(company[$locale], company.en, company) ,
55+ " jobTitle": coalesce(jobTitle[$locale], jobTitle.en, jobTitle) ,
56+ " city": coalesce(city[$locale], city.en, city) ,
57+ " bio": coalesce(bio[$locale], bio.en, bio) ,
5758 "image": image.asset->url,
5859 socialMedia[]{ _key, platform, url }
5960 },
6061
61- body[]{
62+ " body": coalesce(body[$locale], body.en, body) []{
6263 ...,
6364 _type == "image" => {
6465 ...,
@@ -68,15 +69,32 @@ const query = groq`
6869 }
6970` ;
7071
71- export default async function PostDetails ( { slug } : { slug : string } ) {
72+ export default async function PostDetails ( {
73+ slug,
74+ locale,
75+ } : {
76+ slug : string ;
77+ locale : string ;
78+ } ) {
79+ const t = await getTranslations ( { locale, namespace : 'blog' } ) ;
7280 const slugParam = String ( slug || '' ) . trim ( ) ;
7381 if ( ! slugParam ) return notFound ( ) ;
7482
75- const post : Post | null = await client . fetch ( query , { slug : slugParam } ) ;
83+ const post : Post | null = await client . fetch ( query , {
84+ slug : slugParam ,
85+ locale,
86+ } ) ;
7687
7788 if ( ! post ?. title ) return notFound ( ) ;
7889
7990 const authorBio = plainTextFromPortableText ( post . author ?. bio ) ;
91+ const authorName = post . author ?. name ;
92+ const authorMetaParts = [
93+ post . author ?. jobTitle ,
94+ post . author ?. company ,
95+ post . author ?. city ,
96+ ] . filter ( Boolean ) as string [ ] ;
97+ const authorMeta = authorMetaParts . join ( ' · ' ) ;
8098
8199 return (
82100 < main className = "max-w-3xl mx-auto px-6 py-12" >
@@ -113,12 +131,12 @@ export default async function PostDetails({ slug }: { slug: string }) {
113131 ) }
114132
115133 { post . mainImage && (
116- < div className = "relative w-full h-[320px ] rounded-2xl overflow-hidden border border-gray-200 my-8" >
134+ < div className = "relative w-full h-[420px ] rounded-2xl overflow-hidden border border-gray-200 my-8" >
117135 < Image
118136 src = { post . mainImage }
119137 alt = { post . title || 'Post image' }
120138 fill
121- className = "object-cover"
139+ className = "object-cover object-top scale-[1.05] "
122140 />
123141 </ div >
124142 ) }
@@ -160,12 +178,37 @@ export default async function PostDetails({ slug }: { slug: string }) {
160178 </ div >
161179 ) }
162180
163- { ( authorBio || post . author ?. jobTitle ) && (
181+ { ( authorBio || authorName || authorMeta ) && (
164182 < section className = "mt-12 p-6 rounded-2xl border border-gray-200 bg-white" >
165- < h2 className = "text-lg font-semibold" > About the author</ h2 >
166- < p className = "mt-2 text-sm text-gray-700 whitespace-pre-line" >
167- { authorBio }
168- </ p >
183+ < h2 className = "text-lg font-semibold" > { t ( 'aboutAuthor' ) } </ h2 >
184+ < div className = "mt-4 flex items-start gap-4" >
185+ { post . author ?. image && (
186+ < div className = "relative w-14 h-14 shrink-0" >
187+ < Image
188+ src = { post . author . image }
189+ alt = { authorName || 'Author' }
190+ fill
191+ className = "rounded-full object-cover border border-gray-200"
192+ />
193+ </ div >
194+ ) }
195+
196+ < div className = "min-w-0" >
197+ { authorName && (
198+ < p className = "text-sm font-semibold text-gray-900" >
199+ { authorName }
200+ </ p >
201+ ) }
202+ { authorMeta && (
203+ < p className = "mt-1 text-sm text-gray-600" > { authorMeta } </ p >
204+ ) }
205+ { authorBio && (
206+ < p className = "mt-3 text-sm text-gray-700 whitespace-pre-line leading-relaxed" >
207+ { authorBio }
208+ </ p >
209+ ) }
210+ </ div >
211+ </ div >
169212 </ section >
170213 ) }
171214 </ main >
0 commit comments