93 lines
3.3 KiB
TypeScript
93 lines
3.3 KiB
TypeScript
|
|
'use client';
|
||
|
|
|
||
|
|
import * as React from 'react';
|
||
|
|
import { Card } from '@/components/ui/Card';
|
||
|
|
import { Button } from '@/components/ui/Button';
|
||
|
|
import { Sparkles, ChevronDown, ChevronUp } from 'lucide-react';
|
||
|
|
import { cn } from '@/lib/utils/cn';
|
||
|
|
import { TEXT_TEMPLATES, TEMPLATE_CATEGORIES } from '@/lib/constants/templates';
|
||
|
|
|
||
|
|
export interface TextTemplatesProps {
|
||
|
|
onSelectTemplate: (text: string) => void;
|
||
|
|
className?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function TextTemplates({ onSelectTemplate, className }: TextTemplatesProps) {
|
||
|
|
const [isExpanded, setIsExpanded] = React.useState(false);
|
||
|
|
const [selectedCategory, setSelectedCategory] = React.useState<string>('all');
|
||
|
|
|
||
|
|
const filteredTemplates = React.useMemo(() => {
|
||
|
|
if (selectedCategory === 'all') return TEXT_TEMPLATES;
|
||
|
|
return TEXT_TEMPLATES.filter(t => t.category === selectedCategory);
|
||
|
|
}, [selectedCategory]);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Card className={className}>
|
||
|
|
<div className="p-4">
|
||
|
|
<button
|
||
|
|
onClick={() => setIsExpanded(!isExpanded)}
|
||
|
|
className="w-full flex items-center justify-between text-sm font-medium hover:text-primary transition-colors"
|
||
|
|
>
|
||
|
|
<div className="flex items-center gap-2">
|
||
|
|
<Sparkles className="h-4 w-4" />
|
||
|
|
<span>Text Templates</span>
|
||
|
|
<span className="text-xs text-muted-foreground">({TEXT_TEMPLATES.length})</span>
|
||
|
|
</div>
|
||
|
|
{isExpanded ? (
|
||
|
|
<ChevronUp className="h-4 w-4" />
|
||
|
|
) : (
|
||
|
|
<ChevronDown className="h-4 w-4" />
|
||
|
|
)}
|
||
|
|
</button>
|
||
|
|
|
||
|
|
{isExpanded && (
|
||
|
|
<div className="mt-4 space-y-3 slide-down">
|
||
|
|
{/* Category Filter */}
|
||
|
|
<div className="flex gap-1 flex-wrap">
|
||
|
|
<button
|
||
|
|
onClick={() => setSelectedCategory('all')}
|
||
|
|
className={cn(
|
||
|
|
'px-2 py-1 text-xs rounded-md transition-colors',
|
||
|
|
selectedCategory === 'all'
|
||
|
|
? 'bg-primary text-primary-foreground'
|
||
|
|
: 'bg-muted hover:bg-muted/80'
|
||
|
|
)}
|
||
|
|
>
|
||
|
|
All
|
||
|
|
</button>
|
||
|
|
{TEMPLATE_CATEGORIES.map((cat) => (
|
||
|
|
<button
|
||
|
|
key={cat.id}
|
||
|
|
onClick={() => setSelectedCategory(cat.id)}
|
||
|
|
className={cn(
|
||
|
|
'px-2 py-1 text-xs rounded-md transition-colors',
|
||
|
|
selectedCategory === cat.id
|
||
|
|
? 'bg-primary text-primary-foreground'
|
||
|
|
: 'bg-muted hover:bg-muted/80'
|
||
|
|
)}
|
||
|
|
>
|
||
|
|
{cat.icon} {cat.label}
|
||
|
|
</button>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Templates Grid */}
|
||
|
|
<div className="grid grid-cols-2 sm:grid-cols-3 gap-2">
|
||
|
|
{filteredTemplates.map((template) => (
|
||
|
|
<button
|
||
|
|
key={template.id}
|
||
|
|
onClick={() => onSelectTemplate(template.text)}
|
||
|
|
className="px-3 py-2 text-xs bg-muted hover:bg-accent hover:scale-105 rounded-md transition-all text-left truncate"
|
||
|
|
title={template.text}
|
||
|
|
>
|
||
|
|
{template.label}
|
||
|
|
</button>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</Card>
|
||
|
|
);
|
||
|
|
}
|