diff --git a/src/app/blog/[blogId]/MoreBlogs.tsx b/src/app/blog/[blogId]/MoreBlogs.tsx new file mode 100644 index 000000000..972084839 --- /dev/null +++ b/src/app/blog/[blogId]/MoreBlogs.tsx @@ -0,0 +1,52 @@ +import { Pagination } from "swiper/modules" +import { Swiper, SwiperSlide } from "swiper/react" + +import { Box, Stack, Typography } from "@mui/material" + +import ArticleCard from "@/components/ArticleCard" + +const MoreBlogs = props => { + const { blogs, title, ...restProps } = props + + return ( + + + {title} + + + + {props.blogs.map(blog => ( + + + + + + ))} + + + ) +} + +export default MoreBlogs diff --git a/src/app/blog/[blogId]/actions.ts b/src/app/blog/[blogId]/actions.ts new file mode 100644 index 000000000..65e05e043 --- /dev/null +++ b/src/app/blog/[blogId]/actions.ts @@ -0,0 +1,17 @@ +"use server" + +import { fetchBlogDetailURL } from "@/apis/blog" + +export const fetchBlogContent = async (blogId: string) => { + const response = await fetch(fetchBlogDetailURL(blogId)) + + if (response.ok) { + const blogContent = await response.text() + if (!blogContent) { + throw new Error("Not found") + } + return blogContent + } else { + throw new Error("Failed to fetch blog content") + } +} diff --git a/src/app/blog/[blogId]/articles.tsx b/src/app/blog/[blogId]/articles.tsx deleted file mode 100644 index 60a57b456..000000000 --- a/src/app/blog/[blogId]/articles.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Pagination } from "swiper/modules" -import { Swiper, SwiperSlide } from "swiper/react" - -import { Box } from "@mui/material" -import { styled } from "@mui/system" - -import ArticleCard from "@/components/ArticleCard" -import useCheckViewport from "@/hooks/useCheckViewport" - -const ArticleBox = styled(Box)( - ({ theme }) => ` - display: flex; - justify-content: space-between; - ${theme.breakpoints.down("md")} { - justify-content: center; - }; - `, -) as typeof Box - -const Articles = props => { - const { isPortrait, isTabletLandscape } = useCheckViewport() - let slidesPerView = 3 - if (isTabletLandscape) { - slidesPerView = 2 - } else if (isPortrait) { - slidesPerView = 1 - } - return ( - - {props.blogs.map(blog => ( - - - - - - ))} - - ) -} - -export default Articles diff --git a/src/app/blog/[blogId]/detail.tsx b/src/app/blog/[blogId]/detail.tsx index ba95e849e..7531243ca 100644 --- a/src/app/blog/[blogId]/detail.tsx +++ b/src/app/blog/[blogId]/detail.tsx @@ -9,10 +9,9 @@ import rehypeRaw from "rehype-raw" import remarkGfm from "remark-gfm" import remarkMath from "remark-math" -import { Box, Typography } from "@mui/material" +import { Box } from "@mui/material" import { styled } from "@mui/system" -import { fetchBlogDetailURL } from "@/apis/blog" import blogSource from "@/assets/blog/main.data.json" import LoadingPage from "@/components/LoadingPage" import { LANGUAGE_MAP } from "@/constants" @@ -20,7 +19,8 @@ import useCheckViewport from "@/hooks/useCheckViewport" import useUserLanguage from "@/hooks/useUserLanguage" import { filterBlogsByLanguage } from "@/utils" -import Articles from "./articles" +import MoreBlogs from "./MoreBlogs" +import { fetchBlogContent } from "./actions" import TOC from "./components/tableOfContents" const BlogContainer = styled(Box)( @@ -61,36 +61,37 @@ const BlogDetail = props => { const blogsWithLang = useMemo(() => filterBlogsByLanguage(blogSource, language), [blogSource, language]) useEffect(() => { - const regex = /([^_]*?)_lang_[^_]+/g - const blogIdMatch = blogId?.match(regex) - - const blogItemWithLang = blogSource.find(item => item.id === `${blogId}_lang_${language}`) - - if ((!blogIdMatch && language === "en") || (blogIdMatch && language !== "en") || (!blogIdMatch && language !== "en" && !blogItemWithLang)) { - let anchors = [...document.querySelectorAll("a")] - anchors.map(anchor => { - if (anchor.href.includes("/Content/")) { - anchor.setAttribute("target", "") + async function fetchCurrentBlog() { + const regex = /([^_]*?)_lang_[^_]+/g + const blogIdMatch = blogId?.match(regex) + + const blogItemWithLang = blogSource.find(item => item.id === `${blogId}_lang_${language}`) + + if ((!blogIdMatch && language === "en") || (blogIdMatch && language !== "en") || (!blogIdMatch && language !== "en" && !blogItemWithLang)) { + let anchors = [...document.querySelectorAll("a")] + anchors.map(anchor => { + if (anchor.href.includes("/Content/")) { + anchor.setAttribute("target", "") + } + return anchor + }) + try { + setLoading(true) + const text = await fetchBlogContent(blogId) + setBlogContent(text) + } catch (_error) { + router.push("/404") + } finally { + setLoading(false) } - return anchor - }) - try { - setLoading(true) - fetch(fetchBlogDetailURL(blogId)) - .then(response => response.text()) - .then(text => { - setLoading(false) - setBlogContent(text) - }) - } catch (_error) { - router.push("/404") + } else if (blogIdMatch && language === "en") { + const nextBlogId = blogId.replace(regex, "$1") + router.push(`/blog/${nextBlogId}`) + } else if (blogItemWithLang) { + router.push(`/blog/${blogId}_lang_${language}`) } - } else if (blogIdMatch && language === "en") { - const nextBlogId = blogId.replace(regex, "$1") - router.push(`/blog/${nextBlogId}`) - } else if (blogItemWithLang) { - router.push(`/blog/${blogId}_lang_${language}`) } + fetchCurrentBlog() }, [blogId, language]) useEffect(() => { @@ -119,21 +120,8 @@ const BlogDetail = props => { className="markdown-body" /> - {isPortrait ? ( - - - {LANGUAGE_MAP[language].more_articles} - - - - ) : null} + + {!!isPortrait && } )}