Files
kadence/desktop/kadence_desktop/qml/ReportPage.qml
T
2026-10-18 18:02:05 +03:00

181 lines
6.8 KiB
QML

// The day, summarised — the same payload the Telegram message is built from.
import QtQuick
import QtQuick.Controls.Material
import QtQuick.Layouts
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
spacing: 16
ColumnLayout {
Layout.fillWidth: true
Layout.margins: 20
spacing: 16
RowLayout {
Layout.fillWidth: true
Label {
text: page.payload ? "Report for " + page.payload.date : "Report"
font.pixelSize: 20
font.weight: Font.Medium
Layout.fillWidth: true
}
Button { text: "⟳"; flat: true; onClicked: controller.loadReport() }
PrimaryButton { text: "Send to Telegram"; onClicked: controller.sendReport() }
}
GridLayout {
Layout.fillWidth: true
columns: page.width > 760 ? 4 : 2
columnSpacing: 12
rowSpacing: 12
StatTile {
label: "Pomodoros"
value: page.metrics ? page.metrics.pomodoros + "/" + page.metrics.goal : "—"
caption: page.metrics && page.metrics.goal_met ? "goal met 🎯" : "keep going"
accent: window.workColor
}
StatTile {
label: "Focus"
value: page.metrics ? page.metrics.focus_minutes + "m" : "—"
caption: page.metrics ? page.metrics.break_minutes + "m resting" : ""
}
StatTile {
label: "Score"
value: page.payload ? Math.round(page.payload.score) : "—"
caption: "out of 100"
}
StatTile {
label: "Streak"
value: page.payload ? page.payload.streak.current + "d" : "—"
caption: page.payload ? "best " + page.payload.streak.best : ""
}
}
Card {
title: "Last 30 days"
subtitle: "Goal line is the dashed row; darker bars cleared it."
BarRow {
Layout.fillWidth: true
days: controller.stats.range ? controller.stats.range : []
goal: controller.goal
}
}
Card {
visible: page.payload && page.payload.achievements.length > 0
title: "Achievements"
Flow {
Layout.fillWidth: true
spacing: 8
Repeater {
model: page.payload ? page.payload.achievements : []
delegate: Pane {
required property var modelData
Material.elevation: 0
Material.roundedScale: Material.SmallScale
padding: 10
background: Rectangle {
radius: 10
color: Material.accent
opacity: 0.14
}
ColumnLayout {
spacing: 1
Label {
text: modelData.emoji + " " + modelData.title
font.weight: Font.DemiBold
font.pixelSize: 13
}
Label {
text: modelData.detail
visible: modelData.detail !== ""
font.pixelSize: 11
opacity: 0.75
}
}
}
}
}
}
Card {
visible: page.payload && page.payload.fun_facts.length > 0
title: "The funny part"
Repeater {
model: page.payload ? page.payload.fun_facts : []
delegate: Label {
required property var modelData
text: modelData
wrapMode: Text.WordWrap
Layout.fillWidth: true
font.pixelSize: 13
}
}
}
Card {
visible: page.metrics && page.metrics.tasks_completed.length > 0
title: "Closed today"
Repeater {
model: page.metrics ? page.metrics.tasks_completed : []
delegate: RowLayout {
required property var modelData
Layout.fillWidth: true
Label { text: "✅"; font.pixelSize: 12 }
Label { text: modelData.title; Layout.fillWidth: true; elide: Text.ElideRight }
Label { text: modelData.source; font.pixelSize: 11; opacity: 0.6 }
}
}
}
Card {
title: "All time"
RowLayout {
Layout.fillWidth: true
spacing: 12
StatTile {
label: "Pomodoros"
value: controller.stats.lifetime ? controller.stats.lifetime.pomodoros : "—"
}
StatTile {
label: "Hours focused"
value: controller.stats.lifetime ? controller.stats.lifetime.focus_hours : "—"
}
StatTile {
label: "Tasks closed"
value: controller.stats.lifetime ? controller.stats.lifetime.tasks_completed : "—"
}
StatTile {
label: "Blocked"
value: controller.stats.lifetime ? controller.stats.lifetime.blocked_attempts : "—"
}
}
}
Label {
visible: page.payload && page.payload.verdict !== ""
text: page.payload ? page.payload.verdict : ""
font.italic: true
font.pixelSize: 14
opacity: 0.85
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
}
}
Component.onCompleted: controller.loadReport()
}