Files

127 lines
4.5 KiB
TypeScript

'use client';
import { Bot, Search } from 'lucide-react';
import { useState, useCallback } from 'react';
import Link from 'next/link';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { CategoryFilters } from '@/components/CategoryFilters';
import { useScopedI18n } from '@/locales/client';
import { useQuestionnaire } from '@/hooks/useQuestionnaire';
import { Questionnaire, QuestionnaireCategory } from '@/types';
export default function QuestionnaireList() {
const questionnaires = useQuestionnaire();
const t = useScopedI18n('component.questionnaire.list');
const [searchQuery, setSearchQuery] = useState('');
const [selectedCategory, setSelectedCategory] =
useState<QuestionnaireCategory | null>(null);
const handleCategoryChange = useCallback(
(category: QuestionnaireCategory | null) => {
setSelectedCategory(category);
},
[],
);
// Filter questionnaires based on search terms and the selected purpose.
const filteredQuestionnaires = (questionnaires as Questionnaire[]).filter((q) => {
// Text search filtering
const matchesSearch =
q.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
q.description.toLowerCase().includes(searchQuery.toLowerCase()) ||
q.tags.some((tag) =>
tag.toLowerCase().includes(searchQuery.toLowerCase())
);
const matchesCategory =
selectedCategory === null || q.category === selectedCategory;
return matchesSearch && matchesCategory;
});
return (
<div className="flex flex-col min-h-screen">
<main className="flex-1">
<div className="container px-4 py-6 max-w-6xl mx-auto">
<h1 className="text-2xl font-medium mb-6">{t('title')}</h1>
<div className="mb-5 flex gap-3 border bg-muted/30 p-3 text-sm leading-6 text-muted-foreground">
<Bot className="mt-0.5 h-4 w-4 shrink-0 text-foreground" />
<p>
测评完成后可以复制完整记录给 ChatGPT 解读;如果想长期追踪变化,可以在对话中明确说“请记住我的测评背景和后续变化”。
</p>
</div>
{/* Search bar */}
<div className="mb-4 relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
type="search"
placeholder={t('searchPlaceholder')}
className="pl-10"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
</div>
<CategoryFilters
questionnaires={questionnaires as Questionnaire[]}
value={selectedCategory}
onChange={handleCategoryChange}
/>
{/* Questionnaire list */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{filteredQuestionnaires.length > 0 ? (
filteredQuestionnaires.map((questionnaire) => (
<Card key={questionnaire.id}>
<CardHeader>
<CardTitle>{questionnaire.title}</CardTitle>
</CardHeader>
<CardContent>
<div className="mb-4 h-12">
<p
className="text-sm text-muted-foreground"
style={{
display: '-webkit-box',
WebkitLineClamp: '2',
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
}}
>
{questionnaire.description}
</p>
</div>
</CardContent>
<CardFooter className="flex justify-between items-center">
<span className="text-xs text-muted-foreground">
{questionnaire.time}
</span>
<Link href={`/questionnaire/${questionnaire.id}/details`}>
<Button className="cursor-pointer">
{t('detailButton')}
</Button>
</Link>
</CardFooter>
</Card>
))
) : (
<div className="col-span-3 text-center py-8 text-muted-foreground">
{t('noMatch')}
</div>
)}
</div>
</div>
</main>
</div>
);
}