import { AiFaq, type FaqCategory } from "@/components/ui/ai-faq";
/* -------------------------------------------------------------------------- */
/* Simulated AI – in a real app `onAsk` calls your API route (e.g. AI SDK) */
/* -------------------------------------------------------------------------- */
const wait = (ms: number, signal: AbortSignal) =>
new Promise<void>((resolve, reject) => {
const timer = setTimeout(resolve, ms);
signal.addEventListener(
"abort",
() => {
clearTimeout(timer);
reject(new DOMException("Aborted", "AbortError"));
},
{ once: true },
);
});
/** Picks the first answer whose keywords occur in the question and streams it word by word */
function simulateAnswer(answers: { keywords: string[]; text: string }[], fallback: string) {
return async function* (question: string, { signal }: { signal: AbortSignal }) {
const lower = question.toLowerCase();
const text = answers.find((a) => a.keywords.some((k) => lower.includes(k)))?.text ?? fallback;
await wait(900, signal);
for (const word of text.match(/\S+\s*/g) ?? []) {
await wait(28, signal);
yield word;
}
};
}
/* -------------------------------------------------------------------------- */
/* Demo: SaaS product */
/* -------------------------------------------------------------------------- */
const categories: FaqCategory[] = [
{
title: "Getting started",
items: [
{
question: "How long does it take to set up my workspace?",
answer: (
<p>
Most teams are up and running in <strong>under ten minutes</strong>. Create a workspace, invite
your team and import your first project from a CSV file or another tool.
</p>
),
},
{
question: "Can I import data from other tools?",
answer: (
<p>
Yes. We import projects, tasks and comments from the most common project tools. Everything
else works via CSV.
</p>
),
},
{
question: "Is there a mobile app?",
answer: <p>Yes, for iOS and Android. It syncs instantly with the web app and works offline.</p>,
},
],
},
{
title: "Plans & billing",
items: [
{
question: "Is there a free plan?",
answer: (
<p>
The free plan covers up to <strong>3 members and 5 projects</strong>, forever. Upgrade any time
when your team grows.
</p>
),
},
{
question: "Can I switch plans later?",
answer: (
<p>
You can upgrade or downgrade at any time. Changes are prorated to the day, so you only pay for
what you use.
</p>
),
},
{
question: "Which payment methods do you accept?",
answer: <p>All major credit cards, SEPA direct debit and invoice payment on annual plans.</p>,
},
{
question: "How do I cancel my subscription?",
answer: (
<>
<p>Go to Settings → Billing and choose “Cancel plan”. Your workspace stays active until the end of the billing period.</p>
<p>
Need help? <a href="mailto:support@example.com">Contact support</a>.
</p>
</>
),
},
],
},
{
title: "Security & privacy",
items: [
{
question: "Where is my data stored?",
answer: <p>On servers in the EU (Frankfurt), encrypted at rest and in transit.</p>,
},
{
question: "Do you support single sign-on?",
answer: <p>SSO via SAML and SCIM provisioning are included in the Business plan.</p>,
},
{
question: "Can I export all my data?",
answer: <p>Yes, as JSON or CSV at any time – no lock-in.</p>,
},
],
},
{
title: "Integrations",
items: [
{
question: "Which tools can I connect?",
answer: <p>Calendar, chat, code hosting and storage tools – over 40 integrations in total.</p>,
},
{
question: "Is there an API?",
answer: (
<p>
A REST API and webhooks are available on all paid plans. See the{" "}
<a href="https://example.com/docs/api" target="_blank" rel="noopener noreferrer">
API docs
</a>
.
</p>
),
},
],
},
];
const askAi = simulateAnswer(
[
{
keywords: ["discount", "nonprofit", "student", "education"],
text: "Yes! Nonprofits and schools get 50% off every paid plan. Send us a short note with proof of status and we’ll apply the discount to your workspace within a day.",
},
{
keywords: ["guest", "client", "external"],
text: "You can invite guests to single projects for free. They can view and comment, but don’t count towards your paid seats.",
},
{
keywords: ["refund", "money back"],
text: "If you’re not happy within the first 30 days of a paid plan, we refund you in full – just write to support.",
},
],
"Good question! This demo simulates the answer. Connect onAsk to your own API route, for example with the AI SDK and your docs as context, and the answer streams in right here.",
);
function DemoOne() {
return (
<div className="w-full bg-background px-6 py-16 sm:px-10 sm:py-24">
<AiFaq
categories={categories}
defaultOpen={0}
onAsk={askAi}
labels={{ askPlaceholder: "Ask about plans, security …" }}
/>
</div>
);
}
// The 21st studio loads the default export; the named export keeps older setups working
export default DemoOne;
export { DemoOne };