From b5019b41b44af5468aacc12982dd0760ec1accae Mon Sep 17 00:00:00 2001 From: Tieptk Date: Mon, 24 Mar 2025 16:00:41 +0700 Subject: [PATCH] update 24/03 --- data/db.json | 6 +- src/api/apiService.ts | 4 +- src/app/article/page.tsx | 314 +++++++++++++++++++++++------------ src/app/page.tsx | 297 +++++++++++++++++++-------------- src/components/LoadingUi.tsx | 7 + src/styles/style.css | 23 +++ 6 files changed, 422 insertions(+), 229 deletions(-) create mode 100644 src/components/LoadingUi.tsx diff --git a/data/db.json b/data/db.json index 3391860..0c517a3 100644 --- a/data/db.json +++ b/data/db.json @@ -1,5 +1,5 @@ { - "jobs": { + "list_job": { "total": 4, "list": [ { @@ -76,7 +76,7 @@ } ] }, - "articles": { + "list_article": { "total": 11, "list": [ { @@ -423,4 +423,4 @@ "note": "liên hệ tôi" } ] -} \ No newline at end of file +} diff --git a/src/api/apiService.ts b/src/api/apiService.ts index 7c549db..2017e79 100644 --- a/src/api/apiService.ts +++ b/src/api/apiService.ts @@ -16,13 +16,13 @@ const apiRequest = async (endpoint: string, method: string = "GET", body?: objec return response.json(); }; // API cho bài viết -export const fetchListArticles = () => apiRequest("/articles"); +export const fetchListArticles = () => apiRequest("/list_article"); export const fetchArticleDetail = async (slug: string): Promise => { return apiRequest(`/articleDetails?path=${slug}`); }; // API cho công việc -export const fetchListJobs = () => apiRequest("/jobs"); +export const fetchListJobs = () => apiRequest("/list_job"); export const fetchJobDetail = async (slug: string): Promise => { return apiRequest(`/jobDetails?path=${slug}`); }; \ No newline at end of file diff --git a/src/app/article/page.tsx b/src/app/article/page.tsx index 346acfc..6438fee 100644 --- a/src/app/article/page.tsx +++ b/src/app/article/page.tsx @@ -1,5 +1,5 @@ "use client"; -import { 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"; @@ -9,89 +9,56 @@ const HomeArticle = () => { const [articleList, setArticleList] = useState( null ); + const [loadingUi, setLoadingUI] = useState(true); useEffect(() => { const fetchArticleList = async () => { const data = await fetchListArticles(); setArticleList(data.list); + setLoadingUI(false); }; fetchArticleList(); }, []); return ( -
-
-
-

Blog

-
- Cập nhật từ Hurasoft -
-
- {articleList && Array.isArray(articleList) && articleList.length > 0 ? ( -
+ + {loadingUi ? ( +
+
+
+

+ Blog +

+
+ Cập nhật từ Hurasoft +
+
- {articleList.slice(0, 1).map((item) => ( -
- - {item.title} - -
-
- {" "} - - {format( - new Date(item.last_update * 1000), - "dd/MM/yyyy HH:mm" - )} - -
- - {item.title} - -
+
+
+
+
+
- ))} +
- {articleList.slice(1, 3).map((item) => ( -
- - {item.title} - -
-
- {" "} - - {format( - new Date(item.last_update * 1000), - "dd/MM/yyyy HH:mm" - )} - -
- - {item.title} - -
+
+
+
+
+
- ))} +
+
+
+
+
+
+
+
@@ -99,46 +66,187 @@ const HomeArticle = () => { Xem thêm bài khác
- {articleList.map((item) => ( -
- - {item.title} - -
-
- {" "} - - {format( - new Date(item.last_update * 1000), - "dd/MM/yyyy HH:mm" - )} - -
- - {item.title} - -
+
+
+
+
+
- ))} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- ) : ( - <> - )} -
-
+
+ ) : ( +
+
+
+

+ Blog +

+
+ Cập nhật từ Hurasoft +
+
+ {articleList && + Array.isArray(articleList) && + articleList.length > 0 ? ( +
+
+
+ {articleList.slice(0, 1).map((item) => ( +
+ + {item.title} + +
+
+ {" "} + + {format( + new Date(item.last_update * 1000), + "dd/MM/yyyy HH:mm" + )} + +
+ + {item.title} + +
+
+ ))} +
+
+ {articleList.slice(1, 3).map((item) => ( +
+ + {item.title} + +
+
+ {" "} + + {format( + new Date(item.last_update * 1000), + "dd/MM/yyyy HH:mm" + )} + +
+ + {item.title} + +
+
+ ))} +
+
+
+

+ Xem thêm bài khác +

+
+ {articleList.map((item) => ( +
+ + {item.title} + +
+
+ {" "} + + {format( + new Date(item.last_update * 1000), + "dd/MM/yyyy HH:mm" + )} + +
+ + {item.title} + +
+
+ ))} +
+
+
+ ) : ( + <> + )} +
+
+ )} + ); }; diff --git a/src/app/page.tsx b/src/app/page.tsx index c3eb84e..9fe53e6 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,5 +1,5 @@ "use client"; -import { useState, useEffect } from "react"; +import { Suspense, useState, useEffect } from "react"; import Image from "next/image"; import Link from "next/link"; import { format } from "date-fns"; @@ -12,6 +12,8 @@ export default function Home() { null ); + const [loadingUi, setLoadingUI] = useState(true); + useEffect(() => { const typingNode = document.getElementById("typewriter") as HTMLElement; if (typingNode) { @@ -24,6 +26,7 @@ export default function Home() { const fetchArticleNews = async () => { const data = await fetchListArticles(); setArticleList(data.list); + setLoadingUI(false); }; fetchArticleNews(); @@ -467,142 +470,194 @@ export default function Home() {
+ +
+
+

Sản phẩm

-
-
-

Sản phẩm

-
-
-
-
- hura 8 + {loadingUi ? ( +
+
+
+
+
+
+
-

- Phần mềm tạo website TMĐT chạy nên nền tảng Cloud dành cho - doanh nghiệp lớn -

-
- - Xem thêm - -
-
-
-
- xstore +
+
+
+
+
+
-

- Nền tảng quản lý cửa hàng nhỏ toàn diện, bao gồm: Quản lý - đơn hàng đa kênh, Kho hàng, Website và POS -

-
- - Xem thêm - -
-
-
-
- icon-adman +
+
+
+
+
+
-

- Nền tảng marketing toàn diện dành cho các chuyên gia. -

-
- - Xem thêm - -
-
-
-
- icon-chatngay +
+
+
+
+
+
-

- Phần mềm hỗ trợ, cskh tích hợp website giúp khách hàng tương - tác nhanh chóng và thuận tiện. -

- - Xem thêm - -
+ ) : ( +
+
+
+
+ hura 8 +
+

+ Phần mềm tạo website TMĐT chạy nên nền tảng Cloud dành + cho doanh nghiệp lớn +

+
+ + Xem thêm + +
+
+
+
+ xstore +
+

+ Nền tảng quản lý cửa hàng nhỏ toàn diện, bao gồm: Quản + lý đơn hàng đa kênh, Kho hàng, Website và POS +

+
+ + Xem thêm + +
+
+
+
+ icon-adman +
+

+ Nền tảng marketing toàn diện dành cho các chuyên gia. +

+
+ + Xem thêm + +
+
+
+
+ icon-chatngay +
+

+ Phần mềm hỗ trợ, cskh tích hợp website giúp khách hàng + tương tác nhanh chóng và thuận tiện. +

+
+ + Xem thêm + +
+
+ )}
-
- {articleList && Array.isArray(articleList) && articleList.length > 0 ? ( + + +

Có gì mới?

- -
- {articleList.slice(0, 1).map((item) => ( -
+ {loadingUi ? ( +
+
-
- - Blog -
- - {item.title} - -
{item.summary}
- - Chi tiết - - -
-
- Đăng bởi - Admin -
-
- {" "} - - {format( - new Date(item.last_update * 1000), - "dd/MM/yyyy HH:mm" - )} - -
-
-
-
- {item.title} +
+
+
+
+
+
- ))} -
+
+ ) : Array.isArray(articleList) && articleList.length > 0 ? ( +
+ {articleList.slice(0, 1).map((item) => ( +
+
+
+ + Blog +
+ + {item.title} + +
+ {item.summary} +
+ + Chi tiết + + +
+
+ Đăng bởi + Admin +
+
+ {" "} + + {format( + new Date(item.last_update * 1000), + "dd/MM/yyyy HH:mm" + )} + +
+
+
+
+ {item.title} +
+
+ ))} +
+ ) : ( + <> // Nếu không có dữ liệu, không hiển thị gì + )}
- ) : ( - <> - )} +
); diff --git a/src/components/LoadingUi.tsx b/src/components/LoadingUi.tsx new file mode 100644 index 0000000..198c69d --- /dev/null +++ b/src/components/LoadingUi.tsx @@ -0,0 +1,7 @@ +export default function LoadingUI({ width = "100%", height = "150px" }) { + return ( +
+
Đang tải...
+
+ ); +} diff --git a/src/styles/style.css b/src/styles/style.css index 62c3d32..341eff8 100644 --- a/src/styles/style.css +++ b/src/styles/style.css @@ -1137,6 +1137,29 @@ main { width: 50%; } +.loading-box { + background-color: #f0f0f0; + border-radius: 8px; + animation: shimmer 1.5s infinite linear; + display: flex; + justify-content: center; + align-items: center; +} + +.loading-content { + font-size: 18px; + font-weight: bold; +} + +@keyframes shimmer { + 0% { + background-position: -1000px 0; + } + 100% { + background-position: 1000px 0; + } +} + @media only screen and (max-width: 768px) { .page-job .container-job { width: 100%;