import gradio as gr import uuid # ---------- Helpers ---------- def new_item(text): return {"id": str(uuid.uuid4()), "text": text.strip(), "done": False} def build_choices(items): return [f"{i}:{'✅ ' if it['done'] else '◻️ '}{it['text']}" for i, it in enumerate(items)] def parse_idx(choice): return int(choice.split(":", 1)[0]) if choice else None def progress_html(done, total): pct = int(done / total * 100) if total else 0 return f"
{done}/{total} done ({pct}%)" def render_ui(state): """Returns CheckboxGroup + HTML for a given state""" ch = build_choices(state) html = "" if state else "No items yet" done = sum(i["done"] for i in state) prog = progress_html(done, len(state)) return gr.update(choices=ch, value=[]), gr.update(value=html + "
" + prog) # ---------- Actions ---------- def add_item(txt, state): if txt.strip(): state.append(new_item(txt)) cbx_update, html_update = render_ui(state) return cbx_update, html_update, gr.update(value=""), state def toggle_item(selected, state): for s in selected: idx = parse_idx(s) if 0 <= idx < len(state): state[idx]["done"] = not state[idx]["done"] cbx_update, html_update = render_ui(state) return cbx_update, html_update, state def delete_item(selected, state): idxs = sorted([parse_idx(s) for s in selected], reverse=True) for i in idxs: if 0 <= i < len(state): state.pop(i) cbx_update, html_update = render_ui(state) return cbx_update, html_update, state # ---------- Build Gradio Interface ---------- with gr.Blocks(title="To-Do & Habit Tracker") as demo: gr.Markdown("# ✅ To-Do & Habit Tracker\nKeep your daily routine organized!") with gr.Row(): # --- To-Do Section --- with gr.Column(): gr.Markdown("### 📝 To-Do Tasks") task_input = gr.Textbox(label="Add a new task") add_task_btn = gr.Button("➕ Add Task") todo_box = gr.CheckboxGroup(label="Tasks") toggle_task_btn = gr.Button("✔️ Toggle Complete") del_task_btn = gr.Button("🗑️ Delete Selected") todo_html = gr.HTML() todo_state = gr.State([]) # --- Habits Section --- with gr.Column(): gr.Markdown("### 🔁 Daily Habits") habit_input = gr.Textbox(label="Add a new habit") add_habit_btn = gr.Button("➕ Add Habit") habit_box = gr.CheckboxGroup(label="Habits") toggle_habit_btn = gr.Button("✔️ Toggle Complete") del_habit_btn = gr.Button("🗑️ Delete Selected") habit_html = gr.HTML() habit_state = gr.State([]) # Connect To-Do events add_task_btn.click(add_item, [task_input, todo_state], [todo_box, todo_html, task_input, todo_state]) toggle_task_btn.click(toggle_item, [todo_box, todo_state], [todo_box, todo_html, todo_state]) del_task_btn.click(delete_item, [todo_box, todo_state], [todo_box, todo_html, todo_state]) # Connect Habit events add_habit_btn.click(add_item, [habit_input, habit_state], [habit_box, habit_html, habit_input, habit_state]) toggle_habit_btn.click(toggle_item, [habit_box, habit_state], [habit_box, habit_html, habit_state]) del_habit_btn.click(delete_item, [habit_box, habit_state], [habit_box, habit_html, habit_state]) # Initialize UI def init(): cbx1, html1 = render_ui([]) cbx2, html2 = render_ui([]) return cbx1, html1, cbx2, html2, [], [] demo.load(init, None, [todo_box, todo_html, habit_box, habit_html, todo_state, habit_state]) demo.launch()