// A tiny bar chart: magnitude over time, one hue, baseline at zero. // // The ramp step says "did this day clear the goal" without adding a second // colour, and every bar carries its own tooltip, so no bar needs a label. import QtQuick import QtQuick.Controls.Material import QtQuick.Layouts Item { id: chart property var days: [] // [{date, pomodoros, focus_minutes, goal_met}] property int goal: 8 property int barHeight: 110 implicitHeight: barHeight + 18 readonly property int maxValue: { var top = goal for (var i = 0; i < days.length; i++) top = Math.max(top, days[i].pomodoros) return Math.max(top, 1) } Rectangle { anchors.left: parent.left anchors.right: parent.right y: chart.barHeight - (chart.goal / chart.maxValue) * chart.barHeight height: 1 color: Material.hintTextColor opacity: 0.45 visible: chart.goal > 0 } RowLayout { anchors.left: parent.left anchors.right: parent.right height: chart.barHeight spacing: 2 Repeater { model: chart.days delegate: Item { required property var modelData Layout.fillWidth: true Layout.fillHeight: true Rectangle { anchors.bottom: parent.bottom width: parent.width height: Math.max(modelData.pomodoros > 0 ? (modelData.pomodoros / chart.maxValue) * chart.barHeight : 2, 2) radius: 4 color: modelData.pomodoros === 0 ? Material.dividerColor : (modelData.goal_met ? "#256abf" : "#6da7ec") ToolTip.visible: hover.hovered ToolTip.text: modelData.date + ": " + modelData.pomodoros + " pomodoros ยท " + modelData.focus_minutes + " min" HoverHandler { id: hover } Behavior on height { NumberAnimation { duration: 250 } } } } } } RowLayout { anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right Label { text: chart.days.length ? chart.days[0].date.substring(5) : "" font.pixelSize: 10; opacity: 0.6 } Item { Layout.fillWidth: true } Label { text: chart.days.length ? chart.days[chart.days.length - 1].date.substring(5) : "" font.pixelSize: 10; opacity: 0.6 } } }