Spaces:
Sleeping
Sleeping
| 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! | |
| <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;"> | |
| <span></span> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: #666; font-size: 12px;"> | |
| Built with anycoder | |
| </a> | |
| </div> | |
| """, | |
| 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() | |