hilingriviw/src/components/Card/FacilitiesCard/index.tsx

156 lines
5.6 KiB
TypeScript

import { useState } from 'preact/hooks';
import { Dialog, DialogPanel, DialogTitle, Tab, TabGroup, TabList, TabPanel, TabPanels, Transition, TransitionChild } from '@headlessui/react';
export interface FacilityItem {
text: string;
}
export interface FacilityCategory {
title: string;
items: FacilityItem[];
}
interface FacilitiesCardProps {
title?: string;
left: FacilityCategory[];
middle: FacilityCategory[];
right: FacilityCategory[];
seeMoreShow?: boolean;
}
function CategorySection({ category }: { category: FacilityCategory }) {
return (
<div className="mb-6">
<h4 className="text-[#C74F28] underline font-semibold mb-3">{category.title}</h4>
<ol className="list-decimal list-outside pl-5 flex flex-col gap-2.5">
{category.items.map((item, i) => (
<li key={i} className="text-md">
{item.text}
</li>
))}
</ol>
</div>
);
}
export function FacilitiesCard({ title = 'Facilities & Amenities', left, middle, right, seeMoreShow }: FacilitiesCardProps) {
const [dialogOpen, setDialogOpen] = useState(false);
// Flatten all categories from the 3 columns into a single ordered list for tabs
const allCategories = [...left, ...middle, ...right];
function handleSeeMore() {
setDialogOpen(true);
}
return (
<>
<div className="w-full mt-4 bg-black/[0.27] p-6 rounded-xl">
<h3 className="text-center font-bold text-2xl mb-6">{title}</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className={'border-r-2 border-x-gray-700'}>
{left.map((cat, i) => <CategorySection key={i} category={cat} />)}
</div>
<div className={'border-r-2 border-x-gray-700'}>
{middle.map((cat, i) => <CategorySection key={i} category={cat} />)}
</div>
<div className={''}>
{right.map((cat, i) => <CategorySection key={i} category={cat} />)}
</div>
</div>
{seeMoreShow !== undefined && (
<div className="flex justify-end mt-4">
<button
onClick={handleSeeMore}
className="text-sm text-tertiary underline underline-offset-2 hover:text-white transition-colors"
>
See more
</button>
</div>
)}
</div>
{/* Dialog */}
<Transition show={dialogOpen}>
<Dialog onClose={() => setDialogOpen(false)} className="relative z-50">
{/* Backdrop */}
<TransitionChild
enter="ease-out duration-200"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-150"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black/70" />
</TransitionChild>
{/* Panel container */}
<div className="fixed inset-0 flex items-center justify-center p-4">
<TransitionChild
enter="ease-out duration-200"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-150"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<DialogPanel className="bg-[#1a1a1a] text-white rounded-2xl w-full max-w-3xl max-h-[85vh] flex flex-col overflow-hidden relative">
{/* Close button — top right */}
<button
onClick={() => setDialogOpen(false)}
className="absolute top-5 right-5 text-tertiary hover:text-white transition-colors text-2xl leading-none w-9 h-9 flex items-center justify-center rounded-full hover:bg-white/10 z-10"
>
&times;
</button>
{/* Header */}
<div className="px-8 pt-8 pb-0 flex-shrink-0">
<DialogTitle className="text-4xl font-bold mb-5">{title}</DialogTitle>
{/* Pill tabs */}
<TabGroup>
<TabList className="flex flex-row gap-1 bg-[#2a2a2a] rounded-xl p-1 w-fit overflow-x-auto [-webkit-overflow-scrolling:touch] [&::-webkit-scrollbar]:hidden">
{allCategories.map((cat, i) => (
<Tab
key={i}
className="whitespace-nowrap px-5 py-2 text-sm font-medium text-tertiary rounded-lg transition-colors outline-none
data-[selected]:bg-black data-[selected]:text-white
hover:text-white"
>
{cat.title}
</Tab>
))}
</TabList>
{/* Tab panels */}
<TabPanels className="overflow-y-auto py-6 flex-1">
{allCategories.map((cat, i) => (
<TabPanel key={i}>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-x-12 gap-y-4">
{cat.items.map((item, j) => (
<div key={j} className="flex items-start gap-3">
<span className="text-sm leading-relaxed">{item.text}</span>
</div>
))}
</div>
</TabPanel>
))}
</TabPanels>
</TabGroup>
</div>
</DialogPanel>
</TransitionChild>
</div>
</Dialog>
</Transition>
</>
);
}
export default FacilitiesCard;