Commit 9f9abbe5 authored by Phạm Quang Bảo's avatar Phạm Quang Bảo

update/change to components nextjs

parent 3d0df67f
...@@ -2,7 +2,7 @@ import type { NextConfig } from "next"; ...@@ -2,7 +2,7 @@ import type { NextConfig } from "next";
import links from "./src/links/index"; import links from "./src/links/index";
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
/* config options here */ /* config options here */
images: { images: {
remotePatterns: [ remotePatterns: [
{ {
protocol: "https", protocol: "https",
...@@ -10,6 +10,12 @@ const nextConfig: NextConfig = { ...@@ -10,6 +10,12 @@ const nextConfig: NextConfig = {
port: "", port: "",
pathname: "/vcci/images/**", pathname: "/vcci/images/**",
}, },
{
protocol: "https",
hostname: "vcci-hcm.org.vn", // WordPress / media host
port: "",
pathname: "/wp-content/uploads/**",
},
], ],
}, },
}; };
......
...@@ -2,21 +2,21 @@ import { EventItem } from '@/api/types/event' ...@@ -2,21 +2,21 @@ import { EventItem } from '@/api/types/event'
import BASE_URL from '@/links' import BASE_URL from '@/links'
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import AppEditorContent from '@/components/shared/editor-content'; import AppEditorContent from '@/components/shared/editor-content';
import Link from "next/link";
import ImageNext from "@/components/base/image";
function CardEvent({ event }: { event: EventItem }) { function CardEvent({ event }: { event: EventItem }) {
return ( return (
<a <Link
href={`hoat-dong/su-kien/${event.id}`} href={`hoat-dong/su-kien/${event.id}`}
className='flex flex-row gap-2 mb-2 sm:gap-3 sm:mb-3 p-2 sm:p-3 border border-gray-200 bg-white rounded-md' className='flex flex-row gap-2 mb-2 sm:gap-3 sm:mb-3 p-2 sm:p-3 border border-gray-200 bg-white rounded-md'
> >
<img <ImageNext
src={`${BASE_URL.imageEndpoint}${event.image}`} src={`${BASE_URL.imageEndpoint}${event.image}`}
alt={event.name} alt={event.name}
className='w-[100px] md:w-[130px] aspect-3/2 object-cover' className='aspect-3/2 object-cover'
onError={(e) => { width={130}
e.currentTarget.onerror = null height={86}
e.currentTarget.src = "/img-error.png"
}}
/> />
<div className='flex-1'> <div className='flex-1'>
<p className='text-[#0056b3] font-bold text-sm line-clamp-2'> <p className='text-[#0056b3] font-bold text-sm line-clamp-2'>
...@@ -27,7 +27,7 @@ function CardEvent({ event }: { event: EventItem }) { ...@@ -27,7 +27,7 @@ function CardEvent({ event }: { event: EventItem }) {
</p> </p>
{/* <AppEditorContent className='line-clamp-2' value={event.description} /> */} {/* <AppEditorContent className='line-clamp-2' value={event.description} /> */}
</div> </div>
</a> </Link>
); );
} }
......
...@@ -2,21 +2,21 @@ import { NewsItem } from "@/api/types/news"; ...@@ -2,21 +2,21 @@ import { NewsItem } from "@/api/types/news";
import BASE_URL from "@/links"; import BASE_URL from "@/links";
import dayjs from "dayjs"; import dayjs from "dayjs";
import AppEditorContent from "@/components/shared/editor-content"; import AppEditorContent from "@/components/shared/editor-content";
import Link from "next/link";
import ImageNext from "@/components/base/image";
function CardNews({ news }: { news: NewsItem }) { function CardNews({ news }: { news: NewsItem }) {
return ( return (
<a <Link
href={`${news.external_link}`} href={`${news.external_link}`}
className="flex flex-row gap-2 mb-2 sm:gap-3 sm:mb-3" className="flex flex-row gap-2 mb-2 sm:gap-3 sm:mb-3"
> >
<img <ImageNext
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`} src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.title} alt={news.title}
className="w-[100px] md:w-[130px] aspect-3/2 object-cover" className="aspect-3/2 object-cover"
onError={(e) => { width={130}
e.currentTarget.onerror = null height={86}
e.currentTarget.src = "/img-error.png"
}}
/> />
<div className="flex-1"> <div className="flex-1">
<p className="text-[#363636] font-bold text-sm line-clamp-2"> <p className="text-[#363636] font-bold text-sm line-clamp-2">
...@@ -27,7 +27,7 @@ function CardNews({ news }: { news: NewsItem }) { ...@@ -27,7 +27,7 @@ function CardNews({ news }: { news: NewsItem }) {
</p> </p>
{/* <AppEditorContent className='line-clamp-2' value={news.description} /> */} {/* <AppEditorContent className='line-clamp-2' value={news.description} /> */}
</div> </div>
</a> </Link>
); );
} }
......
"use client"; "use client";
import Image from "next/image"; // core
import { useEffect, useRef, useState } from "react"; import { useRef, useState } from "react";
import Link from 'next/link'
// app
import { Autoplay, Grid } from "swiper/modules"; import { Autoplay, Grid } from "swiper/modules";
import { Swiper, SwiperSlide } from "swiper/react"; import { Swiper, SwiperSlide } from "swiper/react";
import { Swiper as SwiperType } from "swiper/types"; import { Swiper as SwiperType } from "swiper/types";
...@@ -9,42 +12,40 @@ import "swiper/css"; ...@@ -9,42 +12,40 @@ import "swiper/css";
import "swiper/css/navigation"; import "swiper/css/navigation";
import "swiper/css/pagination"; import "swiper/css/pagination";
import BASE_URL from "@/links/index"; import BASE_URL from "@/links/index";
import dayjs from "dayjs";
import ImageNext from '@/components/base/image';
import { Spinner } from "@/components/ui"; import { Spinner } from "@/components/ui";
import CardNews from "./components/card-news"; import CardNews from "./components/card-news";
import CardEvent from "./components/card-event"; import CardEvent from "./components/card-event";
import EventCalendar from "@components/base/event-calendar"; import EventCalendar from "@components/base/event-calendar";
import dayjs from "dayjs"; import stripImagesAndHtml from '@/helpers/stripImageAndHtml';
import partnerImages from '@/constants/partnerImages';
import memberImages from '@/constants/memberImages';
// server // server
import { useGetEvents } from "@/api/endpoints/event"; import { useGetEvents } from "@/api/endpoints/event";
import { useGetCategory } from "@/api/endpoints/category";
import { useGetNews } from "@/api/endpoints/news"; import { useGetNews } from "@/api/endpoints/news";
import { GetCategoryAdminResponseType } from "@/api/types/category";
import { GetNewsResponseType, NewsItem } from "@/api/types/news"; import { GetNewsResponseType, NewsItem } from "@/api/types/news";
import { EventApiResponse, EventItem } from "@/api/types/event"; import { EventApiResponse, EventItem } from "@/api/types/event";
import { ChevronsRight, Link } from "lucide-react"; import { ChevronsRight } from "lucide-react";
import { useParams } from "next/navigation";
const Page = () => { const Page = () => {
// state
const [tab, setTab] = useState("all"); const [tab, setTab] = useState("all");
const [currentIndex, setCurrentIndex] = useState(0);
const swiperRef = useRef<SwiperType | null>(null); const swiperRef = useRef<SwiperType | null>(null);
// query // query
const { data: newsData, isLoading: isLoadingNews } = useGetNews<GetNewsResponseType>( const { data: newsAll } = useGetNews<GetNewsResponseType>(
{ {
pageSize: '5', pageSize: '10',
filters: tab === "all" ? `` : `page_config.code @=${tab}`,
} }
); );
const { data: newsData } = useGetNews<GetNewsResponseType>(
const { data: newsAll, isLoading: isLoadingNewsAll } = useGetNews<GetNewsResponseType>(
{ {
pageSize: '10', pageSize: '5',
filters: tab === "all" ? `` : `page_config.code @=${tab}`,
} }
); );
const { data: eventData, isLoading: isLoadingEvent } = useGetEvents<EventApiResponse>();
const { data: businessOpportunities, isLoading: isLoadingBusinessOpportunities } = useGetNews<GetNewsResponseType>( const { data: businessOpportunities, isLoading: isLoadingBusinessOpportunities } = useGetNews<GetNewsResponseType>(
{ {
pageSize: '5', pageSize: '5',
...@@ -58,642 +59,619 @@ const Page = () => { ...@@ -58,642 +59,619 @@ const Page = () => {
} }
); );
const { data: eventData, isLoading: isLoadingEvent } = useGetEvents<EventApiResponse>(); // template
const now = new Date();
const eventDataFiltered = eventData?.responseData.rows.filter(event => {
const eventTime = new Date(event.start_time);
return eventTime > now;
});
// helpers
const stripImagesAndHtml = (html?: string) => {
if (!html) return ''
// remove img tags first
const withoutImgs = html.replace(/<img[^>]*>/gi, '')
// use DOMParser on client for robust extraction
if (typeof window !== 'undefined' && typeof DOMParser !== 'undefined') {
try {
const doc = new DOMParser().parseFromString(withoutImgs, 'text/html')
return doc.body.textContent || ''
} catch {
// fallback to regex
}
}
return withoutImgs.replace(/<[^>]*>/g, '')
}
const images = [
"/home/doi-tac/AMFORI-1.png.webp",
"/home/doi-tac/AUS4SKILLS-1.png.webp",
"/home/doi-tac/BetterWork-1.png.webp",
"/home/doi-tac/BOI-LOGO.jpg.webp",
"/home/doi-tac/DNV-logo-1-1.png.webp",
"/home/doi-tac/GERMAN-COOPERATION-1.png.webp",
"/home/doi-tac/GIZ.png.webp",
"/home/doi-tac/HBA.png.webp",
"/home/doi-tac/ILO-1.png.webp",
"/home/doi-tac/InvestHK.png.webp",
"/home/doi-tac/IOM-1.png.webp",
"/home/doi-tac/JICA-134x100-1-1.jpg.webp",
"/home/doi-tac/KIRBY.png.webp",
"/home/doi-tac/NHO-1.png.webp",
"/home/doi-tac/OXFAM-1.png.webp",
"/home/doi-tac/RECOTVET-1.png.webp",
"/home/doi-tac/SC-1.png.webp",
"/home/doi-tac/UNDP.png.webp",
];
const hoivien = [
"/home/hoi-vien-tieu-bieu/logo-GTD-768x768.png.webp",
"/home/hoi-vien-tieu-bieu/Nhua-Long-Thanh_Logo.jpg.webp",
"/home/hoi-vien-tieu-bieu/Nova_Group_logo-1.png.webp",
"/home/hoi-vien-tieu-bieu/samngoclinh-1-768x768.png.webp",
"/home/hoi-vien-tieu-bieu/Screenshot-2022-12-26-144136-768x768.png.webp",
"/home/hoi-vien-tieu-bieu/UOB-logo_Vuong.jpeg.webp",
];
return ( return (
(isLoadingBusinessOpportunities || isLoadingPolicyAndLegalInformation || isLoadingEvent) ? ( <>
<div className="container w-full h-[80vh] flex justify-center items-center"> {/* Banner */}
<Spinner /> <Swiper
</div> modules={[Autoplay]}
) : ( autoplay={{ delay: 4000, disableOnInteraction: false }}
<> loop
{/* Banner */} slidesPerView={1}
<Swiper onSwiper={(s) => (swiperRef.current = s)}
modules={[Autoplay]} >
autoplay={{ delay: 4000, disableOnInteraction: false }} <SwiperSlide>
loop <ImageNext
slidesPerView={1} src="https://vcci-hcm.org.vn/wp-content/uploads/2025/10/1.1.-Hero-Banner-CEO-2025-Bi-Sai-Nam-2025-Nhe-2560x720-Px.jpg.webp"
onSwiper={(s) => (swiperRef.current = s)} alt="Banner"
onSlideChange={(s) => width={2560}
setCurrentIndex( height={720}
typeof s.realIndex === "number" ? s.realIndex : s.activeIndex priority
) sizes="100vw"
} className="w-full h-[200px] sm:h-[300px] md:h-[400px] lg:h-[500px] object-cover"
> />
<SwiperSlide> </SwiperSlide>
<img <SwiperSlide>
src="https://vcci-hcm.org.vn/wp-content/uploads/2025/10/1.1.-Hero-Banner-CEO-2025-Bi-Sai-Nam-2025-Nhe-2560x720-Px.jpg" <ImageNext
alt="Banner" src="https://vcci-hcm.org.vn/wp-content/uploads/2022/07/Landscape-HCM_3-01.png"
className="w-full h-[200px] sm:h-[300px] md:h-[400px] lg:h-[500px] object-cover" alt="Banner"
/> width={2560}
</SwiperSlide> height={720}
<SwiperSlide> sizes="100vw"
<img className="w-full h-[200px] sm:h-[300px] md:h-[400px] lg:h-[500px] object-cover"
src="https://vcci-hcm.org.vn/wp-content/uploads/2022/07/Landscape-HCM_3-01.png" />
alt="Banner" </SwiperSlide>
className="w-full h-[200px] sm:h-[300px] md:h-[400px] lg:h-[500px] object-cover" </Swiper>
/>
</SwiperSlide> <div className="container mx-auto px-3 sm:px-6 lg:px-10 space-y-12">
</Swiper> {/* Featured News */}
<section>
<div className="container mx-auto px-3 sm:px-6 lg:px-10 space-y-12"> <div className="flex items-center justify-center py-8 px-4">
{/* Featured News */} <div className="flex items-center w-full max-w-4xl">
<section> <div className="flex-1 h-px bg-linear-to-r from-transparent via-gray-300 to-gray-400"></div>
<div className="flex items-center justify-center py-8 px-4"> <h1 className="px-6 text-[20px] sm:text-[24px] md:text-[28px] uppercase font-bold text-[#063e8e] whitespace-nowrap">
<div className="flex items-center w-full max-w-4xl"> Tin Nổi Bật
<div className="flex-1 h-px bg-linear-to-r from-transparent via-gray-300 to-gray-400"></div> </h1>
<h1 className="px-6 text-[20px] sm:text-[24px] md:text-[28px] uppercase font-bold text-[#063e8e] whitespace-nowrap"> <div className="flex-1 h-px bg-linear-to-l from-transparent via-gray-300 to-gray-400"></div>
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> </div>
</div>
<Swiper <Swiper
modules={[Autoplay]} modules={[Autoplay]}
autoplay={{ delay: 4000, disableOnInteraction: false }} autoplay={{ delay: 4000, disableOnInteraction: false }}
loop loop
breakpoints={{ breakpoints={{
0: { slidesPerView: 1.1, spaceBetween: 10 }, 0: { slidesPerView: 1.1, spaceBetween: 10 },
640: { slidesPerView: 2, spaceBetween: 16 }, 640: { slidesPerView: 2, spaceBetween: 16 },
1024: { slidesPerView: 3, spaceBetween: 24 }, 1024: { slidesPerView: 3, spaceBetween: 24 },
}} }}
className="pb-5" className="pb-5"
> >
{newsAll?.responseData?.rows.map((news) => ( {newsAll?.responseData?.rows.map((news) => (
<SwiperSlide key={news.id}> <SwiperSlide key={news.id}>
<a <Link
href={`${news.external_link}`}
className="relative block bg-white shadow-md overflow-hidden hover:shadow-lg transition-shadow duration-300"
>
<ImageNext
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.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"
/>
<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}
</p>
</div>
</Link>
</SwiperSlide>
))}
</Swiper>
</section>
<div>
<Link href="https://hardwaretools.com.vn/">
<ImageNext
src="/home/Standard-Banner-1-2024.png.webp"
alt="banner"
width={2560}
height={720}
/>
</Link>
</div>
{/* Tin tức + Liên kết nhanh */}
<section className="flex flex-col lg:flex-row gap-5 pb-10 mb-0">
{/* Left */}
<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]"
>
Tin tức
</Link>
<Link
href="/thong-tin-truyen-thong/tin-vcci/"
className="text-[#063e8e] text-sm sm:text-base"
>
<ChevronsRight />
</Link>
</div>
<hr className="border-[#063e8e] mb-4" />
<div className="flex flex-col md:flex-row gap-5">
{newsAll?.responseData.rows
.slice(0, 1)
.map((news: NewsItem) => (
<Link
key={news.id}
href={`${news.external_link}`} href={`${news.external_link}`}
className="relative block bg-white shadow-md overflow-hidden hover:shadow-lg transition-shadow duration-300" className="flex flex-col w-full md:w-1/2 min-h-[180px] sm:min-h-[220px] gap-3 mb-3 bg-white"
> >
<img <div className="w-full aspect-3/2 overflow-hidden">
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`} <ImageNext
alt={news.title} src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
className="w-full aspect-3/2 sm:h-56 md:h-64 object-cover" alt={news.title}
onError={(e) => { width={600}
e.currentTarget.onerror = null height={400}
e.currentTarget.src = "/img-error.png" sizes="(max-width:768px) 100vw,50vw"
}} className="w-full h-full object-cover"
/> />
<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"> </div>
<p className="text-white text-center font-semibold line-clamp-2 text-sm sm:text-base leading-snug">
<div className="flex-1 p-5 pt-1">
<p className="text-[#063E8E] font-bold pb-2 text-xl line-clamp-2">
{news.title} {news.title}
</p> </p>
<p className="line-clamp-4 text-justify">{stripImagesAndHtml(news.description)}</p>
</div> </div>
</a> </Link>
</SwiperSlide> ))}
))}
</Swiper>
</section>
<div> <div className="w-full md:w-1/2">
<a href="https://hardwaretools.com.vn/"> <div className="flex flex-wrap gap-2 sm:gap-3 mb-5">
<img src="/home/Standard-Banner-1-2024.png.webp" alt="banner" /> <button
</a> 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>
{newsData?.responseData?.rows.slice(0, 4).map((news) => (
<CardNews key={news.id} news={news} />
))}
</div>
</div>
</div> </div>
{/* Tin tức + Liên kết nhanh */} {/* Right */}
<section className="flex flex-col lg:flex-row gap-5 pb-10 mb-0"> <aside className="w-full lg:w-[30%]">
{/* Left */} <div className="flex justify-between items-center">
<div className="flex-1"> <h2 className="text-[18px] sm:text-[20px] font-semibold uppercase text-[#063e8e]">
<div className="flex justify-between items-center"> Liên kết nhanh
<a </h2>
href="/thong-tin-truyen-thong/tin-vcci/" </div>
className="text-[18px] sm:text-[20px] font-semibold uppercase text-[#063e8e]" <hr className="border-[#063e8e] mb-4" />
<div className="space-y-2 text-[#063e8e] text-sm md:text-base pb-10">
<div>
<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/"
> >
Tin tức 🔗 Cẩm nang hướng dẫn đầu tư kinh doanh tại Việt Nam
</a> </Link>
<a </div>
href="/thong-tin-truyen-thong/tin-vcci/" <div>
className="text-[#063e8e] text-sm sm:text-base" <Link
className="text-[#363636]"
href="https://vcci-hcm.org.vn/lien-ket-nhanh/doanh-nghiep-kien-nghi-ve-chinh-sach-va-phap-luat/"
> >
<ChevronsRight /> 🔗 Doanh nghiệp kiến nghị về chính sách và pháp luật
</a> </Link>
</div> </div>
<hr className="border-[#063e8e] mb-4" /> </div>
<div>
<Link href="https://hardwaretools.com.vn/">
<ImageNext
src="/home/20-2048x1365.webp"
alt="banner"
width={2048}
height={1365}
/>
</Link>
</div>
</aside>
</section >
{/* Sự kiện */}
< section className="flex flex-col lg:flex-row gap-5 pb-10 mb-0" >
<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]">
Sự kiện sắp diễn ra
</h2>
<Link href="/hoat-dong/su-kien" className="text-[#e8c518] text-sm sm:text-base">
<ChevronsRight />
</Link>
</div>
<hr className="border-[#e8c518] mb-4" />
<div className="flex flex-col md:flex-row gap-5"> <div className="flex flex-col md:flex-row gap-5">
{newsAll?.responseData.rows {isLoadingEvent ? (
.slice(0, 1) <div className="container w-full h-[80vh] flex justify-center items-center">
.map((news: NewsItem) => ( <Spinner />
<a </div>
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" {eventData?.responseData.rows.slice(0, 1).map((event: EventItem) => (
<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"
> >
<div className="w-full aspect-3/2 overflow-hidden"> <div className="w-full aspect-3/2 overflow-hidden">
<img <ImageNext
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`} src={`${BASE_URL.imageEndpoint}${event.image}`}
alt={news.title} alt={event.name}
width={600}
height={400}
sizes="(max-width:768px) 100vw,50vw"
className="w-full h-full object-cover" className="w-full h-full object-cover"
onError={(e) => {
e.currentTarget.onerror = null
e.currentTarget.src = "/img-error.png"
}}
/> />
</div> </div>
<div className="flex-1 p-5 pt-1"> <div className="flex-1">
<p className="text-[#063E8E] font-bold pb-2 text-xl line-clamp-2"> <p className="text-[#0056b3] font-bold text-xl line-clamp-2">
{news.title} {event.name}
</p> </p>
<p className="line-clamp-4 text-justify">{stripImagesAndHtml(news.description)}</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> </div>
</a> </Link>
))} ))}
<div className="w-full md:w-1/2">
<div className="w-full md:w-1/2"> {eventData?.responseData.rows.slice(0, 4).map((event) => (
<div className="flex flex-wrap gap-2 sm:gap-3 mb-5"> <CardEvent key={event.id} event={event} />
<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> </div>
</>
{newsData?.responseData?.rows.slice(0, 4).map((news) => ( )}
<CardNews key={news.id} news={news} />
))}
</div>
</div>
</div> </div>
</div>
{/* Right */} <div className="bg-[#063e8e] w-full lg:w-[30%] p-5">
<aside className="w-full lg:w-[30%]"> <aside>
<div className="flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-semibold uppercase text-[#063e8e]">
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>
<a
className="text-[#363636]"
href="https://vcci-hcm.org.vn/lien-ket-nhanh/cam-nang-huong-dan-dau-tu-kinh-doanh-tai-viet-nam-2023/"
>
<Link
size={16}
className="inline mr-2 font-semibold text-[#063e8e]"
style={{ verticalAlign: "middle", marginTop: "-2px" }}
/>
Cẩm nang hướng dẫn đầu tư kinh doanh tại Việt Nam
</a>
</div>
<div>
<a
className="text-[#363636]"
href="https://vcci-hcm.org.vn/lien-ket-nhanh/doanh-nghiep-kien-nghi-ve-chinh-sach-va-phap-luat/"
>
<Link
size={16}
className="inline mr-2 font-semibold text-[#063e8e]"
style={{ verticalAlign: "middle", marginTop: "-2px" }}
/>
Doanh nghiệp kiến nghị về chính sách và pháp luật
</a>
</div>
</div>
<div>
<a href="https://hardwaretools.com.vn/">
<img src="/home/20-2048x1365.webp" alt="banner" />
</a>
</div>
</aside>
</section >
{/* Sự kiện */}
< section className="flex flex-col lg:flex-row gap-5 pb-10 mb-0" >
<div className="flex-1 bg-[#063e8e] p-5">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-[#e8c518]"> <h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-[#e8c518]">
Sự kiện sắp diễn ra Lịch sự kiện
</h2> </h2>
<a href="/hoat-dong/su-kien" className="text-[#e8c518] text-sm sm:text-base"> <Link
href="/hoat-dong/su-kien"
className="text-[#e8c518] hover:underline text-sm sm:text-base"
>
<ChevronsRight /> <ChevronsRight />
</a> </Link>
</div> </div>
<hr className="border-[#e8c518] mb-4" /> <hr className="border-[#e8c518] mb-4" />
<EventCalendar />
<div className="flex flex-col md:flex-row gap-5"> </aside>
{eventDataFiltered?.slice(0, 1).map((event: EventItem) => ( </div>
<a </section >
key={event.id}
href={`hoat-dong/su-kien/${event.id}`} {/* Cơ hội kinh doanh + Chính sách */}
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" < div className="flex flex-col lg:flex-row gap-5 pb-10 mb-0" >
<div className="flex flex-col flex-1">
<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"
alt="banner"
width={2560}
height={720}
/>
</Link>
</div>
<section className="flex flex-col md:flex-row gap-5 pt-8">
<div className="flex-1">
<div className="flex justify-between items-center">
<Link
href="/xuc-tien-thuong-mai/co-hoi/"
className="text-[18px] sm:text-[20px] font-bold uppercase text-[#063e8e]"
> >
<div className="w-full aspect-3/2 overflow-hidden"> Cơ hội kinh doanh
<img </Link>
src={`${BASE_URL.imageEndpoint}${event.image}`} <Link
alt={event.name} href="/xuc-tien-thuong-mai/co-hoi/"
className="w-full h-full object-cover" className="text-[#063e8e] text-sm sm:text-base"
onError={(e) => { >
(e.target as HTMLImageElement).src = <ChevronsRight />
"/img-error.png"; </Link>
}} </div>
/> <hr className="border-[#063e8e] mb-4" />
<div className="pt-2">
{isLoadingBusinessOpportunities ? (
<div className="container w-full h-[80vh] flex justify-center items-center">
<Spinner />
</div> </div>
) : (
<>
{businessOpportunities?.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>
</Link>
))}
<div className="flex-1"> {businessOpportunities?.responseData.rows.slice(0, 3).map((news) => (
<p className="text-[#0056b3] font-bold text-xl line-clamp-2"> <CardNews key={news.id} news={news} />
{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>
</a>
))}
<div className="w-full md:w-1/2">
{eventDataFiltered?.slice(0, 4).map((event) => (
<CardEvent key={event.id} event={event} />
))}
</div> </div>
</div> </div>
</div> <div className="flex-1">
<div className="bg-[#063e8e] w-full lg:w-[30%] p-5">
<aside>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-[#e8c518]"> <Link
Lịch sự kiện href="/thong-tin-truyen-thong/phap-luat"
</h2> className="text-[18px] sm:text-[20px] font-bold uppercase text-[#063e8e]"
<a >
href="/hoat-dong/su-kien" Chính sách & pháp luật
className="text-[#e8c518] hover:underline text-sm sm:text-base" </Link>
<Link
href="/thong-tin-truyen-thong/phap-luat"
className="text-[#063e8e] text-sm sm:text-base"
> >
<ChevronsRight /> <ChevronsRight />
</a> </Link>
</div> </div>
<hr className="border-[#e8c518] mb-4" /> <hr className="border-[#063e8e] mb-4" />
<EventCalendar /> <div className="pt-2">
</aside> {isLoadingPolicyAndLegalInformation ? (
</div> <div className="container w-full h-[80vh] flex justify-center items-center">
</section > <Spinner />
</div>
{/* Cơ hội kinh doanh + Chính sách */} ) : (
< div className="flex flex-col lg:flex-row gap-5 pb-10 mb-0" > <>
<div className="flex flex-col flex-1"> {policyAndLegalInformation?.responseData.rows
<div> .slice(0, 1)
<a href="https://vcci-hcm.org.vn/wp-content/uploads/2022/11/MEDIA-KIT_VCCI-HCM-2022-Final.pdf"> .map((news: NewsItem) => (
<img src="/home/Standard-Banner-1-2024.png.webp" alt="banner" /> <Link key={news.id} href={`${news.external_link}`}>
</a> <div className="w-full aspect-3/2 relative overflow-hidden mb-5">
</div> <ImageNext
<section className="flex flex-col md:flex-row gap-5 pt-8"> src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
<div className="flex-1"> alt={news.title}
<div className="flex justify-between items-center"> width={600}
<a height={400}
href="/xuc-tien-thuong-mai/co-hoi/" sizes="(max-width:768px) 100vw,50vw"
className="text-[18px] sm:text-[20px] font-bold uppercase text-[#063e8e]" className="w-full h-full object-cover"
> />
Cơ hội kinh doanh <div className="absolute bg-white opacity-80 bottom-5 left-5 right-5 p-5">
</a> <p className="text-[#063e8e] font-semibold text-sm sm:text-base z-10 line-clamp-3">
<a {news.title}
href="/xuc-tien-thuong-mai/co-hoi/" </p>
className="text-[#063e8e] text-sm sm:text-base" </div>
>
<ChevronsRight />
</a>
</div>
<hr className="border-[#063e8e] mb-4" />
<div className="pt-2">
{businessOpportunities?.responseData.rows
.slice(0, 1)
.map((news: NewsItem) => (
<a key={news.id} href={`${news.external_link}`}>
<div className="w-full aspect-3/2 relative overflow-hidden mb-5">
<img
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.title}
className="w-full h-full object-cover"
onError={(e) => {
e.currentTarget.onerror = null
e.currentTarget.src = "/img-error.png"
}}
/>
<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>
</div> </Link>
</a> ))}
{policyAndLegalInformation?.responseData.rows.slice(0, 3).map((news) => (
<CardNews key={news.id} news={news} />
))} ))}
</>
{businessOpportunities?.responseData.rows.slice(0, 3).map((news) => ( )}
<CardNews key={news.id} news={news} />
))}
</div>
</div> </div>
<div className="flex-1"> </div>
<div className="flex justify-between items-center"> </section>
<a </div>
href="/thong-tin-truyen-thong/phap-luat" <div className="w-full lg:w-[30%] justify-center items-start flex">
className="text-[18px] sm:text-[20px] font-bold uppercase text-[#063e8e]" <Link href="https://smartgara.ecaraid.com/">
> <ImageNext
Chính sách & pháp luật src="/home/eCarAid_web_banner_600x400.webp"
</a> alt="banner"
<a width={600}
href="/thong-tin-truyen-thong/phap-luat" height={400}
className="text-[#063e8e] text-sm sm:text-base" />
> </Link>
<ChevronsRight /> </div>
</a> </div >
</div>
<hr className="border-[#063e8e] mb-4" />
<div className="pt-2">
{policyAndLegalInformation?.responseData.rows
.slice(0, 1)
.map((news: NewsItem) => (
<a key={news.id} href={`${news.external_link}`}>
<div className="w-full aspect-3/2 relative overflow-hidden mb-5">
<img
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.title}
className="w-full h-full object-cover"
onError={(e) => {
e.currentTarget.onerror = null
e.currentTarget.src = "/img-error.png"
}}
/>
<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>
</a>
))}
{policyAndLegalInformation?.responseData.rows.slice(0, 3).map((news) => ( {/* Hội viên tiêu biểu */}
<CardNews key={news.id} news={news} /> <section className="flex flex-col lg:flex-row gap-5 pb-10 mb-0" >
))} {/* left */}
< 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]">
Hội viên tiêu biểu
</h2>
<Link
href="/danh-ba-hoi-vien"
className="text-[#063e8e] hover:underline text-sm font-medium"
>
<ChevronsRight />
</Link>
</div>
<hr className="border-[#063e8e] mb-5" />
<div>
<Swiper
modules={[Autoplay, Grid]}
autoplay={{ delay: 4000, disableOnInteraction: false }}
loop
grid={{ rows: 1, fill: "row" }}
slidesPerGroup={3}
breakpoints={{
0: { slidesPerView: 2, spaceBetween: 10 },
640: { slidesPerView: 3, spaceBetween: 16 },
1024: { slidesPerView: 3, spaceBetween: 24 },
}}
className="partner-swiper"
>
{memberImages.map((src, i) => (
<SwiperSlide key={i}>
<div className="aspect-square flex justify-center items-center bg-white rounded-lg shadow">
<ImageNext
src={src}
alt={`partner-${i}`}
width={160}
height={160}
sizes="(max-width:640px) 25vw,(max-width:1024px) 15vw,10vw"
className="w-3/4 h-3/4 object-contain"
/>
</div>
</SwiperSlide>
))}
</Swiper>
</div>
</aside >
{/* right */}
<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]">
Kết nối hội viên
</h2>
</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" }}
slidesPerGroup={3}
breakpoints={{
0: { slidesPerView: 2, spaceBetween: 10 },
640: { slidesPerView: 3, spaceBetween: 16 },
1024: { slidesPerView: 3, spaceBetween: 24 },
}}
className="partner-swiper"
>
{partnerImages.map((src, i) => (
<SwiperSlide key={i}>
<div className="aspect-square flex justify-center items-center bg-white rounded-lg shadow">
<ImageNext
src={src}
alt={`partner-${i}`}
width={160}
height={160}
sizes="(max-width:640px) 25vw,(max-width:1024px) 15vw,10vw"
className="w-3/4 h-3/4 object-contain"
/>
</div>
</SwiperSlide>
))}
</Swiper>
</div>
</aside >
</section >
{/* Video + đối tác */}
< section className="flex flex-col lg:flex-row gap-5 pb-10" >
{/* left */}
< 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>
<Link
href="/video"
className="text-[#063e8e] hover:underline text-sm font-medium"
>
<ChevronsRight />
</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> </div>
<p className="mt-2 text-sm text-gray-700 font-medium">
{video.title}
</p>
</div> </div>
</section> ))}
</div>
<div className="w-full lg:w-[30%] justify-center items-start flex">
<a href="https://smartgara.ecaraid.com/">
<img src="/home/eCarAid_web_banner_600x400.webp" alt="banner" />
</a>
</div> </div>
</div > </div >
{/* Hội viên tiêu biểu */} {/* right */}
< section className="flex flex-col lg:flex-row gap-5 pb-10 mb-0" > < aside className="w-full lg:w-[30%]" >
{/* left */} <div className="flex justify-between items-center mb-3">
< aside className="w-full lg:w-1/3 flex-1 bg-[#e8c518] p-5" > <h2 className="text-xl font-bold uppercase text-[#063e8e]">
<div className="flex justify-between items-center mb-3"> Đối tác
<h2 className="text-xl font-bold uppercase text-[#063e8e]"> </h2>
Hội viên tiêu biểu </div>
</h2> <hr className="border-[#063e8e] mb-5" />
<a <div className="pb-10">
href="/danh-ba-hoi-vien" <Swiper
className="text-[#063e8e] hover:underline text-sm font-medium" modules={[Autoplay, Grid]}
> autoplay={{ delay: 4000, disableOnInteraction: false }}
<ChevronsRight /> loop
</a> grid={{ rows: 2, fill: "row" }}
</div> slidesPerGroup={3}
<hr className="border-[#063e8e] mb-5" /> breakpoints={{
<div> 0: { slidesPerView: 2, spaceBetween: 10 },
<Swiper 640: { slidesPerView: 3, spaceBetween: 16 },
modules={[Autoplay, Grid]} 1024: { slidesPerView: 3, spaceBetween: 24 },
autoplay={{ delay: 4000, disableOnInteraction: false }} }}
loop className="partner-swiper"
grid={{ rows: 1, fill: "row" }} >
slidesPerGroup={3} {partnerImages.map((src, i) => (
breakpoints={{ <SwiperSlide key={i}>
0: { slidesPerView: 2, spaceBetween: 10 }, <div className="aspect-square flex justify-center items-center bg-white rounded-lg shadow">
640: { slidesPerView: 3, spaceBetween: 16 }, <ImageNext
1024: { slidesPerView: 3, spaceBetween: 24 }, src={src}
}} alt={`partner-${i}`}
className="partner-swiper" width={160}
> height={160}
{hoivien.map((src, i) => ( sizes="(max-width:640px) 25vw,(max-width:1024px) 15vw,10vw"
<SwiperSlide key={i}> className="w-3/4 h-3/4 object-contain"
<div className="aspect-square flex justify-center items-center bg-white rounded-lg shadow">
<img
src={src}
alt={`partner-${i}`}
className="w-3/4 h-3/4 object-contain"
/>
</div>
</SwiperSlide>
))}
</Swiper>
</div>
</aside >
{/* right */}
<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]">
Kết nối hội viên
</h2>
</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" }}
slidesPerGroup={3}
breakpoints={{
0: { slidesPerView: 2, spaceBetween: 10 },
640: { slidesPerView: 3, spaceBetween: 16 },
1024: { slidesPerView: 3, spaceBetween: 24 },
}}
className="partner-swiper"
>
{images.map((src, i) => (
<SwiperSlide key={i}>
<div className="aspect-square flex justify-center items-center bg-white rounded-lg shadow">
<img
src={src}
alt={`partner-${i}`}
className="w-3/4 h-3/4 object-contain"
/>
</div>
</SwiperSlide>
))}
</Swiper>
</div>
</aside >
</section >
{/* Video + đối tác */}
< section className="flex flex-col lg:flex-row gap-5 pb-10" >
{/* left */}
< 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>
<a
href="/video"
className="text-[#063e8e] hover:underline text-sm font-medium"
>
<ChevronsRight />
</a>
</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> </div>
<p className="mt-2 text-sm text-gray-700 font-medium"> </SwiperSlide>
{video.title}
</p>
</div>
))} ))}
</div> </Swiper>
</div > </div>
</aside>
{/* right */} </section>
< aside className="w-full lg:w-[30%]" > </div>
<div className="flex justify-between items-center mb-3"> </>
<h2 className="text-xl font-bold uppercase text-[#063e8e]">
Đối tác
</h2>
</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" }}
slidesPerGroup={3}
breakpoints={{
0: { slidesPerView: 2, spaceBetween: 10 },
640: { slidesPerView: 3, spaceBetween: 16 },
1024: { slidesPerView: 3, spaceBetween: 24 },
}}
className="partner-swiper"
>
{images.map((src, i) => (
<SwiperSlide key={i}>
<div className="aspect-square flex justify-center items-center bg-white rounded-lg shadow">
<img
src={src}
alt={`partner-${i}`}
className="w-3/4 h-3/4 object-contain"
/>
</div>
</SwiperSlide>
))}
</Swiper>
</div>
</aside >
</section >
</div >
</>
)
); );
}; };
......
import Image from "next/image";
import { useState } from "react";
const ImageNext = ({ src, alt, width, height, className, onError }: any) => {
const [imgSrc, setImgSrc] = useState(src);
return (
<Image
src={imgSrc}
alt={alt}
width={width}
height={height}
className={className}
onError={() => setImgSrc(onError || "/img-error.png")}
/>
);
};
export default ImageNext;
const memberImages = [
"/home/hoi-vien-tieu-bieu/logo-GTD-768x768.png.webp",
"/home/hoi-vien-tieu-bieu/Nhua-Long-Thanh_Logo.jpg.webp",
"/home/hoi-vien-tieu-bieu/Nova_Group_logo-1.png.webp",
"/home/hoi-vien-tieu-bieu/samngoclinh-1-768x768.png.webp",
"/home/hoi-vien-tieu-bieu/Screenshot-2022-12-26-144136-768x768.png.webp",
"/home/hoi-vien-tieu-bieu/UOB-logo_Vuong.jpeg.webp",
];
export default memberImages;
\ No newline at end of file
const partnerImages = [
"/home/doi-tac/AMFORI-1.png.webp",
"/home/doi-tac/AUS4SKILLS-1.png.webp",
"/home/doi-tac/BetterWork-1.png.webp",
"/home/doi-tac/BOI-LOGO.jpg.webp",
"/home/doi-tac/DNV-logo-1-1.png.webp",
"/home/doi-tac/GERMAN-COOPERATION-1.png.webp",
"/home/doi-tac/GIZ.png.webp",
"/home/doi-tac/HBA.png.webp",
"/home/doi-tac/ILO-1.png.webp",
"/home/doi-tac/InvestHK.png.webp",
"/home/doi-tac/IOM-1.png.webp",
"/home/doi-tac/JICA-134x100-1-1.jpg.webp",
"/home/doi-tac/KIRBY.png.webp",
"/home/doi-tac/NHO-1.png.webp",
"/home/doi-tac/OXFAM-1.png.webp",
"/home/doi-tac/RECOTVET-1.png.webp",
"/home/doi-tac/SC-1.png.webp",
"/home/doi-tac/UNDP.png.webp",
];
export default partnerImages;
\ No newline at end of file
const stripImagesAndHtml = (html?: string) => {
if (!html) return ''
// remove img tags first
const withoutImgs = html.replace(/<img[^>]*>/gi, '')
// use DOMParser on client for robust extraction
if (typeof window !== 'undefined' && typeof DOMParser !== 'undefined') {
try {
const doc = new DOMParser().parseFromString(withoutImgs, 'text/html')
return doc.body.textContent || ''
} catch {
// fallback to regex
}
}
return withoutImgs.replace(/<[^>]*>/g, '')
}
export default stripImagesAndHtml
\ No newline at end of file
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