diff --git a/app/blogs/page.js b/app/blogs/page.js index fc888a9..e0f39b0 100644 --- a/app/blogs/page.js +++ b/app/blogs/page.js @@ -1,16 +1,10 @@ import BlogsPage from "@/components/blogs"; import Layout from "@/components/layout/StLayout"; -import { fetchReq } from "@/lib/req"; - -export default async function Blogs() { - const API_URL = process.env.NEXT_PUBLIC_API_URL; - - const response = await fetchReq(`${API_URL}/api/v1/blogs`); - const blogs = response.blogs; +export default function Blogs() { return ( - + ); } diff --git a/components/blogs/index.js b/components/blogs/index.js index ec29a9e..748ac32 100644 --- a/components/blogs/index.js +++ b/components/blogs/index.js @@ -1,15 +1,55 @@ "use client"; +import { useState, useEffect } from "react"; import Head from "./Head"; import Title from "./title"; import LatestArticles from "./latestArticles"; +import { request } from "@/services/response"; + +function BlogsPage() { + const [blogs, setBlogs] = useState([]); + const [page, setPage] = useState(1); + const [totalPages, setTotalPages] = useState(1); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + const fetchBlogs = async () => { + try { + setIsLoading(true); + const params = { + page: page, + limit: 10, + }; + const response = await request.getBlogs(params); + setBlogs(response.blogs || []); + setTotalPages(response.page?.totalPages || 1); + } catch (error) { + console.error("Error fetching blogs:", error); + setBlogs([]); + } finally { + setIsLoading(false); + } + }; + + fetchBlogs(); + }, [page]); + + const handlePageChange = (event, value) => { + setPage(value); + window.scrollTo({ top: 0, behavior: "smooth" }); + }; -function BlogsPage({ blogs }) { return (
<Head /> - <LatestArticles blogs={blogs} /> + <LatestArticles + blogs={blogs} + page={page} + totalPages={totalPages} + onPageChange={handlePageChange} + isLoading={isLoading} + /> </div> ); } diff --git a/components/blogs/latestArticles/Article.js b/components/blogs/latestArticles/Article.js index d7b80c3..c0f4849 100644 --- a/components/blogs/latestArticles/Article.js +++ b/components/blogs/latestArticles/Article.js @@ -2,16 +2,20 @@ import CustomLoading from "@/app/component/loading/Custom"; import TextLoading from "@/app/component/loading/Text"; import Image from "next/image"; import Link from "next/link"; +import { convertTimestampToJalali } from "@/helper"; function Article({ data }) { + const imageSrc = data.images?.[0]?.url || "/assets/images/default-blog.jpg"; + const createdDate = data.created ? convertTimestampToJalali(data.created) : ""; + return ( <li className="rounded-[8px] overflow-hidden bg-[#FFF] shadow-[0px_0px_41px_0px_rgba(173,_181,_189,_0.15)]"> <CustomLoading width="full" height={200}> <Link href={`/blog/${data.uuid}`}> <Image - className="w-full" - alt="article-img" - src={data.src} + className="w-full h-[217px] object-cover" + alt={data.title || "article-img"} + src={imageSrc} height={217} width={392} /> @@ -20,22 +24,24 @@ function Article({ data }) { <div className="p-[12px] md:p-[14px] lg:p-[16px]"> <TextLoading width={150} height={18}> <Link href={`/blog/${data.uuid}`}> - <h1 className="text-[#3B3B3B] mb-[12px] md:mb-[14px] lg:mb-[16px] text-[16px] font-bold"> + <h1 className="text-[#3B3B3B] mb-[12px] md:mb-[14px] lg:mb-[16px] text-[16px] font-bold line-clamp-2"> {data.title} </h1> </Link> </TextLoading> - <div className="flex items-center justify-start gap-[35px]"> + <div className="flex items-center justify-start gap-[16px]"> <TextLoading width={100} height={18}> <p className="text-[#9B9B9B] text-[14px] font-medium"> - تاریخ انتشار: {data.date_of_release} - </p> - </TextLoading> - <TextLoading width={110} height={18}> - <p className="text-[#9B9B9B] text-[14px] font-medium"> - زمان مطالعه: {data.time} + {data.author && `نویسنده: ${data.author}`} </p> </TextLoading> + {createdDate && ( + <TextLoading width={110} height={18}> + <p className="text-[#9B9B9B] text-[14px] font-medium"> + {createdDate} + </p> + </TextLoading> + )} </div> </div> </li> diff --git a/components/blogs/latestArticles/index.js b/components/blogs/latestArticles/index.js index 0559dc5..c910eb6 100644 --- a/components/blogs/latestArticles/index.js +++ b/components/blogs/latestArticles/index.js @@ -1,20 +1,38 @@ import Article from "./Article"; import Pagination from "@/app/component/Pagination"; -function LatestArticles({ blogs }) { +function LatestArticles({ blogs, page, totalPages, onPageChange, isLoading }) { return ( <div> <p className="text-[#3B3B3B] text-[20px] font-bold my-[16px] md:my-[20px] lg:my-[24px]"> جدیدترین مقاله ها </p> - <ul className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-[16px] md:gap-[20px] lg:gap-[24px]"> - {blogs.map((item) => ( - <Article data={item} key={item.uuid} /> - ))} - </ul> - <div className="mt-[56px] flex justify-center"> - <Pagination list={blogs} itemsPerPage={12} /> - </div> + {isLoading ? ( + <div className="flex justify-center items-center min-h-[400px]"> + <p className="text-[#9B9B9B] text-[16px]">در حال بارگذاری...</p> + </div> + ) : blogs && blogs.length > 0 ? ( + <> + <ul className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-[16px] md:gap-[20px] lg:gap-[24px]"> + {blogs.map((item) => ( + <Article data={item} key={item.uuid} /> + ))} + </ul> + {totalPages > 1 && ( + <div className="mt-[56px] flex justify-center"> + <Pagination + page={page} + totalPages={totalPages} + onPageChange={onPageChange} + /> + </div> + )} + </> + ) : ( + <div className="flex justify-center items-center min-h-[400px]"> + <p className="text-[#9B9B9B] text-[16px]">مقاله‌ای یافت نشد</p> + </div> + )} </div> ); } diff --git a/next.config.js b/next.config.js index 2a187b8..8a17243 100644 --- a/next.config.js +++ b/next.config.js @@ -8,7 +8,17 @@ const nextConfig = { missingSuspenseWithCSRBailout: false, }, images: { - domains: ["back-dev.clinic-pro.ir"], + unoptimized: true, + remotePatterns: [ + { + protocol: 'https', + hostname: 'back-dev.clinic-pro.ir', + }, + { + protocol: 'https', + hostname: 'clinic-pro-back.ddev.site', + }, + ], }, env: { // Make DEV_MODE available to the application diff --git a/services/response.js b/services/response.js index ed7575d..1f6e392 100644 --- a/services/response.js +++ b/services/response.js @@ -97,4 +97,11 @@ export const request = { }), getDoctorAddress: (location_id) => api.get(`api/v1/clinic-pro/doctor-address/${location_id}`, removeTokenHead), + getBlogs: (params) => + api.get("api/v1/blogs", { + params, + headers: { + Authorization: "", + }, + }), };