61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
import {computed, type ComputedRef, type Ref} from 'vue'
|
|
|
|
export type DayCell = {
|
|
isoDate: string
|
|
day: number
|
|
isCurrentMonth: boolean
|
|
isToday: boolean
|
|
}
|
|
export type WeekRow = {
|
|
weekNumber: number
|
|
days: DayCell[]
|
|
}
|
|
|
|
const toIso = (d: Date): string => {
|
|
const y = d.getFullYear()
|
|
const m = String(d.getMonth() + 1).padStart(2, '0')
|
|
const day = String(d.getDate()).padStart(2, '0')
|
|
return `${y}-${m}-${day}`
|
|
}
|
|
|
|
const isoWeek = (d: Date): number => {
|
|
const target = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()))
|
|
const dayNum = target.getUTCDay() || 7 // dimanche = 7
|
|
target.setUTCDate(target.getUTCDate() + 4 - dayNum) // jeudi de la semaine
|
|
const yearStart = new Date(Date.UTC(target.getUTCFullYear(), 0, 1))
|
|
return Math.ceil((((target.getTime() - yearStart.getTime()) / 86400000) + 1) / 7)
|
|
}
|
|
|
|
export function useMonthMatrix(
|
|
month: Ref<number>,
|
|
year: Ref<number>,
|
|
): {weeks: ComputedRef<WeekRow[]>} {
|
|
const weeks = computed<WeekRow[]>(() => {
|
|
const todayIso = toIso(new Date())
|
|
const first = new Date(year.value, month.value, 1)
|
|
// recule jusqu'au lundi (getDay : 0 = dimanche)
|
|
const offset = (first.getDay() + 6) % 7
|
|
const start = new Date(year.value, month.value, 1 - offset)
|
|
|
|
const rows: WeekRow[] = []
|
|
const cursor = new Date(start)
|
|
for (let w = 0; w < 6; w++) {
|
|
const days: DayCell[] = []
|
|
for (let i = 0; i < 7; i++) {
|
|
const iso = toIso(cursor)
|
|
days.push({
|
|
isoDate: iso,
|
|
day: cursor.getDate(),
|
|
isCurrentMonth: cursor.getMonth() === month.value,
|
|
isToday: iso === todayIso,
|
|
})
|
|
cursor.setDate(cursor.getDate() + 1)
|
|
}
|
|
rows.push({weekNumber: isoWeek(new Date(`${days[0].isoDate}T00:00:00`)), days})
|
|
}
|
|
return rows
|
|
})
|
|
|
|
return {weeks}
|
|
}
|