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

fix/fallback img and active navigation item

parent 21c709a6
...@@ -15,7 +15,7 @@ function CardEvent({ event }: { event: EventItem }) { ...@@ -15,7 +15,7 @@ function CardEvent({ event }: { event: EventItem }) {
className='w-[100px] md:w-[130px] aspect-3/2 object-cover' className='w-[100px] md:w-[130px] aspect-3/2 object-cover'
onError={(e) => { onError={(e) => {
e.currentTarget.onerror = null e.currentTarget.onerror = null
e.currentTarget.src = "/VCCI-Chung-300x200-1.png" e.currentTarget.src = "/img-error.png"
}} }}
/> />
<div className='flex-1'> <div className='flex-1'>
......
...@@ -15,7 +15,7 @@ function CardNews({ news }: { news: NewsItem }) { ...@@ -15,7 +15,7 @@ function CardNews({ news }: { news: NewsItem }) {
className="w-[100px] md:w-[130px] aspect-3/2 object-cover" className="w-[100px] md:w-[130px] aspect-3/2 object-cover"
onError={(e) => { onError={(e) => {
e.currentTarget.onerror = null e.currentTarget.onerror = null
e.currentTarget.src = "/VCCI-Chung-300x200-1.png" e.currentTarget.src = "/img-error.png"
}} }}
/> />
<div className="flex-1"> <div className="flex-1">
......
...@@ -186,7 +186,7 @@ const Page = () => { ...@@ -186,7 +186,7 @@ const Page = () => {
className="w-full aspect-3/2 sm:h-56 md:h-64 object-cover" className="w-full aspect-3/2 sm:h-56 md:h-64 object-cover"
onError={(e) => { onError={(e) => {
e.currentTarget.onerror = null e.currentTarget.onerror = null
e.currentTarget.src = "/VCCI-Chung-300x200-1.png" e.currentTarget.src = "/img-error.png"
}} }}
/> />
<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 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">
...@@ -242,7 +242,7 @@ const Page = () => { ...@@ -242,7 +242,7 @@ const Page = () => {
className="w-full h-full object-cover" className="w-full h-full object-cover"
onError={(e) => { onError={(e) => {
e.currentTarget.onerror = null e.currentTarget.onerror = null
e.currentTarget.src = "/VCCI-Chung-300x200-1.png" e.currentTarget.src = "/img-error.png"
}} }}
/> />
</div> </div>
...@@ -380,7 +380,7 @@ const Page = () => { ...@@ -380,7 +380,7 @@ const Page = () => {
className="w-full h-full object-cover" className="w-full h-full object-cover"
onError={(e) => { onError={(e) => {
(e.target as HTMLImageElement).src = (e.target as HTMLImageElement).src =
"/VCCI-Chung-300x200-1.png"; "/img-error.png";
}} }}
/> />
</div> </div>
...@@ -459,7 +459,7 @@ const Page = () => { ...@@ -459,7 +459,7 @@ const Page = () => {
className="w-full h-full object-cover" className="w-full h-full object-cover"
onError={(e) => { onError={(e) => {
e.currentTarget.onerror = null e.currentTarget.onerror = null
e.currentTarget.src = "/VCCI-Chung-300x200-1.png" e.currentTarget.src = "/img-error.png"
}} }}
/> />
<div className="absolute bg-white opacity-80 bottom-5 left-5 right-5 p-5"> <div className="absolute bg-white opacity-80 bottom-5 left-5 right-5 p-5">
...@@ -504,7 +504,7 @@ const Page = () => { ...@@ -504,7 +504,7 @@ const Page = () => {
className="w-full h-full object-cover" className="w-full h-full object-cover"
onError={(e) => { onError={(e) => {
e.currentTarget.onerror = null e.currentTarget.onerror = null
e.currentTarget.src = "/VCCI-Chung-300x200-1.png" e.currentTarget.src = "/img-error.png"
}} }}
/> />
<div className="absolute bg-white opacity-80 bottom-5 left-5 right-5 p-5"> <div className="absolute bg-white opacity-80 bottom-5 left-5 right-5 p-5">
......
...@@ -46,7 +46,7 @@ export default function DynamicPage() { ...@@ -46,7 +46,7 @@ export default function DynamicPage() {
} }
if (slug.length === 2) { if (slug.length === 2) {
return category?.responseData.is_article ? <ArticlePage /> : <InformationPage />; return category?.responseData?.is_article ? <ArticlePage /> : <InformationPage />;
} }
if (slug.length === 3) { if (slug.length === 3) {
......
...@@ -45,7 +45,7 @@ export default function EventDetailPage() { ...@@ -45,7 +45,7 @@ export default function EventDetailPage() {
<div className="grid grid-cols-1 lg:grid-cols-3 gap-5"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-5">
<main className="lg:col-span-2 bg-white border rounded-md p-8"> <main className="lg:col-span-2 bg-white border rounded-md p-8">
<div className='pb-5 text-primary text-2xl leading-normal font-medium'> <div className='pb-5 text-primary text-2xl leading-normal font-medium'>
{eventsDetail?.responseData?.rows[0].name} {eventsDetail?.responseData?.rows[0]?.name}
</div> </div>
<hr className="py-2" /> <hr className="py-2" />
...@@ -55,8 +55,8 @@ export default function EventDetailPage() { ...@@ -55,8 +55,8 @@ export default function EventDetailPage() {
{eventsDetail?.responseData?.rows[0].image ? ( {eventsDetail?.responseData?.rows[0].image ? (
<div className="w-full h-52 relative "> <div className="w-full h-52 relative ">
<EventImage <EventImage
src={`${BASE_URL.imageEndpoint}${eventsDetail.responseData.rows[0].image}`} src={`${BASE_URL.imageEndpoint}${eventsDetail?.responseData?.rows[0].image}`}
alt={eventsDetail.responseData.rows[0].name || "image"} alt={eventsDetail?.responseData?.rows[0]?.name || "image"}
/> />
</div> </div>
) : ( ) : (
...@@ -89,8 +89,8 @@ export default function EventDetailPage() { ...@@ -89,8 +89,8 @@ export default function EventDetailPage() {
<div className="text-sm text-gray-500 flex items-center gap-2"> <div className="text-sm text-gray-500 flex items-center gap-2">
<MapPin className="h-5 w-5 text-blue-600" /> <MapPin className="h-5 w-5 text-blue-600" />
<div className="text-sm font-medium text-gray-800"> <div className="text-sm font-medium text-gray-800">
Địa điểm: {eventsDetail?.responseData?.rows[0].location ?? Địa điểm: {eventsDetail?.responseData?.rows[0]?.location ??
eventsDetail?.responseData?.rows[0].province ?? eventsDetail?.responseData?.rows[0]?.province ??
"-"} "-"}
</div> </div>
</div> </div>
...@@ -98,9 +98,9 @@ export default function EventDetailPage() { ...@@ -98,9 +98,9 @@ export default function EventDetailPage() {
<div className="text-sm text-gray-500 flex items-center gap-2"> <div className="text-sm text-gray-500 flex items-center gap-2">
<CreditCard className="h-5 w-5 text-yellow-400" /> <CreditCard className="h-5 w-5 text-yellow-400" />
<div className="text-sm font-medium text-gray-800"> <div className="text-sm font-medium text-gray-800">
Phí tham dự: {eventsDetail?.responseData?.rows[0].table_cost Phí tham dự: {eventsDetail?.responseData?.rows[0]?.table_cost
? `${eventsDetail.responseData.rows[0].table_count ? `${eventsDetail?.responseData?.rows[0]?.table_count
} Bàn : ${eventsDetail.responseData.rows[0].table_cost.toLocaleString()} đ` } Bàn : ${eventsDetail?.responseData?.rows[0]?.table_cost.toLocaleString()} đ`
: "Vui lòng xem chi tiết trong bài"} : "Vui lòng xem chi tiết trong bài"}
</div> </div>
</div> </div>
...@@ -110,7 +110,7 @@ export default function EventDetailPage() { ...@@ -110,7 +110,7 @@ export default function EventDetailPage() {
{/* Full description */} {/* Full description */}
<div className="p-7.5 prose tiptap overflow-hidden"> <div className="p-7.5 prose tiptap overflow-hidden">
{parse(eventsDetail?.responseData?.rows[0].description ?? "")} {parse(eventsDetail?.responseData?.rows[0]?.description ?? "")}
</div> </div>
</main> </main>
...@@ -118,12 +118,12 @@ export default function EventDetailPage() { ...@@ -118,12 +118,12 @@ export default function EventDetailPage() {
<aside className="space-y-6"> <aside className="space-y-6">
<EventCalendar /> <EventCalendar />
<div className="bg-white border rounded-md overflow-hidden"> <div className="bg-white border rounded-md overflow-hidden">
<div className="w-full h-56 relative bg-gray-100"> <div className="w-full h-75 relative bg-gray-100">
<Image <Image
src="/banner.webp" src="/banner.webp"
alt="Quảng cáo" alt="Quảng cáo"
fill fill
className="object-cover" className="object-contain"
/> />
</div> </div>
</div> </div>
...@@ -152,7 +152,7 @@ function EventImage({ src, alt }: EventImageProps) { ...@@ -152,7 +152,7 @@ function EventImage({ src, alt }: EventImageProps) {
className="object-cover" className="object-cover"
onError={() => { onError={() => {
// swap to local fallback file when Next/Image fails to load the provided URL // swap to local fallback file when Next/Image fails to load the provided URL
if (imgSrc !== "/VCCI-Chung-300x200-1.png") setImgSrc("/VCCI-Chung-300x200-1.png"); if (imgSrc !== "/img-error.png") setImgSrc("/img-error.png");
}} }}
/> />
); );
......
...@@ -50,7 +50,7 @@ export default function EventPage() { ...@@ -50,7 +50,7 @@ export default function EventPage() {
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<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">
{events?.responseData.rows.map((item) => ( {events?.responseData?.rows?.map((item) => (
<CardEvents <CardEvents
key={item.id} key={item.id}
event={item} event={item}
...@@ -59,12 +59,12 @@ export default function EventPage() { ...@@ -59,12 +59,12 @@ export default function EventPage() {
))} ))}
<div className="w-full flex justify-center mt-4"> <div className="w-full flex justify-center mt-4">
<Pagination <Pagination
pageCount={Number(events?.responseData.totalPages ?? 1)} pageCount={Number(events?.responseData?.totalPages ?? 1)}
page={Number(events?.responseData.currentPage ?? page)} page={Number(events?.responseData?.currentPage ?? page)}
onChangePage={setPage} onChangePage={setPage}
onGoToPreviousPage={() => setPage(Math.max(1, page - 1))} onGoToPreviousPage={() => setPage(Math.max(1, page - 1))}
onGoToNextPage={() => onGoToNextPage={() =>
setPage(Math.min(Number(events?.responseData.totalPages ?? 1), page + 1)) setPage(Math.min(Number(events?.responseData?.totalPages ?? 1), page + 1))
} }
/> />
</div> </div>
......
...@@ -37,7 +37,7 @@ export default function InformationPage() { ...@@ -37,7 +37,7 @@ export default function InformationPage() {
<ListCategory categories={category?.responseData?.children} /> <ListCategory categories={category?.responseData?.children} />
<main className=" bg-white border rounded-md py-10 px-30"> <main className=" bg-white border rounded-md py-10 px-30">
<div className='text-primary text-2xl leading-normal font-bold'> <div className='text-primary text-2xl leading-normal font-bold'>
{data?.responseData?.rows[0].title} {data?.responseData?.rows[0]?.title}
</div> </div>
{/* <div className='flex items-center gap-2 text-sm mb-4'> {/* <div className='flex items-center gap-2 text-sm mb-4'>
<span className='text-base text-blue-700'> <span className='text-base text-blue-700'>
...@@ -47,7 +47,7 @@ export default function InformationPage() { ...@@ -47,7 +47,7 @@ export default function InformationPage() {
<hr className="my-5" /> <hr className="my-5" />
<div className='flex-1 text-app-grey text-base overflow-hidden'> <div className='flex-1 text-app-grey text-base overflow-hidden'>
<div className="prose tiptap overflow-hidden"> <div className="prose tiptap overflow-hidden">
{parse(data?.responseData?.rows[0].description ?? '')} {parse(data?.responseData?.rows[0]?.description ?? '')}
</div> </div>
</div> </div>
</main> </main>
......
export interface NewsDetailItem {
id: string
title: string
thumbnail: string
external_link: string
description: string
release_at: string
is_active: boolean
created_at: string
created_by: string | null
updated_at: string
updated_by: string | null
mode: 'NOW' | string
category: string
}
export interface NewsDetailResponseData {
count: number
rows: NewsDetailItem[]
totalPages: number
currentPage: number
}
export interface GetNewsDetailResponseType {
message: string
message_en: string
responseData: NewsDetailItem
status: 'success' | 'error'
timeStamp: string
violations: any | null
}
\ No newline at end of file
import { NewsDetailItem } from './CardNews.type'; import { NewsItem } from '@/api/types/news';
import Links from '@links/index' import Links from '@links/index'
import dayjs from 'dayjs'; import dayjs from 'dayjs';
...@@ -20,7 +20,7 @@ const stripImagesAndHtml = (html?: string) => { ...@@ -20,7 +20,7 @@ const stripImagesAndHtml = (html?: string) => {
return withoutImgs.replace(/<[^>]*>/g, '') return withoutImgs.replace(/<[^>]*>/g, '')
} }
const CardNews = ({ news, link }: { news: NewsDetailItem, link: string }) => { const CardNews = ({ news, link }: { news: NewsItem, link: string }) => {
return ( return (
<a <a
href={`${link}`} href={`${link}`}
......
import { usePathname } from "next/navigation";
import Link from "next/link"; import Link from "next/link";
type MenuItemProps = { type MenuItemProps = {
...@@ -7,26 +8,35 @@ type MenuItemProps = { ...@@ -7,26 +8,35 @@ type MenuItemProps = {
}; };
const MenuItem = ({ title, link, items }: MenuItemProps) => { const MenuItem = ({ title, link, items }: MenuItemProps) => {
const pathname = usePathname();
const isActive = !!link && (pathname === link || (link !== "/" && pathname.startsWith(link)));
return ( return (
<div className="group relative"> <div className="group relative">
<Link <Link
href={`${link || ""}`} href={link ?? "#"}
className="px-3 py-5 text-[16px] font-semibold text-[#124588] hover:text-[#E8C518] transition block" className={`px-3 py-5 text-[16px] font-semibold transition block
${isActive ? "text-[#E8C518]" : "text-[#124588] hover:text-[#E8C518]"}
`}
> >
{title} {title}
</Link> </Link>
{/* Dropdown */} {/* Dropdown */}
<div className="absolute left-0 top-full hidden group-hover:block bg-[#124588]/98 text-white text-[14px] font-medium min-w-[220px] shadow-lg"> <div className="absolute left-0 top-full hidden group-hover:block bg-[#124588]/98 text-white text-[14px] font-medium min-w-[220px] shadow-lg">
{items.map((item, i) => ( {items.map((item, i) => {
<Link const isItemActive = pathname === item.link;
key={i} return (
href={`${item.link}`} <Link
className="block px-5 py-3 hover:bg-[#e8c518]/80 cursor-pointer whitespace-nowrap transition" key={i}
> href={item.link}
{item.title} className={`block px-5 py-3 cursor-pointer whitespace-nowrap transition ${isItemActive ? "bg-[#e8c518]/80" : "hover:bg-[#e8c518]/80"
</Link> }`}
))} >
{item.title}
</Link>
);
})}
</div> </div>
</div> </div>
); );
......
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