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

update/responsive home page and members page

parent 5dc31199
...@@ -3,16 +3,16 @@ import BASE_URL from '@/links' ...@@ -3,16 +3,16 @@ 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';
function NewsContent({ news }: { news: NewsAdminItem }) { function CardNews({ news }: { news: NewsAdminItem }) {
return ( return (
<a <a
href={`${news.id}`} href={`${news.id}`}
className='flex flex-col sm:flex-row gap-3 mb-3 border border-gray-200 bg-white rounded-md p-3' className='flex flex-row gap-3 mb-3 border border-gray-200 bg-white rounded-md p-3'
> >
<img <img
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`} src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.title} alt={news.title}
className='w-full sm:w-[120px] h-20 object-cover rounded-sm' className='w-[120px] h-20 object-cover rounded-sm'
/> />
<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,4 +27,4 @@ function NewsContent({ news }: { news: NewsAdminItem }) { ...@@ -27,4 +27,4 @@ function NewsContent({ news }: { news: NewsAdminItem }) {
); );
} }
export default NewsContent; export default CardNews;
\ No newline at end of file \ No newline at end of file
export { default } from './NewsContent';
\ No newline at end of file
...@@ -9,7 +9,7 @@ import 'swiper/css' ...@@ -9,7 +9,7 @@ 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 NewsContent from './components/news-content/NewsContent' import NewsContent from './components/card-news'
import { Spinner } from '@/components/ui' import { Spinner } from '@/components/ui'
import { useGetCategory } from '@/api/endpoints/category' import { useGetCategory } from '@/api/endpoints/category'
import { useGetNews } from '@/api/endpoints/news' import { useGetNews } from '@/api/endpoints/news'
...@@ -18,280 +18,259 @@ import { GetNewsAdminResponseType } from '@/api/types/news' ...@@ -18,280 +18,259 @@ import { GetNewsAdminResponseType } from '@/api/types/news'
import EventCalendar from './components/event-calendar' import EventCalendar from './components/event-calendar'
const Home = () => { const Home = () => {
// states
const [tab, setTab] = useState('all') const [tab, setTab] = useState('all')
const [search, setSearch] = useState('') const [search, setSearch] = useState('')
const [submitSearch, setSubmitSearch] = useState('') const [submitSearch, setSubmitSearch] = useState('')
const [currentIndex, setCurrentIndex] = useState(0) const [currentIndex, setCurrentIndex] = useState(0)
// responsive slidesPerView used to compute pagination pages
const [slidesPerView, setSlidesPerView] = useState<number>(3) const [slidesPerView, setSlidesPerView] = useState<number>(3)
// Refs
const swiperRef = useRef<SwiperType | null>(null) const swiperRef = useRef<SwiperType | null>(null)
// server const { data: categoryData } = useGetCategory<GetCategoryAdminResponseType>()
const { data: categoryData } = useGetCategory<GetCategoryAdminResponseType>();
const { data: allData, isLoading } = useGetNews<GetNewsAdminResponseType>({ const { data: allData, isLoading } = useGetNews<GetNewsAdminResponseType>({
pageSize: '999', pageSize: '999',
filters: submitSearch ? `title @=${submitSearch}` : undefined, filters: submitSearch ? `title @=${submitSearch}` : undefined,
}) })
//tab filter const rows = allData?.responseData?.rows ?? []
const rows = allData?.responseData?.rows ?? []; const filteredRows = tab === 'all' ? rows : rows.filter((n) => n.category === tab)
const filteredRows = tab === 'all'
? rows
: rows.filter(news => news.category === tab);
// update slidesPerView on resize to match the Swiper breakpoints
useEffect(() => { useEffect(() => {
const getSlides = (w: number) => { const getSlides = (w: number) => {
if (w >= 1024) return 3 if (w >= 1024) return 3
if (w >= 640) return 2 if (w >= 640) return 2
return 1 return 1
} }
const update = () => setSlidesPerView(getSlides(window.innerWidth)) const update = () => setSlidesPerView(getSlides(window.innerWidth))
// run once on mount
update() update()
window.addEventListener('resize', update) window.addEventListener('resize', update)
return () => window.removeEventListener('resize', update) return () => window.removeEventListener('resize', update)
}, []) }, [])
//template if (isLoading)
return ( return (
isLoading ? ( <div className="w-full h-[80vh] flex justify-center items-center">
<div className='w-full h-[80vh] flex justify-center items-center'>
<Spinner /> <Spinner />
</div> </div>
) : ( )
<>
{/* Banner */}
<Swiper
modules={[Autoplay]}
// navigation
autoplay={{ delay: 4000, disableOnInteraction: false }}
loop
slidesPerView={1}
onSwiper={(swiper) => {
swiperRef.current = swiper
}}
onSlideChange={(swiper) => {
setCurrentIndex(typeof swiper.realIndex === 'number' ? swiper.realIndex : swiper.activeIndex)
}}
>
<SwiperSlide>
<img
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"
alt="Banner"
className='w-full'
/>
</SwiperSlide>
<SwiperSlide>
<img
src="https://vcci-hcm.org.vn/wp-content/uploads/2022/07/Landscape-HCM_3-01.png"
alt="Banner"
className='w-full'
/>
</SwiperSlide>
</Swiper>
<div className='container'> return (
{/* slider */} <>
<div className='pb-10'> {/* Banner */}
<div className='flex py-10 justify-center items-center w-full text-center'> <Swiper
<hr className='border-blue-900 w-full' /> modules={[Autoplay]}
<h1 className='text-app-blue text-[28px] leading-normal uppercase font-bold w-full text-blue-900'> autoplay={{ delay: 4000, disableOnInteraction: false }}
Tin Nổi Bật loop
</h1> slidesPerView={1}
<hr className='border-blue-900 w-full' /> onSwiper={(s) => (swiperRef.current = s)}
</div> onSlideChange={(s) =>
<div> setCurrentIndex(typeof s.realIndex === 'number' ? s.realIndex : s.activeIndex)
<Swiper }
modules={[Autoplay]} >
// navigation <SwiperSlide>
autoplay={{ delay: 4000, disableOnInteraction: false }} <img
loop 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"
spaceBetween={30} alt="Banner"
breakpoints={{ className="w-full h-[200px] sm:h-[300px] md:h-[400px] lg:h-[500px] object-cover"
0: { slidesPerView: 1 }, />
640: { slidesPerView: 2 }, </SwiperSlide>
1024: { slidesPerView: 3 } <SwiperSlide>
}} <img
onSwiper={(swiper) => { src="https://vcci-hcm.org.vn/wp-content/uploads/2022/07/Landscape-HCM_3-01.png"
swiperRef.current = swiper alt="Banner"
}} className="w-full h-[200px] sm:h-[300px] md:h-[400px] lg:h-[500px] object-cover"
onSlideChange={(swiper) => { />
setCurrentIndex(typeof swiper.realIndex === 'number' ? swiper.realIndex : swiper.activeIndex) </SwiperSlide>
}} </Swiper>
>
{allData?.responseData?.rows.map((news) => ( <div className="container mx-auto px-3 sm:px-6 lg:px-10 space-y-12">
<SwiperSlide key={news.id}> {/* Featured News */}
<a href={`/tin-tuc/${news.id}`} className='block bg-white shadow-md overflow-hidden relative'> <section>
<img <div className="flex flex-col items-center py-8 text-center">
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`} <h1 className="text-app-blue text-[20px] sm:text-[24px] md:text-[28px] uppercase font-bold text-blue-900">
alt={news.title} Tin Nổi Bật
className='w-full h-48 sm:h-56 md:h-64 object-cover' </h1>
/> <div className="w-16 h-[3px] bg-blue-900 mt-2 rounded-full"></div>
<div className="absolute bottom-0 left-0 right-0 h-20 bg-linear-to-t from-black/90 to-transparent text-white px-4 font-semibold text-base flex items-center justify-center text-center md:h-24">
<div
className="w-full overflow-hidden"
style={{
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical',
}}
>
{news.title}
</div>
</div>
</a>
</SwiperSlide>
))}
</Swiper>
</div>
</div> </div>
{/* content 1 */} <Swiper
<div className='flex flex-row gap-[30px] pb-10'> modules={[Autoplay]}
<div className='w-[68.5%]'> autoplay={{ delay: 4000, disableOnInteraction: false }}
<div className='pb-5'> loop
<div className="flex flex-row justify-between items-center"> breakpoints={{
<a href="#" className="text-[20px] font-bold uppercase text-blue-900"> 0: { slidesPerView: 1.1, spaceBetween: 10 },
Tin tức 640: { slidesPerView: 2, spaceBetween: 16 },
</a> 1024: { slidesPerView: 3, spaceBetween: 24 },
<a href="#" className="text-blue-900">{'>>'}</a> }}
</div> className="pb-5"
<hr className="border-blue-900" /> >
{rows.map((news) => (
<SwiperSlide key={news.id}>
<a
href={`/tin-tuc/${news.id}`}
className="relative block bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition-shadow duration-300"
>
<img
src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.title}
className="w-full h-48 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>
</a>
</SwiperSlide>
))}
</Swiper>
</section>
{/* Tin tức + Liên kết nhanh */}
<section className="flex flex-col lg:flex-row gap-8">
{/* Left */}
<div className="flex-1">
<div className="pb-4 flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-blue-900">
Tin tức
</h2>
<a href="#" className="text-blue-900 hover:underline text-sm sm:text-base">
{'>>'}
</a>
</div>
<hr className="border-blue-900 mb-4" />
<div className="flex flex-col md:flex-row gap-4 md:gap-6">
<div className="w-full md:w-1/2 bg-gray-500 flex items-center justify-center rounded-lg p-4 min-h-[180px] sm:min-h-[220px]">
<p className="text-white text-center">Khung tin tức VIP</p>
</div> </div>
<div className='flex flex-row gap-[30px]'>
<div className="w-full bg-gray-500 flex items-center justify-center rounded-md"> <div className="w-full md:w-1/2">
<p className="text-white">khung tin tức vip</p> <div className="flex flex-wrap gap-2 sm:gap-3 mb-3">
</div> <button
<div className="w-full overflow-hidden"> className={`flex-1 px-3 sm:px-4 py-2 rounded-md border text-sm transition-colors ${tab === 'all'
<div className="flex mb-3 flex-wrap justify-between"> ? 'border-blue-700 bg-blue-50 text-blue-800 font-semibold'
: 'border-gray-300 bg-white hover:bg-gray-50'
}`}
onClick={() => setTab('all')}
>
Tất cả
</button>
{categoryData?.responseData.rows.slice(0, 3).map((category) => (
<button <button
className={`w-22 cursor-pointer hover:bg-border-blue-700 hover:bg-blue-50 px-4 py-1 rounded-md border ${'all' === tab ? 'border-blue-700 bg-blue-50' : 'border-gray-300 bg-white' key={category.id}
className={`flex-1 px-3 sm:px-4 py-2 rounded-md border text-sm transition-colors ${category.name === tab
? 'border-blue-700 bg-blue-50 text-blue-800 font-semibold'
: 'border-gray-300 bg-white hover:bg-gray-50'
}`} }`}
onClick={() => setTab('all')} onClick={() => setTab(category.name)}
> >
Tất cả {category.name}
</button> </button>
{categoryData?.responseData.rows.slice(0, 3).map((category) => (
<button
key={category.id}
className={`w-22 cursor-pointer hover:bg-border-blue-700 hover:bg-blue-50 px-4 py-1 rounded-md border ${category.name === tab ? 'border-blue-700 bg-blue-50' : 'border-gray-300 bg-white'
}`}
onClick={() => setTab(category.name)}
>
{category.name}
</button>
))}
</div>
{allData?.responseData.rows.slice(0, 5).map((news) => (
<NewsContent key={news.id} news={news} />
))} ))}
</div> </div>
</div>
</div>
<div className='w-[33%]'> {filteredRows.slice(0, 5).map((news) => (
<div className='pb-5'> <NewsContent key={news.id} news={news} />
<div className="flex flex-row justify-between items-center"> ))}
<a href="#" className="text-[20px] font-bold uppercase text-blue-900">
Liên kết nhanh
</a>
<a href="#" className="text-blue-900">{'>>'}</a>
</div>
<hr className="border-blue-900" />
</div>
<div>
<p>🔗 Cẩm nang Hướng dẫn đầu tư kinh doanh tại Việt Nam</p>
<p>🔗 Doanh nghiệp kiến nghị về chính sách và pháp luật</p>
</div> </div>
</div> </div>
</div> </div>
{/* content 2 */} {/* Right */}
<div className='flex flex-row gap-[30px] pb-10'> <aside className="w-full lg:w-1/3">
<div className='w-[68.5%]'> <div className="pb-4 flex justify-between items-center">
<div className='pb-5'> <h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-blue-900">
<div className="flex flex-row justify-between items-center"> Liên kết nhanh
<a href="#" className="text-[20px] font-bold uppercase text-blue-900"> </h2>
Sự kiện sắp diễn ra <a href="#" className="text-blue-900 hover:underline text-sm sm:text-base">
</a> {'>>'}
<a href="#" className="text-blue-900">{'>>'}</a> </a>
</div> </div>
<hr className="border-blue-900" /> <hr className="border-blue-900 mb-4" />
</div> <div className="space-y-2 text-blue-900 text-sm md:text-base">
<div className='flex flex-row gap-[30px]'> <p>🔗 Cẩm nang hướng dẫn đầu tư kinh doanh tại Việt Nam</p>
<div className="w-full bg-gray-500 flex items-center justify-center rounded-md"> <p>🔗 Doanh nghiệp kiến nghị về chính sách và pháp luật</p>
<p className="text-white">khung tin tức vip</p>
</div>
<div className="w-full overflow-hidden">
{allData?.responseData.rows.slice(0, 5).map((news) => (
<NewsContent key={news.id} news={news} />
))}
</div>
</div>
</div> </div>
</aside>
</section>
<div className='w-[33%]'> {/* Sự kiện */}
<div className='pb-5'> <section className="flex flex-col lg:flex-row gap-8">
<div className="flex flex-row justify-between items-center"> <div className="flex-1">
<a href="#" className="text-[20px] font-bold uppercase text-blue-900"> <div className="pb-4 flex justify-between items-center">
Lịch sự kiện <h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-blue-900">
</a> Sự kiện sắp diễn ra
<a href="#" className="text-blue-900">{'>>'}</a> </h2>
</div> <a href="#" className="text-blue-900 hover:underline text-sm sm:text-base">
<hr className="border-blue-900" /> {'>>'}
</div> </a>
<EventCalendar />
</div> </div>
</div> <hr className="border-blue-900 mb-4" />
{/* content 3 */} <div className="flex flex-col md:flex-row gap-4 md:gap-6">
< div className='flex flex-row gap-[30px] pb-10' > <div className="w-full md:w-1/2 bg-gray-500 flex items-center justify-center rounded-lg p-4 min-h-[180px] sm:min-h-[220px]">
{/* Cơ hội kinh doanh */} <p className="text-white">Khung tin tức VIP</p>
< div className='flex flex-col' >
<div>
<div className='flex justify-between items-center w-full'>
<a href='#' className='text-[20px] font-bold uppercase text-blue-900'>
Cơ hội kinh doanh
</a>
<a href='#' className='text-blue-900'>{'>>'}</a>
</div>
<hr className=' border-blue-900' />
</div> </div>
<div className="w-full md:w-1/2">
<div className='pt-5'> {rows.slice(0, 5).map((news) => (
{allData?.responseData.rows.slice(0, 5).map((news) => (
<NewsContent key={news.id} news={news} /> <NewsContent key={news.id} news={news} />
))} ))}
</div> </div>
</div > </div>
</div>
{/* Chính sách & pháp luật */} <aside className="w-full lg:w-1/3">
< div className='flex flex-col' > <div className="pb-4 flex justify-between items-center">
<div> <h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-blue-900">
<div className='flex justify-between items-center w-full'> Lịch sự kiện
<a href='#' className='text-[20px] font-bold uppercase text-blue-900'> </h2>
Chính sách & pháp luật <a href="#" className="text-blue-900 hover:underline text-sm sm:text-base">
</a> {'>>'}
<a href='#' className='text-blue-900'>{'>>'}</a> </a>
</div> </div>
<hr className=' border-blue-900' /> <hr className="border-blue-900 mb-4" />
</div> <EventCalendar />
</aside>
</section>
<div className='pt-5'> {/* Cơ hội kinh doanh + Chính sách */}
{allData?.responseData.rows.slice(0, 5).map((news) => ( <section className="flex flex-col md:flex-row gap-6 lg:gap-10 border-t border-gray-200 pt-8 pb-16">
<NewsContent key={news.id} news={news} /> <div className="flex-1">
))} <div className="flex justify-between items-center">
</div> <h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-blue-900">
</div > Cơ hội kinh doanh
</div > </h2>
</div > <a href="#" className="text-blue-900 hover:underline text-sm sm:text-base">
</> {'>>'}
) </a>
</div>
<hr className="border-blue-900 mb-4" />
<div className="pt-2 space-y-3">
{rows.slice(0, 5).map((news) => (
<NewsContent key={news.id} news={news} />
))}
</div>
</div>
<div className="flex-1">
<div className="flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-blue-900">
Chính sách & pháp luật
</h2>
<a href="#" className="text-blue-900 hover:underline text-sm sm:text-base">
{'>>'}
</a>
</div>
<hr className="border-blue-900 mb-4" />
<div className="pt-2 space-y-3">
{rows.slice(0, 5).map((news) => (
<NewsContent key={news.id} news={news} />
))}
</div>
</div>
</section>
</div>
</>
) )
} }
......
import { NewsAdminItem } from '@/api/types/news'
import { NewsItem } from '@app/dai-dien-gioi-chu/lib/types/NewsPage.type'; import BASE_URL from '@/links'
import Links from '@links/index'
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import AppEditorContent from '@/components/shared/editor-content';
import parse from 'html-react-parser' import parse from 'html-react-parser'
function NewsContent({ news }: { news: NewsItem }) {
function CardNews({ news }: { news: NewsAdminItem }) {
return ( return (
<a <a
href={`/tin-tuc/${news.id}`} href={`${news.id}`}
className="flex flex-col hover:no-underline sm:flex-row gap-2 mb-6 bg-white rounded-lg shadow-sm p-4 border items-start min-w-0" className="flex flex-col sm:flex-row gap-3 mb-3 border border-gray-200 bg-white rounded-md p-3 hover:shadow-md transition"
> >
<img <img
src={`${Links.imageEndpoint}${news.thumbnail}`} src={`${BASE_URL.imageEndpoint}${news.thumbnail}`}
alt={news.title} alt={news.title}
className="w-full sm:w-56 md:w-64 h-40 md:h-36 object-cover shrink-0" className="w-full sm:w-40 h-40 sm:h-28 object-cover rounded-md"
/> />
<div className="flex-1 min-w-0 pl-0 sm:pl-4"> <div className="flex-1">
<p className="text-primary font-semibold text-base md:text-lg hover:underline line-clamp-2 wrap-break-word hover:no-underline"> <p className="text-[#0056b3] font-bold text-sm sm:text-base line-clamp-2">
{news.title} {news.title}
</p> </p>
<p className="text-gray-500 text-xs sm:text-sm my-1">
<div className="text-sm my-2 text-[#00AED5]">{dayjs(news.release_at).format('DD/MM/YYYY')}</div> {dayjs(news.release_at).format('DD/MM/YYYY')}
</p>
<div className="text-sm text-[#777] line-clamp-3"> <div className="text-xs sm:text-sm text-[#777] line-clamp-3 prose tiptap">
<div className="text-sm prose tiptap">{parse(news.description)}</div> {parse(news.description)}
</div> </div>
</div> </div>
</a> </a>
) );
} }
export default NewsContent; export default CardNews;
\ No newline at end of file \ No newline at end of file
"use client" "use client"
import Link from "next/link" import Link from "next/link"
import { usePathname } from "next/navigation" import { usePathname, useRouter } from "next/navigation"
import React from "react" import React from "react"
type Category = { type Category = {
...@@ -18,17 +18,23 @@ const CATEGORIES: Category[] = [ ...@@ -18,17 +18,23 @@ const CATEGORIES: Category[] = [
const ListCategory: React.FC = () => { const ListCategory: React.FC = () => {
const pathname = usePathname() || "" const pathname = usePathname() || ""
const router = useRouter()
const isActive = (href: string) => { const isActive = (href: string) => {
if (href === "/hoi-vien") return pathname === "/hoi-vien" if (href === "/hoi-vien") return pathname === "/hoi-vien"
return pathname === href return pathname === href
} }
const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
router.push(e.target.value)
}
return ( return (
<div className="border-t border-gray-200 bg-white p-2.5"> <div className="border-t border-gray-200 bg-white p-2.5">
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<nav aria-label="Danh mục" className="py-3"> <nav aria-label="Danh mục" className="py-3">
<ul className="flex items-center"> {/* --- Desktop view --- */}
<ul className="hidden sm:flex items-center">
{CATEGORIES.map((c) => { {CATEGORIES.map((c) => {
const active = isActive(c.href) const active = isActive(c.href)
return ( return (
...@@ -38,8 +44,8 @@ const ListCategory: React.FC = () => { ...@@ -38,8 +44,8 @@ const ListCategory: React.FC = () => {
className={ className={
"text-sm font-bold py-3.5 px-5 transition-colors duration-150 " + "text-sm font-bold py-3.5 px-5 transition-colors duration-150 " +
(active (active
? "text-yellow-500 font-semibold decoration-yellow-300 " ? "text-yellow-500 font-semibold decoration-yellow-300"
: "text-gray-600 hover:text-yellow-500 ") : "text-gray-600 hover:text-yellow-500")
} }
> >
{c.title} {c.title}
...@@ -48,10 +54,25 @@ const ListCategory: React.FC = () => { ...@@ -48,10 +54,25 @@ const ListCategory: React.FC = () => {
) )
})} })}
</ul> </ul>
{/* --- Mobile view (Dropdown) --- */}
<div className="sm:hidden">
<select
value={pathname}
onChange={handleChange}
className="w-full border border-gray-300 rounded-md px-3 py-2 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-yellow-400"
>
{CATEGORIES.map((c) => (
<option key={c.href} value={c.href}>
{c.title}
</option>
))}
</select>
</div>
</nav> </nav>
</div> </div>
</div> </div>
) )
} }
export default ListCategory export default ListCategory
\ No newline at end of file
'use client' 'use client'
import React from "react"; import React from "react";
import ListCategory from "./../components/list-category"; import ListCategory from "./../components/list-category";
const Page = () => { const Page = () => {
return ( return (
<div className="min-h-screen container mx-auto pb-4"> <div className="min-h-screen container mx-auto px-4 sm:px-6 lg:px-8 pb-6">
<div className="w-full flex flex-col gap-5"> <div className="flex flex-col gap-5">
<ListCategory /> <ListCategory />
<div className="gap-6"> <main className="bg-white border rounded-md p-5 sm:p-7 lg:py-10 lg:px-40">
{/* Main content */} <h1 className="text-center mb-4 text-xl sm:text-2xl font-bold text-[#153e8e]">
<main className="lg:col-span-2 bg-white border rounded-md p-7 px-40"> THỦ TỤC GIA NHẬP HỘI VIÊN CHÍNH THỨC
<div> </h1>
<h1 className="text-center mb-4 text-2xl font-bold text-[#153e8e]">THỦ TỤC GIA NHẬP HỘI VIÊN CHÍNH THỨC</h1>
<p className="text-justify leading-7 mb3"> <p className="text-justify leading-7 mb-3">
Điều lệ sửa đổi của Liên đoàn Thương mại và Công nghiệp Việt Nam (VCCI) được Đại hội đại biểu toàn quốc VCCI lần thứ VII thông qua và được Thủ tướng Chính phủ Phê duyệt tại Quyết định số 1496/QĐ-TTg ngày 30/11/2022 đã quy định tất cả các doanh nghiệp, các tổ chức sản xuất, kinh doanh, người sử dụng lao động, các hiệp hội doanh nghiệp có đăng ký và hoạt động hợp pháp ở Việt Nam đều có thể trở thành hội viên của VCCI. Điều lệ sửa đổi của Liên đoàn Thương mại và Công nghiệp Việt Nam (VCCI) được Đại hội đại biểu toàn quốc VCCI lần thứ VII thông qua và được Thủ tướng Chính phủ Phê duyệt tại Quyết định số 1496/QĐ-TTg ngày 30/11/2022 đã quy định tất cả các doanh nghiệp, các tổ chức sản xuất, kinh doanh, người sử dụng lao động, các hiệp hội doanh nghiệp có đăng ký và hoạt động hợp pháp ở Việt Nam đều có thể trở thành hội viên của VCCI.
</p> </p>
<p className="text-justify leading-7 mb-3">
Để trở thành hội viên chính thức, tổ chức quan tâm cần gởi VCCI tại Hà Nội hoặc các Chi nhánh, Văn phòng đại diện của VCCI hồ sơ gia nhập gồm: <p className="text-justify leading-7 mb-3">
</p> Để trở thành hội viên chính thức, tổ chức quan tâm cần gửi VCCI tại Hà Nội hoặc các Chi nhánh, Văn phòng đại diện của VCCI hồ sơ gia nhập gồm:
<ul className="list-disc pl-10 space-y-1 font-bold"> </p>
<li className="text-justify leading-7">Đơn xin gia nhập làm hội viên chính thức VCCI (2 bản theo mẫu của VCCI)</li>
<li className="text-justify leading-7">Giấy phép đăng ký kinh doanh, hoặc giấy phép thành lập hoặc quyết định thành lập (2 bản sao).</li> <ul className="list-disc pl-6 sm:pl-10 space-y-1 font-bold">
</ul> <li className="text-justify leading-7">
<p className="text-justify leading-7 my-3"> Đơn xin gia nhập làm hội viên chính thức VCCI (2 bản theo mẫu của VCCI)
Khi nhận được đơn, Ban Thường trực sẽ xét và thông báo cho tổ chức liên quan về quyết định kết nạp. Trong vòng 1 tháng kể từ ngày nhận thông báo, tổ chức phải thực hiện đóng lệ phí gia nhập. Chỉ khi nào tổ chức đóng lệ phí gia nhập mới được coi là hội viên chính thức. Theo quyết định của Ban chấp hành VCCI, lệ phí hiện hành được tính như sau: </li>
</p> <li className="text-justify leading-7">
<p className="text-justify leading-7 my-3"> Giấy phép đăng ký kinh doanh, hoặc giấy phép thành lập hoặc quyết định thành lập (2 bản sao).
Mức lệ phí gia nhập bằng mức hội phí hàng năm, được tính căn cứ vào doanh số của tổ chức trong năm trước theo các mức: </li>
</p> </ul>
<ul className="list-disc pl-10 space-y-1 font-bold">
<li className="text-justify leading-7">Doanh số dưới 10 tỉ đồng đóng 3 triệu đồng/năm</li> <p className="text-justify leading-7 my-3">
<li className="text-justify leading-7">Doanh số từ 10 {`-`} 50 tỉ đồng đóng 7 triệu đồng/năm</li> Khi nhận được đơn, Ban Thường trực sẽ xét và thông báo cho tổ chức liên quan về quyết định kết nạp. Trong vòng 1 tháng kể từ ngày nhận thông báo, tổ chức phải thực hiện đóng lệ phí gia nhập. Chỉ khi nào tổ chức đóng lệ phí gia nhập mới được coi là hội viên chính thức.
<li className="text-justify leading-7">Doanh số trên 50 tỉ đồng đóng 15 triệu đồng/năm</li> </p>
</ul>
<p className="text-justify leading-7 my-3"> <p className="text-justify leading-7 my-3">
Mức lệ phí gia nhập và hội phí trên có thể được điều chỉnh bởi quyết định của Ban chấp hành VCCI trong từng thời gian cụ thể. Mức lệ phí gia nhập bằng mức hội phí hàng năm, được tính căn cứ vào doanh số của tổ chức trong năm trước theo các mức:
</p> </p>
<div>
<p className="text-[#063e8e] mb-3"> <ul className="list-disc pl-6 sm:pl-10 space-y-1 font-bold">
Để biết thêm thông tin chi tiết, vui lòng liên hệ: <li className="text-justify leading-7">
</p> Doanh số dưới 10 tỉ đồng đóng 3 triệu đồng/năm
<p className="text-[#063e8e]"> </li>
<b>Phòng Hội viên Đào tạo và Truyền thông</b> <li className="text-justify leading-7">
<br /> Doanh số từ 10 - 50 tỉ đồng đóng 7 triệu đồng/năm
<b>C. Thúy {`-`} DĐ: 0903 909 756</b> </li>
<span className="block"> <li className="text-justify leading-7">
Email: luuthanhthuy72@yahoo.com; hoivien@vcci-hcm.org.vn; Doanh số trên 50 tỉ đồng đóng 15 triệu đồng/năm
</span> </li>
<span className="block"> </ul>
Điện thoại: 028.3932.0611 {`-`} Fax: 028.3932.5472
</span> <p className="text-justify leading-7 my-3">
<span className="block"> Mức lệ phí gia nhập và hội phí trên có thể được điều chỉnh bởi quyết định của Ban chấp hành VCCI trong từng thời gian cụ thể.
Địa chỉ: P. 306, Lầu 3, Tòa nhà VCCI, 171 Võ Thị Sáu, Phường Xuân Hoà, TP. Hồ Chí Minh </span> </p>
</p>
</div> <div className="my-4">
<p className="text-justify leading-7 my-3"> <p className="text-[#063e8e] mb-3">
Biểu mẫu đính kèm Để biết thêm thông tin chi tiết, vui lòng liên hệ:
</p> </p>
<ul className="list-disc pl-10 space-y-1"> <p className="text-[#063e8e]">
<li className="text-justify leading-7 "> <b>Phòng Hội viên Đào tạo và Truyền thông</b>
<a href="https://vcci-hcm.org.vn/wp-content/uploads/2025/08/Don-dang-ky-tham-gia-nhap-hoi-vien-VCCI_Mau-Doanh-nghiep-1.docx" className="text-[#063e8e] hover:text-yellow-500 italic" download> <br />
Đơn đăng ký tham gia nhập hội viên VCCI (Mẫu Doanh nghiệp) <b>C. Thúy - ĐĐ: 0903 909 756</b>
</a> <span className="block">
</li> Email: luuthanhthuy72@yahoo.com; hoivien@vcci-hcm.org.vn;
<li className="text-justify leading-7"> </span>
<a href="https://vcci-hcm.org.vn/wp-content/uploads/2025/08/Don-dang-ky-tham-gia-nhap-hoi-vien-VCCI_Mau-Hiep-hoi.docx" className="text-[#063e8e] hover:text-yellow-500 italic" download> <span className="block">
Đơn đăng ký tham gia nhập hội viên VCCI (Mẫu Hiệp hội) Điện thoại: 028.3932.0611 - Fax: 028.3932.5472
</a> </span>
</li> <span className="block">
<li className="text-justify leading-7"> Địa chỉ: P. 306, Lầu 3, Tòa nhà VCCI, 171 Võ Thị Sáu, Phường Xuân Hoà, TP. Hồ Chí Minh
<a href="https://vcci-hcm.org.vn/wp-content/uploads/2025/08/Huong-dan-ho-so-dang-ky-Hoi-vien-VCCI.docx" className="text-[#063e8e] hover:text-yellow-500 italic" download> </span>
Hướng dẫn hồ sơ đăng ký Hội viên VCCI </p>
</a> </div>
</li>
</ul> <p className="text-justify leading-7 my-3 font-semibold">
</div > Biểu mẫu đính kèm:
</main> </p>
</div >
</div > <ul className="list-disc pl-6 sm:pl-10 space-y-1">
</div > <li className="text-justify leading-7">
<a
href="https://vcci-hcm.org.vn/wp-content/uploads/2025/08/Don-dang-ky-tham-gia-nhap-hoi-vien-VCCI_Mau-Doanh-nghiep-1.docx"
className="text-[#063e8e] hover:text-yellow-500 italic"
download
>
Đơn đăng ký tham gia nhập hội viên VCCI (Mẫu Doanh nghiệp)
</a>
</li>
<li className="text-justify leading-7">
<a
href="https://vcci-hcm.org.vn/wp-content/uploads/2025/08/Don-dang-ky-tham-gia-nhap-hoi-vien-VCCI_Mau-Hiep-hoi.docx"
className="text-[#063e8e] hover:text-yellow-500 italic"
download
>
Đơn đăng ký tham gia nhập hội viên VCCI (Mẫu Hiệp hội)
</a>
</li>
<li className="text-justify leading-7">
<a
href="https://vcci-hcm.org.vn/wp-content/uploads/2025/08/Huong-dan-ho-so-dang-ky-Hoi-vien-VCCI.docx"
className="text-[#063e8e] hover:text-yellow-500 italic"
download
>
Hướng dẫn hồ sơ đăng ký Hội viên VCCI
</a>
</li>
</ul>
</main>
</div>
</div>
); );
}; };
export default Page; export default Page;
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import ListCategory from "./../components/list-category"; import ListCategory from "./../components/list-category";
import ListFilter from "./../components/list-filter"; import ListFilter from "./../components/list-filter";
import NewsContent from "./../components/card-news"; import CardNews from "./../components/card-news";
import { Pagination } from '@components/base/pagination' import { Pagination } from '@components/base/pagination'
import Image from "next/image"; import Image from "next/image";
import { useGetNews } from '@api/endpoints/news' import { useGetNews } from '@api/endpoints/news'
...@@ -27,7 +27,7 @@ export default function Page() { ...@@ -27,7 +27,7 @@ export default function Page() {
<main className="lg:col-span-2 bg-background"> <main className="lg:col-span-2 bg-background">
<div className='pb-5 overflow-hidden'> <div className='pb-5 overflow-hidden'>
{allData?.responseData.rows.map((news) => ( {allData?.responseData.rows.map((news) => (
<NewsContent key={news.id} news={news} /> <CardNews key={news.id} news={news} />
))} ))}
<div className='w-full flex justify-center mt-4'> <div className='w-full flex justify-center mt-4'>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import ListCategory from "./../components/list-category"; import ListCategory from "./../components/list-category";
import ListFilter from "./../components/list-filter"; import ListFilter from "./../components/list-filter";
import NewsContent from "./../components/card-news"; import CardNews from "./../components/card-news";
import { Pagination } from '@components/base/pagination' import { Pagination } from '@components/base/pagination'
import Image from "next/image"; import Image from "next/image";
import { useGetNews } from '@api/endpoints/news' import { useGetNews } from '@api/endpoints/news'
...@@ -27,7 +27,7 @@ export default function Page() { ...@@ -27,7 +27,7 @@ export default function Page() {
<main className="lg:col-span-2 bg-background"> <main className="lg:col-span-2 bg-background">
<div className='pb-5 overflow-hidden'> <div className='pb-5 overflow-hidden'>
{allData?.responseData.rows.map((news) => ( {allData?.responseData.rows.map((news) => (
<NewsContent key={news.id} news={news} /> <CardNews key={news.id} news={news} />
))} ))}
<div className='w-full flex justify-center mt-4'> <div className='w-full flex justify-center mt-4'>
......
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