11import { PageLayout } from '../components/layout/PageLayout' ;
22import { ConnectedMarketValueChart } from '../components/charts/ConnectedMarketValueChart' ;
33import { ConnectedIndustryBreakdownChart } from '../components/charts/ConnectedIndustryBreakdownChart' ;
4+ < < << << < HEAD
45import { PendingIngestionsBox } from '../components/portfolio/PendingIngestionsBox' ;
6+ = === ===
7+ import { TasksBox , Task } from '../components/portfolio/TasksBox' ;
8+ > >>> >>> main
59import { LoanRepositoryTable } from '../components/loans/LoanRepositoryTable' ;
610import { LoanDetailModal } from '../components/loans/LoanDetailModal' ;
711import { DealUploadModal } from '../components/deals/DealUploadModal' ;
@@ -26,7 +30,7 @@ import { Upload, Building2, FileText, Sparkles, RefreshCw, CheckCircle, X, Loade
2630import { useState , useEffect } from 'react' ;
2731import { User } from '../../shared/types' ;
2832import { useCompany } from '../contexts/CompanyContext' ;
29- import { getCompanyDeals , transformDealToLoanData , metricsApi , ingestionApi } from '../utils/api' ;
33+ import { getCompanyDeals , transformDealToLoanData , metricsApi , ingestionApi , collateralApi } from '../utils/api' ;
3034import { dealApi } from '../../shared/lib/api' ;
3135import { useToast } from '../components/ui/use-toast' ;
3236import { useExtractionDealCreation } from '../hooks/useExtractionDealCreation' ;
@@ -71,6 +75,8 @@ export default function PortfolioPage() {
7175 const [ csvMappingDocument , setCsvMappingDocument ] = useState < any | null > ( null ) ;
7276 const [ dealToDelete , setDealToDelete ] = useState < LoanData | null > ( null ) ;
7377 const [ isDeleting , setIsDeleting ] = useState ( false ) ;
78+ const [ detectedTasks , setDetectedTasks ] = useState < Task [ ] > ( [ ] ) ;
79+ const [ isCheckingCollateral , setIsCheckingCollateral ] = useState ( false ) ;
7480 const { selectedCompany, userCompanies, isLoadingCompanies } = useCompany ( ) ;
7581 const { toast } = useToast ( ) ;
7682
@@ -423,6 +429,9 @@ export default function PortfolioPage() {
423429 if ( transformedLoans . length > 0 ) {
424430 console . log ( `📈 Portfolio updated with ${ transformedLoans . length } deals for ${ selectedCompany . company_name } ` ) ;
425431 }
432+
433+ // Run collateral detection in the background
434+ detectDoublePledgedCollateral ( transformedLoans ) ;
426435 } catch ( error ) {
427436 console . error ( '❌ Error loading company deals:' , error ) ;
428437
@@ -447,6 +456,56 @@ export default function PortfolioPage() {
447456 loadCompanyDeals ( page ) ;
448457 } ;
449458
459+ // Detect double-pledged collateral and create tasks
460+ const detectDoublePledgedCollateral = async ( loans : LoanData [ ] ) => {
461+ // Filter loans that have collateral
462+ const loansWithCollateral = loans . filter ( loan => loan . collateral_id ) ;
463+
464+ if ( loansWithCollateral . length === 0 ) {
465+ console . log ( '[detectDoublePledgedCollateral] No loans with collateral found' ) ;
466+ setDetectedTasks ( [ ] ) ;
467+ return ;
468+ }
469+
470+ console . log ( `[detectDoublePledgedCollateral] Checking ${ loansWithCollateral . length } loans for double-pledged collateral` ) ;
471+ setIsCheckingCollateral ( true ) ;
472+
473+ try {
474+ // Fetch collateral data for all loans with collateral
475+ const collateralPromises = loansWithCollateral . map ( async ( loan ) => {
476+ try {
477+ const collateralData = await collateralApi . getCollateral ( loan . collateral_id ! ) ;
478+ return { loan, collateralData } ;
479+ } catch ( error : any ) {
480+ console . warn ( `[detectDoublePledgedCollateral] Failed to fetch collateral for loan ${ loan . id } :` , error ) ;
481+ return { loan, collateralData : null } ;
482+ }
483+ } ) ;
484+
485+ const results = await Promise . all ( collateralPromises ) ;
486+
487+ // Create tasks for loans with double-pledged collateral
488+ const tasks : Task [ ] = results
489+ . filter ( ( { collateralData } ) => collateralData ?. double_pledged )
490+ . map ( ( { loan, collateralData } ) => ( {
491+ id : `double-pledge-${ loan . id } ` ,
492+ title : 'Review Double Pledged Collateral' ,
493+ description : `Deal "${ loan . title } " has collateral pledged to another deal (ID: ${ collateralData ! . double_pledged ! . slice ( 0 , 8 ) } ...)` ,
494+ priority : 'high' as const ,
495+ type : 'collateral_risk' as const ,
496+ loanId : loan . id ,
497+ } ) ) ;
498+
499+ console . log ( `[detectDoublePledgedCollateral] Found ${ tasks . length } double-pledged collateral issues` ) ;
500+ setDetectedTasks ( tasks ) ;
501+ } catch ( error ) {
502+ console . error ( '[detectDoublePledgedCollateral] Error during detection:' , error ) ;
503+ setDetectedTasks ( [ ] ) ;
504+ } finally {
505+ setIsCheckingCollateral ( false ) ;
506+ }
507+ } ;
508+
450509 const handleLoanClick = ( loan : LoanData ) => {
451510 setSelectedLoan ( loan ) ;
452511 setIsModalOpen ( true ) ;
@@ -828,12 +887,27 @@ export default function PortfolioPage() {
828887 timeRange = "all_time"
829888 />
830889
890+ < < << << < HEAD
831891 { /* Pending Ingestions Box */ }
832892 < PendingIngestionsBox
833893 documents = { pendingDocuments }
834894 isLoading = { isLoadingPending }
835895 onRefresh = { loadPendingDocuments }
836896 onReview = { handleReviewDocument }
897+ = === ===
898+ { /* Tasks Box */ }
899+ < TasksBox
900+ tasks = { detectedTasks }
901+ onTaskClick = { ( task ) => {
902+ console . log ( 'Task clicked:' , task ) ;
903+ if ( task . loanId ) {
904+ const loan = userLoans . find ( l => l . id === task . loanId ) ;
905+ if ( loan ) {
906+ handleLoanClick ( loan ) ;
907+ }
908+ }
909+ } }
910+ > >>> >>> main
837911 / >
838912 </ div >
839913
0 commit comments