diff --git a/app/blog/[slug]/page.js b/app/blog/[slug]/page.js index d7ecd01..fc27a13 100644 --- a/app/blog/[slug]/page.js +++ b/app/blog/[slug]/page.js @@ -6,11 +6,18 @@ async function Blog({ params: { slug } }) { const API_URL = process.env.NEXT_PUBLIC_API_URL; const blog = await fetchReq(`${API_URL}/api/v1/blog/${slug}`); - const blogs = await fetchReq(`${API_URL}/api/v1/blogs`); + + // Get related blogs based on first tag + let relatedBlogs = []; + if (blog?.tag?.[0]?.id) { + const tagId = blog.tag[0].id; + const relatedResponse = await fetchReq(`${API_URL}/api/v1/blogs?page=1&limit=12&tag=${tagId}`); + relatedBlogs = relatedResponse?.blogs || []; + } return ( - + ); } diff --git a/components/blog/detail/Caption.js b/components/blog/detail/Caption.js index d7fdc8c..4732c53 100644 --- a/components/blog/detail/Caption.js +++ b/components/blog/detail/Caption.js @@ -1,33 +1,23 @@ -import Image from "next/image"; import React from "react"; function Caption({ data }) { + const imageUrl = data?.images?.[0]?.url; + return ( <> - cover-blog -
+ {imageUrl && imageUrl.trim() !== "" && ( + {data?.title + )} + {data?.body?.value && (
-
- cover-blog -
+ )} ); } diff --git a/components/blog/detail/index.js b/components/blog/detail/index.js index 96584b1..351cbaf 100644 --- a/components/blog/detail/index.js +++ b/components/blog/detail/index.js @@ -7,7 +7,7 @@ function Detail({ data }) {
- + {/* */}
); } diff --git a/components/blog/head/index.js b/components/blog/head/index.js index 457ccce..a566603 100644 --- a/components/blog/head/index.js +++ b/components/blog/head/index.js @@ -1,39 +1,52 @@ +import { convertTimestampToJalali } from "@/helper"; + function Head({ data }) { + const firstTag = data?.tag?.[0]; + const createdDate = data?.created ? convertTimestampToJalali(data.created) : ""; + return (

بلاگ {">"}

-

- پوست و مو {">"} -

+ {firstTag && ( + <> +

+ {firstTag.name} {">"} +

+ + )}

- روش های خانگی محافظت از پوست در تابستان + {data?.title}

- روش های خانگی محافظت از پوست در تابستان + {data?.title}

-
-

- تاریخ انتشار: -

-

- {data?.date_of_release} -

-
-
-

- زمان مطالعه: -

-

- {data?.time} -

-
+ {data?.author && ( +
+

+ نویسنده: +

+

+ {data.author} +

+
+ )} + {createdDate && ( +
+

+ تاریخ انتشار: +

+

+ {createdDate} +

+
+ )}
); diff --git a/components/blog/relatedContent/Item.js b/components/blog/relatedContent/Item.js index a132d31..e9f39b1 100644 --- a/components/blog/relatedContent/Item.js +++ b/components/blog/relatedContent/Item.js @@ -1,30 +1,39 @@ import CircularLoading from "@/app/component/loading/Circular"; 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 Item({ data, idx, loading }) { + const imageUrl = data?.images?.[0]?.url; + const createdDate = data?.created ? convertTimestampToJalali(data.created) : ""; + return (
  • - - article + src={imageUrl} + alt={data.title || "article"} + /> + ) : ( +
    + )}
    - +

    {data.title}

    @@ -32,11 +41,11 @@ function Item({ data, idx, loading }) {

    - تاریخ انتشار: {data.date_of_release} + {createdDate && `تاریخ انتشار: ${createdDate}`}

    - {data.id > idx + 1 && ( + {idx > 0 && ( )}
  • diff --git a/components/blogs/Head.js b/components/blogs/Head.js index f057964..7d5481d 100644 --- a/components/blogs/Head.js +++ b/components/blogs/Head.js @@ -1,76 +1,110 @@ +"use client"; +import { useState, useEffect } from "react"; 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 { request } from "@/services/response"; function Head() { + const [topBlogs, setTopBlogs] = useState([]); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + const fetchTopBlogs = async () => { + try { + setIsLoading(true); + const response = await request.getTopBlogs(); + setTopBlogs(response || []); + } catch (error) { + console.error("Error fetching top blogs:", error); + setTopBlogs([]); + } finally { + setIsLoading(false); + } + }; + + fetchTopBlogs(); + }, []); + + if (isLoading || topBlogs.length === 0) { + return null; + } + + const [firstBlog, secondBlog, thirdBlog, fourthBlog] = topBlogs; + return ( + <>{/*
    - - - head blog - - -

    - روش های خانگی محافظت از پوست در تابستان -

    -
    - -
    -
    - - - head blog - - -

    - فواید نوشیدن آب برای سلامتی -

    -
    - - - - head blog - - -

    - راهکارهای ساده برای درمان سر درد -

    -
    - -
    - - - head blog + + {firstBlog.title

    - تغذیه مناسب برای کاهش فشار خون + {firstBlog.title}

    + )} +
    +
    + {secondBlog && ( + + + {secondBlog.title + + +

    + {secondBlog.title} +

    +
    + + )} + {thirdBlog && ( + + + {thirdBlog.title + + +

    + {thirdBlog.title} +

    +
    + + )} +
    + {fourthBlog && ( + + + {fourthBlog.title + + +

    + {fourthBlog.title} +

    +
    + + )}
    + */} ); } diff --git a/components/blogs/index.js b/components/blogs/index.js index 748ac32..0bb5e45 100644 --- a/components/blogs/index.js +++ b/components/blogs/index.js @@ -11,6 +11,7 @@ function BlogsPage() { const [page, setPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [isLoading, setIsLoading] = useState(true); + const [selectedTag, setSelectedTag] = useState(null); useEffect(() => { const fetchBlogs = async () => { @@ -18,8 +19,11 @@ function BlogsPage() { setIsLoading(true); const params = { page: page, - limit: 10, + limit: 12, }; + if (selectedTag) { + params.tag = selectedTag; + } const response = await request.getBlogs(params); setBlogs(response.blogs || []); setTotalPages(response.page?.totalPages || 1); @@ -32,16 +36,21 @@ function BlogsPage() { }; fetchBlogs(); - }, [page]); + }, [page, selectedTag]); const handlePageChange = (event, value) => { setPage(value); window.scrollTo({ top: 0, behavior: "smooth" }); }; + const handleTagChange = (tagUuid) => { + setSelectedTag(tagUuid); + setPage(1); + }; + return (
    - + <Title onTagChange={handleTagChange} /> <Head /> <LatestArticles blogs={blogs} diff --git a/components/blogs/title/index.js b/components/blogs/title/index.js index 995ef00..3b2d2d5 100644 --- a/components/blogs/title/index.js +++ b/components/blogs/title/index.js @@ -1,21 +1,53 @@ "use client"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import ItemTitle from "./ItemTitle"; +import { request } from "@/services/response"; -const listTitle = ["سلامت روان", "پوست و مو", "کودک و نوجوان", "دارو", "تغذیه"]; - -function Title() { +function Title({ onTagChange }) { const [activeBtn, setActiveBtn] = useState(0); + const [tags, setTags] = useState([]); + + useEffect(() => { + const fetchTags = async () => { + try { + const params = { + page: 1, + limit: 100, + }; + const response = await request.getBlogTags(params); + setTags(response.data || []); + } catch (error) { + console.error("Error fetching tags:", error); + setTags([]); + } + }; + + fetchTags(); + }, []); + + const handleTagClick = (idx, tagId) => { + setActiveBtn(idx); + if (onTagChange) { + onTagChange(tagId); + } + }; return ( <ul className="flex w-full overflow-auto hidden-scroll items-center justify-start gap-[8px] sm:gap-[10px] md:gap-[13px] lg:gap-[16px]"> - {listTitle.map((name, idx) => ( + <ItemTitle + setActiveBtn={() => handleTagClick(0, null)} + activeBtn={activeBtn} + name="همه" + idx={0} + key="all" + /> + {tags.map((tag, idx) => ( <ItemTitle - setActiveBtn={setActiveBtn} + setActiveBtn={() => handleTagClick(idx + 1, tag.id)} activeBtn={activeBtn} - name={name} - idx={idx} - key={idx} + name={tag.name} + idx={idx + 1} + key={tag.uuid} /> ))} </ul> diff --git a/lib/req.js b/lib/req.js index 77ebdcd..b95985a 100644 --- a/lib/req.js +++ b/lib/req.js @@ -1,8 +1,16 @@ import axios from "axios"; +import https from "https"; + +// Create axios instance with SSL verification disabled for development +const axiosInstance = axios.create({ + httpsAgent: new https.Agent({ + rejectUnauthorized: false + }) +}); export const fetchReq = async (url, headers) => { try { - const response = await axios.get(url, headers); + const response = await axiosInstance.get(url, headers); return response.data; } catch (error) { console.error("fetchReq error:", error.message); diff --git a/services/response.js b/services/response.js index 1f6e392..3cb33b7 100644 --- a/services/response.js +++ b/services/response.js @@ -104,4 +104,23 @@ export const request = { Authorization: "", }, }), + getBlogTags: (params) => + api.get("api/v1/categorys/tag", { + params, + headers: { + Authorization: "", + }, + }), + getTopBlogs: () => + api.get("api/v1/blogs/top", { + headers: { + Authorization: "", + }, + }), + getSingleBlog: (uuid) => + api.get(`api/v1/blog/${uuid}`, { + headers: { + Authorization: "", + }, + }), };