-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
308 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
<script setup lang="ts"> | ||
import { IonCard, IonCardContent, IonLabel, IonListHeader } from '@ionic/vue'; | ||
import FrontingEntryAvatar from '../frontingEntry/FrontingEntryAvatar.vue'; | ||
import { onMounted, onUnmounted, ref, shallowRef, watch, WatchStopHandle } from 'vue'; | ||
import { PartialBy } from '../../lib/db/types'; | ||
import { FrontingEntryComplete, getFrontingEntriesTable, toFrontingEntryComplete } from '../../lib/db/entities/frontingEntries'; | ||
import { from, useObservable } from '@vueuse/rxjs'; | ||
import { liveQuery } from 'dexie'; | ||
import { getMembersTable } from '../../lib/db/entities/members'; | ||
import { formatWrittenTime } from "../../lib/util/misc"; | ||
import FrontingEntryEdit from '../../modals/FrontingEntryEdit.vue'; | ||
const frontingEntryModal = ref(); | ||
const emptyFrontingEntry: PartialBy<FrontingEntryComplete, "uuid" | "member"> = { | ||
isMainFronter: false, | ||
startTime: new Date(), | ||
endTime: new Date(), | ||
}; | ||
const frontingEntry = shallowRef({...emptyFrontingEntry}); | ||
const frontingEntries = shallowRef<FrontingEntryComplete[]>([]); | ||
const now = ref(new Date()); | ||
let handle: WatchStopHandle; | ||
let interval: NodeJS.Timeout; | ||
onMounted(async () => { | ||
interval = setInterval(() => now.value = new Date(), 1000); | ||
handle = watch([ | ||
useObservable(from(liveQuery(() => getFrontingEntriesTable().toArray()))), | ||
useObservable(from(liveQuery(() => getMembersTable().toArray()))) | ||
], async () => { | ||
frontingEntries.value = await Promise.all( | ||
(await getFrontingEntriesTable() | ||
.filter(x => !x.endTime) | ||
.toArray() | ||
) | ||
.sort((a, b) => b.isMainFronter ? 1 : b.startTime.getTime() - a.startTime.getTime()) | ||
.map(x => toFrontingEntryComplete(x)) | ||
); | ||
}, { immediate: true }); | ||
frontingEntry.value = { ...frontingEntries.value[0] }; | ||
}); | ||
onUnmounted(async () => { | ||
clearInterval(interval); | ||
handle(); | ||
}); | ||
async function showModal(clickedFrontingEntry: FrontingEntryComplete){ | ||
frontingEntry.value = {...clickedFrontingEntry}; | ||
await frontingEntryModal.value.$el.present(); | ||
} | ||
</script> | ||
|
||
<template> | ||
<IonListHeader v-if="frontingEntries.length"> | ||
<IonLabel>{{ $t("dashboard:nowFronting") }}</IonLabel> | ||
</IonListHeader> | ||
<div class="carousel" v-if="frontingEntries.length"> | ||
<IonCard button :class="{outlined: !fronting.isMainFronter, elevated: fronting.isMainFronter}" @click="showModal(fronting)" v-for="fronting in frontingEntries" :key="JSON.stringify(fronting)"> | ||
<IonCardContent> | ||
<FrontingEntryAvatar :entry="fronting" /> | ||
<IonLabel> | ||
<h2> | ||
{{ fronting.member.name }} | ||
</h2> | ||
<p> | ||
{{ formatWrittenTime(now, fronting.startTime) }} | ||
</p> | ||
<p v-if="fronting.customStatus"> | ||
{{ fronting.customStatus }} | ||
</p> | ||
</IonLabel> | ||
</IonCardContent> | ||
</IonCard> | ||
</div> | ||
<FrontingEntryEdit v-if="frontingEntries.length" ref="frontingEntryModal" :frontingEntry /> | ||
</template> | ||
|
||
<style scoped> | ||
div { | ||
display: flex; | ||
flex-direction: row; | ||
flex-wrap: nowrap; | ||
overflow-x: scroll; | ||
} | ||
ion-card { | ||
width: 160px; | ||
} | ||
ion-card ion-avatar { | ||
margin: 16px auto; | ||
} | ||
ion-card ion-card-content { | ||
text-align: center; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<script setup lang="ts"> | ||
import { IonList, IonItem, IonListHeader, IonLabel } from '@ionic/vue'; | ||
import { inject, onMounted, onUnmounted, ref, ShallowRef, shallowRef, watch, WatchStopHandle } from 'vue'; | ||
import FrontingEntryAvatar from "../frontingEntry/FrontingEntryAvatar.vue"; | ||
import FrontingEntryLabel from "../frontingEntry/FrontingEntryLabel.vue"; | ||
import { FrontingEntryComplete, getFrontingEntriesTable, toFrontingEntryComplete } from '../../lib/db/entities/frontingEntries'; | ||
import FrontingEntryEdit from "../../modals/FrontingEntryEdit.vue"; | ||
import dayjs from 'dayjs'; | ||
import { from, useObservable } from '@vueuse/rxjs'; | ||
import { liveQuery } from 'dexie'; | ||
import { getMembersTable } from '../../lib/db/entities/members'; | ||
import { PartialBy } from '../../lib/db/types'; | ||
const isIOS = inject<boolean>("isIOS"); | ||
const frontingEntryModal = ref(); | ||
const emptyFrontingEntry: PartialBy<FrontingEntryComplete, "uuid" | "member"> = { | ||
isMainFronter: false, | ||
startTime: new Date(), | ||
endTime: new Date(), | ||
}; | ||
const frontingEntry = shallowRef({...emptyFrontingEntry}); | ||
const frontingEntries: ShallowRef<FrontingEntryComplete[]> = shallowRef([]); | ||
let handle: WatchStopHandle; | ||
onMounted(() => { | ||
handle = watch([ | ||
useObservable(from(liveQuery(() => getFrontingEntriesTable().toArray()))), | ||
useObservable(from(liveQuery(() => getMembersTable().toArray()))), | ||
], async () => { | ||
frontingEntries.value = await Promise.all( | ||
( | ||
await getFrontingEntriesTable() | ||
.filter(x => !!x.endTime && dayjs.duration(dayjs().diff(x.endTime)).asHours() < 48) | ||
.toArray() | ||
) | ||
.sort((a, b) => b.endTime!.getTime() - a.endTime!.getTime()) | ||
.map(x => toFrontingEntryComplete(x)) | ||
); | ||
}, { immediate: true }); | ||
}); | ||
onUnmounted(async () => { | ||
handle(); | ||
}); | ||
async function showModal(clickedFrontingEntry: FrontingEntryComplete){ | ||
frontingEntry.value = {...clickedFrontingEntry}; | ||
await frontingEntryModal.value.$el.present(); | ||
} | ||
</script> | ||
|
||
<template> | ||
<IonListHeader> | ||
<IonLabel>{{ $t("dashboard:recentFrontingHistory") }}</IonLabel> | ||
</IonListHeader> | ||
|
||
<IonList :inset="isIOS"> | ||
<IonItem button v-for="entry in frontingEntries" :key="JSON.stringify(entry)" @click="showModal(entry)"> | ||
<FrontingEntryAvatar slot="start" :entry /> | ||
<FrontingEntryLabel :entry /> | ||
</IonItem> | ||
</IonList> | ||
|
||
<FrontingEntryEdit :frontingEntry ref="frontingEntryModal" /> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<script setup lang="ts"> | ||
import { IonList, IonLabel, IonButton, IonListHeader } from '@ionic/vue'; | ||
import { inject, onMounted, onUnmounted, ref, shallowRef, watch, WatchStopHandle } from 'vue'; | ||
import { BoardMessageComplete, getBoardMessagesTable, toBoardMessageComplete } from '../../lib/db/entities/boardMessages'; | ||
import BoardMessageEdit from "../../modals/BoardMessageEdit.vue"; | ||
import { PartialBy } from '../../lib/db/types'; | ||
import dayjs from 'dayjs'; | ||
import { from, useObservable } from '@vueuse/rxjs'; | ||
import { liveQuery } from 'dexie'; | ||
import { getMembersTable } from '../../lib/db/entities/members'; | ||
import { getFronting, getMainFronter } from '../../lib/db/entities/frontingEntries'; | ||
import MessageBoardCard from '../MessageBoardCard.vue'; | ||
const isIOS = inject<boolean>("isIOS"); | ||
const emptyBoardMessage: PartialBy<BoardMessageComplete, "uuid" | "member"> = { | ||
title: "", | ||
body: "", | ||
date: new Date() | ||
} | ||
const boardMessage = shallowRef<PartialBy<BoardMessageComplete, "uuid" | "member">>({...emptyBoardMessage}); | ||
const boardMessageEditModal = ref(); | ||
const boardMessages = shallowRef<BoardMessageComplete[]>([]); | ||
let handle: WatchStopHandle; | ||
onMounted(() => { | ||
handle = watch([ | ||
useObservable(from(liveQuery(() => getBoardMessagesTable().toArray()))), | ||
useObservable(from(liveQuery(() => getMembersTable().toArray()))), | ||
], async () => { | ||
boardMessages.value = await Promise.all( | ||
( | ||
await getBoardMessagesTable() | ||
.filter(x => dayjs(x.date).startOf('day').valueOf() === dayjs().startOf('day').valueOf()) | ||
.toArray() | ||
).map(x => toBoardMessageComplete(x)) | ||
); | ||
}, { immediate: true }); | ||
}); | ||
onUnmounted(() => { | ||
handle(); | ||
}); | ||
async function showModal(_boardMessage?: BoardMessageComplete){ | ||
if(_boardMessage) | ||
boardMessage.value = {..._boardMessage}; | ||
else { | ||
boardMessage.value = { | ||
...emptyBoardMessage, | ||
date: new Date(), | ||
member: await getMainFronter() || (await getFronting())[0] | ||
}; | ||
} | ||
await boardMessageEditModal.value.$el.present(); | ||
} | ||
</script> | ||
|
||
<template> | ||
<IonListHeader> | ||
<IonLabel>{{ $t("dashboard:messageBoard.header") }}</IonLabel> | ||
</IonListHeader> | ||
|
||
<IonList :inset="isIOS"> | ||
<MessageBoardCard :boardMessage v-for="boardMessage in boardMessages" :key="JSON.stringify(boardMessage)" @click="showModal(boardMessage)" /> | ||
</IonList> | ||
|
||
<div> | ||
<IonButton @click="showModal()">{{ $t("dashboard:messageBoard.add") }}</IonButton> | ||
<IonButton fill="clear" router-link="/options/messageBoard">{{ $t("dashboard:messageBoard.view") }}</IonButton> | ||
</div> | ||
|
||
<BoardMessageEdit :boardMessage ref="boardMessageEditModal" /> | ||
</template> | ||
|
||
<style scoped> | ||
div { | ||
display: flex; | ||
justify-content: center; | ||
gap: 16px; | ||
} | ||
.ios ion-list { | ||
background-color: transparent; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,12 @@ | ||
{ | ||
"header": "Dashboard" | ||
"header": "Dashboard", | ||
"header_salute": "Hello!", | ||
"header_mainfronter": "Hi, {{fronterName}}!", | ||
"nowFronting": "Now fronting", | ||
"recentFrontingHistory": "Recently switched out", | ||
"messageBoard": { | ||
"header": "Message board", | ||
"add": "Add to message board", | ||
"view": "View more..." | ||
} | ||
} |