"use client" import { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Plus, Check, RotateCcw, Download, Upload, Trash2, Edit2, Save, X } from 'lucide-react'; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { useToast } from "@/components/ui/use-toast"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; interface ChecklistItem { id: string text: string completed: boolean } interface Checklist { id: string name: string items: ChecklistItem[] } export function CombinedChecklistAppComponent() { const [checklists, setChecklists] = useState([]) const [currentChecklist, setCurrentChecklist] = useState('') const [newItemText, setNewItemText] = useState('') const [newChecklistName, setNewChecklistName] = useState('') const [editingId, setEditingId] = useState(null) const [editName, setEditName] = useState('') const { showToast } = useToast() useEffect(() => { const savedChecklists = localStorage.getItem('checklists') if (savedChecklists) { setChecklists(JSON.parse(savedChecklists)) } }, []) useEffect(() => { localStorage.setItem('checklists', JSON.stringify(checklists)) }, [checklists]) const addChecklist = () => { if (newChecklistName.trim() === '') return const newChecklist: Checklist = { id: Date.now().toString(), name: newChecklistName, items: [] } setChecklists([...checklists, newChecklist]) setNewChecklistName('') setCurrentChecklist(newChecklist.id) showToast({ title: "新检查单已创建", description: `"${newChecklistName}" 已添加到您的检查单列表。`, }) } const addItem = () => { if (newItemText.trim() === '' || currentChecklist === '') return const newItem: ChecklistItem = { id: Date.now().toString(), text: newItemText, completed: false } setChecklists(checklists.map(list => list.id === currentChecklist ? { ...list, items: [...list.items, newItem] } : list )) setNewItemText('') } const toggleItem = (itemId: string) => { setChecklists(checklists.map(list => list.id === currentChecklist ? { ...list, items: list.items.map(item => item.id === itemId ? { ...item, completed: !item.completed } : item ) } : list )) } const deleteItem = (itemId: string) => { setChecklists(checklists.map(list => list.id === currentChecklist ? { ...list, items: list.items.filter(item => item.id !== itemId) } : list )) showToast({ title: "检查项已删除", description: "该项目已从您的检查单中移除。", }) } const resetChecklist = () => { setChecklists(checklists.map(list => list.id === currentChecklist ? { ...list, items: list.items.map(item => ({ ...item, completed: false })) } : list )) showToast({ title: "检查单已重置", description: "所有项目已标记为未完成。", }) } const exportData = () => { const dataStr = JSON.stringify(checklists) const dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr) const exportFileDefaultName = 'checklists.json' const linkElement = document.createElement('a') linkElement.setAttribute('href', dataUri) linkElement.setAttribute('download', exportFileDefaultName) linkElement.click() showToast({ title: "数据已导出", description: "您的检查单数据已成功导出为 JSON 文件。", }) } const importData = (event: React.ChangeEvent) => { const file = event.target.files?.[0] if (file) { const reader = new FileReader() reader.onload = (e) => { const content = e.target?.result if (typeof content === 'string') { try { const importedChecklists = JSON.parse(content) setChecklists(importedChecklists) showToast({ title: "数据导入成功", description: "您的检查单已成功导入。", }) } catch (error) { showToast({ title: "导入失败", description: "无法解析导入的文件。请确保它是有效的 JSON 格式。", variant: "destructive", }) } } } reader.readAsText(file) } } const startEditing = (id: string, name: string) => { setEditingId(id) setEditName(name) } const saveEdit = (id: string) => { setChecklists(checklists.map(list => list.id === id ? { ...list, name: editName } : list )) setEditingId(null) showToast({ title: "检查单已更新", description: `检查单名称已更改为 "${editName}"。`, }) } const cancelEdit = () => { setEditingId(null) setEditName('') } const deleteChecklist = (id: string) => { setChecklists(checklists.filter(list => list.id !== id)) if (currentChecklist === id) { setCurrentChecklist('') } showToast({ title: "检查单已删除", description: "该检查单及其所有项目已被移除。", variant: "destructive", }) } return (
检查单应用 检查单 管理检查单
setNewChecklistName(e.target.value)} placeholder="输入检查单名称" className="mr-2 flex-grow" />
{currentChecklist && (
setNewItemText(e.target.value)} placeholder="输入新的检查项" className="mr-2 flex-grow" />
{checklists.find(list => list.id === currentChecklist)?.items.map(item => ( toggleItem(item.id)} whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }} > {item.completed && } {item.text} deleteItem(item.id)} className="text-destructive hover:text-destructive/90 p-1 rounded-full" whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }} > ))}
)}
{checklists.map(checklist => ( {editingId === checklist.id ? (
setEditName(e.target.value)} className="flex-grow" placeholder="输入新的检查单名称" />
) : (
{checklist.name}
确认删除

您确定要删除 "{checklist.name}" 检查单吗?此操作无法撤销。

)}

共 {checklist.items.length} 个项目, {checklist.items.filter(item => item.completed).length} 个已完成

))}
{checklists.length === 0 && ( 暂无检查单。请在检查单标签页创建新的检查单。 )}
) }