173 lines
5.4 KiB
TypeScript
173 lines
5.4 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
import Link from 'next/link';
|
|
import { ChevronDown } from 'lucide-react';
|
|
import type { FaqCategory, FaqItem, FaqPageData } from '@/lib/faqDefaults';
|
|
|
|
export function FaqAccordionList({ faqs }: { faqs: FaqItem[] }) {
|
|
const [openIdx, setOpenIdx] = useState<number | null>(null);
|
|
|
|
if (faqs.length === 0) {
|
|
return (
|
|
<p className="text-[13px] text-gray-500 py-8 text-center">
|
|
No questions in this category yet.
|
|
</p>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-3">
|
|
{faqs.map((faq, idx) => {
|
|
const isOpen = openIdx === idx;
|
|
const collapsed =
|
|
faq.answer.length > 180 ? `${faq.answer.slice(0, 180).trim()}…` : faq.answer;
|
|
return (
|
|
<article
|
|
key={`${faq.question}-${idx}`}
|
|
className="bg-white border border-gray-200 rounded-xl px-5 py-4 shadow-xs"
|
|
>
|
|
<button
|
|
type="button"
|
|
onClick={() => setOpenIdx(isOpen ? null : idx)}
|
|
className="w-full text-left flex items-start justify-between gap-3 cursor-pointer"
|
|
>
|
|
<h3 className="text-[15px] font-bold text-[#1E293B] leading-snug">
|
|
{idx + 1}) {faq.question}
|
|
</h3>
|
|
<ChevronDown
|
|
className={`w-4 h-4 mt-1 shrink-0 text-gray-400 transition-transform ${
|
|
isOpen ? 'rotate-180 text-primary' : ''
|
|
}`}
|
|
/>
|
|
</button>
|
|
<div className="mt-2 text-[13px] text-gray-600 leading-relaxed">
|
|
<p className="font-semibold text-gray-800 mb-1">Answer:</p>
|
|
<p>{isOpen ? faq.answer : collapsed}</p>
|
|
{faq.answer.length > 180 ? (
|
|
<button
|
|
type="button"
|
|
onClick={() => setOpenIdx(isOpen ? null : idx)}
|
|
className="mt-2 text-[12px] font-semibold text-primary hover:underline cursor-pointer"
|
|
>
|
|
{isOpen ? 'read less' : 'read more'}
|
|
</button>
|
|
) : null}
|
|
</div>
|
|
</article>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function FaqCategoryNav({
|
|
categories,
|
|
activeSlug,
|
|
}: {
|
|
categories: FaqCategory[];
|
|
activeSlug?: string;
|
|
}) {
|
|
return (
|
|
<nav className="bg-white border border-gray-200 rounded-xl p-4">
|
|
<h2 className="text-[11px] font-bold uppercase tracking-[0.08em] text-gray-400 mb-3">
|
|
FAQ Categories
|
|
</h2>
|
|
<ul className="space-y-1">
|
|
<li>
|
|
<Link
|
|
href="/faqs"
|
|
className={`block rounded-lg px-3 py-2 text-[13px] font-semibold transition-colors ${
|
|
!activeSlug
|
|
? 'bg-primary/10 text-primary'
|
|
: 'text-gray-600 hover:bg-gray-50 hover:text-primary'
|
|
}`}
|
|
>
|
|
All FAQs
|
|
</Link>
|
|
</li>
|
|
{categories.map((cat) => {
|
|
const active = cat.slug === activeSlug;
|
|
return (
|
|
<li key={cat.slug}>
|
|
<Link
|
|
href={`/faqs/${cat.slug}`}
|
|
className={`block rounded-lg px-3 py-2 text-[13px] font-semibold transition-colors ${
|
|
active
|
|
? 'bg-primary/10 text-primary'
|
|
: 'text-gray-600 hover:bg-gray-50 hover:text-primary'
|
|
}`}
|
|
>
|
|
{cat.title}
|
|
</Link>
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</nav>
|
|
);
|
|
}
|
|
|
|
export function FaqHub({ data }: { data: FaqPageData }) {
|
|
return (
|
|
<div className="space-y-8">
|
|
<div>
|
|
<h1 className="text-[28px] md:text-[32px] font-bold text-[#1E293B]">
|
|
{data.title}
|
|
</h1>
|
|
{data.subtitle ? (
|
|
<p className="text-[14px] text-gray-500 mt-2 max-w-2xl">{data.subtitle}</p>
|
|
) : null}
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
{data.categories.map((cat) => (
|
|
<Link
|
|
key={cat.slug}
|
|
href={`/faqs/${cat.slug}`}
|
|
className="bg-white border border-gray-200 rounded-xl p-5 hover:border-primary/40 hover:shadow-sm transition-all"
|
|
>
|
|
<h2 className="text-[16px] font-bold text-[#1E293B]">{cat.title}</h2>
|
|
{cat.description ? (
|
|
<p className="text-[13px] text-gray-500 mt-2 leading-relaxed">
|
|
{cat.description}
|
|
</p>
|
|
) : null}
|
|
<p className="text-[12px] font-semibold text-primary mt-4">
|
|
{cat.faqs.length} question{cat.faqs.length === 1 ? '' : 's'} →
|
|
</p>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function FaqCategoryPage({
|
|
data,
|
|
category,
|
|
}: {
|
|
data: FaqPageData;
|
|
category: FaqCategory;
|
|
}) {
|
|
return (
|
|
<div className="grid grid-cols-1 lg:grid-cols-[260px_minmax(0,1fr)] gap-6 lg:gap-8">
|
|
<aside className="lg:sticky lg:top-28 h-fit">
|
|
<FaqCategoryNav categories={data.categories} activeSlug={category.slug} />
|
|
</aside>
|
|
|
|
<div className="min-w-0">
|
|
<h1 className="text-[26px] md:text-[30px] font-bold text-[#1E293B]">
|
|
{category.title}
|
|
</h1>
|
|
{category.description ? (
|
|
<p className="text-[14px] text-gray-500 mt-1.5 mb-6">{category.description}</p>
|
|
) : (
|
|
<div className="mb-6" />
|
|
)}
|
|
|
|
<FaqAccordionList faqs={category.faqs} />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|