11
22import React , { useState , useEffect , useCallback } from 'react' ;
33import { useLocation , Link , useNavigate } from 'react-router-dom' ;
4- import { Portfolio , Case , Payment } from '@/api/entities' ;
4+ import { Portfolio , Case , Payment , Vendor } from '@/api/entities' ;
55import { createPageUrl } from '@/utils' ;
66import { Button } from '@/components/ui/button' ;
77import {
@@ -27,6 +27,7 @@ import {
2727 Tooltip as ChartTooltip ,
2828} from 'recharts' ;
2929import { subDays , isAfter } from 'date-fns' ;
30+ import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from '@/components/ui/select' ;
3031
3132const COLORS = [ '#3b82f6' , '#10b981' , '#f59e0b' , '#ef4444' , '#8b5cf6' , '#6b7280' ] ;
3233
@@ -47,6 +48,8 @@ export default function PortfolioDetails() {
4748 const [ casePaymentsMap , setCasePaymentsMap ] = useState ( { } ) ;
4849 const [ portfolioStats , setPortfolioStats ] = useState ( { totalCases : 0 , totalCollected : 0 , collectionRate : 0 , paymentCount : 0 } ) ;
4950 const [ statusDistribution , setStatusDistribution ] = useState ( [ ] ) ;
51+ const [ vendors , setVendors ] = useState ( [ ] ) ;
52+ const [ selectedVendor , setSelectedVendor ] = useState ( 'none' ) ;
5053 const [ isLoading , setIsLoading ] = useState ( true ) ;
5154 const [ filters , setFilters ] = useState ( initialFilters ) ;
5255
@@ -65,22 +68,63 @@ export default function PortfolioDetails() {
6568 const loadPortfolioDetails = async ( id ) => {
6669 setIsLoading ( true ) ;
6770 try {
68- const [ portfolioData , allDebts , allPayments ] = await Promise . all ( [
71+ const [ portfolioData , allDebts , allPayments , vendorList ] = await Promise . all ( [
6972 Portfolio . get ( id ) ,
70- Case . filter ( { portfolio_id : id } ) ,
73+ Case . list ( ) ,
7174 Payment . list ( ) ,
75+ Vendor . list ( )
7276 ] ) ;
77+
78+ console . log ( 'Loading portfolio details for ID:' , id ) ;
79+ console . log ( 'All cases from database:' , allDebts . length ) ;
80+ console . log ( 'Sample cases:' , allDebts . slice ( 0 , 3 ) ) ;
81+
82+ // Combine and deduplicate debts from both sources
83+ const mockData = JSON . parse ( localStorage . getItem ( 'ccai_mock_data' ) || '{}' ) ;
84+ const localCases = mockData . cases || [ ] ;
85+ const localPortfolioDebts = localCases . filter ( debt => debt . portfolio_id === id ) ;
86+
87+ // Filter Supabase debts for this portfolio
88+ const supabasePortfolioDebts = allDebts . filter ( debt => debt . portfolio_id === id ) ;
89+
90+ // Use Map for better deduplication
91+ const debtMap = new Map ( ) ;
92+
93+ // Add Supabase debts first (they take priority)
94+ supabasePortfolioDebts . forEach ( debt => {
95+ debtMap . set ( debt . id , debt ) ;
96+ } ) ;
97+
98+ // Add local debts only if not already present
99+ localPortfolioDebts . forEach ( debt => {
100+ if ( ! debtMap . has ( debt . id ) ) {
101+ debtMap . set ( debt . id , debt ) ;
102+ }
103+ } ) ;
104+
105+ const allPortfolioDebts = Array . from ( debtMap . values ( ) ) ;
106+
107+ console . log ( 'Portfolio ID:' , id , 'Supabase debts:' , supabasePortfolioDebts . length , 'Local debts:' , localPortfolioDebts . length , 'Total unique:' , allPortfolioDebts . length ) ;
108+ console . log ( 'Unique debt IDs:' , allPortfolioDebts . map ( d => d . id ) ) ;
73109
74- const portfolioPayments = allPayments . filter ( p => allDebts . some ( c => c . id === p . case_id ) && p . status === 'completed' ) ;
110+ const portfolioPayments = allPayments . filter ( p => allPortfolioDebts . some ( c => c . id === p . case_id ) && p . status === 'completed' ) ;
75111 const totalCollected = portfolioPayments . reduce ( ( sum , p ) => sum + ( p . amount || 0 ) , 0 ) ;
76- const collectionRate = portfolioData . total_face_value > 0 ? ( totalCollected / portfolioData . total_face_value ) * 100 : 0 ;
77- const totalCases = allDebts . length ;
112+ const totalFaceValue = allPortfolioDebts . reduce ( ( sum , debt ) => sum + ( debt . original_balance || 0 ) , 0 ) ;
113+ const collectionRate = totalFaceValue > 0 ? ( totalCollected / totalFaceValue ) * 100 : 0 ;
114+ const totalCases = allPortfolioDebts . length ;
78115 const paymentCount = portfolioPayments . length ;
79116
80- const statusCounts = allDebts . reduce ( ( acc , curr ) => {
117+ const statusCounts = allPortfolioDebts . reduce ( ( acc , curr ) => {
81118 acc [ curr . status ] = ( acc [ curr . status ] || 0 ) + 1 ;
82119 return acc ;
83120 } , { } ) ;
121+
122+ // Update portfolio with calculated values
123+ const updatedPortfolioData = {
124+ ...portfolioData ,
125+ account_count : totalCases ,
126+ total_face_value : totalFaceValue
127+ } ;
84128
85129 const statusChartData = Object . entries ( statusCounts ) . map ( ( [ name , value ] ) => ( { name, value } ) ) ;
86130
@@ -95,14 +139,9 @@ export default function PortfolioDetails() {
95139 } , { } ) ;
96140 setCasePaymentsMap ( newCasePaymentsMap ) ;
97141
98- // Ensure litigation_eligible exists for display, even if not directly returned by mock entity
99- const processedPortfolioData = {
100- ...portfolioData ,
101- litigation_eligible : portfolioData . litigation_eligible !== undefined ? portfolioData . litigation_eligible : true , // Default to true for demo
102- } ;
103-
104- setPortfolio ( processedPortfolioData ) ;
105- setDebts ( allDebts ) ;
142+ setPortfolio ( updatedPortfolioData ) ;
143+ setDebts ( allPortfolioDebts ) ;
144+ setVendors ( vendorList || [ ] ) ;
106145 setPortfolioStats ( { totalCases, totalCollected, collectionRate, paymentCount } ) ;
107146 setStatusDistribution ( statusChartData ) ;
108147 } catch ( error ) {
@@ -237,7 +276,20 @@ export default function PortfolioDetails() {
237276 < h1 className = "text-3xl font-bold text-gray-900" > { portfolio . name } </ h1 >
238277 < p className = "text-gray-600 mt-1" > { portfolio . original_creditor } </ p >
239278 </ div >
240- < div className = "flex gap-2" >
279+ < div className = "flex gap-2 items-center" >
280+ < Select value = { selectedVendor } onValueChange = { setSelectedVendor } >
281+ < SelectTrigger className = "w-48" >
282+ < SelectValue placeholder = "Select Vendor" />
283+ </ SelectTrigger >
284+ < SelectContent >
285+ < SelectItem value = "none" > No Vendor</ SelectItem >
286+ { vendors . map ( vendor => (
287+ < SelectItem key = { vendor . id } value = { vendor . id } >
288+ { vendor . name }
289+ </ SelectItem >
290+ ) ) }
291+ </ SelectContent >
292+ </ Select >
241293 < Button variant = "outline" >
242294 < Download className = "w-4 h-4 mr-2" />
243295 Export Debts
0 commit comments