akhaliq's picture
akhaliq HF Staff
Deploy from anycoder
bed1072 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 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(
"""
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2em;">
<h1 class="todo-header">πŸš€ My Todo App</h1>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank"
style="color: #666; text-decoration: none; font-size: 0.9em;">
Built with <b>anycoder</b>
</a>
</div>
"""
)
with gr.Row():
with gr.Column(scale=1):
task_input = gr.Textbox(
label="New Task",
placeholder="What needs to be done?",
lines=2
)
priority_input = gr.Slider(
minimum=1,
maximum=3,
value=2,
step=1,
label="Priority",
info="1 = Urgent πŸ”₯ | 2 = Important ⚑ | 3 = Normal πŸ“‹"
)
add_btn = gr.Button("βž• Add Todo", variant="primary", size="lg")
with gr.Column(scale=2):
todos_display = gr.Markdown(
get_todos_display(initial_todos),
label="Your Todos",
elem_classes=["todo-list"]
)
with gr.Row():
clear_btn = gr.Button("πŸ—‘οΈ Clear Completed", variant="secondary")
delete_btn = gr.Button("πŸ—‘οΈ Delete Selected", interactive=False, visible=False)
# Status message
status_msg = gr.Textbox(
label="Status",
interactive=False,
visible=False
)
# Event handlers
add_btn.click(
add_todo,
inputs=[task_input, priority_input],
outputs=[todos_display, status_msg]
).then(
lambda: gr.update(visible=True),
outputs=[status_msg]
).then(
gr.update(value=""),
outputs=[task_input]
)
clear_btn.click(
clear_completed,
outputs=[todos_display]
)
# Update display when todos change
demo.load(
fn=lambda: get_todos_display(load_todos()),
outputs=todos_display
)
if __name__ == "__main__":
demo.launch()