Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
VCCI-News
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Văn Hoàng
VCCI-News
Commits
ee5e37bf
Commit
ee5e37bf
authored
Jan 06, 2026
by
Phạm Quang Bảo
Browse files
Options
Browse Files
Download
Plain Diff
[tag]staging
parents
f55cf677
5bbdd04f
Pipeline
#46565
passed with stages
in 6 minutes and 28 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
43 additions
and
119 deletions
+43
-119
mock-data.ts
src/app/(main)/site-map/_lib/mock-data.ts
+0
-94
page.tsx
src/app/(main)/site-map/page.tsx
+43
-25
No files found.
src/app/(main)/site-map/_lib/mock-data.ts
deleted
100644 → 0
View file @
f55cf677
export
type
SiteMapItem
=
{
label
:
string
;
url
:
string
;
children
?:
SiteMapItem
[];
};
export
const
MOCK_SITEMAP
:
SiteMapItem
[]
=
[
{
label
:
"Trang chủ"
,
url
:
""
,
children
:
[]
},
{
label
:
"Giới thiệu"
,
url
:
"/gioi-thieu"
,
children
:
[
{
label
:
"Về VCCI-HCM"
,
url
:
"/gioi-thieu"
,
children
:
[]
},
{
label
:
"Chức năng và nhiệm vụ"
,
url
:
"/gioi-thieu/chuc-nang-va-nhiem-vu"
,
children
:
[]
},
{
label
:
"Sơ đồ tổ chức"
,
url
:
"/gioi-thieu/so-do-to-chuc"
,
children
:
[]
},
{
label
:
"Dịch vụ cung cấp"
,
url
:
"/gioi-thieu/dich-vu-cung-cap"
,
children
:
[]
},
],
},
{
label
:
"Hội viên"
,
url
:
"/hoi-vien"
,
children
:
[
{
label
:
"Lợi ích của hội viên VCCI"
,
url
:
"/hoi-vien"
,
children
:
[]
},
{
label
:
"Đăng ký hội viên"
,
url
:
"/hoi-vien/dang-ky-hoi-vien"
,
children
:
[]
},
{
label
:
"Kết nối hội viên"
,
url
:
"/hoi-vien/ket-noi-hoi-vien"
,
children
:
[]
},
{
label
:
"Tin hội viên"
,
url
:
"/hoi-vien/tin-hoi-vien"
,
children
:
[]
},
],
},
{
label
:
"Hoạt động"
,
url
:
"/hoat-dong"
,
children
:
[
{
label
:
"Sự kiện"
,
url
:
"/hoat-dong/su-kien"
,
children
:
[]
},
{
label
:
"Đào tạo"
,
url
:
"/hoat-dong/dao-tao"
,
children
:
[]
},
],
},
{
label
:
"Xuất xứ hàng hóa"
,
url
:
"/xuat-xu-hang-hoa"
,
children
:
[
{
label
:
"Định nghĩa chung"
,
url
:
"/xuat-xu-hang-hoa"
,
children
:
[]
},
{
label
:
"Mục đích của C/O"
,
url
:
"/xuat-xu-hang-hoa/muc-dich"
,
children
:
[]
},
{
label
:
"Luật áp dụng về C/O"
,
url
:
"/xuat-xu-hang-hoa/luat-ap-dung"
,
children
:
[]
},
{
label
:
"Thủ tục cấp C/O"
,
url
:
"/xuat-xu-hang-hoa/thu-tuc-cap"
,
children
:
[]
},
{
label
:
"Biểu mẫu C/O và cách khai"
,
url
:
"/xuat-xu-hang-hoa/bieu-mau-c-o-va-cach-khai"
,
children
:
[]
},
{
label
:
"Phí và lệ phí cấp C/O"
,
url
:
"/xuat-xu-hang-hoa/phi-le-phi-cap"
,
children
:
[]
},
{
label
:
"Điểm cấp và thời gian cấp C/O"
,
url
:
"/xuat-xu-hang-hoa/diem-cap-va-thoi-gian-cap"
,
children
:
[]
},
{
label
:
"Thông tin liên hệ"
,
url
:
"/xuat-xu-hang-hoa/thong-tin-lien-he"
,
children
:
[]
},
],
},
{
label
:
"Đại diện giới chủ"
,
url
:
"/dai-dien-gioi-chu"
,
children
:
[
{
label
:
"Chức năng đại diện người sử dụng lao động"
,
url
:
"/dai-dien-gioi-chu/chuc-nang-dai-dien-nguoi-su-dung-lao-dong"
,
children
:
[]
},
{
label
:
"Sự kiện - tập huấn NSDLĐ"
,
url
:
"/dai-dien-gioi-chu/tap-huan-nsdld"
,
children
:
[]
},
{
label
:
"Tin liên quan"
,
url
:
"/dai-dien-gioi-chu/tin-lien-quan"
,
children
:
[]
},
{
label
:
"Chủ đề"
,
url
:
"/dai-dien-gioi-chu/chu-de"
,
children
:
[]
},
],
},
{
label
:
"Xúc tiến thương mại"
,
url
:
"/xuc-tien-thuong-mai"
,
children
:
[
{
label
:
"Hồ sơ thị trường"
,
url
:
"/xuc-tien-thuong-mai/ho-so-thi-truong"
,
children
:
[]
},
{
label
:
"Môi trường kinh doanh"
,
url
:
"/xuc-tien-thuong-mai/moi-truong-kinh-doanh"
,
children
:
[]
},
{
label
:
"Cơ hội kinh doanh"
,
url
:
"/xuc-tien-thuong-mai/co-hoi-kinh-doanh"
,
children
:
[]
},
{
label
:
"Hỗ trợ kinh doanh"
,
url
:
"/xuc-tien-thuong-mai/ho-tro-kinh-doanh"
,
children
:
[]
},
],
},
{
label
:
"Thông tin truyền thông"
,
url
:
"/thong-tin-truyen-thong"
,
children
:
[
{
label
:
"Tin VCCI"
,
url
:
"/thong-tin-truyen-thong/tin-vcci"
,
children
:
[]
},
{
label
:
"Tin kinh tế"
,
url
:
"/thong-tin-truyen-thong/tin-kinh-te"
,
children
:
[]
},
{
label
:
"Tin doanh nghiệp"
,
url
:
"/thong-tin-truyen-thong/tin-doanh-nghiep"
,
children
:
[]
},
{
label
:
"Chuyên đề"
,
url
:
"/thong-tin-truyen-thong/chuyen-de"
,
children
:
[]
},
{
label
:
"Thông tin chính sách và pháp luật"
,
url
:
"/thong-tin-truyen-thong/thong-tin-chinh-sach-va-phap-luat"
,
children
:
[]
},
{
label
:
"Ấn phẩm"
,
url
:
"/thong-tin-truyen-thong/an-pham"
,
children
:
[]
},
{
label
:
"Thư viện tài liệu"
,
url
:
"/thong-tin-truyen-thong/thu-vien-tai-lieu"
,
children
:
[]
},
],
},
];
export
default
MOCK_SITEMAP
;
src/app/(main)/site-map/page.tsx
View file @
ee5e37bf
"use client"
;
"use client"
;
import
React
from
"react"
;
import
React
from
"react"
;
import
{
MOCK_SITEMAP
}
from
"./_lib/mock-data"
;
import
Link
from
"next/link"
;
import
Link
from
"next/link"
;
import
{
useGetNewsPageConfigGetHierarchical
}
from
"@/api/endpoints/news-page-config"
;
import
{
GetNewsPageConfigResponseType
}
from
"@/api/types/news-page-config"
;
function
SiteMapPage
()
{
function
SiteMapPage
()
{
const
homepage
=
MOCK_SITEMAP
[
0
];
const
{
data
:
categoriesData
,
isLoading
,
isError
}
=
useGetNewsPageConfigGetHierarchical
<
GetNewsPageConfigResponseType
>
();
const
sections
=
MOCK_SITEMAP
.
slice
(
1
);
if
(
isLoading
)
{
return
(
<
div
className=
"min-h-screen bg-gray-50 py-12 flex items-center justify-center"
>
<
div
className=
"text-[#063e8e] text-xl font-semibold"
>
Đang tải...
</
div
>
</
div
>
);
}
if
(
isError
||
!
categoriesData
?.
responseData
)
{
return
(
<
div
className=
"min-h-screen bg-gray-50 py-12 flex items-center justify-center"
>
<
div
className=
"text-red-600 text-xl font-semibold"
>
Không thể tải dữ liệu
</
div
>
</
div
>
);
}
const
sections
=
categoriesData
.
responseData
.
children
||
[];
return
(
return
(
<
div
className=
"min-h-screen bg-gray-50 py-12"
>
<
div
className=
"min-h-screen bg-gray-50 py-12"
>
...
@@ -19,34 +37,34 @@ function SiteMapPage() {
...
@@ -19,34 +37,34 @@ function SiteMapPage() {
{
/* Homepage - Top Level */
}
{
/* Homepage - Top Level */
}
<
div
className=
"relative mb-20"
>
<
div
className=
"relative mb-20"
>
<
Link
<
Link
href=
{
homepage
.
url
}
href=
"/"
className=
"block bg-[#063e8e] text-white px-8 py-4 rounded-lg font-semibold text-center hover:bg-[#0a4fb5] transition shadow-lg min-w-[200px]"
className=
"block bg-[#063e8e] text-white px-8 py-4 rounded-lg font-semibold text-center hover:bg-[#0a4fb5] transition shadow-lg min-w-[200px]"
>
>
{
homepage
.
label
.
toUpperCase
()
}
TRANG CHỦ
</
Link
>
</
Link
>
{
/* Vertical line from homepage down */
}
{
/* Vertical line from homepage down */
}
<
div
className=
"absolute left-
1/2 -translate-x-1/2 top-full h-16
w-0.5 bg-gray-600"
></
div
>
<
div
className=
"absolute left-
[99px] -translate-x-1/2 top-full h-20
w-0.5 bg-gray-600"
></
div
>
</
div
>
</
div
>
{
/* Main Sections - Second Level */
}
{
/* Main Sections - Second Level */
}
<
div
className=
"relative w-full max-w-[1400px]"
>
<
div
className=
"relative w-full max-w-[1400px]"
>
{
/* Horizontal line connecting all sections */
}
{
/* Horizontal line connecting all sections */
}
<
div
className=
"absolute top-0 left-[
7%] right-[7
%] h-0.5 bg-gray-600 z-0"
></
div
>
<
div
className=
"absolute top-0 left-[
6.3%] right-[6.3
%] h-0.5 bg-gray-600 z-0"
></
div
>
<
div
className=
"grid grid-cols-2 md:grid-cols-4 lg:grid-cols-7 gap-6 relative pt-4"
>
<
div
className=
"grid grid-cols-2 md:grid-cols-4 lg:grid-cols-7 gap-6 relative pt-4"
>
{
sections
.
map
((
section
,
idx
)
=>
(
{
sections
.
map
((
section
,
idx
)
=>
(
<
div
key=
{
idx
}
className=
"relative flex flex-col items-center"
>
<
div
key=
{
section
.
id
}
className=
"relative flex flex-col items-center"
>
{
/* Vertical line from horizontal bar down to section */
}
{
/* Vertical line from horizontal bar down to section */
}
<
div
className=
"absolute -top-4 left-1/2 -translate-x-1/2 h-4 w-0.5 bg-gray-600 z-10"
></
div
>
<
div
className=
"absolute -top-4 left-1/2 -translate-x-1/2 h-4 w-0.5 bg-gray-600 z-10"
></
div
>
{
/* Section Box */
}
{
/* Section Box */
}
<
div
className=
"relative z-20"
>
<
div
className=
"relative z-20"
>
<
Link
<
Link
href=
{
section
.
url
}
href=
{
section
.
static_link
||
"#"
}
className=
"flex bg-[#063e8e] text-white px-4 py-3 rounded-md font-medium text-center hover:bg-[#0a4fb5] transition shadow-md w-full text-sm min-h-20 items-center justify-center"
className=
"flex bg-[#063e8e] text-white px-4 py-3 rounded-md font-medium text-center hover:bg-[#0a4fb5] transition shadow-md w-full text-sm min-h-20 items-center justify-center"
>
>
<
span
className=
"leading-tight"
>
{
section
.
label
.
toUpperCase
()
}
</
span
>
<
span
className=
"leading-tight"
>
{
section
.
name
.
toUpperCase
()
}
</
span
>
</
Link
>
</
Link
>
{
/* Vertical line from section down to children */
}
{
/* Vertical line from section down to children */
}
...
@@ -57,26 +75,26 @@ function SiteMapPage() {
...
@@ -57,26 +75,26 @@ function SiteMapPage() {
{
/* Children - Third Level */
}
{
/* Children - Third Level */
}
{
section
.
children
&&
section
.
children
.
length
>
0
&&
(
{
section
.
children
&&
section
.
children
.
length
>
0
&&
(
<
div
className=
"mt-6 flex flex-col gap-3 w-full relative z-20"
>
<
div
className=
"mt-6 flex flex-col gap-3 w-full relative"
>
{
/* Vertical spine connecting all children */
}
<
div
className=
"absolute left-1/2 -translate-x-1/2 w-0.5 bg-gray-600"
style=
{
{
top
:
'-24px'
,
bottom
:
'0'
,
}
}
></
div
>
{
section
.
children
.
map
((
child
,
childIdx
)
=>
(
{
section
.
children
.
map
((
child
,
childIdx
)
=>
(
<
div
key=
{
childIdx
}
className=
"relative"
>
<
div
key=
{
child
.
id
}
className=
"relative"
>
{
/* Vertical line connecting child to parent */
}
{
childIdx
===
0
?
(
// First child connects to the line from parent
<
div
className=
"absolute left-1/2 -translate-x-1/2 -top-6 h-6 w-0.5 bg-gray-600"
></
div
>
)
:
(
// Other children connect to the vertical spine
<
div
className=
"absolute left-1/2 -translate-x-1/2 -top-[calc(1.5rem+0.375rem)] bottom-1/2 w-0.5 bg-gray-600"
></
div
>
)
}
{
/* Horizontal line from spine to child box */
}
{
/* Horizontal line from spine to child box */
}
<
div
className=
"absolute
left-1/2 top-1/2 -translate-y-1/2 w-1/2 h-0.5 bg-gray-600 -translate-x-full
"
></
div
>
<
div
className=
"absolute
right-1/2 top-1/2 -translate-y-1/2 w-1/2 h-0.5 bg-gray-600
"
></
div
>
<
Link
<
Link
href=
{
child
.
url
}
href=
{
child
.
static_link
||
"#"
}
className=
"block bg-gray-400 text-white px-3 py-2.5 rounded text-xs font-medium text-center hover:bg-gray-500 transition shadow-sm leading-tight relative z-10"
className=
"block bg-gray-400 text-white px-3 py-2.5 rounded text-xs font-medium text-center hover:bg-gray-500 transition shadow-sm leading-tight relative z-10"
>
>
{
child
.
label
.
toUpperCase
()
}
{
child
.
name
.
toUpperCase
()
}
</
Link
>
</
Link
>
</
div
>
</
div
>
))
}
))
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment