import { Typography, Tooltip } from 'antd'; import { ArrowUpOutlined, ArrowDownOutlined, MinusOutlined } from '@ant-design/icons'; import { formatCurrency } from '@/lib/formatters'; import { accountingColors } from '@/styles/theme'; import { typography, getAmountColor } from '@/styles/designTokens'; const { Text } = Typography; export type AmountType = 'debit' | 'credit' | 'neutral' | 'auto'; export interface AmountTextProps { /** The amount to display */ amount: number; /** Override automatic color detection */ type?: AmountType; /** Whether to show the sign (+/-) */ showSign?: boolean; /** Whether to show currency suffix */ showCurrency?: boolean; /** Currency suffix text */ currencySuffix?: string; /** Text size variant */ size?: 'small' | 'default' | 'large'; /** Whether to use tabular (monospace) numbers */ tabular?: boolean; /** Whether to show tooltip with full precision */ showTooltip?: boolean; /** Show icon indicator for accessibility (not color-only) */ showIcon?: boolean; /** Additional CSS class */ className?: string; /** Inline style overrides */ style?: React.CSSProperties; } /** * A consistent component for displaying monetary amounts. * Automatically colors based on value (positive = credit/green, negative = debit/red). * * @example * * * */ export function AmountText({ amount, type = 'auto', showSign = false, showCurrency = true, currencySuffix = 'kr.', size = 'default', tabular = true, showTooltip = false, showIcon = false, className, style, }: AmountTextProps) { const getColor = (): string => { if (type === 'auto') { return getAmountColor(amount); } if (type === 'neutral') { return accountingColors.neutral; } return accountingColors[type]; }; const getFontSize = (): number => { switch (size) { case 'small': return typography.caption.fontSize; case 'large': return typography.h3.fontSize; default: return typography.body.fontSize; } }; const formatAmount = (): string => { const formatted = formatCurrency(Math.abs(amount)); // Always show +/- prefix for non-zero amounts (accessibility: not color-only) // When showSign is explicitly true, same behavior; kept for API compatibility const alwaysSign = showSign; const sign = alwaysSign && amount !== 0 ? (amount > 0 ? '+' : '-') : amount < 0 ? '-' : ''; const suffix = showCurrency ? ` ${currencySuffix}` : ''; return `${sign}${formatted}${suffix}`; }; // Determine icon for accessibility (not relying on color alone) const getIcon = () => { if (!showIcon) return null; const effectiveType = type === 'auto' ? (amount > 0 ? 'credit' : amount < 0 ? 'debit' : 'neutral') : type; const iconStyle = { marginRight: 4, fontSize: getFontSize() - 2 }; switch (effectiveType) { case 'credit': return ; case 'debit': return ; default: return ; } }; const textStyle: React.CSSProperties = { color: getColor(), fontSize: getFontSize(), fontVariantNumeric: tabular ? 'tabular-nums' : undefined, ...style, }; const content = ( {getIcon()} {formatAmount()} ); if (showTooltip) { return ( {content} ); } return content; } /** * Displays a balance with label */ export interface BalanceDisplayProps { label: string; amount: number; showChange?: boolean; change?: number; size?: 'small' | 'default' | 'large'; } export function BalanceDisplay({ label, amount, size = 'default' }: BalanceDisplayProps) { return (
{label}
); } /** * Displays debit and credit columns for double-entry bookkeeping */ export interface DoubleEntryAmountProps { debit?: number; credit?: number; showZero?: boolean; } export function DoubleEntryAmount({ debit, credit, showZero = false }: DoubleEntryAmountProps) { const showDebit = debit !== undefined && (debit !== 0 || showZero); const showCredit = credit !== undefined && (credit !== 0 || showZero); return ( <> {showDebit && } {showCredit && } ); } /** * Displays a running balance with optional delta indicator */ export interface RunningBalanceProps { balance: number; previousBalance?: number; } export function RunningBalance({ balance, previousBalance }: RunningBalanceProps) { const delta = previousBalance !== undefined ? balance - previousBalance : undefined; return ( {delta !== undefined && delta !== 0 && ( 0 ? accountingColors.credit : accountingColors.debit, }} > ({delta > 0 ? '+' : ''} {formatCurrency(delta)}) )} ); } export default AmountText;