pragma ComponentBehavior: Bound import qs.config import qs.custom import qs.services import qs.util import Quickshell import QtQuick import QtQuick.Controls import QtQuick.Layouts ColumnLayout { id: root spacing: 4 property date currentDate: new Date() property int currentYear: currentDate.getFullYear() property int currentMonth: currentDate.getMonth() RowLayout { Layout.alignment: Qt.AlignHCenter MaterialIcon { Layout.bottomMargin: 1 text: "calendar_month" color: Config.colors.primary font.pointSize: Config.font.size.large } CustomText { text: Time.format("hh:mm:ss") color: Config.colors.primary font.weight: 600 font.pointSize: Config.font.size.large font.family: Config.font.family.mono } ColumnLayout { Layout.fillWidth: true Layout.leftMargin: 10 Layout.rightMargin: 4 spacing: 0 CustomText { text: Time.format("dddd, MMMM d") font.weight: 600 font.pointSize: Config.font.size.normal } CustomText { text: Time.format("yyyy-MM-dd") color: Config.colors.tertiary font.pointSize: Config.font.size.smaller } } } // Calendar grid GridLayout { id: calendarGrid Layout.fillWidth: true Layout.margins: 10 rowSpacing: 7 columnSpacing: 2 // Month navigation RowLayout { Layout.fillWidth: true Layout.bottomMargin: 7 Layout.columnSpan: 2 CustomRect { implicitWidth: implicitHeight implicitHeight: prevIcon.implicitHeight + 8 radius: 1000 color: Config.colors.container StateLayer { anchors.fill: parent function onClicked(): void { if (root.currentMonth !== 0) { root.currentMonth = root.currentMonth - 1; } else { root.currentMonth = 11; root.currentYear = root.currentYear - 1; } } } MaterialIcon { id: prevIcon anchors.centerIn: parent text: "chevron_left" color: Config.colors.secondary } } CustomText { Layout.fillWidth: true readonly property list monthNames: Array.from({ length: 12 }, (_, i) => Qt.locale().monthName(i, Qt.locale().LongFormat)) text: monthNames[root.currentMonth] + " " + root.currentYear horizontalAlignment: Text.AlignHCenter font.weight: 600 font.pointSize: Config.font.size.normal } CustomRect { implicitWidth: implicitHeight implicitHeight: nextIcon.implicitHeight + 8 radius: 1000 color: Config.colors.container StateLayer { anchors.fill: parent function onClicked(): void { if (root.currentMonth !== 11) { root.currentMonth = root.currentMonth + 1; } else { root.currentMonth = 0; root.currentYear = root.currentYear + 1; } } } MaterialIcon { id: nextIcon anchors.centerIn: parent text: "chevron_right" color: Config.colors.primary } } } // Day headers DayOfWeekRow { Layout.row: 1 Layout.column: 1 Layout.fillWidth: true Layout.preferredHeight: Config.font.size.largest delegate: CustomText { required property var model horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter text: model.shortName color: Config.colors.tertiary font.pointSize: Config.font.size.small font.weight: 500 } } CustomText { Layout.row: 1 Layout.leftMargin: -2 text: "Week" color: Config.colors.tertiary font.pointSize: Config.font.size.small font.weight: 500 font.italic: true horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } // ISO week markers WeekNumberColumn { Layout.row: 2 Layout.fillHeight: true Layout.rightMargin: 15 height: 240 month: root.currentMonth year: root.currentYear delegate: CustomText { required property var model horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter text: model.weekNumber color: Config.colors.tertiary font.pointSize: Config.font.size.small font.weight: 600 font.italic: true } } // Calendar days grid MonthGrid { Layout.row: 2 Layout.column: 1 Layout.columnSpan: 2 Layout.fillWidth: true Layout.preferredHeight: implicitHeight Layout.margins: 6 month: root.currentMonth year: root.currentYear spacing: 20 delegate: Item { id: dayItem required property var model implicitWidth: implicitHeight implicitHeight: dayText.implicitHeight + 10 CustomRect { anchors.centerIn: parent implicitWidth: parent.implicitHeight implicitHeight: parent.implicitHeight radius: 1000 color: dayItem.model.today ? Config.colors.calendar : "transparent" StateLayer { anchors.fill: parent visible: dayItem.model.month === root.currentMonth function onClicked(): void {} } CustomText { id: dayText anchors.centerIn: parent anchors.verticalCenterOffset: 0.5 horizontalAlignment: Text.AlignHCenter text: Qt.formatDate(dayItem.model.date, "d") color: dayItem.model.today ? Config.colors.primaryDark : dayItem.model.month === root.currentMonth ? Config.colors.primary : Config.colors.inactive font.pointSize: Config.font.size.small font.weight: dayItem.model.today ? 600 : 400 } } } } } // Today button CustomRect { Layout.fillWidth: true implicitHeight: todayBtn.implicitHeight + 10 radius: 25 color: Config.colors.calendar StateLayer { anchors.fill: parent color: Config.colors.secondary function onClicked(): void { const today = new Date(); root.currentYear = today.getFullYear(); root.currentMonth = today.getMonth(); } } Row { id: todayBtn anchors.centerIn: parent spacing: 7 MaterialIcon { anchors.verticalCenter: parent.verticalCenter text: "today" color: Config.colors.primaryDark font.pointSize: Config.font.size.normal } CustomText { anchors.verticalCenter: parent.verticalCenter text: qsTr("Today") color: Config.colors.primaryDark } } } }