Spaces:
Sleeping
Sleeping
| 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 | |
| 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} | |
| 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() |