akhaliq's picture
akhaliq HF Staff
Deploy from anycoder
3004372 verified
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()