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
60672bc5
Commit
60672bc5
authored
Nov 17, 2025
by
Phạm Quang Bảo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix/fallback img and active navigation item
parent
21c709a6
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
49 additions
and
70 deletions
+49
-70
img-error.png
public/img-error.png
+0
-0
index.tsx
src/app/(main)/(home)/components/card-event/index.tsx
+1
-1
index.tsx
src/app/(main)/(home)/components/card-news/index.tsx
+1
-1
page.tsx
src/app/(main)/(home)/page.tsx
+5
-5
page.tsx
src/app/(main)/[...slug]/page.tsx
+1
-1
EventDetailPage.tsx
src/app/(main)/[...slug]/templates/EventDetailPage.tsx
+12
-12
EventPage.tsx
src/app/(main)/[...slug]/templates/EventPage.tsx
+4
-4
InformationPage.tsx
src/app/(main)/[...slug]/templates/InformationPage.tsx
+2
-2
CardNews.type.ts
src/components/base/card-news/CardNews.type.ts
+0
-31
index.tsx
src/components/base/card-news/index.tsx
+2
-2
index.tsx
src/components/base/menu-item/index.tsx
+21
-11
No files found.
public/
VCCI-Chung-300x200-1
.png
→
public/
img-error
.png
View file @
60672bc5
File moved
src/app/(main)/(home)/components/card-event/index.tsx
View file @
60672bc5
...
...
@@ -15,7 +15,7 @@ function CardEvent({ event }: { event: EventItem }) {
className=
'w-[100px] md:w-[130px] aspect-3/2 object-cover'
onError=
{
(
e
)
=>
{
e
.
currentTarget
.
onerror
=
null
e
.
currentTarget
.
src
=
"/
VCCI-Chung-300x200-1
.png"
e
.
currentTarget
.
src
=
"/
img-error
.png"
}
}
/>
<
div
className=
'flex-1'
>
...
...
src/app/(main)/(home)/components/card-news/index.tsx
View file @
60672bc5
...
...
@@ -15,7 +15,7 @@ function CardNews({ news }: { news: NewsItem }) {
className=
"w-[100px] md:w-[130px] aspect-3/2 object-cover"
onError=
{
(
e
)
=>
{
e
.
currentTarget
.
onerror
=
null
e
.
currentTarget
.
src
=
"/
VCCI-Chung-300x200-1
.png"
e
.
currentTarget
.
src
=
"/
img-error
.png"
}
}
/>
<
div
className=
"flex-1"
>
...
...
src/app/(main)/(home)/page.tsx
View file @
60672bc5
...
...
@@ -186,7 +186,7 @@ const Page = () => {
className=
"w-full aspect-3/2 sm:h-56 md:h-64 object-cover"
onError=
{
(
e
)
=>
{
e
.
currentTarget
.
onerror
=
null
e
.
currentTarget
.
src
=
"/
VCCI-Chung-300x200-1
.png"
e
.
currentTarget
.
src
=
"/
img-error
.png"
}
}
/>
<
div
className=
"absolute bottom-0 left-0 right-0 h-20 md:h-24 bg-linear-to-t from-black/80 to-transparent flex items-center justify-center p-3"
>
...
...
@@ -242,7 +242,7 @@ const Page = () => {
className=
"w-full h-full object-cover"
onError=
{
(
e
)
=>
{
e
.
currentTarget
.
onerror
=
null
e
.
currentTarget
.
src
=
"/
VCCI-Chung-300x200-1
.png"
e
.
currentTarget
.
src
=
"/
img-error
.png"
}
}
/>
</
div
>
...
...
@@ -380,7 +380,7 @@ const Page = () => {
className=
"w-full h-full object-cover"
onError=
{
(
e
)
=>
{
(
e
.
target
as
HTMLImageElement
).
src
=
"/
VCCI-Chung-300x200-1
.png"
;
"/
img-error
.png"
;
}
}
/>
</
div
>
...
...
@@ -459,7 +459,7 @@ const Page = () => {
className=
"w-full h-full object-cover"
onError=
{
(
e
)
=>
{
e
.
currentTarget
.
onerror
=
null
e
.
currentTarget
.
src
=
"/
VCCI-Chung-300x200-1
.png"
e
.
currentTarget
.
src
=
"/
img-error
.png"
}
}
/>
<
div
className=
"absolute bg-white opacity-80 bottom-5 left-5 right-5 p-5"
>
...
...
@@ -504,7 +504,7 @@ const Page = () => {
className=
"w-full h-full object-cover"
onError=
{
(
e
)
=>
{
e
.
currentTarget
.
onerror
=
null
e
.
currentTarget
.
src
=
"/
VCCI-Chung-300x200-1
.png"
e
.
currentTarget
.
src
=
"/
img-error
.png"
}
}
/>
<
div
className=
"absolute bg-white opacity-80 bottom-5 left-5 right-5 p-5"
>
...
...
src/app/(main)/[...slug]/page.tsx
View file @
60672bc5
...
...
@@ -46,7 +46,7 @@ export default function DynamicPage() {
}
if
(
slug
.
length
===
2
)
{
return
category
?.
responseData
.
is_article
?
<
ArticlePage
/>
:
<
InformationPage
/>;
return
category
?.
responseData
?
.
is_article
?
<
ArticlePage
/>
:
<
InformationPage
/>;
}
if
(
slug
.
length
===
3
)
{
...
...
src/app/(main)/[...slug]/templates/EventDetailPage.tsx
View file @
60672bc5
...
...
@@ -45,7 +45,7 @@ export default function EventDetailPage() {
<
div
className=
"grid grid-cols-1 lg:grid-cols-3 gap-5"
>
<
main
className=
"lg:col-span-2 bg-white border rounded-md p-8"
>
<
div
className=
'pb-5 text-primary text-2xl leading-normal font-medium'
>
{
eventsDetail
?.
responseData
?.
rows
[
0
].
name
}
{
eventsDetail
?.
responseData
?.
rows
[
0
]
?
.
name
}
</
div
>
<
hr
className=
"py-2"
/>
...
...
@@ -55,8 +55,8 @@ export default function EventDetailPage() {
{
eventsDetail
?.
responseData
?.
rows
[
0
].
image
?
(
<
div
className=
"w-full h-52 relative "
>
<
EventImage
src=
{
`${BASE_URL.imageEndpoint}${eventsDetail
.responseData
.rows[0].image}`
}
alt=
{
eventsDetail
.
responseData
.
rows
[
0
]
.
name
||
"image"
}
src=
{
`${BASE_URL.imageEndpoint}${eventsDetail
?.responseData?
.rows[0].image}`
}
alt=
{
eventsDetail
?.
responseData
?.
rows
[
0
]?
.
name
||
"image"
}
/>
</
div
>
)
:
(
...
...
@@ -89,8 +89,8 @@ export default function EventDetailPage() {
<
div
className=
"text-sm text-gray-500 flex items-center gap-2"
>
<
MapPin
className=
"h-5 w-5 text-blue-600"
/>
<
div
className=
"text-sm font-medium text-gray-800"
>
Địa điểm:
{
eventsDetail
?.
responseData
?.
rows
[
0
].
location
??
eventsDetail
?.
responseData
?.
rows
[
0
].
province
??
Địa điểm:
{
eventsDetail
?.
responseData
?.
rows
[
0
]
?
.
location
??
eventsDetail
?.
responseData
?.
rows
[
0
]
?
.
province
??
"-"
}
</
div
>
</
div
>
...
...
@@ -98,9 +98,9 @@ export default function EventDetailPage() {
<
div
className=
"text-sm text-gray-500 flex items-center gap-2"
>
<
CreditCard
className=
"h-5 w-5 text-yellow-400"
/>
<
div
className=
"text-sm font-medium text-gray-800"
>
Phí tham dự:
{
eventsDetail
?.
responseData
?.
rows
[
0
].
table_cost
?
`${eventsDetail
.responseData.rows[0]
.table_count
} Bàn : ${eventsDetail
.responseData.rows[0]
.table_cost.toLocaleString()} đ`
Phí tham dự:
{
eventsDetail
?.
responseData
?.
rows
[
0
]
?
.
table_cost
?
`${eventsDetail
?.responseData?.rows[0]?
.table_count
} Bàn : ${eventsDetail
?.responseData?.rows[0]?
.table_cost.toLocaleString()} đ`
:
"Vui lòng xem chi tiết trong bài"
}
</
div
>
</
div
>
...
...
@@ -110,7 +110,7 @@ export default function EventDetailPage() {
{
/* Full description */
}
<
div
className=
"p-7.5 prose tiptap overflow-hidden"
>
{
parse
(
eventsDetail
?.
responseData
?.
rows
[
0
].
description
??
""
)
}
{
parse
(
eventsDetail
?.
responseData
?.
rows
[
0
]
?
.
description
??
""
)
}
</
div
>
</
main
>
...
...
@@ -118,12 +118,12 @@ export default function EventDetailPage() {
<
aside
className=
"space-y-6"
>
<
EventCalendar
/>
<
div
className=
"bg-white border rounded-md overflow-hidden"
>
<
div
className=
"w-full h-
56
relative bg-gray-100"
>
<
div
className=
"w-full h-
75
relative bg-gray-100"
>
<
Image
src=
"/banner.webp"
alt=
"Quảng cáo"
fill
className=
"object-co
ver
"
className=
"object-co
ntain
"
/>
</
div
>
</
div
>
...
...
@@ -152,7 +152,7 @@ function EventImage({ src, alt }: EventImageProps) {
className=
"object-cover"
onError=
{
()
=>
{
// swap to local fallback file when Next/Image fails to load the provided URL
if
(
imgSrc
!==
"/
VCCI-Chung-300x200-1.png"
)
setImgSrc
(
"/VCCI-Chung-300x200-1
.png"
);
if
(
imgSrc
!==
"/
img-error.png"
)
setImgSrc
(
"/img-error
.png"
);
}
}
/>
);
...
...
src/app/(main)/[...slug]/templates/EventPage.tsx
View file @
60672bc5
...
...
@@ -50,7 +50,7 @@ export default function EventPage() {
<
div
className=
"grid grid-cols-1 lg:grid-cols-3 gap-6"
>
<
main
className=
"lg:col-span-2 bg-background"
>
<
div
className=
"pb-5 overflow-hidden"
>
{
events
?.
responseData
.
rows
.
map
((
item
)
=>
(
{
events
?.
responseData
?.
rows
?
.
map
((
item
)
=>
(
<
CardEvents
key=
{
item
.
id
}
event=
{
item
}
...
...
@@ -59,12 +59,12 @@ export default function EventPage() {
))
}
<
div
className=
"w-full flex justify-center mt-4"
>
<
Pagination
pageCount=
{
Number
(
events
?.
responseData
.
totalPages
??
1
)
}
page=
{
Number
(
events
?.
responseData
.
currentPage
??
page
)
}
pageCount=
{
Number
(
events
?.
responseData
?
.
totalPages
??
1
)
}
page=
{
Number
(
events
?.
responseData
?
.
currentPage
??
page
)
}
onChangePage=
{
setPage
}
onGoToPreviousPage=
{
()
=>
setPage
(
Math
.
max
(
1
,
page
-
1
))
}
onGoToNextPage=
{
()
=>
setPage
(
Math
.
min
(
Number
(
events
?.
responseData
.
totalPages
??
1
),
page
+
1
))
setPage
(
Math
.
min
(
Number
(
events
?.
responseData
?
.
totalPages
??
1
),
page
+
1
))
}
/>
</
div
>
...
...
src/app/(main)/[...slug]/templates/InformationPage.tsx
View file @
60672bc5
...
...
@@ -37,7 +37,7 @@ export default function InformationPage() {
<
ListCategory
categories=
{
category
?.
responseData
?.
children
}
/>
<
main
className=
" bg-white border rounded-md py-10 px-30"
>
<
div
className=
'text-primary text-2xl leading-normal font-bold'
>
{
data
?.
responseData
?.
rows
[
0
].
title
}
{
data
?.
responseData
?.
rows
[
0
]
?
.
title
}
</
div
>
{
/* <div className='flex items-center gap-2 text-sm mb-4'>
<span className='text-base text-blue-700'>
...
...
@@ -47,7 +47,7 @@ export default function InformationPage() {
<
hr
className=
"my-5"
/>
<
div
className=
'flex-1 text-app-grey text-base overflow-hidden'
>
<
div
className=
"prose tiptap overflow-hidden"
>
{
parse
(
data
?.
responseData
?.
rows
[
0
].
description
??
''
)
}
{
parse
(
data
?.
responseData
?.
rows
[
0
]
?
.
description
??
''
)
}
</
div
>
</
div
>
</
main
>
...
...
src/components/base/card-news/CardNews.type.ts
deleted
100644 → 0
View file @
21c709a6
export
interface
NewsDetailItem
{
id
:
string
title
:
string
thumbnail
:
string
external_link
:
string
description
:
string
release_at
:
string
is_active
:
boolean
created_at
:
string
created_by
:
string
|
null
updated_at
:
string
updated_by
:
string
|
null
mode
:
'NOW'
|
string
category
:
string
}
export
interface
NewsDetailResponseData
{
count
:
number
rows
:
NewsDetailItem
[]
totalPages
:
number
currentPage
:
number
}
export
interface
GetNewsDetailResponseType
{
message
:
string
message_en
:
string
responseData
:
NewsDetailItem
status
:
'success'
|
'error'
timeStamp
:
string
violations
:
any
|
null
}
\ No newline at end of file
src/components/base/card-news/index.tsx
View file @
60672bc5
import
{
News
DetailItem
}
from
'./CardNews.type
'
;
import
{
News
Item
}
from
'@/api/types/news
'
;
import
Links
from
'@links/index'
import
dayjs
from
'dayjs'
;
...
...
@@ -20,7 +20,7 @@ const stripImagesAndHtml = (html?: string) => {
return
withoutImgs
.
replace
(
/<
[^
>
]
*>/g
,
''
)
}
const
CardNews
=
({
news
,
link
}:
{
news
:
News
Detail
Item
,
link
:
string
})
=>
{
const
CardNews
=
({
news
,
link
}:
{
news
:
NewsItem
,
link
:
string
})
=>
{
return
(
<
a
href=
{
`${link}`
}
...
...
src/components/base/menu-item/index.tsx
View file @
60672bc5
import
{
usePathname
}
from
"next/navigation"
;
import
Link
from
"next/link"
;
type
MenuItemProps
=
{
...
...
@@ -7,26 +8,35 @@ type MenuItemProps = {
};
const
MenuItem
=
({
title
,
link
,
items
}:
MenuItemProps
)
=>
{
const
pathname
=
usePathname
();
const
isActive
=
!!
link
&&
(
pathname
===
link
||
(
link
!==
"/"
&&
pathname
.
startsWith
(
link
)));
return
(
<
div
className=
"group relative"
>
<
Link
href=
{
`${link || ""}`
}
className=
"px-3 py-5 text-[16px] font-semibold text-[#124588] hover:text-[#E8C518] transition block"
href=
{
link
??
"#"
}
className=
{
`px-3 py-5 text-[16px] font-semibold transition block
${isActive ? "text-[#E8C518]" : "text-[#124588] hover:text-[#E8C518]"}
`
}
>
{
title
}
</
Link
>
{
/* Dropdown */
}
<
div
className=
"absolute left-0 top-full hidden group-hover:block bg-[#124588]/98 text-white text-[14px] font-medium min-w-[220px] shadow-lg"
>
{
items
.
map
((
item
,
i
)
=>
(
<
Link
key=
{
i
}
href=
{
`${item.link}`
}
className=
"block px-5 py-3 hover:bg-[#e8c518]/80 cursor-pointer whitespace-nowrap transition"
>
{
item
.
title
}
</
Link
>
))
}
{
items
.
map
((
item
,
i
)
=>
{
const
isItemActive
=
pathname
===
item
.
link
;
return
(
<
Link
key=
{
i
}
href=
{
item
.
link
}
className=
{
`block px-5 py-3 cursor-pointer whitespace-nowrap transition ${isItemActive ? "bg-[#e8c518]/80" : "hover:bg-[#e8c518]/80"
}`
}
>
{
item
.
title
}
</
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