feat(plan): plan ekranı — görüntüleme/düzenleme modu ve haftalık bütçe
- Salt okunur görünüm: özet kutucukları, gelir/gider, 4 grup + haftalık döküm - Düzenle → taslak; Kaydet yalnızca değişenleri gönderir, Vazgeç geri alır - Kaydedilmemiş değişiklikle çıkışta onay - Hafta elle ayarlama / otomatiğe döndürme, canlı önizleme (backend ile aynı hesap) - DistributionBar ve SuggestionPicker ortak bileşen; 9 yeni vitest Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ import type { PlanItem } from '@/types/PlanItem'
|
||||
import type { PlanItemCreateRequest } from '@/types/PlanItemCreateRequest'
|
||||
import type { SuggestMethod } from '@/types/SuggestMethod'
|
||||
import { api } from './api'
|
||||
import type { PlanOps } from './plan-draft'
|
||||
import { queryKeys } from './query'
|
||||
|
||||
function refreshPeriod(qc: QueryClient, id: string) {
|
||||
@@ -132,3 +133,35 @@ export function useSetBudget(periodId: string) {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// ---------- Plan ekranı: toplu kaydet ----------
|
||||
|
||||
/**
|
||||
* Düzenleme modundaki değişiklikleri sırayla gönderir (`diffPlan` çıktısı).
|
||||
* Tek transaction değildir: biri hata verirse kalanlar gönderilmez, hata fırlatılır;
|
||||
* her durumda dönem verisi yeniden yüklenir → ekran sunucudaki gerçek durumu gösterir.
|
||||
*/
|
||||
export function useSavePlan(period: Period) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: async (ops: PlanOps) => {
|
||||
const pid = period.id
|
||||
if (ops.savings !== null) {
|
||||
await api.patch<Period>(`/periods/${pid}`, {
|
||||
savings_goal: ops.savings,
|
||||
version: period.version,
|
||||
})
|
||||
}
|
||||
for (const id of ops.deletes) await api.delete(`/plan-items/${id}`)
|
||||
for (const { id, ...body } of ops.updates) await api.patch(`/plan-items/${id}`, body)
|
||||
for (const body of ops.creates) await api.post(`/periods/${pid}/plan-items`, body)
|
||||
if (ops.monthly) await api.put(`/periods/${pid}/budget`, ops.monthly)
|
||||
for (const body of ops.weeks) await api.put(`/periods/${pid}/budget/weeks`, body)
|
||||
},
|
||||
onSettled: () =>
|
||||
Promise.all([
|
||||
qc.invalidateQueries({ queryKey: queryKeys.periods }),
|
||||
refreshPeriod(qc, period.id),
|
||||
]),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user