import React, { useState } from "react"; import { Pressable, ScrollView, StyleSheet, Text, TextInput, View, } from "react-native"; interface Todo { id: string; title: string; description: string; emoji: string; status: "pending" | "completed"; } interface Theme { bg: string; primary: string; card: string; text: string; muted: string; border: string; } interface TaskManagerProps { todos: Todo[]; onUpdate: (todos: Todo[]) => void; isAgentRunning: boolean; theme: Theme; } const EMOJI_OPTIONS = ["✅", "🔥", "🎯", "💡", "🚀"]; function generateId() { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { const r = (Math.random() * 16) | 0; return (c === "x" ? r : (r & 0x3) | 0x8).toString(16); }); } function TodoCard({ todo, onToggleStatus, onDelete, onUpdateTitle, onUpdateDescription, onUpdateEmoji, theme, }: { todo: Todo; onToggleStatus: (todo: Todo) => void; onDelete: (todo: Todo) => void; onUpdateTitle: (id: string, title: string) => void; onUpdateDescription: (id: string, desc: string) => void; onUpdateEmoji: (id: string, emoji: string) => void; theme: Theme; }) { const [editingField, setEditingField] = useState< "title" | "description" | null >(null); const [editValue, setEditValue] = useState(""); const [showEmojiPicker, setShowEmojiPicker] = useState(false); const isCompleted = todo.status === "completed"; const startEdit = (field: "title" | "description") => { setEditingField(field); setEditValue(field === "title" ? todo.title : todo.description); }; const saveEdit = (field: "title" | "description") => { if (editValue.trim()) { if (field === "title") onUpdateTitle(todo.id, editValue.trim()); else onUpdateDescription(todo.id, editValue.trim()); } setEditingField(null); }; return ( setShowEmojiPicker(!showEmojiPicker)} style={[styles.emojiButton, { backgroundColor: theme.bg }]} > {todo.emoji} onToggleStatus(todo)} style={[ styles.checkbox, { borderColor: theme.primary, backgroundColor: isCompleted ? theme.primary : "transparent", }, ]} > {isCompleted && } onDelete(todo)} style={styles.deleteButton}> {showEmojiPicker && ( {EMOJI_OPTIONS.map((e) => ( { onUpdateEmoji(todo.id, e); setShowEmojiPicker(false); }} style={styles.emojiOption} > {e} ))} )} {editingField === "title" ? ( saveEdit("title")} onSubmitEditing={() => saveEdit("title")} autoFocus /> ) : ( startEdit("title")}> {todo.title} )} {editingField === "description" ? ( saveEdit("description")} multiline autoFocus /> ) : ( startEdit("description")}> {todo.description.length > 120 ? todo.description.slice(0, 120) + "..." : todo.description} )} ); } function TodoSection({ title, todos, showAddButton, onAddTodo, onToggleStatus, onDelete, onUpdateTitle, onUpdateDescription, onUpdateEmoji, isAgentRunning, theme, }: { title: string; todos: Todo[]; showAddButton?: boolean; onAddTodo?: () => void; onToggleStatus: (todo: Todo) => void; onDelete: (todo: Todo) => void; onUpdateTitle: (id: string, title: string) => void; onUpdateDescription: (id: string, desc: string) => void; onUpdateEmoji: (id: string, emoji: string) => void; isAgentRunning: boolean; theme: Theme; }) { return ( {title} {todos.length} {showAddButton && ( + Add )} {todos.length === 0 ? ( {title === "To Do" ? "No pending tasks" : "No completed tasks yet"} ) : ( todos.map((todo) => ( )) )} ); } export function TaskManager({ todos, onUpdate, isAgentRunning, theme, }: TaskManagerProps) { const pendingTodos = todos.filter((t) => t.status === "pending"); const completedTodos = todos.filter((t) => t.status === "completed"); const toggleStatus = (todo: Todo) => { const updated = todos.map((t) => t.id === todo.id ? { ...t, status: (t.status === "completed" ? "pending" : "completed") as | "pending" | "completed", } : t, ); onUpdate(updated); }; const deleteTodo = (todo: Todo) => { onUpdate(todos.filter((t) => t.id !== todo.id)); }; const updateTitle = (id: string, title: string) => { onUpdate(todos.map((t) => (t.id === id ? { ...t, title } : t))); }; const updateDescription = (id: string, description: string) => { onUpdate(todos.map((t) => (t.id === id ? { ...t, description } : t))); }; const updateEmoji = (id: string, emoji: string) => { onUpdate(todos.map((t) => (t.id === id ? { ...t, emoji } : t))); }; const addTodo = () => { onUpdate([ ...todos, { id: generateId(), title: "New Todo", description: "Add a description", emoji: "🎯", status: "pending" as const, }, ]); }; if (todos.length === 0) { return ( ✏️ No todos yet Create your first task to get started Add a task ); } return ( ); } const styles = StyleSheet.create({ container: { flex: 1 }, scrollContent: { padding: 16, gap: 24 }, section: { gap: 10 }, sectionHeader: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginBottom: 4, }, sectionTitleRow: { flexDirection: "row", alignItems: "center", gap: 8 }, sectionTitle: { fontSize: 16, fontWeight: "700" }, badge: { borderRadius: 10, paddingHorizontal: 7, paddingVertical: 2, minWidth: 22, alignItems: "center", }, badgeText: { color: "#fff", fontSize: 12, fontWeight: "700" }, addButton: { borderRadius: 14, paddingHorizontal: 12, paddingVertical: 6 }, addButtonText: { color: "#fff", fontSize: 13, fontWeight: "600" }, emptySection: { fontSize: 13, fontStyle: "italic", paddingVertical: 8 }, card: { borderRadius: 14, padding: 14, borderWidth: StyleSheet.hairlineWidth, shadowColor: "#000", shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.08, shadowRadius: 2, elevation: 1, }, cardHeader: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginBottom: 8, }, emojiButton: { borderRadius: 10, padding: 6 }, emoji: { fontSize: 24 }, cardActions: { flexDirection: "row", alignItems: "center", gap: 10 }, checkbox: { width: 22, height: 22, borderRadius: 6, borderWidth: 2, alignItems: "center", justifyContent: "center", }, checkmark: { color: "#fff", fontSize: 13, fontWeight: "700" }, deleteButton: { padding: 4 }, deleteText: { fontSize: 16, fontWeight: "600" }, emojiPicker: { flexDirection: "row", borderRadius: 20, padding: 6, gap: 4, marginBottom: 8, alignSelf: "flex-start", }, emojiOption: { width: 36, height: 36, borderRadius: 18, alignItems: "center", justifyContent: "center", }, emojiOptionText: { fontSize: 18 }, title: { fontSize: 15, fontWeight: "600", marginBottom: 4 }, titleInput: { fontSize: 15, fontWeight: "600", marginBottom: 4, borderBottomWidth: 2, paddingBottom: 2, }, description: { fontSize: 13, lineHeight: 18 }, descInput: { fontSize: 13, lineHeight: 18, borderBottomWidth: 2, paddingBottom: 2, }, emptyState: { flex: 1, alignItems: "center", justifyContent: "center", gap: 10, padding: 24, }, emptyEmoji: { fontSize: 48 }, emptyTitle: { fontSize: 16, fontWeight: "600" }, emptySubtitle: { fontSize: 14 }, emptyAddButton: { borderRadius: 16, paddingHorizontal: 20, paddingVertical: 10, marginTop: 8, }, emptyAddButtonText: { color: "#fff", fontSize: 14, fontWeight: "600" }, });