to-do-app / app.py
littlebird13's picture
Upload app.py with huggingface_hub
c72ae62 verified
import gradio as gr
import json
import os
from datetime import datetime
# File to store tasks
TASKS_FILE = "tasks.json"
def load_tasks():
if os.path.exists(TASKS_FILE):
with open(TASKS_FILE, "r") as f:
return json.load(f)
return []
def save_tasks(tasks):
with open(TASKS_FILE, "w") as f:
json.dump(tasks, f)
def add_task(task_name, task_description, task_priority, task_due_date):
tasks = load_tasks()
new_task = {
"id": len(tasks) + 1,
"name": task_name,
"description": task_description,
"priority": task_priority,
"due_date": task_due_date,
"completed": False,
"created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
tasks.append(new_task)
save_tasks(tasks)
return "", "", "normal", None, update_task_list()
def update_task_list(filter_status="all", filter_priority="all"):
tasks = load_tasks()
if filter_status != "all":
completed = filter_status == "completed"
tasks = [task for task in tasks if task["completed"] == completed]
if filter_priority != "all":
tasks = [task for task in tasks if task["priority"] == filter_priority]
if not tasks:
return "No tasks found."
html_content = "<div style='max-height: 400px; overflow-y: auto;'>"
for task in tasks:
status_class = "line-through text-gray-500" if task["completed"] else ""
priority_color = {
"low": "bg-green-100 text-green-800",
"normal": "bg-blue-100 text-blue-800",
"high": "bg-red-100 text-red-800"
}.get(task["priority"], "bg-gray-100 text-gray-800")
due_date = task["due_date"] if task["due_date"] else "No due date"
html_content += f"""
<div class="border rounded-lg p-4 mb-3 bg-white shadow-sm">
<div class="flex justify-between items-start">
<div class="flex-1">
<h3 class="font-semibold text-lg {status_class}">{task['name']}</h3>
<p class="text-gray-600 mt-1">{task['description']}</p>
<div class="flex flex-wrap gap-2 mt-2">
<span class="px-2 py-1 rounded-full text-xs font-medium {priority_color}">{task['priority'].capitalize()}</span>
<span class="px-2 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800">{due_date}</span>
<span class="px-2 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800">Created: {task['created_at']}</span>
</div>
</div>
<div class="flex gap-2 ml-4">
<button onclick="completeTask({task['id']})" class="px-3 py-1 bg-orange-500 text-white rounded hover:bg-orange-600 transition">βœ“</button>
<button onclick="deleteTask({task['id']})" class="px-3 py-1 bg-red-500 text-white rounded hover:bg-red-600 transition">Γ—</button>
</div>
</div>
</div>
"""
html_content += "</div>"
return html_content
def toggle_task_completion(task_id):
tasks = load_tasks()
for task in tasks:
if task["id"] == task_id:
task["completed"] = not task["completed"]
break
save_tasks(tasks)
return update_task_list()
def delete_task(task_id):
tasks = load_tasks()
tasks = [task for task in tasks if task["id"] != task_id]
# Reassign IDs
for i, task in enumerate(tasks):
task["id"] = i + 1
save_tasks(tasks)
return update_task_list()
def clear_completed_tasks():
tasks = load_tasks()
tasks = [task for task in tasks if not task["completed"]]
# Reassign IDs
for i, task in enumerate(tasks):
task["id"] = i + 1
save_tasks(tasks)
return update_task_list()
with gr.Blocks(title="To-Do App", theme=gr.themes.Soft()) as demo:
gr.HTML("""
<div style="text-align: center; margin-bottom: 20px;">
<h1 style="font-size: 2em; margin-bottom: 10px;">πŸ“ To-Do App</h1>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: #666; text-decoration: none;">Built with anycoder</a>
</div>
""")
with gr.Row():
with gr.Column(scale=1):
task_name = gr.Textbox(label="Task Name", placeholder="Enter task name...")
task_description = gr.Textbox(label="Description", placeholder="Enter task description...", lines=3)
task_priority = gr.Radio(["low", "normal", "high"], label="Priority", value="normal")
task_due_date = gr.DateTime(label="Due Date (Optional)", include_time=True)
add_btn = gr.Button("Add Task", variant="primary")
with gr.Column(scale=2):
with gr.Row():
filter_status = gr.Radio(["all", "active", "completed"], label="Filter by Status", value="all")
filter_priority = gr.Radio(["all", "low", "normal", "high"], label="Filter by Priority", value="all")
task_list = gr.HTML(label="Tasks", value=update_task_list())
with gr.Row():
clear_completed_btn = gr.Button("Clear Completed Tasks", variant="stop")
# JavaScript for handling button clicks
gr.HTML("""
<script>
function completeTask(taskId) {
const formData = new FormData();
formData.append('task_id', taskId);
fetch('/complete_task', {
method: 'POST',
body: formData
}).then(response => response.json()).then(data => {
document.querySelector('#task_list').innerHTML = data;
});
}
function deleteTask(taskId) {
const formData = new FormData();
formData.append('task_id', taskId);
fetch('/delete_task', {
method: 'POST',
body: formData
}).then(response => response.json()).then(data => {
document.querySelector('#task_list').innerHTML = data;
});
}
</script>
""")
# Event handlers
add_btn.click(
add_task,
inputs=[task_name, task_description, task_priority, task_due_date],
outputs=[task_name, task_description, task_priority, task_due_date, task_list]
)
filter_status.change(
update_task_list,
inputs=[filter_status, filter_priority],
outputs=task_list
)
filter_priority.change(
update_task_list,
inputs=[filter_status, filter_priority],
outputs=task_list
)
clear_completed_btn.click(
clear_completed_tasks,
outputs=task_list
)
# Add API endpoints for JavaScript calls
@demo.app.post("/complete_task")
async def api_complete_task(request):
form = await request.form()
task_id = int(form["task_id"])
result = toggle_task_completion(task_id)
return {"html": result}
@demo.app.post("/delete_task")
async def api_delete_task(request):
form = await request.form()
task_id = int(form["task_id"])
result = delete_task(task_id)
return {"html": result}
if __name__ == "__main__":
demo.launch()