@@ -12,15 +12,68 @@ function unitLabel(phase: Phase): string {
1212 return phase . kind === "aqueous" ? "wt%" : "ppm" ;
1313}
1414
15- function ConvertUnitAccordingToPhase ( phase : Phase ) : Record < string , number > {
15+ function convertUnitAccordingToPhase ( phase : Phase ) : Record < string , number > {
1616 if ( phase . kind === "aqueous" ) {
1717 return ppmMolToWeightPercent ( phase . concentrations ) ;
1818 }
1919 return phase . concentrations ;
2020}
2121
22+ function phaseLabel ( phase : Phase ) : string {
23+ return phase . kind === "aqueous" ? "Aqueous" : "CO2-rich" ;
24+ }
25+
26+ function sortPhases ( phases : Phase [ ] ) : Phase [ ] {
27+ return [ ...phases ] . sort ( ( a , b ) => {
28+ if ( a . kind === "co2-rich" && b . kind === "aqueous" ) return - 1 ;
29+ if ( a . kind === "aqueous" && b . kind === "co2-rich" ) return 1 ;
30+ return 0 ;
31+ } ) ;
32+ }
33+
34+ interface PhaseGroup {
35+ label : string ;
36+ phases : Phase [ ] ;
37+ displayData : Record < string , number > [ ] ;
38+ showTotal : boolean ;
39+ colSpan : number ;
40+ }
41+
42+ function buildPhaseGroup ( label : string , phases : Phase [ ] ) : PhaseGroup {
43+ const sorted = sortPhases ( phases ) ;
44+ const visible = sorted . filter ( ( phase ) => Object . values ( phase . concentrations ) . some ( ( v ) => v > 0 ) ) ;
45+ const showTotal = visible . length > 1 ;
46+ return {
47+ label,
48+ phases : visible ,
49+ displayData : visible . map ( ( phase ) => convertUnitAccordingToPhase ( phase ) ) ,
50+ showTotal,
51+ colSpan : visible . length + ( showTotal ? 1 : 0 ) ,
52+ } ;
53+ }
54+
55+ function phaseColumnHeader ( phase : Phase ) : string {
56+ const fraction = phase . fraction < 1 ? ` (${ formatPhaseFraction ( phase . fraction ) } )` : "" ;
57+ return `${ phaseLabel ( phase ) } [${ unitLabel ( phase ) } ]${ fraction } ` ;
58+ }
59+
60+ function weightedTotal ( phases : Phase [ ] , component : string ) : number {
61+ return phases . reduce ( ( sum , phase ) => sum + ( phase . concentrations [ component ] ?? 0 ) * phase . fraction , 0 ) ;
62+ }
63+
64+ const solidLine = { borderLeft : "2px solid #dcdcdc" } ;
65+
66+ function groupBorderStyle ( groupIndex : number , phaseIndex : number ) : React . CSSProperties | undefined {
67+ return groupIndex > 0 && phaseIndex === 0 ? solidLine : undefined ;
68+ }
69+
2270const PhaseResultTable : React . FC < PhaseResultTableProps > = ( { initialConcentrations, phases } ) => {
23- const phaseDisplayData = phases . map ( ( phase ) => ConvertUnitAccordingToPhase ( phase ) ) ;
71+ const initialPhases : Phase [ ] = [
72+ { kind : "co2-rich" , fraction : 1 , concentrations : initialConcentrations } ,
73+ { kind : "aqueous" , fraction : 0 , concentrations : { } } ,
74+ ] ;
75+
76+ const groups : PhaseGroup [ ] = [ buildPhaseGroup ( "Initial" , initialPhases ) , buildPhaseGroup ( "Final" , phases ) ] ;
2477
2578 const allComponents = Array . from (
2679 new Set ( [
@@ -29,35 +82,64 @@ const PhaseResultTable: React.FC<PhaseResultTableProps> = ({ initialConcentratio
2982 ] )
3083 ) ;
3184
32- const visibleComponents = allComponents . filter ( ( key ) => {
33- const init = initialConcentrations [ key ] ?? 0 ;
34- const hasSignificantPhaseValue = phases . some ( ( phase ) => ( phase . concentrations [ key ] ?? 0 ) >= 0.001 ) ;
35- return init >= 0.001 || hasSignificantPhaseValue ;
85+ const visibleComponents = allComponents . filter ( ( component ) => {
86+ return groups . some ( ( group ) => group . phases . some ( ( phase ) => ( phase . concentrations [ component ] ?? 0 ) >= 0.001 ) ) ;
3687 } ) ;
3788
3889 return (
3990 < Table >
4091 < Table . Head >
4192 < Table . Row >
42- < Table . Cell > Component</ Table . Cell >
43- < Table . Cell > Initial [ppm]</ Table . Cell >
44- { phases . map ( ( phase ) => (
45- < Table . Cell key = { phase . kind } >
46- { phase . kind } [{ unitLabel ( phase ) } ] ({ formatPhaseFraction ( phase . fraction ) } )
93+ < Table . Cell rowSpan = { 2 } > Component</ Table . Cell >
94+ { groups . map ( ( group , groupIndex ) => (
95+ < Table . Cell
96+ key = { group . label }
97+ colSpan = { group . colSpan }
98+ style = { { textAlign : "center" , ...( groupIndex > 0 ? solidLine : { } ) } }
99+ >
100+ { group . label }
47101 </ Table . Cell >
48102 ) ) }
49103 </ Table . Row >
104+ < Table . Row >
105+ { groups . flatMap ( ( group , groupIndex ) => {
106+ const cells = group . phases . map ( ( phase , phaseIndex ) => (
107+ < Table . Cell
108+ key = { `${ group . label } -${ phase . kind } ` }
109+ style = { groupBorderStyle ( groupIndex , phaseIndex ) }
110+ >
111+ { phaseColumnHeader ( phase ) }
112+ </ Table . Cell >
113+ ) ) ;
114+ if ( group . showTotal ) {
115+ cells . push ( < Table . Cell key = { `${ group . label } -total` } > Total [ppm]</ Table . Cell > ) ;
116+ }
117+ return cells ;
118+ } ) }
119+ </ Table . Row >
50120 </ Table . Head >
51121 < Table . Body >
52- { visibleComponents . map ( ( key ) => (
53- < Table . Row key = { key } >
54- < Table . Cell > { key } </ Table . Cell >
55- < Table . Cell > { formatConcentration ( initialConcentrations [ key ] ?? 0 ) } </ Table . Cell >
56- { phaseDisplayData . map ( ( concentrations , idx ) => (
57- < Table . Cell key = { phases [ idx ] . kind } >
58- { formatConcentration ( concentrations [ key ] ?? 0 ) }
59- </ Table . Cell >
60- ) ) }
122+ { visibleComponents . map ( ( component ) => (
123+ < Table . Row key = { component } >
124+ < Table . Cell > { component } </ Table . Cell >
125+ { groups . flatMap ( ( group , groupIndex ) => {
126+ const cells = group . displayData . map ( ( concentrations , phaseIndex ) => (
127+ < Table . Cell
128+ key = { `${ group . label } -${ group . phases [ phaseIndex ] . kind } ` }
129+ style = { groupBorderStyle ( groupIndex , phaseIndex ) }
130+ >
131+ { formatConcentration ( concentrations [ component ] ?? 0 ) }
132+ </ Table . Cell >
133+ ) ) ;
134+ if ( group . showTotal ) {
135+ cells . push (
136+ < Table . Cell key = { `${ group . label } -total` } >
137+ { formatConcentration ( weightedTotal ( group . phases , component ) ) }
138+ </ Table . Cell >
139+ ) ;
140+ }
141+ return cells ;
142+ } ) }
61143 </ Table . Row >
62144 ) ) }
63145 </ Table . Body >
0 commit comments