casualroom/apps/fenghuo/web/components/articles/article-toolbar.tsx

141 lines
4.6 KiB
TypeScript
Raw Normal View History

2025-07-28 07:50:50 +08:00
import { Badge } from '@nice/ui/components/badge';
import { Button } from '@nice/ui/components/button';
import { Input } from '@nice/ui/components/input';
import { Label } from '@nice/ui/components/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@nice/ui/components/select';
import { TabsList, TabsTrigger } from '@nice/ui/components/tabs';
import { IconSearch } from '@tabler/icons-react';
import { SORT_OPTIONS, BATCH_ACTIONS } from '@/lib/articles/constants';
import { TermSelect } from '../selector/term-select';
import { useArticlesContext } from './context';
export function ArticleToolbar() {
const {
filters,
selectedArticles,
batchAction,
stats,
updateFilters,
setBatchAction,
handleBatchAction,
resetSelection,
} = useArticlesContext();
return (
<div className="bg-background px-6 py-4 ">
<div className="flex items-center justify-between gap-4">
{/* 左侧:状态标签页 */}
<div className="flex items-center">
<TabsList className="grid w-auto grid-cols-5 h-9">
<TabsTrigger value="all" className="px-3 text-sm">
{' '}
<Badge variant="secondary" className="ml-1 text-xs">
{stats.all}
</Badge>
</TabsTrigger>
<TabsTrigger value="published" className="px-3 text-sm">
{' '}
<Badge variant="secondary" className="ml-1 text-xs">
{stats.published}
</Badge>
</TabsTrigger>
<TabsTrigger value="draft" className="px-3 text-sm">
稿{' '}
<Badge variant="secondary" className="ml-1 text-xs">
{stats.draft}
</Badge>
</TabsTrigger>
<TabsTrigger value="archived" className="px-3 text-sm">
{' '}
<Badge variant="secondary" className="ml-1 text-xs">
{stats.archived}
</Badge>
</TabsTrigger>
<TabsTrigger value="trash" className="px-3 text-sm">
{' '}
<Badge variant="secondary" className="ml-1 text-xs">
{stats.deleted}
</Badge>
</TabsTrigger>
</TabsList>
</div>
{/* 中间:批量操作 */}
<div className="flex items-center justify-center">
{selectedArticles.length > 0 && (
<div className="flex items-center gap-2">
<Badge variant="secondary" className="text-sm font-medium">
{selectedArticles.length}
</Badge>
<Select value={batchAction} onValueChange={setBatchAction}>
<SelectTrigger className="w-32 h-9">
<SelectValue placeholder="批量操作" />
</SelectTrigger>
<SelectContent>
{BATCH_ACTIONS.map((action) => (
<SelectItem key={action.value} value={action.value}>
<div className="flex items-center gap-2">
<action.icon className="h-3 w-3" />
{action.label}
</div>
</SelectItem>
))}
</SelectContent>
</Select>
<Button size="sm" onClick={handleBatchAction} disabled={!batchAction} className="h-9">
</Button>
<Button size="sm" variant="outline" onClick={resetSelection} className="h-9">
</Button>
</div>
)}
</div>
{/* 右侧:搜索、分类和排序 */}
<div className="flex items-center gap-3">
{/* 搜索和分类 */}
<div className="flex items-center gap-3">
<div className="relative w-64">
<IconSearch className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input
placeholder="搜索文章..."
value={filters.searchTerm}
onChange={(e) => updateFilters({ searchTerm: e.target.value })}
className="pl-10 h-9"
/>
</div>
<TermSelect
taxonomySlug="category"
value={filters.categoryFilter}
onValueChange={(value) => updateFilters({ categoryFilter: value as string })}
placeholder="全部分类"
className="h-9 w-32"
allowClear
/>
</div>
{/* 排序 */}
<div className="flex items-center gap-2">
<Label htmlFor="sort-select" className="text-sm font-medium text-muted-foreground whitespace-nowrap">
</Label>
<Select value={filters.sortBy} onValueChange={(value) => updateFilters({ sortBy: value })}>
<SelectTrigger id="sort-select" className="w-48 h-9">
<SelectValue />
</SelectTrigger>
<SelectContent>
{SORT_OPTIONS.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
</div>
</div>
);
}