fix(frontend) : fix time-tracking page scroll with fixed header and filters

Restructure time-tracking page layout so the page title and filters
stay fixed while only the calendar grid body scrolls internally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-14 09:10:04 +01:00
parent 25aef9b2d5
commit 802659434f
2 changed files with 53 additions and 54 deletions

View File

@@ -1,9 +1,8 @@
<template> <template>
<div ref="calendarEl" class="relative rounded-lg border border-neutral-200 bg-white"> <div ref="calendarEl" class="relative flex h-full flex-col rounded-lg border border-neutral-200 bg-white">
<!-- Day headers --> <!-- Day headers -->
<div <div
class="sticky z-20 flex border-b border-neutral-200 bg-white" class="z-20 flex flex-shrink-0 border-b border-neutral-200 bg-white rounded-t-lg"
:style="{ top: `${stickyOffset}px` }"
> >
<div class="w-16 shrink-0 border-r border-neutral-200" /> <div class="w-16 shrink-0 border-r border-neutral-200" />
<div <div
@@ -22,7 +21,7 @@
</div> </div>
<!-- Grid body --> <!-- Grid body -->
<div ref="gridBodyEl" class="relative flex"> <div ref="gridBodyEl" class="relative flex min-h-0 flex-1 overflow-y-auto">
<!-- Hour labels --> <!-- Hour labels -->
<div class="w-16 shrink-0"> <div class="w-16 shrink-0">
<div <div

View File

@@ -1,6 +1,6 @@
<template> <template>
<div> <div class="flex min-h-0 flex-1 flex-col">
<div ref="pageHeaderEl" class="sticky top-0 z-40 bg-white pb-4"> <div ref="pageHeaderEl" class="flex-shrink-0 pb-4">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<h1 class="text-2xl font-bold text-primary-500">Suivi des temps</h1> <h1 class="text-2xl font-bold text-primary-500">Suivi des temps</h1>
<button <button
@@ -12,61 +12,61 @@
</div> </div>
<div class="relative z-30 mt-4 flex items-center gap-4"> <div class="relative z-30 mt-4 flex items-center gap-4">
<h2 class="text-lg font-bold text-orange-500"> <h2 class="text-lg font-bold text-orange-500">
{{ currentMonthLabel }} {{ currentMonthLabel }}
</h2> </h2>
<div class="flex items-center gap-1 rounded-md border border-neutral-200"> <div class="flex items-center gap-1 rounded-md border border-neutral-200">
<button class="px-2 py-1 text-neutral-500 hover:text-neutral-700" @click="navigatePrev"> <button class="px-2 py-1 text-neutral-500 hover:text-neutral-700" @click="navigatePrev">
<Icon name="mdi:chevron-left" size="20" /> <Icon name="mdi:chevron-left" size="20" />
</button> </button>
<button <button
v-for="mode in (['week', 'day', 'list'] as const)" v-for="mode in (['week', 'day', 'list'] as const)"
:key="mode" :key="mode"
class="px-3 py-1 text-sm font-semibold transition" class="px-3 py-1 text-sm font-semibold transition"
:class="viewMode === mode ? 'bg-primary-500 text-white rounded' : 'text-neutral-500 hover:text-neutral-700'" :class="viewMode === mode ? 'bg-primary-500 text-white rounded' : 'text-neutral-500 hover:text-neutral-700'"
@click="viewMode = mode" @click="viewMode = mode"
> >
{{ mode === 'week' ? 'Semaine' : mode === 'day' ? 'Jour' : 'Liste' }} {{ mode === 'week' ? 'Semaine' : mode === 'day' ? 'Jour' : 'Liste' }}
</button> </button>
<button class="px-2 py-1 text-neutral-500 hover:text-neutral-700" @click="navigateNext"> <button class="px-2 py-1 text-neutral-500 hover:text-neutral-700" @click="navigateNext">
<Icon name="mdi:chevron-right" size="20" /> <Icon name="mdi:chevron-right" size="20" />
</button> </button>
</div> </div>
<MalioSelect <MalioSelect
v-model="selectedUserId" v-model="selectedUserId"
:options="userOptions" :options="userOptions"
min-width="!w-40" min-width="!w-44"
text-field="text-sm" text-field="text-sm"
text-value="text-sm" text-value="text-sm"
label="User" label="User"
empty-option-label="User" empty-option-label="User"
/> />
<MalioSelect <MalioSelect
v-model="selectedProjectId" v-model="selectedProjectId"
:options="projectOptions" :options="projectOptions"
empty-option-label="Tous" empty-option-label="Tous"
label="Projet" label="Projet"
min-width="!w-40" min-width="!w-44"
text-field="text-sm" text-field="text-sm"
text-value="text-sm" text-value="text-sm"
/> />
<MalioSelect <MalioSelect
v-model="selectedTagId" v-model="selectedTagId"
:options="tagOptions" :options="tagOptions"
empty-option-label="Tous" empty-option-label="Tous"
label="Tag" label="Tag"
min-width="!w-40" min-width="!w-44"
text-field="text-sm" text-field="text-sm"
text-value="text-sm" text-value="text-sm"
/> />
</div> </div>
</div> </div>
<div class="mt-4"> <div class="mt-4 -mb-24 min-h-0 flex-1">
<TimeEntryList <TimeEntryList
v-if="viewMode === 'list'" v-if="viewMode === 'list'"
:entries="filteredEntries" :entries="filteredEntries"