Files
kakeibo/frontend/src/lib/money-schema.ts
T
suphicakir ca0d3a505c feat(plan): ilk dönem sihirbazı (dönem, gelir, gider, birikim, bütçe)
- /plan/donem-ac?adim=1..5: her adım hemen kaydedilir, adım adreste
- Panel ve Plan'da açık dönem yoksa "Dönemi başlat" kartı
- MoneyInput (sayısal klavye, Türkçe biçim), moneyText/toKurus, period-dates
- lib/periods.ts: dönem, plan kalemi, özet, bütçe ve öneri kancaları
- SummaryTiles, PageLoading/PageError; 13 yeni vitest

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

45 lines
1.6 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.
/**
* Formlarda tutar alanı: kullanıcı metin yazar (`1.250,50`), doğrulama `parseMoney` ile yapılır.
* Gönderirken `toKurus(metin)` ile kuruşa çevrilir.
*/
import { z } from 'zod'
import { parseMoney } from './format'
/** Backend ile aynı üst sınır (`services/period.rs` → `MAX_AMOUNT`): 100 milyar ₺ */
export const MAX_AMOUNT_KURUS = 10_000_000_000_000
export const moneyMessages = {
required: 'Tutarı yazın',
invalid: 'Geçerli bir tutar yazın (ör. 1.250,50)',
positive: 'Tutar sıfırdan büyük olmalı',
negative: 'Tutar eksi olamaz',
tooLarge: 'Tutar çok büyük',
}
/**
* - `positive`: 0'dan büyük olmalı (gelir/gider kalemi)
* - `optional`: boş bırakılabilir → 0 sayılır (birikim hedefi, bütçe)
*/
export function moneyText(mode: 'positive' | 'optional') {
return z
.string()
.trim()
.superRefine((value, ctx) => {
if (value === '') {
if (mode === 'positive') ctx.addIssue({ code: 'custom', message: moneyMessages.required })
return
}
const k = parseMoney(value)
if (k === null) return ctx.addIssue({ code: 'custom', message: moneyMessages.invalid })
if (k < 0) return ctx.addIssue({ code: 'custom', message: moneyMessages.negative })
if (mode === 'positive' && k === 0)
return ctx.addIssue({ code: 'custom', message: moneyMessages.positive })
if (k > MAX_AMOUNT_KURUS) ctx.addIssue({ code: 'custom', message: moneyMessages.tooLarge })
})
}
/** Doğrulanmış metin → kuruş (boş → 0) */
export function toKurus(value: string): number {
return parseMoney(value) ?? 0
}