mirror of
https://github.com/complexcaresolutions/dak.c2s.git
synced 2026-03-17 23:03:41 +00:00
refactor: migrate ReportsPage to TanStack Query
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
29b54e58a2
commit
150be9183c
2 changed files with 54 additions and 43 deletions
38
frontend/src/hooks/useReports.ts
Normal file
38
frontend/src/hooks/useReports.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||||
|
import api from '@/services/api'
|
||||||
|
import type { ReportMeta } from '@/types'
|
||||||
|
|
||||||
|
interface ReportsListResponse {
|
||||||
|
items: ReportMeta[]
|
||||||
|
total: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useReports() {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ['reports'],
|
||||||
|
queryFn: () =>
|
||||||
|
api.get<ReportsListResponse>('/reports/list').then(r => r.data),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useGenerateReport() {
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (params: { jahr: number; kw: number }) =>
|
||||||
|
api.post<ReportMeta>('/reports/generate', null, { params }).then(r => r.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['reports'] })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useDeleteReports() {
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (ids: number[]) =>
|
||||||
|
api.delete('/reports/delete', { data: ids }),
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['reports'] })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { useState, useEffect } from 'react'
|
import { useState } from 'react'
|
||||||
import { Download, FileSpreadsheet, Loader2, Plus, Trash2 } from 'lucide-react'
|
import { Download, FileSpreadsheet, Loader2, Plus, Trash2 } from 'lucide-react'
|
||||||
import api from '@/services/api'
|
import api from '@/services/api'
|
||||||
import type { ReportMeta } from '@/types'
|
|
||||||
import { useAuth } from '@/context/AuthContext'
|
import { useAuth } from '@/context/AuthContext'
|
||||||
|
import { useReports, useGenerateReport, useDeleteReports } from '@/hooks/useReports'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||||
import { Checkbox } from '@/components/ui/checkbox'
|
import { Checkbox } from '@/components/ui/checkbox'
|
||||||
|
|
@ -19,54 +19,31 @@ export function ReportsPage() {
|
||||||
const currentYear = new Date().getFullYear()
|
const currentYear = new Date().getFullYear()
|
||||||
const currentKw = getISOWeek(new Date())
|
const currentKw = getISOWeek(new Date())
|
||||||
|
|
||||||
const [reports, setReports] = useState<ReportMeta[]>([])
|
// TanStack Query hooks
|
||||||
const [totalReports, setTotalReports] = useState(0)
|
const { data, isLoading: loading } = useReports()
|
||||||
const [loading, setLoading] = useState(true)
|
const reports = data?.items ?? []
|
||||||
|
const totalReports = data?.total ?? 0
|
||||||
|
|
||||||
|
const generateMutation = useGenerateReport()
|
||||||
|
const deleteMutation = useDeleteReports()
|
||||||
|
|
||||||
// Report generation state
|
// Report generation state
|
||||||
const [genJahr, setGenJahr] = useState(currentYear)
|
const [genJahr, setGenJahr] = useState(currentYear)
|
||||||
const [genKw, setGenKw] = useState(currentKw)
|
const [genKw, setGenKw] = useState(currentKw)
|
||||||
const [generating, setGenerating] = useState(false)
|
|
||||||
const [genError, setGenError] = useState('')
|
const [genError, setGenError] = useState('')
|
||||||
const [genSuccess, setGenSuccess] = useState('')
|
const [genSuccess, setGenSuccess] = useState('')
|
||||||
|
|
||||||
// Selection state for deletion
|
// Selection state for deletion
|
||||||
const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set())
|
const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set())
|
||||||
const [deleting, setDeleting] = useState(false)
|
|
||||||
|
|
||||||
// Fetch reports list
|
|
||||||
const fetchReports = () => {
|
|
||||||
setLoading(true)
|
|
||||||
api.get<{ items: ReportMeta[]; total: number }>('/reports/list')
|
|
||||||
.then((res) => {
|
|
||||||
setReports(res.data.items)
|
|
||||||
setTotalReports(res.data.total)
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
setReports([])
|
|
||||||
setTotalReports(0)
|
|
||||||
})
|
|
||||||
.finally(() => setLoading(false))
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchReports()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const generateReport = async () => {
|
const generateReport = async () => {
|
||||||
setGenerating(true)
|
|
||||||
setGenError('')
|
setGenError('')
|
||||||
setGenSuccess('')
|
setGenSuccess('')
|
||||||
try {
|
try {
|
||||||
const res = await api.post<ReportMeta>('/reports/generate', null, {
|
const result = await generateMutation.mutateAsync({ jahr: genJahr, kw: genKw })
|
||||||
params: { jahr: genJahr, kw: genKw },
|
setGenSuccess(`Bericht für KW ${result.kw}/${result.jahr} wurde generiert.`)
|
||||||
})
|
|
||||||
setGenSuccess(`Bericht für KW ${res.data.kw}/${res.data.jahr} wurde generiert.`)
|
|
||||||
fetchReports()
|
|
||||||
} catch {
|
} catch {
|
||||||
setGenError('Fehler beim Generieren des Berichts.')
|
setGenError('Fehler beim Generieren des Berichts.')
|
||||||
} finally {
|
|
||||||
setGenerating(false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,15 +99,11 @@ export function ReportsPage() {
|
||||||
|
|
||||||
const deleteSelected = async () => {
|
const deleteSelected = async () => {
|
||||||
if (selectedIds.size === 0) return
|
if (selectedIds.size === 0) return
|
||||||
setDeleting(true)
|
|
||||||
try {
|
try {
|
||||||
await api.delete('/reports/delete', { data: Array.from(selectedIds) })
|
await deleteMutation.mutateAsync(Array.from(selectedIds))
|
||||||
setSelectedIds(new Set())
|
setSelectedIds(new Set())
|
||||||
fetchReports()
|
|
||||||
} catch {
|
} catch {
|
||||||
setGenError('Fehler beim Löschen der Berichte.')
|
setGenError('Fehler beim Löschen der Berichte.')
|
||||||
} finally {
|
|
||||||
setDeleting(false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,8 +146,8 @@ export function ReportsPage() {
|
||||||
max={53}
|
max={53}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={generateReport} disabled={generating}>
|
<Button onClick={generateReport} disabled={generateMutation.isPending}>
|
||||||
{generating ? (
|
{generateMutation.isPending ? (
|
||||||
<>
|
<>
|
||||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||||
Wird generiert...
|
Wird generiert...
|
||||||
|
|
@ -213,9 +186,9 @@ export function ReportsPage() {
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={deleteSelected}
|
onClick={deleteSelected}
|
||||||
disabled={deleting}
|
disabled={deleteMutation.isPending}
|
||||||
>
|
>
|
||||||
{deleting ? (
|
{deleteMutation.isPending ? (
|
||||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||||
) : (
|
) : (
|
||||||
<Trash2 className="mr-2 h-4 w-4" />
|
<Trash2 className="mr-2 h-4 w-4" />
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue