92 lines
2.2 KiB
Vue
92 lines
2.2 KiB
Vue
<script setup>
|
|
import { defineAsyncComponent } from "vue";
|
|
import { useStore } from "@/stores/index";
|
|
import Info from "@/components/snackbar/Info.vue";
|
|
import Success from "@/components/snackbar/Success.vue";
|
|
import Error from "@/components/snackbar/Error.vue";
|
|
const props = defineProps({
|
|
component: String,
|
|
vbind: Object,
|
|
});
|
|
|
|
const store = useStore();
|
|
const componentFiles = import.meta.glob("@/components/**/*.vue");
|
|
const resolvedComponent = shallowRef(null);
|
|
|
|
function loadDynamicComponent() {
|
|
if (!props.component) {
|
|
resolvedComponent.value = null;
|
|
return;
|
|
}
|
|
|
|
const fullPath = `/components/snackbar/${props.component}.vue`;
|
|
const componentPath = Object.keys(componentFiles).find((path) => path.endsWith(fullPath));
|
|
|
|
if (componentPath) {
|
|
resolvedComponent.value = defineAsyncComponent(componentFiles[componentPath]);
|
|
} else {
|
|
console.error(`Không tìm thấy component tại: ${fullPath}`);
|
|
resolvedComponent.value = null;
|
|
}
|
|
}
|
|
|
|
// Theo dõi sự thay đổi của props.component để load lại nếu cần
|
|
watchEffect(() => {
|
|
loadDynamicComponent();
|
|
});
|
|
// setTimeout(() => store.commit("snackbar", undefined), 3900);
|
|
</script>
|
|
|
|
<template>
|
|
<div class="snackbar is-flex is-align-items-center is-gap-3 pl-3 pr-1.5 py-2 rounded-md has-text-white">
|
|
<Info
|
|
v-if="component === 'Info'"
|
|
v-bind="vbind"
|
|
@close="$emit('close')"
|
|
/>
|
|
<Success
|
|
v-if="component === 'Success'"
|
|
v-bind="vbind"
|
|
@close="$emit('close')"
|
|
/>
|
|
<Error
|
|
v-if="component === 'Error'"
|
|
v-bind="vbind"
|
|
@close="$emit('close')"
|
|
/>
|
|
<button
|
|
@click="$emit('close')"
|
|
class="button is-ghost is-small"
|
|
>
|
|
<span class="icon">
|
|
<Icon
|
|
name="material-symbols:close-rounded"
|
|
:size="18"
|
|
/>
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.snackbar {
|
|
position: fixed;
|
|
z-index: 999;
|
|
top: 50px;
|
|
left: 0;
|
|
right: 0;
|
|
margin-inline: auto;
|
|
width: fit-content;
|
|
max-width: 500px;
|
|
background-color: hsl(from var(--bulma-grey-darker) h s l / 0.9);
|
|
}
|
|
|
|
.button.is-ghost {
|
|
color: white;
|
|
}
|
|
.button.is-ghost:hover,
|
|
.button.is-ghost.is-hovered {
|
|
color: hsl(from white h s l / 0.6);
|
|
}
|
|
</style>
|