mirror of
https://github.com/ckaczor/HomeMonitor.git
synced 2026-01-13 17:22:54 -05:00
Split calendar and national days to components
This commit is contained in:
2
WebDisplay/components.d.ts
vendored
2
WebDisplay/components.d.ts
vendored
@@ -8,12 +8,14 @@ export {}
|
|||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
Almanac: typeof import('./src/components/Almanac.vue')['default']
|
Almanac: typeof import('./src/components/Almanac.vue')['default']
|
||||||
|
CalendarAgenda: typeof import('./src/components/CalendarAgenda.vue')['default']
|
||||||
CurrentLaundryStatus: typeof import('./src/components/CurrentLaundryStatus.vue')['default']
|
CurrentLaundryStatus: typeof import('./src/components/CurrentLaundryStatus.vue')['default']
|
||||||
CurrentPower: typeof import('./src/components/CurrentPower.vue')['default']
|
CurrentPower: typeof import('./src/components/CurrentPower.vue')['default']
|
||||||
CurrentWeather: typeof import('./src/components/CurrentWeather.vue')['default']
|
CurrentWeather: typeof import('./src/components/CurrentWeather.vue')['default']
|
||||||
DashboardItem: typeof import('./src/components/DashboardItem.vue')['default']
|
DashboardItem: typeof import('./src/components/DashboardItem.vue')['default']
|
||||||
Indoor: typeof import('./src/components/Indoor.vue')['default']
|
Indoor: typeof import('./src/components/Indoor.vue')['default']
|
||||||
IndoorSummary: typeof import('./src/components/IndoorSummary.vue')['default']
|
IndoorSummary: typeof import('./src/components/IndoorSummary.vue')['default']
|
||||||
|
NationalDays: typeof import('./src/components/NationalDays.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
TimeRange: typeof import('./src/components/TimeRange.vue')['default']
|
TimeRange: typeof import('./src/components/TimeRange.vue')['default']
|
||||||
|
|||||||
148
WebDisplay/src/components/CalendarAgenda.vue
Normal file
148
WebDisplay/src/components/CalendarAgenda.vue
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useCalendarStore } from '@/stores/calendarStore';
|
||||||
|
import { format, startOfDay, endOfDay } from 'date-fns';
|
||||||
|
import CalendarDay from '@/models/calendar/calendar-day';
|
||||||
|
|
||||||
|
const props = defineProps(['days', 'refreshInterval']);
|
||||||
|
|
||||||
|
const calendarStore = useCalendarStore();
|
||||||
|
|
||||||
|
const calendarDays = ref([] as CalendarDay[]);
|
||||||
|
const calendarReady = ref(false);
|
||||||
|
|
||||||
|
function loadCalendar() {
|
||||||
|
const newCalendarDays = [] as CalendarDay[];
|
||||||
|
|
||||||
|
calendarStore.getUpcoming(props.days, true).then((upcoming) => {
|
||||||
|
const currentDay = startOfDay(new Date());
|
||||||
|
|
||||||
|
for (let i = 0; i < props.days; i++) {
|
||||||
|
const day = new Date(currentDay);
|
||||||
|
day.setDate(day.getDate() + i);
|
||||||
|
|
||||||
|
const entries = upcoming
|
||||||
|
.filter((entry) => {
|
||||||
|
const entryStart = startOfDay(entry.start);
|
||||||
|
const entryEnd = endOfDay(entry.end);
|
||||||
|
|
||||||
|
if (entry.isAllDay) {
|
||||||
|
return day > entryStart && day < entryEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return day >= entryStart && day <= entryEnd;
|
||||||
|
})
|
||||||
|
.sort((a, b) => {
|
||||||
|
if (a.isHoliday == b.isHoliday) {
|
||||||
|
return a.summary.localeCompare(b.summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (b.isHoliday ? 1 : 0) - (a.isHoliday ? 1 : 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
newCalendarDays.push(new CalendarDay(day, entries));
|
||||||
|
}
|
||||||
|
|
||||||
|
calendarDays.value = newCalendarDays;
|
||||||
|
|
||||||
|
calendarReady.value = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCalendar();
|
||||||
|
|
||||||
|
setInterval(() => loadCalendar(), props.refreshInterval);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="calendar"
|
||||||
|
v-if="calendarReady">
|
||||||
|
<div class="calendar-header">
|
||||||
|
{{ 'Next ' + days + ' Days' }}
|
||||||
|
</div>
|
||||||
|
<ul class="calendar-day-list">
|
||||||
|
<li
|
||||||
|
class="calendar-day-item"
|
||||||
|
v-for="calendarDay in calendarDays">
|
||||||
|
<div>
|
||||||
|
<div class="calendar-day-item-header">
|
||||||
|
<span class="calendar-day-item-number">
|
||||||
|
{{ format(calendarDay.date, 'dd') }}
|
||||||
|
</span>
|
||||||
|
<span class="calendar-day-item-name">
|
||||||
|
{{ format(calendarDay.date, 'EEEE') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<ul
|
||||||
|
class="calendar-entry"
|
||||||
|
v-for="calendarEntry in calendarDay.entries"
|
||||||
|
:class="{ 'calendar-holiday': calendarEntry.isHoliday }">
|
||||||
|
<span>
|
||||||
|
{{ calendarEntry.summary }}
|
||||||
|
</span>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.calendar {
|
||||||
|
background-color: #121212;
|
||||||
|
border-radius: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-header {
|
||||||
|
font-size: 1.15em;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day-item-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day-item-number {
|
||||||
|
font-size: 1.25em;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day-item-name {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day-list {
|
||||||
|
margin-left: 10px;
|
||||||
|
overflow: auto;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day-item:not(:last-child) {
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day-item:first-of-type {
|
||||||
|
color: #c75ec7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day-item:not(:first-child) {
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-entry {
|
||||||
|
color: #ebebeb;
|
||||||
|
padding-left: 2em;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-holiday {
|
||||||
|
color: #5e83c7;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
56
WebDisplay/src/components/NationalDays.vue
Normal file
56
WebDisplay/src/components/NationalDays.vue
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useCalendarStore } from '@/stores/calendarStore';
|
||||||
|
import { startOfDay, isEqual } from 'date-fns';
|
||||||
|
import NationalDayEntry from '@/models/calendar/national-day';
|
||||||
|
|
||||||
|
const calendarStore = useCalendarStore();
|
||||||
|
|
||||||
|
const nationalDays = ref([] as NationalDayEntry[]);
|
||||||
|
const nationalDaysReady = ref(false);
|
||||||
|
const loadedNationalDay = ref(null as Date | null);
|
||||||
|
|
||||||
|
function loadNationalDays() {
|
||||||
|
calendarStore.getNationalDays().then((data) => {
|
||||||
|
nationalDays.value = data.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
|
||||||
|
loadedNationalDay.value = startOfDay(new Date());
|
||||||
|
|
||||||
|
nationalDaysReady.value = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadNationalDays();
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
if (loadedNationalDay.value && !isEqual(loadedNationalDay.value, startOfDay(new Date()))) {
|
||||||
|
loadNationalDays();
|
||||||
|
}
|
||||||
|
}, 10 * 1000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="national-days"
|
||||||
|
v-if="nationalDaysReady">
|
||||||
|
<ul>
|
||||||
|
<li
|
||||||
|
class="national-day"
|
||||||
|
v-for="nationalDay in nationalDays">
|
||||||
|
{{ nationalDay.name }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.national-days {
|
||||||
|
background-color: #121212;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.national-day:not(:last-child) {
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -4,12 +4,7 @@
|
|||||||
import { useLaundryStore } from '@/stores/laundryStore';
|
import { useLaundryStore } from '@/stores/laundryStore';
|
||||||
import { usePowerStore } from '@/stores/powerStore';
|
import { usePowerStore } from '@/stores/powerStore';
|
||||||
import { useHomeAssistantStore } from '@/stores/homeAssistantStore';
|
import { useHomeAssistantStore } from '@/stores/homeAssistantStore';
|
||||||
import { useCalendarStore } from '@/stores/calendarStore';
|
import CalendarAgenda from '@/components/CalendarAgenda.vue';
|
||||||
import { format, startOfDay, endOfDay, isEqual } from 'date-fns';
|
|
||||||
import CalendarDay from '@/models/calendar/calendar-day';
|
|
||||||
import NationalDayEntry from '@/models/calendar/national-day';
|
|
||||||
|
|
||||||
const calendarDayCount = 7;
|
|
||||||
|
|
||||||
const weatherStore = useWeatherStore();
|
const weatherStore = useWeatherStore();
|
||||||
weatherStore.start();
|
weatherStore.start();
|
||||||
@@ -23,15 +18,7 @@
|
|||||||
const homeAssistantStore = useHomeAssistantStore();
|
const homeAssistantStore = useHomeAssistantStore();
|
||||||
homeAssistantStore.start();
|
homeAssistantStore.start();
|
||||||
|
|
||||||
const calendarStore = useCalendarStore();
|
|
||||||
|
|
||||||
const currentTime = ref(new Date());
|
const currentTime = ref(new Date());
|
||||||
const calendarDays = ref([] as CalendarDay[]);
|
|
||||||
const calendarReady = ref(false);
|
|
||||||
|
|
||||||
const nationalDays = ref([] as NationalDayEntry[]);
|
|
||||||
const nationalDaysReady = ref(false);
|
|
||||||
const loadedNationalDay = ref(null as Date | null);
|
|
||||||
|
|
||||||
const timeFormatter = new Intl.DateTimeFormat('en-US', { hour: 'numeric', minute: '2-digit' });
|
const timeFormatter = new Intl.DateTimeFormat('en-US', { hour: 'numeric', minute: '2-digit' });
|
||||||
const dateFormatter = new Intl.DateTimeFormat('en-US', { weekday: 'long', month: 'long', day: 'numeric' });
|
const dateFormatter = new Intl.DateTimeFormat('en-US', { weekday: 'long', month: 'long', day: 'numeric' });
|
||||||
@@ -49,67 +36,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadCalendar() {
|
setInterval(() => (currentTime.value = new Date()), 1000);
|
||||||
const newCalendarDays = [] as CalendarDay[];
|
|
||||||
|
|
||||||
calendarStore.getUpcoming(calendarDayCount, true).then((upcoming) => {
|
|
||||||
const currentDay = startOfDay(currentTime.value);
|
|
||||||
|
|
||||||
for (let i = 0; i < calendarDayCount; i++) {
|
|
||||||
const day = new Date(currentDay);
|
|
||||||
day.setDate(day.getDate() + i);
|
|
||||||
|
|
||||||
const entries = upcoming
|
|
||||||
.filter((entry) => {
|
|
||||||
const entryStart = startOfDay(entry.start);
|
|
||||||
const entryEnd = endOfDay(entry.end);
|
|
||||||
|
|
||||||
if (entry.isAllDay) {
|
|
||||||
return day > entryStart && day < entryEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
return day >= entryStart && day <= entryEnd;
|
|
||||||
})
|
|
||||||
.sort((a, b) => {
|
|
||||||
if (a.isHoliday == b.isHoliday) {
|
|
||||||
return a.summary.localeCompare(b.summary);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (b.isHoliday ? 1 : 0) - (a.isHoliday ? 1 : 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
newCalendarDays.push(new CalendarDay(day, entries));
|
|
||||||
}
|
|
||||||
|
|
||||||
calendarDays.value = newCalendarDays;
|
|
||||||
|
|
||||||
calendarReady.value = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
loadCalendar();
|
|
||||||
|
|
||||||
function loadNationalDays() {
|
|
||||||
calendarStore.getNationalDays().then((data) => {
|
|
||||||
nationalDays.value = data.sort((a, b) => a.name.localeCompare(b.name));
|
|
||||||
|
|
||||||
loadedNationalDay.value = startOfDay(currentTime.value);
|
|
||||||
|
|
||||||
nationalDaysReady.value = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
loadNationalDays();
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
currentTime.value = new Date();
|
|
||||||
|
|
||||||
if (loadedNationalDay.value && !isEqual(loadedNationalDay.value, startOfDay(currentTime.value))) {
|
|
||||||
loadNationalDays();
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
setInterval(() => loadCalendar(), 30 * 60 * 1000);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -202,46 +129,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="kiosk-content">
|
<div class="kiosk-content">
|
||||||
<div
|
<CalendarAgenda
|
||||||
class="kiosk-calendar"
|
class="kiosk-calendar"
|
||||||
v-if="calendarReady">
|
days="7"
|
||||||
<div class="kiosk-calendar-header">
|
:refresh-interval="30 * 60 * 1000" />
|
||||||
{{ 'Next ' + calendarDayCount + ' Days' }}
|
<NationalDays class="kiosk-national-days" />
|
||||||
</div>
|
|
||||||
<ul class="kiosk-calendar-day-list">
|
|
||||||
<li
|
|
||||||
class="kiosk-calendar-day-item"
|
|
||||||
v-for="calendarDay in calendarDays">
|
|
||||||
<div>
|
|
||||||
<div class="kiosk-calendar-day-item-header">
|
|
||||||
<span class="kiosk-calendar-day-item-number">
|
|
||||||
{{ format(calendarDay.date, 'dd') }}
|
|
||||||
</span>
|
|
||||||
<span class="kiosk-calendar-day-item-name">
|
|
||||||
{{ format(calendarDay.date, 'EEEE') }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<ul
|
|
||||||
class="kiosk-calendar-entry"
|
|
||||||
v-for="calendarEntry in calendarDay.entries"
|
|
||||||
:class="calendarEntry.isHoliday ? 'holiday' : ''">
|
|
||||||
<span>
|
|
||||||
{{ calendarEntry.summary }}
|
|
||||||
</span>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="kiosk-national-days"
|
|
||||||
v-if="nationalDaysReady">
|
|
||||||
<ul>
|
|
||||||
<li v-for="nationalDay in nationalDays">
|
|
||||||
{{ nationalDay.name }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
@@ -356,66 +248,14 @@
|
|||||||
|
|
||||||
.kiosk-calendar {
|
.kiosk-calendar {
|
||||||
grid-area: kiosk-calendar;
|
grid-area: kiosk-calendar;
|
||||||
background-color: #121212;
|
overflow: auto;
|
||||||
border-radius: 10px;
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.kiosk-national-days {
|
.kiosk-national-days {
|
||||||
grid-area: kiosk-national-days;
|
grid-area: kiosk-national-days;
|
||||||
background-color: #121212;
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 10px;
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kiosk-calendar-header {
|
|
||||||
font-size: 1.15em;
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiosk-calendar-day-item-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiosk-calendar-day-item-number {
|
|
||||||
font-size: 1.25em;
|
|
||||||
padding-right: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiosk-calendar-day-item-name {
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiosk-calendar-day-list {
|
|
||||||
margin-left: 10px;
|
|
||||||
overflow: auto;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiosk-calendar-day-item:not(:last-child) {
|
|
||||||
padding-bottom: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiosk-calendar-day-item:first-of-type {
|
|
||||||
color: #c75ec7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiosk-calendar-day-item:not(:first-child) {
|
|
||||||
padding-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiosk-calendar-entry {
|
|
||||||
color: #ebebeb;
|
|
||||||
padding-left: 2em;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.warning {
|
.warning {
|
||||||
color: #d09f27;
|
color: #d09f27;
|
||||||
}
|
}
|
||||||
@@ -423,8 +263,4 @@
|
|||||||
.normal {
|
.normal {
|
||||||
color: #208b20;
|
color: #208b20;
|
||||||
}
|
}
|
||||||
|
|
||||||
.holiday {
|
|
||||||
color: #5e83c7;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user