Files
web/app/components/datepicker/PickDay.vue
2026-03-02 09:45:33 +07:00

181 lines
6.5 KiB
Vue

<template>
<div class="p-2" style="width: 300px">
<div class="field is-grouped mb-4 border-bottom">
<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="fsb-16 mr-2" @click="type='months'" v-if="type==='days'">{{`T${month}`}}</a>
<a class="fsb-16" @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>
<div v-if="type==='days'">
<div class="columns is-mobile mx-0 mb-3">
<div class="column p-0 has-text-grey-light-dark is-flex is-justify-content-center is-align-items-center" style="height: 32px;" v-for="(m,h) in dateOfWeek" :key="h">
{{ 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-14 has-text-grey-light" v-if="m.disable">
{{m.dayPrint}}
</span>
<a class="fs-14" @click="choose(m)" v-else>
<span
style="width: 25px; height: 25px; border-radius: 4px"
:class="[
'p-1 is-flex is-justify-content-center is-align-items-center',
{
'has-background-primary has-text-white': m.date === curdate,
'has-background-light has-text-white': m.date === today,
'has-text-grey-light': m.currentMonth !== m.monthCondition
}
]"
>
{{ m.dayPrint }}
</span>
</a>
</div>
</div>
<div class="border-bottom"></div>
<div class="mt-2">
<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>