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>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
Reference in New Issue
Block a user