@@ -2,6 +2,7 @@ import React from 'react';
22import type { ResultData , TaxSettings , Message , FormData } from '../types' ;
33import { formatCurrency } from '../utils' ;
44import { calculateStateTax , getStandardDeduction , hasIncomeTax } from '../stateTaxData' ;
5+ import { getFilingRequirement , isFilingRequired } from '../nonresidentFilingRequirements' ;
56import { CloudDownloadIcon } from './Icons' ;
67import { IncomeAllocationCalendar } from './IncomeAllocationCalendar' ;
78
@@ -112,15 +113,19 @@ const generatePDF = (results: ResultData[] | null, mnSettings: TaxSettings, form
112113 return a . localeCompare ( b ) ;
113114 } ) ;
114115
115- let primaryStateTax = null ;
116- if ( stateTotals [ primaryState ] && hasIncomeTax ( primaryState ) ) {
117- const { tax } = calculateStateTax (
118- stateTotals [ primaryState ] . total ,
119- primaryState ,
120- mnSettings . deductionType ,
121- Number ( mnSettings . itemizedDeduction || 0 )
122- ) ;
123- primaryStateTax = tax ;
116+ // Calculate tax for all states
117+ const stateTaxes : Record < string , number > = { } ;
118+ for ( const state in stateTotals ) {
119+ if ( hasIncomeTax ( state ) && stateTotals [ state ] . total > 0 ) {
120+ const { tax } = calculateStateTax (
121+ stateTotals [ state ] . total ,
122+ state ,
123+ state === primaryState ? mnSettings . deductionType : 'standard' ,
124+ state === primaryState ? Number ( mnSettings . itemizedDeduction || 0 ) : 0 ,
125+ mnSettings . filingStatus
126+ ) ;
127+ stateTaxes [ state ] = tax ;
128+ }
124129 }
125130
126131 // Generate calendar HTML for PDF
@@ -356,18 +361,49 @@ const generatePDF = (results: ResultData[] | null, mnSettings: TaxSettings, form
356361 </div>
357362 </div>
358363
359- ${ isPrimary && primaryStateTax !== null && hasIncomeTax ( state ) ? `
364+ ${ stateTaxes [ state ] !== undefined && stateTaxes [ state ] > 0 ? `
360365 <div class="tax-info">
361- <p class="tax-owed">Estimated ${ state } Income Tax Owed: ${ formatCurrency ( primaryStateTax ) } </p>
366+ <p class="tax-owed">Estimated ${ state } Income Tax Owed: ${ formatCurrency ( stateTaxes [ state ] ) } </p>
362367 </div>
363368 ` : '' }
364369
365- ${ ! isPrimary && hasIncomeTax ( state ) && total > getStandardDeduction ( state ) ? `
370+ ${ ! isPrimary && hasIncomeTax ( state ) && total > getStandardDeduction ( state ) && getStandardDeduction ( state ) > 0 ? `
366371 <div class="warning">
367372 ⚠️ Income exceeds ${ state } standard deduction (${ formatCurrency ( getStandardDeduction ( state ) ) } ).
368373 You may owe taxes in ${ state } . Consult a tax professional.
369374 </div>
370375 ` : '' }
376+
377+ ${ ( ( ) => {
378+ const filingReq = getFilingRequirement ( state ) ;
379+ const requiresFiling = filingReq ? isFilingRequired ( state , total , days ) : false ;
380+
381+ if ( ! filingReq ) return '' ;
382+
383+ const badgeColor = requiresFiling
384+ ? '#dc2626'
385+ : filingReq . requiresReturn
386+ ? '#f59e0b'
387+ : '#059669' ;
388+
389+ const badgeText = requiresFiling
390+ ? 'YES'
391+ : filingReq . requiresReturn
392+ ? 'MAYBE'
393+ : 'NO' ;
394+
395+ return `
396+ <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #d1d5db; font-size: 14px;">
397+ <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;">
398+ <span style="font-weight: 500; color: #374151;">Nonresident Return Required:</span>
399+ <span style="background: ${ badgeColor } ; color: white; padding: 2px 6px; border-radius: 4px; font-size: 12px; font-weight: 500;">
400+ ${ badgeText }
401+ </span>
402+ </div>
403+ <p style="color: #6b7280; font-size: 12px; margin: 0;">${ filingReq . description } </p>
404+ </div>
405+ ` ;
406+ } ) ( ) }
371407 </div>
372408 ` ;
373409 } ) . join ( '' ) }
@@ -557,6 +593,41 @@ export const ResultsPanel: React.FC<ResultsPanelProps> = ({
557593 </ p >
558594 </ div >
559595 ) }
596+
597+ { /* Nonresident Filing Requirement */ }
598+ { ( ( ) => {
599+ const filingReq = getFilingRequirement ( state ) ;
600+ const requiresFiling = filingReq ? isFilingRequired ( state , total , days ) : false ;
601+
602+ if ( ! filingReq ) return null ;
603+
604+ return (
605+ < div className = "mt-3 pt-3 border-t border-zinc-200 dark:border-zinc-700" >
606+ < div className = "flex items-center justify-between" >
607+ < span className = "text-sm font-medium text-zinc-700 dark:text-zinc-300" >
608+ Nonresident Return Required:
609+ </ span >
610+ < span className = { `badge ${
611+ requiresFiling
612+ ? 'badge-red'
613+ : filingReq . requiresReturn
614+ ? 'badge-yellow'
615+ : 'badge-green'
616+ } `} >
617+ { requiresFiling
618+ ? 'YES'
619+ : filingReq . requiresReturn
620+ ? 'MAYBE'
621+ : 'NO'
622+ }
623+ </ span >
624+ </ div >
625+ < p className = "form-description mt-1 text-xs" >
626+ { filingReq . description }
627+ </ p >
628+ </ div >
629+ ) ;
630+ } ) ( ) }
560631 </ div >
561632 </ div >
562633 ) ;
0 commit comments