Teren-app/resources/js/Components/Toast/ToastContainer.vue
2025-11-02 21:46:02 +01:00

182 lines
4.9 KiB
Vue

<script setup>
import { watch, onMounted, onUnmounted, h } from 'vue';
import { usePage } from '@inertiajs/vue3';
import { Toaster } from '@/Components/ui/sonner';
import { toast } from 'vue-sonner';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { library } from '@fortawesome/fontawesome-svg-core';
import {
faCircleCheck,
faPen,
faPencil,
faTrash
} from '@fortawesome/free-solid-svg-icons';
library.add(faCircleCheck, faPen, faPencil, faTrash);
const page = usePage();
// Helper function to get toast config based on HTTP method
const getToastConfig = (method, message) => {
const methodUpper = method?.toUpperCase() || '';
switch (methodUpper) {
case 'POST':
return {
type: 'success',
message: message,
icon: () => h(FontAwesomeIcon, { icon: faCircleCheck, class: 'text-green-600' }),
description: 'Ustvarjeno',
className: 'border-green-500 bg-green-50',
};
case 'PUT':
return {
type: 'info',
message: message,
icon: () => h(FontAwesomeIcon, { icon: faPen, class: 'text-blue-600' }),
description: 'Posodobljeno',
className: 'border-blue-500 bg-blue-50',
};
case 'PATCH':
return {
type: 'info',
message: message,
icon: () => h(FontAwesomeIcon, { icon: faPencil, class: 'text-indigo-600' }),
description: 'Spremenjeno',
className: 'border-indigo-500 bg-indigo-50',
};
case 'DELETE':
return {
type: 'error',
message: message,
icon: () => h(FontAwesomeIcon, { icon: faTrash, class: 'text-red-600' }),
description: 'Izbrisano',
className: 'border-red-500 bg-red-50',
};
default:
return null;
}
};
// Watch for flash messages from Inertia
watch(
() => page.props.flash,
(flash) => {
if (!flash) return;
const flashTypes = ['success', 'error', 'warning', 'info'];
const method = flash.method?.toUpperCase();
for (const type of flashTypes) {
if (flash[type]) {
const message = flash[type];
// If method is provided, use custom styling
if (method) {
const config = getToastConfig(method, message);
if (config) {
// Use toast.custom or the appropriate type with options
switch (config.type) {
case 'success':
toast.success(message, {
description: config.description,
icon: config.icon,
class: config.className,
});
break;
case 'error':
toast.error(message, {
description: config.description,
icon: config.icon,
class: config.className,
});
break;
case 'info':
toast.info(message, {
description: config.description,
icon: config.icon,
class: config.className,
});
break;
case 'warning':
toast.warning(message, {
description: config.description,
icon: config.icon,
class: config.className,
});
break;
}
} else {
// Fallback to default behavior
switch (type) {
case 'success':
toast.success(message);
break;
case 'error':
toast.error(message);
break;
case 'warning':
toast.warning(message);
break;
case 'info':
toast.info(message);
break;
}
}
} else {
// Default behavior when no method is specified
switch (type) {
case 'success':
toast.success(message);
break;
case 'error':
toast.error(message);
break;
case 'warning':
toast.warning(message);
break;
case 'info':
toast.info(message);
break;
}
}
}
}
},
{ deep: true, immediate: true }
);
// Expose toast methods globally for backward compatibility
onMounted(() => {
window.$toast = {
success: (message, options = {}) => {
toast.success(message, options);
},
error: (message, options = {}) => {
toast.error(message, options);
},
warning: (message, options = {}) => {
toast.warning(message, options);
},
info: (message, options = {}) => {
toast.info(message, options);
},
remove: (id) => {
if (id) {
toast.dismiss(id);
}
},
};
});
onUnmounted(() => {
if (window.$toast) {
delete window.$toast;
}
});
</script>
<template>
<Toaster class="pointer-events-auto" position="bottom-right" />
</template>