import gradio as gr from utils import ( initial_state, format_todos, add_task, toggle_complete, delete_task ) # Initialize global constants INITIAL_TODOS = initial_state() with gr.Blocks(title="Gradio Todo App") as demo: gr.HTML("""

Simple Todo List

Built with anycoder

""") # --- State Management --- todo_state = gr.State(value=INITIAL_TODOS) # --- Input and Adding Tasks --- with gr.Row(): new_task_input = gr.Textbox( placeholder="What needs to be done?", label="New Task", scale=3 ) add_btn = gr.Button("Add Task", variant="primary", scale=1) # --- Todo List Display --- # We use Dataframe and rely on the 'select' event to handle actions todo_display = gr.Dataframe( value=format_todos(INITIAL_TODOS), headers=["Task Description", "Status"], row_count=(1, "dynamic"), col_count=(2, "fixed"), datatype=["str", "str"], interactive=True, label="Tasks", show_row_numbers=True, wrap=True, line_breaks=True, height=300 ) # --- Action Buttons (triggered by Dataframe selection) --- with gr.Row(): complete_btn = gr.Button("Toggle Complete (Select Row First)", variant="secondary") delete_btn = gr.Button("Delete Task (Select Row First)", variant="stop") # --- Event Handling --- # 1. Adding a new task add_btn.click( fn=add_task, inputs=[todo_state, new_task_input], outputs=[todo_state, todo_display, new_task_input] ) new_task_input.submit( fn=add_task, inputs=[todo_state, new_task_input], outputs=[todo_state, todo_display, new_task_input] ) # 2. Handling actions upon selection + button click # When a user clicks a row and then the Toggle button complete_btn.click( fn=toggle_complete, inputs=[todo_state, todo_display], outputs=[todo_state, todo_display] ) # When a user clicks a row and then the Delete button delete_btn.click( fn=delete_task, inputs=[todo_state, todo_display], outputs=[todo_state, todo_display] ) demo.queue() if __name__ == "__main__": demo.launch()