import React, { useState } from 'react'; import { repaymentFee } from './repayment'; import { AccountPicker } from './AccountPicker'; import { QuickTransfer } from './QuickTransfer'; import { money, positionAmount, type Position } from './api'; import { t as tr } from './i18n'; export type QuickEntry = { key: string; kind: 'balance' | 'transfer' | 'mark' | 'booked'; id: string; positionId: string; title: string; currency: string; before?: string; after?: string; amount?: string; received?: string; fee?: string; targetCurrency?: string; date: string; previousMonth?: string | null; month?: string | null; markUpdatedAt?: string; previousDate?: string | null; bookedDate?: string | null; undone?: boolean; }; export const isPaidForMonth = ( position: Pick, month: string, ) => position.kind === 'account' && position.side === 'liability' && position.lastRepaymentMonth === month; export const isBookedToday = (position: Pick, day: string) => position.kind === 'account' && position.lastBookedDate === day; export const quickAccountVisible = ( position: Position, month: string, day: string, unpaidOnly: boolean, hideBooked: boolean, ) => (!unpaidOnly || (position.side === 'liability' && !position.archived && !isPaidForMonth(position, month))) && (!hideBooked || !isBookedToday(position, day)); export const canQuickRepay = (position: Pick) => position.kind === 'account' && position.side === 'liability' && !position.archived && !position.amount.startsWith('-') && !/^0(?:\.0+)?$/.test(position.amount); export function QuickJournal({ entries, busy, undo, }: { entries: QuickEntry[]; busy: boolean; undo: (entry: QuickEntry) => void; }) { return (

{tr('本次快速记账')}

{tr('本次保存成功的记录,可逐项撤回。')}

{!entries.length ? (

{tr('还没有保存记录')}

) : (
    {entries.map((entry) => (
  1. {entry.title} {entry.kind === 'balance' && (

    {money(entry.before || '0', entry.currency)} →{' '} {money(entry.after || '0', entry.currency)}

    )} {entry.kind === 'transfer' && (

    {money(entry.amount || '0', entry.currency)} {entry.targetCurrency !== entry.currency && ( <> → {money(entry.received || '0', entry.targetCurrency || entry.currency)} )}

    )} {entry.kind === 'transfer' && entry.fee && !/^-?0(?:\.0+)?$/.test(entry.fee) && (

    {tr(entry.fee.startsWith('-') ? '优惠' : '手续费')} ·{' '} {money( entry.fee.startsWith('-') ? repaymentFee(entry.fee) : entry.fee, entry.currency, )}

    )} {entry.kind === 'mark' && (

    {tr(entry.month ? '已标记本月还款' : '已取消本月标记')}

    )} {entry.kind === 'booked' && (

    {tr(entry.bookedDate ? '已标记当天记账' : '已取消当天标记')}

    )} {entry.date.replace('T', ' ')} · UTC+8 {entry.undone ? ( {tr('已撤回')} ) : ( )}
  2. ))}
)}
); } export function QuickRepayment({ target, accounts, busy, submit, }: { target: Position; accounts: Position[]; busy: boolean; submit: (data: unknown) => void; }) { const choices = accounts.filter( (p) => p.kind === 'account' && p.side === 'asset' && !p.archived && p.id !== target.id, ); const [sourceId, setSourceId] = useState(choices[0]?.id || ''); const source = choices.find((p) => p.id === sourceId); return (

{tr('还款账户')}:{target.name} · {money(positionAmount(target), target.currency)}

{tr('从付款账户转入欠款账户,双方余额同步更新;这里填写本次还款金额。')}

{!choices.length ? (

{tr('请先添加启用的资产账户作为付款账户。')}

) : ( <> {source && ( setSourceId('')} changeTarget={() => {}} fixedTarget repayment actionLabel={tr('确认还款')} submit={submit} /> )} )}
); }