update 26/03

This commit is contained in:
2025-03-26 13:18:49 +07:00
parent cc8b18bbc9
commit 306a9de89b
11 changed files with 880 additions and 977 deletions

View File

@@ -14,7 +14,9 @@ const ArticleDetail = () => {
if (typeof slug === "string") { if (typeof slug === "string") {
const getArticleDetail = async () => { const getArticleDetail = async () => {
const data = await fetchArticleDetail(slug); const data = await fetchArticleDetail(slug);
setArticleDetails(data[0]); if (Array.isArray(data) && data.length > 0) {
setArticleDetails(data[0]);
}
}; };
getArticleDetail(); getArticleDetail();
} }

View File

@@ -1,9 +1,8 @@
"use client"; "use client";
import { Suspense, useEffect, useState } from "react"; import { Suspense, useEffect, useState } from "react";
import { format } from "date-fns";
import Link from "next/link";
import { ArticleListDataType } from "@/types/article";
import { fetchListArticles } from "@/api/apiService"; import { fetchListArticles } from "@/api/apiService";
import ArticleItem from "@/components/articles/ArticleItem"; // Import ArticleItem component
import { ArticleListDataType } from "@/types/article";
const HomeArticle = () => { const HomeArticle = () => {
const [articleList, setArticleList] = useState<ArticleListDataType | null>( const [articleList, setArticleList] = useState<ArticleListDataType | null>(
@@ -13,240 +12,149 @@ const HomeArticle = () => {
useEffect(() => { useEffect(() => {
const fetchArticleList = async () => { const fetchArticleList = async () => {
const data = await fetchListArticles(); try {
setArticleList(data.list); const data = await fetchListArticles();
setLoadingUI(false); setArticleList(data.list);
} catch (error) {
console.error("Failed to fetch articles:", error);
} finally {
setLoadingUI(false);
}
}; };
fetchArticleList(); fetchArticleList();
}, []); }, []);
return ( return (
<Suspense> <div className="page-article">
{loadingUi ? ( <div className="container">
<div className="page-article"> <div className="main-title">
<div className="container"> <h2 className="text-center text-4xl text-sky-800 mb-[15px]">Blog</h2>
<div className="main-title"> <div className="text-center text-base text-gray-400">
<h2 className="text-center text-4xl text-sky-800 mb-[15px]"> Cập nhật từ Hurasoft
Blog
</h2>
<div className="text-center text-base text-gray-400">
Cập nhật từ Hurasoft
</div>
</div>
<div className="box-big-article flex">
<div className="box-big" id="js-holder-big">
<div className="relative">
<div className="bg-gray-300 w-full h-[606px] block rounded-[12px]"></div>
<div className="absolute bottom-[20px] left-[20px] right-0 p-[20px] bg-gray-50 rounded-[12px] w-[90%]">
<div className="time block bg-gray-200 w-[150px] h-[30px] rounded-[6px]"></div>
<div className="block bg-gray-200 w-full h-[50px] rounded-[6px]"></div>
</div>
</div>
</div>
<div className="box-small" id="js-holder-small">
<div className="item]">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
<div className="item]">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
</div>
</div>
<div className="box-article-other mt-[50px]">
<h2 className="title text-xl font-bold mb-[25px]">
Xem thêm bài khác
</h2>
<div className="list-article flex flex-wrap" id="js-list-article">
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
) : ( <Suspense>
<div className="page-article"> {loadingUi ? (
<div className="container"> <>
<div className="main-title"> <div className="box-big-article flex">
<h2 className="text-center text-4xl text-sky-800 mb-[15px]"> <div className="box-big" id="js-holder-big">
Blog <div className="relative">
</h2> <div className="bg-gray-300 w-full h-[606px] block rounded-[12px]"></div>
<div className="text-center text-base text-gray-400"> <div className="absolute bottom-[20px] left-[20px] right-0 p-[20px] bg-gray-50 rounded-[12px] w-[90%]">
Cập nhật từ Hurasoft <div className="time block bg-gray-200 w-[150px] h-[30px] rounded-[6px]"></div>
</div> <div className="block bg-gray-200 w-full h-[50px] rounded-[6px]"></div>
</div> </div>
{articleList &&
Array.isArray(articleList) &&
articleList.length > 0 ? (
<div>
<div className="box-big-article flex">
<div className="box-big" id="js-holder-big">
{articleList.slice(0, 1).map((item) => (
<div className="item-article" key={item.id}>
<a
href={`/article${item.url}`}
className="image-article"
>
<img
src={`https://hurasoft8.hurasoft.com/${item.image.large}`}
width={100}
height={100}
alt={item.title}
/>
</a>
<div className="info">
<div className="time">
<i className="fa-regular fa-clock"></i>{" "}
<span>
{format(
new Date(item.last_update * 1000),
"dd/MM/yyyy HH:mm"
)}
</span>
</div>
<a
href={`/article${item.url}`}
className="name-article line-clamp-2"
>
{item.title}
</a>
</div>
</div>
))}
</div>
<div className="box-small" id="js-holder-small">
{articleList.slice(1, 3).map((item) => (
<div className="item-article" key={item.id}>
<a
href={`/article/${item.url}`}
className="image-article"
>
<img
src={`https://hurasoft8.hurasoft.com/${item.image.large}`}
width={100}
height={100}
alt={item.title}
/>
</a>
<div className="info">
<div className="time">
<i className="fa-regular fa-clock"></i>{" "}
<span>
{format(
new Date(item.last_update * 1000),
"dd/MM/yyyy HH:mm"
)}
</span>
</div>
<a
href={`/article/${item.url}`}
className="name-article line-clamp-2"
>
{item.title}
</a>
</div>
</div>
))}
</div> </div>
</div> </div>
<div className="box-article-other mt-[50px]"> <div className="box-small" id="js-holder-small">
<h2 className="title text-xl font-bold mb-[25px]"> <div className="item]">
Xem thêm bài khác <div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
</h2> <div className="info mt-[10px]">
<div <div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
className="list-article flex flex-wrap" <div className="bg-gray-300 block w-[full] h-[48px]"></div>
id="js-list-article" </div>
> </div>
{articleList.map((item) => ( <div className="item]">
<div className="item-article" key={item.id}> <div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<Link <div className="info mt-[10px]">
href={`/article/${item.url}`} <div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
className="image-article" <div className="bg-gray-300 block w-[full] h-[48px]"></div>
> </div>
<img
src={`https://hurasoft8.hurasoft.com/${item.image.large}`}
width={100}
height={100}
alt={item.title}
/>
</Link>
<div className="info">
<div className="time">
<i className="fa-regular fa-clock"></i>{" "}
<span>
{format(
new Date(item.last_update * 1000),
"dd/MM/yyyy HH:mm"
)}
</span>
</div>
<Link
href={`/article/${item.url}`}
className="name-article line-clamp-2"
>
{item.title}
</Link>
</div>
</div>
))}
</div> </div>
</div> </div>
</div> </div>
) : ( <div className="box-article-other mt-[50px]">
<></> <h2 className="title text-xl font-bold mb-[25px]">
)} Xem thêm bài khác
</div> </h2>
</div> <div
)} className="list-article flex flex-wrap"
</Suspense> id="js-list-article"
>
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
<div className="item-article">
<div className="bg-gray-300 w-[full] h-[202px] block rounded-[12px]"></div>
<div className="info mt-[10px]">
<div className="bg-gray-300 block w-[150px] h-[20px] mb-[5px]"></div>
<div className="bg-gray-300 block w-[full] h-[48px]"></div>
</div>
</div>
</div>
</div>
</>
) : (
<>
{articleList &&
Array.isArray(articleList) &&
articleList.length > 0 ? (
<div>
<div className="box-big-article flex">
<div className="box-big w-full">
{articleList.slice(0, 1).map((article) => (
<ArticleItem key={article.id} article={article} />
))}
</div>
<div className="box-small">
{articleList?.slice(1, 3).map((article) => (
<ArticleItem key={article.id} article={article} />
))}
</div>
</div>
<div className="box-article-other mt-[50px]">
<h2 className="title text-xl font-bold mb-[25px]">
Xem thêm bài khác
</h2>
<div className="list-article flex flex-wrap">
{articleList.map((article) => (
<ArticleItem key={article.id} article={article} />
))}
</div>
</div>
</div>
) : (
<></>
)}
</>
)}
</Suspense>
</div>
</div>
); );
}; };

View File

@@ -30,35 +30,35 @@ const JobDetails = () => {
<Suspense> <Suspense>
{loadingUi ? ( {loadingUi ? (
<div className="container-job"> <div className="container-job">
<h2 className="title animate-fade-in text-xl font-medium bg-gray-200 rounded-[12px]"></h2> <h2 className="w-full h-[100px] mb-[50px] text-xl font-medium bg-gray-300 rounded-[12px] animate-pulse"></h2>
<div className="content-job flex"> <div className="content-job flex">
<div className="left-job"> <div className="left-job">
<div className="item"> <div className="item">
<p className="bg-gray-200 h-[20px] block w-full"></p> <p className="bg-gray-300 h-[20px] block w-full animate-pulse"></p>
<b className="bg-gray-200 h-[20px] block w-full"></b> <b className="bg-gray-300 h-[20px] block w-full animate-pulse"></b>
</div> </div>
<div className="item"> <div className="item">
<p className="bg-gray-200 h-[20px] block w-full"></p> <p className="bg-gray-300 h-[20px] block w-full animate-pulse"></p>
<b className="bg-gray-200 h-[20px] block w-full"></b> <b className="bg-gray-300 h-[20px] block w-full animate-pulse"></b>
</div> </div>
<div className="item"> <div className="item">
<p className="bg-gray-200 h-[20px] block w-full"></p> <p className="bg-gray-300 h-[20px] block w-full animate-pulse"></p>
<b className="bg-gray-200 h-[20px] block w-full"></b> <b className="bg-gray-300 h-[20px] block w-full animate-pulse"></b>
</div> </div>
</div> </div>
<div className="right-job"> <div className="right-job">
<div className="list-tab flex items-center"> <div className="list-tab flex items-center">
<div className="item-tab bg-gray-200 w-[170px] h-[45px] mr-[12px] rounded-[5px]"></div> <div className="item-tab bg-gray-300 w-[170px] h-[45px] mr-[12px] rounded-[5px] animate-pulse"></div>
<div className="item-tab bg-gray-200 w-[170px] h-[45px] mr-[12px] rounded-[5px]"></div> <div className="item-tab bg-gray-300 w-[170px] h-[45px] mr-[12px] rounded-[5px] animate-pulse"></div>
</div> </div>
<div> <div>
<div className="bg-gray-200 w-full h-[30px] rounded-[5px] ml-[20px] mb-[20px]"></div> <div className="bg-gray-300 w-full h-[30px] rounded-[5px] ml-[20px] mb-[20px] animate-pulse"></div>
<ul> <ul>
<li className="bg-gray-200 w-full h-[20px] rounded-[5px] mb-[10px] ml-[10px]"></li> <li className="bg-gray-300 w-full h-[20px] rounded-[5px] mb-[10px] ml-[10px] animate-pulse"></li>
<li className="bg-gray-200 w-full h-[20px] rounded-[5px] mb-[10px] ml-[10px]"></li> <li className="bg-gray-300 w-full h-[20px] rounded-[5px] mb-[10px] ml-[10px] animate-pulse"></li>
<li className="bg-gray-200 w-full h-[20px] rounded-[5px] mb-[10px] ml-[10px]"></li> <li className="bg-gray-300 w-full h-[20px] rounded-[5px] mb-[10px] ml-[10px] animate-pulse"></li>
<li className="bg-gray-200 w-full h-[20px] rounded-[5px] mb-[10px] ml-[10px]"></li> <li className="bg-gray-300 w-full h-[20px] rounded-[5px] mb-[10px] ml-[10px] animate-pulse"></li>
<li className="bg-gray-200 w-full h-[20px] rounded-[5px] mb-[10px] ml-[10px]"></li> <li className="bg-gray-300 w-full h-[20px] rounded-[5px] mb-[10px] ml-[10px] animate-pulse"></li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@@ -1,104 +1,62 @@
"use client"; "use client";
import Link from "next/link"; import { useState, useEffect } from "react";
import { Suspense, useState, useEffect } from "react";
import { ListJobDataType } from "@/types/job";
import { fetchListJobs } from "@/api/apiService"; import { fetchListJobs } from "@/api/apiService";
import JobItem from "@/components/jobs/JobItem";
import { ListJobDataType } from "@/types/job";
const HomeJob = () => { const HomeJob = () => {
const [ListJob, setListJob] = useState<ListJobDataType | null>(null); const [jobList, setJobList] = useState<ListJobDataType | null>(null);
const [loadingUi, setLoadingUI] = useState(true); const [loadingUi, setLoadingUI] = useState(true);
useEffect(() => { useEffect(() => {
const getListJob = async () => { const getJobList = async () => {
const data = await fetchListJobs(); try {
setListJob(data.list); const data = await fetchListJobs();
setLoadingUI(false); setJobList(data.list);
} catch (error) {
console.error("Failed to fetch jobs:", error);
} finally {
setLoadingUI(false);
}
}; };
getListJob(); getJobList();
}, []); }, []);
return ( return (
<div className="page-job list"> <div className="page-job list">
<div className="container-job"> <div className="container-job">
<h2 className="title">Tuyển dụng</h2> <h2 className="title">Tuyển dụng</h2>
<Suspense> {loadingUi ? (
{loadingUi ? ( <div className="list-job">
<div className="list-job"> {[...Array(4)].map((_, index) => (
<div className="item-job"> <div className="item-job" key={index}>
<div className="job-left flex items-center"> <div className="job-left flex items-center">
<div className="name line-clamp-1 bg-gray-200 h-[21px] w-[300px] mr-[15px]"></div> <div className="name line-clamp-1 bg-gray-200 h-[21px] w-[300px] mr-[15px] animate-pulse"></div>
<div className="time bg-gray-200 h-[20px] w-[120px] block"></div> <div className="time bg-gray-200 h-[20px] w-[120px] block animate-pulse"></div>
</div> </div>
<div className="job-right flex items-center"> <div className="job-right flex items-center">
<div className="localhost bg-gray-200 h-[21px] w-[60px] mr-[20px] block"></div> <div className="localhost bg-gray-200 h-[21px] w-[60px] mr-[20px] block animate-pulse"></div>
<div className="more bg-gray-200 h-[21px] block w-[120px]"></div> <div className="more bg-gray-200 h-[21px] block w-[120px] animate-pulse"></div>
</div> </div>
</div> </div>
<div className="item-job"> ))}
<div className="job-left flex items-center"> </div>
<div className="name line-clamp-1 bg-gray-200 h-[21px] w-[300px] mr-[15px]"></div> ) : (
<div className="time bg-gray-200 h-[20px] w-[120px] block"></div> <div>
</div> {jobList && Array.isArray(jobList) && jobList.length > 0 ? (
<div className="job-right flex items-center"> <div className="list-job">
<div className="localhost bg-gray-200 h-[21px] w-[60px] mr-[20px] block"></div> {jobList.map((job) => (
<div className="more bg-gray-200 h-[21px] block w-[120px]"></div> <JobItem key={job.id} job={job} />
</div> ))}
</div> </div>
<div className="item-job"> ) : (
<div className="job-left flex items-center"> <div className="text-center text-2xl py-[50px] font-bold italic">
<div className="name line-clamp-1 bg-gray-200 h-[21px] w-[300px] mr-[15px]"></div> Không công việc nào.
<div className="time bg-gray-200 h-[20px] w-[120px] block"></div>
</div>
<div className="job-right flex items-center">
<div className="localhost bg-gray-200 h-[21px] w-[60px] mr-[20px] block"></div>
<div className="more bg-gray-200 h-[21px] block w-[120px]"></div>
</div>
</div> </div>
<div className="item-job"> )}
<div className="job-left flex items-center"> </div>
<div className="name line-clamp-1 bg-gray-200 h-[21px] w-[300px] mr-[15px]"></div> )}
<div className="time bg-gray-200 h-[20px] w-[120px] block"></div>
</div>
<div className="job-right flex items-center">
<div className="localhost bg-gray-200 h-[21px] w-[60px] mr-[20px] block"></div>
<div className="more bg-gray-200 h-[21px] block w-[120px]"></div>
</div>
</div>
</div>
) : (
<div>
{ListJob && Array.isArray(ListJob) && ListJob.length > 0 ? (
<div className="list-job">
{ListJob.map((item) => (
<div className="item-job" key={item.id}>
<div className="job-left">
<Link
href={`${item.url}`}
className="name line-clamp-1"
>
{item.title}
</Link>
<div className="time">{item.end_date}</div>
</div>
<div className="job-right flex items-center">
<div className="localhost">{item.location}</div>
<Link href={`${item.url}`} className="more">
ng tuyển ngay{" "}
<i className="fa-solid fa-angle-right"></i>
</Link>
</div>
</div>
))}
</div>
) : (
<div className="text-center text-2xl py-[50px] font-bold italic">
Không công việc nào.
</div>
)}
</div>
)}
</Suspense>
</div> </div>
</div> </div>
); );

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +0,0 @@
export default function LoadingUI({ width = "100%", height = "150px" }) {
return (
<div style={{ width, height }} className="loading-box">
<div className="loading-content">Đang tải...</div>
</div>
);
}

View File

@@ -0,0 +1,44 @@
// ArticleCard.tsx
import { format } from "date-fns";
import { Article } from "@/types/article";
const ArticleCard = ({ article }: { article: Article }) => (
<div className="flex" key={article.id}>
<div className="info">
<div className="tag-blog flex items-center">
<i className="icon_2024 blog"></i>
<span>Blog</span>
</div>
<a href={article.url} className="name line-clamp-4">
{article.title}
</a>
<div className="summary line-clamp-4">{article.summary}</div>
<a href={article.url} className="more">
Chi tiết <i className="fa-solid fa-arrow-right"></i>
</a>
<div className="info-author">
<div className="author flex items-center">
<span>Đăng bởi</span>
<span className="name-author">Admin</span>
</div>
<div className="time">
<i className="far fa-clock"></i>{" "}
<span>
{format(new Date(article.last_update * 1000), "dd/MM/yyyy HH:mm")}
</span>
</div>
</div>
</div>
<div className="image-right">
<img
src={`https://hurasoft8.hurasoft.com/${article.image.large}`}
width={100}
height={100}
alt={article.title}
/>
</div>
</div>
);
export default ArticleCard;

View File

@@ -0,0 +1,28 @@
import { format } from "date-fns";
import { Article } from "@/types/article";
const ArticleItem = ({ article }: { article: Article }) => (
<div className="item-article">
<a href={`/article/${article.url}`} className="image-article">
<img
src={`https://hurasoft8.hurasoft.com/${article.image.large}`}
width={100}
height={100}
alt={article.title}
/>
</a>
<div className="info">
<div className="time">
<i className="fa-regular fa-clock"></i>{" "}
<span>
{format(new Date(article.last_update * 1000), "dd/MM/yyyy HH:mm")}
</span>
</div>
<a href={`/article/${article.url}`} className="name-article line-clamp-2">
{article.title}
</a>
</div>
</div>
);
export default ArticleItem;

View File

@@ -0,0 +1,21 @@
import Link from "next/link";
import { JobdataType } from "@/types/job";
const JobItem = ({ job }: { job: JobdataType }) => (
<div className="item-job" key={job.id}>
<div className="job-left">
<Link href={job.url} className="name line-clamp-1">
{job.title}
</Link>
<div className="time">{job.end_date}</div>
</div>
<div className="job-right flex items-center">
<div className="localhost">{job.location}</div>
<Link href={job.url} className="more">
ng tuyển ngay <i className="fa-solid fa-angle-right"></i>
</Link>
</div>
</div>
);
export default JobItem;

View File

@@ -0,0 +1,27 @@
import Image from "next/image";
const ProductCard = ({
title,
description,
imageSrc,
link,
}: {
title: string;
description: string;
imageSrc: string;
link: string;
}) => (
<div className="item-product">
<div className="top">
<div className="icon">
<Image src={imageSrc} width={100} height={100} alt={title} />
</div>
<p className="txt line-clamp-5">{description}</p>
</div>
<a href={link} target="_blank" className="more">
Xem thêm <i className="fa-solid fa-arrow-right"></i>
</a>
</div>
);
export default ProductCard;

29
src/hooks/useArticles.ts Normal file
View File

@@ -0,0 +1,29 @@
import { useState, useEffect } from "react";
import { ArticleListDataType } from "@/types/article";
import { fetchListArticles } from "@/api/apiService";
// Custom Hook để lấy danh sách bài viết
const useArticles = () => {
const [articles, setArticles] = useState<ArticleListDataType | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchArticles = async () => {
try {
const data = await fetchListArticles();
setArticles(data.list);
} catch {
setError('Lỗi khi tải bài viết.');
} finally {
setLoading(false);
}
};
fetchArticles();
}, []);
return { articles, loading, error };
};
export default useArticles;