2026-03-27 22:45:12 +00:00
|
|
|
<template>
|
|
|
|
|
<BaseDialog
|
2026-03-28 17:18:12 +00:00
|
|
|
v-if="currentAnnouncement"
|
2026-03-27 22:45:12 +00:00
|
|
|
v-model="dialog"
|
2026-03-28 01:05:08 +00:00
|
|
|
:title="$t('announcements.announcements')"
|
|
|
|
|
:icon="$globals.icons.bullhornVariant"
|
2026-03-28 16:28:57 +00:00
|
|
|
:cancel-text="$t('general.done')"
|
2026-03-28 01:05:08 +00:00
|
|
|
width="100%"
|
|
|
|
|
max-width="1200"
|
2026-03-27 22:45:12 +00:00
|
|
|
>
|
2026-03-28 01:05:08 +00:00
|
|
|
<v-card-title>
|
|
|
|
|
<v-chip label large class="me-1">
|
|
|
|
|
<v-icon class="me-1">
|
|
|
|
|
{{ $globals.icons.calendar }}
|
|
|
|
|
</v-icon>
|
|
|
|
|
{{ $d(new Date(currentAnnouncement.key.split('_', 1)[0])) }}
|
|
|
|
|
</v-chip>
|
|
|
|
|
{{ currentAnnouncement.meta?.title }}
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text>
|
|
|
|
|
<component :is="currentAnnouncement.component" />
|
|
|
|
|
</v-card-text>
|
2026-03-28 17:18:12 +00:00
|
|
|
<template #custom-card-action>
|
|
|
|
|
<div v-if="newAnnouncements.length">
|
|
|
|
|
<BaseButton
|
|
|
|
|
color="success"
|
|
|
|
|
:icon="$globals.icons.textBoxCheckOutline"
|
|
|
|
|
:text="$t('announcements.mark-all-as-read')"
|
|
|
|
|
class="mx-4"
|
|
|
|
|
@click="markAllAsRead"
|
|
|
|
|
/>
|
|
|
|
|
<BaseButton
|
|
|
|
|
color="info"
|
|
|
|
|
:icon="$globals.icons.arrowRightBold"
|
|
|
|
|
icon-right
|
|
|
|
|
:text="$t('general.next')"
|
|
|
|
|
@click="nextAnnouncement"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
2026-03-27 22:45:12 +00:00
|
|
|
</BaseDialog>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2026-03-28 01:05:08 +00:00
|
|
|
import { useAnnouncements } from "~/composables/use-announcements";
|
|
|
|
|
import { useUserApi } from "~/composables/api";
|
|
|
|
|
|
2026-03-27 22:45:12 +00:00
|
|
|
const dialog = defineModel<boolean>({ default: false });
|
2026-03-28 01:05:08 +00:00
|
|
|
|
|
|
|
|
const auth = useMealieAuth();
|
|
|
|
|
const api = useUserApi();
|
|
|
|
|
const { newAnnouncements, allAnnouncements } = useAnnouncements();
|
|
|
|
|
|
2026-03-28 17:18:12 +00:00
|
|
|
const currentAnnouncement = shallowRef<Announcement | undefined>();
|
2026-03-28 01:05:08 +00:00
|
|
|
watch(
|
2026-03-28 16:17:34 +00:00
|
|
|
dialog,
|
2026-03-28 01:05:08 +00:00
|
|
|
() => {
|
2026-03-28 17:18:12 +00:00
|
|
|
// Once the dialog is opened, show the next announcement
|
2026-03-28 01:05:08 +00:00
|
|
|
if (dialog.value) {
|
2026-03-28 17:18:12 +00:00
|
|
|
nextAnnouncement();
|
|
|
|
|
|
|
|
|
|
// If there are no new announcements, this is never set, so show the newest one
|
|
|
|
|
if (!currentAnnouncement.value) {
|
|
|
|
|
currentAnnouncement.value = allAnnouncements.at(-1);
|
|
|
|
|
}
|
2026-03-28 01:05:08 +00:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
async function setLastRead(key: string) {
|
|
|
|
|
const user = auth.user.value!;
|
2026-03-28 16:28:57 +00:00
|
|
|
if (user.lastReadAnnouncement && key <= user.lastReadAnnouncement) {
|
2026-03-28 01:05:08 +00:00
|
|
|
// Don't update the last read announcement if it's older than the current one
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await api.users.updateOne(
|
|
|
|
|
user.id,
|
|
|
|
|
{
|
|
|
|
|
...user,
|
2026-03-28 17:18:12 +00:00
|
|
|
lastReadAnnouncement: null, // TODO: switch back to key
|
2026-03-28 01:05:08 +00:00
|
|
|
},
|
2026-03-28 16:43:07 +00:00
|
|
|
{ suppressAlert: true },
|
2026-03-28 01:05:08 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function markAllAsRead() {
|
2026-03-28 17:18:12 +00:00
|
|
|
newAnnouncements.value = [];
|
|
|
|
|
|
2026-03-28 01:05:08 +00:00
|
|
|
const newestAnnouncement = allAnnouncements.at(-1)!;
|
|
|
|
|
setLastRead(newestAnnouncement.key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function nextAnnouncement() {
|
|
|
|
|
const nextAnnouncement = newAnnouncements.value.at(0);
|
2026-03-28 17:18:12 +00:00
|
|
|
newAnnouncements.value = newAnnouncements.value.slice(1);
|
|
|
|
|
|
2026-03-28 01:05:08 +00:00
|
|
|
if (!nextAnnouncement) {
|
2026-03-28 17:18:12 +00:00
|
|
|
markAllAsRead();
|
2026-03-28 01:05:08 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentAnnouncement.value = nextAnnouncement;
|
|
|
|
|
setLastRead(currentAnnouncement.value.key);
|
|
|
|
|
}
|
2026-03-27 22:45:12 +00:00
|
|
|
</script>
|