feat : MonthGrid n° de semaine interactif + repère (mode semaine) (#MUI-33)

This commit is contained in:
2026-05-20 15:16:17 +02:00
parent 9263cb3722
commit 4021240df3

View File

@@ -19,17 +19,24 @@
v-for="(week, wIndex) in weeks" v-for="(week, wIndex) in weeks"
:key="week.days[0].isoDate" :key="week.days[0].isoDate"
> >
<div <component
:is="interactiveWeekNumber ? 'button' : 'div'"
data-test="week-number" data-test="week-number"
class="mr-[12px] flex h-[45px] w-[35px] shrink-0 items-center justify-center bg-m-primary-light p-[10px] text-sm" :data-week-start="week.days[0].isoDate"
:data-marked="markedWeekStart === week.days[0].isoDate"
:type="interactiveWeekNumber ? 'button' : undefined"
:disabled="interactiveWeekNumber ? !weekSelectable(week) : undefined"
class="mr-[12px] flex h-[45px] w-[35px] shrink-0 items-center justify-center p-[10px] text-sm"
:class="[ :class="[
week.days.some(d => d.isToday) ? 'text-black' : 'text-black/60', weekNumberClass(week),
wIndex === 0 ? 'rounded-t-md' : '', wIndex === 0 ? 'rounded-t-md' : '',
wIndex === weeks.length - 1 ? 'rounded-b-md' : '', wIndex === weeks.length - 1 ? 'rounded-b-md' : '',
]" ]"
@click="onWeekNumberClick(week)"
@mouseenter="onWeekNumberHover(week)"
> >
{{ week.weekNumber }} {{ week.weekNumber }}
</div> </component>
<button <button
v-for="cell in week.days" v-for="cell in week.days"
:key="cell.isoDate" :key="cell.isoDate"
@@ -71,7 +78,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {computed, toRef} from 'vue' import {computed, toRef} from 'vue'
import {useMonthMatrix, type DayCell} from '../composables/useMonthMatrix' import {useMonthMatrix, type DayCell, type WeekRow} from '../composables/useMonthMatrix'
import {isDateInRange} from '../composables/dateFormat' import {isDateInRange} from '../composables/dateFormat'
import {dayRangeRole, resolveRangeBounds, type DayRangeRole} from '../composables/dateRange' import {dayRangeRole, resolveRangeBounds, type DayRangeRole} from '../composables/dateRange'
@@ -85,6 +92,8 @@ const props = withDefaults(
rangeStart?: string | null rangeStart?: string | null
rangeEnd?: string | null rangeEnd?: string | null
previewDate?: string | null previewDate?: string | null
interactiveWeekNumber?: boolean
markedWeekStart?: string | null
min?: string min?: string
max?: string max?: string
}>(), }>(),
@@ -93,6 +102,8 @@ const props = withDefaults(
rangeStart: undefined, rangeStart: undefined,
rangeEnd: undefined, rangeEnd: undefined,
previewDate: undefined, previewDate: undefined,
interactiveWeekNumber: false,
markedWeekStart: null,
min: undefined, min: undefined,
max: undefined, max: undefined,
}, },
@@ -111,6 +122,26 @@ const {weeks} = useMonthMatrix(toRef(props, 'month'), toRef(props, 'year'))
const inRange = (iso: string) => isDateInRange(iso, props.min, props.max) const inRange = (iso: string) => isDateInRange(iso, props.min, props.max)
const weekSelectable = (week: WeekRow) => week.days.some(d => inRange(d.isoDate))
const weekNumberClass = (week: WeekRow) => {
if (props.markedWeekStart === week.days[0].isoDate) return 'bg-m-primary text-white'
const parts = ['bg-m-primary-light']
parts.push(week.days.some(d => d.isToday) ? 'text-black' : 'text-black/60')
if (props.interactiveWeekNumber && weekSelectable(week)) parts.push('cursor-pointer')
return parts.join(' ')
}
const onWeekNumberClick = (week: WeekRow) => {
if (!props.interactiveWeekNumber || !weekSelectable(week)) return
emit('select', week.days[0].isoDate)
}
const onWeekNumberHover = (week: WeekRow) => {
if (!props.interactiveWeekNumber || !weekSelectable(week)) return
emit('hover', week.days[0].isoDate)
}
const isRangeMode = computed(() => props.rangeStart !== undefined) const isRangeMode = computed(() => props.rangeStart !== undefined)
const bounds = computed(() => const bounds = computed(() =>
isRangeMode.value isRangeMode.value