diff --git a/src/App.vue b/src/App.vue index f1ca377..839413a 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,38 +1,18 @@ - - diff --git a/src/components/ToastNotification.vue b/src/components/ToastNotification.vue new file mode 100644 index 0000000..d856fdd --- /dev/null +++ b/src/components/ToastNotification.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/stores/toast.ts b/src/stores/toast.ts new file mode 100644 index 0000000..3ae11ab --- /dev/null +++ b/src/stores/toast.ts @@ -0,0 +1,43 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' + +export interface Toast { + id: number + message: string + type: 'success' | 'error' | 'info' + exiting?: boolean +} + +export const useToastStore = defineStore('toast', () => { + const toasts = ref([]) + let nextId = 0 + + function addToast(message: string, type: Toast['type'] = 'info') { + const id = nextId++ + toasts.value.push({ id, message, type }) + + // Max 3 visible + if (toasts.value.length > 3) { + toasts.value.shift() + } + + // Auto-dismiss after 3s + setTimeout(() => removeToast(id), 3000) + } + + function removeToast(id: number) { + const toast = toasts.value.find(t => t.id === id) + if (toast) { + toast.exiting = true + setTimeout(() => { + toasts.value = toasts.value.filter(t => t.id !== id) + }, 150) + } + } + + function success(message: string) { addToast(message, 'success') } + function error(message: string) { addToast(message, 'error') } + function info(message: string) { addToast(message, 'info') } + + return { toasts, addToast, removeToast, success, error, info } +})