feat(storefront): update FAQ and legal documentation
- Added new FAQ sections for account security, ordering and checkout, returns, shipping, and contact information. - Introduced legal documents including privacy policy, terms of service, data protection, and general terms and conditions. - Updated package dependencies to include gray-matter and remark-gfm for enhanced markdown support.
This commit is contained in:
132
apps/storefront/src/components/support/FaqPageView.tsx
Normal file
132
apps/storefront/src/components/support/FaqPageView.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
"use client";
|
||||
|
||||
import { Accordion } from "@heroui/react";
|
||||
import Link from "next/link";
|
||||
import { useMemo, useState } from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import type { FaqSection } from "@/lib/faq/getFaqSections";
|
||||
|
||||
type FaqPageViewProps = {
|
||||
sections: FaqSection[];
|
||||
lastUpdated?: string;
|
||||
};
|
||||
|
||||
function FaqAnswer({ content }: { content: string }) {
|
||||
return (
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
components={{
|
||||
a: ({ href, children }) =>
|
||||
href?.startsWith("/") ? (
|
||||
<Link
|
||||
href={href}
|
||||
className="font-medium text-[#38a99f] underline transition-colors hover:text-[#236f6b]"
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
) : (
|
||||
<a
|
||||
href={href}
|
||||
className="font-medium text-[#38a99f] underline transition-colors hover:text-[#236f6b]"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
),
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
</ReactMarkdown>
|
||||
);
|
||||
}
|
||||
|
||||
export function FaqPageView({ sections, lastUpdated }: FaqPageViewProps) {
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
|
||||
const selectedSection = useMemo(
|
||||
() => (selectedId ? sections.find((s) => s.title === selectedId) ?? null : null),
|
||||
[sections, selectedId]
|
||||
);
|
||||
|
||||
const sectionId = (title: string) => title.replace(/\s+/g, "-").toLowerCase();
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{sections.map((section) => {
|
||||
const id = sectionId(section.title);
|
||||
const isSelected = selectedId === section.title;
|
||||
return (
|
||||
<button
|
||||
key={id}
|
||||
type="button"
|
||||
onClick={() => setSelectedId(isSelected ? null : section.title)}
|
||||
className="flex flex-col items-start rounded-lg border-2 border-[#236f6b]/20 bg-[#f0f8f7] p-5 text-left transition-colors hover:border-[#38a99f] hover:bg-[#e8f7f6] focus:outline-none focus:ring-2 focus:ring-[#38a99f] focus:ring-offset-2"
|
||||
aria-expanded={isSelected}
|
||||
data-selected={isSelected ? "" : undefined}
|
||||
style={
|
||||
isSelected
|
||||
? { borderColor: "#236f6b", backgroundColor: "#e8f7f6" }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<span className="font-[family-name:var(--font-fraunces)] text-lg font-semibold text-[#1a2e2d]">
|
||||
{section.title}
|
||||
</span>
|
||||
{section.subtitle && (
|
||||
<span className="mt-1 text-sm text-[#3d5554]">
|
||||
{section.subtitle}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{selectedSection && selectedSection.items.length > 0 && (
|
||||
<section
|
||||
id={`faq-${sectionId(selectedSection.title)}`}
|
||||
aria-labelledby={`faq-heading-${sectionId(selectedSection.title)}`}
|
||||
className="rounded-lg border border-[#236f6b]/20 bg-white p-4 md:p-6"
|
||||
>
|
||||
<h2
|
||||
id={`faq-heading-${sectionId(selectedSection.title)}`}
|
||||
className="font-[family-name:var(--font-fraunces)] text-xl font-semibold text-[#236f6b]"
|
||||
>
|
||||
{selectedSection.title}
|
||||
</h2>
|
||||
<Accordion
|
||||
allowsMultipleExpanded
|
||||
className="mt-4 w-full"
|
||||
hideSeparator={false}
|
||||
>
|
||||
{selectedSection.items.map((item, index) => (
|
||||
<Accordion.Item
|
||||
key={`${sectionId(selectedSection.title)}-${index}`}
|
||||
id={`${sectionId(selectedSection.title)}-q-${index}`}
|
||||
>
|
||||
<Accordion.Heading>
|
||||
<Accordion.Trigger className="text-left text-sm font-medium text-[#1a2e2d]">
|
||||
{item.question}
|
||||
<Accordion.Indicator />
|
||||
</Accordion.Trigger>
|
||||
</Accordion.Heading>
|
||||
<Accordion.Panel>
|
||||
<Accordion.Body className="pb-4 pt-1 text-[#1a2e2d] leading-relaxed [&_a]:font-medium [&_a]:text-[#38a99f] [&_a]:underline [&_a:hover]:text-[#236f6b]">
|
||||
<FaqAnswer content={item.answer} />
|
||||
</Accordion.Body>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
))}
|
||||
</Accordion>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{lastUpdated && (
|
||||
<p className="text-sm text-[#3d5554]">Last updated: {lastUpdated}</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user