Files
web/app/components/datepicker/PickDay.vue
2026-05-05 11:06:49 +07:00

261 lines
6.9 KiB
Vue

<template>
<div
class="p-2"
style="width: 300px"
>
<div class="field is-grouped">
<div class="control pl-2">
<a
class="mr-1"
@click="previousYear()"
>
<SvgIcon v-bind="{ name: 'doubleleft.svg', type: 'gray', size: 18 }"></SvgIcon>
</a>
<a
@click="previousMonth()"
v-if="type === 'days'"
>
<SvgIcon v-bind="{ name: 'left1.svg', type: 'gray', size: 18 }"></SvgIcon>
</a>
</div>
<div class="control is-expanded has-text-centered">
<a
class="font-bold mr-2"
@click="type = 'months'"
v-if="type === 'days'"
>{{ `T${month}` }}</a
>
<a
class="font-bold"
@click="type = 'years'"
>{{ caption || year }}</a
>
</div>
<div class="control pr-2">
<a
class="mr-1"
@click="nextMonth()"
v-if="type === 'days'"
>
<SvgIcon v-bind="{ name: 'right.svg', type: 'gray', size: 18 }"></SvgIcon>
</a>
<a @click="nextYear()">
<SvgIcon v-bind="{ name: 'doubleright.svg', type: 'gray', size: 18 }"></SvgIcon>
</a>
</div>
</div>
<hr class="mt-0 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
:class="`columns is-mobile mx-0 mb-1 ${i === weeks.length - 1 ? 'mb-1' : ''}`"
v-for="(v, i) in weeks"
:key="i"
>
<div
class="column p-0 is-flex is-justify-content-center is-align-items-center"
style="width: 40px; height: 32px"
v-for="(m, h) in v.dates"
:key="h"
>
<span
class="fs-13 has-text-grey-80"
v-if="m.disable"
>
{{ m.dayPrint }}
</span>
<span
class="fs-13 is-clickable"
@click="choose(m)"
v-else
>
<span
style="width: 25px; height: 25px"
:class="[
'p-1 rounded-md is-flex is-justify-content-center is-align-items-center',
{
'has-background-primary-50 has-text-white': m.date === curdate,
'has-background-success-50 has-text-white': m.date === today,
'has-text-grey-70': 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
class="has-text-primary"
@click="chooseToday()"
>{{ $dayjs(today).format("DD/MM/YYYY") }}</a
>
</div>
</div>
<PickMonth
v-else-if="type === 'months'"
@month="selectMonth"
></PickMonth>
<PickYear
v-else-if="type === 'years'"
v-bind="{ year, month, action }"
@year="selectYear"
@caption="changeCaption"
></PickYear>
</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"]);
var props = defineProps({
date: String,
maxdate: String,
});
var dates = [];
var 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" },
];
var weeks = ref([]);
var year = ref(undefined);
var month = undefined;
var type = ref("days");
var caption = ref(undefined);
var action = ref(undefined);
var curdate = undefined;
var today = new Date();
function showDate() {
curdate = props.date ? props.date.replaceAll("-", "/") : undefined;
year.value = $dayjs(curdate || today).year();
month = $dayjs(curdate || 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 = allDaysInMonth(year.value, month);
weeks.value = $unique(dates, ["week"]).map((v) => {
return { week: v.week };
});
weeks.value.map((v) => {
v.dates = dates.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,
(newVal, oldVal) => {
showDate();
},
);
</script>
<style scoped>
a {
color: var(--bulma-link-60);
}
</style>