Files
kakeibo/frontend/src/lib/review.ts
T
suphicakir 311cfc8c60 feat(değerlendirme): ay sonu değerlendirmesi sayfası
- Kakeibo'nun 4 sorusu, nasıl hesaplandığıyla birlikte
- Grup bazında planlanan/gerçekleşen, en çok harcanan kategoriler, haftalık dağılım
- "Nasıl daha iyi yapabilirim?" (Markdown) ve yalnızca başlıkları listelenen notlar

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 12:31:35 +03:00

27 lines
1.1 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.
/**
* Değerlendirme sayfasının saf hesapları. Tutarlar backend'den gelir (`PeriodReview`);
* burada yalnızca yorum (durum, oran) yapılır.
*/
import type { PeriodReview } from '@/types/PeriodReview'
/** 4. soru: birikim hedefe göre nerede? */
export type SavingsStatus =
| { kind: 'above'; amount: number } // hedefe ulaşıldı/aşıldı (amount ≥ 0)
| { kind: 'below'; amount: number } // birikim var ama hedefin altında
| { kind: 'deficit'; amount: number } // açık var → borç olarak devreder
export function savingsStatus(
r: Pick<PeriodReview, 'realized_savings' | 'savings_gap'>,
): SavingsStatus {
if (r.realized_savings < 0) return { kind: 'deficit', amount: -r.realized_savings }
if (r.savings_gap < 0) return { kind: 'below', amount: -r.savings_gap }
return { kind: 'above', amount: r.savings_gap }
}
/** Oran (0–1); payda 0 ise pay varsa 1, yoksa 0. Çubuk genişliği için 1'de kesilir. */
export function ratio(part: number, total: number, cap = true): number {
if (total <= 0) return part > 0 ? 1 : 0
const r = part / total
return cap ? Math.min(r, 1) : r
}