66import React , { useState , useEffect , useCallback } from 'react' ;
77import { useAccount } from 'wagmi' ;
88import { motion } from 'framer-motion' ;
9- import { getAmbassadorStats , getAmbassadorLeaderboard , getReferralTree , getClaimableCommissions , getNextCommissionInfo , getLeaderboardByReferrals , getLeaderboardByCommissions } from '../lib/supabaseClient' ;
9+ import { getAmbassadorStats , getAmbassadorLeaderboard , getReferralTree , getClaimableCommissions , getNextCommissionInfo , getLeaderboardByReferrals , getLeaderboardByCommissions , getCommissionHistory } from '../lib/supabaseClient' ;
1010import { formatUSD , calculateUSDValue } from '../lib/priceUtils' ;
1111import { BADGE_TIERS , createDynamicReferralLink } from './AfrodexStaking' ;
1212
@@ -33,6 +33,8 @@ export default function AmbassadorDashboard({ stakedBalance, badgeTier, afroxPri
3333 const [ leaderboardByCommissions , setLeaderboardByCommissions ] = useState ( [ ] ) ;
3434 const [ claimableAmount , setClaimableAmount ] = useState ( 0 ) ;
3535 const [ nextCommission , setNextCommission ] = useState ( null ) ;
36+ const [ commissionHistory , setCommissionHistory ] = useState ( { pending : [ ] , matured : [ ] , claimed : [ ] } ) ;
37+ const [ activeHistoryTab , setActiveHistoryTab ] = useState ( 'pending' ) ;
3638 const [ loading , setLoading ] = useState ( false ) ;
3739 const [ copied , setCopied ] = useState ( false ) ;
3840 const [ activeTreeView , setActiveTreeView ] = useState ( 'tree' ) ;
@@ -123,6 +125,12 @@ export default function AmbassadorDashboard({ stakedBalance, badgeTier, afroxPri
123125 const nextCommissionInfo = await getNextCommissionInfo ( address ) ;
124126 setNextCommission ( nextCommissionInfo ) ;
125127
128+ // =============================================
129+ // NEW: Fetch commission history (pending, matured, claimed)
130+ // =============================================
131+ const history = await getCommissionHistory ( address ) ;
132+ setCommissionHistory ( history ) ;
133+
126134 } catch ( e ) {
127135 console . error ( 'Error loading ambassador data:' , e ) ;
128136 } finally {
@@ -199,21 +207,19 @@ export default function AmbassadorDashboard({ stakedBalance, badgeTier, afroxPri
199207 < div className = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6" >
200208 < motion . div className = "bg-gray-900 p-4 rounded-xl border border-orange-600/10" whileHover = { cardGlow } >
201209 < div className = "text-sm text-gray-400" > Total Referrals</ div >
202- < div className = "text-2xl font-bold text-orange-400 mt-1" >
203- { stats . totalReferrals }
204- { /* Show countdown if nextCommission has data */ }
205- { nextCommission && nextCommission . daysUntilClaim > 0 && (
206- < span className = "text-sm font-normal text-yellow-400 ml-2" >
207- ⏳ { nextCommission . daysUntilClaim } d ({ prettyNumber ( nextCommission . nextClaimAmount ) } AfroX)
208- </ span >
209- ) }
210- { /* Fallback: if no nextCommission data but there are pending commissions in stats */ }
211- { ! nextCommission && stats . pendingCommissions > 0 && (
212- < span className = "text-sm font-normal text-yellow-400 ml-2" >
213- ⏳ ~30d ({ prettyNumber ( stats . pendingCommissions ) } AfroX)
214- </ span >
215- ) }
216- </ div >
210+ < div className = "text-2xl font-bold text-orange-400 mt-1" > { stats . totalReferrals } </ div >
211+ { /* Show countdown on new line */ }
212+ { nextCommission && nextCommission . daysUntilClaim > 0 && (
213+ < div className = "text-sm text-yellow-400 mt-1" >
214+ ⏳ { nextCommission . daysUntilClaim } d ({ prettyNumber ( nextCommission . nextClaimAmount ) } AfroX)
215+ </ div >
216+ ) }
217+ { /* Fallback: if no nextCommission data but there are pending commissions in stats */ }
218+ { ! nextCommission && stats . pendingCommissions > 0 && (
219+ < div className = "text-sm text-yellow-400 mt-1" >
220+ ⏳ ~30d ({ prettyNumber ( stats . pendingCommissions ) } AfroX)
221+ </ div >
222+ ) }
217223 { nextCommission && nextCommission . hasClaimable && (
218224 < div className = "text-xs text-green-400 mt-1" > ✓ { prettyNumber ( nextCommission . claimableAmount ) } AfroX ready!</ div >
219225 ) }
@@ -379,6 +385,113 @@ export default function AmbassadorDashboard({ stakedBalance, badgeTier, afroxPri
379385 </ div >
380386 </ motion . div >
381387
388+ { /* Commission History */ }
389+ < motion . div className = "bg-gray-900 p-6 rounded-xl border border-orange-600/20 mb-6" whileHover = { cardGlow } >
390+ < div className = "flex justify-between items-center mb-4" >
391+ < h2 className = "text-xl font-bold" > 📜 Commission History</ h2 >
392+ < div className = "flex gap-2" >
393+ < button
394+ onClick = { ( ) => setActiveHistoryTab ( 'pending' ) }
395+ className = { `px-3 py-1 rounded text-sm ${ activeHistoryTab === 'pending' ? 'bg-yellow-500 text-black' : 'bg-gray-800 text-gray-400' } ` }
396+ >
397+ ⏳ Pending ({ commissionHistory . pending . length } )
398+ </ button >
399+ < button
400+ onClick = { ( ) => setActiveHistoryTab ( 'matured' ) }
401+ className = { `px-3 py-1 rounded text-sm ${ activeHistoryTab === 'matured' ? 'bg-green-500 text-black' : 'bg-gray-800 text-gray-400' } ` }
402+ >
403+ ✓ Ready ({ commissionHistory . matured . length } )
404+ </ button >
405+ < button
406+ onClick = { ( ) => setActiveHistoryTab ( 'claimed' ) }
407+ className = { `px-3 py-1 rounded text-sm ${ activeHistoryTab === 'claimed' ? 'bg-blue-500 text-black' : 'bg-gray-800 text-gray-400' } ` }
408+ >
409+ 💸 Claimed ({ commissionHistory . claimed . length } )
410+ </ button >
411+ </ div >
412+ </ div >
413+
414+ < div className = "space-y-2 max-h-64 overflow-y-auto" >
415+ { /* Pending Commissions */ }
416+ { activeHistoryTab === 'pending' && (
417+ commissionHistory . pending . length > 0 ? (
418+ commissionHistory . pending . map ( ( commission , index ) => {
419+ const colors = LEVEL_COLORS [ commission . level ] || LEVEL_COLORS [ 1 ] ;
420+ return (
421+ < div key = { index } className = { `flex items-center justify-between p-3 rounded-lg ${ colors . bg } border ${ colors . border } ` } >
422+ < div className = "flex items-center gap-3" >
423+ < span className = { `px-2 py-1 rounded text-xs font-bold ${ colors . text } ` } > L{ commission . level } </ span >
424+ < div >
425+ < div className = { `text-sm font-semibold ${ colors . text } ` } > { prettyNumber ( commission . amount ) } AfroX</ div >
426+ < div className = "text-xs text-gray-400" > from { shortAddr ( commission . referee_address ) } </ div >
427+ </ div >
428+ </ div >
429+ < div className = "text-right" >
430+ < div className = "text-sm text-yellow-400 font-semibold" > ⏳ { commission . displayText } </ div >
431+ < div className = "text-xs text-gray-500" > until claimable</ div >
432+ </ div >
433+ </ div >
434+ ) ;
435+ } )
436+ ) : (
437+ < div className = "text-center p-8 bg-gray-800 rounded text-gray-400" > No pending commissions</ div >
438+ )
439+ ) }
440+
441+ { /* Matured Commissions (Ready to Claim) */ }
442+ { activeHistoryTab === 'matured' && (
443+ commissionHistory . matured . length > 0 ? (
444+ commissionHistory . matured . map ( ( commission , index ) => {
445+ const colors = LEVEL_COLORS [ commission . level ] || LEVEL_COLORS [ 1 ] ;
446+ return (
447+ < div key = { index } className = "flex items-center justify-between p-3 rounded-lg bg-green-500/20 border border-green-500" >
448+ < div className = "flex items-center gap-3" >
449+ < span className = { `px-2 py-1 rounded text-xs font-bold ${ colors . text } ` } > L{ commission . level } </ span >
450+ < div >
451+ < div className = "text-sm font-semibold text-green-400" > { prettyNumber ( commission . amount ) } AfroX</ div >
452+ < div className = "text-xs text-gray-400" > from { shortAddr ( commission . referee_address ) } </ div >
453+ </ div >
454+ </ div >
455+ < div className = "text-right" >
456+ < div className = "text-sm text-green-400 font-semibold" > ✓ Ready</ div >
457+ < div className = "text-xs text-gray-500" > matured { commission . displayText } </ div >
458+ </ div >
459+ </ div >
460+ ) ;
461+ } )
462+ ) : (
463+ < div className = "text-center p-8 bg-gray-800 rounded text-gray-400" > No matured commissions ready to claim</ div >
464+ )
465+ ) }
466+
467+ { /* Claimed Commissions */ }
468+ { activeHistoryTab === 'claimed' && (
469+ commissionHistory . claimed . length > 0 ? (
470+ commissionHistory . claimed . map ( ( commission , index ) => {
471+ const colors = LEVEL_COLORS [ commission . level ] || LEVEL_COLORS [ 1 ] ;
472+ return (
473+ < div key = { index } className = "flex items-center justify-between p-3 rounded-lg bg-blue-500/20 border border-blue-500/50" >
474+ < div className = "flex items-center gap-3" >
475+ < span className = { `px-2 py-1 rounded text-xs font-bold ${ colors . text } ` } > L{ commission . level } </ span >
476+ < div >
477+ < div className = "text-sm font-semibold text-blue-400" > { prettyNumber ( commission . amount ) } AfroX</ div >
478+ < div className = "text-xs text-gray-400" > from { shortAddr ( commission . referee_address ) } </ div >
479+ </ div >
480+ </ div >
481+ < div className = "text-right" >
482+ < div className = "text-sm text-blue-400 font-semibold" > 💸 Claimed</ div >
483+ < div className = "text-xs text-gray-500" > { commission . displayText } </ div >
484+ </ div >
485+ </ div >
486+ ) ;
487+ } )
488+ ) : (
489+ < div className = "text-center p-8 bg-gray-800 rounded text-gray-400" > No claimed commissions yet</ div >
490+ )
491+ ) }
492+ </ div >
493+ </ motion . div >
494+
382495 { /* Leaderboards - Two Cards Side by Side */ }
383496 < div className = "grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6" >
384497 { /* Left: Top by Referrals */ }
0 commit comments