290 lines
7.6 KiB
Vue
290 lines
7.6 KiB
Vue
<template>
|
|
<div
|
|
class="px-2"
|
|
style="width: 300px"
|
|
>
|
|
<div class="is-flex is-gap-1 is-justify-content-space-between is-align-items-stretch h-8">
|
|
<div class="buttons is-gap-0.5 m-0 is-align-items-stretch">
|
|
<button
|
|
@click="previousYear"
|
|
class="button is-text rounded-full"
|
|
>
|
|
<span class="icon">
|
|
<Icon
|
|
name="ic:baseline-keyboard-double-arrow-left"
|
|
:size="24"
|
|
/>
|
|
</span>
|
|
</button>
|
|
<button
|
|
v-if="type === 'days'"
|
|
@click="previousMonth"
|
|
class="button is-text rounded-full"
|
|
>
|
|
<span class="icon">
|
|
<Icon
|
|
name="ic:baseline-keyboard-arrow-left"
|
|
:size="24"
|
|
/>
|
|
</span>
|
|
</button>
|
|
</div>
|
|
<div class="is-flex is-align-items-center is-gap-0">
|
|
<button
|
|
v-if="type === 'days'"
|
|
@click="type = 'months'"
|
|
class="button is-white p-2 has-text-primary font-bold h-full"
|
|
>
|
|
T{{ month }}
|
|
</button>
|
|
<button
|
|
@click="type = 'years'"
|
|
class="button is-white p-2 has-text-primary font-bold h-full"
|
|
>
|
|
{{ caption || year }}
|
|
</button>
|
|
</div>
|
|
<div class="buttons is-gap-0.5 m-0 is-align-items-stretch">
|
|
<button
|
|
class="button is-text rounded-full"
|
|
@click="nextMonth"
|
|
v-if="type === 'days'"
|
|
>
|
|
<span class="icon">
|
|
<Icon
|
|
name="ic:baseline-keyboard-arrow-right"
|
|
:size="24"
|
|
/>
|
|
</span>
|
|
</button>
|
|
<button
|
|
@click="nextYear"
|
|
class="button is-text rounded-full"
|
|
>
|
|
<span class="icon">
|
|
<Icon
|
|
name="ic:baseline-keyboard-double-arrow-right"
|
|
:size="24"
|
|
/>
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<hr class="mt-1 mb-5" />
|
|
<div v-if="type === 'days'">
|
|
<div class="columns is-mobile mx-0 mb-3">
|
|
<div
|
|
v-for="(m, h) in dateOfWeek"
|
|
:key="h"
|
|
class="fs-14 column p-0 has-text-grey is-flex is-justify-content-center is-align-items-center"
|
|
>
|
|
{{ m.text }}
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-for="(v, i) in weeks"
|
|
:key="i"
|
|
:class="`columns is-mobile mx-0 mb-1 ${i === weeks.length - 1 ? 'mb-1' : ''}`"
|
|
>
|
|
<div
|
|
v-for="(m, h) in v.dates"
|
|
:key="h"
|
|
class="column p-0 is-flex is-justify-content-center is-align-items-center"
|
|
style="width: 40px; height: 32px"
|
|
>
|
|
<span
|
|
v-if="m.disable"
|
|
class="fs-13 has-text-grey-lighter"
|
|
>
|
|
{{ m.dayPrint }}
|
|
</span>
|
|
<span
|
|
v-else
|
|
class="fs-13 is-clickable"
|
|
@click="choose(m)"
|
|
>
|
|
<span
|
|
style="width: 25px; height: 25px"
|
|
:class="[
|
|
'p-1 rounded-full is-flex is-justify-content-center is-align-items-center',
|
|
{
|
|
'has-background-primary has-text-white': m.date === curdate,
|
|
'has-background-success-50 has-text-white': m.date === today,
|
|
'has-text-grey-light': m.currentMonth !== m.monthCondition,
|
|
},
|
|
]"
|
|
>
|
|
{{ m.dayPrint }}
|
|
</span>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<hr class="my-1" />
|
|
<div class="mt-2 fs-14">
|
|
<span class="ml-2">Hôm nay: </span>
|
|
<a @click="chooseToday">{{ $dayjs(today).format("L") }}</a>
|
|
</div>
|
|
</div>
|
|
<PickMonth
|
|
v-else-if="type === 'months'"
|
|
@month="selectMonth"
|
|
/>
|
|
<PickYear
|
|
v-else-if="type === 'years'"
|
|
v-bind="{ year, month, action }"
|
|
@year="selectYear"
|
|
@caption="changeCaption"
|
|
/>
|
|
</div>
|
|
</template>
|
|
<script setup>
|
|
import PickMonth from "@/components/datepicker/PickMonth";
|
|
import PickYear from "@/components/datepicker/PickYear";
|
|
|
|
const { $id, $dayjs, $unique } = useNuxtApp();
|
|
const emit = defineEmits(["date"]);
|
|
const props = defineProps({
|
|
date: String,
|
|
maxdate: [Date, String],
|
|
});
|
|
const dates = ref([]);
|
|
const dateOfWeek = [
|
|
{ id: 0, text: "CN" },
|
|
{ id: 1, text: "T2" },
|
|
{ id: 2, text: "T3" },
|
|
{ id: 3, text: "T4" },
|
|
{ id: 4, text: "T5" },
|
|
{ id: 5, text: "T6" },
|
|
{ id: 6, text: "T7" },
|
|
];
|
|
const weeks = ref([]);
|
|
const year = ref();
|
|
let month;
|
|
const type = ref("days");
|
|
const caption = ref();
|
|
const action = ref();
|
|
const curdate = ref();
|
|
const today = new Date();
|
|
|
|
function showDate() {
|
|
curdate.value = props.date ? props.date.replaceAll("-", "/") : undefined;
|
|
year.value = $dayjs(curdate.value || today).year();
|
|
month = $dayjs(curdate.value || today).month() + 1;
|
|
getDates();
|
|
}
|
|
function chooseToday() {
|
|
emit("date", $dayjs(today).format("YYYY-MM-DD")); //today.replaceAll('/', '-'))
|
|
year.value = $dayjs(today).year();
|
|
month = $dayjs(today).month() + 1;
|
|
getDates();
|
|
}
|
|
function changeCaption(v) {
|
|
caption.value = v;
|
|
}
|
|
function selectMonth(v) {
|
|
month = v;
|
|
getDates();
|
|
type.value = "days";
|
|
}
|
|
function selectYear(v) {
|
|
year.value = v;
|
|
getDates();
|
|
type.value = "days";
|
|
}
|
|
function getDates() {
|
|
caption.value = undefined;
|
|
dates.value = allDaysInMonth(year.value, month);
|
|
weeks.value = $unique(dates.value, ["week"]).map((v) => {
|
|
return { week: v.week };
|
|
});
|
|
weeks.value.map((v) => {
|
|
v.dates = dates.value.filter((x) => x.week === v.week);
|
|
});
|
|
}
|
|
function nextMonth() {
|
|
month = month + 1;
|
|
if (month > 12) {
|
|
month = 1;
|
|
year.value += 1;
|
|
}
|
|
getDates();
|
|
}
|
|
function previousMonth() {
|
|
month = month - 1;
|
|
if (month === 0) {
|
|
month = 12;
|
|
year.value -= 1;
|
|
}
|
|
getDates();
|
|
}
|
|
function nextYear() {
|
|
if (type.value === "years") return (action.value = { name: "next", id: $id() });
|
|
year.value += 1;
|
|
getDates();
|
|
}
|
|
function previousYear() {
|
|
if (type.value === "years") return (action.value = { name: "previous", id: $id() });
|
|
year.value -= 1;
|
|
getDates();
|
|
}
|
|
function choose(m) {
|
|
emit("date", m.date.replaceAll("/", "-"));
|
|
}
|
|
function createDate(v, x, y) {
|
|
return v + "/" + (x < 10 ? "0" + x.toString() : x.toString()) + "/" + (y < 10 ? "0" + y.toString() : y.toString());
|
|
}
|
|
function allDaysInMonth(year, month) {
|
|
let days = Array.from({ length: $dayjs(createDate(year, month, 1)).daysInMonth() }, (_, i) => i + 1);
|
|
let arr = [];
|
|
days.map((v) => {
|
|
for (let i = 0; i < 7; i++) {
|
|
let thedate = $dayjs(createDate(year, month, v)).weekday(i);
|
|
let date = $dayjs(new Date(thedate.$d)).format("YYYY/MM/DD");
|
|
let dayPrint = $dayjs(new Date(thedate.$d)).format("DD");
|
|
let monthCondition = $dayjs(date).month() + 1;
|
|
let currentMonth = month;
|
|
let found = arr.find((x) => x.date === date);
|
|
if (!found) {
|
|
let dayOfWeek = $dayjs(date).day();
|
|
let week = $dayjs(date).week();
|
|
let disable = false;
|
|
if (props.maxdate ? $dayjs(props.maxdate).diff(props.date, "day") >= 0 : false) {
|
|
if ($dayjs(props.maxdate).startOf("day").diff(date, "day") < 0) disable = true;
|
|
}
|
|
let ele = {
|
|
date: date,
|
|
week: week,
|
|
day: v,
|
|
dayOfWeek: dayOfWeek,
|
|
dayPrint: dayPrint,
|
|
monthCondition: monthCondition,
|
|
currentMonth: currentMonth,
|
|
disable: disable,
|
|
};
|
|
arr.push(ele);
|
|
}
|
|
}
|
|
});
|
|
return arr;
|
|
}
|
|
// display
|
|
showDate();
|
|
// change date
|
|
watch(
|
|
() => props.date,
|
|
() => {
|
|
showDate();
|
|
},
|
|
);
|
|
</script>
|
|
<style scoped>
|
|
a {
|
|
color: var(--bulma-link-60);
|
|
}
|
|
.control.has-icons-left .icon,
|
|
.control.has-icons-right .icon {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
</style>
|