from fastapi import FastAPI from pydantic import BaseModel from supabase import create_client, Client import os import gradio as gr import requests # --- Supabase Config --- SUPABASE_URL = os.getenv("SUPABASE_URL") SUPABASE_KEY = os.getenv("SUPABASE_KEY") supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY) # --- FastAPI Setup --- app = FastAPI() # --- Pydantic Task Model --- class Task(BaseModel): title: str completed: bool = False # --- API Endpoints --- @app.post("/tasks/") def add_task(task: Task): response = supabase.table("tasks").insert(task.dict()).execute() return response.data @app.get("/tasks/") def get_tasks(): response = supabase.table("tasks").select("*").order("id", desc=False).execute() return response.data @app.patch("/tasks/{task_id}") def update_task(task_id: str, completed: bool): response = supabase.table("tasks").update({"completed": completed}).eq("id", task_id).execute() return response.data @app.delete("/tasks/{task_id}") def delete_task(task_id: str): supabase.table("tasks").delete().eq("id", task_id).execute() return {"detail": "Task deleted"} # --- Gradio Frontend Logic --- API_URL = "http://localhost:7860" # adjust if needed for Hugging Face Spaces def get_tasks_data(): response = requests.get(f"{API_URL}/tasks/") return response.json() def get_task_choices(): """Returns [(label, uuid)] for the dropdown.""" tasks = get_tasks_data() return [(f"{t['title']} - {'✔️' if t['completed'] else '❌'}", t['id']) for t in tasks] def get_task_display(): """Returns formatted list of tasks for display.""" return [f"{t['title']} - {'✔️' if t['completed'] else '❌'}" for t in get_tasks_data()] def add_task_ui(title): if not title.strip(): return "Title cannot be empty", get_task_display(), gr.update(choices=get_task_choices()) requests.post(f"{API_URL}/tasks/", json={"title": title, "completed": False}) return "", get_task_display(), gr.update(choices=get_task_choices()) def complete_task_ui(task_id): requests.patch(f"{API_URL}/tasks/{task_id}", params={"completed": True}) return get_task_display(), gr.update(choices=get_task_choices()) def delete_task_ui(task_id): requests.delete(f"{API_URL}/tasks/{task_id}") return get_task_display(), gr.update(choices=get_task_choices()) # --- Gradio UI --- with gr.Blocks() as demo: gr.Markdown("## ✅ Task List Manager") with gr.Row(): task_input = gr.Textbox(label="New Task", placeholder="e.g., Write blog post") add_button = gr.Button("Add Task") task_selector = gr.Dropdown(label="Select a Task", choices=[]) with gr.Row(): complete_button = gr.Button("Mark as Completed") delete_button = gr.Button("Delete Task") task_display = gr.Textbox(label="All Tasks", lines=10) # Button Logic add_button.click(add_task_ui, inputs=task_input, outputs=[task_input, task_display, task_selector]) complete_button.click(complete_task_ui, inputs=task_selector, outputs=[task_display, task_selector]) delete_button.click(delete_task_ui, inputs=task_selector, outputs=[task_display, task_selector]) # Load initial data demo.load( lambda: ( get_task_display(), gr.update(choices=get_task_choices()) ), outputs=[task_display, task_selector] ) # Mount Gradio app into FastAPI app = gr.mount_gradio_app(app, demo, path="/")