@@ -14,7 +14,7 @@ import {
1414 Loading ,
1515} from '@votingworks/ui' ;
1616import { hasSplits } from '@votingworks/types' ;
17- import { format } from '@votingworks/utils' ;
17+ import { format , getLanguageOptions } from '@votingworks/utils' ;
1818import { assert } from '@votingworks/basics' ;
1919
2020import {
@@ -80,6 +80,43 @@ const TableRow = styled.tr`
8080 }
8181` ;
8282
83+ interface ColumnWidths {
84+ precinctName : number ;
85+ attribute : number ;
86+ count : number ;
87+ rightPadding : number ;
88+ }
89+
90+ type AttributeColumnCount = 0 | 1 | 2 ;
91+
92+ // Column width percentages for different numbers of attribute columns.
93+ // precinctName -> precinct name column, adjusts based on number of attribute columns
94+ // attribute -> optional attribute columns (Party, Language)
95+ // count -> three count columns (Total, Precinct, Absentee), fixed width
96+ // rightPadding -> extra padding to make space for the scrollbar, fixed width
97+ const COUNT_COLUMN_WIDTH = 10 ; // Each count column is 10% of the table's width
98+ const RIGHT_PADDING_WIDTH = 2 ; // Right padding to accommodate scrollbar
99+ const COLUMN_WIDTH_MAP : Record < AttributeColumnCount , ColumnWidths > = {
100+ 0 : {
101+ precinctName : 68 , // 100% - COUNT_COLUMN_WIDTH * 3 - RIGHT_PADDING_WIDTH = 68
102+ attribute : 0 ,
103+ count : COUNT_COLUMN_WIDTH ,
104+ rightPadding : RIGHT_PADDING_WIDTH ,
105+ } ,
106+ 1 : {
107+ precinctName : 38 , // 100 - attributeWidth - COUNT_COLUMN_WIDTH * 3 - RIGHT_PADDING_WIDTH = 38
108+ attribute : 30 , // Measured by eye
109+ count : COUNT_COLUMN_WIDTH ,
110+ rightPadding : RIGHT_PADDING_WIDTH ,
111+ } ,
112+ 2 : {
113+ precinctName : 30 , // 100 - attributeWidth * 2 - COUNT_COLUMN_WIDTH * 3 - RIGHT_PADDING_WIDTH = 38
114+ attribute : 19 , // Measured by eye
115+ count : COUNT_COLUMN_WIDTH ,
116+ rightPadding : RIGHT_PADDING_WIDTH ,
117+ } ,
118+ } ;
119+
83120export function ReportScreen ( ) : JSX . Element | null {
84121 const getBallotPrintCountsQuery = getBallotPrintCounts . useQuery ( ) ;
85122 const getElectionRecordQuery = getElectionRecord . useQuery ( ) ;
@@ -112,10 +149,15 @@ export function ReportScreen(): JSX.Element | null {
112149 }
113150
114151 assert ( election !== undefined ) ;
115- const ballotPrintCounts = getBallotPrintCountsQuery . data ;
116152 const hasParties = election . type === 'primary' ;
153+ const showLanguage = getLanguageOptions ( election ) . length > 1 ;
154+ const ballotPrintCounts = getBallotPrintCountsQuery . data ;
117155 const { printer } = getDeviceStatusesQuery . data ;
118156
157+ const attributeColumnCount = ( ( hasParties ? 1 : 0 ) +
158+ ( showLanguage ? 1 : 0 ) ) as AttributeColumnCount ;
159+ const columnWidths = COLUMN_WIDTH_MAP [ attributeColumnCount ] ;
160+
119161 return (
120162 < Container >
121163 < TitleBar
@@ -175,16 +217,28 @@ export function ReportScreen(): JSX.Element | null {
175217 < Table style = { { tableLayout : 'fixed' , width : '100%' } } >
176218 < thead >
177219 < TableRow >
178- < TH style = { { width : hasParties ? '25%' : '35%' } } >
220+ < TH style = { { width : ` ${ columnWidths . precinctName } %` } } >
179221 { electionHasSplits
180222 ? 'Precinct / Split Name'
181223 : 'Precinct Name' }
182224 </ TH >
183- { hasParties && < TH style = { { width : '19%' } } > Party</ TH > }
184- < TH style = { { width : hasParties ? '20%' : '25%' } } > Language</ TH >
185- < TH style = { { width : '12%' } } > Total</ TH >
186- < TH style = { { width : '12%' } } > Precinct</ TH >
187- < TH style = { { width : '12%' } } > Absentee</ TH >
225+ { hasParties && (
226+ < TH style = { { width : `${ columnWidths . attribute } %` } } > Party</ TH >
227+ ) }
228+ { showLanguage && (
229+ < TH style = { { width : `${ columnWidths . attribute } %` } } >
230+ Language
231+ </ TH >
232+ ) }
233+ < TH style = { { width : `${ columnWidths . count } %` } } > Total</ TH >
234+ < TH style = { { width : `${ columnWidths . count } %` } } > Precinct</ TH >
235+ < TH
236+ style = { {
237+ width : `${ columnWidths . count + columnWidths . rightPadding } %` ,
238+ } }
239+ >
240+ Absentee
241+ </ TH >
188242 </ TableRow >
189243 </ thead >
190244 </ Table >
@@ -204,21 +258,37 @@ export function ReportScreen(): JSX.Element | null {
204258 < TableRow
205259 key = { `${ counts . ballotStyleId } -${ counts . precinctOrSplitName } ` }
206260 >
207- < TD style = { { width : hasParties ? '25%' : '35%' } } >
261+ < TD style = { { width : ` ${ columnWidths . precinctName } %` } } >
208262 { counts . precinctOrSplitName }
209263 </ TD >
210264 { hasParties && (
211- < TD style = { { width : '19%' } } > { counts . partyName } </ TD >
265+ < TD style = { { width : `${ columnWidths . attribute } %` } } >
266+ { counts . partyName }
267+ </ TD >
212268 ) }
213- < TD style = { { width : hasParties ? '20%' : '25%' } } >
214- { format . languageDisplayName ( {
215- languageCode : counts . languageCode ,
216- displayLanguageCode : 'en' ,
217- } ) }
269+ { showLanguage && (
270+ < TD style = { { width : `${ columnWidths . attribute } %` } } >
271+ { format . languageDisplayName ( {
272+ languageCode : counts . languageCode ,
273+ displayLanguageCode : 'en' ,
274+ } ) }
275+ </ TD >
276+ ) }
277+ < TD style = { { width : `${ columnWidths . count } %` } } >
278+ { counts . totalCount }
279+ </ TD >
280+ < TD style = { { width : `${ columnWidths . count } %` } } >
281+ { counts . precinctCount }
282+ </ TD >
283+ < TD
284+ style = { {
285+ width : `${
286+ columnWidths . count + columnWidths . rightPadding
287+ } %`,
288+ } }
289+ >
290+ { counts . absenteeCount }
218291 </ TD >
219- < TD style = { { width : '12%' } } > { counts . totalCount } </ TD >
220- < TD style = { { width : '12%' } } > { counts . precinctCount } </ TD >
221- < TD style = { { width : '12%' } } > { counts . absenteeCount } </ TD >
222292 </ TableRow >
223293 ) ) }
224294 </ tbody >
0 commit comments