311cfc8c60
- 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>
27 lines
1.1 KiB
TypeScript
27 lines
1.1 KiB
TypeScript
/**
|
||
* 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
|
||
}
|