12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- #!/usr/bin/env python3
- from dataclasses import dataclass
- from typing import Callable
- from nicegui import ui
- @dataclass
- class TodoItem:
- name: str
- on_change: Callable
- done: bool = False
- def toggle(self) -> None:
- self.done = not self.done
- def set_name(self, new_name: str) -> None:
- self.name = new_name
- def __setattr__(self, name, value) -> None:
- super().__setattr__(name, value)
- if hasattr(self, 'on_change'):
- self.on_change()
- class ToDoList:
- def __init__(self, title: str, on_change: Callable):
- self.title = title
- self.items = []
- self.on_change: Callable = on_change
- def add(self, name: str, done: bool = False) -> None:
- self.items.append(TodoItem(name, self.on_change, done))
- self.on_change()
- def remove(self, item: TodoItem) -> None:
- self.items.remove(item)
- self.on_change()
- @ui.refreshable
- def todo_ui():
- if not todos.items:
- ui.label('List is empty.').classes('mx-auto')
- return
- ui.linear_progress(sum(item.done for item in todos.items) / len(todos.items), show_value=False)
- with ui.row().classes('justify-center w-full'):
- ui.label(f'Completed: {sum(item.done for item in todos.items)}')
- ui.label(f'Remaining: {sum(not item.done for item in todos.items)}')
- for item in todos.items:
- with ui.row().classes('items-center'):
- ui.checkbox(value=item.done, on_change=lambda _, item=item: item.toggle())
- input = ui.input(value=item.name).classes('flex-grow')
- input.on('keydown.enter', lambda _, item=item, input=input: item.set_name(input.value))
- ui.button(on_click=lambda _, item=item: todos.remove(item)).props('flat fab-mini icon=delete color=grey')
- todos = ToDoList('Shopping', on_change=todo_ui.refresh)
- todos.add('Buy milk', done=True)
- todos.add('Clean the house')
- todos.add('Call mom')
- with ui.card().classes('w-80 items-stretch'):
- ui.label().bind_text_from(todos, 'title').classes('text-semibold text-2xl')
- todo_ui()
- add_input = ui.input('New item').classes('mx-12')
- add_input.on('keydown.enter', lambda: (todos.add(add_input.value), add_input.set_value('')))
- ui.run()
|