118 lines
2.6 KiB
Vue
118 lines
2.6 KiB
Vue
<script setup>
|
|
const props = defineProps({
|
|
dateValue: {
|
|
type: [String, Date],
|
|
required: true,
|
|
},
|
|
format: {
|
|
type: String,
|
|
default: "HH:mm:ss",
|
|
},
|
|
});
|
|
|
|
const store = useStore();
|
|
const { $dayjs } = useNuxtApp();
|
|
|
|
const timeRemaining = ref({
|
|
days: 0,
|
|
hours: 0,
|
|
minutes: 0,
|
|
seconds: 0,
|
|
});
|
|
|
|
const isExpired = ref(false);
|
|
let intervalId = null;
|
|
|
|
const isVietnamese = computed(() => store.lang === "vi");
|
|
|
|
const tagClass = computed(() => {
|
|
if (isExpired) return "is-danger";
|
|
|
|
const totalSeconds =
|
|
timeRemaining.value.days * 86400 +
|
|
timeRemaining.value.hours * 3600 +
|
|
timeRemaining.value.minutes * 60 +
|
|
timeRemaining.value.seconds;
|
|
|
|
if (totalSeconds <= 0) return "is-danger";
|
|
if (totalSeconds <= 3600) return "is-warning"; // <= 1 hour
|
|
if (totalSeconds <= 86400) return "is-info"; // <= 1 day
|
|
return "is-primary"; // > 1 day
|
|
});
|
|
|
|
const formattedTime = computed(() => {
|
|
const { days, hours, minutes, seconds } = timeRemaining.value;
|
|
|
|
if (days > 0) {
|
|
return isVietnamese ? `${days}d ${hours}h ${minutes}m` : `${days}d ${hours}h ${minutes}m`;
|
|
}
|
|
|
|
if (hours > 0) {
|
|
return isVietnamese ? `${hours}h ${minutes}m ${seconds}s` : `${hours}h ${minutes}m ${seconds}s`;
|
|
}
|
|
|
|
return isVietnamese ? `${minutes}m ${seconds}s` : `${minutes}m ${seconds}s`;
|
|
});
|
|
|
|
const calculateTimeRemaining = () => {
|
|
try {
|
|
const targetDate = $dayjs(props.dateValue);
|
|
const now = $dayjs();
|
|
|
|
if (now.isAfter(targetDate)) {
|
|
isExpired.value = true;
|
|
timeRemaining.value = { days: 0, hours: 0, minutes: 0, seconds: 0 };
|
|
return;
|
|
}
|
|
|
|
isExpired.value = false;
|
|
const diff = targetDate.diff(now, "second");
|
|
|
|
const days = Math.floor(diff / 86400);
|
|
const hours = Math.floor((diff % 86400) / 3600);
|
|
const minutes = Math.floor((diff % 3600) / 60);
|
|
const seconds = diff % 60;
|
|
|
|
timeRemaining.value = { days, hours, minutes, seconds };
|
|
} catch (error) {
|
|
console.error("Error calculating countdown:", error);
|
|
isExpired.value = true;
|
|
}
|
|
};
|
|
|
|
const startCountdown = () => {
|
|
calculateTimeRemaining();
|
|
|
|
if (intervalId) clearInterval(intervalId);
|
|
|
|
intervalId = setInterval(() => {
|
|
calculateTimeRemaining();
|
|
|
|
if (isExpired.value && intervalId) {
|
|
clearInterval(intervalId);
|
|
intervalId = null;
|
|
}
|
|
}, 1000);
|
|
};
|
|
|
|
watch(
|
|
() => props.dateValue,
|
|
() => {
|
|
startCountdown();
|
|
},
|
|
{ deep: true },
|
|
);
|
|
|
|
onMounted(startCountdown);
|
|
|
|
onBeforeUnmount(() => {
|
|
clearInterval(intervalId);
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<span :class="['tag', tagClass]">
|
|
{{ isExpired ? (isVietnamese ? "Hết giờ" : "Expired") : formattedTime }}
|
|
</span>
|
|
</template>
|