Commit 3ce24867 authored by Vũ Đình Nguyên's avatar Vũ Đình Nguyên

Merge branch 'feat/home_page' into 'develop'

Feat/home page

See merge request !5
parents fc8def4e b9ca187b
......@@ -2,7 +2,7 @@
import Image from 'next/image'
import { useEffect, useRef, useState } from 'react'
import { Autoplay } from 'swiper/modules'
import { Autoplay, Grid } from 'swiper/modules'
import { Swiper, SwiperSlide } from 'swiper/react'
import { Swiper as SwiperType } from 'swiper/types'
import 'swiper/css'
......@@ -17,7 +17,7 @@ import { GetCategoryAdminResponseType } from '@/api/types/category'
import { GetNewsAdminResponseType } from '@/api/types/news'
import EventCalendar from './components/event-calendar'
const Home = () => {
const Page = () => {
const [tab, setTab] = useState('all')
const [search, setSearch] = useState('')
const [submitSearch, setSubmitSearch] = useState('')
......@@ -34,6 +34,36 @@ const Home = () => {
const rows = allData?.responseData?.rows ?? []
const filteredRows = tab === 'all' ? rows : rows.filter((n) => n.category === tab)
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',
]
useEffect(() => {
const getSlides = (w: number) => {
if (w >= 1024) return 3
......@@ -125,11 +155,17 @@ const Home = () => {
</Swiper>
</section>
<div>
<a href="https://hardwaretools.com.vn/">
<img src="/home/Standard-Banner-1-2024.png.webp" alt="banner" />
</a>
</div>
{/* Tin tức + Liên kết nhanh */}
<section className="flex flex-col lg:flex-row gap-8">
<section className="flex flex-col lg:flex-row gap-5 pb-10 mb-0">
{/* Left */}
<div className="flex-1">
<div className="pb-4 flex justify-between items-center">
<div className="flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-blue-900">
Tin tức
</h2>
......@@ -139,7 +175,7 @@ const Home = () => {
</div>
<hr className="border-blue-900 mb-4" />
<div className="flex flex-col md:flex-row gap-4 md:gap-6">
<div className="flex flex-col md:flex-row gap-5">
<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>
......@@ -177,37 +213,50 @@ const Home = () => {
</div>
{/* Right */}
<aside className="w-full lg:w-1/3">
<div className="pb-4 flex justify-between items-center">
<aside className="w-full lg:w-[30%]">
<div className="flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-blue-900">
Liên kết nhanh
</h2>
<a href="#" className="text-blue-900 hover:underline text-sm sm:text-base">
<a href="#" className="text-blue-900 text-sm sm:text-base">
{'>>'}
</a>
</div>
<hr className="border-blue-900 mb-4" />
<div className="space-y-2 text-blue-900 text-sm md:text-base">
<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 className="space-y-2 text-blue-900 text-sm md:text-base pb-10">
<div>
<a href="https://vcci-hcm.org.vn/lien-ket-nhanh/cam-nang-huong-dan-dau-tu-kinh-doanh-tai-viet-nam-2023/">
🔗 Cẩm nang hướng dẫn đầu tư kinh doanh tại Việt Nam
</a>
</div>
<div>
<a href='https://vcci-hcm.org.vn/lien-ket-nhanh/doanh-nghiep-kien-nghi-ve-chinh-sach-va-phap-luat/'>
🔗 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-8">
<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">
<section className="flex flex-col lg:flex-row gap-5 pb-10 mb-0">
<div className="flex-1 bg-blue-900 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>
<a href="#" className="text-blue-900 hover:underline text-sm sm:text-base">
<a href="#" className="text-[#e8c518] text-sm sm:text-base">
{'>>'}
</a>
</div>
<hr className="border-blue-900 mb-4" />
<hr className="border-[#e8c518] mb-4" />
<div className="flex flex-col md:flex-row gap-4 md:gap-6">
<div className="flex flex-col md:flex-row gap-5">
<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">Khung tin tức VIP</p>
</div>
......@@ -218,60 +267,244 @@ const Home = () => {
</div>
</div>
</div>
<div className='bg-blue-900 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]">
Lịch sự kiện
</h2>
<a href="#" className="text-[#e8c518] hover:underline text-sm sm:text-base">
{'>>'}
</a>
</div>
<hr className="border-[#e8c518] mb-4" />
<EventCalendar />
</aside>
</div>
</section>
<aside className="w-full lg:w-1/3">
<div className="pb-4 flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-blue-900">
Lịch sự kiện
</h2>
<a href="#" className="text-blue-900 hover:underline text-sm sm:text-base">
{/* 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'>
<div>
<a href="https://vcci-hcm.org.vn/wp-content/uploads/2022/11/MEDIA-KIT_VCCI-HCM-2022-Final.pdf">
<img src="/home/Standard-Banner-1-2024.png.webp" alt="banner" />
</a>
</div>
<section className="flex flex-col md:flex-row gap-5 pt-8">
<div className="flex-1">
<div className="flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-blue-900">
Cơ hội kinh doanh
</h2>
<a href="#" className="text-blue-900 text-sm sm:text-base">
{'>>'}
</a>
</div>
<hr className="border-blue-900 mb-4" />
<div className="pt-2 space-y-3">
{rows.slice(0, 4).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 text-sm sm:text-base">
{'>>'}
</a>
</div>
<hr className="border-blue-900 mb-4" />
<div className="pt-2 space-y-3">
{rows.slice(0, 4).map((news) => (
<NewsContent key={news.id} news={news} />
))}
</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>
{/* Hội viên tiêu biểu */}
<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-blue-900">Hội viên tiêu biểu</h2>
<a
href="#"
className="text-blue-900 hover:underline text-sm font-medium"
>
{'>>'}
</a>
</div>
<hr className="border-blue-900 mb-4" />
<EventCalendar />
<hr className="border-blue-900 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"
>
{hoivien.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>
{/* 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-blue-900">Kết nối hội viên</h2>
<a
href="#"
className="text-blue-900 hover:underline text-sm font-medium"
>
{'>>'}
</a>
</div>
<hr className="border-blue-900 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>
{/* Cơ hội kinh doanh + Chính sách */}
<section className="flex flex-col md:flex-row gap-6 lg:gap-10 border-t border-gray-200 pt-8 pb-16">
<div className="flex-1">
<div className="flex justify-between items-center">
<h2 className="text-[18px] sm:text-[20px] font-bold uppercase text-blue-900">
Cơ hội kinh doanh
</h2>
<a href="#" className="text-blue-900 hover:underline text-sm sm:text-base">
{/* 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-blue-900">Video</h2>
<a
href="#"
className="text-blue-900 hover:underline text-sm font-medium"
>
{'>>'}
</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} />
<hr className="border-blue-900 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>
<p className="mt-2 text-sm text-gray-700 font-medium">{video.title}</p>
</div>
))}
</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">
{/* right */}
<aside className="w-full lg:w-[30%]">
<div className="flex justify-between items-center mb-3">
<h2 className="text-xl font-bold uppercase text-blue-900">Đối tác</h2>
<a
href="#"
className="text-blue-900 hover:underline text-sm font-medium"
>
{'>>'}
</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} />
))}
<hr className="border-blue-900 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>
</div>
</aside>
</section>
</div>
</>
)
}
export default Home
export default Page
......@@ -30,24 +30,24 @@ export default function Page() {
<CardNews key={news.id} news={news} />
))}
<div className="w-full flex justify-center mt-4">
<Pagination
pageCount={Number(allData?.responseData.totalPages ?? 1)}
page={Number(allData?.responseData.currentPage ?? page)}
onChangePage={(p) => setPage(p)}
onGoToPreviousPage={() => setPage(Math.max(1, page - 1))}
onGoToNextPage={() =>
setPage(
Math.min(
Number(allData?.responseData.totalPages ?? 1),
page + 1
)
)
}
/>
</div>
</div>
</main>
<div className='w-full flex justify-center mt-4'>
<Pagination
pageCount={Number(allData?.responseData.totalPages ?? 1)}
page={Number(allData?.responseData.currentPage ?? page)}
onChangePage={(p) => setPage(p)}
onGoToPreviousPage={() => setPage(Math.max(1, page - 1))}
onGoToNextPage={() =>
setPage(
Math.min(
Number(allData?.responseData.totalPages ?? 1),
page + 1
)
)
}
/>
</div>
</div>
</main>
{/* Sidebar */}
<aside className="space-y-6">
......@@ -57,4 +57,4 @@ export default function Page() {
</div>
</div>
);
}
}
\ No newline at end of file
......@@ -31,13 +31,20 @@ export default function Page() {
))}
<div className='w-full flex justify-center mt-4'>
<Pagination
pageCount={Number(allData?.responseData.totalPages ?? 1)}
page={Number(allData?.responseData.currentPage ?? page)}
onChangePage={(p) => setPage(p)}
onGoToPreviousPage={() => setPage(Math.max(1, page - 1))}
onGoToNextPage={() => setPage(Math.min(Number(allData?.responseData.totalPages ?? 1), page + 1))}
/>
<Pagination
pageCount={Number(allData?.responseData.totalPages ?? 1)}
page={Number(allData?.responseData.currentPage ?? page)}
onChangePage={(p) => setPage(p)}
onGoToPreviousPage={() => setPage(Math.max(1, page - 1))}
onGoToNextPage={() =>
setPage(
Math.min(
Number(allData?.responseData.totalPages ?? 1),
page + 1
)
)
}
/>
</div>
</div>
</main>
......
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