import { ref, computed, watch } from 'vue' import { localDateStr, startOfWeek, startOfMonth } from 'src/composables/useHelpers' // Buffer: 1 period before, 2 after — biased toward the future for natural right-scroll const BUFFER_BEFORE = 1 const BUFFER_AFTER = 2 export function usePeriodNavigation () { const currentView = ref(localStorage.getItem('sbv2-view') || 'week') const savedDate = localStorage.getItem('sbv2-date') let initDate = new Date() if (savedDate && /^\d{4}-\d{2}-\d{2}$/.test(savedDate)) { const d = new Date(savedDate + 'T00:00:00') if (!isNaN(d.getTime())) initDate = d } const anchorDate = ref(initDate) watch(currentView, v => localStorage.setItem('sbv2-view', v)) watch(anchorDate, d => localStorage.setItem('sbv2-date', localDateStr(d))) const periodStart = computed(() => { const d = new Date(anchorDate.value); d.setHours(0,0,0,0) if (currentView.value === 'day') return d if (currentView.value === 'week') return startOfWeek(d) return startOfMonth(d) }) // The "core" period length (what the label describes) const periodDays = computed(() => { if (currentView.value === 'day') return 1 if (currentView.value === 'week') return 7 const s = periodStart.value return new Date(s.getFullYear(), s.getMonth()+1, 0).getDate() }) // Buffer: extra periods before/after for seamless scroll (week only, not day) const bufferDaysBefore = computed(() => { if (currentView.value !== 'week') return 0 return periodDays.value * BUFFER_BEFORE }) const renderedDays = computed(() => { if (currentView.value !== 'week') return periodDays.value return periodDays.value * (1 + BUFFER_BEFORE + BUFFER_AFTER) }) // The start date of all rendered columns (buffer included) const renderedStart = computed(() => { const ps = periodStart.value if (!ps || isNaN(ps.getTime())) return new Date() const d = new Date(ps) d.setDate(d.getDate() - bufferDaysBefore.value) return d }) // dayColumns spans the full rendered range (prev + current + next) const dayColumns = computed(() => { const cols = [] const base = renderedStart.value if (!base || isNaN(base.getTime())) return cols for (let i = 0; i < renderedDays.value; i++) { const d = new Date(base); d.setDate(d.getDate() + i); cols.push(d) } return cols }) function safeFmt (d, opts) { try { return d.toLocaleDateString('fr-CA', opts) } catch { return localDateStr(d) } } const periodLabel = computed(() => { const s = periodStart.value if (!s || isNaN(s.getTime())) return '—' if (currentView.value === 'day') return safeFmt(s, { weekday:'long', day:'numeric', month:'long', year:'numeric' }) if (currentView.value === 'week') { const e = new Date(s); e.setDate(e.getDate() + 6) return `${safeFmt(s,{day:'numeric',month:'short'})} – ${safeFmt(e,{day:'numeric',month:'short',year:'numeric'})}` } return safeFmt(s, { month:'long', year:'numeric' }) }) const todayStr = localDateStr(new Date()) function prevPeriod () { const d = new Date(anchorDate.value) if (currentView.value === 'day') d.setDate(d.getDate()-1) if (currentView.value === 'week') d.setDate(d.getDate()-7) if (currentView.value === 'month') d.setMonth(d.getMonth()-1) anchorDate.value = d } function nextPeriod () { const d = new Date(anchorDate.value) if (currentView.value === 'day') d.setDate(d.getDate()+1) if (currentView.value === 'week') d.setDate(d.getDate()+7) if (currentView.value === 'month') d.setMonth(d.getMonth()+1) anchorDate.value = d } function goToToday () { anchorDate.value = new Date(); currentView.value = 'day' } function goToDay (d) { anchorDate.value = new Date(d); currentView.value = 'day' } return { currentView, anchorDate, periodStart, periodDays, dayColumns, periodLabel, todayStr, bufferDaysBefore, renderedDays, prevPeriod, nextPeriod, goToToday, goToDay, } }