refactor(frontend): tighten dashboard visual helpers per code review

This commit is contained in:
Sergey Krylov 2026-06-27 12:57:03 +03:00
parent af0aaeda9d
commit 1a2937ad58
3 changed files with 36 additions and 33 deletions

View File

@ -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()
}

View File

@ -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')
})
})

View File

@ -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'