Files
kakeibo/frontend/src/lib/entries.ts
T
suphicakir feb2e1d16c feat(raporlar): raporlar sayfası, CSV dışa aktarma ve yazdırma
- Filtreler (kapsam, grup, kategori, ödeme türü) adreste
- Gruplar, tüm kategoriler, ödeme türleri, aylar; bütçe sapması; gelir–gider ve birikim oranı; varlık performansı
- Her bölümde Excel uyumlu CSV (BOM, ;) ve tek bölüm yazdırma
- Yazdırmada açık tema, menüler gizli, kapsam satırı

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 01:59:58 +03:00

74 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Günlük defter: harcama kayıtları (sunucu verisi kancaları).
*
* Kayıt değişince dönemin tüm sorguları yenilenir (`queryKeys.period(id)` öneki):
* liste, özet (`spent_total`, `remaining`) ve bütçe (`spent`) birlikte güncellenir.
*/
import {
keepPreviousData,
useMutation,
useQuery,
useQueryClient,
type QueryClient,
} from '@tanstack/react-query'
import type { Entry } from '@/types/Entry'
import type { EntryCreateRequest } from '@/types/EntryCreateRequest'
import type { EntryUpdateRequest } from '@/types/EntryUpdateRequest'
import { api } from './api'
import { queryKeys } from './query'
/** Bir tarih aralığının kayıtları (ikisi de dahil); en yeni başta */
/** Kayıt değişince: dönemin tüm verileri + Panel istatistikleri (harcanan) */
function refresh(qc: QueryClient, periodId: string) {
return Promise.all([
qc.invalidateQueries({ queryKey: queryKeys.period(periodId) }),
qc.invalidateQueries({ queryKey: queryKeys.stats }),
qc.invalidateQueries({ queryKey: queryKeys.reports }),
])
}
export function useEntries(periodId: string, range: { from: string; to: string }) {
return useQuery({
queryKey: queryKeys.entries(periodId, range),
queryFn: () =>
api.get<Entry[]>(`/periods/${periodId}/entries?from=${range.from}&to=${range.to}`),
// hafta değiştirirken liste boşalıp titremesin
placeholderData: keepPreviousData,
})
}
export function useCreateEntry(periodId: string) {
const qc = useQueryClient()
return useMutation({
mutationFn: (body: EntryCreateRequest) => api.post<Entry>(`/periods/${periodId}/entries`, body),
onSuccess: () => refresh(qc, periodId),
})
}
/** Düzenle (`version` ile: başkası değiştirdiyse 409). Hata da olsa liste yenilenir. */
export function useUpdateEntry(periodId: string) {
const qc = useQueryClient()
return useMutation({
mutationFn: ({ id, ...body }: EntryUpdateRequest & { id: string }) =>
api.patch<Entry>(`/entries/${id}`, body),
onSettled: () => refresh(qc, periodId),
})
}
/** Sil (soft) → `useRestoreEntry` ile geri alınabilir */
export function useDeleteEntry(periodId: string) {
const qc = useQueryClient()
return useMutation({
mutationFn: (id: string) => api.delete(`/entries/${id}`),
onSettled: () => refresh(qc, periodId),
})
}
export function useRestoreEntry(periodId: string) {
const qc = useQueryClient()
return useMutation({
mutationFn: (id: string) => api.post<Entry>(`/entries/${id}/restore`),
onSettled: () => refresh(qc, periodId),
})
}