refactor(frontend): polish dashboard tables per code review

- Drop unused `letterSpacing: 0.2` from TH_SX in both table cards
  (HTML mockup has no letter-spacing on headers)
- Move `eventStatusTone` from EventsCard to dashboardVisual.ts
  for symmetry with `eventTypeTone` (single source of tone semantics)
- Drop unused `columnWidths` prop and `widthsFor` override branch
  in BrokerDashboardTableSkeleton (no caller passes it)
- Drop redundant `role="presentation"` on skeleton wrapper
  (rows already carry `aria-hidden="true"`)
- Drop unused `TypeTone` import from EventsCard after moving
  eventStatusTone out
This commit is contained in:
Sergey Krylov 2026-06-27 13:39:23 +03:00
parent 94f8bb876d
commit 27fb6e77be
4 changed files with 10 additions and 15 deletions

View File

@ -73,6 +73,10 @@ export function incomeTypeTone(label: DashboardIncomeTypeLabel): TypeTone {
} }
} }
export function eventStatusTone(source: BrokerEventItem['source']): TypeTone {
return source === 'actual' ? 'success' : 'neutral'
}
function nonEmpty(value: string | null | undefined): string | null { function nonEmpty(value: string | null | undefined): string | null {
return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null
} }

View File

@ -6,6 +6,7 @@ import { formatBrokerDate } from '@/shared/lib/formatters'
import type { DashboardDatePreset, DashboardEventType } from '../lib/dashboardFilters' import type { DashboardDatePreset, DashboardEventType } from '../lib/dashboardFilters'
import { eventStatusLabel, eventTypeLabel } from '../lib/dashboardFormatters' import { eventStatusLabel, eventTypeLabel } from '../lib/dashboardFormatters'
import { import {
eventStatusTone,
eventTypeTone, eventTypeTone,
formatDashboardCurrency, formatDashboardCurrency,
instrumentDisplay, instrumentDisplay,
@ -39,7 +40,6 @@ const TH_SX = {
color: 'text.secondary', color: 'text.secondary',
fontWeight: 600, fontWeight: 600,
fontSize: 12, fontSize: 12,
letterSpacing: 0.2,
textTransform: 'uppercase' as const, textTransform: 'uppercase' as const,
whiteSpace: 'nowrap' as const, whiteSpace: 'nowrap' as const,
} }
@ -86,10 +86,6 @@ type BrokerDashboardEventsCardProps = {
canGoForward: boolean canGoForward: boolean
} }
function eventStatusTone(event: BrokerEventItem): TypeTone {
return event.source === 'actual' ? 'success' : 'neutral'
}
function eventAmountValue(event: BrokerEventItem): number | null { function eventAmountValue(event: BrokerEventItem): number | null {
return event.source === 'actual' ? event.actualAmount : event.estimatedAmount return event.source === 'actual' ? event.actualAmount : event.estimatedAmount
} }
@ -254,7 +250,7 @@ export function BrokerDashboardEventsCard({
<Box component="td" sx={TD_SX_RIGHT}> <Box component="td" sx={TD_SX_RIGHT}>
<Chip <Chip
label={eventStatusLabel(event)} label={eventStatusLabel(event)}
tone={eventStatusTone(event)} tone={eventStatusTone(event.source)}
selected={false} selected={false}
/> />
</Box> </Box>

View File

@ -34,7 +34,6 @@ const TH_SX = {
color: 'text.secondary', color: 'text.secondary',
fontWeight: 600, fontWeight: 600,
fontSize: 12, fontSize: 12,
letterSpacing: 0.2,
textTransform: 'uppercase' as const, textTransform: 'uppercase' as const,
whiteSpace: 'nowrap' as const, whiteSpace: 'nowrap' as const,
} }

View File

@ -1,12 +1,11 @@
import { Skeleton } from '@moex-vibe/design-system' import { Skeleton } from '@moex-vibe/design-system'
import { Box } from '@mui/material' import { Box } from '@mui/material'
type ColumnWidth = number | string type ColumnWidth = string
type BrokerDashboardTableSkeletonProps = { type BrokerDashboardTableSkeletonProps = {
rows?: number rows?: number
columns?: number columns?: number
columnWidths?: ColumnWidth[]
} }
const DEFAULT_EVENT_WIDTHS: ColumnWidth[] = ['14%', '32%', '18%', '18%', '18%'] const DEFAULT_EVENT_WIDTHS: ColumnWidth[] = ['14%', '32%', '18%', '18%', '18%']
@ -21,8 +20,7 @@ const EVENT_ROW_VARIANTS: Array<'short' | 'long' | 'full'> = [
] ]
const INCOME_ROW_VARIANTS: Array<'short' | 'long' | 'full'> = ['short', 'long', 'medium', 'short'] const INCOME_ROW_VARIANTS: Array<'short' | 'long' | 'full'> = ['short', 'long', 'medium', 'short']
function widthsFor(columns: number, override?: ColumnWidth[]): ColumnWidth[] { function widthsFor(columns: number): ColumnWidth[] {
if (override && override.length === columns) return override
if (columns === 4) return DEFAULT_INCOME_WIDTHS if (columns === 4) return DEFAULT_INCOME_WIDTHS
if (columns === 5) return DEFAULT_EVENT_WIDTHS if (columns === 5) return DEFAULT_EVENT_WIDTHS
return Array.from({ length: columns }, () => '100%') return Array.from({ length: columns }, () => '100%')
@ -36,16 +34,15 @@ function rowVariantsFor(columns: number): Array<'short' | 'long' | 'full' | 'med
export function BrokerDashboardTableSkeleton({ export function BrokerDashboardTableSkeleton({
rows = 5, rows = 5,
columns = 5, columns = 5,
columnWidths,
}: BrokerDashboardTableSkeletonProps) { }: BrokerDashboardTableSkeletonProps) {
const widths = widthsFor(columns, columnWidths) const widths = widthsFor(columns)
const variants = rowVariantsFor(columns) const variants = rowVariantsFor(columns)
return ( return (
<Box <Box
sx={{ display: 'grid', gap: 1, py: 1 }} sx={{ display: 'grid', gap: 1, py: 1 }}
data-testid="dashboard-table-skeleton" data-testid="dashboard-table-skeleton"
role="presentation" aria-hidden="true"
> >
{Array.from({ length: rows }, (_, i) => ( {Array.from({ length: rows }, (_, i) => (
<Box <Box
@ -57,7 +54,6 @@ export function BrokerDashboardTableSkeleton({
minHeight: 38, minHeight: 38,
py: 0.5, py: 0.5,
}} }}
aria-hidden="true"
> >
{widths.map((width, j) => ( {widths.map((width, j) => (
<Box key={j} sx={{ flex: `0 0 ${width}`, minWidth: 0 }}> <Box key={j} sx={{ flex: `0 0 ${width}`, minWidth: 0 }}>