76 lines
1.7 KiB
Vue
76 lines
1.7 KiB
Vue
<template>
|
|
<div class="week-row">
|
|
<div class="week-label">W{{ weekNumber }}</div>
|
|
<div class="days-grid">
|
|
<DayCell v-for="day in days" :key="day.dateStr" :day="day" />
|
|
<div class="week-overlay">
|
|
<!-- Event spans will be rendered here -->
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-if="monthLabel"
|
|
class="month-name-label"
|
|
:style="{ height: `${monthLabel.weeksSpan * 64}px` }"
|
|
>
|
|
<span>{{ monthLabel.name }} '{{ monthLabel.year }}</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from 'vue'
|
|
import DayCell from './DayCell.vue'
|
|
import {
|
|
toLocalString,
|
|
getLocalizedMonthName,
|
|
monthAbbr,
|
|
DEFAULT_TZ,
|
|
getISOWeek,
|
|
} from '@/utils/date'
|
|
import { addDays } from 'date-fns'
|
|
|
|
const props = defineProps({
|
|
week: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
})
|
|
|
|
const weekNumber = computed(() => getISOWeek(props.week.monday))
|
|
|
|
const days = computed(() => {
|
|
const d = new Date(props.week.monday)
|
|
const result = []
|
|
for (let i = 0; i < 7; i++) {
|
|
const dateStr = toLocalString(d, DEFAULT_TZ)
|
|
result.push({
|
|
date: new Date(d),
|
|
dateStr,
|
|
dayOfMonth: d.getDate(),
|
|
month: d.getMonth(),
|
|
isFirstDayOfMonth: d.getDate() === 1,
|
|
monthClass: monthAbbr[d.getMonth()],
|
|
})
|
|
d.setTime(addDays(d, 1).getTime())
|
|
}
|
|
return result
|
|
})
|
|
|
|
const monthLabel = computed(() => {
|
|
const firstDayOfMonth = days.value.find((d) => d.isFirstDayOfMonth)
|
|
if (!firstDayOfMonth) return null
|
|
|
|
const month = firstDayOfMonth.month
|
|
const year = firstDayOfMonth.date.getFullYear()
|
|
|
|
// This is a simplified calculation for weeksSpan
|
|
const weeksSpan = 4
|
|
|
|
return {
|
|
name: getLocalizedMonthName(month),
|
|
year: String(year).slice(-2),
|
|
weeksSpan,
|
|
}
|
|
})
|
|
</script>
|