Files

157 lines
5.2 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import qs.Common
import qs.Services
import qs.DCommon.Widgets
import qs.Modules.DDash
Rectangle {
id: root
property bool daily: false
property bool chartMode: true
property var widgetOptions: ({})
property bool live: false
readonly property int visibleCount: Math.max(1, Math.min(daily ? DashMetrics.dailyVisibleCount : DashMetrics.chartHourlyCount, Math.floor(width / DashMetrics.gridRowUnit)))
property int startIndex: daily ? 0 : (WeatherService.weather.currentHourIndex ?? new Date().getHours())
readonly property var forecasts: (daily ? WeatherService.weather.forecast : WeatherService.weather.hourlyForecast) ?? []
readonly property int maxStart: Math.max(0, forecasts.length - visibleCount)
readonly property int start: Math.max(0, Math.min(maxStart, startIndex))
radius: Theme.cornerRadiusXL
color: DashMetrics.cardColor
border.width: Theme.layerOutlineWidth
border.color: Theme.outlineMedium
function step(delta) {
const next = Math.max(0, Math.min(maxStart, start + delta));
if (next === start)
return false;
startIndex = next;
return true;
}
Item {
id: header
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Theme.spacingM
height: Theme.buttonHeightS
Row {
id: title
anchors.left: parent.left
anchors.right: actions.left
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DIcon {
anchors.verticalCenter: parent.verticalCenter
name: root.daily ? "calendar_month" : "schedule"
size: Theme.iconSize
color: Theme.onSurface
}
StyledText {
anchors.verticalCenter: parent.verticalCenter
width: Math.max(0, title.width - Theme.iconSize - title.spacing)
text: root.daily ? I18n.tr("Daily") : I18n.tr("Hourly")
font.pixelSize: Theme.fontSizeLarge
font.weight: Theme.fontWeightMedium
color: Theme.onSurface
elide: Text.ElideRight
}
}
Row {
id: actions
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS
DActionButton {
buttonSize: Theme.buttonHeightS
iconName: I18n.isRtl ? "chevron_right" : "chevron_left"
Accessible.name: I18n.tr("Previous")
enabled: root.start > 0
onClicked: root.step(-1)
}
DActionButton {
buttonSize: Theme.buttonHeightS
iconName: "today"
Accessible.name: I18n.tr("Today")
onClicked: root.startIndex = root.daily ? 0 : (WeatherService.weather.currentHourIndex ?? new Date().getHours())
}
DActionButton {
buttonSize: Theme.buttonHeightS
iconName: I18n.isRtl ? "chevron_left" : "chevron_right"
Accessible.name: I18n.tr("Next")
enabled: root.start < root.maxStart
onClicked: root.step(1)
}
}
}
Loader {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: header.bottom
anchors.bottom: parent.bottom
active: root.live
sourceComponent: root.chartMode ? chart : cards
}
Component {
id: chart
WeatherForecastChart {
daily: root.daily
visibleCount: root.visibleCount
startIndex: root.start
onPageRequested: delta => root.step(delta)
}
}
Component {
id: cards
Item {
Row {
id: cardRow
anchors.fill: parent
anchors.topMargin: Theme.spacingS
anchors.leftMargin: Theme.spacingM
anchors.rightMargin: Theme.spacingM
anchors.bottomMargin: Theme.spacingM
spacing: Theme.spacingS
Repeater {
model: root.forecasts.slice(root.start, root.start + root.visibleCount)
WeatherForecastCard {
required property var modelData
required property int index
width: (cardRow.width - cardRow.spacing * (root.visibleCount - 1)) / root.visibleCount
height: cardRow.height
daily: root.daily
dense: true
forecastData: modelData
isCurrent: root.start + index === (root.daily ? 0 : (WeatherService.weather.currentHourIndex ?? new Date().getHours()))
}
}
}
StyledText {
anchors.centerIn: parent
visible: root.forecasts.length === 0
text: I18n.tr("Forecast Not Available")
color: Theme.onSurfaceVariant
}
}
}
}