75 lines
2.0 KiB
Vue
75 lines
2.0 KiB
Vue
<script setup>
|
||
import { defineProps, ref, watch } from "vue";
|
||
import { twMerge } from "tailwind-merge";
|
||
import { useI18n } from "vue-i18n";
|
||
const { t } = useI18n();
|
||
const props = defineProps({
|
||
content: String,
|
||
status: String,
|
||
open: Boolean,
|
||
cancel: Function,
|
||
confirm: Function,
|
||
to: {
|
||
default: "body",
|
||
type: String,
|
||
},
|
||
});
|
||
const isOpen = ref(false);
|
||
|
||
// TODO: 之後需要優化,改將Toast放在 App.js 裡面, 這樣可以簡單復用
|
||
watch(
|
||
() => props.open,
|
||
(newVal) => {
|
||
isOpen.value = newVal;
|
||
if (newVal && props.status !== "warning") {
|
||
setTimeout(() => {
|
||
props.cancel && props.cancel();
|
||
}, 3000);
|
||
}
|
||
}
|
||
);
|
||
</script>
|
||
|
||
<template>
|
||
<Teleport :to="to">
|
||
<template v-if="isOpen">
|
||
<div
|
||
role="alert"
|
||
:class="
|
||
twMerge(
|
||
`alert text-xl rounded-md fixed left-1/2 -translate-x-1/2 top-24 z-[1000] max-w-fit`,
|
||
status === 'info'
|
||
? 'alert-info'
|
||
: status === 'error'
|
||
? 'alert-error text-white'
|
||
: status === 'warning'
|
||
? 'alert-warning bg-yellow-400'
|
||
: 'alert-success'
|
||
)
|
||
"
|
||
>
|
||
<svg
|
||
xmlns="http://www.w3.org/2000/svg"
|
||
fill="none"
|
||
viewBox="0 0 24 24"
|
||
class="stroke-current shrink-0 w-6 h-6"
|
||
>
|
||
<path
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
stroke-width="2"
|
||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||
></path>
|
||
</svg>
|
||
<span>{{ content }}</span>
|
||
<div v-if="status === 'warning'">
|
||
<button @click="props.cancel && props.cancel();" className="btn btn-sm btn-outline me-2">{{$t("button.cancel")}}</button>
|
||
<button @click="props.confirm && props.confirm()" className="btn btn-sm">{{$t("button.confirm")}}</button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</Teleport>
|
||
</template>
|
||
|
||
<style lang="scss" scoped></style>
|