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

re-design ui home client

parent 051d8a8b
......@@ -5,6 +5,7 @@ import { Swiper, SwiperSlide } from "swiper/react";
import { Autoplay } from "swiper/modules";
import { Swiper as SwiperType } from "swiper/types";
import { useRef } from "react";
import "swiper/css";
const Banner = () => {
const swiperRef = useRef<SwiperType | null>(null);
......@@ -16,6 +17,7 @@ const Banner = () => {
loop
slidesPerView={1}
onSwiper={(s) => (swiperRef.current = s)}
className="w-full overflow-hidden"
>
<SwiperSlide>
<ImageNext
......
import { useGetNews } from "@/api/endpoints/news";
import { GetNewsResponseType, NewsItem } from "@/api/types/news";
import ImageNext from "@/components/shared/image-next";
import { Spinner } from "@/components/ui/spinner";
import { ChevronsRight } from "lucide-react";
'use client';
import {
type AdminNewsItem,
getAdminNewsSeed,
} from "@/mockdata/admin-news";
import dayjs from "dayjs";
import { ChevronRight } from "lucide-react";
import Link from "next/link";
import BASE_URL from "@/links/index";
import CardNews from "./components/card-news";
const businessOpportunities = () => {
const { data, isLoading } = useGetNews<GetNewsResponseType>(
{
pageSize: '5',
filters: `page_config.code @=co-hoi-kinh-doanh`,
}
const businessItems = getAdminNewsSeed()
.filter(
(item) =>
item.type === "tintuc" &&
!item.is_hidden &&
(item.category_ids.includes("cat-business-opportunity") ||
item.tagsearch_values.some((tag) => tag.toLowerCase().includes("cơ hội kinh doanh"))),
)
.sort(
(left, right) =>
new Date(right.published_at || right.created_at).getTime() -
new Date(left.published_at || left.created_at).getTime(),
);
function formatPublishDate(item: AdminNewsItem) {
return dayjs(item.published_at || item.created_at).format("DD/MM/YYYY");
}
function BusinessOpportunities() {
const [featuredItem, ...listItems] = businessItems;
if (!featuredItem) return null;
return (
<div className="flex-1">
<div className="flex justify-between items-center">
<section className="flex-1">
<div className="mb-4 flex items-center justify-between gap-3">
<div>
<h2 className="text-[28px] font-extrabold uppercase tracking-tight text-[#24469c] md:text-[34px]">
Cơ hội kinh doanh
</h2>
<div className="mt-2.5 h-[4px] w-[40px] rounded-full bg-[#f7b500]" />
</div>
<Link
href="/xuc-tien-thuong-mai/co-hoi/"
className="text-[18px] sm:text-[20px] font-bold uppercase text-[#063e8e]"
className="text-[#24469c] transition-colors hover:text-[#1b55a1]"
>
Cơ hội kinh doanh
<ChevronRight className="h-5 w-5" />
</Link>
</div>
<div className="space-y-3">
<Link
href="/xuc-tien-thuong-mai/co-hoi/"
className="text-[#063e8e] text-sm sm:text-base"
className="block rounded-[18px] bg-[#f5f7fb] px-4 py-3.5 transition-colors hover:bg-[#eef3fb]"
>
<ChevronsRight />
<h3 className="line-clamp-2 text-[16px] font-bold leading-[1.45] text-[#264798] md:text-[17px]">
{featuredItem.title}
</h3>
<p className="mt-2 text-[13px] text-[#9aa8c1]">{formatPublishDate(featuredItem)}</p>
</Link>
</div>
<hr className="border-[#063e8e] mb-4" />
<div className="pt-2">
{isLoading ? (
<div className="container w-full h-[80vh] flex justify-center items-center">
<Spinner />
</div>
) : (
<>
{data?.responseData.rows
.slice(0, 1)
.map((news: NewsItem) => (
<Link key={news.id} href={`${news.external_link}`}>
<div className="w-full aspect-3/2 relative overflow-hidden mb-5">
<ImageNext
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.title}
width={600}
height={400}
sizes="(max-width:768px) 100vw,50vw"
className="w-full h-full object-cover"
/>
<div className="absolute bg-white opacity-80 bottom-5 left-5 right-5 p-5">
<p className="text-[#063e8e] font-semibold text-sm sm:text-base z-10 line-clamp-3">
{news.title}
</p>
</div>
<div className="space-y-2.5">
{listItems.slice(0, 3).map((item) => (
<Link
key={item.id}
href="/xuc-tien-thuong-mai/co-hoi/"
className="flex gap-3 rounded-[14px] px-0.5 py-1 transition-colors hover:bg-[#f8fafe]"
>
<span className="mt-1 h-[40px] w-[2px] shrink-0 rounded-full bg-[#f7b500]" />
<div className="min-w-0">
<h4 className="line-clamp-2 text-[15px] leading-[1.45] text-[#264798]">
{item.title}
</h4>
<p className="mt-1.5 text-[13px] text-[#9aa8c1]">{formatPublishDate(item)}</p>
</div>
</Link>
))}
{data?.responseData.rows.slice(0, 3).map((news) => (
<CardNews key={news.id} news={news} />
))}
</>
)}
</div>
</div>
</section>
);
};
}
export default businessOpportunities;
export default BusinessOpportunities;
import EventCalendar from "@/components/base/event-calendar"
import { ChevronsRight } from "lucide-react"
import Link from "next/link"
'use client';
import {
type AdminNewsItem,
getAdminNewsSeed,
} from "@/mockdata/admin-news";
import { addMonths, format, getDay, startOfMonth, subMonths } from "date-fns";
import dayjs from "dayjs";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { useMemo, useState } from "react";
const weekDays = ["CN", "T2", "T3", "T4", "T5", "T6", "T7"];
const eventItems = getAdminNewsSeed()
.filter(
(item) =>
item.type === "tintuc" &&
!item.is_hidden &&
item.started_at,
)
.sort(
(left, right) =>
new Date(left.started_at).getTime() - new Date(right.started_at).getTime(),
);
function isTrainingEvent(item: AdminNewsItem) {
return item.tagsearch_values.some((tag) => tag.toLowerCase().includes("đào tạo"));
}
function EventsCalendar() {
const firstEventDate = eventItems[0]?.started_at
? new Date(eventItems[0].started_at)
: new Date("2026-11-01T00:00:00");
const [currentMonth, setCurrentMonth] = useState(
new Date(firstEventDate.getFullYear(), firstEventDate.getMonth(), 1),
);
const monthEvents = useMemo(
() =>
eventItems.filter((item) => {
const date = new Date(item.started_at);
return (
date.getMonth() === currentMonth.getMonth() &&
date.getFullYear() === currentMonth.getFullYear()
);
}),
[currentMonth],
);
const days = useMemo(() => {
const monthStart = startOfMonth(currentMonth);
const startWeekDay = getDay(monthStart);
const start = new Date(monthStart);
start.setDate(monthStart.getDate() - startWeekDay);
return Array.from({ length: 35 }, (_, index) => {
const day = new Date(start);
day.setDate(start.getDate() + index);
return day;
});
}, [currentMonth]);
const eventMap = useMemo(() => {
const map = new Map<string, AdminNewsItem[]>();
monthEvents.forEach((item) => {
const key = dayjs(item.started_at).format("YYYY-MM-DD");
const existing = map.get(key) ?? [];
existing.push(item);
map.set(key, existing);
});
return map;
}, [monthEvents]);
const highlightedEvent = monthEvents[0];
const EventsCalendar = () => {
return (
<div className="bg-[#063e8e] w-full lg:w-[30%] p-5">
<aside>
<div className="flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-[#e8c518]">
<aside className="w-full rounded-[28px] bg-white p-4 text-[#24469c] shadow-[0_18px_38px_rgba(16,61,130,0.16)] md:p-5 xl:w-[28%] xl:min-w-[320px]">
<div className="flex items-start justify-between gap-3">
<div>
<h2 className="text-[28px] font-extrabold uppercase tracking-tight md:text-[34px]">
Lịch sự kiện
</h2>
<Link
href="/hoat-dong/su-kien"
className="text-[#e8c518] hover:underline text-sm sm:text-base"
<p className="mt-1.5 text-[12px] uppercase tracking-[0.28em] text-[#7f8eab]">
{`THÁNG ${format(currentMonth, "MM/yyyy")}`}
</p>
</div>
<div className="flex gap-2">
<button
type="button"
onClick={() => setCurrentMonth(subMonths(currentMonth, 1))}
className="flex h-8 w-8 items-center justify-center rounded-full border border-[#dbe4f2] text-[#7f8eab] transition-colors hover:border-[#24469c] hover:text-[#24469c]"
>
<ChevronsRight />
</Link>
<ChevronLeft className="h-4 w-4" />
</button>
<button
type="button"
onClick={() => setCurrentMonth(addMonths(currentMonth, 1))}
className="flex h-8 w-8 items-center justify-center rounded-full border border-[#dbe4f2] text-[#7f8eab] transition-colors hover:border-[#24469c] hover:text-[#24469c]"
>
<ChevronRight className="h-4 w-4" />
</button>
</div>
<hr className="border-[#e8c518] mb-4" />
<EventCalendar />
</aside>
</div>
)
<div className="mt-3 h-[4px] w-[60px] rounded-full bg-[#f7b500]" />
<div className="mt-4 border-t border-[#ebf0f8] pt-3.5">
<div className="grid grid-cols-7 gap-y-2.5 text-center text-[11px] font-semibold uppercase text-[#9aabc6]">
{weekDays.map((day) => (
<div key={day}>{day}</div>
))}
</div>
<div className="mt-2.5 grid grid-cols-7 gap-y-2.5 text-center text-[13px] text-[#5e7090]">
{days.map((day) => {
const key = dayjs(day).format("YYYY-MM-DD");
const items = eventMap.get(key) ?? [];
const inMonth = day.getMonth() === currentMonth.getMonth();
const hasTraining = items.some((item) => isTrainingEvent(item));
const hasEvent = items.length > 0 && !hasTraining;
return (
<div key={key} className="relative flex items-center justify-center">
<span
className={`relative flex h-7 w-7 items-center justify-center rounded-full ${
!inMonth
? "text-[#c9d2e2]"
: hasTraining
? "bg-[#ffbc11] font-semibold text-[#163b73]"
: hasEvent
? "bg-[#1e3f9a] font-semibold text-white"
: ""
}`}
>
{format(day, "d")}
</span>
{items.length > 0 && !hasTraining && inMonth ? (
<span className="absolute bottom-[-5px] h-1.5 w-1.5 rounded-full bg-[#1e3f9a]" />
) : null}
{items.length > 0 && hasTraining && inMonth ? (
<span className="absolute bottom-[-5px] h-1.5 w-1.5 rounded-full bg-[#ffbc11]" />
) : null}
</div>
);
})}
</div>
</div>
<div className="mt-4 flex items-center gap-5 text-[12px] font-medium text-[#45608f]">
<div className="flex items-center gap-2">
<span className="h-2.5 w-2.5 rounded-full bg-[#1e3f9a]" />
<span>Sự kiện</span>
</div>
<div className="flex items-center gap-2">
<span className="h-2.5 w-2.5 rounded-full bg-[#ffbc11]" />
<span>Đào tạo</span>
</div>
</div>
{highlightedEvent ? (
<div className="mt-4 rounded-[16px] bg-[#f7f9fd] p-3.5 text-[12px] leading-5 text-[#3d547f]">
<div className="flex items-start gap-3">
<span
className={`mt-1 h-2.5 w-2.5 rounded-full ${
isTrainingEvent(highlightedEvent) ? "bg-[#ffbc11]" : "bg-[#1e3f9a]"
}`}
/>
<p className="line-clamp-3">{highlightedEvent.title}</p>
</div>
</div>
) : null}
</aside>
);
}
export default EventsCalendar
\ No newline at end of file
export default EventsCalendar;
import { useGetEvents } from "@/api/endpoints/event";
import { EventApiResponse, EventItem } from "@/api/types/event";
'use client';
import ImageNext from "@/components/shared/image-next";
import { Spinner } from "@/components/ui/spinner";
import { ChevronsRight } from "lucide-react"
import Link from "next/link"
import BASE_URL from "@/links/index";
import CardEvent from "./components/card-event";
import stripImagesAndHtml from "@/helpers/stripImageAndHtml";
import {
type AdminNewsItem,
getAdminNewsSeed,
} from "@/mockdata/admin-news";
import dayjs from "dayjs";
import Link from "next/link";
const eventItems = getAdminNewsSeed()
.filter(
(item) =>
item.type === "tintuc" &&
item.header_category_id === "activity-events" &&
!item.is_hidden &&
item.started_at,
)
.sort(
(left, right) =>
new Date(left.started_at).getTime() - new Date(right.started_at).getTime(),
);
function formatEventDate(item: AdminNewsItem) {
return dayjs(item.started_at || item.published_at || item.created_at).format("DD/MM/YYYY");
}
function Events() {
const { data, isLoading } = useGetEvents<EventApiResponse>();
const [featuredEvent, ...sideEvents] = eventItems;
if (!featuredEvent) return null;
return (
<div className="flex-1 bg-[#063e8e] p-5">
<div className="flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-[#e8c518]">
<div className="flex-1 rounded-[28px] bg-linear-to-br from-[#14488f] to-[#2d67bf] p-4 text-white shadow-[0_18px_38px_rgba(16,61,130,0.24)] md:p-5">
<div className="mb-4 flex items-start justify-between gap-4">
<div>
<h2 className="text-[28px] font-extrabold uppercase tracking-tight text-white md:text-[34px]">
Sự kiện sắp diễn ra
</h2>
<Link href="/hoat-dong/su-kien" className="text-[#e8c518] text-sm sm:text-base">
<ChevronsRight />
<div className="mt-2.5 h-[4px] w-[60px] rounded-full bg-[#f7b500]" />
</div>
<Link
href="/hoat-dong/su-kien"
className="pt-1.5 text-sm font-semibold text-[#ffd34f] transition-colors hover:text-white"
>
Xem sự kiện
</Link>
</div>
<hr className="border-[#e8c518] mb-4" />
<div className="flex flex-col md:flex-row gap-5">
{isLoading ? (
<div className="flex flex-col justify-center items-center w-full min-h-[180px] sm:min-h-[220px] p-3">
<Spinner />
<div className="grid items-stretch gap-3 xl:grid-cols-[minmax(0,1.02fr)_minmax(270px,0.98fr)]">
<Link
href="/hoat-dong/su-kien"
className="flex h-full flex-col overflow-hidden rounded-[22px] bg-white text-[#20408f] shadow-[0_14px_28px_rgba(10,39,95,0.18)]"
>
<div className="h-[220px] overflow-hidden md:h-[235px] xl:h-[248px]">
<ImageNext
src={featuredEvent.thumbnail?.url ?? "/thumbnail.png"}
alt={featuredEvent.thumbnail?.alt || featuredEvent.title}
width={720}
height={520}
className="h-full w-full object-cover"
/>
</div>
<div className="p-3 pt-2.5">
<h3 className="line-clamp-2 text-[16px] font-extrabold uppercase leading-[1.28] text-[#22459b] md:text-[18px]">
{featuredEvent.title}
</h3>
<p className="mt-1.5 text-[13px] text-[#90a0bd]">{formatEventDate(featuredEvent)}</p>
</div>
) : (
<>
{data?.responseData.rows.slice(0, 1).map((event: EventItem) => (
</Link>
<div className="flex h-full flex-col gap-3">
{sideEvents.slice(0, 4).map((item) => (
<Link
key={event.id}
href={`hoat-dong/su-kien/${event.id}`}
className="flex flex-col w-full md:w-1/2 min-h-[180px] sm:min-h-[220px] gap-3 mb-3 border border-gray-200 bg-white rounded-md p-3"
key={item.id}
href="/hoat-dong/su-kien"
className="flex flex-1 items-center gap-3 rounded-[18px] bg-white/10 p-2.5 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.08)] backdrop-blur-sm transition-colors hover:bg-white/14"
>
<div className="w-full aspect-3/2 overflow-hidden">
<div className="h-[64px] w-[64px] shrink-0 overflow-hidden rounded-[12px]">
<ImageNext
src={`${BASE_URL.imageEndpoint}${event.image}`}
alt={event.name}
width={600}
height={400}
sizes="(max-width:768px) 100vw,50vw"
className="w-full h-full object-cover"
src={item.thumbnail?.url ?? "/thumbnail.png"}
alt={item.thumbnail?.alt || item.title}
width={160}
height={160}
className="h-full w-full object-cover"
/>
</div>
<div className="flex-1">
<p className="text-[#0056b3] font-bold text-xl line-clamp-2">
{event.name}
</p>
<p className="text-gray-500 text-sm my-1">
{dayjs(event.start_time).format("DD/MM/YYYY")}
</p>
<p className="line-clamp-3 text-justify">{stripImagesAndHtml(event.description)}</p>
<div className="min-w-0">
<h4 className="line-clamp-2 text-[15px] font-semibold leading-[1.35] text-white">
{item.title}
</h4>
<p className="mt-1 text-[12px] text-white/78">{formatEventDate(item)}</p>
</div>
</Link>
))}
<div className="w-full md:w-1/2">
{data?.responseData.rows.slice(0, 4).map((event) => (
<CardEvent key={event.id} event={event} />
))}
</div>
</>
)}
</div>
</div>
)
);
}
export default Events
\ No newline at end of file
export default Events;
'use client';
import { useGetNews } from "@/api/endpoints/news";
import { GetNewsResponseType } from "@/api/types/news";
import ImageNext from "@/components/shared/image-next";
import {
type AdminNewsItem,
getAdminNewsSeed,
} from "@/mockdata/admin-news";
import { getHeaderCategorySeed } from "@/mockdata/header-config";
import dayjs from "dayjs";
import { ChevronRight, Mail, Phone } from "lucide-react";
import Link from "next/link";
import { Swiper, SwiperSlide } from "swiper/react";
import { Autoplay, Grid } from "swiper/modules";
import BASE_URL from "@/links/index";
import { Spinner } from "@/components/ui/spinner";
const FALLBACK_CATEGORY_LINK = "/hoat-dong/tin-tuc";
const headerCategoryMap = new Map(
getHeaderCategorySeed().map((item) => [item.id, item.static_link]),
);
const FEATURED_OVERVIEW_LINK =
headerCategoryMap.get("activity-news") ?? FALLBACK_CATEGORY_LINK;
function getFeaturedNewsItems(items: AdminNewsItem[]) {
return items
.filter(
(item) =>
item.type === "tintuc" &&
item.is_featured &&
!item.is_hidden &&
Boolean(item.thumbnail?.url),
)
.slice(0, 3);
}
function getNewsLink(item: AdminNewsItem) {
return headerCategoryMap.get(item.header_category_id) ?? FALLBACK_CATEGORY_LINK;
}
function getBadgeLabel(item: AdminNewsItem) {
if (item.header_category_id === "activity-events") return "Sự kiện";
const firstTag = item.tagsearch_values.find(Boolean);
if (firstTag) return firstTag;
return "Tin VCCI";
}
const featuredNewsItems = getFeaturedNewsItems(getAdminNewsSeed());
function FeaturedNews() {
const { data, isLoading } = useGetNews<GetNewsResponseType>(
{
pageSize: '10',
}
);
const [primaryItem, ...secondaryItems] = featuredNewsItems;
if (!primaryItem) return null;
return (
<section>
<div className="flex items-center justify-center py-8 px-4">
<div className="flex items-center w-full max-w-4xl">
<div className="flex-1 h-px bg-linear-to-r from-transparent via-gray-300 to-gray-400"></div>
<h1 className="px-6 text-[20px] sm:text-[24px] md:text-[28px] uppercase font-bold text-[#063e8e] whitespace-nowrap">
Tin Nổi Bật
</h1>
<div className="flex-1 h-px bg-linear-to-l from-transparent via-gray-300 to-gray-400"></div>
</div>
</div>
{isLoading ? (
<div className="flex justify-center items-center w-full h-64">
<Spinner />
</div>
) : (
<Swiper
modules={[Autoplay]}
autoplay={{ delay: 4000, disableOnInteraction: false }}
loop
breakpoints={{
0: { slidesPerView: 1.1, spaceBetween: 10 },
640: { slidesPerView: 2, spaceBetween: 16 },
1024: { slidesPerView: 3, spaceBetween: 24 },
}}
className="pb-5"
<section className="py-8 md:py-10">
<div className="w-full">
<div className="mb-8 flex items-start justify-between gap-4">
<div>
<h2 className="text-[28px] font-extrabold uppercase tracking-tight text-[#24469c] md:text-[34px]">
Tin nổi bật
</h2>
<div className="mt-3 h-[5px] w-[68px] rounded-full bg-[#f7b500]" />
</div>
<Link
href={FEATURED_OVERVIEW_LINK}
className="inline-flex items-center gap-2 pt-2 text-base font-semibold text-[#2b56c0] transition-colors hover:text-[#173f9f]"
>
{data?.responseData?.rows.map((news) => (
<SwiperSlide key={news.id}>
<span>Xem tất cả</span>
<ChevronRight className="h-4 w-4" />
</Link>
</div>
<div className="grid gap-5 xl:grid-cols-[minmax(0,1.14fr)_minmax(0,0.96fr)]">
<Link
href={`${news.external_link}`}
className="relative block bg-white shadow-md overflow-hidden hover:shadow-lg transition-shadow duration-300"
href={getNewsLink(primaryItem)}
className="group relative block min-h-[260px] overflow-hidden rounded-[24px] bg-[#0d2f5f] shadow-[0_18px_38px_rgba(28,52,120,0.22)] md:min-h-[320px] xl:min-h-[350px]"
>
<div className="relative h-full min-h-[260px] md:min-h-[320px] xl:min-h-[350px]">
<ImageNext
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.title}
src={primaryItem.thumbnail?.url ?? "/thumbnail.png"}
alt={primaryItem.thumbnail?.alt || primaryItem.title}
width={1200}
height={800}
className="absolute inset-0 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-[#26356d] via-[#53669b]/34 to-transparent" />
<div className="relative flex h-full flex-col justify-end p-4 md:p-5">
<span className="mb-2 inline-flex w-fit rounded-[10px] bg-[#ffc400] px-3 py-1 text-sm font-bold text-[#1d3f90]">
{getBadgeLabel(primaryItem)}
</span>
<h3 className="max-w-3xl text-[20px] font-bold leading-[1.28] text-white md:text-[28px] xl:text-[32px]">
{primaryItem.title}
</h3>
<p className="mt-2 text-base font-medium text-white/78 md:text-[17px]">
{dayjs(primaryItem.published_at || primaryItem.created_at).format("DD/MM/YYYY")}
</p>
</div>
</div>
</Link>
<div className="grid gap-4">
<div className="grid gap-4 md:grid-cols-2">
{secondaryItems.map((item) => (
<Link
key={item.id}
href={getNewsLink(item)}
className="group relative block min-h-[195px] overflow-hidden rounded-[20px] bg-[#27447f] shadow-[0_16px_32px_rgba(28,52,120,0.2)] md:min-h-[205px] xl:min-h-[215px]"
>
<div className="relative h-full min-h-[195px] md:min-h-[205px] xl:min-h-[215px]">
<ImageNext
src={item.thumbnail?.url ?? "/thumbnail.png"}
alt={item.thumbnail?.alt || item.title}
width={600}
height={400}
sizes="(max-width:640px) 100vw,(max-width:1024px) 50vw,33vw"
className="w-full aspect-3/2 sm:h-56 md:h-64 object-cover"
height={420}
className="absolute inset-0 h-full w-full object-cover transition-transform duration-500 group-hover:scale-[1.05]"
/>
<div className="absolute bottom-0 left-0 right-0 h-20 md:h-24 bg-linear-to-t from-black/80 to-transparent flex items-center justify-center p-3">
<p className="text-white text-center font-semibold line-clamp-2 text-sm sm:text-base leading-snug">
{news.title}
<div className="absolute inset-0 bg-linear-to-t from-[#5a6796] via-[#405083]/34 to-transparent" />
<div className="relative flex h-full flex-col justify-end p-3.5">
<span className="mb-2 inline-flex w-fit rounded-[10px] bg-[#ffc400] px-3 py-1 text-sm font-bold text-[#1d3f90]">
{getBadgeLabel(item)}
</span>
<h4 className="line-clamp-2 text-[16px] font-bold leading-[1.32] text-white md:text-[17px]">
{item.title}
</h4>
<p className="mt-1.5 text-[15px] font-medium text-white/78 md:text-base">
{dayjs(item.published_at || item.created_at).format("DD/MM/YYYY")}
</p>
</div>
</div>
</Link>
</SwiperSlide>
))}
</Swiper>
)}
</div>
<div className="overflow-hidden rounded-[28px] bg-linear-to-r from-[#214b95] to-[#2b66bb] px-5 py-5 text-white shadow-[0_18px_38px_rgba(28,52,120,0.2)] md:px-7">
<div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<p className="text-[12px] uppercase tracking-[0.4em] text-white/80">
Quảng bá & tiếp cận
</p>
<h3 className="mt-2 max-w-[520px] text-[20px] font-extrabold uppercase leading-[1.02] xl:text-[28px]">
Cộng đồng doanh nghiệp
</h3>
</div>
<div className="w-full max-w-60 rounded-[999px] bg-white px-4 py-3 text-[#173f88] shadow-[0_10px_24px_rgba(8,25,74,0.12)]">
<div className="flex items-center gap-3 text-sm font-medium">
<Mail className="h-5 w-5 shrink-0" />
<span>info@vcci-hcm.org.vn</span>
</div>
<div className="mt-2 flex items-center gap-3 text-sm font-medium">
<Phone className="h-5 w-5 shrink-0" />
<span>+84-28-3932 5171</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
);
}
......
'use client';
import ImageNext from "@/components/shared/image-next";
import memberImages from "@/constants/memberImages";
import { ChevronsRight } from "lucide-react";
import {
getAdminNewsSeed,
} from "@/mockdata/admin-news";
import Link from "next/link";
import { Autoplay } from "swiper/modules";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/grid";
import { GetNewsResponseType, NewsItem } from "@/api/types/news";
import BASE_URL from "@/links/index";
import { useGetNews } from "@/api/endpoints/news";
import { Spinner } from "@/components/ui/spinner";
const Members = () => {
const { data, isLoading } = useGetNews<GetNewsResponseType>(
{
filters: `page_config.code @=ket-noi-hoi-vien`,
}
const memberConnectionItems = getAdminNewsSeed()
.filter(
(item) =>
item.type === "tintuc" &&
!item.is_hidden &&
(item.category_ids.includes("cat-member-connection") ||
item.tagsearch_values.some((tag) => tag.toLowerCase().includes("kết nối hội viên"))),
)
.sort(
(left, right) =>
new Date(right.published_at || right.created_at).getTime() -
new Date(left.published_at || left.created_at).getTime(),
);
function Members() {
const featuredConnection = memberConnectionItems[0];
return (
<section className="flex flex-col lg:flex-row gap-5 pb-10 mb-0">
{/* LEFT: HỘI VIÊN TIÊU BIỂU */}
<aside className="w-full lg:w-1/3 flex-1 bg-[#e8c518] p-5">
<div className="flex justify-between items-center mb-3">
<h2 className="text-xl font-bold uppercase text-[#063e8e]">
<section className="flex flex-col gap-5 pb-8 xl:flex-row xl:items-stretch">
<aside className="flex-1 rounded-[22px] bg-[#f7b500] p-4 shadow-[0_18px_34px_rgba(247,181,0,0.18)] md:p-5">
<div className="flex items-start justify-between gap-3">
<div>
<h2 className="text-[28px] font-extrabold uppercase tracking-tight text-[#20449a] md:text-[34px]">
Hội viên tiêu biểu
</h2>
<div className="mt-2.5 h-[4px] w-[40px] rounded-full bg-white" />
</div>
<Link
href="/danh-ba-hoi-vien"
className="text-[#063e8e] hover:underline text-sm font-medium"
className="pt-1 text-sm font-semibold text-[#1e2f5e] transition-colors hover:text-[#20449a]"
>
<ChevronsRight />
Xem thêm
</Link>
</div>
<hr className="border-[#063e8e] mb-5" />
<div className="mt-4 border-t border-[#e7aa00] pt-5" />
<Swiper
modules={[Autoplay]}
autoplay={{ delay: 4000, disableOnInteraction: false }}
loop
slidesPerView={3}
spaceBetween={16}
breakpoints={{
0: { slidesPerView: 2, spaceBetween: 10 },
640: { slidesPerView: 3, spaceBetween: 16 },
1024: { slidesPerView: 3, spaceBetween: 24 },
}}
className="partner-swiper"
<div className="grid gap-4 sm:grid-cols-3">
{memberImages.slice(0, 3).map((src, index) => (
<div
key={src}
className="rounded-[24px] bg-white p-[7px] shadow-[0_10px_22px_rgba(158,114,0,0.16)]"
>
{memberImages.map((src, i) => (
<SwiperSlide key={i}>
<div className="flex justify-center items-center bg-white rounded-lg shadow p-3">
<div className="flex aspect-[1.06/1] items-center justify-center overflow-hidden rounded-[18px] bg-[#f4f7fb] px-4 py-5">
<ImageNext
src={src}
alt={`member-${i}`}
width={160}
height={160}
sizes="(max-width:640px) 25vw,(max-width:1024px) 15vw,10vw"
className="object-contain w-full h-full"
alt={`Hội viên tiêu biểu ${index + 1}`}
width={320}
height={220}
className="max-h-full max-w-full object-contain"
/>
</div>
</SwiperSlide>
</div>
))}
</Swiper>
</div>
</aside>
{/* RIGHT: KẾT NỐI HỘI VIÊN */}
{isLoading ? (
<div className="flex justify-center items-center w-full h-64">
<Spinner />
</div>
) : (
<aside className="w-full lg:w-[30%] py-5">
<div className="flex justify-between items-center mb-3">
<h2 className="text-xl font-bold uppercase text-[#063e8e]">
<aside className="w-full xl:w-[31%] xl:min-w-[320px]">
<div className="mb-4 flex items-start justify-between gap-3">
<div>
<h2 className="text-[28px] font-extrabold uppercase tracking-tight text-[#24469c] md:text-[34px]">
Kết nối hội viên
</h2>
<div className="mt-2.5 h-[4px] w-[40px] rounded-full bg-[#f7b500]" />
</div>
<hr className="border-[#063e8e] mb-5" />
<Swiper
modules={[Autoplay]}
autoplay={{ delay: 4000, disableOnInteraction: false }}
loop
className="partner-swiper"
</div>
{featuredConnection ? (
<Link
href="/danh-ba-hoi-vien"
className="block overflow-hidden rounded-[20px] shadow-[0_16px_32px_rgba(31,59,124,0.12)]"
>
{data?.responseData.rows.map((news: NewsItem) => (
<SwiperSlide key={news.id}>
<a href={`${news.external_link}`}>
<div className="w-full aspect-3/2 relative overflow-hidden mb-5">
<div className="aspect-[1.25/1] overflow-hidden rounded-[20px]">
<ImageNext
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.title}
width={600}
height={400}
sizes="(max-width:768px) 100vw,50vw"
className="w-full h-full object-cover"
src={featuredConnection.thumbnail?.url ?? "/thumbnail.png"}
alt={featuredConnection.thumbnail?.alt || featuredConnection.title}
width={520}
height={420}
className="h-full w-full object-cover"
/>
<div className="absolute bg-white opacity-90 bottom-5 left-5 right-5 p-5">
<p className="text-[#063e8e] font-semibold text-sm sm:text-base z-10 line-clamp-3">
{news.title}
</p>
</div>
</div>
</a>
</SwiperSlide>
))}
</Swiper>
</Link>
) : null}
</aside>
)}
</section>
);
};
}
export default Members;
import { useGetNews } from "@/api/endpoints/news";
import { GetNewsResponseType, NewsItem } from "@/api/types/news";
'use client';
import ImageNext from "@/components/shared/image-next";
import Link from "next/link";
import BASE_URL from "@/links/index";
import { ChevronsRight } from "lucide-react";
import { useState } from "react";
import stripImagesAndHtml from "@/helpers/stripImageAndHtml";
import CardNews from "./components/card-news";
import { Spinner } from "@/components/ui/spinner";
import {
type AdminNewsItem,
getAdminNewsSeed,
} from "@/mockdata/admin-news";
import dayjs from "dayjs";
import Link from "next/link";
import { useMemo, useState } from "react";
const News = () => {
const [tab, setTab] = useState("all");
const tabs = [
{ id: "all", label: "Tất cả" },
{ id: "tin-vcci", label: "Tin VCCI" },
{ id: "tin-kinh-te", label: "Tin Kinh Tế" },
{ id: "chuyen-de", label: "Chuyên Đề" },
];
const allNewsItems = getAdminNewsSeed().filter(
(item) => item.type === "tintuc" && !item.is_hidden,
);
function getTabLabel(item: AdminNewsItem) {
const tags = item.tagsearch_values.map((tag) => tag.toLowerCase());
if (tags.some((tag) => tag.includes("kinh tế") || tag.includes("vĩ mô"))) {
return "Tin Kinh Tế";
}
if (tags.some((tag) => tag.includes("chuyên đề") || tag.includes("cẩm nang"))) {
return "Chuyên Đề";
}
return "Tin VCCI";
}
function matchesTab(item: AdminNewsItem, tab: string) {
if (tab === "all") return true;
const tags = item.tagsearch_values.map((value) => value.toLowerCase());
if (tab === "tin-vcci") {
return tags.some((tag) => tag.includes("tin vcci") || tag.includes("hợp tác"));
}
if (tab === "tin-kinh-te") {
return tags.some((tag) => tag.includes("kinh tế") || tag.includes("vĩ mô"));
}
const { data: newsSpecial, isLoading: isLoadingSpecial } = useGetNews<GetNewsResponseType>({ pageSize: '1' });
const { data: newsFilters, isLoading: isLoadingFilters } = useGetNews<GetNewsResponseType>(
{
pageSize: '5',
filters: tab === "all" ? `` : `page_config.code @=${tab}`,
if (tab === "chuyen-de") {
return tags.some((tag) => tag.includes("chuyên đề") || tag.includes("cẩm nang"));
}
return true;
}
function News() {
const [tab, setTab] = useState("all");
const filteredItems = useMemo(
() => allNewsItems.filter((item) => matchesTab(item, tab)),
[tab],
);
const featuredArticle = filteredItems[0] ?? allNewsItems[0];
const listArticles = filteredItems.slice(1, 5);
if (!featuredArticle) return null;
return (
<div className="flex-1">
<div className="flex justify-between items-center">
<Link
href="/thong-tin-truyen-thong/tin-vcci/"
className="text-[18px] sm:text-[20px] font-semibold uppercase text-[#063e8e]"
>
<div className="mb-6 flex flex-col gap-4 xl:flex-row xl:items-start xl:justify-between">
<div>
<h2 className="text-[28px] font-extrabold uppercase tracking-tight text-[#24469c] md:text-[34px]">
Tin tức
</Link>
<Link
href="/thong-tin-truyen-thong/tin-vcci/"
className="text-[#063e8e] text-sm sm:text-base"
>
<ChevronsRight />
</Link>
</h2>
<div className="mt-3 h-[5px] w-[68px] rounded-full bg-[#f7b500]" />
</div>
<hr className="border-[#063e8e] mb-4" />
<div className="flex flex-col md:flex-row gap-5">
{isLoadingSpecial ? (
<div className="flex justify-center items-center flex-col w-full md:w-1/2 min-h-[180px] sm:min-h-[220px] gap-3 mb-3">
<Spinner />
<div className="flex flex-wrap gap-3 xl:justify-end">
{tabs.map((item) => {
const active = item.id === tab;
return (
<button
key={item.id}
type="button"
onClick={() => setTab(item.id)}
className={`rounded-full px-5 py-2.5 text-[14px] font-semibold transition-all ${
active
? "bg-[#1f5ba9] text-white shadow-[0_10px_20px_rgba(31,91,169,0.18)]"
: "bg-[#f4f7fb] text-[#7f8eab] hover:bg-[#eaf0f8]"
}`}
>
{item.label}
</button>
);
})}
</div>
</div>
) : (
newsSpecial?.responseData.rows
.slice(0, 1)
.map((news: NewsItem) => (
<div className="grid gap-4 xl:grid-cols-[minmax(0,1.02fr)_minmax(320px,0.98fr)]">
<div>
<Link
key={news.id}
href={`${news.external_link}`}
className="flex flex-col w-full md:w-1/2 min-h-[180px] sm:min-h-[220px] gap-3 mb-3 bg-white"
href="/hoat-dong/tin-tuc"
className="block h-full overflow-hidden rounded-[22px] border border-[#dbe4f2] bg-white shadow-[0_8px_24px_rgba(31,59,124,0.08)]"
>
<div className="w-full aspect-3/2 overflow-hidden">
<div className="aspect-[1.75/1] overflow-hidden">
<ImageNext
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.title}
width={600}
height={400}
sizes="(max-width:768px) 100vw,50vw"
className="w-full h-full object-cover"
src={featuredArticle.thumbnail?.url ?? "/thumbnail.png"}
alt={featuredArticle.thumbnail?.alt || featuredArticle.title}
width={720}
height={580}
className="h-full w-full object-cover"
/>
</div>
<div className="flex-1 p-5 pt-1">
<p className="text-[#063E8E] font-bold pb-2 text-xl line-clamp-2">
{news.title}
<div className="space-y-1.5 p-3">
<span className="inline-flex text-[14px] font-bold text-[#e2a500]">
{getTabLabel(featuredArticle)}
</span>
<h3 className="line-clamp-2 text-[16px] font-bold leading-[1.28] text-[#20408f] md:text-[17px]">
{featuredArticle.title}
</h3>
<p className="line-clamp-2 text-[13px] leading-[1.45] text-[#6c7b96]">
{stripImagesAndHtml(featuredArticle.summary)}
</p>
<p className="text-[14px] text-[#8a9bb6]">
{dayjs(featuredArticle.published_at || featuredArticle.created_at).format("DD/MM/YYYY")}
</p>
<p className="line-clamp-4 text-justify">{stripImagesAndHtml(news.description)}</p>
</div>
</Link>
))
)}
<div className="w-full md:w-1/2">
<div className="flex flex-wrap gap-2 sm:gap-3 mb-5">
<button
className={`flex-1 py-[3px] text-sm transition-colors cursor-pointer ${tab === "all"
? " bg-[#d3d3d3] text-[#063e8e] font-semibold"
: "border-gray-300 text-[#363636] bg-[#e8e8e8] hover:bg-[#e8e8e8] hover:text-[#063e8e] font-semibold"
}`}
onClick={() => setTab("all")}>
Tất cả
</button>
<button
className={`flex-1 py-[3px] text-[14px] transition-colors cursor-pointer ${`tin-vcci` === tab
? "bg-[#d3d3d3] text-[#063e8e] font-semibold"
: "border-gray-300 text-[#363636] bg-[#e8e8e8] hover:bg-[#e8e8e8] hover:text-[#063e8e] font-semibold"
}`}
onClick={() => setTab("tin-vcci")}
>
Tin VCCI
</button>
<button
className={`flex-1 py-[3px] text-[14px] transition-colors cursor-pointer ${`tin-kinh-te` === tab
? "bg-[#d3d3d3] text-[#063e8e] font-semibold"
: "border-gray-300 text-[#363636] bg-[#e8e8e8] hover:bg-[#e8e8e8] hover:text-[#063e8e] font-semibold"
}`}
onClick={() => setTab("tin-kinh-te")}
>
Tin Kinh Tế
</button>
<button
className={`flex-1 py-[3px] text-[14px] transition-colors cursor-pointer ${`chuyen-de` === tab
? "bg-[#d3d3d3] text-[#063e8e] font-semibold"
: "border-gray-300 text-[#363636] bg-[#e8e8e8] hover:bg-[#e8e8e8] hover:text-[#063e8e] font-semibold"
}`}
onClick={() => setTab("chuyen-de")}
>
Chuyên Đề
</button>
</div>
{isLoadingFilters ? (
<div className="flex justify-center py-10">
<Spinner />
<div className="xl:flex xl:h-full xl:flex-col">
<div className="space-y-3 xl:flex xl:flex-1 xl:flex-col">
{listArticles.map((news) => (
<Link
key={news.id}
href="/hoat-dong/tin-tuc"
className="block rounded-[18px] border border-[#dbe4f2] bg-white px-4 py-2.5 shadow-[0_8px_24px_rgba(31,59,124,0.08)] transition-all hover:-translate-y-0.5 hover:shadow-[0_14px_28px_rgba(31,59,124,0.12)] xl:flex-1"
>
<h4 className="line-clamp-2 text-[15px] font-bold leading-[1.28] text-[#21408f]">
{news.title}
</h4>
<p className="mt-1 text-[13px] text-[#8a9bb6]">
{dayjs(news.published_at || news.created_at).format("DD/MM/YYYY")}
</p>
</Link>
))}
</div>
) : (
newsFilters?.responseData?.rows.slice(0, 4).map((news) => (
<CardNews key={news.id} news={news} />
))
)}
</div>
</div>
</div>
......
import { useGetNews } from "@/api/endpoints/news";
import { GetNewsResponseType, NewsItem } from "@/api/types/news";
import ImageNext from "@/components/shared/image-next";
import { Spinner } from "@/components/ui/spinner";
import { ChevronsRight } from "lucide-react";
'use client';
import {
type AdminNewsItem,
getAdminNewsSeed,
} from "@/mockdata/admin-news";
import dayjs from "dayjs";
import { ChevronRight } from "lucide-react";
import Link from "next/link";
import BASE_URL from "@/links/index";
import CardNews from "./card-news";
const PolicyAndLaws = () => {
const { data, isLoading } = useGetNews<GetNewsResponseType>(
{
pageSize: '5',
filters: `page_config.code @=phap-luat`,
}
const policyItems = getAdminNewsSeed()
.filter(
(item) =>
item.type === "tintuc" &&
!item.is_hidden &&
(item.category_ids.includes("cat-policy-law") ||
item.category_ids.includes("cat-policy") ||
item.tagsearch_values.some((tag) => {
const normalized = tag.toLowerCase();
return normalized.includes("chính sách") || normalized.includes("pháp luật");
})),
)
.sort(
(left, right) =>
new Date(right.published_at || right.created_at).getTime() -
new Date(left.published_at || left.created_at).getTime(),
);
function formatPublishDate(item: AdminNewsItem) {
return dayjs(item.published_at || item.created_at).format("DD/MM/YYYY");
}
function PolicyAndLaws() {
const [featuredItem, ...listItems] = policyItems;
if (!featuredItem) return null;
return (
<div className="flex-1">
<div className="flex justify-between items-center">
<section className="flex-1">
<div className="mb-4 flex items-center justify-between gap-3">
<div>
<h2 className="text-[28px] font-extrabold uppercase tracking-tight text-[#24469c] md:text-[34px]">
Chính sách & pháp luật
</h2>
<div className="mt-2.5 h-[4px] w-[40px] rounded-full bg-[#f7b500]" />
</div>
<Link
href="/thong-tin-truyen-thong/phap-luat"
className="text-[18px] sm:text-[20px] font-bold uppercase text-[#063e8e]"
className="text-[#24469c] transition-colors hover:text-[#1b55a1]"
>
Chính sách & pháp luật
<ChevronRight className="h-5 w-5" />
</Link>
</div>
<div className="space-y-2.5">
{[featuredItem, ...listItems.slice(0, 2)].map((item, index) => (
<Link
key={item.id}
href="/thong-tin-truyen-thong/phap-luat"
className="text-[#063e8e] text-sm sm:text-base"
className={`flex gap-3 rounded-[14px] px-0.5 py-1 transition-colors hover:bg-[#f8fafe] ${
index === 0 ? "pt-0.5" : ""
}`}
>
<ChevronsRight />
</Link>
</div>
<hr className="border-[#063e8e] mb-4" />
<div className="pt-2">
{isLoading ? (
<div className="container w-full h-[80vh] flex justify-center items-center">
<Spinner />
</div>
) : (
<>
{data?.responseData.rows
.slice(0, 1)
.map((news: NewsItem) => (
<Link key={news.id} href={`${news.external_link}`}>
<div className="w-full aspect-3/2 relative overflow-hidden mb-5">
<ImageNext
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.title}
width={600}
height={400}
sizes="(max-width:768px) 100vw,50vw"
className="w-full h-full object-cover"
/>
<div className="absolute bg-white opacity-80 bottom-5 left-5 right-5 p-5">
<p className="text-[#063e8e] font-semibold text-sm sm:text-base z-10 line-clamp-3">
{news.title}
</p>
</div>
<span className="mt-1 h-[40px] w-[2px] shrink-0 rounded-full bg-[#f7b500]" />
<div className="min-w-0">
<h3 className="line-clamp-2 text-[15px] leading-[1.45] text-[#264798] md:text-[16px]">
{item.title}
</h3>
<p className="mt-1.5 text-[13px] text-[#9aa8c1]">{formatPublishDate(item)}</p>
</div>
</Link>
))}
{data?.responseData.rows.slice(0, 3).map((news) => (
<CardNews key={news.id} news={news} />
))}
</>
)}
</div>
</div>
</section>
);
}
......
'use client';
import ImageNext from "@/components/shared/image-next";
import Link from "next/link";
const quickLinks = [
{
href: "https://vcci-hcm.org.vn/lien-ket-nhanh/doanh-nghiep-kien-nghi-ve-chinh-sach-va-phap-luat/",
label: "Doanh nghiệp kiến nghị về chính sách và pháp luật",
},
{
href: "https://vcci-hcm.org.vn/lien-ket-nhanh/cam-nang-huong-dan-dau-tu-kinh-doanh-tai-viet-nam-2023/",
label: "Cẩm nang hướng dẫn đầu tư kinh doanh tại Việt Nam",
},
];
function QuickLinks() {
return (
<aside className="w-full lg:w-[30%]">
<div className="flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-semibold uppercase text-[#063e8e]">
<aside className="w-full xl:grid xl:w-[32%] xl:grid-rows-[0.74fr_0.88fr] xl:gap-4">
<div className="rounded-[22px] border border-[#dbe4f2] bg-white p-4 shadow-[0_8px_24px_rgba(31,59,124,0.08)] xl:h-full">
<h2 className="text-[28px] md:text-[34px] font-extrabold uppercase tracking-tight text-[#24469c]">
Liên kết nhanh
</h2>
</div>
<hr className="border-[#063e8e] mb-4" />
<div className="space-y-2 text-[#063e8e] text-sm md:text-base pb-10">
<div>
<div className="mt-3 h-[5px] w-[68px] rounded-full bg-[#f7b500]" />
<div className="mt-4 space-y-2.5">
{quickLinks.map((item) => (
<Link
className="text-[#363636]"
href="https://vcci-hcm.org.vn/lien-ket-nhanh/cam-nang-huong-dan-dau-tu-kinh-doanh-tai-viet-nam-2023/"
key={item.href}
href={item.href}
className="flex items-start gap-3 text-[15px] leading-[1.32] text-[#556684] transition-colors hover:text-[#21408f]"
>
🔗 Cẩm nang hướng dẫn đầu tư kinh doanh tại Việt Nam
<span className="mt-1 text-[#e2a500]"></span>
<span>{item.label}</span>
</Link>
))}
</div>
</div>
<div>
<Link
className="text-[#363636]"
href="https://vcci-hcm.org.vn/lien-ket-nhanh/doanh-nghiep-kien-nghi-ve-chinh-sach-va-phap-luat/"
href="https://hardwaretools.com.vn/"
className="mt-4 block overflow-hidden rounded-[28px] shadow-[0_12px_28px_rgba(31,59,124,0.14)] xl:mt-0 xl:h-full"
>
🔗 Doanh nghiệp kiến nghị về chính sách và pháp luật
</Link>
</div>
</div>
<div>
<Link href="https://hardwaretools.com.vn/">
<div className="aspect-[1.55/1] overflow-hidden xl:h-full xl:aspect-auto">
<ImageNext
src="/home/20-2048x1365.webp"
alt="banner"
alt="Liên kết nhanh"
width={2048}
height={1365}
className="h-full w-full object-cover"
/>
</Link>
</div>
</Link>
</aside>
);
}
......
'use client';
import ImageNext from "@/components/shared/image-next";
import partnerImages from "@/constants/partnerImages";
import { ChevronsRight } from "lucide-react";
import { ChevronRight, Play } from "lucide-react";
import Link from "next/link";
import { Autoplay, Grid } from "swiper/modules";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/grid";
const videos = [
{
embedSrc: "https://www.youtube.com/embed/J0Iz0iGuAXY",
title: "VCCI-HCM 2025 IN REVIEW (ENGLISH VERSION)",
thumbnail:
"https://img.youtube.com/vi/J0Iz0iGuAXY/hqdefault.jpg",
},
{
embedSrc: "https://www.youtube.com/embed/_OnnGWv2ehM",
title: "Hội nghị Hội viên VCCI - Gala Mừng Xuân 2026",
thumbnail:
"https://img.youtube.com/vi/_OnnGWv2ehM/hqdefault.jpg",
},
];
const VideoAndPartners = () => {
function VideoAndPartners() {
return (
<section className="flex flex-col lg:flex-row gap-5 pb-10">
{/* LEFT: VIDEO */}
<div className="flex flex-col flex-1">
<div className="flex justify-between items-center mb-3">
<h2 className="text-xl font-bold uppercase text-[#063e8e]">Video</h2>
<section className="flex flex-col gap-6 pb-10 xl:flex-row xl:items-start">
<div className="flex-1">
<div className="mb-5 flex items-start justify-between gap-3">
<div>
<h2 className="text-[28px] font-extrabold uppercase tracking-tight text-[#24469c] md:text-[34px]">
Video
</h2>
<div className="mt-2.5 h-[4px] w-[40px] rounded-full bg-[#f7b500]" />
</div>
<Link
href="/video"
className="text-[#063e8e] hover:underline text-sm font-medium"
className="pt-1 text-[#24469c] transition-colors hover:text-[#1b55a1]"
>
<ChevronsRight />
<ChevronRight className="h-5 w-5" />
</Link>
</div>
<hr className="border-[#063e8e] mb-5" />
<div className="flex flex-col md:flex-row gap-4 md:gap-6">
{[
{
src: "https://www.youtube.com/embed/J0Iz0iGuAXY",
title: "VCCI-HCM 2024 IN REVIEW (ENGLISH VERSION)",
},
{
src: "https://www.youtube.com/embed/_OnnGWv2ehM",
title: "Hội nghị Hội viên VCCI - Gala Mừng Xuân Ất Tỵ 2025",
},
].map((video, i) => (
<div key={i} className="w-full md:w-1/2">
<div className="aspect-video rounded-lg overflow-hidden shadow">
<iframe
className="w-full h-full font-bold"
src={video.src}
title={video.title}
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerPolicy="strict-origin-when-cross-origin"
allowFullScreen
<div className="grid gap-4 md:grid-cols-2">
{videos.map((video) => (
<a
key={video.embedSrc}
href={video.embedSrc.replace("/embed/", "/watch?v=")}
target="_blank"
rel="noreferrer"
className="overflow-hidden rounded-[16px] border border-[#e5ebf4] bg-white shadow-[0_10px_22px_rgba(31,59,124,0.08)] transition-all hover:-translate-y-0.5 hover:shadow-[0_16px_30px_rgba(31,59,124,0.12)]"
>
<div className="group relative aspect-[1.95/1] overflow-hidden">
<ImageNext
src={video.thumbnail}
alt={video.title}
width={640}
height={440}
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-[1.03]"
/>
<div className="absolute inset-0 bg-black/18" />
<div className="absolute inset-0 flex items-center justify-center">
<span className="flex h-12 w-12 items-center justify-center rounded-full bg-white/92 text-[#2a4ea3] shadow-[0_10px_26px_rgba(0,0,0,0.18)]">
<Play className="ml-1 h-5 w-5 fill-current" />
</span>
</div>
</div>
<p className="mt-2 text-sm text-gray-700 font-medium">
<div className="px-4 py-2.5">
<p className="line-clamp-2 text-[14px] font-semibold leading-[1.32] text-[#264798] md:text-[15px]">
{video.title}
</p>
</div>
</a>
))}
</div>
</div>
{/* RIGHT: ĐỐI TÁC */}
<aside className="w-full lg:w-[30%]">
<div className="flex justify-between items-center mb-3">
<h2 className="text-xl font-bold uppercase text-[#063e8e]">
<aside className="w-full xl:w-[43%]">
<div className="mb-5 flex items-start justify-between gap-3">
<div>
<h2 className="text-[28px] font-extrabold uppercase tracking-tight text-[#24469c] md:text-[34px]">
Đối tác
</h2>
<div className="mt-2.5 h-[4px] w-[40px] rounded-full bg-[#f7b500]" />
</div>
</div>
<hr className="border-[#063e8e] mb-5" />
<div className="pb-10">
<Swiper
modules={[Autoplay, Grid]}
autoplay={{ delay: 4000, disableOnInteraction: false }}
loop
grid={{ rows: 2, fill: "row" }}
slidesPerView={3}
spaceBetween={16}
breakpoints={{
0: { slidesPerView: 3, spaceBetween: 10, grid: { rows: 2 } },
640: { slidesPerView: 3, spaceBetween: 16, grid: { rows: 2 } },
1024: { slidesPerView: 3, spaceBetween: 24, grid: { rows: 2 } },
}}
className="partner-swiper"
<div className="grid grid-cols-2 gap-4 sm:grid-cols-3">
{partnerImages.slice(0, 6).map((src, index) => (
<div
key={src}
className="flex h-[96px] items-center justify-center rounded-[14px] border border-[#edf1f7] bg-white px-5 py-4 shadow-[0_8px_20px_rgba(31,59,124,0.05)]"
>
{partnerImages.map((src, i) => (
<SwiperSlide key={i}>
<div className="flex justify-center items-center bg-white rounded-lg shadow p-3 w-[120px] h-[120px]">
<ImageNext
src={src}
alt={`partner-${i}`}
width={120}
height={120}
className="object-contain w-full h-full"
alt={`Đối tác ${index + 1}`}
width={140}
height={72}
className="max-h-full w-full object-contain"
/>
</div>
</SwiperSlide>
))}
</Swiper>
</div>
</aside>
</section>
);
};
}
export default VideoAndPartners;
'use client'
import Link from 'next/link'
import ImageNext from '@/components/shared/image-next';
import FeaturedNews from "./components/featured-news";
import QuickLinks from "./components/quick-links";
import News from "./components/news";
......@@ -18,9 +16,9 @@ const Page = () => {
<div>
<Banner />
{/* contents */}
<div className="container mx-auto px-3 sm:px-6 lg:px-10 space-y-12">
<div className="container mx-auto px-3 sm:px-6 lg:px-10 space-y-6">
<FeaturedNews />
<div>
{/* <div>
<Link href="https://hardwaretools.com.vn/">
<ImageNext
src="/home/Standard-Banner-1-2024.png.webp"
......@@ -29,21 +27,21 @@ const Page = () => {
height={720}
/>
</Link>
</div>
</div> */}
<section className="flex flex-col lg:flex-row gap-5 pb-10 mb-0">
<section className="flex flex-col lg:flex-row pb-16 gap-5 mb-0">
<News />
<QuickLinks />
</section >
<section className="flex flex-col lg:flex-row gap-5 pb-10 mb-0" >
<section className="flex flex-col gap-5 xl:flex-row xl:items-stretch" >
<Events />
<EventsCalendar />
</section >
<div className="flex flex-col lg:flex-row gap-5 pb-10 mb-0" >
<div className="flex flex-col flex-1">
<div>
{/* <div>
<Link href="https://vcci-hcm.org.vn/wp-content/uploads/2022/11/MEDIA-KIT_VCCI-HCM-2022-Final.pdf">
<ImageNext
src="/home/Standard-Banner-1-2024.png.webp"
......@@ -52,7 +50,7 @@ const Page = () => {
height={720}
/>
</Link>
</div>
</div> */}
<section className="flex flex-col md:flex-row gap-5 pt-8">
<BusinessOpportunities />
......@@ -60,7 +58,7 @@ const Page = () => {
</section>
</div>
<div className="w-full lg:w-[30%] justify-center items-start flex">
{/* <div className="w-full lg:w-[30%] justify-center items-start flex">
<Link href="https://smartgara.ecaraid.com/">
<ImageNext
src="/home/eCarAid_web_banner_600x400.webp"
......@@ -69,7 +67,7 @@ const Page = () => {
height={400}
/>
</Link>
</div>
</div> */}
</div >
<Members />
......
"use client";
import React, { useRef, useState } from "react";
import {
Facebook,
Linkedin,
Mail,
MailCheck,
MapPin,
Phone,
Printer,
SendHorizonal,
Twitter,
Youtube,
} from "lucide-react";
import Image from "next/image";
import vietnamMap from "@/assets/vietnam-map-white.png";
import Link from "next/link";
const socialLinks = [
{ icon: <Facebook className="h-5 w-5" />, link: "https://www.facebook.com/VCCIHCMC/" },
{ icon: <Twitter className="h-5 w-5" />, link: "https://twitter.com/VCCI_HCM" },
{ icon: <Youtube className="h-5 w-5" />, link: "https://www.youtube.com/user/VCCIHCMC" },
{
icon: <Linkedin className="h-5 w-5" />,
link: "https://www.linkedin.com/company/vietnam-chamber-of-commerce-and-industry-ho-chi-minh-city-branch-vcci-hcm-?trk=biz-companies-cym",
},
];
const quickLinks = [
{ label: "Giới thiệu", href: "/gioi-thieu" },
{ label: "Hội viên", href: "/danh-ba-hoi-vien" },
{ label: "Hoạt động", href: "/hoat-dong/tin-tuc" },
{ label: "Xúc tiến Thương mại", href: "/xuc-tien-thuong-mai/co-hoi/" },
];
function Footer() {
const emailRef = useRef<HTMLInputElement>(null);
const checkBoxRef = useRef<HTMLInputElement>(null);
const [emailError, setEmailError] = useState(false);
const [chechError, setCheckError] = useState(false);
const [checkError, setCheckError] = useState(false);
const handleSubmit = () => {
if (!checkBoxRef.current?.checked) setCheckError(true);
else setCheckError(false);
if (emailRef.current?.value === "") setEmailError(true);
else setEmailError(false);
if (!checkBoxRef.current?.checked) setCheckError(true);
else setCheckError(false);
};
return (
<div className="overflow-hidden w-full">
<div className="py-5 xl:p-5 bg-[#e3e3e3]">
<div className="container w-full flex flex-col lg:flex-row m-auto lg:flex-nowrap flex-wrap relative gap-10">
<div className="z-10 w-full lg:w-1/3 flex flex-col gap-5 p-3 sm:p-5">
<h2 className="text-[#063E8E] text-[20px] font-bold text-left">
ĐĂNG KÝ NHẬN THÔNG TIN VCCI
<footer className="w-full bg-[#202f67] text-white">
<div className="container mx-auto px-5 py-10 sm:px-6 lg:px-10 lg:py-12">
<div className="grid gap-10 lg:grid-cols-[1.15fr_1.05fr_0.9fr]">
<div>
<h2 className="text-xl md:text-2xl font-extrabold uppercase tracking-tight">
Đăng ký nhận thông tin VCCI
</h2>
<div className="h-0.5 w-14 bg-[#063e8e] mx-0"></div>
<div className="mt-2.5 h-[4px] w-[48px] rounded-full bg-[#f7b500]" />
<div className="flex flex-col gap-2">
<div className="flex gap-2 items-center w-full">
<div className="mt-5">
<div className="flex w-full max-w-[350px] gap-2">
<input
ref={emailRef}
className="h-12 flex-1 px-3 outline-hidden bg-white rounded-sm text-[14px] w-full"
className="h-12 flex-1 rounded-[4px] border border-[#31458d] bg-[#29418f] px-4 text-[15px] text-white placeholder:text-[#84a1ef] outline-hidden"
type="email"
placeholder="Nhập email của bạn"
/>
<button
onClick={handleSubmit}
className="group w-14 h-12 flex items-center justify-center cursor-pointer bg-white rounded-sm text-[#063e8e]"
className="flex h-12 w-12 items-center justify-center rounded-[4px] bg-[#f7b500] text-[#203067] transition-colors hover:bg-[#ffca30]"
>
<Mail size={20} className="group-hover:hidden" />
<MailCheck size={20} className="group-hover:block hidden" />
<SendHorizonal className="h-5 w-5" />
</button>
</div>
{emailError && (
<p className="text-[#F56C6C] text-[12px]">
Thông tin bắt buộc
</p>
)}
<div className="flex items-center gap-2">
<input ref={checkBoxRef} type="checkbox" id="check" />
<label className="text-[14px] text-[#636363]" htmlFor="check">
{emailError ? (
<p className="mt-2 text-[12px] text-[#ff9b9b]">Thông tin bắt buộc</p>
) : null}
<div className="mt-3 flex items-center gap-2">
<input
ref={checkBoxRef}
type="checkbox"
id="footer-check"
className="h-4 w-4 rounded border-white/30 bg-transparent accent-[#f7b500]"
/>
<label
className="text-[13px] text-[#86b8ff]"
htmlFor="footer-check"
>
Đồng ý với Điều khoản nhận email
</label>
</div>
{chechError && (
<p className="text-[#F56C6C] text-[12px]">
{checkError ? (
<p className="mt-2 text-[12px] text-[#ff9b9b]">
Bạn cần đồng ý với Điều khoản nhận email
</p>
)}
) : null}
</div>
</div>
<div className="w-full lg:w-1/3 flex flex-col gap-5 p-3 sm:p-5">
<h2 className="text-[#063E8E] text-[20px] font-bold text-left">
LIÊN HỆ
<div>
<h2 className="text-xl md:text-2xl font-extrabold uppercase tracking-tight">
Liên hệ
</h2>
<div className="h-0.5 w-14 bg-[#063e8e] mx-0"></div>
<div className="mt-2.5 h-[4px] w-[48px] rounded-full bg-[#f7b500]" />
<p className="text-[14px] font-semibold text-justify text-[#363636]">
<div className="mt-5 space-y-4">
<p className="max-w-[420px] text-[16px] font-semibold leading-[1.5] text-[#dce7ff]">
LIÊN ĐOÀN THƯƠNG MẠI & CÔNG NGHIỆP VIỆT NAM - CHI NHÁNH KHU VỰC THÀNH PHỐ HỒ CHÍ MINH
</p>
<div className="flex flex-col items-start gap-3">
<div className="flex items-center gap-2 text-[15px] text-[#363636] font-[500]">
<MapPin size={16} className="text-[#124588]" />
<span>171 Võ Thị Sáu, Phường Xuân Hoà, TP. HCM</span>
<div className="space-y-2.5 text-[15px] text-[#c7d8ff]">
<div className="flex items-start gap-3">
<MapPin className="mt-0.5 h-4 w-4 shrink-0 text-[#f7b500]" />
<span>171 Võ Thị Sáu, Phường Xuân Hòa, TP. HCM</span>
</div>
<div className="flex items-center gap-2 text-[15px] text-[#363636] font-[500]">
<Phone size={16} className="text-[#124588]" />
<div className="flex items-center gap-3">
<Phone className="h-4 w-4 shrink-0 text-[#f7b500]" />
<span>+84 28 3932 6598</span>
</div>
<div className="flex items-center gap-2 text-[15px] text-[#363636] font-[500]">
<Printer size={16} className="text-[#124588]" />
<div className="flex items-center gap-3">
<Printer className="h-4 w-4 shrink-0 text-[#f7b500]" />
<span>+84 28 3932 5472</span>
</div>
<div className="flex items-center gap-2 text-[15px] text-[#363636] font-[500]">
<Mail size={16} className="text-[#124588]" />
<a href="mailto:info@vcci-hcm.org.vn">
info@vcci-hcm.org.vn
</a>
<div className="flex items-center gap-3">
<Mail className="h-4 w-4 shrink-0 text-[#f7b500]" />
<a href="mailto:info@vcci-hcm.org.vn">info@vcci-hcm.org.vn</a>
</div>
</div>
</div>
</div>
<div className="w-full lg:w-1/3 flex flex-col gap-5 p-3 sm:p-5">
<h2 className="text-[#063E8E] text-[20px] font-bold text-left">
KẾT NỐI
<div>
<h2 className="text-xl font-extrabold uppercase tracking-tight md:text-2xl">
Kết nối
</h2>
<div className="h-[2px] w-14 bg-[#063e8e] mx-0"></div>
<div className="w-full overflow-hidden rounded-md">
<iframe
className="w-full sm:h-[140px]"
src="https://www.facebook.com/plugins/page.php?href=https%3A%2F%2Fwww.facebook.com%2FVCCIHCMC%3Fref%3Dembed_page&tabs=&width=340&height=130&small_header=false&adapt_container_width=true&hide_cover=false&show_facepile=false"
style={{ border: "none", overflow: "hidden" }}
scrolling="no"
frameBorder="0"
allowFullScreen={true}
allow="autoplay; clipboard-write; encrypted-media; picture-in-picture; web-share"
></iframe>
</div>
<div className="flex gap-3 justify-start">
{[
{ icon: <Facebook size={20} />, link: "https://www.facebook.com/VCCIHCMC/" },
{ icon: <Twitter size={20} />, link: "https://twitter.com/VCCI_HCM" },
{ icon: <Youtube size={20} />, link: "https://www.youtube.com/user/VCCIHCMC" },
{ icon: <Linkedin size={20} />, link: "https://www.linkedin.com/company/vietnam-chamber-of-commerce-and-industry-ho-chi-minh-city-branch-vcci-hcm-?trk=biz-companies-cym" },
].map((s, i) => (
<div className="mt-2.5 h-[4px] w-[48px] rounded-full bg-[#f7b500]" />
<div className="mt-5 flex flex-wrap gap-3">
{socialLinks.map((item) => (
<a
key={i}
href={s.link}
key={item.link}
href={item.link}
target="_blank"
className="h-[38px] w-[38px] sm:h-[42px] sm:w-[42px] bg-[#124588] text-white rounded-full flex items-center justify-center hover:opacity-90 transition"
rel="noreferrer"
className="flex h-11 w-11 items-center justify-center rounded-full bg-[#2a4ec4] text-white transition-colors hover:bg-[#3b60da]"
>
{s.icon}
{item.icon}
</a>
))}
</div>
</div>
<div className="z-0 absolute -left-20 -top-20 hidden xl:block">
<Image className="size-[500px] object-contain" src={vietnamMap} alt="" />
<div className="footer-bg-pin" style={{ top: "144px", left: "145px" }}></div>
<div className="footer-bg-pin" style={{ top: "238px", left: "260px" }}></div>
<div className="footer-bg-pin" style={{ top: "342px", left: "162px" }}></div>
<div className="footer-bg-pin" style={{ top: "395px", left: "215px" }}></div>
<div className="mt-5 space-y-2 text-[15px] text-[#c7d8ff]">
{quickLinks.map((item) => (
<Link
key={item.href}
href={item.href}
className="block transition-colors hover:text-white"
>
{item.label}
</Link>
))}
</div>
</div>
</div>
<div className="bg-[#032248] h-20 flex items-center justify-center">
<div className="container w-full p-5 text-left">
<p className="text-[14px] text-white text-center lg:text-left">
<div className="mt-10 border-t border-[#2946a3] pt-5 text-center text-[14px] text-[#62a7ff]">
© Bản quyền VCCI-HCM | All rights reserved
</p>
</div>
</div>
<style jsx>{`
@keyframes newpulse {
0% {
transform: scale(1);
opacity: 0.8;
}
100% {
transform: scale(10);
opacity: 0;
}
}
.footer-bg-pin {
position: absolute;
z-index: 2;
width: 6px;
height: 6px;
background-color: #facc15;
border-radius: 50%;
}
.footer-bg-pin::before {
content: "";
position: absolute;
inset: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.4);
transform-origin: center;
animation: newpulse 2s infinite ease-in-out;
z-index: -1;
}
`}</style>
</div>
</footer>
);
}
......
......@@ -189,7 +189,7 @@ const newsSeed: AdminNewsItem[] = [
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-news", "cat-activity"],
tagsearch_values: ["Doanh nghiệp hội viên", "Chuyển đổi số"],
tagsearch_values: ["Tin VCCI", "Doanh nghiệp hội viên", "Chuyển đổi số"],
is_featured: true,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
......@@ -236,7 +236,7 @@ const newsSeed: AdminNewsItem[] = [
type: "tintuc",
header_category_id: "activity-events",
category_ids: ["cat-event"],
tagsearch_values: ["Hội thảo", "Đăng ký"],
tagsearch_values: ["Sự kiện", "Đăng ký"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[3]),
is_hidden: false,
......@@ -306,6 +306,916 @@ const newsSeed: AdminNewsItem[] = [
},
],
},
{
id: "admin-news-04",
title: "Diễn đàn xúc tiến thương mại khu vực phía Nam thu hút hơn 300 doanh nghiệp tham dự",
slug: "dien-dan-xuc-tien-thuong-mai-khu-vuc-phia-nam-thu-hut-hon-300-doanh-nghiep-tham-du",
summary:
"<p>Chương trình quy tụ doanh nghiệp sản xuất, logistics và các đơn vị hỗ trợ xuất khẩu nhằm tạo mạng lưới kết nối giao thương thực chất.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-news", "cat-activity"],
tagsearch_values: ["Tin Kinh Tế", "Xúc tiến thương mại", "Kết nối giao thương"],
is_featured: true,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
created_at: "2026-05-12T08:20:00.000Z",
updated_at: "2026-05-12T10:00:00.000Z",
published_at: "2026-05-12T08:20",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "Trung tâm Hội chợ và Triển lãm Sài Gòn",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-04-a",
type: "text",
position: 1,
content:
"<p>Sự kiện nhấn mạnh nhu cầu tạo chuỗi kết nối ngắn, nhanh và có khả năng chuyển hóa thành cơ hội kinh doanh ngay sau chương trình.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-05",
title: "Bản tin nhanh: doanh nghiệp hội viên tăng tốc chuyển đổi số trong khâu bán hàng và chăm sóc khách hàng",
slug: "ban-tin-nhanh-doanh-nghiep-hoi-vien-tang-toc-chuyen-doi-so-trong-khau-ban-hang-va-cham-soc-khach-hang",
summary:
"<p>Nhiều mô hình ứng dụng CRM, dashboard và tự động hóa quy trình đang được chia sẻ tại chuỗi chuyên đề của VCCI News.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-news"],
tagsearch_values: ["Chuyên Đề", "Chuyển đổi số"],
is_featured: true,
thumbnail: toImageRef(mediaSeed[3]),
is_hidden: false,
created_at: "2026-05-11T07:45:00.000Z",
updated_at: "2026-05-11T13:15:00.000Z",
published_at: "2026-05-11T07:45",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "Hệ thống trực tuyến",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-05-a",
type: "text",
position: 1,
content:
"<p>Xu hướng tập trung vào trải nghiệm khách hàng, đo lường hiệu quả vận hành và chuẩn hóa dữ liệu đang trở thành ưu tiên hàng đầu.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-06",
title: "Khởi động chuỗi đối thoại chính sách với doanh nghiệp và hiệp hội ngành hàng năm 2026",
slug: "khoi-dong-chuoi-doi-thoai-chinh-sach-voi-doanh-nghiep-va-hiep-hoi-nganh-hang-nam-2026",
summary:
"<p>Chuỗi đối thoại sẽ tập trung vào vướng mắc thủ tục, chi phí tuân thủ và các đề xuất cải thiện môi trường kinh doanh.</p>",
type: "tintuc",
header_category_id: "activity-events",
category_ids: ["cat-event", "cat-policy"],
tagsearch_values: ["Sự kiện", "Chính sách"],
is_featured: true,
thumbnail: toImageRef(mediaSeed[0]),
is_hidden: false,
created_at: "2026-05-10T09:10:00.000Z",
updated_at: "2026-05-10T14:40:00.000Z",
published_at: "2026-05-10T09:10",
expired_at: "",
started_at: "2026-05-28T08:30",
ended_at: "2026-05-28T12:00",
registration_deadline: "2026-05-25T17:00",
location: "Hà Nội",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-06-a",
type: "text",
position: 1,
content:
"<p>Chương trình được thiết kế như một không gian lắng nghe phản hồi thực tiễn và tạo đầu mối điều phối cho các kiến nghị có trọng tâm.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-07",
title: "Cẩm nang thiết kế gian hàng triển lãm hiệu quả cho doanh nghiệp tham gia hội chợ quốc tế",
slug: "cam-nang-thiet-ke-gian-hang-trien-lam-hieu-qua-cho-doanh-nghiep-tham-gia-hoi-cho-quoc-te",
summary:
"<p>Nội dung tổng hợp những lưu ý về nhận diện thương hiệu, luồng trưng bày và cách tạo trải nghiệm ghi nhớ cho khách tham quan.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-news", "cat-activity"],
tagsearch_values: ["Chuyên Đề", "Cẩm nang"],
is_featured: true,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
created_at: "2026-05-07T14:00:00.000Z",
updated_at: "2026-05-09T09:00:00.000Z",
published_at: "2026-05-07T14:00",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "TP. Hồ Chí Minh",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-07-a",
type: "text",
position: 1,
content:
"<p>Tài liệu hướng dẫn được biên tập để doanh nghiệp có thể ứng dụng ngay khi chuẩn bị tham gia các sự kiện giao thương trong nước và quốc tế.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-08",
title: "Hoa Kỳ muốn đẩy mạnh hợp tác kinh tế, thương mại bền vững với Việt Nam",
slug: "hoa-ky-muon-day-manh-hop-tac-kinh-te-thuong-mai-ben-vung-voi-viet-nam",
summary:
"<p>Chương trình làm việc tập trung vào hợp tác chuỗi cung ứng, tiêu chuẩn xanh và kết nối doanh nghiệp giữa các địa phương.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-news"],
tagsearch_values: ["Tin VCCI", "Hợp tác quốc tế"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[3]),
is_hidden: false,
created_at: "2026-03-27T09:00:00.000Z",
updated_at: "2026-03-27T11:00:00.000Z",
published_at: "2026-03-27T09:00",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "TP. Hồ Chí Minh",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-08-a",
type: "text",
position: 1,
content:
"<p>Đại diện hai bên nhấn mạnh nhu cầu phát triển bền vững và hỗ trợ cộng đồng doanh nghiệp thích ứng với thay đổi thị trường toàn cầu.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-09",
title: "Những điểm sáng trong bức tranh kinh tế, số liệu quý II và 6 tháng đầu năm 2026",
slug: "nhung-diem-sang-trong-buc-tranh-kinh-te-so-lieu-quy-ii-va-6-thang-dau-nam-2026",
summary:
"<p>Bản tin tổng hợp các tín hiệu phục hồi, tăng trưởng xuất khẩu và mức độ cải thiện niềm tin thị trường trong nhiều nhóm ngành.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-news"],
tagsearch_values: ["Tin Kinh Tế", "Vĩ mô"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
created_at: "2026-03-25T08:30:00.000Z",
updated_at: "2026-03-25T10:00:00.000Z",
published_at: "2026-03-25T08:30",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "Hà Nội",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-09-a",
type: "text",
position: 1,
content:
"<p>Dữ liệu cho thấy nhiều nhóm doanh nghiệp đang cải thiện năng lực đơn hàng và thích ứng tốt hơn với biến động chi phí.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-10",
title: "Tình hình kinh tế - vĩ mô Quý 1 năm 2026",
slug: "tinh-hinh-kinh-te-vi-mo-quy-1-nam-2026",
summary:
"<p>Báo cáo nhanh về tăng trưởng, lạm phát, lãi suất và xu hướng đầu tư trong bối cảnh kinh tế quốc tế còn nhiều thay đổi.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-news"],
tagsearch_values: ["Tin Kinh Tế", "Vĩ mô"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[0]),
is_hidden: false,
created_at: "2026-03-22T08:00:00.000Z",
updated_at: "2026-03-22T09:30:00.000Z",
published_at: "2026-03-22T08:00",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "Hà Nội",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-10-a",
type: "text",
position: 1,
content:
"<p>Bản tin cung cấp góc nhìn cô đọng về những chỉ số ảnh hưởng trực tiếp đến hoạt động sản xuất, thương mại và đầu tư.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-11",
title: "Cẩm nang hướng dẫn đầu tư kinh doanh tại Việt Nam dành cho doanh nghiệp mới",
slug: "cam-nang-huong-dan-dau-tu-kinh-doanh-tai-viet-nam-danh-cho-doanh-nghiep-moi",
summary:
"<p>Tài liệu tổng hợp các bước chuẩn bị hồ sơ, lựa chọn địa điểm và những lưu ý pháp lý ban đầu cho nhà đầu tư và doanh nghiệp.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-news"],
tagsearch_values: ["Chuyên Đề", "Cẩm nang"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
created_at: "2026-03-20T07:30:00.000Z",
updated_at: "2026-03-20T09:00:00.000Z",
published_at: "2026-03-20T07:30",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "Trực tuyến",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-11-a",
type: "text",
position: 1,
content:
"<p>Nội dung được biên tập theo hướng dễ áp dụng, giúp doanh nghiệp mới có thể tra cứu nhanh khi bắt đầu triển khai dự án.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-12",
title: "Khóa đào tạo: Quản trị Thuế và Pháp lý trong giao dịch",
slug: "khoa-dao-tao-quan-tri-thue-va-phap-ly-trong-giao-dich",
summary:
"<p>Chương trình cập nhật các điểm mới về quản trị thuế, hồ sơ giao dịch và kiểm soát rủi ro pháp lý trong doanh nghiệp.</p>",
type: "tintuc",
header_category_id: "activity-events",
category_ids: ["cat-event"],
tagsearch_values: ["Đào tạo", "Sự kiện"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[3]),
is_hidden: false,
created_at: "2026-11-01T08:00:00.000Z",
updated_at: "2026-11-01T10:00:00.000Z",
published_at: "2026-11-01T08:00",
expired_at: "",
started_at: "2026-11-18T08:30",
ended_at: "2026-11-18T16:30",
registration_deadline: "2026-11-15T17:00",
location: "TP. Hồ Chí Minh",
participation_fee: "800.000 VNĐ",
post_content: [
{
id: "section-admin-news-12-a",
type: "text",
position: 1,
content:
"<p>Khóa học dành cho đội ngũ quản lý, kế toán trưởng và chuyên viên pháp chế cần chuẩn hóa quy trình nội bộ.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-13",
title: "Sự kiện - Tập huấn NSDLĐ",
slug: "su-kien-tap-huan-nsdld",
summary:
"<p>Buổi tập huấn hướng dẫn người sử dụng lao động cập nhật các quy định thực thi và quy trình phối hợp với bộ phận nhân sự.</p>",
type: "tintuc",
header_category_id: "activity-events",
category_ids: ["cat-event"],
tagsearch_values: ["Đào tạo", "Sự kiện"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
created_at: "2026-11-03T09:00:00.000Z",
updated_at: "2026-11-03T09:30:00.000Z",
published_at: "2026-11-03T09:00",
expired_at: "",
started_at: "2026-11-20T13:30",
ended_at: "2026-11-20T17:00",
registration_deadline: "2026-11-18T17:00",
location: "Hà Nội",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-13-a",
type: "text",
position: 1,
content:
"<p>Nội dung tập huấn tập trung vào các tình huống thường gặp trong quá trình vận hành chính sách nhân sự và lao động.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-14",
title: "Diễn đàn hội viên: Kết nối thị trường và chuỗi cung ứng",
slug: "dien-dan-hoi-vien-ket-noi-thi-truong-va-chuoi-cung-ung",
summary:
"<p>Diễn đàn tạo không gian gặp gỡ giữa doanh nghiệp sản xuất, đơn vị phân phối và nhà cung cấp dịch vụ hỗ trợ thị trường.</p>",
type: "tintuc",
header_category_id: "activity-events",
category_ids: ["cat-event"],
tagsearch_values: ["Sự kiện", "Hội viên"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[0]),
is_hidden: false,
created_at: "2026-11-05T08:30:00.000Z",
updated_at: "2026-11-05T11:00:00.000Z",
published_at: "2026-11-05T08:30",
expired_at: "",
started_at: "2026-11-24T08:00",
ended_at: "2026-11-24T12:00",
registration_deadline: "2026-11-22T17:00",
location: "Đà Nẵng",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-14-a",
type: "text",
position: 1,
content:
"<p>Chương trình hướng đến việc mở rộng cơ hội kết nối đối tác, chia sẻ nhu cầu thị trường và xây dựng chuỗi cung ứng linh hoạt hơn.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-15",
title: "Chương trình kết nối doanh nghiệp hội viên ngành thực phẩm và bán lẻ",
slug: "chuong-trinh-ket-noi-doanh-nghiep-hoi-vien-nganh-thuc-pham-va-ban-le",
summary:
"<p>Buổi kết nối tạo không gian giới thiệu sản phẩm, chia sẻ nhu cầu mua hàng và ghép nối đối tác giữa doanh nghiệp sản xuất với hệ thống phân phối.</p>",
type: "tintuc",
header_category_id: "activity-events",
category_ids: ["cat-event"],
tagsearch_values: ["Sự kiện", "Hội viên"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
created_at: "2026-05-11T08:15:00.000Z",
updated_at: "2026-05-11T10:30:00.000Z",
published_at: "2026-05-11T08:15",
expired_at: "",
started_at: "2026-05-22T14:00",
ended_at: "2026-05-22T17:00",
registration_deadline: "2026-05-20T17:00",
location: "TP. Hồ Chí Minh",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-15-a",
type: "text",
position: 1,
content:
"<p>Chương trình ưu tiên các nhóm doanh nghiệp đang cần mở rộng hệ thống phân phối và tìm đối tác đồng hành tại khu vực phía Nam.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-16",
title: "Lớp đào tạo ngắn hạn: Kỹ năng xây dựng kế hoạch xúc tiến thương mại",
slug: "lop-dao-tao-ngan-han-ky-nang-xay-dung-ke-hoach-xuc-tien-thuong-mai",
summary:
"<p>Khóa học hướng dẫn doanh nghiệp xác định mục tiêu, ngân sách và cách triển khai hoạt động xúc tiến thương mại theo từng giai đoạn.</p>",
type: "tintuc",
header_category_id: "activity-events",
category_ids: ["cat-event"],
tagsearch_values: ["Đào tạo", "Sự kiện"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[3]),
is_hidden: false,
created_at: "2026-05-12T07:45:00.000Z",
updated_at: "2026-05-12T09:20:00.000Z",
published_at: "2026-05-12T07:45",
expired_at: "",
started_at: "2026-05-26T08:30",
ended_at: "2026-05-26T11:30",
registration_deadline: "2026-05-24T17:00",
location: "Trực tuyến",
participation_fee: "350.000 VNĐ",
post_content: [
{
id: "section-admin-news-16-a",
type: "text",
position: 1,
content:
"<p>Nội dung tập trung vào cấu trúc kế hoạch, xây dựng đầu việc ưu tiên và lựa chọn kênh triển khai phù hợp với nguồn lực của doanh nghiệp.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-17",
title: "Công ty Western Coast Enterprise LTD cần thuê mua vật liệu xây dựng tại Việt Nam",
slug: "cong-ty-western-coast-enterprise-ltd-can-thue-mua-vat-lieu-xay-dung-tai-viet-nam",
summary:
"<p>Doanh nghiệp tìm kiếm đối tác cung ứng vật liệu xây dựng ổn định tại thị trường Việt Nam để phục vụ kế hoạch mở rộng chuỗi dự án trong khu vực.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-business-opportunity"],
tagsearch_values: ["Cơ hội kinh doanh", "Kết nối giao thương"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
created_at: "2025-11-12T08:00:00.000Z",
updated_at: "2025-11-12T09:30:00.000Z",
published_at: "2025-11-12T08:00",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "TP. Hồ Chí Minh",
participation_fee: "",
post_content: [
{
id: "section-admin-news-17-a",
type: "text",
position: 1,
content:
"<p>Nhu cầu tập trung vào nhóm vật liệu hoàn thiện, vật liệu nền móng và các nhà cung ứng có khả năng đáp ứng đơn hàng dài hạn.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-18",
title: "VCCI-HCM kết nối các nhà đầu tư nước ngoài với doanh nghiệp Việt trong chuỗi cung ứng công nghiệp",
slug: "vcci-hcm-ket-noi-cac-nha-dau-tu-nuoc-ngoai-voi-doanh-nghiep-viet-trong-chuoi-cung-ung-cong-nghiep",
summary:
"<p>Chương trình giới thiệu danh mục nhu cầu hợp tác, tìm nhà cung ứng linh kiện và đối tác gia công cho nhóm doanh nghiệp FDI.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-business-opportunity"],
tagsearch_values: ["Cơ hội kinh doanh", "Hội viên"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[3]),
is_hidden: false,
created_at: "2025-11-12T07:00:00.000Z",
updated_at: "2025-11-12T08:15:00.000Z",
published_at: "2025-11-12T07:00",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "Bình Dương",
participation_fee: "",
post_content: [
{
id: "section-admin-news-18-a",
type: "text",
position: 1,
content:
"<p>Hoạt động ưu tiên những doanh nghiệp có năng lực sản xuất ổn định, minh bạch hồ sơ chất lượng và sẵn sàng tham gia đánh giá nhà máy.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-19",
title: "Doanh nghiệp logistics tìm đối tác phân phối và khai thác tuyến vận chuyển liên vùng",
slug: "doanh-nghiep-logistics-tim-doi-tac-phan-phoi-va-khai-thac-tuyen-van-chuyen-lien-vung",
summary:
"<p>Thông tin mời hợp tác dành cho các doanh nghiệp có hệ thống kho bãi, đội xe và năng lực xử lý đơn hàng tại khu vực phía Nam.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-business-opportunity"],
tagsearch_values: ["Cơ hội kinh doanh", "Logistics"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[0]),
is_hidden: false,
created_at: "2025-11-11T10:30:00.000Z",
updated_at: "2025-11-11T11:00:00.000Z",
published_at: "2025-11-11T10:30",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "Long An",
participation_fee: "",
post_content: [
{
id: "section-admin-news-19-a",
type: "text",
position: 1,
content:
"<p>Nội dung hợp tác bao gồm phân phối nội địa, gom hàng xuất khẩu và phát triển thêm các điểm trung chuyển mới tại khu vực lân cận.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-20",
title: "Những chính sách mới có hiệu lực từ ngày 01/10/2026",
slug: "nhung-chinh-sach-moi-co-hieu-luc-tu-ngay-01-10-2026",
summary:
"<p>Tổng hợp nhanh các quy định mới liên quan đến thuế, lao động và thủ tục hành chính mà doanh nghiệp cần lưu ý trong kỳ áp dụng mới.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-policy-law"],
tagsearch_values: ["Chính sách & pháp luật", "Chính sách"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[0]),
is_hidden: false,
created_at: "2025-11-12T09:00:00.000Z",
updated_at: "2025-11-12T09:40:00.000Z",
published_at: "2025-11-12T09:00",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "Hà Nội",
participation_fee: "",
post_content: [
{
id: "section-admin-news-20-a",
type: "text",
position: 1,
content:
"<p>Bài viết hệ thống lại các mốc áp dụng, nhóm đối tượng chịu tác động và một số đầu việc doanh nghiệp nên chuẩn bị sớm.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-21",
title: "Luật được sửa đổi: nhiều quy định mới có lợi cho doanh nghiệp",
slug: "luat-duoc-sua-doi-nhieu-quy-dinh-moi-co-loi-cho-doanh-nghiep",
summary:
"<p>Nội dung cập nhật tập trung vào các điểm sửa đổi về điều kiện kinh doanh, thủ tục hồ sơ và cơ chế hỗ trợ doanh nghiệp nhỏ và vừa.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-policy-law"],
tagsearch_values: ["Chính sách & pháp luật", "Pháp luật"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
created_at: "2025-11-12T08:30:00.000Z",
updated_at: "2025-11-12T09:00:00.000Z",
published_at: "2025-11-12T08:30",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "Hà Nội",
participation_fee: "",
post_content: [
{
id: "section-admin-news-21-a",
type: "text",
position: 1,
content:
"<p>Các thay đổi đáng chú ý giúp rút ngắn thời gian xử lý thủ tục và mở rộng thêm một số cơ chế linh hoạt cho nhà đầu tư.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-22",
title: "Bảo vệ cổ đông: có được coi là sự kiện bất khả kháng đối với doanh nghiệp",
slug: "bao-ve-co-dong-co-duoc-coi-la-su-kien-bat-kha-khang-doi-voi-doanh-nghiep",
summary:
"<p>Phân tích tình huống pháp lý thường gặp trong quản trị doanh nghiệp, trách nhiệm công bố thông tin và cách xác định rủi ro phát sinh.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-policy-law"],
tagsearch_values: ["Chính sách & pháp luật", "Pháp luật"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[3]),
is_hidden: false,
created_at: "2025-11-12T08:00:00.000Z",
updated_at: "2025-11-12T08:45:00.000Z",
published_at: "2025-11-12T08:00",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "TP. Hồ Chí Minh",
participation_fee: "",
post_content: [
{
id: "section-admin-news-22-a",
type: "text",
position: 1,
content:
"<p>Bài viết đưa ra góc nhìn thực tiễn và khuyến nghị bước chuẩn bị hồ sơ nội bộ khi phát sinh tranh chấp liên quan đến quyền cổ đông.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-23",
title: "Kết nối hội viên ngành xây dựng và vật liệu tại khu vực phía Nam",
slug: "ket-noi-hoi-vien-nganh-xay-dung-va-vat-lieu-tai-khu-vuc-phia-nam",
summary:
"<p>Hoạt động kết nối tập trung vào nhóm doanh nghiệp sản xuất vật liệu, thi công công trình và đơn vị tư vấn đang cần mở rộng mạng lưới hợp tác.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-member-connection"],
tagsearch_values: ["Kết nối hội viên", "Hội viên"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
created_at: "2026-05-13T08:00:00.000Z",
updated_at: "2026-05-13T08:30:00.000Z",
published_at: "2026-05-13T08:00",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "TP. Hồ Chí Minh",
participation_fee: "",
post_content: [
{
id: "section-admin-news-23-a",
type: "text",
position: 1,
content:
"<p>Chương trình giới thiệu nhu cầu hợp tác, nhu cầu nhà cung ứng và các cơ hội triển khai dự án chung trong giai đoạn tới.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-24",
title: "Không gian gặp gỡ hội viên mới trong mạng lưới doanh nghiệp dịch vụ",
slug: "khong-gian-gap-go-hoi-vien-moi-trong-mang-luoi-doanh-nghiep-dich-vu",
summary:
"<p>Buổi networking quy tụ đại diện doanh nghiệp dịch vụ, thương mại và đơn vị tư vấn cùng chia sẻ nhu cầu kết nối khách hàng.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-member-connection"],
tagsearch_values: ["Kết nối hội viên", "Networking"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[0]),
is_hidden: false,
created_at: "2026-05-12T15:00:00.000Z",
updated_at: "2026-05-12T16:15:00.000Z",
published_at: "2026-05-12T15:00",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "TP. Hồ Chí Minh",
participation_fee: "",
post_content: [
{
id: "section-admin-news-24-a",
type: "text",
position: 1,
content:
"<p>Nội dung chú trọng vào việc tạo điểm chạm ban đầu giữa các hội viên mới với cộng đồng doanh nghiệp hiện có của VCCI-HCM.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-25",
title: "Chương trình chia sẻ cơ hội hợp tác giữa hội viên công nghệ và doanh nghiệp truyền thống",
slug: "chuong-trinh-chia-se-co-hoi-hop-tac-giua-hoi-vien-cong-nghe-va-doanh-nghiep-truyen-thong",
summary:
"<p>Chuỗi hoạt động giúp doanh nghiệp công nghệ giới thiệu giải pháp số và tìm đối tác ứng dụng trong sản xuất, thương mại và dịch vụ.</p>",
type: "tintuc",
header_category_id: "activity-news",
category_ids: ["cat-member-connection"],
tagsearch_values: ["Kết nối hội viên", "Chuyển đổi số"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[3]),
is_hidden: false,
created_at: "2026-05-11T16:00:00.000Z",
updated_at: "2026-05-11T17:00:00.000Z",
published_at: "2026-05-11T16:00",
expired_at: "",
started_at: "",
ended_at: "",
registration_deadline: "",
location: "Trực tuyến",
participation_fee: "",
post_content: [
{
id: "section-admin-news-25-a",
type: "text",
position: 1,
content:
"<p>Chương trình mở ra nhiều phiên giới thiệu nhanh, matching nhu cầu và trao đổi mô hình triển khai phù hợp theo từng nhóm ngành.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-26",
title: "Phiên kết nối nhà mua hàng quốc tế với doanh nghiệp hội viên ngành gỗ",
slug: "phien-ket-noi-nha-mua-hang-quoc-te-voi-doanh-nghiep-hoi-vien-nganh-go",
summary:
"<p>Chương trình tập trung vào nhu cầu sourcing sản phẩm nội thất, vật liệu hoàn thiện và nhóm doanh nghiệp có năng lực xuất khẩu tại khu vực phía Nam.</p>",
type: "tintuc",
header_category_id: "activity-events",
category_ids: ["cat-event"],
tagsearch_values: ["Sự kiện", "Hội viên"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
created_at: "2026-05-13T09:00:00.000Z",
updated_at: "2026-05-13T10:15:00.000Z",
published_at: "2026-05-13T09:00",
expired_at: "",
started_at: "2026-05-29T08:30",
ended_at: "2026-05-29T11:30",
registration_deadline: "2026-05-27T17:00",
location: "TP. Hồ Chí Minh",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-26-a",
type: "text",
position: 1,
content:
"<p>Hoạt động ưu tiên các doanh nghiệp có bộ hồ sơ năng lực xuất khẩu rõ ràng và sản phẩm phù hợp với nhóm nhà mua hàng đang mở rộng nguồn cung tại Việt Nam.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-27",
title: "Hội thảo chuyên đề logistics lạnh cho doanh nghiệp thực phẩm và nông sản",
slug: "hoi-thao-chuyen-de-logistics-lanh-cho-doanh-nghiep-thuc-pham-va-nong-san",
summary:
"<p>Chuỗi chia sẻ cập nhật xu hướng bảo quản lạnh, tối ưu chi phí vận chuyển và tiêu chuẩn chất lượng trong chuỗi cung ứng thực phẩm.</p>",
type: "tintuc",
header_category_id: "activity-events",
category_ids: ["cat-event"],
tagsearch_values: ["Sự kiện", "Chuyên đề"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[0]),
is_hidden: false,
created_at: "2026-05-14T07:45:00.000Z",
updated_at: "2026-05-14T08:20:00.000Z",
published_at: "2026-05-14T07:45",
expired_at: "",
started_at: "2026-05-30T13:30",
ended_at: "2026-05-30T16:30",
registration_deadline: "2026-05-28T17:00",
location: "Cần Thơ",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-27-a",
type: "text",
position: 1,
content:
"<p>Phiên thảo luận kết nối doanh nghiệp sản xuất với đơn vị kho vận, chuỗi bán lẻ và nhà cung cấp giải pháp kiểm soát nhiệt độ trong bảo quản.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-28",
title: "Khóa đào tạo thực hành xây dựng hồ sơ năng lực số cho doanh nghiệp hội viên",
slug: "khoa-dao-tao-thuc-hanh-xay-dung-ho-so-nang-luc-so-cho-doanh-nghiep-hoi-vien",
summary:
"<p>Khóa học hướng dẫn doanh nghiệp chuẩn hóa profile giới thiệu, tài liệu bán hàng và công cụ trình bày năng lực trên môi trường số.</p>",
type: "tintuc",
header_category_id: "activity-events",
category_ids: ["cat-event"],
tagsearch_values: ["Đào tạo", "Hội viên"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[3]),
is_hidden: false,
created_at: "2026-05-14T10:10:00.000Z",
updated_at: "2026-05-14T10:50:00.000Z",
published_at: "2026-05-14T10:10",
expired_at: "",
started_at: "2026-06-03T08:30",
ended_at: "2026-06-03T11:30",
registration_deadline: "2026-06-01T17:00",
location: "Trực tuyến",
participation_fee: "300.000 VNĐ",
post_content: [
{
id: "section-admin-news-28-a",
type: "text",
position: 1,
content:
"<p>Nội dung tập trung vào các phần cốt lõi của bộ hồ sơ giới thiệu doanh nghiệp, hình ảnh minh họa và cách trình bày thông tin súc tích để chào đối tác.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
{
id: "admin-news-29",
title: "Diễn đàn kết nối tài chính xanh cho doanh nghiệp sản xuất và xuất khẩu",
slug: "dien-dan-ket-noi-tai-chinh-xanh-cho-doanh-nghiep-san-xuat-va-xuat-khau",
summary:
"<p>Chương trình cập nhật các nguồn vốn xanh, tiêu chí đánh giá dự án và giải pháp chuẩn bị hồ sơ tiếp cận tài chính cho doanh nghiệp.</p>",
type: "tintuc",
header_category_id: "activity-events",
category_ids: ["cat-event"],
tagsearch_values: ["Sự kiện", "Tài chính xanh"],
is_featured: false,
thumbnail: toImageRef(mediaSeed[2]),
is_hidden: false,
created_at: "2026-05-14T11:20:00.000Z",
updated_at: "2026-05-14T12:00:00.000Z",
published_at: "2026-05-14T11:20",
expired_at: "",
started_at: "2026-06-05T14:00",
ended_at: "2026-06-05T17:00",
registration_deadline: "2026-06-03T17:00",
location: "Hà Nội",
participation_fee: "Miễn phí",
post_content: [
{
id: "section-admin-news-29-a",
type: "text",
position: 1,
content:
"<p>Diễn đàn tạo nhịp kết nối giữa doanh nghiệp, ngân hàng và đơn vị tư vấn để trao đổi về điều kiện tiếp cận các chương trình tài chính xanh.</p>",
image_columns: 2,
image_rows: 2,
images: [],
},
],
},
];
export function slugifyAdminNews(value: string) {
......
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