implement basic placeholder announcement

This commit is contained in:
Michael Genson
2026-03-28 01:05:08 +00:00
parent bd1ed028b5
commit fcf2b7ef2a
4 changed files with 114 additions and 5 deletions

View File

@@ -1,11 +1,76 @@
<template>
<BaseDialog
v-model="dialog"
:title="$t('announcements.announcements')"
:icon="$globals.icons.bullhornVariant"
width="100%"
max-width="1200"
>
test <!-- TODO -->
<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>
</BaseDialog>
</template>
<script setup lang="ts">
import { useAnnouncements } from "~/composables/use-announcements";
import { useUserApi } from "~/composables/api";
const dialog = defineModel<boolean>({ default: false });
const auth = useMealieAuth();
const api = useUserApi();
const { newAnnouncements, allAnnouncements } = useAnnouncements();
const currentAnnouncement = shallowRef(newAnnouncements.value.at(0) || allAnnouncements.at(-1)!);
watch(
() => dialog,
() => {
// Once the dialog is opened, mark the current announcement as read
if (dialog.value) {
setLastRead(currentAnnouncement.value.key);
}
},
);
async function setLastRead(key: string) {
const user = auth.user.value!;
if (user.lastReadAnnouncement && key < user.lastReadAnnouncement) {
// Don't update the last read announcement if it's older than the current one
return;
}
await api.users.updateOne(
user.id,
{
...user,
lastReadAnnouncement: key,
},
);
}
function markAllAsRead() {
const newestAnnouncement = allAnnouncements.at(-1)!;
setLastRead(newestAnnouncement.key);
}
function nextAnnouncement() {
newAnnouncements.value.shift();
const nextAnnouncement = newAnnouncements.value.at(0);
if (!nextAnnouncement) {
return;
}
currentAnnouncement.value = nextAnnouncement;
setLastRead(currentAnnouncement.value.key);
}
</script>

View File

@@ -0,0 +1,13 @@
<template>
<div>
Welcome to Mealie! This is a placeholder test announcement.
</div>
</template>
<script lang="ts">
import type { AnnouncementMeta } from "~/composables/use-announcements";
export const meta: AnnouncementMeta = {
title: "Placeholder Title",
};
</script>

View File

@@ -125,7 +125,7 @@
>
<template #prepend>
<v-badge
:model-value="!!newAnnouncements?.length"
:model-value="!!newAnnouncements.length"
color="accent"
:content="newAnnouncements?.length"
offset-x="-2"

View File

@@ -1,6 +1,28 @@
import { useHouseholdSelf } from "~/composables/use-households";
import { useGroupSelf } from "~/composables/use-groups";
export type AnnouncementMeta = {
title: string | undefined;
};
export type Announcement = {
key: string;
component: Component;
meta: AnnouncementMeta | undefined;
};
const _announcementsUnsorted = import.meta.glob<{ default: Component; meta?: AnnouncementMeta }>(
"~/components/Domain/Announcement/Announcements/*.vue",
{ eager: true },
);
const allAnnouncements: Announcement[] = Object.entries(_announcementsUnsorted)
.sort(([a], [b]) => a.localeCompare(b))
.map(([path, mod]) => ({
key: path.split("/").at(-1)!.replace(".vue", ""),
component: mod.default,
meta: mod.meta,
}));
export function useAnnouncements() {
const auth = useMealieAuth();
const { household } = useHouseholdSelf();
@@ -15,10 +37,18 @@ export function useAnnouncements() {
),
);
const newAnnouncements = ref<string[] | undefined>();
const newAnnouncements = shallowRef<Announcement[]>([]);
function refreshUnreadAnnouncements() {
if (!auth.user.value) {
newAnnouncements.value = undefined;
// Only logged-in users can see announcements
if (!auth.user.value || !allAnnouncements.length) {
newAnnouncements.value = [];
return;
}
// If a user has never seen an announcement, show them only the welcome announcement
if (!auth.user.value.lastReadAnnouncement) {
newAnnouncements.value = [allAnnouncements.at(0)!];
return;
}
newAnnouncements.value = []; // TODO
@@ -32,5 +62,6 @@ export function useAnnouncements() {
return {
announcementsEnabled,
newAnnouncements,
allAnnouncements,
};
}