refactor(frontend): tighten dashboard visual helpers per code review
This commit is contained in:
parent
af0aaeda9d
commit
1a2937ad58
@ -69,9 +69,3 @@ export function incomeTypesToOperationTypes(types: DashboardIncomeType[]): strin
|
||||
if (types.includes('coupon')) operationTypes.add('OPERATION_TYPE_COUPON')
|
||||
return [...operationTypes].join(',')
|
||||
}
|
||||
|
||||
export function resetDashboardFilters<T extends string>(
|
||||
factory: () => DashboardFilterState<T>,
|
||||
): DashboardFilterState<T> {
|
||||
return factory()
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { BrokerMoney } from '@/shared/api'
|
||||
import {
|
||||
type DashboardMoneyLike,
|
||||
eventTypeTone,
|
||||
formatDashboardCurrency,
|
||||
incomeTypeTone,
|
||||
@ -14,21 +13,28 @@ function money(currency: string, value: number): BrokerMoney {
|
||||
}
|
||||
|
||||
describe('formatDashboardCurrency', () => {
|
||||
it('renders RUB with the ₽ symbol', () => {
|
||||
it('renders RUB with the ₽ symbol via the shared formatter', () => {
|
||||
const result = formatDashboardCurrency(money('RUB', 1234.56))
|
||||
expect(result).toContain('₽')
|
||||
expect(result).not.toContain('RUB')
|
||||
})
|
||||
|
||||
it('falls back to currency code for unknown currencies', () => {
|
||||
it('renders known non-RUB currencies via the shared formatter', () => {
|
||||
const result = formatDashboardCurrency(money('USD', 42))
|
||||
expect(result).toContain('USD')
|
||||
expect(result).toContain('$')
|
||||
expect(result).not.toContain('USD')
|
||||
expect(result).not.toContain('₽')
|
||||
})
|
||||
|
||||
it('falls back to currency code for unknown currencies', () => {
|
||||
const result = formatDashboardCurrency(money('XYZ', 100))
|
||||
expect(result).toContain('XYZ')
|
||||
expect(result).not.toContain('¤')
|
||||
})
|
||||
|
||||
it('falls back to currency code via the value-only shape', () => {
|
||||
const result = formatDashboardCurrency({ currency: 'EUR', value: 9.99 } as DashboardMoneyLike)
|
||||
expect(result).toContain('EUR')
|
||||
const result = formatDashboardCurrency({ currency: 'XYZ', value: 9.99 })
|
||||
expect(result).toContain('XYZ')
|
||||
})
|
||||
|
||||
it('returns "—" for null or undefined', () => {
|
||||
@ -72,26 +78,18 @@ describe('moneyTone', () => {
|
||||
|
||||
describe('eventTypeTone', () => {
|
||||
it('maps each event type to a stable tone', () => {
|
||||
expect(eventTypeTone('dividend')).toBeTruthy()
|
||||
expect(eventTypeTone('coupon')).toBeTruthy()
|
||||
expect(eventTypeTone('maturity')).toBeTruthy()
|
||||
expect(eventTypeTone('offer')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('returns success for dividend events', () => {
|
||||
expect(eventTypeTone('dividend')).toBe('success')
|
||||
expect(eventTypeTone('coupon')).toBe('info')
|
||||
expect(eventTypeTone('maturity')).toBe('warning')
|
||||
expect(eventTypeTone('offer')).toBe('neutral')
|
||||
})
|
||||
})
|
||||
|
||||
describe('incomeTypeTone', () => {
|
||||
it('returns a tone for each supported label', () => {
|
||||
expect(incomeTypeTone('Дивиденд')).toBeTruthy()
|
||||
expect(incomeTypeTone('Дивиденд (внешний)')).toBeTruthy()
|
||||
expect(incomeTypeTone('Купон')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('marks plain dividends as success', () => {
|
||||
it('maps each income label to a stable tone', () => {
|
||||
expect(incomeTypeTone('Дивиденд')).toBe('success')
|
||||
expect(incomeTypeTone('Дивиденд (внешний)')).toBe('info')
|
||||
expect(incomeTypeTone('Купон')).toBe('warning')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import type { BrokerEventItem, BrokerMoney } from '@/shared/api'
|
||||
import { formatBrokerCurrencyValue } from '@/shared/lib/formatters'
|
||||
import type { DashboardIncomeTypeLabel } from './dashboardIncome'
|
||||
|
||||
export type MoneyTone = 'positive' | 'negative' | 'planned' | 'neutral'
|
||||
|
||||
@ -17,11 +19,22 @@ export function moneyTone(value: number | null | undefined, source?: MoneySource
|
||||
|
||||
export function formatDashboardCurrency(money: DashboardMoneyLike | null | undefined): string {
|
||||
if (!money) return '—'
|
||||
const value = new Intl.NumberFormat('ru-RU', {
|
||||
try {
|
||||
const formatted = formatBrokerCurrencyValue(money.currency, money.value)
|
||||
if (formatted.includes('¤')) {
|
||||
return formatCurrencyCodeFallback(money.value, money.currency)
|
||||
}
|
||||
return formatted
|
||||
} catch {
|
||||
return formatCurrencyCodeFallback(money.value, money.currency)
|
||||
}
|
||||
}
|
||||
|
||||
function formatCurrencyCodeFallback(value: number, currency: string): string {
|
||||
const numberPart = new Intl.NumberFormat('ru-RU', {
|
||||
maximumFractionDigits: 2,
|
||||
}).format(money.value)
|
||||
if (money.currency === 'RUB') return `${value}\u00a0₽`
|
||||
return `${value}\u00a0${money.currency}`
|
||||
}).format(value)
|
||||
return `${numberPart}\u00a0${currency}`
|
||||
}
|
||||
|
||||
export function eventTypeTone(type: BrokerEventItem['type']): TypeTone {
|
||||
@ -37,9 +50,7 @@ export function eventTypeTone(type: BrokerEventItem['type']): TypeTone {
|
||||
}
|
||||
}
|
||||
|
||||
type IncomeTypeLabel = 'Дивиденд' | 'Дивиденд (внешний)' | 'Купон'
|
||||
|
||||
export function incomeTypeTone(label: IncomeTypeLabel): TypeTone {
|
||||
export function incomeTypeTone(label: DashboardIncomeTypeLabel): TypeTone {
|
||||
switch (label) {
|
||||
case 'Дивиденд':
|
||||
return 'success'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user