139 lines
5.0 KiB
Vue
139 lines
5.0 KiB
Vue
<script setup>
|
|
import { ref, watch, computed } from 'vue';
|
|
import { usePage } from '@inertiajs/vue3';
|
|
import { toastMessage } from '@/Composables/useToast';
|
|
|
|
const show = ref(false);
|
|
const message = ref('');
|
|
const type = ref('success');
|
|
const page = usePage();
|
|
|
|
const props = defineProps({
|
|
duration: {
|
|
type: Number,
|
|
default: 4,
|
|
},
|
|
});
|
|
|
|
const closeToast = () => {
|
|
show.value = false;
|
|
};
|
|
|
|
watch(() => page.props.flash, (flash) => {
|
|
if (flash.success || flash.error || flash.warning || flash.info) {
|
|
show.value = true;
|
|
message.value = flash.success || flash.error || flash.warning || flash.info;
|
|
type.value = flash.success
|
|
? 'success'
|
|
: flash.error
|
|
? 'danger'
|
|
: flash.warning
|
|
? 'warning'
|
|
: 'info';
|
|
|
|
setTimeout(() => {
|
|
show.value = false;
|
|
}, props.duration * 1000);
|
|
}
|
|
}, { immediate: true });
|
|
|
|
// Watch for global toast messages
|
|
watch(toastMessage, (val) => {
|
|
if (val) {
|
|
message.value = val.message;
|
|
type.value = val.type;
|
|
show.value = true;
|
|
|
|
setTimeout(() => {
|
|
show.value = false;
|
|
toastMessage.value = null;
|
|
}, props.duration * 1000);
|
|
}
|
|
});
|
|
|
|
const toastClasses = computed(() => {
|
|
console.log('Toast type is:', type.value);
|
|
switch (type.value) {
|
|
case 'success':
|
|
return 'text-green-500 bg-green-100 dark:bg-green-800 dark:text-green-200';
|
|
case 'danger':
|
|
return 'text-red-500 bg-red-100 dark:bg-red-800 dark:text-red-200';
|
|
case 'warning':
|
|
return 'text-orange-500 bg-orange-100 dark:bg-orange-700 dark:text-orange-200';
|
|
case 'info':
|
|
return 'text-blue-500 bg-blue-100 dark:bg-blue-800 dark:text-blue-200';
|
|
default:
|
|
return 'text-gray-800 bg-white dark:bg-gray-800 dark:text-gray-200';
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<transition name="fade">
|
|
<div
|
|
v-if="show"
|
|
class="fixed top-5 right-5 z-50 w-full max-w-xs flex items-center p-4 rounded-lg shadow-sm"
|
|
:class="toastClasses"
|
|
role="alert"
|
|
>
|
|
<div class="inline-flex items-center justify-center shrink-0 w-8 h-8 rounded-lg">
|
|
<svg
|
|
v-if="type === 'success'"
|
|
class="w-5 h-5"
|
|
fill="currentColor"
|
|
viewBox="0 0 20 20"
|
|
>
|
|
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z"/>
|
|
</svg>
|
|
<svg
|
|
v-else-if="type === 'danger'"
|
|
class="w-5 h-5"
|
|
fill="currentColor"
|
|
viewBox="0 0 20 20"
|
|
>
|
|
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 11.793a1 1 0 1 1-1.414 1.414L10 11.414l-2.293 2.293a1 1 0 0 1-1.414-1.414L8.586 10 6.293 7.707a1 1 0 0 1 1.414-1.414L10 8.586l2.293-2.293a1 1 0 0 1 1.414 1.414L11.414 10l2.293 2.293Z"/>
|
|
</svg>
|
|
<svg
|
|
v-else-if="type === 'warning'"
|
|
class="w-5 h-5"
|
|
fill="currentColor"
|
|
viewBox="0 0 20 20"
|
|
>
|
|
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM10 15a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-4a1 1 0 0 1-2 0V6a1 1 0 0 1 2 0v5Z"/>
|
|
</svg>
|
|
<svg
|
|
v-else
|
|
class="w-5 h-5"
|
|
fill="currentColor"
|
|
viewBox="0 0 20 20"
|
|
>
|
|
<path d="M10 2a8 8 0 100 16 8 8 0 000-16zm1 11H9v-2h2v2zm0-4H9V5h2v4z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="ms-3 text-sm font-normal">
|
|
{{ message }}
|
|
</div>
|
|
<button
|
|
type="button"
|
|
@click="closeToast"
|
|
class="ms-auto -mx-1.5 -my-1.5 text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex items-center justify-center h-8 w-8 dark:hover:text-white dark:hover:bg-gray-700"
|
|
>
|
|
<svg class="w-3 h-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
|
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1l6 6m0 0l6 6M7 7L1 13m6-6l6-6"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</transition>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.fade-enter-active,
|
|
.fade-leave-active {
|
|
transition: opacity 0.4s ease;
|
|
}
|
|
.fade-enter-from,
|
|
.fade-leave-to {
|
|
opacity: 0;
|
|
}
|
|
</style>
|