@@ -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,66 @@ 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 ) =>
87+ group . phases . some ( ( phase ) => ( phase . concentrations [ component ] ?? 0 ) >= 0.001 )
88+ ) ;
3689 } ) ;
3790
3891 return (
3992 < Table >
4093 < Table . Head >
4194 < 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 ) } )
95+ < Table . Cell rowSpan = { 2 } > Component</ Table . Cell >
96+ { groups . map ( ( group , groupIndex ) => (
97+ < Table . Cell
98+ key = { group . label }
99+ colSpan = { group . colSpan }
100+ style = { { textAlign : "center" , ...( groupIndex > 0 ? solidLine : { } ) } }
101+ >
102+ { group . label }
47103 </ Table . Cell >
48104 ) ) }
49105 </ Table . Row >
106+ < Table . Row >
107+ { groups . flatMap ( ( group , groupIndex ) => {
108+ const cells = group . phases . map ( ( phase , phaseIndex ) => (
109+ < Table . Cell
110+ key = { `${ group . label } -${ phase . kind } ` }
111+ style = { groupBorderStyle ( groupIndex , phaseIndex ) }
112+ >
113+ { phaseColumnHeader ( phase ) }
114+ </ Table . Cell >
115+ ) ) ;
116+ if ( group . showTotal ) {
117+ cells . push ( < Table . Cell key = { `${ group . label } -total` } > Total [ppm]</ Table . Cell > ) ;
118+ }
119+ return cells ;
120+ } ) }
121+ </ Table . Row >
50122 </ Table . Head >
51123 < 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- ) ) }
124+ { visibleComponents . map ( ( component ) => (
125+ < Table . Row key = { component } >
126+ < Table . Cell > { component } </ Table . Cell >
127+ { groups . flatMap ( ( group , groupIndex ) => {
128+ const cells = group . displayData . map ( ( concentrations , phaseIndex ) => (
129+ < Table . Cell
130+ key = { `${ group . label } -${ group . phases [ phaseIndex ] . kind } ` }
131+ style = { groupBorderStyle ( groupIndex , phaseIndex ) }
132+ >
133+ { formatConcentration ( concentrations [ component ] ?? 0 ) }
134+ </ Table . Cell >
135+ ) ) ;
136+ if ( group . showTotal ) {
137+ cells . push (
138+ < Table . Cell key = { `${ group . label } -total` } >
139+ { formatConcentration ( weightedTotal ( group . phases , component ) ) }
140+ </ Table . Cell >
141+ ) ;
142+ }
143+ return cells ;
144+ } ) }
61145 </ Table . Row >
62146 ) ) }
63147 </ Table . Body >
0 commit comments