-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathApp.vue
93 lines (87 loc) · 2.76 KB
/
App.vue
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
<template>
<Head>
<meta :content="$t('head.meta.content')" :name="$t('head.meta.description')" />
<html :lang="$i18n.locale.substring(0, 2)" />
</Head>
<LoadingSpinner v-if="state.isLoading" class="m-auto size-16" />
<router-view v-else />
<Teleport to="body">
<Toaster
:position="width <= 600 ? 'top-center' : 'bottom-left'"
:toast-options="{
unstyled: true,
}"
:visible-toasts="5"></Toaster>
</Teleport>
</template>
<script lang="ts" setup>
import NotificationToast from './components/NotificationToast.vue';
import { useNotificationsStore } from './store/notifications';
import LoadingSpinner from '@/components/LoadingSpinner.vue';
import { useHead } from '@unhead/vue';
import { Head } from '@unhead/vue/components';
import { useWindowSize } from '@vueuse/core';
import { isNil } from 'lodash';
import { markRaw, reactive, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import { Toaster, toast } from 'vue-sonner';
const { width } = useWindowSize();
const i18n = useI18n();
const router = useRouter();
const notificationsStore = useNotificationsStore();
const state = reactive({
isLoading: true as boolean,
});
useHead({
titleTemplate: (title?: string) => [title, i18n.t('head.title')].filter(Boolean).join(' - '),
});
router.isReady().finally(() => {
state.isLoading = false;
});
router.onError((error) => {
if (
error.message.includes('Failed to fetch dynamically imported module') ||
error.message.includes('Importing a module script failed')
) {
notificationsStore.addNotification({
message: i18n.t('errors.onImport.message'),
description: i18n.t('errors.onImport.description'),
type: 'error',
actions: [
{
label: i18n.t('action.reload'),
onClick: () => window.location.reload(),
},
{
label: i18n.t('action.help'),
onClick: () =>
window.open(
`mailto:contact@coworking-metz.fr?body=${encodeURIComponent(error.message)}`,
),
},
],
});
}
});
watch(
() => notificationsStore.history.length,
(_historyLength) => {
const history = notificationsStore.history;
const allNotificationsNotDismissed = history.filter(({ dismissed }) => isNil(dismissed));
const allNotificationsNotDismissedSorted = allNotificationsNotDismissed.sort(
(first, second) => new Date(second.created).getTime() - new Date(first.created).getTime(),
);
const [notification] = allNotificationsNotDismissedSorted;
if (notification) {
toast.custom(markRaw(NotificationToast), {
duration: Infinity,
componentProps: {
notification,
},
});
}
},
{ immediate: true, deep: true },
);
</script>