diff --git a/data/db.json b/data/db.json
index 76c23dd..3391860 100644
--- a/data/db.json
+++ b/data/db.json
@@ -4,12 +4,12 @@
"list": [
{
"id": 13,
- "title": "Nh\u00e2n vi\u00ean ph\u00e1t tri\u1ec3n th\u1ecb tr\u01b0\u1eddng",
+ "title": "Nhân viên phát triển thị trường",
"summary": "",
- "salary": "Th\u1ecfa thu\u1eadn",
+ "salary": "Thỏa thuận",
"vacancy_num": 2,
"end_date": "31-12-2024",
- "location": "H\u00e0 N\u1ed9i",
+ "location": "Hà Nội",
"visit": 0,
"create_time": 1731653302,
"last_update": 1733899503,
@@ -22,12 +22,12 @@
},
{
"id": 12,
- "title": "Nh\u00e2n vi\u00ean ch\u0103m s\u00f3c kh\u00e1ch h\u00e0ng",
+ "title": "Nhân viên chăm sóc khách hàng",
"summary": "",
- "salary": "7-12 tri\u1ec7u",
+ "salary": "7-12 triệu",
"vacancy_num": 2,
"end_date": "31-12-2024",
- "location": "H\u00e0 N\u1ed9i",
+ "location": "Hà Nội",
"visit": 0,
"create_time": 1731653230,
"last_update": 1733899517,
@@ -40,12 +40,12 @@
},
{
"id": 11,
- "title": "L\u1eadp tr\u00ecnh vi\u00ean front-end",
+ "title": "Lập trình viên front-end",
"summary": "",
- "salary": "Th\u1ecfa thu\u1eadn",
+ "salary": "Thỏa thuận",
"vacancy_num": 2,
"end_date": "31-12-2024",
- "location": "H\u00e0 N\u1ed9i",
+ "location": "Hà Nội",
"visit": 0,
"create_time": 1731652851,
"last_update": 1733899525,
@@ -58,12 +58,12 @@
},
{
"id": 10,
- "title": "Thi\u1ebft k\u1ebf \u0111\u1ed3 h\u1ecda Website, Mobile (UX Designer)",
+ "title": "Thiết kế đồ họa Website, Mobile (UX Designer)",
"summary": "",
- "salary": "$500-1,000/th\u00e1ng",
+ "salary": "$500-1,000/tháng",
"vacancy_num": 1,
"end_date": "31-12-2024",
- "location": "H\u00e0 N\u1ed9i",
+ "location": "Hà Nội",
"visit": 0,
"create_time": 1731652564,
"last_update": 1733899533,
@@ -283,7 +283,7 @@
},
"articleDetails": [
{
- "id": 726,
+ "id": "726",
"category": 39,
"title": "An toàn thông tin website",
"summary": "An toàn thông tin website đề cập đến các biện pháp và quy trình nhằm bảo vệ dữ liệu và thông tin trên website khỏi các mối đe dọa như hacker, phần mềm độc hại, và các cuộc tấn công mạng khác",
@@ -301,7 +301,7 @@
"path": "an-toan-thong-tin-website"
},
{
- "id": 724,
+ "id": "724",
"category": 39,
"title": "Xu hướng cá nhân hóa trải nghiệm người dùng trong thương mại điện tử",
"summary": "",
@@ -319,7 +319,7 @@
"path": "xu-huong-ca-nhan-hoa-trai-nghiem-nguoi-dung-trong-thuong-mai-dien-tue"
},
{
- "id": 723,
+ "id": "723",
"category": 39,
"title": "Thu hút người dùng bằng minigame trên website",
"summary": "",
@@ -337,7 +337,7 @@
"path": "marketing-bang-minigame-tren-website"
},
{
- "id": 723,
+ "id": "723",
"category": 39,
"title": "Test bài viết tin tức",
"summary": "",
@@ -363,7 +363,8 @@
"end_date": "31-12-2024",
"location": "Hà Nội",
"applicant_count": 7,
- "description": "
Mô tả công việc
- Tìm kiếm khách hàng mới, tiếp cận khai thác Khách hàng tiềm năng.
- Tư vấn khách hàng về sản phẩm, dịch vụ của công ty.
- Chốt hợp đồng khách hàng, triển khai quy trình làm việc với khách hàng.
- Hỗ trợ và chăm sóc khách hàng (tiềm năng, hiện tại, cũ) tạo mối quan hệ với khách hàng.
- Tiếp thu ý kiến khách hàng, phối hợp với các bộ phận khác để khai thác tối đa lợi ích của dịch vụ, khách hàng.
- Hoàn thành chỉ tiêu kinh doanh nhóm và chỉ tiêu cá nhân.
Yêu cầu ứng viên:
- Tốt nghiệp Cao Đẳng trở lên các trường đào tạo chuyên ngành quản trị kinh doanh, CNTT hoặc các ngành liên quan.
- Đặc biệt ưu tiên có kinh nghiệm làm việc ở các lĩnh vực kinh doanh phần mềm, bán hàng, tư vấn, tiếp thị các sản phẩm về CNTT là 1 lợi thế.
- Có kỹ năng giao tiếp thuyết phục đàm phán tốt , năng động, cải tiến, sáng tạo, chủ động trong công việc.
- Tinh thần trách nhiệm trong công việc. Yêu thích công việc kinh doanh và không ngừng học hỏi, sẳn sàng tiếp thu các kiến thức mới.
- Có laptop, có phương tiện đi lại.
Quyền lợi:
- Môi trường làm việc chuyên nghiệp, năng động, thân thiện
- Luôn được tiếp xúc với công nghệ và thử thách mới.
- Lương: Lương cứng + hoa hồng + phụ cấp xăng xe, điện thoại
- Thưởng theo ngày lễ, tết
- Được đào tạo kĩ năng mềm ( kỹ năng giao tiếp, xử lý tình huống…..)
- Làm việc từ T2 – sáng T7
- Đóng bảo hiểm theo quy định của Nhà nước
- Được hưởng đầy đủ các chế độ theo quy định của luật lao động
Ứng viên vui lòng gửi hồ sơ cho chúng tôi qua email info@hurasoft.com
"
+ "description": "Mô tả công việc
- Tìm kiếm khách hàng mới, tiếp cận khai thác Khách hàng tiềm năng.
- Tư vấn khách hàng về sản phẩm, dịch vụ của công ty.
- Chốt hợp đồng khách hàng, triển khai quy trình làm việc với khách hàng.
- Hỗ trợ và chăm sóc khách hàng (tiềm năng, hiện tại, cũ) tạo mối quan hệ với khách hàng.
- Tiếp thu ý kiến khách hàng, phối hợp với các bộ phận khác để khai thác tối đa lợi ích của dịch vụ, khách hàng.
- Hoàn thành chỉ tiêu kinh doanh nhóm và chỉ tiêu cá nhân.
Yêu cầu ứng viên:
- Tốt nghiệp Cao Đẳng trở lên các trường đào tạo chuyên ngành quản trị kinh doanh, CNTT hoặc các ngành liên quan.
- Đặc biệt ưu tiên có kinh nghiệm làm việc ở các lĩnh vực kinh doanh phần mềm, bán hàng, tư vấn, tiếp thị các sản phẩm về CNTT là 1 lợi thế.
- Có kỹ năng giao tiếp thuyết phục đàm phán tốt , năng động, cải tiến, sáng tạo, chủ động trong công việc.
- Tinh thần trách nhiệm trong công việc. Yêu thích công việc kinh doanh và không ngừng học hỏi, sẳn sàng tiếp thu các kiến thức mới.
- Có laptop, có phương tiện đi lại.
Quyền lợi:
- Môi trường làm việc chuyên nghiệp, năng động, thân thiện
- Luôn được tiếp xúc với công nghệ và thử thách mới.
- Lương: Lương cứng + hoa hồng + phụ cấp xăng xe, điện thoại
- Thưởng theo ngày lễ, tết
- Được đào tạo kĩ năng mềm ( kỹ năng giao tiếp, xử lý tình huống…..)
- Làm việc từ T2 – sáng T7
- Đóng bảo hiểm theo quy định của Nhà nước
- Được hưởng đầy đủ các chế độ theo quy định của luật lao động
Ứng viên vui lòng gửi hồ sơ cho chúng tôi qua email info@hurasoft.com
",
+ "id": "c5c1"
},
{
"title": "Nhân viên chăm sóc khách hàng",
@@ -372,7 +373,8 @@
"end_date": "31-12-2024",
"location": "Hà Nội",
"applicant_count": 1,
- "description": "MÔ TẢ CÔNG VIỆC
- Tư vấn các khách hàng tiềm năng sản phẩm, dịch vụ của công ty ( sản phẩm phần mềm)
- Chốt hợp đồng khách hàng, triển khai quy trình làm việc với khách hàng.
- Hỗ trợ và chăm sóc khách hàng để đảm bảo khách hàng khai thác tối đa lợi ích của sản phẩm.
- Làm việc với các phòng ban liên quan để liên tục cải thiện, nâng cao chất lượng sản phẩm
YÊU CẦU CÔNG VIỆC
- Nữ từ 1992 - 2002
- Ưu tiên ứng viên được đào tạo chuyên ngành quản trị kinh doanh, CNTT, Thương mại điện tử, marketing hoặc các ngành liên quan.
- Không có kinh nghiệm sẽ được đào tạo, nhưng đã có kinh nghiệm làm việc ở môi trường doanh nghiệp là một lợi thế
- Ứng viên muốn tìm một nơi gắn bó lâu dài, được đào tạo để phát triển sự nghiệp
- Tinh thần trách nhiệm trong công việc. Yêu thích công việc làm việc với khách hàng, sẳn sàng tiếp thu các kiến thức mới
QUYỀN LỢI ĐƯỢC HƯỞNG
- Môi trường trẻ, năng động, được đào tạo kiến thức về sản phẩm TMĐT, công nghệ
- Thưởng theo ngày lễ, tết
- Được đào tạo kĩ năng mềm ( kỹ năng giao tiếp, xử lý tình huống…..)
- Thời gian làm việc: 8h30 - 17h30 (từ T2 – sáng T7 )
- Đóng bảo hiểm theo quy định của Nhà nước
- Được hưởng đầy đủ các chế độ theo quy định của luật lao động
LIÊN HỆ
Ứng viên vui lòng gửi hồ sơ đến email .
"
+ "description": "MÔ TẢ CÔNG VIỆC
- Tư vấn các khách hàng tiềm năng sản phẩm, dịch vụ của công ty ( sản phẩm phần mềm)
- Chốt hợp đồng khách hàng, triển khai quy trình làm việc với khách hàng.
- Hỗ trợ và chăm sóc khách hàng để đảm bảo khách hàng khai thác tối đa lợi ích của sản phẩm.
- Làm việc với các phòng ban liên quan để liên tục cải thiện, nâng cao chất lượng sản phẩm
YÊU CẦU CÔNG VIỆC
- Nữ từ 1992 - 2002
- Ưu tiên ứng viên được đào tạo chuyên ngành quản trị kinh doanh, CNTT, Thương mại điện tử, marketing hoặc các ngành liên quan.
- Không có kinh nghiệm sẽ được đào tạo, nhưng đã có kinh nghiệm làm việc ở môi trường doanh nghiệp là một lợi thế
- Ứng viên muốn tìm một nơi gắn bó lâu dài, được đào tạo để phát triển sự nghiệp
- Tinh thần trách nhiệm trong công việc. Yêu thích công việc làm việc với khách hàng, sẳn sàng tiếp thu các kiến thức mới
QUYỀN LỢI ĐƯỢC HƯỞNG
- Môi trường trẻ, năng động, được đào tạo kiến thức về sản phẩm TMĐT, công nghệ
- Thưởng theo ngày lễ, tết
- Được đào tạo kĩ năng mềm ( kỹ năng giao tiếp, xử lý tình huống…..)
- Thời gian làm việc: 8h30 - 17h30 (từ T2 – sáng T7 )
- Đóng bảo hiểm theo quy định của Nhà nước
- Được hưởng đầy đủ các chế độ theo quy định của luật lao động
LIÊN HỆ
Ứng viên vui lòng gửi hồ sơ đến email .
",
+ "id": "7faa"
},
{
"title": "Lập trình viên front-end",
@@ -381,7 +383,8 @@
"end_date": "31-12-2024",
"location": "Hà Nội",
"applicant_count": 2,
- "description": "Mô tả công việc:
- Tham gia phát triển các sản phẩm web/app của công ty.
- Phối hợp với các bộ phận liên quan để đảm bảo tiến độ bàn giao website được triển khai theo đúng cam kết và chất lượng website bàn giao.
- Công việc sẽ được trao đổi cụ thể hơn trong quá trình phỏng vấn.
Yêu cầu ứng viên:
- Có kinh nghiệm từ 1 năm trở lên phát triển website.
- Thành thạo HTML, CSS, Bootstrap.
- Biết cơ bản Javascript trở lên (sẽ được đào tạo thêm)
- Có kiến thức về chuẩn SEO onpage.
- Có khả năng làm việc độc lập.
- Có tinh thần trách nhiệm trong công việc.
Quyền lợi:
- Lương + hoa hồng dự án theo năng lực.
- Review tăng lương 3-6 tháng/ lần.
- BHXH BHYT theo quy định.
- Được làm việc trong môi trường năng động, có cơ hội học hỏi, phát triển nhanh.
Liên hệ:
Ứng viên vui lòng gửi hồ sơ cho chúng tôi qua email info@hurasoft.com
"
+ "description": "Mô tả công việc:
- Tham gia phát triển các sản phẩm web/app của công ty.
- Phối hợp với các bộ phận liên quan để đảm bảo tiến độ bàn giao website được triển khai theo đúng cam kết và chất lượng website bàn giao.
- Công việc sẽ được trao đổi cụ thể hơn trong quá trình phỏng vấn.
Yêu cầu ứng viên:
- Có kinh nghiệm từ 1 năm trở lên phát triển website.
- Thành thạo HTML, CSS, Bootstrap.
- Biết cơ bản Javascript trở lên (sẽ được đào tạo thêm)
- Có kiến thức về chuẩn SEO onpage.
- Có khả năng làm việc độc lập.
- Có tinh thần trách nhiệm trong công việc.
Quyền lợi:
- Lương + hoa hồng dự án theo năng lực.
- Review tăng lương 3-6 tháng/ lần.
- BHXH BHYT theo quy định.
- Được làm việc trong môi trường năng động, có cơ hội học hỏi, phát triển nhanh.
Liên hệ:
Ứng viên vui lòng gửi hồ sơ cho chúng tôi qua email info@hurasoft.com
",
+ "id": "2faf"
},
{
"title": "Thiết kế đồ họa Website, Mobile (UX Designer)",
@@ -390,7 +393,34 @@
"end_date": "31-12-2024",
"location": "Hà Nội",
"applicant_count": 2,
- "description": "Mô tả công việc:
- Tham gia thiết kế các sản phẩm của công ty (bao gồm website, mobile web, mobile app)
- Nghiên cứu các xu hướng thiết kế mới để liên tục cải thiện, nâng cao chất lượng sản phẩm
- Phối hợp với các phòng ban liên quan để hoàn thành nhiệm vụ được giao
Yêu cầu công việc:
- Thành thạo Figma, Photoshop
- Tiếng Anh đọc hiểu tài liệu
- Ưu tiên ứng viên có hiểu biết về HTML/CSS và các thư viện Ant Design, Material Design, Tailwind CSS ..
- Năng động, tinh thần làm việc tốt.
Liên hệ:
Ứng viên vui lòng gửi hồ sơ cho chúng tôi qua email info@hurasoft.com
"
+ "description": "Mô tả công việc:
- Tham gia thiết kế các sản phẩm của công ty (bao gồm website, mobile web, mobile app)
- Nghiên cứu các xu hướng thiết kế mới để liên tục cải thiện, nâng cao chất lượng sản phẩm
- Phối hợp với các phòng ban liên quan để hoàn thành nhiệm vụ được giao
Yêu cầu công việc:
- Thành thạo Figma, Photoshop
- Tiếng Anh đọc hiểu tài liệu
- Ưu tiên ứng viên có hiểu biết về HTML/CSS và các thư viện Ant Design, Material Design, Tailwind CSS ..
- Năng động, tinh thần làm việc tốt.
Liên hệ:
Ứng viên vui lòng gửi hồ sơ cho chúng tôi qua email info@hurasoft.com
",
+ "id": "5632"
+ }
+ ],
+ "contacts": [
+ {
+ "id": "e59b",
+ "name": "",
+ "email": "",
+ "phone": "",
+ "website": "",
+ "note": ""
+ },
+ {
+ "id": "54e2",
+ "name": "",
+ "email": "",
+ "phone": "",
+ "website": "",
+ "note": ""
+ },
+ {
+ "id": "3be7",
+ "name": "hura",
+ "email": "hura@gmail.com",
+ "phone": "0987654321",
+ "website": "mega@gmail.com",
+ "note": "liên hệ tôi"
}
]
-}
+}
\ No newline at end of file
diff --git a/src/api/apiService.ts b/src/api/apiService.ts
new file mode 100644
index 0000000..7c549db
--- /dev/null
+++ b/src/api/apiService.ts
@@ -0,0 +1,28 @@
+import { ArticleDetailDataType } from "@/types/article";
+import { JobDetailDataType } from "@/types/job";
+
+
+// Hàm chung để gọi API
+const apiRequest = async (endpoint: string, method: string = "GET", body?: object) => {
+ const response = await fetch(`http://localhost:5000${endpoint}`, {
+ method,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: body ? JSON.stringify(body) : null,
+ });
+
+ if (!response.ok) throw new Error(`Error: ${response.statusText}`);
+ return response.json();
+};
+// API cho bài viết
+export const fetchListArticles = () => apiRequest("/articles");
+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 fetchJobDetail = async (slug: string): Promise => {
+ return apiRequest(`/jobDetails?path=${slug}`);
+};
\ No newline at end of file
diff --git a/src/app/article/[slug]/page.tsx b/src/app/article/[slug]/page.tsx
index c9eaab7..440bcf8 100644
--- a/src/app/article/[slug]/page.tsx
+++ b/src/app/article/[slug]/page.tsx
@@ -2,58 +2,55 @@
import { useParams } from "next/navigation";
import { format } from "date-fns";
import { useEffect, useState } from "react";
-import { ArticleDetails } from "@/types/article";
+import { ArticleDetailDataType } from "@/types/article";
+import { fetchArticleDetail } from "@/api/apiService";
const ArticleDetail = () => {
const { slug } = useParams();
- const [article, setArticle] = useState(null);
+ const [ArticleDetail, setArticleDetails] =
+ useState(null);
useEffect(() => {
- if (slug) {
- const fetchArticleDetail = async () => {
- const response = await fetch(
- `http://localhost:5000/articleDetails?path=${slug}`
- );
- const data = await response.json();
- setArticle(data[0]);
+ if (typeof slug === "string") {
+ const getArticleDetail = async () => {
+ const data = await fetchArticleDetail(slug);
+ setArticleDetails(data[0]);
};
- fetchArticleDetail();
+ getArticleDetail();
}
}, [slug]);
- if (!article) {
- return (
-
- Article not found.
-
- );
- }
-
return (
-
-
- {format(new Date(article.last_update * 1000), "dd/MM/yyyy")}
-
-
{article.title}
+ {ArticleDetail ? (
+
+
+ {format(new Date(ArticleDetail.last_update * 1000), "dd/MM/yyyy")}
+
+
{ArticleDetail.title}
-
{article.summary}
+
{ArticleDetail.summary}
-
-

+

+
+
+
-
-
-
+ ) : (
+
+ Bài viết đang cập nhật...!
+
+ )}
);
diff --git a/src/app/article/page.tsx b/src/app/article/page.tsx
index 49658c1..346acfc 100644
--- a/src/app/article/page.tsx
+++ b/src/app/article/page.tsx
@@ -2,29 +2,23 @@
import { useEffect, useState } from "react";
import { format } from "date-fns";
import Link from "next/link";
-import { ArticlesType } from "@/types/article";
+import { ArticleListDataType } from "@/types/article";
+import { fetchListArticles } from "@/api/apiService";
const HomeArticle = () => {
- const [article, setArticle] = useState(null);
+ const [articleList, setArticleList] = useState(
+ null
+ );
useEffect(() => {
- const fetchArticles = async () => {
- const response = await fetch(`http://localhost:5000/articles`);
- const data = await response.json();
- setArticle(data);
+ const fetchArticleList = async () => {
+ const data = await fetchListArticles();
+ setArticleList(data.list);
};
- fetchArticles();
+ fetchArticleList();
}, []);
- if (!article) {
- return (
-
- Article not found.
-
- );
- }
-
return (
@@ -34,106 +28,115 @@ const HomeArticle = () => {
Cập nhật từ Hurasoft
-
-
- {article.list.slice(0, 1).map((item) => (
-
-
-
-
-
-
-
{" "}
-
- {format(
- new Date(item.last_update * 1000),
- "dd/MM/yyyy HH:mm"
- )}
-
+ {articleList && Array.isArray(articleList) && articleList.length > 0 ? (
+
+
+
+ {articleList.slice(0, 1).map((item) => (
+
+
+
+
+
+
+ {" "}
+
+ {format(
+ new Date(item.last_update * 1000),
+ "dd/MM/yyyy HH:mm"
+ )}
+
+
+
+ {item.title}
+
+
-
- {item.title}
-
-
+ ))}
- ))}
-
-
- {article.list.slice(1, 3).map((item) => (
-
-
-
-
-
-
-
{" "}
-
- {format(
- new Date(item.last_update * 1000),
- "dd/MM/yyyy HH:mm"
- )}
-
+
+ {articleList.slice(1, 3).map((item) => (
+
+
+
+
+
+
+ {" "}
+
+ {format(
+ new Date(item.last_update * 1000),
+ "dd/MM/yyyy HH:mm"
+ )}
+
+
+
+ {item.title}
+
+
-
- {item.title}
-
-
+ ))}
- ))}
-
-
-
-
- Xem thêm bài khác
-
-
- {article.list.map((item) => (
-
-
-

-
-
-
- {" "}
-
- {format(
- new Date(item.last_update * 1000),
- "dd/MM/yyyy HH:mm"
- )}
-
+
+
+
+ Xem thêm bài khác
+
+
+ {articleList.map((item) => (
+
+
+

+
+
+
+ {" "}
+
+ {format(
+ new Date(item.last_update * 1000),
+ "dd/MM/yyyy HH:mm"
+ )}
+
+
+
+ {item.title}
+
+
-
- {item.title}
-
-
+ ))}
- ))}
+
-
+ ) : (
+ <>>
+ )}
);
diff --git a/src/app/contact/page.tsx b/src/app/contact/page.tsx
index 1d65504..4740476 100644
--- a/src/app/contact/page.tsx
+++ b/src/app/contact/page.tsx
@@ -1,5 +1,82 @@
"use client";
+
+import React, { useState } from "react";
+
+interface FormData {
+ name: string;
+ email: string;
+ phone: string;
+ website: string;
+ note: string;
+}
+
+interface Errors {
+ name?: string;
+ email?: string;
+ phone?: string;
+ website?: string;
+ note?: string;
+}
+
+// Hàm kiểm tra định dạng email và số điện thoại
+const validateEmail = (email: string) =>
+ /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email);
+const validatePhone = (phone: string) => /^[0-9]{10,11}$/.test(phone);
+
const Contact = () => {
+ const [formData, setFormData] = useState
({
+ name: "",
+ email: "",
+ phone: "",
+ website: "",
+ note: "",
+ });
+
+ const [errors, setErrors] = useState({});
+
+ // Cập nhật dữ liệu form
+ const handleChange = (e) =>
+ setFormData({ ...formData, [e.target.name]: e.target.value });
+
+ // Kiểm tra và gửi form
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+
+ // Kiểm tra form trước khi gửi
+ const newErrors: Errors = {};
+ if (!formData.name) newErrors.name = "Tên không được để trống!";
+ if (!formData.email || !validateEmail(formData.email))
+ newErrors.email = "Email không hợp lệ!";
+ if (!formData.phone || !validatePhone(formData.phone))
+ newErrors.phone = "Số điện thoại không hợp lệ!";
+ if (!formData.note) newErrors.note = "Nội dung không được để trống!";
+ setErrors(newErrors);
+
+ if (Object.keys(newErrors).length > 0) return;
+
+ // Gửi dữ liệu
+ try {
+ const response = await fetch("http://localhost:5000/contacts", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(formData),
+ });
+
+ if (response.ok) {
+ alert("Bạn đã gửi liên hệ thành công!");
+ setFormData({ name: "", email: "", phone: "", website: "", note: "" });
+ setErrors({});
+ } else {
+ alert(
+ "Liên hệ không thành công. Vui lòng kiểm tra lại thông tin của bạn."
+ );
+ }
+ } catch (error) {
+ console.error("Error submitting form:", error);
+ alert("An error occurred. Please try again.");
+ }
+ };
+
return (
@@ -9,14 +86,13 @@ const Contact = () => {
Đội ngũ hỗ trợ của Hurasoft luôn sẵn sàng hỗ trợ quý khách
-
- Tầng 5 - Số 3,ngõ 18 Yên Lãng,Đống Đa, Hà Nội
+ Tầng 5 - Số 3, ngõ 18 Yên Lãng, Đống Đa, Hà Nội
@@ -24,7 +100,7 @@ const Contact = () => {
@@ -42,72 +118,44 @@ const Contact = () => {
Để lại lời nhắn
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Gửi thông tin
-
+
diff --git a/src/app/job/[slug]/page.tsx b/src/app/job/[slug]/page.tsx
index afd247a..56127f3 100644
--- a/src/app/job/[slug]/page.tsx
+++ b/src/app/job/[slug]/page.tsx
@@ -1,41 +1,38 @@
"use client";
import { useState, useEffect } from "react";
import { useParams } from "next/navigation";
-import { JobDetailType } from "@/types/job";
+import { JobDetailDataType } from "@/types/job";
+import { fetchJobDetail } from "@/api/apiService";
const JobDetails = () => {
- const [job, setJob] = useState
(null);
+ const [JobDetail, setJobDetail] = useState(null);
const [activeTab, setActiveTab] = useState("#info");
const { slug } = useParams();
const showTab = (tab: string) => {
- console.log(`Tab clicked: ${tab}`);
setActiveTab(tab);
};
useEffect(() => {
- if (slug) {
- const fetchJobDetail = async () => {
- const response = await fetch(
- `http://localhost:5000/jobDetails?path=${slug}`
- );
- const data = await response.json();
- setJob(data[0]);
+ if (typeof slug === "string") {
+ const getJobDetail = async () => {
+ const data = await fetchJobDetail(slug);
+ setJobDetail(data[0]);
};
- fetchJobDetail();
+ getJobDetail();
}
}, [slug]);
return (
- {job ? (
+ {JobDetail ? (
-
{job.title}
+
{JobDetail.title}
Địa điểm
-
{job.location}
+
{JobDetail.location}
Hình thức làm việc
@@ -43,7 +40,7 @@ const JobDetails = () => {
Số lượng tuyển
-
{job.applicant_count}
+
{JobDetail.applicant_count}
@@ -73,7 +70,9 @@ const JobDetails = () => {
}`}
id="info"
>
-
+
showTab("#formjob")}
diff --git a/src/app/job/page.tsx b/src/app/job/page.tsx
index d11f86d..b40f129 100644
--- a/src/app/job/page.tsx
+++ b/src/app/job/page.tsx
@@ -1,28 +1,28 @@
"use client";
import Link from "next/link";
import { useState, useEffect } from "react";
-import { JobType } from "@/types/job";
+import { ListJobDataType } from "@/types/job";
+import { fetchListJobs } from "@/api/apiService";
const HomeJob = () => {
- const [job, setJob] = useState(null);
+ const [ListJob, setListJob] = useState(null);
useEffect(() => {
- const fetchJob = async () => {
- const response = await fetch(`http://localhost:5000/jobs`);
- const data = await response.json();
- setJob(data);
+ const getListJob = async () => {
+ const data = await fetchListJobs();
+ setListJob(data.list);
};
- fetchJob();
+ getListJob();
}, []);
return (
Tuyển dụng
- {job && job.list && job.list.length > 0 ? (
+ {ListJob && Array.isArray(ListJob) && ListJob.length > 0 ? (
- {job.list.map((item) => (
+ {ListJob.map((item) => (
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 03f7423..c3eb84e 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -4,10 +4,13 @@ import Image from "next/image";
import Link from "next/link";
import { format } from "date-fns";
import { homePageEffect } from "@/effects/homeEffect";
-import { ArticlesType } from "@/types/article";
+import { ArticleListDataType } from "@/types/article";
+import { fetchListArticles } from "@/api/apiService";
export default function Home() {
- const [article, setArticle] = useState
(null);
+ const [articleList, setArticleList] = useState(
+ null
+ );
useEffect(() => {
const typingNode = document.getElementById("typewriter") as HTMLElement;
@@ -19,9 +22,8 @@ export default function Home() {
homePageEffect.startCarousel("#navheight", true, 3000);
const fetchArticleNews = async () => {
- const response = await fetch(`http://localhost:5000/articles`);
- const data = await response.json();
- setArticle(data);
+ const data = await fetchListArticles();
+ setArticleList(data.list);
};
fetchArticleNews();
@@ -548,13 +550,13 @@ export default function Home() {
- {article && article.list && article.list.length > 0 ? (
+ {articleList && Array.isArray(articleList) && articleList.length > 0 ? (
Có gì mới?
- {article.list.slice(0, 1).map((item) => (
+ {articleList.slice(0, 1).map((item) => (
diff --git a/src/styles/style.css b/src/styles/style.css
index 38a6922..62c3d32 100644
--- a/src/styles/style.css
+++ b/src/styles/style.css
@@ -1110,6 +1110,12 @@ main {
.page-contact .item-form {
margin-bottom: 10px;
}
+.page-contact .item-form .note-error {
+ color: red;
+ margin-top: 5px;
+ font-style: italic;
+}
+
.page-contact .input-item {
background: #fff;
}
diff --git a/src/types/article.ts b/src/types/article.ts
index 30f5dce..02c4a86 100644
--- a/src/types/article.ts
+++ b/src/types/article.ts
@@ -21,7 +21,7 @@ export interface Article {
url: string;
}
-export interface ArticleDetails {
+export interface ArticleDetailDataType {
id: number;
title: string;
summary: string;
@@ -35,7 +35,7 @@ export interface ArticleDetails {
last_update: number;
}
-export interface ArticlesType {
+export interface ArticleListDataType {
total: number;
list: Article[];
}
\ No newline at end of file
diff --git a/src/types/job.ts b/src/types/job.ts
index 2664f15..a725b2d 100644
--- a/src/types/job.ts
+++ b/src/types/job.ts
@@ -3,8 +3,7 @@ export interface JobImage {
large: string; // Đường dẫn ảnh lớn
}
-
-export interface Job {
+export interface JobdataType {
id: number;
title: string;
summary: string;
@@ -21,12 +20,12 @@ export interface Job {
}
-export interface JobType {
+export interface ListJobDataType {
total: number;
- list: Job[];
+ list: JobdataType[];
}
-export interface JobDetailType {
+export interface JobDetailDataType {
title: string;
path: string;
salary: string;