summaryrefslogtreecommitdiff
path: root/modules/dashboard/dash/Calendar.qml
blob: ff27669431046d817755f91f9a1912e71da6fbf4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
pragma ComponentBehavior: Bound

import qs.components
import qs.components.effects
import qs.services
import qs.config
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

Column {
    id: root

    required property var state

    readonly property int currMonth: state.currentDate.getMonth()
    readonly property int currYear: state.currentDate.getFullYear()

    anchors.left: parent.left
    anchors.right: parent.right
    padding: Appearance.padding.large
    spacing: Appearance.spacing.small

    RowLayout {
        id: monthNavigationRow

        anchors.left: parent.left
        anchors.right: parent.right
        anchors.margins: parent.padding
        spacing: Appearance.spacing.small

        Item {
            implicitWidth: implicitHeight
            implicitHeight: prevMonthText.implicitHeight + Appearance.padding.small * 2

            StateLayer {
                id: prevMonthStateLayer

                radius: Appearance.rounding.full

                function onClicked(): void {
                    root.state.currentDate = new Date(root.currYear, root.currMonth - 1, 1);
                }
            }

            MaterialIcon {
                id: prevMonthText

                anchors.centerIn: parent
                text: "chevron_left"
                color: Colours.palette.m3tertiary
                font.pointSize: Appearance.font.size.normal
                font.weight: 700
            }
        }

        Item {
            Layout.fillWidth: true

            implicitWidth: monthYearDisplay.implicitWidth + Appearance.padding.small * 2
            implicitHeight: monthYearDisplay.implicitHeight + Appearance.padding.small * 2

            StateLayer {
                anchors.fill: monthYearDisplay
                anchors.margins: -Appearance.padding.small
                anchors.leftMargin: -Appearance.padding.normal
                anchors.rightMargin: -Appearance.padding.normal

                radius: Appearance.rounding.full
                disabled: root.state.currentDate.toDateString() == new Date().toDateString()

                function onClicked(): void {
                    root.state.currentDate = new Date();
                }
            }

            StyledText {
                id: monthYearDisplay

                anchors.centerIn: parent
                text: grid.title
                color: Colours.palette.m3primary
                font.pointSize: Appearance.font.size.normal
                font.weight: 500
                font.capitalization: Font.Capitalize
            }
        }

        Item {
            implicitWidth: implicitHeight
            implicitHeight: nextMonthText.implicitHeight + Appearance.padding.small * 2

            StateLayer {
                id: nextMonthStateLayer

                radius: Appearance.rounding.full

                function onClicked(): void {
                    root.state.currentDate = new Date(root.currYear, root.currMonth + 1, 1);
                }
            }

            MaterialIcon {
                id: nextMonthText

                anchors.centerIn: parent
                text: "chevron_right"
                color: Colours.palette.m3tertiary
                font.pointSize: Appearance.font.size.normal
                font.weight: 700
            }
        }
    }

    DayOfWeekRow {
        id: daysRow

        locale: grid.locale

        anchors.left: parent.left
        anchors.right: parent.right
        anchors.margins: parent.padding

        delegate: StyledText {
            required property var model

            horizontalAlignment: Text.AlignHCenter
            text: model.shortName
            font.weight: 500
            color: (model.day === 0 || model.day === 6) ? Colours.palette.m3secondary : Colours.palette.m3onSurfaceVariant
        }
    }

    Item {
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.margins: parent.padding

        implicitHeight: grid.implicitHeight

        MonthGrid {
            id: grid

            month: root.currMonth
            year: root.currYear

            anchors.left: parent.left
            anchors.right: parent.right

            spacing: 3
            locale: Qt.locale()

            delegate: Item {
                id: dayItem

                required property var model

                implicitWidth: implicitHeight
                implicitHeight: text.implicitHeight + Appearance.padding.small * 2

                StyledText {
                    id: text

                    anchors.centerIn: parent

                    horizontalAlignment: Text.AlignHCenter
                    text: grid.locale.toString(dayItem.model.day)
                    color: {
                        const dayOfWeek = dayItem.model.date.getUTCDay();
                        if (dayOfWeek === 0 || dayOfWeek === 6)
                            return Colours.palette.m3secondary;

                        return Colours.palette.m3onSurfaceVariant;
                    }
                    opacity: dayItem.model.today || dayItem.model.month === grid.month ? 1 : 0.4
                    font.pointSize: Appearance.font.size.normal
                    font.weight: 500
                }
            }
        }

        StyledClippingRect {
            id: todayIndicator

            readonly property Item todayItem: grid.contentItem.children.find(c => c.model.today) ?? null
            property Item today

            onTodayItemChanged: {
                if (todayItem)
                    today = todayItem;
            }

            x: today ? today.x + (today.width - implicitWidth) / 2 : 0
            y: today?.y ?? 0

            implicitWidth: today?.implicitWidth ?? 0
            implicitHeight: today?.implicitHeight ?? 0

            radius: Appearance.rounding.full
            color: Colours.palette.m3primary

            opacity: todayItem ? 1 : 0
            scale: todayItem ? 1 : 0.7

            Colouriser {
                x: -todayIndicator.x
                y: -todayIndicator.y

                implicitWidth: grid.width
                implicitHeight: grid.height

                source: grid
                sourceColor: Colours.palette.m3onSurface
                colorizationColor: Colours.palette.m3onPrimary
            }

            Behavior on opacity {
                Anim {}
            }

            Behavior on scale {
                Anim {}
            }

            Behavior on x {
                Anim {
                    easing.bezierCurve: Appearance.anim.curves.emphasized
                }
            }

            Behavior on y {
                Anim {
                    easing.bezierCurve: Appearance.anim.curves.emphasized
                }
            }
        }
    }
}