2026-02-15 16:13:41 +08:00

111 lines
3.6 KiB
TypeScript

import { useState } from 'react';
import { Plus } from 'lucide-react';
import { useQuery } from '@tanstack/react-query';
import api from '@/lib/api';
import type { Todo } from '@/types';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Select } from '@/components/ui/select';
import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
import { ListSkeleton } from '@/components/ui/skeleton';
import TodoList from './TodoList';
import TodoForm from './TodoForm';
export default function TodosPage() {
const [showForm, setShowForm] = useState(false);
const [editingTodo, setEditingTodo] = useState<Todo | null>(null);
const [filters, setFilters] = useState({
priority: '',
category: '',
showCompleted: true,
search: '',
});
const { data: todos = [], isLoading } = useQuery({
queryKey: ['todos'],
queryFn: async () => {
const { data } = await api.get<Todo[]>('/todos');
return data;
},
});
const filteredTodos = todos.filter((todo) => {
if (filters.priority && todo.priority !== filters.priority) return false;
if (filters.category && todo.category !== filters.category) return false;
if (!filters.showCompleted && todo.completed) return false;
if (filters.search && !todo.title.toLowerCase().includes(filters.search.toLowerCase()))
return false;
return true;
});
const handleEdit = (todo: Todo) => {
setEditingTodo(todo);
setShowForm(true);
};
const handleCloseForm = () => {
setShowForm(false);
setEditingTodo(null);
};
return (
<div className="flex flex-col h-full">
<div className="border-b bg-card px-6 py-4">
<div className="flex items-center justify-between mb-4">
<h1 className="text-3xl font-bold">Todos</h1>
<Button onClick={() => setShowForm(true)}>
<Plus className="mr-2 h-4 w-4" />
Add Todo
</Button>
</div>
<div className="flex flex-wrap gap-4">
<div className="flex-1 min-w-[200px]">
<Input
placeholder="Search todos..."
value={filters.search}
onChange={(e) => setFilters({ ...filters, search: e.target.value })}
/>
</div>
<Select
value={filters.priority}
onChange={(e) => setFilters({ ...filters, priority: e.target.value })}
>
<option value="">All Priorities</option>
<option value="low">Low</option>
<option value="medium">Medium</option>
<option value="high">High</option>
</Select>
<Input
placeholder="Filter by category..."
value={filters.category}
onChange={(e) => setFilters({ ...filters, category: e.target.value })}
className="w-48"
/>
<div className="flex items-center gap-2">
<Checkbox
id="show-completed"
checked={filters.showCompleted}
onChange={(e) =>
setFilters({ ...filters, showCompleted: (e.target as HTMLInputElement).checked })
}
/>
<Label htmlFor="show-completed">Show completed</Label>
</div>
</div>
</div>
<div className="flex-1 overflow-y-auto p-6">
{isLoading ? (
<ListSkeleton rows={6} />
) : (
<TodoList todos={filteredTodos} onEdit={handleEdit} />
)}
</div>
{showForm && <TodoForm todo={editingTodo} onClose={handleCloseForm} />}
</div>
);
}