/** * TanStack Query ayarları: sunucu verisinin önbelleği, yeniden deneme, yenileme. */ import { QueryCache, QueryClient } from '@tanstack/react-query' import { ApiError } from './api' /** Önbellek anahtarları tek yerde (yazım hatası olmasın) */ export const queryKeys = { me: ['me'] as const, registration: ['registration'] as const, health: ['health'] as const, household: ['household'] as const, categories: (includeInactive = false) => ['categories', { includeInactive }] as const, paymentMethods: (includeInactive = false) => ['payment-methods', { includeInactive }] as const, /** Dönem listesi; `currentPeriod` da bu önekle başlar (birlikte yenilenir) */ periods: ['periods'] as const, currentPeriod: ['periods', 'current'] as const, /** Bir döneme bağlı tüm veriler bu önekle başlar → `invalidateQueries({ queryKey: period(id) })` */ period: (id: string) => ['period', id] as const, planItems: (id: string) => ['period', id, 'plan-items'] as const, summary: (id: string) => ['period', id, 'summary'] as const, budget: (id: string) => ['period', id, 'budget'] as const, suggestion: (id: string, method: string) => ['period', id, 'suggestion', method] as const, notes: (id: string, context: string) => ['period', id, 'notes', context] as const, /** Harcamalar; `range` verilmezse tüm dönem (`entries(id)` → tüm aralıkların öneki) */ entries: (id: string, range?: { from: string; to: string }) => range ? (['period', id, 'entries', range] as const) : (['period', id, 'entries'] as const), } /** 4xx hataları tekrar denemenin anlamı yok (yanlış istek / yetki); ağ ve 5xx için 2 kez dene. */ function shouldRetry(failureCount: number, error: unknown) { if (error instanceof ApiError && error.status >= 400 && error.status < 500) return false return failureCount < 2 } export const queryClient = new QueryClient({ queryCache: new QueryCache({ onError: (error) => { // Herhangi bir istek 401 alırsa oturum bitmiş demektir → "me" boşaltılır, // korumalı sayfalar (Adım 4) kullanıcıyı giriş ekranına yönlendirir. if (error instanceof ApiError && error.isUnauthorized) { queryClient.setQueryData(queryKeys.me, null) } }, }), defaultOptions: { queries: { retry: shouldRetry, staleTime: 30_000, // 30 sn içinde aynı veri tekrar istenmez refetchOnWindowFocus: true, // sekmeye dönünce güncel veri (ör. eşin eklediği harcama) }, mutations: { retry: false, }, }, })