This commit is contained in:
Viet An
2026-05-26 12:44:03 +07:00
parent aa084150b5
commit cc3bb9cfb5
6 changed files with 172 additions and 138 deletions

View File

@@ -10,22 +10,6 @@
font-size: 15px; font-size: 15px;
} }
// Block Layout
.blockdiv {
max-width: 1900px !important;
padding: 1rem 2rem 2rem;
@include mobile {
padding: 1rem;
}
.columns .column {
@include mobile {
padding-left: 0;
padding-right: 0;
}
}
}
// Tooltip Styles // Tooltip Styles
.tooltiptext { .tooltiptext {
visibility: hidden; visibility: hidden;

View File

@@ -23,7 +23,7 @@
role="menu" role="menu"
@click="doClick()" @click="doClick()"
> >
<div class="dropdown-content"> <div class="dropdown-content px-2 w-xs">
<PickDay <PickDay
v-bind="{ date, maxdate }" v-bind="{ date, maxdate }"
@date="selectDate" @date="selectDate"
@@ -41,6 +41,8 @@
</div> </div>
</template> </template>
<script setup> <script setup>
import PickDay from "@/components/datepicker/PickDay.vue";
const props = defineProps({ const props = defineProps({
record: Object, record: Object,
attr: String, attr: String,
@@ -51,7 +53,7 @@ const props = defineProps({
}); });
const emit = defineEmits(["date"]); const emit = defineEmits(["date"]);
const { $id, $copy, $dayjs, $empty } = useNuxtApp(); const { $copy, $dayjs, $empty } = useNuxtApp();
const date = ref(); const date = ref();
const show = ref(); const show = ref();
@@ -144,8 +146,8 @@ function checkDate() {
date.value = undefined; date.value = undefined;
if ($empty(show.value)) return emit("date", null); if ($empty(show.value)) return emit("date", null);
show.value = getDate(show.value); show.value = getDate(show.value);
let val = `${show.value.substring(6, 10)}-${show.value.substring(3, 5)}-${show.value.substring(0, 2)}`; const val = `${show.value.substring(6, 10)}/${show.value.substring(3, 5)}/${show.value.substring(0, 2)}`;
if ($dayjs(val, "YYYY-MM-DD", true).isValid()) { if ($dayjs(val, "YYYY/MM/DD", true).isValid()) {
date.value = val; date.value = val;
emit("date", date.value); emit("date", date.value);
} else error.value = true; } else error.value = true;

View File

@@ -1,9 +1,6 @@
<template> <template>
<div <div class="is-flex is-flex-direction-column is-gap-1">
class="px-2" <div class="is-flex is-gap-1 is-justify-content-space-between h-8">
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"> <div class="buttons is-gap-0.5 m-0 is-align-items-stretch">
<button <button
@click="previousYear" @click="previousYear"
@@ -29,17 +26,17 @@
</span> </span>
</button> </button>
</div> </div>
<div class="is-flex is-align-items-center is-gap-0"> <div class="buttons is-gap-0 m-0 is-align-items-center">
<button <button
v-if="type === 'days'" v-if="type === 'days'"
@click="type = 'months'" @click="type = 'months'"
class="button is-white p-2 has-text-primary font-bold h-full" class="button is-white p-1.5 fs-14 has-text-primary font-semibold h-full"
> >
T{{ month }} T{{ month }}
</button> </button>
<button <button
@click="type = 'years'" @click="type = 'years'"
class="button is-white p-2 has-text-primary font-bold h-full" class="button is-white p-1.5 fs-14 has-text-primary font-semibold h-full"
> >
{{ caption || year }} {{ caption || year }}
</button> </button>
@@ -70,59 +67,63 @@
</button> </button>
</div> </div>
</div> </div>
<hr class="mt-1 mb-5" />
<div v-if="type === 'days'"> <div v-if="type === 'days'">
<div class="columns is-mobile mx-0 mb-3"> <div class="fixed-grid has-7-cols mb-1 fs-13 has-background-white-bis has-text-grey rounded-sm">
<div <div class="grid is-gap-0">
v-for="(m, h) in dateOfWeek" <p
:key="h" v-for="(m, h) in dateOfWeek"
class="fs-14 column p-0 has-text-grey is-flex is-justify-content-center is-align-items-center" :key="h"
> class="cell py-1 is-flex is-justify-content-center is-align-items-center is-unselectable"
{{ m.text }} >
{{ m.text }}
</p>
</div> </div>
</div> </div>
<div <div
v-for="(v, i) in weeks" v-for="(v, i) in weeks"
:key="i" :key="i"
:class="`columns is-mobile mx-0 mb-1 ${i === weeks.length - 1 ? 'mb-1' : ''}`" class="fixed-grid has-7-cols mb-0"
> >
<div <div class="grid is-gap-0">
v-for="(m, h) in v.dates" <div
:key="h" v-for="(m, h) in v.dates"
class="column p-0 is-flex is-justify-content-center is-align-items-center" :key="h"
style="width: 40px; height: 32px" class="cell is-flex is-justify-content-center is-align-items-center"
> style="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 <span
style="width: 25px; height: 25px" v-if="m.disabled"
class="fs-13 has-text-grey-light is-unselectable"
>
{{ m.dayPrint.replace(/^0/, "") }}
</span>
<button
v-else
@click="choose(m)"
style="width: 26px; height: 26px"
:class="[ :class="[
'p-1 rounded-full is-flex is-justify-content-center is-align-items-center', 'button fs-13 font-normal p-1 rounded-full is-flex',
{ {
'has-background-primary has-text-white': m.date === curdate, 'is-white': m.date !== $dayjs(today).format('YYYY/MM/DD'),
'has-background-success-50 has-text-white': m.date === today, 'is-primary': m.date === curdate,
'has-text-grey-light': m.currentMonth !== m.monthCondition, 'has-text-grey': m.currentMonth !== m.monthCondition && m.date !== curdate,
}, },
]" ]"
> >
{{ m.dayPrint }} {{ m.dayPrint.replace(/^0/, "") }}
</span> </button>
</span> </div>
</div> </div>
</div> </div>
<hr class="my-1" /> <hr class="my-2" />
<div class="mt-2 fs-14"> <div class="mx-2 is-flex is-gap-0.5 is-align-items-center">
<span class="ml-2">Hôm nay: </span> <p class="fs-14">Hôm nay:</p>
<a @click="chooseToday">{{ $dayjs(today).format("L") }}</a> <button
@click="chooseToday"
class="button is-white has-text-primary-65 p-1 fs-14"
>
{{ $dayjs(today).format("L") }}
</button>
</div> </div>
</div> </div>
<PickMonth <PickMonth
@@ -138,8 +139,8 @@
</div> </div>
</template> </template>
<script setup> <script setup>
import PickMonth from "@/components/datepicker/PickMonth"; import PickMonth from "@/components/datepicker/PickMonth.vue";
import PickYear from "@/components/datepicker/PickYear"; import PickYear from "@/components/datepicker/PickYear.vue";
const { $id, $dayjs, $unique } = useNuxtApp(); const { $id, $dayjs, $unique } = useNuxtApp();
const emit = defineEmits(["date"]); const emit = defineEmits(["date"]);
@@ -149,17 +150,17 @@ const props = defineProps({
}); });
const dates = ref([]); const dates = ref([]);
const dateOfWeek = [ const dateOfWeek = [
{ id: 0, text: "CN" }, { id: 0, text: "T2" },
{ id: 1, text: "T2" },
{ id: 2, text: "T3" }, { id: 2, text: "T3" },
{ id: 3, text: "T4" }, { id: 2, text: "T4" },
{ id: 4, text: "T5" }, { id: 3, text: "T5" },
{ id: 5, text: "T6" }, { id: 4, text: "T6" },
{ id: 6, text: "T7" }, { id: 5, text: "T7" },
{ id: 6, text: "CN" },
]; ];
const weeks = ref([]); const weeks = ref([]);
const year = ref(); const year = ref();
let month; const month = ref();
const type = ref("days"); const type = ref("days");
const caption = ref(); const caption = ref();
const action = ref(); const action = ref();
@@ -167,22 +168,22 @@ const curdate = ref();
const today = new Date(); const today = new Date();
function showDate() { function showDate() {
curdate.value = props.date ? props.date.replaceAll("-", "/") : undefined; curdate.value = props.date;
year.value = $dayjs(curdate.value || today).year(); year.value = $dayjs(curdate.value || today).year();
month = $dayjs(curdate.value || today).month() + 1; month.value = $dayjs(curdate.value || today).month() + 1;
getDates(); getDates();
} }
function chooseToday() { function chooseToday() {
emit("date", $dayjs(today).format("YYYY-MM-DD")); //today.replaceAll('/', '-')) emit("date", $dayjs(today).format("YYYY/MM/DD"));
year.value = $dayjs(today).year(); year.value = $dayjs(today).year();
month = $dayjs(today).month() + 1; month.value = $dayjs(today).month() + 1;
getDates(); getDates();
} }
function changeCaption(v) { function changeCaption(v) {
caption.value = v; caption.value = v;
} }
function selectMonth(v) { function selectMonth(v) {
month = v; month.value = v;
getDates(); getDates();
type.value = "days"; type.value = "days";
} }
@@ -193,26 +194,26 @@ function selectYear(v) {
} }
function getDates() { function getDates() {
caption.value = undefined; caption.value = undefined;
dates.value = allDaysInMonth(year.value, month); dates.value = allDaysInMonth(year.value, month.value);
weeks.value = $unique(dates.value, ["week"]).map((v) => { weeks.value = $unique(dates.value, ["week"]).map((v) => {
return { week: v.week }; return { week: v.week };
}); });
weeks.value.map((v) => { weeks.value.forEach((v) => {
v.dates = dates.value.filter((x) => x.week === v.week); v.dates = dates.value.filter((x) => x.week === v.week);
}); });
} }
function nextMonth() { function nextMonth() {
month = month + 1; month.value = month.value + 1;
if (month > 12) { if (month.value > 12) {
month = 1; month.value = 1;
year.value += 1; year.value += 1;
} }
getDates(); getDates();
} }
function previousMonth() { function previousMonth() {
month = month - 1; month.value = month.value - 1;
if (month === 0) { if (month.value === 0) {
month = 12; month.value = 12;
year.value -= 1; year.value -= 1;
} }
getDates(); getDates();
@@ -228,53 +229,52 @@ function previousYear() {
getDates(); getDates();
} }
function choose(m) { function choose(m) {
emit("date", m.date.replaceAll("/", "-")); emit("date", m.date);
}
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) { function allDaysInMonth(year, month) {
let days = Array.from({ length: $dayjs(createDate(year, month, 1)).daysInMonth() }, (_, i) => i + 1); const days = Array.from({ length: $dayjs([year, month, 1]).daysInMonth() }, (_, i) => i + 1);
let arr = []; const arr = [];
days.map((v) => {
days.forEach((day) => {
for (let i = 0; i < 7; i++) { for (let i = 0; i < 7; i++) {
let thedate = $dayjs(createDate(year, month, v)).weekday(i); const thedate = $dayjs([year, month, day]).weekday(i);
let date = $dayjs(new Date(thedate.$d)).format("YYYY/MM/DD"); const date = thedate.format("YYYY/MM/DD");
let dayPrint = $dayjs(new Date(thedate.$d)).format("DD");
let monthCondition = $dayjs(date).month() + 1; const monthCondition = thedate.month() + 1;
let currentMonth = month; const found = arr.find((x) => x.date === date);
let found = arr.find((x) => x.date === date);
if (!found) { if (!found) {
let dayOfWeek = $dayjs(date).day(); let disabled = false;
let week = $dayjs(date).week(); if (props.maxdate) {
let disable = false; const maxDateObj = $dayjs(props.maxdate);
if (props.maxdate ? $dayjs(props.maxdate).diff(props.date, "day") >= 0 : false) { if (maxDateObj.diff(props.date, "day") >= 0 && maxDateObj.startOf("day").diff(date, "day") < 0) {
if ($dayjs(props.maxdate).startOf("day").diff(date, "day") < 0) disable = true; disabled = true;
}
} }
let ele = { const ele = {
date: date, date,
week: week, day,
day: v, week: thedate.week(),
dayOfWeek: dayOfWeek, dayOfWeek: thedate.day(),
dayPrint: dayPrint, dayPrint: thedate.format("DD"),
monthCondition: monthCondition, monthCondition,
currentMonth: currentMonth, currentMonth: month,
disable: disable, disabled,
}; };
arr.push(ele); arr.push(ele);
} }
} }
}); });
return arr; return arr;
} }
// display
showDate();
// change date
watch( watch(
() => props.date, () => props.date,
() => { () => {
showDate(); showDate();
}, },
{ immediate: true },
); );
</script> </script>
<style scoped> <style scoped>

View File

@@ -1,11 +1,26 @@
<template> <template>
<div class="columns is-mobile is-multiline mx-0"> <div class="fixed-grid has-3-cols">
<span <div
v-for="month in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]" class="grid"
:id="String(month)" style="gap: 0.5rem 0"
class="column has-text-centered is-4 is-clickable fs-14" >
@click="$emit('month', month)" <div
>Tháng {{ month }} v-for="month in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]"
</span> :key="month"
class="cell is-flex"
>
<button
class="button is-white fs-14 w-full"
@click="$emit('month', month)"
>
Tháng {{ month }}
</button>
</div>
</div>
</div> </div>
</template> </template>
<style scoped>
.button {
--bulma-button-color-l: 25%;
}
</style>

View File

@@ -1,13 +1,22 @@
<template> <template>
<div class="columns is-mobile is-multiline mx-0"> <div class="fixed-grid has-3-cols">
<span <div
v-for="(year, i) in years" class="grid"
:key="year" style="gap: 0.5rem 0"
:class="['column is-4 has-text-centered is-clickable fs-14', (i === 0 || i === 11) && 'has-text-grey-light']"
@click="$emit('year', year)"
> >
{{ year }} <div
</span> v-for="(year, i) in years"
:key="year"
class="cell"
>
<button
:class="['button is-white w-full fs-14', (i === 0 || i === 11) && 'has-text-grey-light']"
@click="emit('year', year)"
>
{{ year }}
</button>
</div>
</div>
</div> </div>
</template> </template>
<script setup> <script setup>
@@ -17,13 +26,12 @@ const props = defineProps({
action: Object, action: Object,
}); });
const emit = defineEmits(["caption"]); const emit = defineEmits(["caption", "year"]);
const years = ref( const years = ref(
Array.from({ length: 12 }) Array.from({ length: 12 })
.fill(props.year) .fill(props.year)
.map((y, i) => y + i - 6), .map((y, i) => y + i - 6),
); );
emit("caption", `${years.value[1]} ${years.value[10]}`);
watch( watch(
() => props.action, () => props.action,
@@ -33,9 +41,13 @@ watch(
}, },
); );
watch(years, () => { watch(
emit("caption", `${years.value[1]} ${years.value[10]}`); years,
}); () => {
emit("caption", `${years.value[1]} ${years.value[10]}`);
},
{ immediate: true },
);
function next() { function next() {
const baseYear = years.value[11]; const baseYear = years.value[11];
@@ -51,3 +63,8 @@ function previous() {
.map((y, i) => y + i - 6); .map((y, i) => y + i - 6);
} }
</script> </script>
<style scoped>
.button {
--bulma-button-color-l: 25%;
}
</style>

View File

@@ -102,3 +102,19 @@ function refresh() {
setTimeout(() => (componentKey.value = copy)); setTimeout(() => (componentKey.value = copy));
} }
</script> </script>
<style scoped>
.blockdiv {
max-width: 1900px !important;
padding: 1rem 2rem 2rem;
@include mobile {
padding: 1rem;
}
.columns .column {
@include mobile {
padding-left: 0;
padding-right: 0;
}
}
}
</style>