app\posts\page.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | //app\posts\page.tsx import { Suspense } from "react" ; import { Spinner } from "@/components/spinner" ; import PostTable from "@/components/tableposts" ; const Posts = async () => { return ( <div className= "max-w-screen-lg mx-auto py-14" > <h1 className= "text-4xl font-bold" >Nextjs + WordPress Load Posts with Featured Image and View Single Page</h1> <div className= "flex items-end justify-between m-12" > <h1 className= "text-4xl font-bold" >Latest Post</h1> </div> <Suspense fallback={<Spinner />}> <PostTable/> </Suspense> </div> ); }; export default Posts; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | //app\components\tableposts.tsx import Image from "next/image" ; import Link from "next/link" ; import { formatDate } from "@/lib/utils" ; const PostTable = async () => { const data = await res.json(); return ( <div className= "grid md:grid-cols-3 gap-5 mt-10" > {data.map((post: any) => ( <div key={post.id} className= "max-w-sm border border-gray-200 rounded-md shadow" > <div className= "relative aspect-video" > <Image src={post._embedded[ "wp:featuredmedia" ][0].media_details.sizes.full.source_url} alt={post.title.rendered} fill priority sizes= "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" className= "rounded-t-md object-cover" /> </div> <div className= "p-5" > <h1> <Link href={`/posts/${post.slug}`}>{post.title.rendered}</Link> </h1> </div> <div className= "flex items-center justify-between" > <div className= "py-3 text-sm text-black rounded-bl-md w-full text-center" >{formatDate(post. date .toString())}</div> </div> </div> ))} </div> ); }; export default PostTable; |
1 2 3 4 5 6 | //app\components\Spinner.tsx export const Spinner = () => { return ( <span className= "loading loading-spinner loading-lg" >Loading</span> ); }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | //app\posts\[slug]\page.tsx import { notFound } from "next/navigation" ; const PostPage = async ({ params }: { params: { slug: string } }) => { const slug = params.slug; //console.log(data); const res = await fetch(`http: //localhost:8888/cairocoders/wp-json/wp/v2/posts?_embed&slug=${slug}`); const data = await res.json(); if (!data) return notFound(); return ( <div className= "min-h-screen flex items-center justify-center bg-slate-100" > <div className= "bg-white rounded-sm shadow p-8" > {data.map((post) => ( <div key={post.id}> <h1 className= "text-2xl font-bold mb-5" >{post.title.rendered}</h1> <div className= "mb-4" > <div dangerouslySetInnerHTML={{ __html: post[ 'content' ][ 'rendered' ] }} /> </div> </div> ))} </div> </div> ); }; export default PostPage; |
1 2 3 4 5 6 7 8 9 10 11 | //next.config.mjs /** @type {import('next').NextConfig} */ //const nextConfig = {}; const nextConfig = { reactStrictMode: true, images : { domains : [ 'localhost' ] // Domain name } } export default nextConfig; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | //themes\cairocoders\functions.php <?php /** * Theme functions and definitions * * @package cairocoders */ add_action( 'rest_api_init' , 'register_rest_images' ); function register_rest_images(){ register_rest_field( array ( 'post' ), 'fimg_url' , array ( 'get_callback' => 'get_rest_featured_image' , 'update_callback' => null, 'schema' => null, ) ); } function get_rest_featured_image( $object , $field_name , $request ) { if ( $object [ 'featured_media' ] ){ $img = wp_get_attachment_image_src( $object [ 'featured_media' ], 'app-thumb' ); return $img [0]; } return false; } |