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: pass # Silently fail on save issues def add_todo(task: str, priority: int) -> tuple[List[Dict], str]: """Add a new todo item""" if not task.strip(): return load_todos(), "Please enter a task!" todos = load_todos() new_todo = { "id": len(todos) + 1, "task": task.strip(), "priority": priority, "completed": False, "created": datetime.now().isoformat() } todos.insert(0, new_todo) # Add to top save_todos(todos) return todos, f"Added: '{task}'" 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] 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 = [] for todo in todos: status = "✅" if todo["completed"] else "⏳" priority_emoji = "🔥" if todo["priority"] == 3 else "⚡" if todo["priority"] == 2 else "📝" lines.append(f"{status} {priority_emoji} {todo['task']}") return "\n".join(lines) def clear_completed() -> List[Dict]: """Remove all completed todos""" todos = [todo for todo in load_todos() if not todo["completed"]] save_todos(todos) return todos # Load initial todos initial_todos = load_todos() with gr.Blocks( title="🚀 Todo App", theme=gr.themes.Soft(), css=""" .todo-item { margin: 8px 0; padding: 12px; border-radius: 8px; background: var(--neutral-100); } .priority-high { border-left: 4px solid #ef4444; } .priority-medium { border-left: 4px solid #f59e0b; } .priority-low { border-left: 4px solid #10b981; } """ ) as demo: gr.Markdown( """ # 🚀 My Todo App Add, complete, and manage your tasks with priority levels!
Built with anycoder
""", elem_id="header" ) with gr.Row(): with gr.Column(scale=1): task_input = gr.Textbox( label="New Task", placeholder="What needs to be done?", lines=2, max_lines=3 ) priority_slider = gr.Slider( minimum=1, maximum=3, value=2, step=1, label="Priority", info="1=Low 📝, 2=Medium ⚡, 3=High 🔥" ) with gr.Row(): add_btn = gr.Button("➕ Add Task", variant="primary", scale=1) clear_btn = gr.Button("🗑️ Clear Completed", scale=1) status_msg = gr.Textbox( label="Status", interactive=False, scale=1 ) with gr.Column(scale=2): todos_display = gr.Markdown( get_todos_display(initial_todos), label="Your Todos" ) # Examples gr.Examples( examples=[ ["Buy groceries", 2], ["Finish project report", 3], ["Call mom", 1] ], inputs=[task_input, priority_slider], label="Quick Examples" ) # Event handlers add_btn.click( add_todo, inputs=[task_input, priority_slider], outputs=[todos_display, status_msg] ).then( lambda: gr.update(value=""), outputs=[task_input] ) clear_btn.click( clear_completed, outputs=[todos_display, status_msg] ).then( lambda: gr.update(value=""), outputs=[status_msg] ) # Clear status after 3 seconds def clear_status(): return gr.update(value="") status_msg.change( clear_status, outputs=[status_msg], show_progress=False ) if __name__ == "__main__": demo.launch()