ca0d3a505c
- /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>
45 lines
1.6 KiB
TypeScript
45 lines
1.6 KiB
TypeScript
/**
|
||
* 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
|
||
}
|