import gradio as gr import json import os from datetime import datetime from typing import List, Dict # File to persist todos TODO_FILE = "todos.json" def load_todos() -> List[Dict]: """Load todos from JSON file""" if os.path.exists(TODO_FILE): try: with open(TODO_FILE, 'r') as f: return json.load(f) except: return [] return [] def save_todos(todos: List[Dict]): """Save todos to JSON file""" try: with open(TODO_FILE, 'w') as f: json.dump(todos, f, indent=2) except Exception as e: print(f"Error saving todos: {e}") def add_todo(task: str, priority: int) -> tuple[List[Dict], str]: """Add a new todo item""" if not task.strip(): return load_todos(), "Task cannot be empty!" todos = load_todos() new_todo = { "id": len(todos) + 1, "task": task.strip(), "priority": priority, "completed": False, "created": datetime.now().isoformat() } todos.append(new_todo) save_todos(todos) return todos, f"Added: '{task}' (Priority: {priority})" def toggle_todo(todo_id: int) -> List[Dict]: """Toggle todo completion status""" todos = load_todos() for todo in todos: if todo["id"] == todo_id: todo["completed"] = not todo["completed"] break save_todos(todos) return todos def delete_todo(todo_id: int) -> List[Dict]: """Delete a todo item""" todos = load_todos() todos = [todo for todo in todos if todo["id"] != todo_id] # Update IDs to maintain sequential order for i, todo in enumerate(todos): todo["id"] = i + 1 save_todos(todos) return todos def get_todos_display(todos: List[Dict]) -> str: """Format todos for display""" if not todos: return "🎉 No todos! Great job!" lines = [] sorted_todos = sorted(todos, key=lambda x: (x["priority"], x["id"])) for todo in sorted_todos: status = "✅" if todo["completed"] else "⏳" priority_emoji = {1: "🔥", 2: "⚡", 3: "📋"}.get(todo["priority"], "📌") line = f"{status} [{priority_emoji} P{todo['priority']}] {todo['task']}" lines.append(line) return "\n".join(lines) def clear_completed() -> List[Dict]: """Remove all completed todos""" todos = load_todos() todos = [todo for todo in todos if not todo["completed"]] # Update IDs for i, todo in enumerate(todos): todo["id"] = i + 1 save_todos(todos) return todos # Initialize app with current todos initial_todos = load_todos() with gr.Blocks( title="🚀 Todo App", theme=gr.themes.Soft(), css=""" .todo-header { font-size: 2em; margin-bottom: 1em; } .priority-selector { display: flex; gap: 1em; align-items: center; } .todo-list { background: white; border-radius: 10px; padding: 1.5em; min-height: 200px; } .action-buttons { display: flex; gap: 1em; flex-wrap: wrap; } """ ) as demo: gr.HTML( """