diff --git a/src/components/ToastRenderer.vue b/src/components/ToastRenderer.vue new file mode 100644 index 0000000..65e9587 --- /dev/null +++ b/src/components/ToastRenderer.vue @@ -0,0 +1,106 @@ + + + + + + + diff --git a/src/layouts/default.vue b/src/layouts/default.vue index be7b6e7..5b751a0 100644 --- a/src/layouts/default.vue +++ b/src/layouts/default.vue @@ -11,6 +11,7 @@ useHead({ id="root" class="main-body" > +
diff --git a/src/pages/account/login.vue b/src/pages/account/login.vue index 3dbc949..fada313 100644 --- a/src/pages/account/login.vue +++ b/src/pages/account/login.vue @@ -2,6 +2,7 @@ const route = useRoute(); const auth = useAuthStore(); const authUtils = useAuthUtils(); +const toasts = useToasts(); const redirect = computed(() => route.query.redirect?.toString() ?? null); const registerURI = computed(() => { if (redirect.value) { @@ -14,7 +15,6 @@ const registerURI = computed(() => { }); const loginForm = reactive({ username: '', password: '' }); -const errorMessage = ref(); async function loginSubmission() { try { @@ -32,11 +32,10 @@ async function loginSubmission() { await authUtils.safelyRedirectAfterLogin(redirect.value); } catch (error: unknown) { const err = getApiError(error); - errorMessage.value = err.code; - - setTimeout(() => { // TODO: replace this toast - errorMessage.value = null; - }, 5000); + toasts.publish({ + type: 'error', + text: err.message + }); } } @@ -85,14 +84,6 @@ async function loginSubmission() {
- diff --git a/src/pages/account/register.vue b/src/pages/account/register.vue index 752a4d2..284345a 100644 --- a/src/pages/account/register.vue +++ b/src/pages/account/register.vue @@ -4,6 +4,7 @@ import type { ApiAuthRegisterRequest } from '~~/shared/api-types'; const route = useRoute(); const auth = useAuthStore(); const authUtils = useAuthUtils(); +const toasts = useToasts(); const redirect = computed(() => route.query.redirect?.toString() ?? null); const loginURI = computed(() => { if (redirect.value) { @@ -16,8 +17,6 @@ const loginURI = computed(() => { }); const registerForm = reactive({ email: '', username: '', mii_name: '', password: '', password_confirm: '' }); - -const errorMessage = ref(); const captchaRef = useTemplateRef('captcha'); async function registerSubmission() { @@ -47,10 +46,10 @@ async function registerSubmission() { await authUtils.safelyRedirectAfterLogin(redirect.value); } catch (error: unknown) { const err = getApiError(error); - errorMessage.value = err.code; - setTimeout(() => { // TODO: replace this toast - errorMessage.value = null; - }, 5000); + toasts.publish({ + type: 'error', + text: err.message + }); } } @@ -137,14 +136,6 @@ async function registerSubmission() { - diff --git a/src/stores/toasts.ts b/src/stores/toasts.ts new file mode 100644 index 0000000..d908ca8 --- /dev/null +++ b/src/stores/toasts.ts @@ -0,0 +1,30 @@ +export type ToastContent = { + type: 'success' | 'error'; + text: string; +}; + +export type ToastItem = { + id: number; + content: ToastContent; +}; + +export const useToasts = defineStore('toasts', () => { + let idCounter = 0; + const toasts = ref([]); + const readonlyToasts = computed(() => toasts.value); + + return { + getAll() { + return readonlyToasts.value; + }, + remove(id: number) { + toasts.value = toasts.value.filter(v => v.id !== id); + }, + publish(item: ToastContent) { + toasts.value.push({ + id: idCounter++, + content: item + }); + } + }; +});