5801cbf85b
- KnowledgeBoard + KnowledgeItem models + migration (DRAFT/PUBLISHED/ARCHIVED status, slug per tenant) - KnowledgeModule: admin CRUD for boards + items (auto-slug, status workflow) - Member endpoint GET /my/knowledge?q= — published items grouped by board, optional text search over question/answer - /my/knowledge page: search box + collapsible boards with accordion FAQ items - KnowledgeItem accordion + KnowledgeSearch (debounced URL-driven) client components - Knowledge nav item; register KnowledgeModule Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
39 lines
1.1 KiB
TypeScript
39 lines
1.1 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
|
|
interface Props {
|
|
question: string;
|
|
answer: string;
|
|
tags: string[];
|
|
}
|
|
|
|
export function KnowledgeItem({ question, answer, tags }: Props) {
|
|
const [open, setOpen] = useState(false);
|
|
|
|
return (
|
|
<div className="border-b border-gray-100 last:border-0">
|
|
<button
|
|
type="button"
|
|
onClick={() => setOpen((o) => !o)}
|
|
className="w-full flex items-center justify-between gap-3 py-3.5 text-left"
|
|
>
|
|
<span className="text-sm font-medium text-gray-900">{question}</span>
|
|
<span className={`text-gray-400 transition-transform shrink-0 ${open ? 'rotate-180' : ''}`}>⌄</span>
|
|
</button>
|
|
{open && (
|
|
<div className="pb-4">
|
|
<p className="text-sm text-gray-600 whitespace-pre-line leading-relaxed">{answer}</p>
|
|
{tags.length > 0 && (
|
|
<div className="flex flex-wrap gap-1.5 mt-2">
|
|
{tags.map((t) => (
|
|
<span key={t} className="text-[10px] bg-gray-100 text-gray-500 rounded-full px-2 py-0.5">{t}</span>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|