46 lines
1.3 KiB
Vue
46 lines
1.3 KiB
Vue
<script setup lang="ts">
|
|
import type { Alert } from "@/types";
|
|
import { computed, ref, onBeforeMount } from "vue";
|
|
import { CircleXIcon, CircleAlertIcon, CircleCheckIcon, InfoIcon } from "@lucide/vue";
|
|
|
|
const props = defineProps<{ alert: Alert }>();
|
|
const dismissed = ref<boolean>(false);
|
|
const refreshKey = ref<number>(1);
|
|
const visible = computed<boolean>(
|
|
() =>
|
|
refreshKey.value > 0 &&
|
|
!dismissed.value &&
|
|
new Date().getTime() - props.alert.created.getTime() <=
|
|
props.alert.seconds * 1000,
|
|
);
|
|
|
|
function onDismiss() {
|
|
dismissed.value = true;
|
|
}
|
|
|
|
onBeforeMount(() => {
|
|
setInterval(() => {
|
|
refreshKey.value++;
|
|
}, 500);
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
v-if="visible"
|
|
class="alert alert-soft cursor-pointer"
|
|
:class="`alert-${alert.type}`"
|
|
@click="onDismiss"
|
|
>
|
|
<circle-x-icon v-if="alert.type === 'error'" class="inline" />
|
|
<!-- alert-error -->
|
|
<circle-alert-icon v-if="alert.type === 'warning'" class="inline" />
|
|
<!-- alert-warning -->
|
|
<circle-check-icon v-if="alert.type === 'success'" class="inline" />
|
|
<!-- alert-success -->
|
|
<info-icon v-if="alert.type === 'info'" class="inline" />
|
|
<!-- alert-info -->
|
|
<span>{{ alert.message }}</span>
|
|
</div>
|
|
</template>
|