@@ -85,9 +85,18 @@ export function AttackResults({ result, onDiscuss }: AttackResultsProps) {
8585 const [ isExportingGDocs , setIsExportingGDocs ] = useState ( false ) ;
8686 const [ showDriveAuth , setShowDriveAuth ] = useState ( false ) ;
8787
88- const criticalCount = result . weaknesses . filter ( w => w . severity === 'critical' ) . length ;
89- const majorCount = result . weaknesses . filter ( w => w . severity === 'major' ) . length ;
90- const minorCount = result . weaknesses . filter ( w => w . severity === 'minor' ) . length ;
88+ // Guard against malformed/legacy persisted results so navigating back to
89+ // this page renders an empty state instead of crashing the route.
90+ const weaknesses = Array . isArray ( result ?. weaknesses ) ? result . weaknesses : [ ] ;
91+ const fallaciesDetected = Array . isArray ( result ?. fallaciesDetected ) ? result . fallaciesDetected : [ ] ;
92+ const crossExQuestions = Array . isArray ( result ?. crossExQuestions ) ? result . crossExQuestions : [ ] ;
93+ const overallAssessment = result ?. overallAssessment ?? { summary : '' , score : 0 , strengthAreas : [ ] } ;
94+ const strengthAreas = Array . isArray ( overallAssessment . strengthAreas ) ? overallAssessment . strengthAreas : [ ] ;
95+ const weighingAnalysis = result ?. weighingAnalysis ;
96+
97+ const criticalCount = weaknesses . filter ( w => w . severity === 'critical' ) . length ;
98+ const majorCount = weaknesses . filter ( w => w . severity === 'major' ) . length ;
99+ const minorCount = weaknesses . filter ( w => w . severity === 'minor' ) . length ;
91100
92101 const handleDocxExport = async ( ) => {
93102 const success = await exportAttackToDocx ( result ) ;
@@ -128,22 +137,22 @@ export function AttackResults({ result, onDiscuss }: AttackResultsProps) {
128137 { /* Overall Assessment */ }
129138 < SectionCard
130139 title = { t ( 'attackResults.overall' ) }
131- description = { result . overallAssessment . summary }
140+ description = { overallAssessment . summary }
132141 >
133142 < div className = "space-y-4" >
134143 < div >
135144 < div className = "flex items-center justify-between mb-2" >
136145 < span className = "text-sm font-medium text-foreground" > { t ( 'attackResults.caseStrength' ) } </ span >
137146 < span className = { cn (
138147 'text-lg font-bold' ,
139- result . overallAssessment . score >= 70 ? 'text-primary' :
140- result . overallAssessment . score >= 50 ? 'text-amber-500' : 'text-destructive'
148+ overallAssessment . score >= 70 ? 'text-primary' :
149+ overallAssessment . score >= 50 ? 'text-amber-500' : 'text-destructive'
141150 ) } >
142- { result . overallAssessment . score } /100
151+ { overallAssessment . score } /100
143152 </ span >
144153 </ div >
145154 < Progress
146- value = { result . overallAssessment . score }
155+ value = { overallAssessment . score }
147156 className = "h-3"
148157 />
149158 < div className = "flex flex-wrap items-center justify-end gap-2 mt-3" >
@@ -199,9 +208,9 @@ export function AttackResults({ result, onDiscuss }: AttackResultsProps) {
199208 < div >
200209 < h4 className = "text-sm font-medium text-muted-foreground mb-2" > { t ( 'attackResults.strengths' ) } </ h4 >
201210 < ul className = "space-y-1" >
202- { result . overallAssessment . strengthAreas . map ( ( strength , i ) => (
203- < li key = { i } className = "flex items-start gap-2 text-sm" >
204- < span className = "text-primary mt-1 " > ✓</ span >
211+ { strengthAreas . map ( ( strength , i ) => (
212+ < li key = { i } className = "flex items-baseline gap-2 text-sm" >
213+ < span className = "text-primary leading-none " > ✓</ span >
205214 < span className = "text-foreground" > { strength } </ span >
206215 </ li >
207216 ) ) }
@@ -213,26 +222,26 @@ export function AttackResults({ result, onDiscuss }: AttackResultsProps) {
213222 { /* Weaknesses */ }
214223 < SectionCard
215224 title = { t ( 'attackResults.weaknesses' ) }
216- description = { `${ result . weaknesses . length } ${ t ( 'attackResults.weaknessesCount' ) } `
225+ description = { `${ weaknesses . length } ${ t ( 'attackResults.weaknessesCount' ) } `
217226 }
218227 icon = { < AlertCircle className = "h-5 w-5" /> }
219228 >
220229 < div className = "space-y-4" >
221- { result . weaknesses . map ( ( weakness ) => (
230+ { weaknesses . map ( ( weakness ) => (
222231 < WeaknessCard key = { weakness . id } weakness = { weakness } />
223232 ) ) }
224233 </ div >
225234 </ SectionCard >
226235
227236 { /* Fallacies */ }
228237 {
229- result . fallaciesDetected . length > 0 && (
238+ fallaciesDetected . length > 0 && (
230239 < SectionCard
231240 title = { t ( 'attackResults.fallacies' ) }
232241 description = { t ( 'attackResults.fallaciesDesc' ) }
233242 >
234243 < div className = "space-y-3" >
235- { result . fallaciesDetected . map ( ( fallacy , i ) => (
244+ { fallaciesDetected . map ( ( fallacy , i ) => (
236245 < div key = { i } className = "rounded-lg border border-border p-3" >
237246 < div className = "flex items-center gap-2 mb-1" >
238247 < Badge variant = "destructive" > { fallacy . name } </ Badge >
@@ -253,7 +262,7 @@ export function AttackResults({ result, onDiscuss }: AttackResultsProps) {
253262 icon = { < MessageSquare className = "h-5 w-5" /> }
254263 >
255264 < div className = "space-y-4" >
256- { result . crossExQuestions . map ( ( q , i ) => (
265+ { crossExQuestions . map ( ( q , i ) => (
257266 < div key = { i } className = "rounded-lg border border-border p-4" >
258267 < p className = "font-medium text-foreground mb-2" > "{ q . question } "</ p >
259268 < div className = "grid gap-2 text-sm" >
@@ -272,42 +281,44 @@ export function AttackResults({ result, onDiscuss }: AttackResultsProps) {
272281 </ SectionCard >
273282
274283 { /* Weighing Analysis */ }
275- < SectionCard
276- title = { t ( 'attackResults.weighing' ) }
277- description = { t ( 'attackResults.weighingDesc' ) }
278- icon = { < Scale className = "h-5 w-5" /> }
279- >
280- < div className = "space-y-4" >
281- < div >
282- < h4 className = "text-sm font-medium text-muted-foreground mb-1" > { t ( 'attackResults.currentWeighing' ) } </ h4 >
283- < p className = "text-foreground" > { result . weighingAnalysis . currentWeighing } </ p >
284- </ div >
285- < Separator />
286- < div >
287- < h4 className = "text-sm font-medium text-muted-foreground mb-2" > { t ( 'attackResults.missingComparisons' ) } </ h4 >
288- < ul className = "space-y-1" >
289- { result . weighingAnalysis . missingComparisons . map ( ( comparison , i ) => (
290- < li key = { i } className = "flex items-start gap-2 text-sm" >
291- < span className = "text-destructive mt-1" > •</ span >
292- < span className = "text-foreground" > { comparison } </ span >
293- </ li >
294- ) ) }
295- </ ul >
296- </ div >
297- < Separator />
298- < div >
299- < h4 className = "text-sm font-medium text-muted-foreground mb-2" > { t ( 'attackResults.improvements' ) } </ h4 >
300- < ul className = "space-y-1" >
301- { result . weighingAnalysis . improvementSuggestions . map ( ( suggestion , i ) => (
302- < li key = { i } className = "flex items-start gap-2 text-sm" >
303- < span className = "text-primary mt-1" > →</ span >
304- < span className = "text-foreground" > { suggestion } </ span >
305- </ li >
306- ) ) }
307- </ ul >
284+ { weighingAnalysis && (
285+ < SectionCard
286+ title = { t ( 'attackResults.weighing' ) }
287+ description = { t ( 'attackResults.weighingDesc' ) }
288+ icon = { < Scale className = "h-5 w-5" /> }
289+ >
290+ < div className = "space-y-4" >
291+ < div >
292+ < h4 className = "text-sm font-medium text-muted-foreground mb-1" > { t ( 'attackResults.currentWeighing' ) } </ h4 >
293+ < p className = "text-foreground" > { weighingAnalysis . currentWeighing } </ p >
294+ </ div >
295+ < Separator />
296+ < div >
297+ < h4 className = "text-sm font-medium text-muted-foreground mb-2" > { t ( 'attackResults.missingComparisons' ) } </ h4 >
298+ < ul className = "space-y-1" >
299+ { ( weighingAnalysis . missingComparisons ?? [ ] ) . map ( ( comparison , i ) => (
300+ < li key = { i } className = "flex items-start gap-2 text-sm" >
301+ < span className = "text-destructive mt-1" > •</ span >
302+ < span className = "text-foreground" > { comparison } </ span >
303+ </ li >
304+ ) ) }
305+ </ ul >
306+ </ div >
307+ < Separator />
308+ < div >
309+ < h4 className = "text-sm font-medium text-muted-foreground mb-2" > { t ( 'attackResults.improvements' ) } </ h4 >
310+ < ul className = "space-y-1" >
311+ { ( weighingAnalysis . improvementSuggestions ?? [ ] ) . map ( ( suggestion , i ) => (
312+ < li key = { i } className = "flex items-start gap-2 text-sm" >
313+ < span className = "text-primary mt-1" > →</ span >
314+ < span className = "text-foreground" > { suggestion } </ span >
315+ </ li >
316+ ) ) }
317+ </ ul >
318+ </ div >
308319 </ div >
309- </ div >
310- </ SectionCard >
320+ </ SectionCard >
321+ ) }
311322 </ StaggeredContainer >
312323 ) ;
313324}
0 commit comments