// Everything you owe, from every source, grouped by deadline. import QtQuick import QtQuick.Controls.Material import QtQuick.Layouts import "components" Item { id: page function bucketTasks(bucket) { var out = [] for (var i = 0; i < controller.tasks.length; i++) { var task = controller.tasks[i] if (!task.is_done && task.bucket === bucket) out.push(task) } return out } ColumnLayout { anchors.fill: parent anchors.margins: 20 spacing: 12 RowLayout { Layout.fillWidth: true spacing: 8 Label { text: controller.tasks.length + " open" font.pixelSize: 13 opacity: 0.7 } Item { Layout.fillWidth: true } Button { text: "+ Add"; onClicked: addDialog.open() } PrimaryButton { text: "⟳ Refresh sources"; onClicked: controller.refreshSources() } } ScrollView { Layout.fillWidth: true Layout.fillHeight: true contentWidth: availableWidth clip: true ColumnLayout { width: parent.parent.availableWidth spacing: 12 Repeater { model: [ { key: "overdue", label: "Overdue", mark: "🔴" }, { key: "today", label: "Due today", mark: "🟡" }, { key: "upcoming", label: "Coming up", mark: "🔵" }, { key: "someday", label: "No deadline", mark: "⚪" } ] delegate: Card { required property var modelData property var items: page.bucketTasks(modelData.key) visible: items.length > 0 title: modelData.mark + " " + modelData.label + " (" + items.length + ")" Repeater { model: parent.parent.items delegate: RowLayout { required property var modelData Layout.fillWidth: true spacing: 10 CheckBox { checked: modelData.is_done onToggled: controller.setTaskDone(modelData.id, checked) } ColumnLayout { Layout.fillWidth: true spacing: 2 Label { text: modelData.title font.pixelSize: 14 elide: Text.ElideRight Layout.fillWidth: true } RowLayout { spacing: 6 Label { text: modelData.source_label font.pixelSize: 10 opacity: 0.65 } Label { visible: !!modelData.project text: "· " + modelData.project font.pixelSize: 10 opacity: 0.65 } Label { visible: modelData.days_overdue > 0 text: "· " + modelData.days_overdue + "d overdue" font.pixelSize: 10 color: "#e34948" } Label { visible: !!modelData.due_date && modelData.days_overdue === 0 text: "· " + modelData.due_date font.pixelSize: 10 opacity: 0.65 } Label { visible: !!modelData.priority text: "· " + modelData.priority font.pixelSize: 10 opacity: 0.65 } } } ToolButton { text: "↗" visible: !!modelData.url onClicked: controller.openUrl(modelData.url) ToolTip.visible: hovered ToolTip.text: "Open in " + modelData.source_label } ToolButton { text: "▶" onClicked: { controller.attachTask(modelData.id); controller.startWork(); window.page = 0 } ToolTip.visible: hovered ToolTip.text: "Start a pomodoro on this" } } } } } Card { visible: controller.tasks.length === 0 title: "Nothing on the list" subtitle: "Connect Jira, Todoist or Google Tasks in Settings → Sources, " + "or add something here yourself." Button { text: "Open settings" onClicked: window.page = 4 } } } } } Dialog { id: addDialog anchors.centerIn: Overlay.overlay width: 380 modal: true title: "New task" standardButtons: Dialog.Cancel ColumnLayout { anchors.fill: parent spacing: 10 TextField { id: titleField Layout.fillWidth: true placeholderText: "What needs doing?" } TextField { id: dueField Layout.fillWidth: true placeholderText: "Due date (YYYY-MM-DD, optional)" inputMask: "" } PrimaryButton { text: "Add" enabled: titleField.text.trim() !== "" Layout.alignment: Qt.AlignRight onClicked: { controller.createTask(titleField.text.trim(), dueField.text.trim()) titleField.text = ""; dueField.text = "" addDialog.close() } } } } }