feb2e1d16c
- 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>
74 lines
2.5 KiB
TypeScript
74 lines
2.5 KiB
TypeScript
/**
|
||
* 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),
|
||
})
|
||
}
|