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
c3277c9a
Commit
c3277c9a
authored
Sep 07, 2026
by
Phạm Quang Bảo
Browse files
Options
Browse Files
Download
Plain Diff
[tag]0.1-vcci
parents
f64d2172
3102cf75
Pipeline
#53005
passed with stages
in 5 minutes and 11 seconds
Changes
16
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
73 additions
and
64 deletions
+73
-64
news.ts
src/api/vcci-news/types/news.ts
+0
-1
use-home-posts.ts
src/app/(main)/(home)/lib/use-home-posts.ts
+3
-3
page.tsx
src/app/(main)/[...slug]/page.tsx
+2
-2
ArticlePage.tsx
src/app/(main)/[...slug]/templates/ArticlePage.tsx
+1
-1
CatalogPage.tsx
src/app/(main)/[...slug]/templates/CatalogPage.tsx
+1
-1
StructuredPostContent.tsx
src/app/(main)/[...slug]/templates/StructuredPostContent.tsx
+5
-0
data.ts
src/app/(main)/[...slug]/templates/data.ts
+10
-18
AboutVcciHcmPage.tsx
......slug]/templates/information-pages/AboutVcciHcmPage.tsx
+2
-2
MemberRegistrationPage.tsx
...g]/templates/information-pages/MemberRegistrationPage.tsx
+1
-1
Router.tsx
.../templates/information-pages/legal-trade-pages/Router.tsx
+26
-22
types.ts
src/app/(main)/[...slug]/templates/types.ts
+1
-1
page.tsx
src/app/(main)/search/page.tsx
+1
-1
post-history-viewer.tsx
src/app/admin/news/[id]/_components/post-history-viewer.tsx
+0
-1
footer.tsx
src/components/layout/main/footer.tsx
+20
-6
cms-admin.ts
src/lib/api/cms-admin.ts
+0
-3
news-detail-response-data.ts
src/lib/types/news-detail-response-data.ts
+0
-1
No files found.
src/api/vcci-news/types/news.ts
View file @
c3277c9a
...
@@ -2,7 +2,6 @@ export interface NewsItem {
...
@@ -2,7 +2,6 @@ export interface NewsItem {
id
:
string
id
:
string
title
:
string
title
:
string
thumbnail
:
string
thumbnail
:
string
external_link
:
string
description
:
string
description
:
string
release_at
:
string
release_at
:
string
is_active
:
boolean
is_active
:
boolean
...
...
src/app/(main)/(home)/lib/use-home-posts.ts
View file @
c3277c9a
...
@@ -23,7 +23,7 @@ type RawHomeThumbnail = {
...
@@ -23,7 +23,7 @@ type RawHomeThumbnail = {
type
RawHomePost
=
{
type
RawHomePost
=
{
id
?:
string
|
null
;
id
?:
string
|
null
;
title
?:
string
|
null
;
title
?:
string
|
null
;
external_link
?:
string
|
null
;
slug
?:
string
|
null
;
summary
?:
string
|
null
;
summary
?:
string
|
null
;
content
?:
string
|
null
;
content
?:
string
|
null
;
release_at
?:
string
|
null
;
release_at
?:
string
|
null
;
...
@@ -400,7 +400,7 @@ async function fetchHomePostsFromApi() {
...
@@ -400,7 +400,7 @@ async function fetchHomePostsFromApi() {
const
thumbnailPath
=
item
.
thumbnail
?.
path
??
item
.
thumbnail
?.
original
??
null
;
const
thumbnailPath
=
item
.
thumbnail
?.
path
??
item
.
thumbnail
?.
original
??
null
;
const
title
=
String
(
item
.
title
??
""
).
trim
();
const
title
=
String
(
item
.
title
??
""
).
trim
();
const
externalLink
=
buildPostLink
(
const
externalLink
=
buildPostLink
(
item
.
external_link
||
(
title
?
`/
${
title
}
`
:
undefined
),
item
.
slug
?
`/
${
item
.
slug
}
`
:
(
title
?
`/
${
title
}
`
:
undefined
),
item
.
id
?
String
(
item
.
id
)
:
""
,
item
.
id
?
String
(
item
.
id
)
:
""
,
"#"
,
"#"
,
);
);
...
@@ -626,7 +626,7 @@ export function useEventCalendarPosts(currentMonth: Date) {
...
@@ -626,7 +626,7 @@ export function useEventCalendarPosts(currentMonth: Date) {
const
thumbnailPath
=
item
.
thumbnail
?.
path
??
item
.
thumbnail
?.
original
??
null
;
const
thumbnailPath
=
item
.
thumbnail
?.
path
??
item
.
thumbnail
?.
original
??
null
;
const
title
=
String
(
item
.
title
??
""
).
trim
();
const
title
=
String
(
item
.
title
??
""
).
trim
();
const
externalLink
=
buildPostLink
(
const
externalLink
=
buildPostLink
(
item
.
external_link
||
(
title
?
`/
${
title
}
`
:
undefined
),
item
.
slug
?
`/
${
item
.
slug
}
`
:
(
title
?
`/
${
title
}
`
:
undefined
),
item
.
id
?
String
(
item
.
id
)
:
""
,
item
.
id
?
String
(
item
.
id
)
:
""
,
"#"
,
"#"
,
);
);
...
...
src/app/(main)/[...slug]/page.tsx
View file @
c3277c9a
...
@@ -2,7 +2,7 @@ import type { Metadata } from "next";
...
@@ -2,7 +2,7 @@ import type { Metadata } from "next";
import
links
from
"@links/index"
;
import
links
from
"@links/index"
;
import
{
import
{
fetchDynamicPostById
,
fetchDynamicPostById
,
fetchDynamicPostBy
ExternalLink
,
fetchDynamicPostBy
Slug
,
getDynamicPostSeoImage
,
getDynamicPostSeoImage
,
getDynamicPostExcerpt
,
getDynamicPostExcerpt
,
stripHtml
,
stripHtml
,
...
@@ -66,7 +66,7 @@ export async function generateMetadata({
...
@@ -66,7 +66,7 @@ export async function generateMetadata({
try {
try {
post = postId
post = postId
? await fetchDynamicPostById(postId)
? await fetchDynamicPostById(postId)
: await fetchDynamicPostBy
ExternalLink
(path);
: await fetchDynamicPostBy
Slug
(path);
} catch {
} catch {
post = null;
post = null;
}
}
...
...
src/app/(main)/[...slug]/templates/ArticlePage.tsx
View file @
c3277c9a
...
@@ -151,7 +151,7 @@ export default function ArticlePage({ category, allCategories }: ArticlePageProp
...
@@ -151,7 +151,7 @@ export default function ArticlePage({ category, allCategories }: ArticlePageProp
className=
"border-b border-[#eceff3] pb-8 last:border-b-0"
className=
"border-b border-[#eceff3] pb-8 last:border-b-0"
>
>
<
Link
<
Link
href=
{
buildDynamicPostHref
(
item
.
external_link
,
item
.
id
,
category
.
id
)
}
href=
{
buildDynamicPostHref
(
item
.
slug
,
item
.
id
,
category
.
id
)
}
className=
"group grid items-center gap-5 sm:grid-cols-[250px_minmax(0,1fr)]"
className=
"group grid items-center gap-5 sm:grid-cols-[250px_minmax(0,1fr)]"
>
>
<
div
className=
"relative overflow-hidden rounded-md bg-[#edf1f5] aspect-[25/15] sm:aspect-[5/3]"
>
<
div
className=
"relative overflow-hidden rounded-md bg-[#edf1f5] aspect-[25/15] sm:aspect-[5/3]"
>
...
...
src/app/(main)/[...slug]/templates/CatalogPage.tsx
View file @
c3277c9a
...
@@ -103,7 +103,7 @@ export default function CatalogPage({ category, allCategories }: CatalogPageProp
...
@@ -103,7 +103,7 @@ export default function CatalogPage({ category, allCategories }: CatalogPageProp
return
(
return
(
<
Link
<
Link
key=
{
item
.
id
}
key=
{
item
.
id
}
href=
{
buildDynamicPostHref
(
item
.
external_link
,
item
.
id
,
category
.
id
)
}
href=
{
buildDynamicPostHref
(
item
.
slug
,
item
.
id
,
category
.
id
)
}
className=
"group block"
className=
"group block"
>
>
<
div
className=
"overflow-hidden bg-white shadow-[0_10px_24px_rgba(17,24,39,0.08)]"
>
<
div
className=
"overflow-hidden bg-white shadow-[0_10px_24px_rgba(17,24,39,0.08)]"
>
...
...
src/app/(main)/[...slug]/templates/StructuredPostContent.tsx
View file @
c3277c9a
...
@@ -39,6 +39,11 @@ function StructuredImageSection({ section }: { section: DynamicPostContentSectio
...
@@ -39,6 +39,11 @@ function StructuredImageSection({ section }: { section: DynamicPostContentSectio
height=
{
800
}
height=
{
800
}
className=
"h-auto w-full object-contain"
className=
"h-auto w-full object-contain"
/>
/>
{
item
.
caption
?
(
<
figcaption
className=
"mt-2 text-center text-sm text-gray-600"
>
{
item
.
caption
}
</
figcaption
>
)
:
null
}
</
figure
>
</
figure
>
);
);
})
}
})
}
...
...
src/app/(main)/[...slug]/templates/data.ts
View file @
c3277c9a
...
@@ -46,6 +46,7 @@ type RawPostUser = {
...
@@ -46,6 +46,7 @@ type RawPostUser = {
type
RawPostSectionImage
=
{
type
RawPostSectionImage
=
{
position
?:
number
|
null
;
position
?:
number
|
null
;
caption
?:
string
|
null
;
image
?:
{
image
?:
{
id
?:
string
|
null
;
id
?:
string
|
null
;
name
?:
string
|
null
;
name
?:
string
|
null
;
...
@@ -60,7 +61,6 @@ type RawPostItem = {
...
@@ -60,7 +61,6 @@ type RawPostItem = {
id
?:
string
|
null
;
id
?:
string
|
null
;
title
?:
string
|
null
;
title
?:
string
|
null
;
slug
?:
string
|
null
;
slug
?:
string
|
null
;
external_link
?:
string
|
null
;
content
?:
string
|
null
;
content
?:
string
|
null
;
summary
?:
string
|
null
;
summary
?:
string
|
null
;
release_at
?:
string
|
null
;
release_at
?:
string
|
null
;
...
@@ -126,11 +126,13 @@ const normalizePath = (value?: string | null) => {
...
@@ -126,11 +126,13 @@ const normalizePath = (value?: string | null) => {
};
};
export
const
buildDynamicPostHref
=
(
export
const
buildDynamicPostHref
=
(
path
?:
string
|
null
,
slug
?:
string
|
null
,
_id
?:
string
|
null
,
_id
?:
string
|
null
,
_categoryId
?:
string
|
null
,
_categoryId
?:
string
|
null
,
)
=>
{
)
=>
{
return
normalizePath
(
path
);
const
trimmed
=
(
slug
??
""
).
trim
();
if
(
!
trimmed
)
return
"#"
;
return
normalizePath
(
trimmed
);
};
};
const
getSlugFromPath
=
(
value
?:
string
|
null
)
=>
{
const
getSlugFromPath
=
(
value
?:
string
|
null
)
=>
{
...
@@ -188,6 +190,7 @@ const mapPostContentSections = (item: RawPostItem): DynamicPostContentSection[]
...
@@ -188,6 +190,7 @@ const mapPostContentSections = (item: RawPostItem): DynamicPostContentSection[]
typeof
item
?.
position
===
"number"
typeof
item
?.
position
===
"number"
?
item
.
position
?
item
.
position
:
imageIndex
+
1
,
:
imageIndex
+
1
,
caption
:
item
?.
caption
??
null
,
image
:
item
?.
image
image
:
item
?.
image
?
{
?
{
id
:
String
(
item
.
image
.
id
??
""
),
id
:
String
(
item
.
image
.
id
??
""
),
...
@@ -228,7 +231,6 @@ export const mapPost = (item: RawPostItem): DynamicPostItem => ({
...
@@ -228,7 +231,6 @@ export const mapPost = (item: RawPostItem): DynamicPostItem => ({
id
:
String
(
item
.
id
??
""
),
id
:
String
(
item
.
id
??
""
),
title
:
String
(
item
.
title
??
""
).
trim
(),
title
:
String
(
item
.
title
??
""
).
trim
(),
slug
:
String
(
item
.
slug
??
""
).
trim
(),
slug
:
String
(
item
.
slug
??
""
).
trim
(),
external_link
:
normalizePath
(
item
.
external_link
),
content
:
String
(
item
.
content
??
""
),
content
:
String
(
item
.
content
??
""
),
summary
:
String
(
item
.
summary
??
""
),
summary
:
String
(
item
.
summary
??
""
),
release_at
:
item
.
release_at
??
null
,
release_at
:
item
.
release_at
??
null
,
...
@@ -360,26 +362,16 @@ export async function fetchDynamicPostById(id: string) {
...
@@ -360,26 +362,16 @@ export async function fetchDynamicPostById(id: string) {
return
post
.
id
&&
post
.
title
?
post
:
null
;
return
post
.
id
&&
post
.
title
?
post
:
null
;
}
}
export
async
function
fetchDynamicPostBy
ExternalLink
(
path
:
string
)
{
export
async
function
fetchDynamicPostBy
Slug
(
path
:
string
)
{
const
normalizedPath
=
normalizePath
(
path
);
const
normalizedPath
=
normalizePath
(
path
);
const
slug
=
getSlugFromPath
(
normalizedPath
);
const
slug
=
getSlugFromPath
(
normalizedPath
);
if
(
slug
)
{
if
(
!
slug
)
return
null
;
const
slugResult
=
await
fetchDynamicPostList
({
page
:
1
,
pageSize
:
1
,
filters
:
buildVisibleNewsFilters
([
`slug==
${
slug
}
`
]),
});
if
(
slugResult
.
rows
[
0
])
{
return
slugResult
.
rows
[
0
];
}
}
const
result
=
await
fetchDynamicPostList
({
const
result
=
await
fetchDynamicPostList
({
page
:
1
,
page
:
1
,
pageSize
:
1
,
pageSize
:
1
,
filters
:
buildVisibleNewsFilters
([
`
external_link==
${
normalizedPath
}
`
]),
filters
:
buildVisibleNewsFilters
([
`
slug==
${
slug
}
`
]),
});
});
return
result
.
rows
[
0
]
??
null
;
return
result
.
rows
[
0
]
??
null
;
...
@@ -729,7 +721,7 @@ export function useDynamicPostDetail(postId: string, routePath: string, options:
...
@@ -729,7 +721,7 @@ export function useDynamicPostDetail(postId: string, routePath: string, options:
queryFn
:
()
=>
queryFn
:
()
=>
postId
postId
?
fetchDynamicPostById
(
postId
)
?
fetchDynamicPostById
(
postId
)
:
fetchDynamicPostBy
ExternalLink
(
routePath
),
:
fetchDynamicPostBy
Slug
(
routePath
),
enabled
:
options
.
enabled
!==
false
,
enabled
:
options
.
enabled
!==
false
,
staleTime
:
options
.
staleTime
??
60
*
1000
,
staleTime
:
options
.
staleTime
??
60
*
1000
,
});
});
...
...
src/app/(main)/[...slug]/templates/information-pages/AboutVcciHcmPage.tsx
View file @
c3277c9a
...
@@ -80,7 +80,7 @@ function renderSummary(summary?: string) {
...
@@ -80,7 +80,7 @@ function renderSummary(summary?: string) {
type
TinVcciApiRow
=
{
type
TinVcciApiRow
=
{
id
?:
string
|
null
;
id
?:
string
|
null
;
title
?:
string
|
null
;
title
?:
string
|
null
;
external_link
?:
string
|
null
;
slug
?:
string
|
null
;
published_at
?:
string
|
null
;
published_at
?:
string
|
null
;
release_at
?:
string
|
null
;
release_at
?:
string
|
null
;
created_at
?:
string
|
null
;
created_at
?:
string
|
null
;
...
@@ -119,7 +119,7 @@ export default function AboutVcciHcmPage({
...
@@ -119,7 +119,7 @@ export default function AboutVcciHcmPage({
((
response
?.
responseData
?.
rows
??
[])
as
unknown
as
TinVcciApiRow
[]).
map
((
item
)
=>
({
((
response
?.
responseData
?.
rows
??
[])
as
unknown
as
TinVcciApiRow
[]).
map
((
item
)
=>
({
id
:
String
(
item
.
id
??
""
),
id
:
String
(
item
.
id
??
""
),
title
:
String
(
item
.
title
??
""
).
trim
(),
title
:
String
(
item
.
title
??
""
).
trim
(),
externalLink
:
buildDynamicPostHref
(
item
.
external_link
?.
trim
()
||
"#"
,
item
.
id
?
String
(
item
.
id
)
:
""
),
externalLink
:
buildDynamicPostHref
(
item
.
slug
?.
trim
()
||
"#"
,
item
.
id
?
String
(
item
.
id
)
:
""
),
publishedAt
:
String
(
item
.
published_at
??
item
.
release_at
??
item
.
created_at
??
""
),
publishedAt
:
String
(
item
.
published_at
??
item
.
release_at
??
item
.
created_at
??
""
),
thumbnailUrl
:
thumbnailUrl
:
links
.
resolveImageUrl
(
links
.
resolveImageUrl
(
...
...
src/app/(main)/[...slug]/templates/information-pages/MemberRegistrationPage.tsx
View file @
c3277c9a
...
@@ -115,7 +115,7 @@ export default function MemberRegistrationPage({ post }: MemberRegistrationPageP
...
@@ -115,7 +115,7 @@ export default function MemberRegistrationPage({ post }: MemberRegistrationPageP
<
div
className=
"flex justify-center pt-4"
>
<
div
className=
"flex justify-center pt-4"
>
<
a
<
a
href=
{
`
${links.externalApiOrigin}
/dang-ky`
}
href=
{
`
https://vccihcm.vn
/dang-ky`
}
target=
"_blank"
target=
"_blank"
rel=
"noreferrer"
rel=
"noreferrer"
className=
"inline-flex min-w-[220px] items-center justify-center rounded-[4px] bg-[#2450b5] px-6 py-4 text-[18px] font-semibold text-white transition-colors hover:bg-[#173f9f]"
className=
"inline-flex min-w-[220px] items-center justify-center rounded-[4px] bg-[#2450b5] px-6 py-4 text-[18px] font-semibold text-white transition-colors hover:bg-[#173f9f]"
...
...
src/app/(main)/[...slug]/templates/information-pages/legal-trade-pages/Router.tsx
View file @
c3277c9a
...
@@ -15,10 +15,13 @@ type LegalTradeRouterProps = {
...
@@ -15,10 +15,13 @@ type LegalTradeRouterProps = {
category
:
DynamicCategoryRouteItem
;
category
:
DynamicCategoryRouteItem
;
};
};
function
resolveVariant
(
post
:
DynamicPostItem
,
category
:
DynamicCategoryRouteItem
)
{
function
resolveVariant
(
const
url
=
category
.
url
||
post
.
external_link
;
post
:
DynamicPostItem
,
category
:
DynamicCategoryRouteItem
,
fullPath
:
string
,
)
{
const
url
=
category
.
url
||
fullPath
;
const
slug
=
category
.
slug
||
post
.
slug
;
const
slug
=
category
.
slug
||
post
.
slug
;
const
externalLink
=
post
.
external_link
;
if
(
if
(
slug
===
"phap-che"
||
slug
===
"phap-che"
||
...
@@ -51,7 +54,7 @@ function resolveVariant(post: DynamicPostItem, category: DynamicCategoryRouteIte
...
@@ -51,7 +54,7 @@ function resolveVariant(post: DynamicPostItem, category: DynamicCategoryRouteIte
if
(
if
(
slug
===
"bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm"
||
slug
===
"bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm"
||
externalLink
===
fullPath
===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm"
||
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm"
||
url
===
url
===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm"
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm"
...
@@ -62,7 +65,7 @@ function resolveVariant(post: DynamicPostItem, category: DynamicCategoryRouteIte
...
@@ -62,7 +65,7 @@ function resolveVariant(post: DynamicPostItem, category: DynamicCategoryRouteIte
if
(
if
(
slug
===
"phi-cap-gcn-va-xac-nhan-cttm"
||
slug
===
"phi-cap-gcn-va-xac-nhan-cttm"
||
slug
===
"phi-va-le-phi-cap-co"
||
slug
===
"phi-va-le-phi-cap-co"
||
externalLink
===
fullPath
===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/phi-cap-gcn-va-xac-nhan-cttm"
||
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/phi-cap-gcn-va-xac-nhan-cttm"
||
url
===
url
===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/phi-cap-gcn-va-xac-nhan-cttm"
||
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/phi-cap-gcn-va-xac-nhan-cttm"
||
...
@@ -75,9 +78,9 @@ function resolveVariant(post: DynamicPostItem, category: DynamicCategoryRouteIte
...
@@ -75,9 +78,9 @@ function resolveVariant(post: DynamicPostItem, category: DynamicCategoryRouteIte
slug
===
"diem-cap-va-cap-gcn-va-xac-nhan-cttm"
||
slug
===
"diem-cap-va-cap-gcn-va-xac-nhan-cttm"
||
slug
===
"diem-cap-va-thoi-gian-cap-co"
||
slug
===
"diem-cap-va-thoi-gian-cap-co"
||
slug
===
"diem-cap-va-thoi-gian-cap-gcn-va-xac-nhan-cttm"
||
slug
===
"diem-cap-va-thoi-gian-cap-gcn-va-xac-nhan-cttm"
||
externalLink
===
fullPath
===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/diem-cap-va-cap-gcn-va-xac-nhan-cttm"
||
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/diem-cap-va-cap-gcn-va-xac-nhan-cttm"
||
externalLink
===
fullPath
===
"/phap-che-va-xac-nhan-chung-tu-tm/diem-cap-va-thoi-gian-cap-gcn-va-xac-nhan-cttm"
||
"/phap-che-va-xac-nhan-chung-tu-tm/diem-cap-va-thoi-gian-cap-gcn-va-xac-nhan-cttm"
||
url
===
url
===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/diem-cap-va-cap-gcn-va-xac-nhan-cttm"
||
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/diem-cap-va-cap-gcn-va-xac-nhan-cttm"
||
...
@@ -91,7 +94,7 @@ function resolveVariant(post: DynamicPostItem, category: DynamicCategoryRouteIte
...
@@ -91,7 +94,7 @@ function resolveVariant(post: DynamicPostItem, category: DynamicCategoryRouteIte
if
(
if
(
slug
===
"thong-tin-lien-he"
||
slug
===
"thong-tin-lien-he"
||
slug
===
"thong-tin-lien-he-co"
||
slug
===
"thong-tin-lien-he-co"
||
externalLink
===
fullPath
===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/thong-tin-lien-he"
||
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/thong-tin-lien-he"
||
url
===
url
===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/thong-tin-lien-he"
||
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/thong-tin-lien-he"
||
...
@@ -107,17 +110,18 @@ export default function LegalTradePages({ post, category }: LegalTradeRouterProp
...
@@ -107,17 +110,18 @@ export default function LegalTradePages({ post, category }: LegalTradeRouterProp
const
params
=
useParams
();
const
params
=
useParams
();
const
pathSegments
=
Array
.
isArray
(
params
.
slug
)
?
params
.
slug
:
[
params
.
slug
];
const
pathSegments
=
Array
.
isArray
(
params
.
slug
)
?
params
.
slug
:
[
params
.
slug
];
const
currentSlug
=
pathSegments
.
at
(
-
1
)
??
""
;
const
currentSlug
=
pathSegments
.
at
(
-
1
)
??
""
;
const
fullPath
=
`/
${
pathSegments
.
filter
(
Boolean
).
join
(
"/"
)}
`
;
const
variant
=
resolveVariant
(
const
variant
=
resolveVariant
(
{
{
...
post
,
...
post
,
slug
:
currentSlug
||
post
.
slug
,
slug
:
currentSlug
||
post
.
slug
,
external_link
:
`/
${
pathSegments
.
filter
(
Boolean
).
join
(
"/"
)}
`
||
post
.
external_link
,
},
},
{
{
...
category
,
...
category
,
slug
:
currentSlug
||
category
.
slug
,
slug
:
currentSlug
||
category
.
slug
,
url
:
`/
${
pathSegments
.
filter
(
Boolean
).
join
(
"/"
)}
`
||
category
.
url
,
url
:
fullPath
||
category
.
url
,
},
},
fullPath
,
);
);
if
(
variant
===
"phap-che"
)
{
if
(
variant
===
"phap-che"
)
{
...
...
src/app/(main)/[...slug]/templates/types.ts
View file @
c3277c9a
...
@@ -49,6 +49,7 @@ export type DynamicPostContentSection = {
...
@@ -49,6 +49,7 @@ export type DynamicPostContentSection = {
image_columns
:
number
;
image_columns
:
number
;
images
:
Array
<
{
images
:
Array
<
{
position
:
number
;
position
:
number
;
caption
:
string
|
null
;
image
:
{
image
:
{
id
:
string
;
id
:
string
;
name
:
string
;
name
:
string
;
...
@@ -64,7 +65,6 @@ export type DynamicPostItem = {
...
@@ -64,7 +65,6 @@ export type DynamicPostItem = {
id
:
string
;
id
:
string
;
title
:
string
;
title
:
string
;
slug
:
string
;
slug
:
string
;
external_link
:
string
;
content
:
string
;
content
:
string
;
summary
:
string
;
summary
:
string
;
release_at
:
string
|
null
;
release_at
:
string
|
null
;
...
...
src/app/(main)/search/page.tsx
View file @
c3277c9a
...
@@ -50,7 +50,7 @@ function SearchResultItem({ item, index }: { item: DynamicPostItem; index: numbe
...
@@ -50,7 +50,7 @@ function SearchResultItem({ item, index }: { item: DynamicPostItem; index: numbe
return
(
return
(
<
article
className=
"border-b border-[#eceff3] pb-8 last:border-b-0"
>
<
article
className=
"border-b border-[#eceff3] pb-8 last:border-b-0"
>
<
Link
<
Link
href=
{
buildDynamicPostHref
(
item
.
external_link
,
item
.
id
)
}
href=
{
buildDynamicPostHref
(
item
.
slug
,
item
.
id
)
}
className=
"group grid gap-5 sm:grid-cols-[250px_minmax(0,1fr)]"
className=
"group grid gap-5 sm:grid-cols-[250px_minmax(0,1fr)]"
>
>
<
div
className=
"overflow-hidden rounded-md bg-[#edf1f5]"
>
<
div
className=
"overflow-hidden rounded-md bg-[#edf1f5]"
>
...
...
src/app/admin/news/[id]/_components/post-history-viewer.tsx
View file @
c3277c9a
...
@@ -52,7 +52,6 @@ function formatFieldName(field: string): string {
...
@@ -52,7 +52,6 @@ function formatFieldName(field: string): string {
slug
:
"Slug"
,
slug
:
"Slug"
,
published_at
:
"Ngày xuất bản"
,
published_at
:
"Ngày xuất bản"
,
expired_at
:
"Ngày hết hạn"
,
expired_at
:
"Ngày hết hạn"
,
external_link
:
"Liên kết ngoài"
,
};
};
return
fieldMap
[
field
]
||
field
;
return
fieldMap
[
field
]
||
field
;
}
}
...
...
src/components/layout/main/footer.tsx
View file @
c3277c9a
...
@@ -87,6 +87,7 @@ function Footer() {
...
@@ -87,6 +87,7 @@ function Footer() {
const
[
emailError
,
setEmailError
]
=
useState
(
""
);
const
[
emailError
,
setEmailError
]
=
useState
(
""
);
const
[
checkError
,
setCheckError
]
=
useState
(
false
);
const
[
checkError
,
setCheckError
]
=
useState
(
false
);
const
[
message
,
setMessage
]
=
useState
(
""
);
const
[
message
,
setMessage
]
=
useState
(
""
);
const
[
messageType
,
setMessageType
]
=
useState
<
"success"
|
"error"
>
(
"success"
);
const
[
submitting
,
setSubmitting
]
=
useState
(
false
);
const
[
submitting
,
setSubmitting
]
=
useState
(
false
);
const
{
data
:
siteInformationResponse
}
=
const
{
data
:
siteInformationResponse
}
=
...
@@ -156,6 +157,7 @@ function Footer() {
...
@@ -156,6 +157,7 @@ function Footer() {
let
hasError
=
false
;
let
hasError
=
false
;
setMessage
(
""
);
setMessage
(
""
);
setMessageType
(
"success"
);
if
(
!
trimmedEmail
)
{
if
(
!
trimmedEmail
)
{
setEmailError
(
"Thông tin bắt buộc"
);
setEmailError
(
"Thông tin bắt buộc"
);
...
@@ -182,13 +184,15 @@ function Footer() {
...
@@ -182,13 +184,15 @@ function Footer() {
await
postApiV10NewsletterSubscription
({
email
:
trimmedEmail
.
trim
()
});
await
postApiV10NewsletterSubscription
({
email
:
trimmedEmail
.
trim
()
});
setEmail
(
""
);
setEmail
(
""
);
setAccepted
(
false
);
setAccepted
(
false
);
setMessageType
(
"success"
);
setMessage
(
"Đăng ký nhận thông tin thành công."
);
setMessage
(
"Đăng ký nhận thông tin thành công."
);
}
catch
(
error
)
{
}
catch
(
error
)
{
setMessage
(
const
errorMessage
=
error
instanceof
Error
error
instanceof
Error
?
error
.
message
?
error
.
message
:
"Không thể đăng ký nhận thông tin."
,
:
"Không thể đăng ký nhận thông tin."
;
);
setMessageType
(
"error"
);
setMessage
(
errorMessage
);
}
finally
{
}
finally
{
setSubmitting
(
false
);
setSubmitting
(
false
);
}
}
...
@@ -251,7 +255,17 @@ function Footer() {
...
@@ -251,7 +255,17 @@ function Footer() {
)
:
null
}
)
:
null
}
{
message
?
(
{
message
?
(
<
p
className=
"mt-2 text-[12px] text-[#b8d8ff]"
>
{
message
}
</
p
>
<
div
className=
{
`mt-3 flex items-center gap-2 rounded-[6px] px-4 py-3 text-[13px] font-medium ${messageType === "success"
? "bg-[#1a8754] text-white"
: "bg-[#c0392b] text-white"
}`
}
>
<
span
className=
"text-base leading-none"
>
{
messageType
===
"success"
?
"✓"
:
"✕"
}
</
span
>
<
span
>
{
message
}
</
span
>
</
div
>
)
:
null
}
)
:
null
}
</
div
>
</
div
>
</
div
>
</
div
>
...
@@ -346,7 +360,7 @@ function Footer() {
...
@@ -346,7 +360,7 @@ function Footer() {
href=
"https://vcci-hcm.org.vn/"
href=
"https://vcci-hcm.org.vn/"
target=
"_blank"
target=
"_blank"
rel=
"noreferrer"
rel=
"noreferrer"
className=
"font-
semibold
text-white transition-colors hover:text-[#f7b500]"
className=
"font-
medium
text-white transition-colors hover:text-[#f7b500]"
>
>
VCCI-HCM
VCCI-HCM
</
a
>
</
a
>
...
@@ -355,7 +369,7 @@ function Footer() {
...
@@ -355,7 +369,7 @@ function Footer() {
href=
"https://meu.com.vn/"
href=
"https://meu.com.vn/"
target=
"_blank"
target=
"_blank"
rel=
"noreferrer"
rel=
"noreferrer"
className=
"font-
semibold
text-white transition-colors hover:text-[#f7b500]"
className=
"font-
medium
text-white transition-colors hover:text-[#f7b500]"
>
>
MEU Solutions
MEU Solutions
</
a
>
</
a
>
...
...
src/lib/api/cms-admin.ts
View file @
c3277c9a
...
@@ -171,7 +171,6 @@ interface CmsCategoryNode extends CmsCategoryItem {
...
@@ -171,7 +171,6 @@ interface CmsCategoryNode extends CmsCategoryItem {
interface
CmsRawPostItem
{
interface
CmsRawPostItem
{
id
?:
string
;
id
?:
string
;
title
?:
string
;
title
?:
string
;
external_link
?:
string
|
null
;
content
?:
string
|
null
;
content
?:
string
|
null
;
release_at
?:
string
|
null
;
release_at
?:
string
|
null
;
is_active
?:
boolean
|
null
;
is_active
?:
boolean
|
null
;
...
@@ -803,7 +802,6 @@ export async function createCmsNewsItem(input: {
...
@@ -803,7 +802,6 @@ export async function createCmsNewsItem(input: {
slug
:
input
.
slug
,
slug
:
input
.
slug
,
summary
:
input
.
summary
,
summary
:
input
.
summary
,
type
:
input
.
type
===
"baiviettrang"
?
"page"
:
"news"
,
type
:
input
.
type
===
"baiviettrang"
?
"page"
:
"news"
,
external_link
:
input
.
slug
?
`/
${
input
.
slug
}
`
:
"/"
,
content
:
input
.
summary
||
""
,
content
:
input
.
summary
||
""
,
category_ids
:
input
.
category_ids
,
category_ids
:
input
.
category_ids
,
thumbnail_id
:
input
.
thumbnail_id
??
null
,
thumbnail_id
:
input
.
thumbnail_id
??
null
,
...
@@ -864,7 +862,6 @@ export async function updateCmsNewsItem(
...
@@ -864,7 +862,6 @@ export async function updateCmsNewsItem(
slug
:
input
.
slug
,
slug
:
input
.
slug
,
summary
:
input
.
summary
,
summary
:
input
.
summary
,
type
:
input
.
type
===
"baiviettrang"
?
"page"
:
"news"
,
type
:
input
.
type
===
"baiviettrang"
?
"page"
:
"news"
,
external_link
:
input
.
slug
?
`/
${
input
.
slug
}
`
:
"/"
,
content
:
input
.
summary
||
""
,
content
:
input
.
summary
||
""
,
category_ids
:
input
.
category_ids
,
category_ids
:
input
.
category_ids
,
thumbnail_id
:
input
.
thumbnail_id
??
null
,
thumbnail_id
:
input
.
thumbnail_id
??
null
,
...
...
src/lib/types/news-detail-response-data.ts
View file @
c3277c9a
...
@@ -2,7 +2,6 @@ export interface NewsDetailItem {
...
@@ -2,7 +2,6 @@ export interface NewsDetailItem {
id
:
string
id
:
string
title
:
string
title
:
string
thumbnail
:
string
thumbnail
:
string
external_link
:
string
description
:
string
description
:
string
release_at
:
string
release_at
:
string
is_active
:
boolean
is_active
:
boolean
...
...
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