From 926669f28f7bdcff46ed724061d356772ec0ddb9 Mon Sep 17 00:00:00 2001 From: Alexander Winkler Date: Mon, 18 May 2026 16:16:40 +0200 Subject: [PATCH 1/5] add basic database functionality --- src/chore_manager/database.py | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/chore_manager/database.py diff --git a/src/chore_manager/database.py b/src/chore_manager/database.py new file mode 100644 index 0000000..ff96b9e --- /dev/null +++ b/src/chore_manager/database.py @@ -0,0 +1,50 @@ +import sqlite3 +from pathlib import Path +import os +from dataclasses import dataclass, fields + +@dataclass +class Task: + title: str + done: bool + def __post_init__(self): + for field in fields(self): + if field.type is bool: + value = getattr(self, field.name) + setattr(self, field.name, bool(value)) + +class Database: + def __init__(self, filepath: Path|str): + is_new_database = not Path(filepath).exists() + self.con = sqlite3.connect(filepath) + self.cur = self.con.cursor() + if is_new_database: + self.initialize_table() + + def initialize_table(self): + self.cur.execute("CREATE TABLE tasks(title TEXT, done INTEGER)") + + + def create_task(self, title: str, done:bool=False) -> None: + converted_done = "" + if done: + converted_done = "TRUE" + else: + converted_done = "FALSE" + + self.cur.execute(f"""INSERT INTO tasks VALUES ("{title}", {converted_done});""") + self.con.commit() + + def get_all_tasks(self) -> list[Task]: + self.cur.execute("SELECT * FROM tasks") + raw_data = self.cur.fetchall() + return [Task(*task) for task in raw_data] + +if __name__ == '__main__': + try: + os.remove("DEBUG.db") + except FileNotFoundError: + pass + database = Database("DEBUG.db") + database.create_task("test") + print(database.get_all_tasks()) From b8e20525496c09b9f18c321a7ae8d34d899b6620 Mon Sep 17 00:00:00 2001 From: Alexander Winkler Date: Mon, 18 May 2026 16:18:11 +0200 Subject: [PATCH 2/5] rename done to is_done --- src/chore_manager/database.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chore_manager/database.py b/src/chore_manager/database.py index ff96b9e..c127696 100644 --- a/src/chore_manager/database.py +++ b/src/chore_manager/database.py @@ -6,7 +6,7 @@ from dataclasses import dataclass, fields @dataclass class Task: title: str - done: bool + is_done: bool def __post_init__(self): for field in fields(self): if field.type is bool: @@ -22,7 +22,7 @@ class Database: self.initialize_table() def initialize_table(self): - self.cur.execute("CREATE TABLE tasks(title TEXT, done INTEGER)") + self.cur.execute("CREATE TABLE tasks(title TEXT, is_done INTEGER)") def create_task(self, title: str, done:bool=False) -> None: From c7f8016c4bf791f5d8a5f8ba54e80a1ea599511b Mon Sep 17 00:00:00 2001 From: Alexander Winkler Date: Mon, 18 May 2026 16:26:59 +0200 Subject: [PATCH 3/5] add textual as a dependancy --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 511f5e8..7b6708a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name="chore-manager" dynamic = ["version"] -dependencies = [] +dependencies = ["textual"] requires-python = ">=3.13" readme = "README.md" From a6e3738b7a2e82371ff9631d7e14059263b0f2af Mon Sep 17 00:00:00 2001 From: Alexander Winkler Date: Mon, 18 May 2026 16:28:17 +0200 Subject: [PATCH 4/5] add textual app skeleton --- src/chore_manager/main.py | 6 ++++-- src/chore_manager/tui.py | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 src/chore_manager/tui.py diff --git a/src/chore_manager/main.py b/src/chore_manager/main.py index 74106cf..ced5536 100644 --- a/src/chore_manager/main.py +++ b/src/chore_manager/main.py @@ -1,3 +1,5 @@ - +from .tui import ChoreManagerTui def main_tui() -> None: - print("Hello World") + app = ChoreManagerTui() + app.run() + diff --git a/src/chore_manager/tui.py b/src/chore_manager/tui.py new file mode 100644 index 0000000..c7fcc9b --- /dev/null +++ b/src/chore_manager/tui.py @@ -0,0 +1,9 @@ +from textual.app import App, ComposeResult +from textual.widgets import Header + + +class ChoreManagerTui(App): + + + def compose(self) -> ComposeResult: + yield Header() From 80d06c653dabaf4250fbf549e20ac5f3b59e8e8e Mon Sep 17 00:00:00 2001 From: Alexander Winkler Date: Mon, 18 May 2026 16:46:52 +0200 Subject: [PATCH 5/5] list tasks in textual --- src/chore_manager/database.py | 2 ++ src/chore_manager/tui.py | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/chore_manager/database.py b/src/chore_manager/database.py index c127696..53d07a1 100644 --- a/src/chore_manager/database.py +++ b/src/chore_manager/database.py @@ -21,6 +21,8 @@ class Database: if is_new_database: self.initialize_table() + for i in range(0, 15): + self.create_task(f"task{i}", bool(i%2)) def initialize_table(self): self.cur.execute("CREATE TABLE tasks(title TEXT, is_done INTEGER)") diff --git a/src/chore_manager/tui.py b/src/chore_manager/tui.py index c7fcc9b..06f0987 100644 --- a/src/chore_manager/tui.py +++ b/src/chore_manager/tui.py @@ -1,9 +1,19 @@ from textual.app import App, ComposeResult -from textual.widgets import Header - +from textual.widgets import Header, Checkbox +from textual.containers import VerticalScroll +from .database import Database class ChoreManagerTui(App): + def __init__(self): + super().__init__() + self.database = Database("DEBUG") def compose(self) -> ComposeResult: yield Header() + tasks = self.database.get_all_tasks() + with VerticalScroll(): + for task in tasks: + yield Checkbox(task.title, task.is_done) + +