|
1 | 1 | <script lang="ts" setup> |
2 | | -import {FontAwesomeIcon} from "@fortawesome/vue-fontawesome"; |
3 | | -import {computed, onBeforeUnmount, onMounted, ref} from 'vue'; |
| 2 | +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; |
| 3 | +import { computed, onBeforeUnmount, onMounted, ref } from 'vue'; |
4 | 4 |
|
5 | 5 | const props = defineProps({ |
6 | | - type: { |
7 | | - type: String, |
8 | | - default: "success", |
9 | | - validator: (value) => ["success", "error", "exception"].includes(value as string), |
10 | | - }, |
11 | | - message: { |
12 | | - type: String, |
13 | | - default: "Chat request has been sent", |
14 | | - }, |
15 | | - duration: { |
16 | | - type: Number, |
17 | | - default: 3000, |
18 | | - }, |
19 | | - buttonText: { |
20 | | - type: String, |
21 | | - default: "close", |
22 | | - } |
| 6 | + type: { |
| 7 | + type: String, |
| 8 | + default: "success", |
| 9 | + validator: (value) => [ "success", "error", "exception" ].includes(value as string), |
| 10 | + }, |
| 11 | + message: { |
| 12 | + type: String, |
| 13 | + default: "Chat request has been sent", |
| 14 | + }, |
| 15 | + duration: { |
| 16 | + type: Number, |
| 17 | + default: 3000, |
| 18 | + }, |
| 19 | + buttonText: { |
| 20 | + type: String, |
| 21 | + default: "close", |
| 22 | + } |
23 | 23 | }); |
24 | 24 |
|
25 | | -const emit = defineEmits(['buttonClick', 'close']); |
| 25 | +const emit = defineEmits([ 'buttonClick', 'close' ]); |
26 | 26 |
|
27 | 27 | // Internal visibility state |
28 | 28 | const visible = ref(true); |
29 | 29 |
|
30 | 30 | // Helper function to get the correct alert class based on type - now as computed property |
31 | 31 | const alertClass = computed(() => ({ |
32 | | - 'alert-success': props.type === 'success' || props.type === undefined, |
33 | | - 'alert-error': props.type === 'error' || props.type === 'exception', |
| 32 | + 'alert-success': props.type === 'success' || props.type === undefined, |
| 33 | + 'alert-error': props.type === 'error' || props.type === 'exception', |
34 | 34 | })); |
35 | 35 |
|
36 | 36 |
|
37 | 37 | // Get the actual icon name as a string |
38 | 38 | const iconName = computed(() => { |
39 | | - if (props.type === 'error') return 'ban'; |
40 | | - if (props.type === 'exception') return 'triangle-exclamation'; |
41 | | - return 'check'; // default for success |
| 39 | + if (props.type === 'error') return 'ban'; |
| 40 | + if (props.type === 'exception') return 'triangle-exclamation'; |
| 41 | + return 'check'; // default for success |
42 | 42 | }); |
43 | 43 |
|
44 | 44 | // Auto-close toast after duration by changing internal visibility |
45 | 45 | let timeoutId: ReturnType<typeof setTimeout> | null = null; |
46 | 46 | onMounted(() => { |
47 | | - if (props.duration > 0) { |
48 | | - timeoutId = setTimeout(() => { |
49 | | - emit('close'); |
50 | | - visible.value = false; |
51 | | - }, props.duration); |
52 | | - } |
| 47 | + if (props.duration > 0) { |
| 48 | + timeoutId = setTimeout(() => { |
| 49 | + emit('close'); |
| 50 | + visible.value = false; |
| 51 | + }, props.duration); |
| 52 | + } |
53 | 53 | }); |
54 | 54 |
|
55 | 55 | onBeforeUnmount(() => { |
56 | | - if (timeoutId !== null) { |
57 | | - clearTimeout(timeoutId); |
58 | | - } |
| 56 | + if (timeoutId !== null) { |
| 57 | + clearTimeout(timeoutId); |
| 58 | + } |
59 | 59 | }); |
60 | 60 | // Just emit the event, don't change visibility |
61 | 61 | const handleButtonClick = () => { |
62 | | - emit('buttonClick'); |
| 62 | + emit('buttonClick'); |
63 | 63 | }; |
64 | 64 | </script> |
65 | 65 |
|
66 | 66 | <template> |
| 67 | + <div |
| 68 | + v-if="visible" |
| 69 | + class="fixed bottom-18 left-0 right-0 flex justify-center z-50 px-8" |
| 70 | + > |
67 | 71 | <div |
68 | | - v-if="visible" |
69 | | - class="fixed bottom-18 left-0 right-0 flex justify-center z-50 px-12" |
70 | | - > |
71 | | - <div |
72 | | - :class="alertClass" |
73 | | - class="alert w-full shadow-lg flex alert-soft" |
74 | | - role="alert"> |
75 | | - <FontAwesomeIcon :icon="iconName" class="text-xl"/> |
76 | | - <span class="w-full">{{ message }}</span> |
77 | | - <CustomButton |
78 | | - :text="buttonText" |
79 | | - :color="props.type === 'success' ? 'success' : 'error'" |
80 | | - variant="outline" |
81 | | - @click="handleButtonClick" |
82 | | - /> |
83 | | - </div> |
| 72 | + :class="alertClass" |
| 73 | + class="alert w-full !shadow-lg flex alert-soft" |
| 74 | + role="alert"> |
| 75 | + <FontAwesomeIcon :icon="iconName" class="text-xl"/> |
| 76 | + <span class="w-full">{{ message }}</span> |
| 77 | + <CustomButton |
| 78 | + :color="props.type === 'success' ? 'success' : 'error'" |
| 79 | + :text="buttonText" |
| 80 | + variant="outline" |
| 81 | + @click="handleButtonClick" |
| 82 | + /> |
84 | 83 | </div> |
| 84 | + </div> |
85 | 85 | </template> |
86 | 86 |
|
87 | 87 | <style scoped> |
|
0 commit comments