Commit 67165167 authored by Lê Bảo Hồng Đức's avatar Lê Bảo Hồng Đức

fix

parent e18f1e9a
'use client';
import dayjs from "dayjs";
import ListCategory from "@/components/base/list-category";
import { buildDynamicCategoryMenu } from "./data";
import StructuredPostContent from "./StructuredPostContent";
import type { DynamicCategoryRouteItem, DynamicPostItem } from "./types";
import {
ABOUT_VCCI_HCM_SLUG,
AboutVcciHcmPage,
DefaultInformationPage,
LEGAL_TRADE_PAGE_SLUG,
LegalTradePages,
MARKET_PROFILE_PAGE_SLUG,
MarketProfilePage,
MEMBER_REGISTRATION_PAGE_SLUG,
MEMBER_BENEFITS_PAGE_SLUG,
MemberRegistrationPage,
MemberBenefitsPage,
SERVICE_PAGE_SLUG,
ServicePage,
} from "./information-pages";
type InformationPageProps = {
post: DynamicPostItem;
......@@ -12,44 +25,118 @@ type InformationPageProps = {
allCategories: DynamicCategoryRouteItem[];
};
const LEGAL_TRADE_CATEGORY_ID = "69b4c7e7-28ea-41f2-97f4-988fe702a8a3";
const LEGAL_TRADE_CHILD_SLUGS = new Set([
"xuat-xu-hang-hoa-co",
"thu-tuc-cap-co",
"bieu-mau-co-va-cach-khai",
"phi-va-le-phi-cap-co",
"diem-cap-va-thoi-gian-cap-co",
"thong-tin-lien-he-co",
]);
function resolveInformationVariant(post: DynamicPostItem, category: DynamicCategoryRouteItem) {
if (
category.slug === ABOUT_VCCI_HCM_SLUG ||
post.slug === ABOUT_VCCI_HCM_SLUG ||
post.categories.some((item) => item.url === "/gioi-thieu/ve-vcci-hcm")
) {
return "about-vcci-hcm" as const;
}
if (
category.slug === SERVICE_PAGE_SLUG ||
post.slug === SERVICE_PAGE_SLUG ||
post.categories.some((item) => item.url === "/gioi-thieu/dich-vu-cung-cap")
) {
return "service" as const;
}
if (
category.slug === MEMBER_BENEFITS_PAGE_SLUG ||
post.slug === MEMBER_BENEFITS_PAGE_SLUG ||
post.categories.some((item) => item.url === "/hoi-vien/loi-ich-hoi-vien-vcci")
) {
return "member-benefits" as const;
}
if (
category.slug === MEMBER_REGISTRATION_PAGE_SLUG ||
post.slug === MEMBER_REGISTRATION_PAGE_SLUG ||
post.categories.some((item) => item.url === "/hoi-vien/dang-ky-hoi-vien")
) {
return "member-registration" as const;
}
if (
category.slug === MARKET_PROFILE_PAGE_SLUG ||
post.slug === MARKET_PROFILE_PAGE_SLUG ||
post.categories.some((item) => item.url === "/xuc-tien-thuong-mai/ho-so-thi-truong")
) {
return "market-profile" as const;
}
if (
category.slug === LEGAL_TRADE_PAGE_SLUG ||
category.parent_id === LEGAL_TRADE_CATEGORY_ID ||
LEGAL_TRADE_CHILD_SLUGS.has(category.slug) ||
post.slug === LEGAL_TRADE_PAGE_SLUG ||
LEGAL_TRADE_CHILD_SLUGS.has(post.slug) ||
post.categories.some((item) => item.id === LEGAL_TRADE_CATEGORY_ID) ||
post.categories.some(
(item) =>
item.url === "/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai" ||
item.url.startsWith("/xuat-xu-hang-hoa/"),
)
) {
return "legal-trade" as const;
}
return "default" as const;
}
function hasRenderablePostData(post: DynamicPostItem) {
if (post.content.trim()) return true;
const sections = post.content_structure?.post_content ?? [];
return sections.some((section) => section.content.trim() || section.images.length > 0);
}
export default function InformationPage({
post,
category,
allCategories,
}: InformationPageProps) {
const publishedDate = dayjs(
post.release_at ?? post.published_at ?? post.created_at,
).format("DD/MM/YYYY");
const categoryMenu = buildDynamicCategoryMenu(category, allCategories);
const variant = resolveInformationVariant(post, category);
const useSpecialUi =
variant === "about-vcci-hcm" ||
(variant !== "default" && !hasRenderablePostData(post));
return (
<div className="min-h-screen bg-white">
{categoryMenu.length ? <ListCategory categories={categoryMenu} /> : null}
<div className="container mx-auto px-4 py-4 lg:pb-6 sm:px-6 lg:px-10">
<div className="container mx-auto px-4 py-4 sm:px-6 lg:px-10 lg:pb-6">
<main className="w-full">
{/* <div className="mb-5 flex flex-wrap items-center gap-3 text-xs">
<span className="rounded-full bg-[#eaf0ff] px-2.5 py-1 font-semibold text-[#1f4fa3]">
{category.name}
</span>
<span className="text-[#9aa3ad]">{publishedDate}</span>
</div> */}
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
{post.title}
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
{post.summary ? (
<p className="mt-5 max-w-6xl text-base font-semibold leading-7 text-[#374151] md:text-lg md:leading-8">
{post.summary}
</p>
) : null}
<div className="mt-7 rounded-3xl bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8 lg:px-10">
<div className="page-detail-content prose tiptap max-w-none overflow-hidden">
<StructuredPostContent post={post} />
</div>
</div>
{useSpecialUi ? (
variant === "about-vcci-hcm" ? (
<AboutVcciHcmPage post={post} />
) : variant === "service" ? (
<ServicePage post={post} />
) : variant === "member-benefits" ? (
<MemberBenefitsPage />
) : variant === "member-registration" ? (
<MemberRegistrationPage post={post} />
) : variant === "market-profile" ? (
<MarketProfilePage post={post} />
) : variant === "legal-trade" ? (
<LegalTradePages post={post} category={category} />
) : (
<DefaultInformationPage post={post} />
)
) : (
<DefaultInformationPage post={post} />
)}
<div className="page-detail-styles">
<style jsx global>{`
......
......@@ -46,13 +46,37 @@ function StructuredImageSection({ section }: { section: DynamicPostContentSectio
);
}
function normalizeCaptionShortcodes(html: string) {
return html.replace(/\[caption[^\]]*]([\s\S]*?)\[\/caption]/gi, (_match, innerContent: string) => {
const normalizedInnerContent = innerContent.trim();
const imageMatch = normalizedInnerContent.match(/(<img[\s\S]*?>)([\s\S]*)/i);
if (!imageMatch) {
return normalizedInnerContent;
}
const imageHtml = imageMatch[1]?.trim() ?? "";
const captionText = imageMatch[2]?.trim() ?? "";
if (!captionText) {
return imageHtml;
}
return `<figure>${imageHtml}<figcaption>${captionText}</figcaption></figure>`;
});
}
function renderStructuredHtml(html: string) {
return parse(normalizeCaptionShortcodes(html));
}
export default function StructuredPostContent({ post }: StructuredPostContentProps) {
const sections = (post.content_structure?.post_content ?? [])
.slice()
.sort((left, right) => left.position - right.position);
if (!sections.length) {
return <>{parse(getDynamicPostBodyHtml(post))}</>;
return <>{renderStructuredHtml(getDynamicPostBodyHtml(post))}</>;
}
const hasRenderableSection = sections.some(
......@@ -60,7 +84,7 @@ export default function StructuredPostContent({ post }: StructuredPostContentPro
);
if (!hasRenderableSection) {
return <>{parse(getDynamicPostBodyHtml(post))}</>;
return <>{renderStructuredHtml(getDynamicPostBodyHtml(post))}</>;
}
return (
......@@ -73,7 +97,7 @@ export default function StructuredPostContent({ post }: StructuredPostContentPro
const content = section.content.trim();
if (!content) return null;
return <div key={section.id}>{parse(content)}</div>;
return <div key={section.id}>{renderStructuredHtml(content)}</div>;
})}
</>
);
......
'use client';
import dayjs from "dayjs";
import { useQuery } from "@tanstack/react-query";
import { Play, ShieldCheck, Target, Zap } from "lucide-react";
import Link from "next/link";
import { useCustomClient } from "@/api/mutator/custom-client";
import ImageNext from "@/components/shared/image-next";
import { fetchClientVideos } from "@/lib/api/videos";
import StructuredPostContent from "../StructuredPostContent";
import type { DynamicPostItem } from "../types";
const ABOUT_HIGHLIGHTS = [
{
key: "vision",
title: "Tầm nhìn",
description:
"Trở thành tổ chức hàng đầu đại diện cho cộng đồng doanh nghiệp tại phía Nam, kiến tạo môi trường kinh doanh thuận lợi và bền vững.",
icon: Target,
featured: false,
},
{
key: "mission",
title: "Sứ mệnh",
description:
"Nâng cao năng lực cạnh tranh của cộng đồng doanh nghiệp thông qua các hoạt động đối thoại, xúc tiến và xây dựng năng lực, tạo cầu nối vững chắc.",
icon: Zap,
featured: true,
},
{
key: "values",
title: "Giá trị cốt lõi",
bullets: ["Uy tín - Minh bạch", "Chuyên nghiệp", "Đổi mới sáng tạo", "Tinh thần cộng đồng"],
icon: ShieldCheck,
featured: false,
},
] as const;
const ACTIVITY_AREAS = [
"TP. Hồ Chí Minh",
"Bình Dương",
"Bình Phước",
"Đồng Nai",
"Lâm Đồng",
"Tây Ninh",
] as const;
const TIN_VCCI_CATEGORY_ID = "b89b2ba6-a699-47cb-87e4-0643aea549a9";
type TinVcciApiRow = {
id?: string | null;
title?: string | null;
external_link?: string | null;
published_at?: string | null;
release_at?: string | null;
created_at?: string | null;
thumbnail?: {
path?: string | null;
original?: string | null;
url?: string | null;
} | null;
};
type TinVcciApiEnvelope = {
responseData?: {
rows?: TinVcciApiRow[];
};
};
type AboutVcciHcmPageProps = {
post: DynamicPostItem;
};
export default function AboutVcciHcmPage({
post,
}: AboutVcciHcmPageProps) {
const videosQuery = useQuery({
queryKey: ["about-vcci-hcm-video"],
queryFn: () => fetchClientVideos({ page: 1, pageSize: 1 }),
staleTime: 60 * 1000,
});
const tinVcciQuery = useQuery({
queryKey: ["about-vcci-hcm-tin-vcci"],
queryFn: async () => {
const query = new URLSearchParams({
page: "1",
pageSize: "3",
sortField: "release_at",
sortOrder: "desc",
filters: [
`category.id==${TIN_VCCI_CATEGORY_ID}`,
"is_hidden==false",
"is_active==true",
"status==published",
"type==news",
].join(","),
});
const response = await useCustomClient<TinVcciApiEnvelope>(`/post?${query.toString()}`);
return (response.responseData?.rows ?? []).map((item) => ({
id: String(item.id ?? ""),
title: String(item.title ?? "").trim(),
externalLink: item.external_link?.trim() || "#",
publishedAt: String(item.published_at ?? item.release_at ?? item.created_at ?? ""),
thumbnailUrl:
item.thumbnail?.url?.trim() ||
item.thumbnail?.path?.trim() ||
item.thumbnail?.original?.trim() ||
"/thumbnail.png",
thumbnailAlt: String(item.title ?? "").trim() || "Tin VCCI",
}));
},
staleTime: 60 * 1000,
});
const introVideo = videosQuery.data?.rows[0] ?? null;
const tinVcciItems = tinVcciQuery.data ?? [];
return (
<>
<section className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_360px] lg:items-start">
<div className="min-w-0">
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
Giới thiệu <span className="text-[#2f57ff]">chung</span>
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
{post.summary ? (
<p className="mt-5 max-w-6xl text-base font-semibold leading-7 text-[#374151] md:text-lg md:leading-8">
{post.summary}
</p>
) : null}
<div className="mt-7 rounded-3xl bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8 lg:px-10">
<div className="page-detail-content prose tiptap max-w-none overflow-hidden">
<StructuredPostContent post={post} />
</div>
</div>
</div>
<aside className="rounded-[28px] border border-[#edf1f6] bg-[#fbfcff] px-6 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.05)] lg:sticky lg:top-24">
<h2 className="text-[30px] font-bold leading-tight text-[#1f2a44]">
Khu vực hoạt động
</h2>
<div className="mt-6 space-y-4">
{ACTIVITY_AREAS.map((item) => (
<div key={item} className="flex items-center gap-3 text-[18px] text-[#58667d]">
<span className="h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>{item}</span>
</div>
))}
</div>
</aside>
</section>
<section className="mt-10 space-y-10 md:mt-12 md:space-y-12">
<div>
<div className="text-center">
<h2 className="text-[30px] font-bold leading-tight text-[#1f2a44] md:text-[38px]">
Tầm nhìn, <span className="text-[#2f57ff]">Sứ mệnh</span> &{" "}
<span className="text-[#f0a400]">Giá trị</span>
</h2>
<div className="mx-auto mt-3 h-1 w-16 rounded-full bg-[#f5a400]" />
</div>
<div className="mt-8 grid gap-4 lg:grid-cols-3">
{ABOUT_HIGHLIGHTS.map((item) => {
const Icon = item.icon;
return (
<article
key={item.key}
className={[
"rounded-3xl border px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)]",
item.featured
? "border-[#1f56b8] bg-linear-to-br from-[#1d56b7] to-[#21467f] text-white"
: "border-[#edf1f6] bg-white text-[#24415f]",
].join(" ")}
>
<div
className={[
"flex h-11 w-11 items-center justify-center rounded-2xl",
item.featured ? "bg-white/10 text-[#ffbf2b]" : "bg-[#eff4ff] text-[#7ea1eb]",
].join(" ")}
>
<Icon className="h-5 w-5" />
</div>
<h3
className={[
"mt-5 text-[24px] font-bold",
item.featured ? "text-white" : "text-[#1d2e4f]",
].join(" ")}
>
{item.title}
</h3>
{"description" in item ? (
<p
className={[
"mt-3 text-[15px] leading-7",
item.featured ? "text-white/82" : "text-[#5f6f86]",
].join(" ")}
>
{item.description}
</p>
) : (
<ul className="mt-3 space-y-2.5 text-[15px] text-[#5f6f86]">
{item.bullets.map((bullet) => (
<li key={bullet} className="flex items-start gap-2.5">
<span className="mt-2 h-1.5 w-1.5 shrink-0 rounded-full bg-[#f5a400]" />
<span>{bullet}</span>
</li>
))}
</ul>
)}
</article>
);
})}
</div>
</div>
<div className="grid gap-6 lg:grid-cols-[minmax(0,0.8fr)_minmax(0,1.2fr)] lg:items-center">
<div className="space-y-5">
<div>
<h2 className="text-[28px] font-bold leading-tight text-[#1f2a44] md:text-[34px]">
Video về <span className="text-[#2f57ff]">VCCI-HCM</span>
</h2>
<div className="mt-3 h-1 w-16 rounded-full bg-[#f5a400]" />
</div>
<p className="max-w-xl text-[15px] leading-7 text-[#66758d]">
Khám phá hoạt động của Liên đoàn Thương mại và Công nghiệp Việt Nam - Chi nhánh TP. Hồ Chí Minh qua video giới thiệu chính thức.
</p>
<div className="grid max-w-md grid-cols-3 gap-3">
{[
{ value: "20+", label: "Năm hoạt động" },
{ value: "5000+", label: "Hội viên" },
{ value: "6", label: "Tỉnh thành" },
].map((stat) => (
<div
key={stat.label}
className="rounded-[18px] border border-[#edf1f6] bg-white px-4 py-3 text-center shadow-[0_12px_28px_rgba(17,24,39,0.04)]"
>
<div className="text-[28px] font-bold leading-none text-[#2450b5]">
{stat.value}
</div>
<div className="mt-2 text-[13px] text-[#6b7a91]">{stat.label}</div>
</div>
))}
</div>
</div>
<div className="overflow-hidden rounded-[28px] bg-[#dde6f5] shadow-[0_20px_44px_rgba(29,65,138,0.18)]">
{introVideo ? (
<a
href={introVideo.watchUrl}
target="_blank"
rel="noreferrer"
className="group relative block aspect-video"
>
<ImageNext
src={introVideo.thumbnail}
alt={introVideo.name}
width={1200}
height={675}
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-[1.03]"
/>
<div className="absolute inset-0 bg-linear-to-r from-[#183b78]/78 via-[#365f9d]/38 to-[#183b78]/24" />
<div className="absolute inset-0 flex items-center justify-center">
<span className="flex h-18 w-18 items-center justify-center rounded-full bg-white/90 text-[#24469c] shadow-[0_18px_38px_rgba(0,0,0,0.18)]">
<Play className="ml-1 h-8 w-8 fill-current" />
</span>
</div>
<div className="absolute bottom-4 left-4 rounded-full bg-[#1b2e4f]/72 px-3 py-1 text-xs font-medium text-white backdrop-blur-sm">
{introVideo.name}
</div>
</a>
) : (
<div className="flex aspect-video items-center justify-center bg-[#eef3fb] px-6 text-center text-[#6b7a91]">
Đang cập nhật video giới thiệu VCCI-HCM.
</div>
)}
</div>
</div>
<div>
<div className="mb-6 flex items-center justify-between gap-4">
<div>
<h2 className="text-[28px] font-bold leading-tight text-[#2450b5] md:text-[32px]">
TIN VCCI
</h2>
<div className="mt-3 h-1 w-16 rounded-full bg-[#f5a400]" />
</div>
<Link
href="/thong-tin-truyen-thong/tin-vcci"
className="text-sm font-semibold text-[#2450b5] transition-colors hover:text-[#173f9f]"
>
Xem tất cả
</Link>
</div>
<div className="grid gap-5 md:grid-cols-2 xl:grid-cols-3">
{tinVcciItems.map((item) => (
<Link
key={item.id}
href={item.externalLink}
className="group overflow-hidden rounded-[22px] bg-white shadow-[0_18px_38px_rgba(28,52,120,0.16)] transition-transform hover:-translate-y-1"
>
<div className="relative aspect-[1.28] overflow-hidden">
<ImageNext
src={item.thumbnailUrl}
alt={item.thumbnailAlt}
width={720}
height={520}
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-[1.04]"
/>
<div className="absolute inset-0 bg-linear-to-t from-[#1d2f56]/90 via-[#1d2f56]/28 to-transparent" />
<div className="absolute inset-x-0 bottom-0 p-4">
<span className="inline-flex rounded-[10px] bg-[#f5c21b] px-2.5 py-1 text-xs font-bold text-[#1d3f90]">
Tin VCCI
</span>
<h3 className="mt-3 line-clamp-2 text-[17px] font-bold leading-6 text-white">
{item.title}
</h3>
<p className="mt-2 text-sm text-white/78">
{dayjs(item.publishedAt).format("DD/MM/YYYY")}
</p>
</div>
</div>
</Link>
))}
</div>
</div>
</section>
</>
);
}
'use client';
import StructuredPostContent from "../StructuredPostContent";
import type { DynamicPostItem } from "../types";
type DefaultInformationPageProps = {
post: DynamicPostItem;
};
export default function DefaultInformationPage({
post,
}: DefaultInformationPageProps) {
return (
<section className="block">
<div className="min-w-0">
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
{post.title}
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
{post.summary ? (
<p className="mt-5 max-w-6xl text-base font-semibold leading-7 text-[#374151] md:text-lg md:leading-8">
{post.summary}
</p>
) : null}
<div className="mt-7 rounded-3xl bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8 lg:px-10">
<div className="page-detail-content prose tiptap max-w-none overflow-hidden">
<StructuredPostContent post={post} />
</div>
</div>
</div>
</section>
);
}
'use client';
import { useMemo, useState } from "react";
import { ArrowDownToLine, Globe2, MapPinned, Newspaper, TrendingUp } from "lucide-react";
import ImageNext from "@/components/shared/image-next";
import type { DynamicPostItem } from "../types";
type MarketProfilePageProps = {
post: DynamicPostItem;
};
type RegionMarketItem = {
name: string;
href: string;
tone: string;
};
type RegionConfig = {
key: string;
label: string;
title: string;
image: string;
imageAlt: string;
description: string;
markets: RegionMarketItem[];
featuredDocument?: {
title: string;
href: string;
description: string;
};
};
const REGION_CONFIGS: RegionConfig[] = [
{
key: "dong-nam-a",
label: "Đông Nam Á",
title: "Đông Nam Á",
image: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/Dong-Nam-A-scaled.jpg",
imageAlt: "Bản đồ thị trường Đông Nam Á",
description:
"Khu vực trọng điểm dành cho doanh nghiệp theo dõi cơ hội thương mại, xuất nhập khẩu, chuỗi cung ứng và kết nối đối tác trong ASEAN.",
markets: [
{
name: "Việt Nam",
href: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/VN-factsheet.pdf",
tone: "bg-[#da251d]",
},
{ name: "Lào", href: "#", tone: "bg-[#002868]" },
{ name: "Myanmar", href: "#", tone: "bg-[#34b233]" },
{ name: "Thái Lan", href: "#", tone: "bg-[#2d2a4a]" },
{ name: "Campuchia", href: "#", tone: "bg-[#032ea1]" },
{ name: "Malaysia", href: "#", tone: "bg-[#c00]" },
{
name: "Singapore",
href: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/SINGAPORE-2020.pdf",
tone: "bg-[#df0000]",
},
{ name: "Philippines", href: "#", tone: "bg-[#0038a8]" },
{ name: "Indonesia", href: "#", tone: "bg-[#e70011]" },
{ name: "Brunei", href: "#", tone: "bg-[#f7e017]" },
],
featuredDocument: {
title: "Factsheet Việt Nam",
href: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/VN-factsheet.pdf",
description: "Mở tài liệu tham khảo",
},
},
{
key: "dong-bac-a",
label: "Đông Bắc Á",
title: "Đông Bắc Á",
image: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/Dong-Bac-A-scaled.jpg",
imageAlt: "Khu vực Đông Bắc Á",
description:
"Nhóm thị trường phù hợp để doanh nghiệp tiếp cận chuỗi giá trị công nghiệp, công nghệ, logistics và thương mại khu vực Đông Bắc Á.",
markets: [
{ name: "Nhật Bản", href: "#", tone: "bg-[#d93f3f]" },
{ name: "Hàn Quốc", href: "#", tone: "bg-[#244f9e]" },
{ name: "Trung Quốc", href: "#", tone: "bg-[#de2910]" },
{ name: "Đài Loan", href: "#", tone: "bg-[#012169]" },
{ name: "Mông Cổ", href: "#", tone: "bg-[#c4272f]" },
],
},
{
key: "nam-a",
label: "Nam Á",
title: "Nam Á",
image: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/d60bf053ad586e063749-scaled.jpg",
imageAlt: "Khu vực Nam Á",
description:
"Không gian thị trường giàu tiềm năng với dân số lớn, tốc độ đô thị hóa nhanh và nhu cầu hợp tác thương mại đa ngành.",
markets: [
{ name: "Ấn Độ", href: "#", tone: "bg-[#ff9933]" },
{ name: "Bangladesh", href: "#", tone: "bg-[#006a4e]" },
{ name: "Pakistan", href: "#", tone: "bg-[#01411c]" },
{ name: "Sri Lanka", href: "#", tone: "bg-[#8d153a]" },
{ name: "Nepal", href: "#", tone: "bg-[#003893]" },
],
},
{
key: "tay-a",
label: "Tây Á",
title: "Tây Á",
image: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/33a2e0fdbdf67ea827e7-scaled.jpg",
imageAlt: "Khu vực Tây Á",
description:
"Thị trường phù hợp với định hướng mở rộng đối tác năng lượng, xây dựng, thương mại dịch vụ và kết nối trung chuyển.",
markets: [
{ name: "UAE", href: "#", tone: "bg-[#00732f]" },
{ name: "Ả Rập Xê Út", href: "#", tone: "bg-[#006c35]" },
{ name: "Qatar", href: "#", tone: "bg-[#8a1538]" },
{ name: "Kuwait", href: "#", tone: "bg-[#007a3d]" },
{ name: "Oman", href: "#", tone: "bg-[#db161b]" },
],
},
{
key: "bac-my",
label: "Bắc Mỹ",
title: "Bắc Mỹ",
image: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/Bac-My-1-scaled.jpg",
imageAlt: "Khu vực Bắc Mỹ",
description:
"Thị trường quy mô lớn, yêu cầu cao về tiêu chuẩn, truy xuất nguồn gốc và chiến lược tiếp cận bài bản.",
markets: [
{ name: "Hoa Kỳ", href: "#", tone: "bg-[#3c3b6e]" },
{ name: "Canada", href: "#", tone: "bg-[#d52b1e]" },
{ name: "Mexico", href: "#", tone: "bg-[#006847]" },
],
},
{
key: "nam-my",
label: "Nam Mỹ",
title: "Nam Mỹ",
image: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/Nam-My-1-scaled.jpg",
imageAlt: "Khu vực Nam Mỹ",
description:
"Nhóm thị trường phù hợp để theo dõi nhu cầu hàng tiêu dùng, nông sản, logistics biển và liên kết chuỗi cung ứng mới.",
markets: [
{ name: "Brazil", href: "#", tone: "bg-[#009b3a]" },
{ name: "Argentina", href: "#", tone: "bg-[#74acdf]" },
{ name: "Chile", href: "#", tone: "bg-[#0039a6]" },
{ name: "Peru", href: "#", tone: "bg-[#d91023]" },
],
},
{
key: "chau-au",
label: "Châu Âu",
title: "Châu Âu",
image: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/Chau-Au-scaled.jpg",
imageAlt: "Khu vực Châu Âu",
description:
"Khu vực trọng tâm cho doanh nghiệp quan tâm đến EVFTA, tiêu chuẩn xanh, phát triển bền vững và thị trường giá trị cao.",
markets: [
{ name: "Đức", href: "#", tone: "bg-[#000000]" },
{ name: "Pháp", href: "#", tone: "bg-[#0055a4]" },
{ name: "Hà Lan", href: "#", tone: "bg-[#ae1c28]" },
{ name: "Ý", href: "#", tone: "bg-[#009246]" },
{ name: "Tây Ban Nha", href: "#", tone: "bg-[#aa151b]" },
],
},
{
key: "chau-uc",
label: "Châu Úc",
title: "Châu Úc",
image: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/Chau-Uc-scaled.jpg",
imageAlt: "Khu vực Châu Úc",
description:
"Phù hợp với chiến lược tìm hiểu nhu cầu nhập khẩu ổn định, tiêu chuẩn chất lượng cao và hợp tác thương mại dài hạn.",
markets: [
{ name: "Úc", href: "#", tone: "bg-[#012169]" },
{ name: "New Zealand", href: "#", tone: "bg-[#00247d]" },
{ name: "Papua New Guinea", href: "#", tone: "bg-[#ce1126]" },
],
},
{
key: "chau-phi",
label: "Châu Phi",
title: "Châu Phi",
image: "https://vcci-hcm.org.vn/wp-content/uploads/2022/06/Chau-Phi-1-scaled.jpg",
imageAlt: "Khu vực Châu Phi",
description:
"Khu vực giàu dư địa tiếp cận thị trường mới cho hàng tiêu dùng, nông sản, vật liệu và hợp tác thương mại song phương.",
markets: [
{ name: "Nam Phi", href: "#", tone: "bg-[#007749]" },
{ name: "Ai Cập", href: "#", tone: "bg-[#ce1126]" },
{ name: "Nigeria", href: "#", tone: "bg-[#008751]" },
{ name: "Kenya", href: "#", tone: "bg-[#000000]" },
],
},
];
const OVERVIEW_ITEMS = [
{
title: "Bản tin thị trường",
description:
"Tổng hợp nhanh các đầu mối thông tin phục vụ doanh nghiệp theo dõi diễn biến thương mại và nhu cầu thị trường.",
icon: Newspaper,
},
{
title: "Cơ hội xuất nhập khẩu",
description:
"Ưu tiên các nhóm thị trường giàu tiềm năng để doanh nghiệp tra cứu nhanh theo khu vực và theo từng nước.",
icon: TrendingUp,
},
{
title: "Kết nối khu vực",
description:
"Gợi ý nhóm thị trường theo khu vực để doanh nghiệp thuận tiện định hướng khảo sát và mở rộng đối tác.",
icon: Globe2,
},
] as const;
export default function MarketProfilePage({ post }: MarketProfilePageProps) {
const [activeRegionKey, setActiveRegionKey] = useState("dong-nam-a");
const activeRegion = useMemo(
() =>
REGION_CONFIGS.find((item) => item.key === activeRegionKey) ?? REGION_CONFIGS[0],
[activeRegionKey],
);
return (
<section className="space-y-8">
<div className="grid gap-8 xl:grid-cols-[minmax(0,1fr)_300px] xl:items-start">
<div className="min-w-0">
<h1 className="text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
{activeRegion.title}
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
<p className="mt-5 max-w-4xl text-base leading-8 text-[#5b6880] md:text-[17px]">
{post.summary?.trim() || activeRegion.description}
</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="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
key={`${activeRegion.key}-${item.name}`}
href={item.href}
target={item.href.startsWith("http") ? "_blank" : undefined}
rel={item.href.startsWith("http") ? "noreferrer" : undefined}
className="inline-flex items-center gap-2 rounded-full border border-white/80 bg-white/92 px-3 py-2 text-xs font-semibold text-[#1e3768] shadow-[0_10px_24px_rgba(36,80,181,0.12)] transition-colors hover:bg-[#f8fbff]"
>
<span className={`h-2.5 w-2.5 rounded-full ${item.tone}`} />
<span>{item.name}</span>
</a>
))}
</div>
<ImageNext
src={activeRegion.image}
alt={activeRegion.imageAlt}
width={1200}
height={900}
className="h-full min-h-[320px] w-full rounded-[24px] object-cover 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>
<aside className="rounded-[28px] border border-[#e6eefb] bg-[#fbfcff] p-6 shadow-[0_18px_42px_rgba(17,24,39,0.05)] xl:sticky xl:top-24">
<h2 className="text-[28px] font-bold leading-tight text-[#1f2a44]">Khu vực</h2>
<div className="mt-5 space-y-2">
{REGION_CONFIGS.map((item) => {
const isActive = item.key === activeRegion.key;
return (
<button
key={item.key}
type="button"
onClick={() => setActiveRegionKey(item.key)}
className={[
"flex w-full items-center rounded-[18px] px-4 py-3 text-left text-[15px] font-medium transition-all duration-200",
isActive
? "bg-[#2450b5] text-white shadow-[0_14px_28px_rgba(36,80,181,0.22)]"
: "bg-[#f4f7fc] text-[#55657d] hover:bg-[#eaf1ff] hover:text-[#2450b5]",
].join(" ")}
>
{item.label}
</button>
);
})}
</div>
</aside>
</div>
<div className="grid gap-5 lg:grid-cols-3">
{OVERVIEW_ITEMS.map((item) => {
const Icon = item.icon;
return (
<article
key={item.title}
className="rounded-[26px] border border-[#e5edf8] bg-white px-5 py-6 shadow-[0_16px_36px_rgba(17,24,39,0.05)]"
>
<div className="flex h-11 w-11 items-center justify-center rounded-2xl bg-[#edf4ff] text-[#2450b5]">
<Icon className="h-5 w-5" />
</div>
<h3 className="mt-4 text-[20px] font-bold leading-7 text-[#1e2f50]">{item.title}</h3>
<p className="mt-3 text-[15px] leading-7 text-[#617089]">{item.description}</p>
</article>
);
})}
</div>
</section>
);
}
'use client';
import {
BadgeCheck,
Bell,
Globe2,
Mail,
MapPin,
MessageCircleMore,
Phone,
ShieldCheck,
TrendingUp,
WalletCards,
} from "lucide-react";
const MEMBER_BENEFITS = [
{
key: "voice",
title: "Tiếng nói",
icon: MessageCircleMore,
iconClassName: "bg-[#f59e0b]",
bullets: [
"Được hỗ trợ giải quyết các vướng mắc, kiến nghị của doanh nghiệp với các cơ quan quản lý trong quá trình kinh doanh và thực thi pháp luật.",
"Được tham dự miễn phí các hội nghị, hội thảo, đối thoại với các cơ quan ban ngành về pháp luật và chính sách hàng năm.",
"Được tham dự hội nghị đối thoại thường niên về chính sách thuế, hải quan và thủ tục hành chính.",
],
},
{
key: "recognition",
title: "Độ nhận diện",
icon: BadgeCheck,
iconClassName: "bg-[#1f2937]",
bullets: [
"Hồ sơ doanh nghiệp được đăng tải miễn phí trên Danh bạ Hội viên CONNECTIONS.",
"Thông tin doanh nghiệp được giới thiệu miễn phí trên website và các kênh truyền thông của VCCI-HCM.",
"Cơ hội trở thành nhà tài trợ cho các sự kiện của VCCI-HCM.",
"Được ưu đãi đặc biệt khi sử dụng các dịch vụ truyền thông, quảng bá thương hiệu của VCCI-HCM.",
],
},
{
key: "network",
title: "Mạng lưới liên kết",
icon: Globe2,
iconClassName: "bg-[#10b981]",
bullets: [
"Được tham dự miễn phí các sự kiện xúc tiến thương mại và đầu tư hằng năm.",
"Được ưu đãi khi tham gia các đoàn khảo sát thị trường nước ngoài do VCCI-HCM tổ chức.",
"Tương tác trong mạng lưới hội viên VCCI-HCM, tiếp cận các đối tác tin cậy và khách hàng tiềm năng.",
],
},
{
key: "growth",
title: "Phát triển",
icon: TrendingUp,
iconClassName: "bg-[#3b82f6]",
bullets: [
"Được tham gia các khóa đào tạo của VCCI-HCM với chi phí ưu đãi.",
"Được tiếp cận các dự án hỗ trợ doanh nghiệp phát triển được tài trợ bởi các tổ chức trong nước và quốc tế.",
"Được tư vấn bởi các chuyên gia về pháp luật, quan hệ lao động, thị trường,... với chi phí ưu đãi.",
],
},
{
key: "trust",
title: "Độ tin cậy",
icon: ShieldCheck,
iconClassName: "bg-[#9333ea]",
bullets: [
"Tăng uy tín và độ tin cậy cho doanh nghiệp khi trở thành hội viên VCCI-HCM.",
"Tạo thuận lợi cho doanh nghiệp trong các hoạt động hợp tác kinh doanh - đầu tư.",
],
},
{
key: "information",
title: "Thông tin",
icon: Bell,
iconClassName: "bg-[#ef4444]",
bullets: [
"Được nhận miễn phí Bản tin điện tử phát hành hằng tháng và Tạp chí VCCI-HCM phát hành hằng quý.",
"Được nhận miễn phí Danh bạ Hội viên VCCI-HCM.",
"Được nhận các sản phẩm thông tin phục vụ cho doanh nghiệp và các nhà đầu tư.",
],
},
] as const;
export default function MemberBenefitsPage() {
return (
<section className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_320px] lg:items-start">
<div>
<h1 className="text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
Lợi ích của hội viên VCCI
</h1>
<div className="mt-3 h-[3px] w-14 rounded-full bg-[#f5a400]" />
<div className="mt-7 space-y-7">
{MEMBER_BENEFITS.map((section) => {
const Icon = section.icon;
return (
<article key={section.key} className="flex items-start gap-4">
<div
className={`mt-1 flex h-11 w-11 shrink-0 items-center justify-center rounded-2xl text-white shadow-[0_12px_30px_rgba(17,24,39,0.12)] ${section.iconClassName}`}
>
<Icon className="h-5 w-5" />
</div>
<div className="min-w-0">
<h2 className="text-[30px] font-bold leading-tight text-[#1f2a44]">
{section.title}
</h2>
<ul className="mt-3 space-y-2.5">
{section.bullets.map((bullet) => (
<li
key={bullet}
className="flex items-start gap-3 text-[16px] leading-8 text-[#5f6f86]"
>
<span className="mt-3 h-2 w-2 shrink-0 rounded-full bg-[#f5a400]" />
<span>{bullet}</span>
</li>
))}
</ul>
</div>
</article>
);
})}
</div>
</div>
<aside className="rounded-[28px] bg-[#1c56a1] px-6 py-6 text-white shadow-[0_22px_46px_rgba(28,52,120,0.18)] lg:sticky lg:top-24">
<h2 className="text-[28px] font-bold leading-tight">Liên hệ</h2>
<div className="mt-6 space-y-5 text-[15px] leading-7 text-white/90">
<div>
<div className="flex items-center gap-2 text-[#f5c21b]">
<Phone className="h-4 w-4" />
<span className="font-semibold">Phòng Hội viên và Đào tạo</span>
</div>
<p className="mt-1">C. Thanh Thủy</p>
<p>ĐT: 0903 909 796</p>
</div>
<div>
<div className="flex items-center gap-2 text-[#f5c21b]">
<Mail className="h-4 w-4" />
<span className="font-semibold">Email</span>
</div>
<p className="mt-1 wrap-break-word">luuthanhthuy72@yahoo.com</p>
<p className="wrap-break-word">hoivien@vcci-hcm.org.vn</p>
</div>
<div>
<div className="flex items-center gap-2 text-[#f5c21b]">
<WalletCards className="h-4 w-4" />
<span className="font-semibold">Điện thoại</span>
</div>
<p className="mt-1">028. 3932 0817 - Fax: 028. 3932 5472</p>
</div>
<div>
<div className="flex items-center gap-2 text-[#f5c21b]">
<MapPin className="h-4 w-4" />
<span className="font-semibold">Địa chỉ</span>
</div>
<p className="mt-1">
P. 306, Lầu 3, Tòa nhà VCCI, 171 Võ Thị Sáu,
<br />
Quận 3, TP. Hồ Chí Minh
</p>
</div>
</div>
</aside>
</section>
);
}
'use client';
import type { DynamicPostItem } from "../types";
type MemberRegistrationPageProps = {
post: DynamicPostItem;
};
const MEMBERSHIP_REQUIREMENTS = [
"Đơn xin gia nhập làm hội viên chính thức VCCI (2 bản theo mẫu của VCCI)",
"Giấy phép đăng ký kinh doanh, hoặc giấy phép thành lập hoặc quyết định thành lập (2 bản sao)",
];
const MEMBERSHIP_FEES = [
"Doanh số dưới 10 tỉ đồng đóng 3 triệu đồng/năm",
"Doanh số từ 10 - 50 tỉ đồng đóng 7 triệu đồng/năm",
"Doanh số trên 50 tỉ đồng đóng 15 triệu đồng/năm",
];
const ATTACHED_FORMS = [
{
label: "Đơn đăng ký tham gia nhập hội viên VCCI (Mẫu Doanh nghiệp)",
href: "/Don-dang-ky-tham-gia-nhap-hoi-vien-VCCI_Mau-Doanh-nghiep-1.docx",
download: true,
},
{
label: "Đơn đăng ký tham gia nhập hội viên VCCI (Mẫu Hiệp hội)",
href: "/Don-dang-ky-tham-gia-nhap-hoi-vien-VCCI_Mau-Hiep-hoi.docx",
download: true,
},
{
label: "Hướng dẫn hồ sơ đăng ký Hội viên VCCI",
href: "https://vccihcm.vn/dang-ky",
download: false,
},
] as const;
export default function MemberRegistrationPage({ post }: MemberRegistrationPageProps) {
return (
<section className="">
<div className="min-w-0">
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
Đăng ký hội viên
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
<div className="mt-7 space-y-7 rounded-3xl bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8 lg:px-10">
<p className="text-justify text-[18px] leading-9 text-[#1f2a44]">
{post.content?.trim() ||
"Điều lệ sửa đổi của Liên đoàn Thương mại và Công nghiệp Việt Nam (VCCI) được Đại hội đại biểu toàn quốc VCCI lần thứ VII thông qua và được Thủ tướng Chính phủ phê duyệt tại Quyết định số 1496/QĐ-TTg ngày 30/11/2022 đã quy định tất cả các doanh nghiệp, các tổ chức sản xuất, kinh doanh, người sử dụng lao động, các hiệp hội doanh nghiệp có đăng ký và hoạt động hợp pháp ở Việt Nam đều có thể trở thành hội viên của VCCI."}
</p>
<p className="text-justify text-[18px] leading-9 text-[#1f2a44]">
Để trở thành hội viên chính thức, tổ chức quan tâm cần gửi VCCI tại Hà Nội hoặc các Chi nhánh, Văn phòng đại diện của VCCI hồ sơ gia nhập gồm:
</p>
<ul className="space-y-2 pl-6 text-[18px] leading-9 text-[#1f2a44]">
{MEMBERSHIP_REQUIREMENTS.map((item) => (
<li key={item} className="list-disc">
<strong>{item}</strong>
</li>
))}
</ul>
<p className="text-justify text-[18px] leading-9 text-[#1f2a44]">
Khi nhận được đơn, Ban Thường trực sẽ xét và thông báo cho tổ chức liên quan về quyết định kết nạp. Trong vòng 1 tháng kể từ ngày nhận thông báo, tổ chức phải thực hiện đóng lệ phí gia nhập. Chỉ khi nào tổ chức đóng lệ phí gia nhập mới được coi là hội viên chính thức. Theo quyết định của Ban chấp hành VCCI, lệ phí hiện hành được tính như sau:
</p>
<p className="text-justify text-[18px] leading-9 text-[#1f2a44]">
Mức lệ phí gia nhập bằng mức hội phí hàng năm, được tính căn cứ vào doanh số của tổ chức trong năm trước theo các mức:
</p>
<ul className="space-y-2 pl-6 text-[18px] leading-9 text-[#1f2a44]">
{MEMBERSHIP_FEES.map((item) => (
<li key={item} className="list-disc">
{item}
</li>
))}
</ul>
<p className="text-justify text-[18px] leading-9 text-[#1f2a44]">
Mức lệ phí gia nhập và hội phí trên có thể được điều chỉnh bởi quyết định của Ban chấp hành VCCI trong từng thời gian cụ thể.
</p>
<div>
<p className="font-semibold text-[#2450b5]">Để biết thêm thông tin chi tiết, vui lòng liên hệ:</p>
<div className="mt-4 space-y-1 text-[18px] leading-9 text-[#1f2a44]">
<p className="font-semibold">Phòng Hội viên Đào tạo và Truyền thông:</p>
<p>C. Thúy – ĐD: 0903 909 756</p>
<p>Email: luuthanhthuy72@yahoo.com; hoivien@vcci-hcm.org.vn;</p>
<p>Điện thoại: 028. 3932 0611 – Fax: 028. 3932 5472</p>
<p>Địa chỉ: P. 306, Lầu 3, Tòa nhà VCCI, 171 Võ Thị Sáu, Phường Xuân Hòa, TP. Hồ Chí Minh</p>
</div>
</div>
<div>
<p className="font-semibold text-[#1f2a44]">Biểu mẫu đính kèm:</p>
<ul className="mt-3 space-y-2 pl-6 text-[#2450b5]">
{ATTACHED_FORMS.map((item) => (
<li key={item.label} className="list-disc italic">
{item.download ? (
<a href={item.href} download className="hover:text-[#173f9f]">
{item.label}
</a>
) : (
<a href={item.href} target="_blank" rel="noreferrer" className="hover:text-[#173f9f]">
{item.label}
</a>
)}
</li>
))}
</ul>
</div>
<div className="flex justify-center pt-4">
<a
href="https://vccihcm.vn/dang-ky"
target="_blank"
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]"
>
Đăng ký Hội viên
</a>
</div>
</div>
</div>
</section>
);
}
'use client';
import {
BriefcaseBusiness,
CalendarDays,
FileBadge2,
GraduationCap,
Languages,
Megaphone,
Scale,
Search,
Store,
Ticket,
} from "lucide-react";
import type { DynamicPostItem } from "../types";
const SERVICE_SUPPORT_ITEMS = [
{
key: "events",
title: "Tổ chức sự kiện, hội nghị, hội thảo, giao lưu thương mại, hội chợ, triển lãm",
icon: CalendarDays,
},
{
key: "training",
title: "Đào tạo nâng cao năng lực quản trị doanh nghiệp",
icon: GraduationCap,
},
{
key: "market",
title: "Khảo sát thị trường nước ngoài",
icon: Search,
},
{
key: "venue",
title: "Cho thuê văn phòng, hội trường",
icon: Store,
},
{
key: "media",
title: "Quảng cáo, truyền thông",
icon: Megaphone,
},
{
key: "legal",
title: "Tư vấn về pháp lý, quan hệ lao động, môi trường kinh doanh",
icon: Scale,
},
{
key: "certificate",
title: "Cấp C/O và xác nhận các chứng từ thương mại",
icon: FileBadge2,
},
{
key: "business-info",
title: "Cung cấp thông tin thị trường và hồ sơ doanh nghiệp",
icon: BriefcaseBusiness,
},
{
key: "visa",
title: "Thu xếp visa nhập cảnh",
icon: Ticket,
},
{
key: "translate",
title: "Phiên biên dịch",
icon: Languages,
},
] as const;
type ServicePageProps = {
post: DynamicPostItem;
};
export default function ServicePage({ post }: ServicePageProps) {
const introText =
post.summary?.trim() ||
"VCCI-HCM cung cấp đa dạng các dịch vụ hỗ trợ doanh nghiệp phát triển và hội nhập kinh tế quốc tế.";
return (
<section className="grid gap-8 lg:grid-cols-[minmax(0,0.8fr)_minmax(0,1.2fr)] lg:items-start">
<div className="">
<h1 className="text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
Dịch vụ cung cấp
</h1>
<div className="mt-3 h-[3px] w-14 rounded-full bg-[#f5a400]" />
<p className="mt-5 max-w-[520px] text-[18px] leading-9 text-[#66758d]">
{introText}
</p>
</div>
<div className="overflow-hidden rounded-4xl border border-[#d9e3f2] bg-white shadow-[0_22px_46px_rgba(28,52,120,0.12)]">
<div className="bg-[#19519c] px-5 py-5 text-white md:px-6">
<div className="flex flex-wrap items-center justify-between gap-3">
<div>
<h2 className="text-[26px] font-bold leading-tight">Danh mục hỗ trợ</h2>
<p className="mt-1 text-sm text-white/80">
Dành cho hội viên, doanh nghiệp và đối tác thương mại
</p>
</div>
<span className="inline-flex rounded-full bg-white/12 px-4 py-1.5 text-xs font-semibold tracking-[0.24em] text-white/92">
VCCI-HCM
</span>
</div>
</div>
<div className="grid md:grid-cols-2">
{SERVICE_SUPPORT_ITEMS.map((item, index) => {
const Icon = item.icon;
const isRightColumn = index % 2 === 1;
const isLastRow = index >= SERVICE_SUPPORT_ITEMS.length - 2;
return (
<div
key={item.key}
className={[
"flex min-h-28 items-start gap-4 px-5 py-5 md:px-6",
!isLastRow ? "border-b border-[#e7edf7]" : "",
isRightColumn ? "md:border-l md:border-[#e7edf7]" : "",
].join(" ")}
>
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-full bg-[#fff8ea] text-[#5c6f8d]">
<Icon className="h-5 w-5" />
</div>
<p className="pt-1 text-[18px] leading-8 text-[#5f6f86]">
{item.title}
</p>
</div>
);
})}
</div>
</div>
</section>
);
}
export const ABOUT_VCCI_HCM_SLUG = "ve-vcci-hcm";
export const SERVICE_PAGE_SLUG = "dich-vu-cung-cap";
export const MEMBER_BENEFITS_PAGE_SLUG = "loi-ich-hoi-vien-vcci";
export const MEMBER_REGISTRATION_PAGE_SLUG = "dang-ky-hoi-vien";
export const MARKET_PROFILE_PAGE_SLUG = "ho-so-thi-truong";
export const LEGAL_TRADE_PAGE_SLUG =
"phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai";
export { default as AboutVcciHcmPage } from "./AboutVcciHcmPage";
export { default as DefaultInformationPage } from "./DefaultInformationPage";
export { default as LegalTradePages } from "./legal-trade-pages";
export { default as MarketProfilePage } from "./MarketProfilePage";
export { default as MemberBenefitsPage } from "./MemberBenefitsPage";
export { default as MemberRegistrationPage } from "./MemberRegistrationPage";
export { default as ServicePage } from "./ServicePage";
export * from "./constants";
'use client';
import {
BadgeCheck,
Building2,
FileCheck2,
Files,
Globe2,
ShieldCheck,
} from "lucide-react";
import type { LegalTradePageProps } from "./types";
const DEFINITIONS = [
{
title: "Giấy chứng nhận của VCCI (VCCI Certificate)",
description:
"Là một loại chứng từ thương mại do VCCI phát hành trên phôi chính thức của VCCI, nhằm chứng nhận các khai báo của Thương nhân liên quan đến hoạt động mua bán, xuất khẩu, nhập khẩu, gia công, chế biến hàng hóa, dựa trên cơ sở các hồ sơ, tài liệu do Thương nhân đó xuất trình. Giấy chứng nhận này không phải là giấy chứng nhận xuất xứ hàng hóa (C/O) và không có giá trị thay thế C/O theo quy định của pháp luật Việt Nam và các điều ước quốc tế mà Việt Nam là thành viên.",
icon: BadgeCheck,
},
{
title: "Chứng từ thương mại (Commercial Document)",
description:
"Là các loại giấy tờ, tài liệu được sử dụng trong các giao dịch thương mại trong nước và quốc tế, bao gồm nhưng không giới hạn ở: Hóa đơn thương mại, Phiếu đóng gói, Vận đơn, Tờ khai hải quan hàng hóa xuất khẩu/nhập khẩu, Bảng kê chi tiết, Bảng giá, Giấy chứng nhận chất lượng, Giấy chứng nhận kiểm dịch và các tài liệu, chứng từ thương mại khác.",
icon: Files,
},
{
title: "Xác nhận chứng từ thương mại",
description:
"Là hành vi của VCCI, thông qua người có thẩm quyền, xác nhận bằng hình thức điện tử hoặc đóng dấu và ký tên lên một chứng từ thương mại phục vụ cho hoạt động xuất khẩu để chứng nhận rằng chứng từ đó, với số và ngày cụ thể, đã được một Thương nhân cụ thể xuất trình tại VCCI. Hành vi này không đồng nghĩa với việc VCCI bảo lãnh hay xác thực tính hợp pháp, tính chính xác về nội dung của chứng từ, hoặc thẩm quyền của bên phát hành gốc.",
icon: FileCheck2,
},
{
title: "Đơn vị cấp",
description:
"Đơn vị cấp Giấy chứng nhận, xác nhận Chứng từ thương mại của VCCI bao gồm Ban Pháp chế và các Chi nhánh VCCI được giao nhiệm vụ thực hiện công tác cấp Giấy chứng nhận, xác nhận Chứng từ thương mại.",
icon: Building2,
},
{
title: "Thương nhân (Trader)",
description:
"Là tổ chức kinh tế được thành lập hợp pháp, cá nhân hoạt động thương mại một cách độc lập, thường xuyên và có đăng ký kinh doanh tại Việt Nam.",
icon: ShieldCheck,
},
{
title: "Hệ thống COVCCI",
description:
"Là hệ thống dịch vụ trực tuyến của VCCI tại địa chỉ trang điện tử covcci.com.vn, được sử dụng để tiếp nhận khai báo, quản lý hồ sơ, cấp số tham chiếu và thực hiện các thủ tục liên quan đến việc cấp Giấy chứng nhận, xác nhận Chứng từ thương mại.",
icon: Globe2,
},
];
export default function CertificateTradeDocumentPage(_: LegalTradePageProps) {
return (
<section className="">
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_320px] lg:items-start">
<div className="min-w-0">
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
Giấy chứng nhận (GCN) và Chứng từ thương mại (CTTM)
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
<p className="mt-5 max-w-6xl text-base font-semibold leading-7 text-[#374151] md:text-lg md:leading-8">
Định nghĩa chung về Giấy chứng nhận của VCCI, Chứng từ thương mại và cơ chế xác nhận chứng từ phục vụ hoạt động thương mại, xuất khẩu của doanh nghiệp.
</p>
<div className="mt-7 rounded-3xl bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8 lg:px-10">
<div className="rounded-[24px] border border-[#e5edf8] bg-[#f8fbff] px-5 py-5">
<p className="text-sm font-semibold uppercase tracking-[0.18em] text-[#2450b5]">Định nghĩa chung</p>
<p className="mt-3 text-[16px] leading-8 text-[#5f6f86]">
Nội dung dưới đây làm rõ phạm vi, bản chất pháp lý và cơ chế vận hành liên quan đến việc cấp Giấy chứng nhận và xác nhận Chứng từ thương mại tại VCCI.
</p>
</div>
<div className="mt-8 grid gap-4 xl:grid-cols-2">
{DEFINITIONS.map((item, index) => {
const Icon = item.icon;
return (
<article
key={item.title}
className={[
"rounded-[26px] border px-5 py-5 shadow-[0_14px_34px_rgba(17,24,39,0.06)]",
index === 0 || index === 2 ? "border-[#dbe7ff] bg-[#f8fbff]" : "border-[#edf1f6] bg-white",
].join(" ")}
>
<div className="flex h-11 w-11 items-center justify-center rounded-2xl bg-[#eff4ff] text-[#2450b5]">
<Icon className="h-5 w-5" />
</div>
<h2 className="mt-4 text-[21px] font-bold leading-tight text-[#1f2a44]">{item.title}</h2>
<p className="mt-3 text-[16px] leading-8 text-[#5f6f86]">{item.description}</p>
</article>
);
})}
</div>
</div>
</div>
<aside className="space-y-5 lg:sticky lg:top-24">
<div className="rounded-[28px] border border-[#edf1f6] bg-[#fbfcff] px-6 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.05)]">
<h2 className="text-[28px] font-bold leading-tight text-[#1f2a44]">Thành phần chính</h2>
<div className="mt-5 space-y-4 text-[16px] leading-7 text-[#5f6f86]">
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>Giấy chứng nhận của VCCI</span>
</div>
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>Chứng từ thương mại trong giao dịch trong nước và quốc tế</span>
</div>
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>Xác nhận chứng từ thương mại và Hệ thống COVCCI</span>
</div>
</div>
</div>
<div className="rounded-[28px] bg-linear-to-br from-[#1d56b7] to-[#21467f] px-6 py-6 text-white shadow-[0_22px_46px_rgba(28,52,120,0.18)]">
<h2 className="text-[26px] font-bold leading-tight">Ghi chú pháp lý</h2>
<div className="mt-5 space-y-4 text-[15px] leading-7 text-white/88">
<p>
Giấy chứng nhận của VCCI không phải là C/O và không có giá trị thay thế C/O theo quy định pháp luật hiện hành.
</p>
<p>
Việc xác nhận chứng từ thương mại không đồng nghĩa với việc VCCI bảo lãnh hay xác thực toàn bộ nội dung pháp lý của chứng từ gốc.
</p>
</div>
</div>
</aside>
</div>
</section>
);
}
'use client';
import { Mail, MapPin, Phone, UserRound } from "lucide-react";
import type { LegalTradePageProps } from "./types";
export default function ContactPage(_: LegalTradePageProps) {
return (
<section className="py-2">
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_320px] lg:items-start">
<div className="min-w-0">
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
Thông tin liên hệ
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
<div className="mt-7 space-y-5">
<article className="rounded-3xl border border-[#edf1f6] bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8">
<h2 className="text-[24px] font-bold leading-tight text-[#1f2a44]">
Phòng Pháp chế và xác nhận Chứng từ thương mại
</h2>
<div className="mt-5 space-y-4 text-[16px] leading-8 text-[#5f6f86]">
<p>Liên đoàn Thương mại và Công nghiệp Việt Nam – Chi nhánh khu vực Thành phố Hồ Chí Minh (VCCI-HCM)</p>
<div className="flex items-start gap-3">
<MapPin className="mt-1 h-4 w-4 shrink-0 text-[#2450b5]" />
<span>Phòng 103, Lầu 1, Tòa nhà VCCI HCM, 171 Võ Thị Sáu, P. Xuân Hòa, TP. HCM</span>
</div>
<div className="flex items-start gap-3">
<Phone className="mt-1 h-4 w-4 shrink-0 text-[#2450b5]" />
<span>028-3932 6498</span>
</div>
<div className="flex items-start gap-3">
<Mail className="mt-1 h-4 w-4 shrink-0 text-[#2450b5]" />
<span>co@vcci-hcm.org.vn</span>
</div>
</div>
</article>
<article className="rounded-3xl border border-[#edf1f6] bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8">
<h2 className="text-[24px] font-bold leading-tight text-[#1f2a44]">
Xử lý vướng mắc, phản ánh, góp ý trong quá trình làm thủ tục cấp GCN và xác nhận CTTM
</h2>
<div className="mt-5 space-y-5 text-[16px] leading-8 text-[#5f6f86]">
<div>
<p className="font-semibold text-[#1f2a44]">Điểm cấp số 1</p>
<p>Điện thoại: 028-3932 6498</p>
<p>Email: co@vcci-hcm.org.vn</p>
</div>
<div>
<p className="font-semibold text-[#1f2a44]">Điểm cấp số 2</p>
<p>Phó Trưởng phòng: Nguyễn Văn Đức</p>
<p>Mobile: 090 949 7155</p>
<p>Email: nvduc1980@gmail.com</p>
</div>
<div>
<p className="font-semibold text-[#1f2a44]">Điểm cấp số 3</p>
<p>Trưởng phòng (Cơ sở 2): Bà Ma Thị Hương</p>
<p>Mobile: 039 512 2922</p>
<p>Email: huongmtvccivt@gmail.com</p>
</div>
</div>
</article>
<article className="rounded-3xl border border-[#edf1f6] bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8">
<h2 className="text-[24px] font-bold leading-tight text-[#1f2a44]">
Hướng dẫn hồ sơ và tiếp nhận phản ánh
</h2>
<div className="mt-5 space-y-5 text-[16px] leading-8 text-[#5f6f86]">
<div>
<p className="font-semibold text-[#1f2a44]">Hướng dẫn khai hồ sơ thương nhân, chữ ký số và IT</p>
<p>Điểm cấp số 1, điện thoại: 028-3932 6498</p>
<p>Điểm cấp số 2, điện thoại: 0274-380 0048</p>
<p>Điểm cấp số 3, điện thoại: 025-4385 2710</p>
</div>
<div>
<p className="font-semibold text-[#1f2a44]">Tiếp thu, giải quyết phản ánh, khiếu nại, góp ý</p>
<p>Trưởng phòng (Trụ sở chính): Ông Vũ Xuân Hưng</p>
<p>Điện thoại: 028-3932 6929 hoặc Mobile: 0909 170 171 (Đường dây nóng)</p>
<p>Email: vuxuanhung@vcci-hcm.org.vn</p>
</div>
</div>
</article>
</div>
</div>
<aside className="space-y-5 lg:sticky lg:top-24">
<div className="rounded-[28px] border border-[#edf1f6] bg-[#fbfcff] px-6 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.05)]">
<h2 className="text-[28px] font-bold leading-tight text-[#1f2a44]">Đầu mối hỗ trợ</h2>
<div className="mt-5 space-y-4 text-[16px] leading-7 text-[#5f6f86]">
<div className="flex items-start gap-3">
<Mail className="mt-1 h-4 w-4 shrink-0 text-[#2450b5]" />
<span>co@vcci-hcm.org.vn</span>
</div>
<div className="flex items-start gap-3">
<Phone className="mt-1 h-4 w-4 shrink-0 text-[#2450b5]" />
<span>Đường dây nóng: 0909 170 171</span>
</div>
<div className="flex items-start gap-3">
<UserRound className="mt-1 h-4 w-4 shrink-0 text-[#2450b5]" />
<span>Ông Vũ Xuân Hưng</span>
</div>
</div>
</div>
</aside>
</div>
</section>
);
}
'use client';
import { CircleDollarSign, FileStack, Layers3 } from "lucide-react";
import type { LegalTradePageProps } from "./types";
const FEE_ITEMS = [
{
title: "Một bộ GCN, CTTM (4 bản)",
value: "100.000đ/bộ",
icon: FileStack,
},
{
title: "Bản làm thêm tính từ bản thứ 5 trở lên",
value: "10.000đ/bản",
icon: Layers3,
},
{
title: "Phôi Giấy chứng nhận",
value: "20.000đ/tờ",
icon: CircleDollarSign,
},
] as const;
export default function FeesPage(_: LegalTradePageProps) {
return (
<section className="">
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_320px] lg:items-start">
<div className="min-w-0">
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
Phí cấp GCN và xác nhận CTTM
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
<div className="mt-7 rounded-3xl bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8 lg:px-10">
<div className="rounded-3xl border border-[#e5edf8] bg-[#f8fbff] px-5 py-5">
<p className="text-sm font-semibold uppercase tracking-[0.18em] text-[#2450b5]">Biểu phí hiện hành</p>
<p className="mt-3 text-[16px] leading-8 text-[#5f6f86]">
Mức phí áp dụng cho việc cấp Giấy chứng nhận và xác nhận Chứng từ thương mại được tính theo từng loại hồ sơ và số lượng bản phát hành.
</p>
</div>
<div className="mt-8 grid gap-4 md:grid-cols-3">
{FEE_ITEMS.map((item, index) => {
const Icon = item.icon;
return (
<article
key={item.title}
className={[
"rounded-[26px] border px-5 py-5 shadow-[0_14px_34px_rgba(17,24,39,0.06)]",
index === 0 ? "border-[#dbe7ff] bg-[#f8fbff]" : "border-[#edf1f6] bg-white",
].join(" ")}
>
<div className="flex h-11 w-11 items-center justify-center rounded-2xl bg-[#eff4ff] text-[#2450b5]">
<Icon className="h-5 w-5" />
</div>
<h2 className="mt-4 text-[20px] font-bold leading-tight text-[#1f2a44]">{item.title}</h2>
<p className="mt-4 text-[30px] font-bold leading-none text-[#2450b5]">{item.value}</p>
</article>
);
})}
</div>
</div>
</div>
<aside className="space-y-5 lg:sticky lg:top-24">
<div className="rounded-[28px] border border-[#edf1f6] bg-[#fbfcff] px-6 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.05)]">
<h2 className="text-[28px] font-bold leading-tight text-[#1f2a44]">Tóm tắt chi phí</h2>
<div className="mt-5 space-y-4 text-[16px] leading-7 text-[#5f6f86]">
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>01 bộ tiêu chuẩn gồm 4 bản</span>
</div>
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>Có phụ phí cho bản làm thêm từ bản thứ 5</span>
</div>
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>Phôi Giấy chứng nhận được tính riêng theo từng tờ</span>
</div>
</div>
</div>
<div className="rounded-[28px] bg-linear-to-br from-[#1d56b7] to-[#21467f] px-6 py-6 text-white shadow-[0_22px_46px_rgba(28,52,120,0.18)]">
<h2 className="text-[26px] font-bold leading-tight">Lưu ý khi chuẩn bị</h2>
<div className="mt-5 space-y-4 text-[15px] leading-7 text-white/88">
<p>Kiểm tra trước số lượng bản cần cấp để chuẩn bị đúng chi phí thực hiện.</p>
<p>Chuẩn bị lệ phí đầy đủ sẽ giúp quá trình tiếp nhận và xử lý hồ sơ diễn ra nhanh hơn.</p>
</div>
</div>
</aside>
</div>
</section>
);
}
'use client';
import { Download, FileBadge2, FileText } from "lucide-react";
import type { LegalTradePageProps } from "./types";
export default function FormsPage(_: LegalTradePageProps) {
return (
<section className="py-2">
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_320px] lg:items-start">
<div className="min-w-0">
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
Biểu mẫu GCN và nội dung khai báo GCN, CTTM
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
<div className="rounded-3xl bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8 lg:px-10">
<div className="rounded-[26px] border border-[#edf1f6] bg-white px-5 py-5 shadow-[0_14px_34px_rgba(17,24,39,0.06)]">
<div className="flex items-start gap-4">
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-2xl bg-[#eff4ff] text-[#2450b5]">
<FileText className="h-5 w-5" />
</div>
<div className="min-w-0 flex-1">
<h2 className="text-[22px] font-bold leading-tight text-[#1f2a44]">
bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm.docx
</h2>
<p className="mt-3 text-[16px] leading-8 text-[#5f6f86]">
Nhấn tải xuống để xem toàn bộ biểu mẫu và nội dung khai báo.
</p>
<a
href="/bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm.docx"
download
className="mt-5 inline-flex items-center gap-2 rounded-[4px] bg-[#2450b5] px-5 py-3 text-[15px] font-semibold text-white transition-colors hover:bg-[#173f9f]"
>
<Download className="h-4 w-4" />
Tải biểu mẫu
</a>
</div>
</div>
</div>
</div>
</div>
<aside className="space-y-5 lg:sticky lg:top-24">
<div className="rounded-[28px] border border-[#edf1f6] bg-[#fbfcff] px-6 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.05)]">
<h2 className="text-[28px] font-bold leading-tight text-[#1f2a44]">Lưu ý</h2>
<div className="mt-5 space-y-4 text-[16px] leading-7 text-[#5f6f86]">
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>Người dùng có thể tải về để xem biểu mẫu đầy đủ trên máy của mình.</span>
</div>
</div>
</div>
</aside>
</div>
</section>
);
}
'use client';
import {
Building2,
CircleDollarSign,
ClipboardList,
FileBadge2,
FileCheck2,
Mail,
MapPin,
Phone,
Scale,
ScrollText,
} from "lucide-react";
import type { LegalTradeTemplate } from "./types";
type LegalTradeLayoutProps = {
template: LegalTradeTemplate;
};
const ICONS = [Scale, FileCheck2, ScrollText, CircleDollarSign, Building2, ClipboardList];
export default function LegalTradeLayout({ template }: LegalTradeLayoutProps) {
return (
<section className="">
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_340px] lg:items-start">
<div className="min-w-0">
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
{template.pageTitle}
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
{template.intro ? (
<p className="mt-5 max-w-6xl text-base font-semibold leading-7 text-[#374151] md:text-lg md:leading-8">
{template.intro}
</p>
) : null}
<div className="mt-7 space-y-5">
{template.sections.map((section, index) => {
const Icon = ICONS[index % ICONS.length];
return (
<article
key={section.title}
className="rounded-3xl border border-[#edf1f6] bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8"
>
<div className="flex items-start gap-4">
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-2xl bg-[#eff4ff] text-[#2450b5]">
<Icon className="h-5 w-5" />
</div>
<div className="min-w-0 flex-1">
<h2 className="text-[24px] font-bold leading-tight text-[#1f2a44]">{section.title}</h2>
{section.description ? (
<p className="mt-4 text-[16px] leading-8 text-[#5f6f86]">{section.description}</p>
) : null}
{section.bullets?.length ? (
<ul className="mt-4 space-y-3 text-[16px] leading-8 text-[#5f6f86]">
{section.bullets.map((item) => (
<li key={item} className="flex items-start gap-3">
<span className="mt-3 h-2 w-2 shrink-0 rounded-full bg-[#f5a400]" />
<span>{item}</span>
</li>
))}
</ul>
) : null}
{section.numbered?.length ? (
<ol className="mt-4 space-y-4 text-[16px] leading-8 text-[#5f6f86]">
{section.numbered.map((item, itemIndex) => (
<li key={item} className="flex items-start gap-4">
<span className="mt-0.5 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[#2450b5] text-sm font-bold text-white">
{itemIndex + 1}
</span>
<span>{item}</span>
</li>
))}
</ol>
) : null}
</div>
</div>
</article>
);
})}
</div>
</div>
<aside className="space-y-5 lg:sticky lg:top-24">
{template.sideCard ? (
<div className="rounded-[28px] border border-[#edf1f6] bg-[#fbfcff] px-6 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.05)]">
<h2 className="text-[28px] font-bold leading-tight text-[#1f2a44]">{template.sideCard.title}</h2>
<div className="mt-5 space-y-4">
{template.sideCard.items.map((item) => (
<div key={item} className="flex items-start gap-3 text-[16px] leading-7 text-[#5f6f86]">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>{item}</span>
</div>
))}
</div>
</div>
) : null}
<div className="rounded-[28px] bg-linear-to-br from-[#1d56b7] to-[#21467f] px-6 py-6 text-white shadow-[0_22px_46px_rgba(28,52,120,0.18)]">
<h2 className="text-[26px] font-bold leading-tight">Liên hệ hỗ trợ</h2>
<div className="mt-5 space-y-4 text-[15px] leading-7 text-white/88">
<div className="flex items-start gap-3">
<Phone className="mt-1 h-4 w-4 shrink-0 text-[#f5c21b]" />
<span>028-3932 6498</span>
</div>
<div className="flex items-start gap-3">
<Mail className="mt-1 h-4 w-4 shrink-0 text-[#f5c21b]" />
<span>co@vcci-hcm.org.vn</span>
</div>
<div className="flex items-start gap-3">
<MapPin className="mt-1 h-4 w-4 shrink-0 text-[#f5c21b]" />
<span>Phòng 103, Lầu 1, Tòa nhà VCCI HCM, 171 Võ Thị Sáu, P. Xuân Hòa, TP. HCM</span>
</div>
<div className="flex items-start gap-3">
<FileBadge2 className="mt-1 h-4 w-4 shrink-0 text-[#f5c21b]" />
<span>Hệ thống trực tuyến: covcci.com.vn</span>
</div>
</div>
</div>
</aside>
</div>
</section>
);
}
'use client';
import { Building2, Clock3, MapPin, Phone } from "lucide-react";
import type { LegalTradePageProps } from "./types";
const LOCATIONS = [
{
title: "Điểm cấp số 1",
address:
"Phòng 103, Lầu 1, Tòa nhà VCCI HCM, 171 Võ Thị Sáu, Phường Xuân Hòa, Thành phố Hồ Chí Minh",
phone: "028-3932 6498",
},
{
title: "Điểm cấp số 2",
address:
"Lầu 3, Tòa nhà Công ty CP ICD Tân Cảng Sóng Thần, Số 7/20, Đường ĐT 743, KP. Bình Đáng, Phường Bình Hòa, Thành phố Hồ Chí Minh",
phone: "0274-380 0048",
},
{
title: "Điểm cấp số 3",
address: "155 Nguyễn Thái Học, Phường Tam Thắng, Thành phố Hồ Chí Minh",
phone: "025-4385 2710",
},
] as const;
export default function LocationsPage(_: LegalTradePageProps) {
return (
<section className="">
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_320px] lg:items-start">
<div className="min-w-0">
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
Điểm cấp và cấp GCN và xác nhận CTTM
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
<div className="mt-7 rounded-3xl bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8 lg:px-10">
<div className="rounded-3xl border border-[#e5edf8] bg-[#f8fbff] px-5 py-5">
<div className="flex items-center gap-3 text-[#2450b5]">
<Building2 className="h-5 w-5" />
<p className="text-sm font-semibold uppercase tracking-[0.18em]">
1. Các điểm cấp GCN và xác nhận CTTM thuộc VCCI-HCM
</p>
</div>
</div>
<div className="mt-8 grid gap-4">
{LOCATIONS.map((item, index) => (
<article
key={item.title}
className={[
"rounded-[26px] border px-5 py-5 shadow-[0_14px_34px_rgba(17,24,39,0.06)]",
index === 0 ? "border-[#dbe7ff] bg-[#f8fbff]" : "border-[#edf1f6] bg-white",
].join(" ")}
>
<div className="flex items-start gap-4">
<span className="inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-2xl bg-[#eff4ff] text-lg font-bold text-[#2450b5]">
{index + 1}
</span>
<div className="min-w-0 flex-1">
<h2 className="text-[22px] font-bold leading-tight text-[#1f2a44]">{item.title}</h2>
<div className="mt-4 space-y-3 text-[16px] leading-8 text-[#5f6f86]">
<div className="flex items-start gap-3">
<MapPin className="mt-1 h-4 w-4 shrink-0 text-[#2450b5]" />
<span>{item.address}</span>
</div>
<div className="flex items-start gap-3">
<Phone className="mt-1 h-4 w-4 shrink-0 text-[#2450b5]" />
<span>{item.phone}</span>
</div>
</div>
</div>
</div>
</article>
))}
</div>
<div className="mt-8 rounded-3xl border border-[#dbe7ff] bg-[#f8fbff] px-5 py-5">
<div className="flex items-center gap-3 text-[#2450b5]">
<Clock3 className="h-5 w-5" />
<p className="text-sm font-semibold uppercase tracking-[0.18em]">2. Giờ tiếp nhận hồ sơ</p>
</div>
<div className="mt-4 space-y-2 text-[16px] leading-8 text-[#5f6f86]">
<p>– Từ thứ Hai đến thứ Sáu</p>
<p>Buổi sáng: 7h30 – 11h30</p>
<p>Buổi chiều: 13h30 – 16h30</p>
<p>Thời gian cấp: không quá 08 giờ làm việc</p>
</div>
</div>
</div>
</div>
<aside className="space-y-5 lg:sticky lg:top-24">
<div className="rounded-[28px] border border-[#edf1f6] bg-[#fbfcff] px-6 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.05)]">
<h2 className="text-[28px] font-bold leading-tight text-[#1f2a44]">Liên hệ nhanh</h2>
<div className="mt-5 space-y-4 text-[16px] leading-7 text-[#5f6f86]">
{LOCATIONS.map((item) => (
<div key={item.title} className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>
{item.title}: {item.phone}
</span>
</div>
))}
</div>
</div>
<div className="rounded-[28px] bg-linear-to-br from-[#1d56b7] to-[#21467f] px-6 py-6 text-white shadow-[0_22px_46px_rgba(28,52,120,0.18)]">
<h2 className="text-[26px] font-bold leading-tight">Khung giờ làm việc</h2>
<div className="mt-5 space-y-4 text-[15px] leading-7 text-white/88">
<p>Từ thứ Hai đến thứ Sáu</p>
<p>Buổi sáng: 7h30 – 11h30</p>
<p>Buổi chiều: 13h30 – 16h30</p>
<p>Thời gian cấp: không quá 08 giờ làm việc</p>
</div>
</div>
</aside>
</div>
</section>
);
}
'use client';
import { BriefcaseBusiness, FileText, GraduationCap, Mail, Phone, Scale } from "lucide-react";
import type { LegalTradePageProps } from "./types";
const PHAP_CHE_SERVICES = [
{
title: "Góp ý và hỗ trợ pháp lý",
description:
"Tập hợp ý kiến góp ý xây dựng pháp luật, tiếp nhận các khó khăn, vướng mắc trong hoạt động kinh doanh của doanh nghiệp.",
icon: Scale,
},
{
title: "Tư vấn chuyên sâu",
description:
"Tư vấn, kết nối và cung cấp dịch vụ pháp lý kinh doanh chuyên sâu (Luật sư/ Trọng tài viên).",
icon: FileText,
},
{
title: "Dịch vụ thương mại",
description:
"Dịch vụ xuất khẩu, nhập khẩu; Chứng nhận lãnh sự; Phân loại HS; C/O; Lộ trình thuế quan trong các FTA; …",
icon: BriefcaseBusiness,
},
{
title: "Đào tạo chuyên sâu",
description:
"Tổ chức tập huấn đào tạo chuyên sâu trong các lĩnh vực Thuế; Hải quan; Tài chính kế toán; Phân loại mã số hàng hóa (Mã HS); Xuất xứ hàng hóa; Những vấn đề pháp lý của hợp đồng mua bán hàng hóa trong nước và quốc tế; …",
icon: GraduationCap,
},
];
export default function PhapChePage(_: LegalTradePageProps) {
return (
<section className="">
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_320px] lg:items-start">
<div className="min-w-0">
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
Pháp chế
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
<div className="mt-7 rounded-3xl bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8 lg:px-10">
<div className="grid gap-4 md:grid-cols-2">
<div className="rounded-[24px] border border-[#e5edf8] bg-[#f8fbff] px-5 py-5">
<div className="flex items-center gap-3 text-[#2450b5]">
<Phone className="h-5 w-5" />
<span className="text-sm font-semibold uppercase tracking-[0.18em]">Điện thoại</span>
</div>
<p className="mt-3 text-[28px] font-bold text-[#1f2a44]">028-3932 6498</p>
</div>
<div className="rounded-[24px] border border-[#e5edf8] bg-[#f8fbff] px-5 py-5">
<div className="flex items-center gap-3 text-[#2450b5]">
<Mail className="h-5 w-5" />
<span className="text-sm font-semibold uppercase tracking-[0.18em]">Email</span>
</div>
<p className="mt-3 break-words text-[22px] font-bold text-[#1f2a44]">co@vcci-hcm.org.vn</p>
</div>
</div>
<div className="mt-8 grid gap-4 xl:grid-cols-2">
{PHAP_CHE_SERVICES.map((item) => {
const Icon = item.icon;
return (
<article
key={item.title}
className="rounded-[26px] border border-[#edf1f6] bg-white px-5 py-5 shadow-[0_14px_34px_rgba(17,24,39,0.06)]"
>
<div className="flex h-11 w-11 items-center justify-center rounded-2xl bg-[#eff4ff] text-[#2450b5]">
<Icon className="h-5 w-5" />
</div>
<h2 className="mt-4 text-[22px] font-bold leading-tight text-[#1f2a44]">{item.title}</h2>
<p className="mt-3 text-[16px] leading-8 text-[#5f6f86]">{item.description}</p>
</article>
);
})}
</div>
</div>
</div>
<aside className="space-y-5 lg:sticky lg:top-24">
<div className="rounded-[28px] border border-[#edf1f6] bg-[#fbfcff] px-6 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.05)]">
<h2 className="text-[28px] font-bold leading-tight text-[#1f2a44]">Phạm vi hỗ trợ</h2>
<div className="mt-5 space-y-4 text-[16px] leading-7 text-[#5f6f86]">
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>Góp ý xây dựng pháp luật và tiếp nhận vướng mắc doanh nghiệp</span>
</div>
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>Tư vấn và kết nối chuyên gia pháp lý kinh doanh</span>
</div>
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>Đào tạo chuyên sâu về thuế, hải quan, xuất xứ và hợp đồng</span>
</div>
</div>
</div>
<div className="rounded-[28px] bg-linear-to-br from-[#1d56b7] to-[#21467f] px-6 py-6 text-white shadow-[0_22px_46px_rgba(28,52,120,0.18)]">
<h2 className="text-[26px] font-bold leading-tight">Liên hệ Pháp chế</h2>
<div className="mt-5 space-y-4 text-[15px] leading-7 text-white/88">
<div className="flex items-start gap-3">
<Phone className="mt-1 h-4 w-4 shrink-0 text-[#f5c21b]" />
<span>028-3932 6498</span>
</div>
<div className="flex items-start gap-3">
<Mail className="mt-1 h-4 w-4 shrink-0 text-[#f5c21b]" />
<span>co@vcci-hcm.org.vn</span>
</div>
</div>
</div>
</aside>
</div>
</section>
);
}
'use client';
import { Clock3, FileCheck2, FileUp, Landmark, ReceiptText, RotateCcw } from "lucide-react";
import type { LegalTradePageProps } from "./types";
const REQUIREMENTS = [
"Đăng ký tài khoản Thương nhân và khai báo các trường thông tin của Thương nhân trên Hệ thống COVCCI.",
"Liên hệ với Đơn vị cấp Giấy chứng nhận, xác nhận Chứng từ thương mại của VCCI kích hoạt tài khoản cho Thương nhân.",
];
const STEPS = [
{
title: "Bước 1. Khai báo trực tuyến",
description:
"Thương nhân truy cập Hệ thống COVCCI, thực hiện khai báo các thông tin theo hướng dẫn, đính kèm hồ sơ dưới dạng điện tử đã được Thương nhân xác nhận bằng chữ ký số do cơ quan có thẩm quyền cấp và nhận số tham chiếu cho bộ hồ sơ.",
icon: FileUp,
},
{
title: "Bước 2. Thanh toán giá dịch vụ và hồ sơ giấy",
description:
"Thương nhân thanh toán giá dịch vụ và bộ hồ sơ giấy đầy đủ theo quy định tại bộ phận tiếp nhận của đơn vị VCCI có thẩm quyền.",
icon: ReceiptText,
},
{
title: "Bước 3. Phân công và thẩm định",
description:
"Bộ phận tiếp nhận hồ sơ kiểm tra tính đầy đủ, hợp lệ ban đầu và phân công cho cán bộ nghiệp vụ xử lý.",
icon: FileCheck2,
},
{
title: "Bước 4. Phê duyệt và cấp",
description:
"Nếu hồ sơ hợp lệ và đầy đủ, cán bộ nghiệp vụ trình hồ sơ lên người có thẩm quyền ký duyệt. Sau khi được ký duyệt, chứng từ sẽ được đóng dấu, tách, lưu trữ (hoặc vào hộp) và trả kết quả cho Thương nhân.",
icon: Landmark,
},
{
title: "Bước 5. Trả hồ sơ hoặc yêu cầu bổ sung",
description:
"Nếu hồ sơ có sai sót, không hợp lệ hoặc vi phạm các quy định, cán bộ nghiệp vụ thông báo rõ lý do cho Thương nhân (thông qua hệ thống hoặc trực tiếp) để yêu cầu sửa đổi, bổ sung hoặc từ chối cấp.",
icon: RotateCcw,
},
];
export default function ProcedurePage(_: LegalTradePageProps) {
return (
<section className="">
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_320px] lg:items-start">
<div className="min-w-0">
<h1 className="max-w-6xl text-3xl font-bold leading-tight text-[#111827] md:text-[38px] md:leading-[1.15]">
Quy trình tiếp nhận hồ sơ cấp GCN và xác nhận CTTM
</h1>
<div className="mt-3 h-[3px] w-16 rounded-full bg-[#f5a400]" />
<div className="mt-7 rounded-3xl bg-white px-5 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.06)] sm:px-8 lg:px-10">
<div className="rounded-[24px] border border-[#e5edf8] bg-[#f8fbff] px-5 py-5">
<p className="text-sm font-semibold uppercase tracking-[0.18em] text-[#2450b5]">
1. Yêu cầu đối với Thương nhân
</p>
<div className="mt-4 space-y-3 text-[16px] leading-8 text-[#5f6f86]">
{REQUIREMENTS.map((item) => (
<div key={item} className="flex items-start gap-3">
<span className="mt-3 h-2 w-2 shrink-0 rounded-full bg-[#f5a400]" />
<span>{item}</span>
</div>
))}
</div>
</div>
<div className="mt-8">
<div className="flex items-center gap-3">
<div className="h-11 w-11 rounded-2xl bg-[#eff4ff] text-[#2450b5] flex items-center justify-center">
<FileCheck2 className="h-5 w-5" />
</div>
<div>
<p className="text-sm font-semibold uppercase tracking-[0.18em] text-[#2450b5]">
2. Quy trình thực hiện
</p>
<h2 className="mt-1 text-[24px] font-bold leading-tight text-[#1f2a44]">
Các bước xử lý thống nhất
</h2>
</div>
</div>
<div className="mt-6 space-y-4">
{STEPS.map((step, index) => {
const Icon = step.icon;
return (
<article
key={step.title}
className="rounded-[24px] border border-[#edf1f6] bg-white px-5 py-5 shadow-[0_14px_34px_rgba(17,24,39,0.06)]"
>
<div className="flex items-start gap-4">
<div className="inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-2xl bg-[#eff4ff] text-[#2450b5]">
<Icon className="h-5 w-5" />
</div>
<div className="min-w-0 flex-1">
<div className="flex items-center gap-3">
<span className="inline-flex h-7 min-w-7 items-center justify-center rounded-full bg-[#2450b5] px-2 text-sm font-bold text-white">
{index + 1}
</span>
<h3 className="text-[20px] font-bold leading-tight text-[#1f2a44]">{step.title}</h3>
</div>
<p className="mt-3 text-[16px] leading-8 text-[#5f6f86]">{step.description}</p>
</div>
</div>
</article>
);
})}
</div>
</div>
<div className="mt-8 rounded-[24px] border border-[#dbe7ff] bg-[#f8fbff] px-5 py-5">
<div className="flex items-center gap-3 text-[#2450b5]">
<Clock3 className="h-5 w-5" />
<p className="text-sm font-semibold uppercase tracking-[0.18em]">3. Thời gian xử lý</p>
</div>
<p className="mt-4 text-[16px] leading-8 text-[#5f6f86]">
Trường hợp hồ sơ chưa hợp lệ, VCCI sẽ thông báo qua Hệ thống COVCCI các nội dung cần sửa đổi, bổ sung cho Thương nhân trong thời hạn 03 ngày làm việc kể từ ngày tiếp nhận hồ sơ. Thời gian xử lý cho một bộ hồ sơ hợp lệ là không quá 08 giờ làm việc kể từ thời điểm VCCI nhận đủ hồ sơ hợp lệ. Đối với trường hợp cần thẩm tra, xác minh hay trao đổi nội bộ và từ cơ quan chức năng trong và ngoài nước khác, thời gian giải quyết có thể kéo dài hơn so với quy định chung.
</p>
</div>
</div>
</div>
<aside className="space-y-5 lg:sticky lg:top-24">
<div className="rounded-[28px] border border-[#edf1f6] bg-[#fbfcff] px-6 py-6 shadow-[0_18px_42px_rgba(17,24,39,0.05)]">
<h2 className="text-[28px] font-bold leading-tight text-[#1f2a44]">Mốc thời gian</h2>
<div className="mt-5 space-y-4 text-[16px] leading-7 text-[#5f6f86]">
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>Thông báo bổ sung: trong 03 ngày làm việc</span>
</div>
<div className="flex items-start gap-3">
<span className="mt-2 h-2.5 w-2.5 shrink-0 rounded-full bg-[#2f6ce5]" />
<span>Xử lý hồ sơ hợp lệ: không quá 08 giờ làm việc</span>
</div>
</div>
</div>
<div className="rounded-[28px] bg-linear-to-br from-[#1d56b7] to-[#21467f] px-6 py-6 text-white shadow-[0_22px_46px_rgba(28,52,120,0.18)]">
<h2 className="text-[26px] font-bold leading-tight">Kênh xử lý</h2>
<div className="mt-5 space-y-4 text-[15px] leading-7 text-white/88">
<p>Hệ thống COVCCI dùng để khai báo, tiếp nhận và theo dõi hồ sơ trực tuyến.</p>
<p>Thương nhân cần chuẩn bị đầy đủ hồ sơ điện tử, chữ ký số và hồ sơ giấy theo quy định.</p>
</div>
</div>
</aside>
</div>
</section>
);
}
'use client';
import { useParams } from "next/navigation";
import type { DynamicCategoryRouteItem, DynamicPostItem } from "../../types";
import ContactPage from "./ContactPage";
import CertificateTradeDocumentPage from "./CertificateTradeDocumentPage";
import FeesPage from "./FeesPage";
import FormsPage from "./FormsPage";
import LocationsPage from "./LocationsPage";
import PhapChePage from "./PhapChePage";
import ProcedurePage from "./ProcedurePage";
type LegalTradeRouterProps = {
post: DynamicPostItem;
category: DynamicCategoryRouteItem;
};
function resolveVariant(post: DynamicPostItem, category: DynamicCategoryRouteItem) {
const url = category.url || post.external_link;
const slug = category.slug || post.slug;
const externalLink = post.external_link;
if (
slug === "phap-che" ||
url === "/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/phap-che"
) {
return "phap-che" as const;
}
if (
slug === "giay-chung-nhan-gcn-va-chung-tu-thuong-mai-cttm" ||
url ===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/giay-chung-nhan-gcn-va-chung-tu-thuong-mai-cttm"
) {
return "certificate-trade-document" as const;
}
if (
slug === "quy-trinh-tiep-nhan-ho-so-cap-gcn-va-xac-nhan-cttm" ||
slug === "thu-tuc-cap-co" ||
url ===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/quy-trinh-tiep-nhan-ho-so-cap-gcn-va-xac-nhan-cttm" ||
url === "/xuat-xu-hang-hoa/thu-tuc-cap-co"
) {
return "procedure" as const;
}
if (slug === "bieu-mau-co-va-cach-khai" || url === "/xuat-xu-hang-hoa/bieu-mau-co-va-cach-khai") {
return "forms" as const;
}
if (
slug === "bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm" ||
externalLink ===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm" ||
url ===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm"
) {
return "forms" as const;
}
if (
slug === "phi-cap-gcn-va-xac-nhan-cttm" ||
slug === "phi-va-le-phi-cap-co" ||
externalLink ===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/phi-cap-gcn-va-xac-nhan-cttm" ||
url ===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/phi-cap-gcn-va-xac-nhan-cttm" ||
url === "/xuat-xu-hang-hoa/phi-va-le-phi-cap-co"
) {
return "fees" as const;
}
if (
slug === "diem-cap-va-cap-gcn-va-xac-nhan-cttm" ||
slug === "diem-cap-va-thoi-gian-cap-co" ||
externalLink ===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/diem-cap-va-cap-gcn-va-xac-nhan-cttm" ||
url ===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/diem-cap-va-cap-gcn-va-xac-nhan-cttm" ||
url === "/xuat-xu-hang-hoa/diem-cap-va-thoi-gian-cap-co"
) {
return "locations" as const;
}
if (
slug === "thong-tin-lien-he" ||
slug === "thong-tin-lien-he-co" ||
externalLink ===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/thong-tin-lien-he" ||
url ===
"/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/thong-tin-lien-he" ||
url === "/xuat-xu-hang-hoa/thong-tin-lien-he-co"
) {
return "contact" as const;
}
return "overview" as const;
}
export default function LegalTradePages({ post, category }: LegalTradeRouterProps) {
const params = useParams();
const pathSegments = Array.isArray(params.slug) ? params.slug : [params.slug];
const currentSlug = pathSegments.at(-1) ?? "";
const variant = resolveVariant(
{
...post,
slug: currentSlug || post.slug,
external_link: `/${pathSegments.filter(Boolean).join("/")}` || post.external_link,
},
{
...category,
slug: currentSlug || category.slug,
url: `/${pathSegments.filter(Boolean).join("/")}` || category.url,
},
);
if (variant === "phap-che") {
return <PhapChePage post={post} category={category} />;
}
if (variant === "certificate-trade-document") {
return <CertificateTradeDocumentPage post={post} category={category} />;
}
if (variant === "procedure") {
return <ProcedurePage post={post} category={category} />;
}
if (variant === "forms") {
return <FormsPage post={post} category={category} />;
}
if (variant === "fees") {
return <FeesPage post={post} category={category} />;
}
if (variant === "locations") {
return <LocationsPage post={post} category={category} />;
}
if (variant === "contact") {
return <ContactPage post={post} category={category} />;
}
return <PhapChePage post={post} category={category} />;
}
import type { DynamicCategoryRouteItem, DynamicPostItem } from "../../types";
export type LegalTradePageProps = {
post: DynamicPostItem;
category: DynamicCategoryRouteItem;
};
export type LegalTradeSection = {
title: string;
description?: string;
bullets?: string[];
numbered?: string[];
};
export type LegalTradeTemplate = {
pageTitle: string;
intro?: string;
sections: LegalTradeSection[];
sideCard?: {
title: string;
items: string[];
};
};
import type { Category } from "@/api/models/category";
export const categoryFallbackRows: Category[] = [
{
"id": "450bed53-0e17-4f0a-8a02-17fa657ab5b0",
"name": "Điểm cấp và cấp GCN và xác nhận CTTM",
"slug": "diem-cap-va-cap-gcn-va-xac-nhan-cttm",
"url": "/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/diem-cap-va-cap-gcn-va-xac-nhan-cttm",
"created_at": "2026-05-19T07:10:47.564Z",
"created_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"updated_at": "2026-05-19T07:10:47.564Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 6,
"thumbnail": null
},
{
"id": "9adf2741-f2ee-4a0a-88a2-0b6fd8d9adfd",
"name": "Tin Doanh nghiệp",
......@@ -15,6 +29,20 @@ export const categoryFallbackRows: Category[] = [
"sort_order": 3,
"thumbnail": null
},
{
"id": "bec6a070-80bc-448f-b7b6-bbe5188e320f",
"name": "Phí cấp GCN và xác nhận CTTM",
"slug": "phi-cap-gcn-va-xac-nhan-cttm",
"url": "/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/phi-cap-gcn-va-xac-nhan-cttm",
"created_at": "2026-05-19T07:10:32.998Z",
"created_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"updated_at": "2026-05-19T07:10:32.998Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 5,
"thumbnail": null
},
{
"id": "cc448be9-b9ea-46a8-aa7b-0584803330e8",
"name": "Thông tin Chính sách và Pháp luật",
......@@ -43,6 +71,20 @@ export const categoryFallbackRows: Category[] = [
"sort_order": 4,
"thumbnail": null
},
{
"id": "1eeffdb0-4edd-4770-aaa7-8e4bde8fa992",
"name": "Biểu mẫu GCN và nội dung khai báo GCN, CTTM",
"slug": "bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm",
"url": "/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/bieu-mau-gcn-va-noi-dung-khai-bao-gcn-cttm",
"created_at": "2026-05-19T07:10:21.291Z",
"created_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"updated_at": "2026-05-19T07:10:21.291Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 4,
"thumbnail": null
},
{
"id": "8e7090e5-bfc3-4128-81a5-37ec78c33bad",
"name": "Chuyên đề",
......@@ -50,10 +92,10 @@ export const categoryFallbackRows: Category[] = [
"url": "/thong-tin-truyen-thong/chuyen-de",
"created_at": "2026-05-14T04:54:26.127Z",
"created_by": null,
"updated_at": "2026-05-16T14:12:23.853Z",
"updated_at": "2026-05-19T05:56:44.774Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "news",
"parent_id": "b85f6710-bcbc-4c0b-8b3a-09fff0e5e51a",
"parent_id": "23dc501f-93bb-41d7-b05e-ace02a65cfd7",
"sort_order": 4,
"thumbnail": null
},
......@@ -86,17 +128,17 @@ export const categoryFallbackRows: Category[] = [
"thumbnail": null
},
{
"id": "ebe30f9c-d7e5-411b-a7ca-ae851118e200",
"name": "Điểm cấp và Thời gian cấp C/O",
"slug": "diem-cap-va-thoi-gian-cap-co",
"url": "/xuat-xu-hang-hoa/diem-cap-va-thoi-gian-cap-co",
"created_at": "2026-05-14T04:54:26.127Z",
"created_by": null,
"updated_at": "2026-05-14T16:13:57.088Z",
"id": "c568d697-3f33-4a42-aeeb-9d495cbdadd2",
"name": "Giấy chứng nhận (GCN) và Chứng từ thương mại (CTTM)",
"slug": "giay-chung-nhan-gcn-va-chung-tu-thuong-mai-cttm",
"url": "/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/giay-chung-nhan-gcn-va-chung-tu-thuong-mai-cttm",
"created_at": "2026-05-19T07:10:00.759Z",
"created_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"updated_at": "2026-05-19T07:10:00.759Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 7,
"sort_order": 2,
"thumbnail": null
},
{
......@@ -141,90 +183,6 @@ export const categoryFallbackRows: Category[] = [
"sort_order": 1,
"thumbnail": null
},
{
"id": "5fdd332c-e42d-490f-964b-2db464f75630",
"name": "Thông tin liên hệ",
"slug": "thong-tin-lien-he-co",
"url": "/xuat-xu-hang-hoa/thong-tin-lien-he-co",
"created_at": "2026-05-14T04:54:26.127Z",
"created_by": null,
"updated_at": "2026-05-14T16:14:01.427Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 8,
"thumbnail": null
},
{
"id": "9ddb2539-41ee-4ed3-8146-75362ac2b1be",
"name": "Phí và Lệ phí cấp C/O",
"slug": "phi-va-le-phi-cap-co",
"url": "/xuat-xu-hang-hoa/phi-va-le-phi-cap-co",
"created_at": "2026-05-14T04:54:26.127Z",
"created_by": null,
"updated_at": "2026-05-14T16:13:45.539Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 6,
"thumbnail": null
},
{
"id": "c177a719-7f9e-443c-bdeb-0676a2f6fa6b",
"name": "Biểu mẫu C/O và cách khai",
"slug": "bieu-mau-co-va-cach-khai",
"url": "/xuat-xu-hang-hoa/bieu-mau-co-va-cach-khai",
"created_at": "2026-05-14T04:54:26.127Z",
"created_by": null,
"updated_at": "2026-05-14T16:13:27.063Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 5,
"thumbnail": null
},
{
"id": "531d92b1-ae11-4915-815a-c2a4bdb9952d",
"name": "Thủ tục cấp C/O",
"slug": "thu-tuc-cap-co",
"url": "/xuat-xu-hang-hoa/thu-tuc-cap-co",
"created_at": "2026-05-14T04:54:26.127Z",
"created_by": null,
"updated_at": "2026-05-14T16:13:09.052Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 4,
"thumbnail": null
},
{
"id": "e4540f67-ee2c-4d12-a015-0c4484276ff2",
"name": "Luật áp dụng về C/O",
"slug": "luat-ap-dung-ve-co",
"url": "/xuat-xu-hang-hoa/luat-ap-dung-ve-co",
"created_at": "2026-05-14T04:54:26.127Z",
"created_by": null,
"updated_at": "2026-05-14T16:12:56.267Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 3,
"thumbnail": null
},
{
"id": "8ea819ea-bedf-4357-9228-f8730c706c34",
"name": "Mục đích của C/O",
"slug": "muc-dich-cua-co",
"url": "/xuat-xu-hang-hoa/muc-dich-cua-co",
"created_at": "2026-05-14T04:54:26.127Z",
"created_by": null,
"updated_at": "2026-05-14T16:12:49.423Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 2,
"thumbnail": null
},
{
"id": "23dc501f-93bb-41d7-b05e-ace02a65cfd7",
"name": "Thông tin truyền thống",
......@@ -309,6 +267,20 @@ export const categoryFallbackRows: Category[] = [
"sort_order": 1,
"thumbnail": null
},
{
"id": "a37b8a02-e8b3-42ce-9225-6dae460fed99",
"name": "Kết nối hội viên",
"slug": "ket-noi-hoi-vien",
"url": "/hoi-vien/ket-noi-hoi-vien",
"created_at": "2026-05-14T04:54:26.127Z",
"created_by": null,
"updated_at": "2026-05-19T08:07:50.076Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "news",
"parent_id": "3c92b2d5-1fa8-412b-bf3b-49b779f1a1c1",
"sort_order": 3,
"thumbnail": null
},
{
"id": "605a2eb4-bd60-4469-891c-d809ec46b5b5",
"name": "Thư viện tài liệu",
......@@ -379,20 +351,6 @@ export const categoryFallbackRows: Category[] = [
"sort_order": 4,
"thumbnail": null
},
{
"id": "a37b8a02-e8b3-42ce-9225-6dae460fed99",
"name": "Kết nối hội viên",
"slug": "ket-noi-hoi-vien",
"url": "/hoi-vien/ket-noi-hoi-vien",
"created_at": "2026-05-14T04:54:26.127Z",
"created_by": null,
"updated_at": "2026-05-14T16:11:58.465Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "3c92b2d5-1fa8-412b-bf3b-49b779f1a1c1",
"sort_order": 3,
"thumbnail": null
},
{
"id": "fb53905e-999b-4f54-a5f1-98c94ba03d62",
"name": "Hoạt động",
......@@ -408,13 +366,41 @@ export const categoryFallbackRows: Category[] = [
"thumbnail": null
},
{
"id": "521f4270-0836-4c18-b81f-9c25e7822c0a",
"name": "Xuất xứ hàng hóa (C/O)",
"slug": "xuat-xu-hang-hoa-co",
"url": "/xuat-xu-hang-hoa/xuat-xu-hang-hoa-co",
"created_at": "2026-05-14T04:54:26.127Z",
"created_by": null,
"updated_at": "2026-05-14T16:12:40.839Z",
"id": "098af313-3ee9-4195-910b-da4001a412eb",
"name": "Quy trình tiếp nhận hồ sơ cấp GCN và xác nhận CTTM",
"slug": "quy-trinh-tiep-nhan-ho-so-cap-gcn-va-xac-nhan-cttm",
"url": "/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/quy-trinh-tiep-nhan-ho-so-cap-gcn-va-xac-nhan-cttm",
"created_at": "2026-05-19T07:10:10.758Z",
"created_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"updated_at": "2026-05-19T07:10:10.758Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 3,
"thumbnail": null
},
{
"id": "4f552269-4629-4965-bd2f-a0b52e7630ad",
"name": "Thông tin liên hệ",
"slug": "thong-tin-lien-he",
"url": "/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/thong-tin-lien-he",
"created_at": "2026-05-19T07:10:57.232Z",
"created_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"updated_at": "2026-05-19T07:10:57.232Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
"sort_order": 7,
"thumbnail": null
},
{
"id": "3011e827-573c-438f-9c62-954331e9f25c",
"name": "Pháp chế",
"slug": "phap-che",
"url": "/phap-che-cap-giay-chung-nhan-va-xac-nhan-chung-tu-thuong-mai/phap-che",
"created_at": "2026-05-19T07:09:50.981Z",
"created_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"updated_at": "2026-05-19T07:09:50.981Z",
"updated_by": "aff87dea-73a3-4076-b1be-6b0b7b59a21d",
"type": "page",
"parent_id": "69b4c7e7-28ea-41f2-97f4-988fe702a8a3",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment