fix(time-tracking) : filtres projet/tag server-side et vue liste au mois
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled

- Pousse les filtres projet et tag a l'API (au lieu d'un filtrage client-side
  partiel sur la page courante) pour eviter les resultats incomplets en cas
  de pagination
- Ajoute les watchers selectedProjectId/selectedTagId qui declenchent un reload
- Mode liste : navigation et plage de chargement passent a 1 mois (au lieu
  d'une fenetre de 7 jours qui rendait le mode liste inutilisable)
- Renomme l'option vide du filtre User en "Tous" (etait "User", ambigu)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-05-06 09:51:18 +02:00
parent 9f3fc05a52
commit 3e6b0e877a
2 changed files with 54 additions and 19 deletions

View File

@@ -56,7 +56,7 @@
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="Tous"
/> />
</div> </div>
@@ -217,16 +217,7 @@ function updatePageHeaderHeight() {
pageHeaderHeight.value = pageHeaderEl.value?.offsetHeight ?? 0 pageHeaderHeight.value = pageHeaderEl.value?.offsetHeight ?? 0
} }
const filteredEntries = computed(() => { const filteredEntries = computed(() => entries.value)
let result = entries.value
if (selectedProjectId.value) {
result = result.filter((e) => e.project?.id === selectedProjectId.value)
}
if (selectedTagId.value) {
result = result.filter((e) => e.tags.some((t) => t.id === selectedTagId.value))
}
return result
})
function getMonday(d: Date): Date { function getMonday(d: Date): Date {
const date = new Date(d) const date = new Date(d)
@@ -239,15 +230,35 @@ function getMonday(d: Date): Date {
function navigatePrev() { function navigatePrev() {
const d = new Date(startDate.value) const d = new Date(startDate.value)
d.setDate(d.getDate() - (viewMode.value === 'day' ? 1 : 7)) if (viewMode.value === 'day') {
startDate.value = viewMode.value === 'day' ? d : getMonday(d) d.setDate(d.getDate() - 1)
startDate.value = d
} else if (viewMode.value === 'list') {
d.setMonth(d.getMonth() - 1)
d.setDate(1)
d.setHours(0, 0, 0, 0)
startDate.value = d
} else {
d.setDate(d.getDate() - 7)
startDate.value = getMonday(d)
}
loadEntries() loadEntries()
} }
function navigateNext() { function navigateNext() {
const d = new Date(startDate.value) const d = new Date(startDate.value)
d.setDate(d.getDate() + (viewMode.value === 'day' ? 1 : 7)) if (viewMode.value === 'day') {
startDate.value = viewMode.value === 'day' ? d : getMonday(d) d.setDate(d.getDate() + 1)
startDate.value = d
} else if (viewMode.value === 'list') {
d.setMonth(d.getMonth() + 1)
d.setDate(1)
d.setHours(0, 0, 0, 0)
startDate.value = d
} else {
d.setDate(d.getDate() + 7)
startDate.value = getMonday(d)
}
loadEntries() loadEntries()
} }
@@ -359,12 +370,20 @@ async function onExport(params: {
async function loadEntries() { async function loadEntries() {
const end = new Date(startDate.value) const end = new Date(startDate.value)
end.setDate(end.getDate() + (viewMode.value === 'day' ? 1 : 7)) if (viewMode.value === 'day') {
end.setDate(end.getDate() + 1)
} else if (viewMode.value === 'list') {
end.setMonth(end.getMonth() + 1)
} else {
end.setDate(end.getDate() + 7)
}
entries.value = await timeEntryService.getByDateRange({ entries.value = await timeEntryService.getByDateRange({
after: startDate.value.toISOString(), after: startDate.value.toISOString(),
before: end.toISOString(), before: end.toISOString(),
user: selectedUserId.value ?? undefined, user: selectedUserId.value ?? undefined,
project: selectedProjectId.value ?? undefined,
tag: selectedTagId.value ?? undefined,
}) })
} }
@@ -400,11 +419,20 @@ onMounted(async () => {
watch(viewMode, () => { watch(viewMode, () => {
selectedDateFilter.value = null selectedDateFilter.value = null
startDate.value = viewMode.value === 'day' ? startDate.value : getMonday(startDate.value) if (viewMode.value === 'day') {
// keep current date
} else if (viewMode.value === 'list') {
const d = new Date(startDate.value)
d.setDate(1)
d.setHours(0, 0, 0, 0)
startDate.value = d
} else {
startDate.value = getMonday(startDate.value)
}
loadEntries() loadEntries()
}) })
watch(selectedUserId, () => { watch([selectedUserId, selectedProjectId, selectedTagId], () => {
loadEntries() loadEntries()
}) })

View File

@@ -9,7 +9,8 @@ export function useTimeEntryService() {
after: string after: string
before: string before: string
user?: number user?: number
types?: number[] project?: number
tag?: number
}): Promise<TimeEntry[]> { }): Promise<TimeEntry[]> {
const query: Record<string, unknown> = { const query: Record<string, unknown> = {
'startedAt[after]': params.after, 'startedAt[after]': params.after,
@@ -18,6 +19,12 @@ export function useTimeEntryService() {
if (params.user) { if (params.user) {
query.user = `/api/users/${params.user}` query.user = `/api/users/${params.user}`
} }
if (params.project) {
query.project = `/api/projects/${params.project}`
}
if (params.tag) {
query['tags[]'] = `/api/task_tags/${params.tag}`
}
const data = await api.get<HydraCollection<TimeEntry>>('/time_entries', query) const data = await api.get<HydraCollection<TimeEntry>>('/time_entries', query)
return extractHydraMembers(data) return extractHydraMembers(data)
} }