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
764fca75
Commit
764fca75
authored
May 21, 2026
by
Lê Bảo Hồng Đức
☄
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'fix/home' into 'develop-news'
fix See merge request
!68
parents
ced57884
878bfb2f
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
74 additions
and
123 deletions
+74
-123
index.tsx
...(main)/(home)/components/business-opportunities/index.tsx
+42
-53
index.tsx
src/app/(main)/(home)/components/events-calendar/index.tsx
+11
-7
index.tsx
src/app/(main)/(home)/components/policies-and-laws/index.tsx
+16
-7
MarketProfilePage.tsx
.....slug]/templates/information-pages/MarketProfilePage.tsx
+2
-53
footer.tsx
src/app/(main)/_lib/layout/footer.tsx
+3
-3
No files found.
src/app/(main)/(home)/components/business-opportunities/index.tsx
View file @
764fca75
...
...
@@ -7,9 +7,7 @@ import Link from "next/link";
function
BusinessOpportunities
()
{
const
{
businessPosts
,
categoryLinks
,
categoryNames
}
=
useHomePosts
();
const
businessItems
=
businessPosts
;
const
[
featuredItem
,
...
listItems
]
=
businessItems
;
const
listSlots
=
Array
.
from
({
length
:
3
},
(
_
,
index
)
=>
listItems
[
index
]
??
null
);
const
listSlots
=
Array
.
from
({
length
:
4
},
(
_
,
index
)
=>
businessPosts
[
index
]
??
null
);
const
sectionLink
=
categoryLinks
.
get
(
categoryNames
.
coHoiKinhDoanh
.
toLowerCase
())
??
"/xuc-tien-thuong-mai/co-hoi-kinh-doanh"
;
...
...
@@ -32,39 +30,31 @@ function BusinessOpportunities() {
</
Link
>
</
div
>
<
div
className=
"flex min-h-[270px] flex-1 flex-col justify-between gap-3"
>
{
featuredItem
?
(
<
div
className=
"flex min-h-[270px] flex-1 flex-col gap-2.5"
>
{
listSlots
.
map
((
item
,
index
)
=>
item
?
(
<
Link
href=
{
featuredItem
.
externalLink
}
className=
"block rounded-[18px] bg-[#f5f7fb] px-4 py-3.5 transition-colors hover:bg-[#eef3fb]"
key=
{
item
.
id
}
href=
{
item
.
externalLink
}
className=
{
`group flex min-h-[58px] gap-3 rounded-[18px] px-4 py-3 transition-all duration-200 hover:bg-[#f5f7fb] hover:shadow-[0_10px_24px_rgba(36,70,156,0.08)] ${
index === 0 ? "pt-3.5" : ""
}`
}
>
<
span
className=
"mt-1 h-[40px] w-[2px] shrink-0 rounded-full bg-[#f7b500] transition-opacity duration-200 group-hover:opacity-0"
/>
<
div
className=
"hidden min-w-0 group-hover:block"
>
<
h3
className=
"line-clamp-2 text-[16px] font-bold leading-[1.45] text-[#264798] md:text-[17px]"
>
{
featuredI
tem
.
title
}
{
i
tem
.
title
}
</
h3
>
<
p
className=
"mt-2 text-[13px] text-[#9aa8c1]"
>
{
dayjs
(
featuredItem
.
publishedAt
||
featuredI
tem
.
createdAt
).
format
(
"DD/MM/YYYY"
)
}
{
dayjs
(
item
.
publishedAt
||
i
tem
.
createdAt
).
format
(
"DD/MM/YYYY"
)
}
</
p
>
</
Link
>
)
:
(
<
div
className=
"rounded-[18px] bg-[#f5f7fb] px-4 py-3.5"
>
<
div
className=
"h-6 w-5/6 rounded bg-white"
/>
<
div
className=
"mt-2 h-4 w-24 rounded bg-white/80"
/>
</
div
>
)
}
<
div
className=
"flex flex-col gap-2.5"
>
{
listSlots
.
map
((
item
,
index
)
=>
item
?
(
<
Link
key=
{
item
.
id
}
href=
{
item
.
externalLink
}
className=
"flex min-h-[58px] gap-3 rounded-[14px] px-0.5 py-1 transition-colors hover:bg-[#f8fafe]"
>
<
span
className=
"mt-1 h-[40px] w-[2px] shrink-0 rounded-full bg-[#f7b500]"
/>
<
div
className=
"min-w-0"
>
<
h4
className=
"line-clamp-2 text-[15px] leading-[1.45] text-[#264798]"
>
<
div
className=
"min-w-0 group-hover:hidden"
>
<
h3
className=
"line-clamp-2 text-[15px] leading-[1.45] text-[#264798] md:text-[16px]"
>
{
item
.
title
}
</
h4
>
</
h3
>
<
p
className=
"mt-1.5 text-[13px] text-[#9aa8c1]"
>
{
dayjs
(
item
.
publishedAt
||
item
.
createdAt
).
format
(
"DD/MM/YYYY"
)
}
</
p
>
...
...
@@ -73,7 +63,7 @@ function BusinessOpportunities() {
)
:
(
<
div
key=
{
`business-placeholder-${index}`
}
className=
"flex min-h-[58px] gap-3 rounded-[14px] px-0.5 py-1"
className=
{
`flex min-h-[58px] gap-3 rounded-[14px] px-0.5 py-1 ${index === 0 ? "pt-0.5" : ""}`
}
>
<
span
className=
"mt-1 h-[40px] w-[2px] shrink-0 rounded-full bg-[#f7b500]/40"
/>
<
div
className=
"min-w-0 flex-1"
>
...
...
@@ -84,7 +74,6 @@ function BusinessOpportunities() {
),
)
}
</
div
>
</
div
>
</
section
>
);
}
...
...
src/app/(main)/(home)/components/events-calendar/index.tsx
View file @
764fca75
...
...
@@ -37,14 +37,21 @@ function EventsCalendar({
className
?:
string
;
compact
?:
boolean
;
})
{
const
today
=
dayjs
();
const
todayKey
=
today
.
format
(
"YYYY-MM-DD"
);
const
todayMonth
=
today
.
month
();
const
todayYear
=
today
.
year
();
const
[
currentMonth
,
setCurrentMonth
]
=
useState
(
new
Date
());
const
[
selectedDateKey
,
setSelectedDateKey
]
=
useState
<
string
|
null
>
(
null
);
const
eventCalendarQuery
=
useEventCalendarPosts
(
currentMonth
);
const
monthEvents
=
eventCalendarQuery
.
data
??
[];
useEffect
(()
=>
{
setSelectedDateKey
(
null
);
},
[
currentMonth
]);
const
viewingCurrentMonth
=
currentMonth
.
getMonth
()
===
todayMonth
&&
currentMonth
.
getFullYear
()
===
todayYear
;
setSelectedDateKey
(
viewingCurrentMonth
?
todayKey
:
null
);
},
[
currentMonth
,
todayKey
,
todayMonth
,
todayYear
]);
const
days
=
useMemo
(()
=>
{
const
monthStart
=
startOfMonth
(
currentMonth
);
...
...
@@ -80,7 +87,6 @@ function EventsCalendar({
const
selectedEvents
=
selectedDateKey
?
eventMap
.
get
(
selectedDateKey
)
??
[]
:
[];
const
highlightedEvents
=
selectedEvents
.
length
>
0
?
selectedEvents
:
monthEvents
.
slice
(
0
,
1
);
const
todayKey
=
dayjs
().
format
(
"YYYY-MM-DD"
);
return
(
<
aside
...
...
@@ -173,16 +179,14 @@ function EventsCalendar({
isToday
&&
inMonth
&&
!
selectable
&&
"bg-[#eef3fb] font-semibold text-[#24469c] ring-2 ring-[#d7e2f5]"
,
variant
===
"training"
&&
"bg-[#ffbc11] font-semibold text-[#163b73]"
,
variant
===
"event"
&&
"bg-[#1e3f9a] font-semibold text-white"
,
variant
===
"mixed"
&&
"bg-[#1e3f9a] font-semibold text-white ring-2 ring-[#ffbc11] ring-offset-2 ring-offset-white"
,
variant
===
"mixed"
&&
"bg-[#1e3f9a] font-semibold text-white"
,
selectable
?
"cursor-pointer hover:scale-[1.04] hover:shadow-[0_10px_20px_rgba(36,70,156,0.16)]"
:
"cursor-default"
,
selected
&&
variant
!==
"mixed"
&&
"ring-2 ring-[#f7b500] ring-offset-2 ring-offset-white"
,
selected
&&
"ring-2 ring-[#f7b500] ring-offset-2 ring-offset-white"
,
isToday
&&
selectable
&&
!
selected
&&
variant
!==
"mixed"
&&
"ring-2 ring-[#9fb3db] ring-offset-2 ring-offset-white"
,
)
}
>
...
...
src/app/(main)/(home)/components/policies-and-laws/index.tsx
View file @
764fca75
...
...
@@ -7,8 +7,7 @@ import Link from "next/link";
function
PolicyAndLaws
()
{
const
{
policyPosts
,
categoryLinks
,
categoryNames
}
=
useHomePosts
();
const
policyItems
=
policyPosts
;
const
listSlots
=
Array
.
from
({
length
:
4
},
(
_
,
index
)
=>
policyItems
[
index
]
??
null
);
const
listSlots
=
Array
.
from
({
length
:
4
},
(
_
,
index
)
=>
policyPosts
[
index
]
??
null
);
const
sectionLink
=
categoryLinks
.
get
(
categoryNames
.
chinhSachPhapLuat
.
toLowerCase
())
??
"/thong-tin-truyen-thong/thong-tin-chinh-sach-va-phap-luat"
;
...
...
@@ -31,18 +30,28 @@ function PolicyAndLaws() {
</
Link
>
</
div
>
<
div
className=
"flex min-h-[270px] flex-1 flex-col
justify-between
gap-2.5"
>
<
div
className=
"flex min-h-[270px] flex-1 flex-col gap-2.5"
>
{
listSlots
.
map
((
item
,
index
)
=>
item
?
(
<
Link
key=
{
item
.
id
}
href=
{
item
.
externalLink
}
className=
{
`
flex min-h-[58px] gap-3 rounded-[14px] px-0.5 py-1 transition-colors hover:bg-[#f8fafe
] ${
index === 0 ? "pt-
0
.5" : ""
className=
{
`
group flex min-h-[58px] gap-3 rounded-[18px] px-4 py-3 transition-all duration-200 hover:bg-[#f5f7fb] hover:shadow-[0_10px_24px_rgba(36,70,156,0.08)
] ${
index === 0 ? "pt-
3
.5" : ""
}`
}
>
<
span
className=
"mt-1 h-[40px] w-[2px] shrink-0 rounded-full bg-[#f7b500]"
/>
<
div
className=
"min-w-0"
>
<
span
className=
"mt-1 h-[40px] w-[2px] shrink-0 rounded-full bg-[#f7b500] transition-opacity duration-200 group-hover:opacity-0"
/>
<
div
className=
"hidden min-w-0 group-hover:block"
>
<
h3
className=
"line-clamp-2 text-[16px] font-bold leading-[1.45] text-[#264798] md:text-[17px]"
>
{
item
.
title
}
</
h3
>
<
p
className=
"mt-2 text-[13px] text-[#9aa8c1]"
>
{
dayjs
(
item
.
publishedAt
||
item
.
createdAt
).
format
(
"DD/MM/YYYY"
)
}
</
p
>
</
div
>
<
div
className=
"min-w-0 group-hover:hidden"
>
<
h3
className=
"line-clamp-2 text-[15px] leading-[1.45] text-[#264798] md:text-[16px]"
>
{
item
.
title
}
</
h3
>
...
...
src/app/(main)/[...slug]/templates/information-pages/MarketProfilePage.tsx
View file @
764fca75
...
...
@@ -234,8 +234,7 @@ export default function MarketProfilePage({ post }: MarketProfilePageProps) {
</
p
>
<
div
className=
"mt-7 overflow-hidden rounded-[30px] border border-[#dce7f7] bg-white shadow-[0_18px_42px_rgba(17,24,39,0.06)]"
>
<
div
className=
"grid gap-0 lg:grid-cols-[minmax(0,1.2fr)_minmax(280px,0.8fr)]"
>
<
div
className=
"relative min-h-[320px] bg-[#f3f7ff] p-4 sm:p-6"
>
<
div
className=
"relative min-h-[280px] bg-[#f3f7ff] p-4 sm:p-5"
>
<
div
className=
"absolute inset-x-4 top-4 z-10 flex flex-wrap gap-2 sm:inset-x-6 sm:top-6"
>
{
activeRegion
.
markets
.
map
((
item
)
=>
(
<
a
...
...
@@ -256,59 +255,9 @@ export default function MarketProfilePage({ post }: MarketProfilePageProps) {
alt=
{
activeRegion
.
imageAlt
}
width=
{
1200
}
height=
{
900
}
className=
"h-full min-h-[
320px] w-full rounded-[24px] object-cov
er transition-all duration-300"
className=
"h-full min-h-[
280px] w-full rounded-[24px] object-cover object-cent
er transition-all duration-300"
/>
</
div
>
<
div
className=
"flex flex-col justify-between bg-linear-to-br from-[#0f418f] to-[#1a2f65] p-6 text-white"
>
<
div
>
<
p
className=
"text-sm font-semibold uppercase tracking-[0.18em] text-white/72"
>
Tài liệu tham khảo
</
p
>
<
h2
className=
"mt-3 text-[28px] font-bold leading-tight"
>
Tra cứu nhanh theo từng thị trường
</
h2
>
<
p
className=
"mt-4 text-sm leading-7 text-white/82"
>
Dữ liệu mẫu được dựng từ nguồn website bạn gửi, cho phép chuyển nhanh giữa các khu vực để thay đổi phần hình ảnh và nhóm thị trường đang hiển thị.
</
p
>
</
div
>
<
div
className=
"mt-6 space-y-3"
>
{
activeRegion
.
featuredDocument
?
(
<
a
href=
{
activeRegion
.
featuredDocument
.
href
}
target=
"_blank"
rel=
"noreferrer"
className=
"flex items-center justify-between rounded-[22px] bg-white/10 px-4 py-3 transition-colors hover:bg-white/16"
>
<
div
>
<
p
className=
"text-sm font-semibold text-white"
>
{
activeRegion
.
featuredDocument
.
title
}
</
p
>
<
p
className=
"mt-1 text-xs text-white/70"
>
{
activeRegion
.
featuredDocument
.
description
}
</
p
>
</
div
>
<
ArrowDownToLine
className=
"h-5 w-5 shrink-0 text-[#ffca4f]"
/>
</
a
>
)
:
(
<
div
className=
"rounded-[22px] bg-white/10 px-4 py-3"
>
<
p
className=
"text-sm font-semibold text-white"
>
Nguồn tài liệu
</
p
>
<
p
className=
"mt-1 text-xs leading-6 text-white/74"
>
Khu vực này hiện đã có khối chuyển hình ảnh và danh sách thị trường; tài liệu chi tiết sẽ được bổ sung khi có nguồn riêng tương ứng.
</
p
>
</
div
>
)
}
<
div
className=
"rounded-[22px] border border-white/12 bg-white/8 px-4 py-3"
>
<
p
className=
"text-sm font-semibold text-white"
>
Gợi ý sử dụng
</
p
>
<
p
className=
"mt-1 text-xs leading-6 text-white/74"
>
Khi API của trang có nội dung thật, phần UI mẫu này sẽ tự nhường chỗ cho dữ liệu bài viết từ hệ thống.
</
p
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
src/app/(main)/_lib/layout/footer.tsx
View file @
764fca75
...
...
@@ -70,9 +70,9 @@ const getSocialIcon = (key: string): React.ReactNode => {
const quickLinks = [
{
label
:
"Giới thiệu"
,
href
:
"/gioi-thieu"
}
,
{
label
:
"Hội viên"
,
href
:
"/
danh-ba-hoi-vien
"
}
,
{
label
:
"Hoạt động"
,
href
:
"/hoat-dong/
tin-tuc
"
}
,
{
label
:
"Xúc tiến Thương mại"
,
href
:
"/xuc-tien-thuong-mai/
co-hoi/
"
}
,
{
label
:
"Hội viên"
,
href
:
"/
hoi-vien/loi-ich-hoi-vien-vcci
"
}
,
{
label
:
"Hoạt động"
,
href
:
"/hoat-dong/
su-kien
"
}
,
{
label
:
"Xúc tiến Thương mại"
,
href
:
"/xuc-tien-thuong-mai/
ho-so-thi-truong
"
}
,
];
const isValidEmail = (value: string) =
>
...
...
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