Files
kadence/desktop/kadence_desktop/qml/ReportPage.qml
T

230 lines
8.9 KiB
QML

// The day in numbers — the same payload the Telegram message is built from.
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "."
import "components"
ScrollView {
id: page
contentWidth: availableWidth
clip: true
readonly property var payload: controller.report.report ? controller.report.report : null
readonly property var metrics: payload ? payload.metrics : null
ColumnLayout {
width: page.availableWidth - 56
x: 28
y: 26
spacing: 22
PageHeader {
eyebrow: controller.report.sent_at ? "sent to Telegram" : "not sent yet"
title: page.payload ? "Report · " + page.payload.date : "Report"
caption: page.payload ? page.payload.verdict : ""
GhostButton { text: "Reload"; onClicked: controller.loadReport() }
PrimaryButton { text: "Send to Telegram"; onClicked: controller.sendReport() }
}
Panel {
padding: 0
RowLayout {
Layout.fillWidth: true
spacing: 0
Repeater {
model: [
{ label: "Pomodoros",
value: page.metrics ? page.metrics.pomodoros + "/" + page.metrics.goal : "—",
caption: page.metrics && page.metrics.goal_met ? "goal met" : "goal not met yet",
accent: true },
{ label: "Focus",
value: page.metrics ? Theme.humanMinutes(page.metrics.focus_minutes) : "—",
caption: page.metrics ? Theme.humanMinutes(page.metrics.break_minutes) + " resting" : "" },
{ label: "Score",
value: page.payload ? "" + Math.round(page.payload.score) : "—",
caption: "out of 100" },
{ label: "Streak",
value: page.payload ? page.payload.streak.current + "d" : "—",
caption: page.payload ? "best " + page.payload.streak.best : "" }
]
delegate: RowLayout {
required property int index
required property var modelData
Layout.fillWidth: true
spacing: 0
Rectangle {
visible: index > 0
width: 1
Layout.preferredHeight: 84
color: Theme.rule
}
Stat {
Layout.fillWidth: true
Layout.margins: 20
label: modelData.label
value: modelData.value
caption: modelData.caption
size: 38
accent: modelData.accent ? Theme.work : Theme.ink
}
}
}
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 10
SectionTitle { text: "Last 30 days"; trailing: "goal line dashed" }
Panel {
BarRow {
Layout.fillWidth: true
days: controller.stats.range ? controller.stats.range : []
goal: controller.goal
}
}
}
ColumnLayout {
Layout.fillWidth: true
visible: page.payload && page.payload.achievements.length > 0
spacing: 10
SectionTitle { text: "Achievements" }
Flow {
Layout.fillWidth: true
spacing: 8
Repeater {
model: page.payload ? page.payload.achievements : []
delegate: Rectangle {
required property var modelData
implicitWidth: badge.implicitWidth + 24
implicitHeight: badge.implicitHeight + 18
radius: 10
color: Qt.alpha(Theme.ember, 0.08)
border.width: 1
border.color: Qt.alpha(Theme.ember, 0.22)
ColumnLayout {
id: badge
anchors.centerIn: parent
spacing: 1
Label {
text: modelData.emoji + " " + modelData.title
color: Theme.ink
font.pixelSize: 13
font.weight: Font.DemiBold
font.family: Theme.sansFamily
}
Label {
visible: modelData.detail !== ""
text: modelData.detail
color: Theme.muted
font.pixelSize: 11
font.family: Theme.sansFamily
}
}
}
}
}
}
ColumnLayout {
Layout.fillWidth: true
visible: page.payload && page.payload.fun_facts.length > 0
spacing: 8
SectionTitle { text: "The funny part" }
Repeater {
model: page.payload ? page.payload.fun_facts : []
delegate: Label {
required property var modelData
text: modelData
color: Theme.ink
font.pixelSize: 13
font.family: Theme.sansFamily
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
}
}
ColumnLayout {
Layout.fillWidth: true
visible: page.metrics && page.metrics.tasks_completed.length > 0
spacing: 6
SectionTitle { text: "Closed today" }
Repeater {
model: page.metrics ? page.metrics.tasks_completed : []
delegate: RowLayout {
required property var modelData
Layout.fillWidth: true
spacing: 12
Label {
text: modelData.title
color: Theme.ink
font.pixelSize: 13
font.family: Theme.sansFamily
elide: Text.ElideRight
Layout.fillWidth: true
}
Label {
text: modelData.source
color: Theme.faint
font.pixelSize: 11
font.family: Theme.sansFamily
}
}
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 10
SectionTitle { text: "All time" }
Panel {
padding: 0
RowLayout {
Layout.fillWidth: true
spacing: 0
Repeater {
model: [
{ label: "Pomodoros",
value: controller.stats.lifetime ? "" + controller.stats.lifetime.pomodoros : "—" },
{ label: "Hours focused",
value: controller.stats.lifetime ? "" + controller.stats.lifetime.focus_hours : "—" },
{ label: "Tasks closed",
value: controller.stats.lifetime ? "" + controller.stats.lifetime.tasks_completed : "—" },
{ label: "Blocked",
value: controller.stats.lifetime ? "" + controller.stats.lifetime.blocked_attempts : "—" }
]
delegate: RowLayout {
required property int index
required property var modelData
Layout.fillWidth: true
spacing: 0
Rectangle {
visible: index > 0
width: 1
Layout.preferredHeight: 64
color: Theme.rule
}
Stat {
Layout.fillWidth: true
Layout.margins: 18
label: modelData.label
value: modelData.value
}
}
}
}
}
}
Item { Layout.preferredHeight: 10 }
}
Component.onCompleted: controller.loadReport()
}