From 6e683f714df7009a4d707c22cc7ff082dc024d1c Mon Sep 17 00:00:00 2001 From: tristan Date: Wed, 20 May 2026 11:52:00 +0200 Subject: [PATCH] =?UTF-8?q?feat=20:=20composable=20de=20navigation=20mois/?= =?UTF-8?q?ann=C3=A9e=20du=20calendrier=20(#MUI-33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 (1M context) --- .../date/composables/useCalendarView.test.ts | 68 +++++++++++++++++++ .../malio/date/composables/useCalendarView.ts | 51 ++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 app/components/malio/date/composables/useCalendarView.test.ts create mode 100644 app/components/malio/date/composables/useCalendarView.ts diff --git a/app/components/malio/date/composables/useCalendarView.test.ts b/app/components/malio/date/composables/useCalendarView.test.ts new file mode 100644 index 0000000..1aa0d99 --- /dev/null +++ b/app/components/malio/date/composables/useCalendarView.test.ts @@ -0,0 +1,68 @@ +import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest' +import {ref} from 'vue' +import {useCalendarView} from './useCalendarView' + +describe('useCalendarView', () => { + beforeEach(() => { + vi.useFakeTimers() + vi.setSystemTime(new Date(2026, 4, 19)) // 19 mai 2026 + }) + afterEach(() => vi.useRealTimers()) + + it('initialises to the current month and year', () => { + const {currentMonth, currentYear} = useCalendarView(ref('days')) + expect(currentMonth.value).toBe(4) + expect(currentYear.value).toBe(2026) + }) + + it('goToNext advances the month in days view', () => { + const {currentMonth, goToNext} = useCalendarView(ref('days')) + goToNext() + expect(currentMonth.value).toBe(5) + }) + + it('rolls December to January and bumps the year', () => { + const {currentMonth, currentYear, goToNext} = useCalendarView(ref('days')) + currentMonth.value = 11 + goToNext() + expect(currentMonth.value).toBe(0) + expect(currentYear.value).toBe(2027) + }) + + it('rolls January to December backwards', () => { + const {currentMonth, currentYear, goToPrev} = useCalendarView(ref('days')) + currentMonth.value = 0 + goToPrev() + expect(currentMonth.value).toBe(11) + expect(currentYear.value).toBe(2025) + }) + + it('navigates the year in months view', () => { + const {currentYear, goToNext, goToPrev} = useCalendarView(ref('months')) + goToNext() + expect(currentYear.value).toBe(2027) + goToPrev() + expect(currentYear.value).toBe(2026) + }) + + it('selectMonth sets the current month', () => { + const {currentMonth, selectMonth} = useCalendarView(ref('days')) + selectMonth(0) + expect(currentMonth.value).toBe(0) + }) + + it('syncToIso sets month/year from a valid ISO', () => { + const {currentMonth, currentYear, syncToIso} = useCalendarView(ref('days')) + syncToIso('2025-12-25') + expect(currentMonth.value).toBe(11) + expect(currentYear.value).toBe(2025) + }) + + it('syncToIso falls back to today for null/invalid', () => { + const {currentMonth, currentYear, syncToIso} = useCalendarView(ref('days')) + syncToIso('2025-12-25') + syncToIso(null) + expect(currentMonth.value).toBe(4) + expect(currentYear.value).toBe(2026) + }) +}) diff --git a/app/components/malio/date/composables/useCalendarView.ts b/app/components/malio/date/composables/useCalendarView.ts new file mode 100644 index 0000000..f0097b4 --- /dev/null +++ b/app/components/malio/date/composables/useCalendarView.ts @@ -0,0 +1,51 @@ +import {ref, type Ref} from 'vue' +import {isValidIso} from './dateFormat' + +export function useCalendarView(viewMode: Ref<'days' | 'months'>) { + const today = new Date() + const currentMonth = ref(today.getMonth()) + const currentYear = ref(today.getFullYear()) + + const goToPrev = () => { + if (viewMode.value === 'months') { + currentYear.value -= 1 + return + } + if (currentMonth.value === 0) { + currentMonth.value = 11 + currentYear.value -= 1 + } else { + currentMonth.value -= 1 + } + } + + const goToNext = () => { + if (viewMode.value === 'months') { + currentYear.value += 1 + return + } + if (currentMonth.value === 11) { + currentMonth.value = 0 + currentYear.value += 1 + } else { + currentMonth.value += 1 + } + } + + const selectMonth = (m: number) => { + currentMonth.value = m + } + + const syncToIso = (iso: string | null) => { + if (iso && isValidIso(iso)) { + currentMonth.value = Number(iso.slice(5, 7)) - 1 + currentYear.value = Number(iso.slice(0, 4)) + } else { + const now = new Date() + currentMonth.value = now.getMonth() + currentYear.value = now.getFullYear() + } + } + + return {currentMonth, currentYear, goToPrev, goToNext, selectMonth, syncToIso} +}