@@ -29,6 +29,7 @@ import { useReferralStats, useReferralLink } from "../hooks/useReferral";
2929import ShareModal from "../components/ShareModal" ;
3030import EmptyState from "../components/ui/EmptyState" ;
3131import FirstTimePortfolioPanel from "../components/FirstTimePortfolioPanel" ;
32+ import { PortfolioCardSkeleton } from "../components/Skeleton" ;
3233import { useNavigate } from "react-router-dom" ;
3334import { triggerDepositIntent } from "../lib/vaultIntentActions" ;
3435import { formatCurrency , formatNumber , formatPercent } from "../lib/formatters" ;
@@ -413,67 +414,81 @@ const Portfolio: React.FC<PortfolioProps> = ({ walletAddress }) => {
413414 < div
414415 className = "portfolio-summary-grid"
415416 style = { { marginBottom : "8px" } }
417+ aria-busy = { isLoading || undefined }
416418 >
417- < PortfolioSummaryCard
418- label = { t ( "portfolio.totalNetValue" ) }
419- value = { formatSensitiveCurrency ( totalValue ) }
420- icon = { < DollarSign size = { 20 } color = "var(--accent-cyan)" /> }
421- trend = { totalNetValueTrend }
422- trendPositive = { totalGain >= 0 }
423- />
424- < PortfolioSummaryCard
425- label = { t ( "portfolio.cumulativeYield" ) }
426- value = { formatSensitiveCurrency ( totalGain , true ) }
427- icon = { < TrendingUp size = { 20 } color = "var(--accent-purple)" /> }
428- trend = { cumulativeYieldTrend }
429- trendPositive = { totalGain >= 0 }
430- />
431- < PortfolioSummaryCard
432- label = {
433- < span style = { { display : "flex" , alignItems : "center" , gap : "6px" } } >
434- Weighted Avg APY
435- < HelpIcon
436- variant = "tooltip"
437- content = "The portfolio-value-weighted average of all active position APYs."
438- />
439- </ span >
440- }
441- value = { formatPercent ( weightedApy , {
442- locale,
443- minimumFractionDigits : 2 ,
444- maximumFractionDigits : 2 ,
445- } ) }
446- icon = { < Percent size = { 20 } color = "var(--accent-cyan)" /> }
447- trend = { weightedApyTrend }
448- trendPositive = { true }
449- />
450- < PortfolioSummaryCard
451- label = { t ( "portfolio.activePositions" ) }
452- value = { holdings . filter ( h => h . status === 'active' ) . length . toString ( ) }
453- icon = { < Briefcase size = { 20 } color = "var(--text-secondary)" /> }
454- />
455- < PortfolioSummaryCard
456- label = {
457- < span style = { { display : "flex" , alignItems : "center" , gap : "6px" } } >
458- Referral Earnings
459- < HelpIcon
460- variant = "tooltip"
461- content = { t ( "portfolio.referralTooltip" ) }
462- />
463- </ span >
464- }
465- value = { referralStats ? `$${ referralStats . total_reward_earned } ` : "$0.00" }
466- icon = { < TrendingUp size = { 20 } color = "var(--accent-green)" /> }
467- trend = { referralStats ? `${ referralStats . referral_count } referral${ referralStats . referral_count !== 1 ? 's' : '' } ` : "0 referrals" }
468- trendPositive = { true }
469- />
470- < PortfolioSummaryCard
471- label = { t ( "portfolio.shareReferralLink" ) }
472- value = ""
473- icon = { < Share2 size = { 20 } color = "var(--accent-cyan)" /> }
474- onClick = { ( ) => setShowShareModal ( true ) }
475- clickable = { true }
476- />
419+ { isLoading ? (
420+ < >
421+ < PortfolioCardSkeleton />
422+ < PortfolioCardSkeleton />
423+ < PortfolioCardSkeleton />
424+ < PortfolioCardSkeleton />
425+ < PortfolioCardSkeleton />
426+ < PortfolioCardSkeleton />
427+ </ >
428+ ) : (
429+ < >
430+ < PortfolioSummaryCard
431+ label = { t ( "portfolio.totalNetValue" ) }
432+ value = { formatSensitiveCurrency ( totalValue ) }
433+ icon = { < DollarSign size = { 20 } color = "var(--accent-cyan)" /> }
434+ trend = { totalNetValueTrend }
435+ trendPositive = { totalGain >= 0 }
436+ />
437+ < PortfolioSummaryCard
438+ label = { t ( "portfolio.cumulativeYield" ) }
439+ value = { formatSensitiveCurrency ( totalGain , true ) }
440+ icon = { < TrendingUp size = { 20 } color = "var(--accent-purple)" /> }
441+ trend = { cumulativeYieldTrend }
442+ trendPositive = { totalGain >= 0 }
443+ />
444+ < PortfolioSummaryCard
445+ label = {
446+ < span style = { { display : "flex" , alignItems : "center" , gap : "6px" } } >
447+ Weighted Avg APY
448+ < HelpIcon
449+ variant = "tooltip"
450+ content = "The portfolio-value-weighted average of all active position APYs."
451+ />
452+ </ span >
453+ }
454+ value = { formatPercent ( weightedApy , {
455+ locale,
456+ minimumFractionDigits : 2 ,
457+ maximumFractionDigits : 2 ,
458+ } ) }
459+ icon = { < Percent size = { 20 } color = "var(--accent-cyan)" /> }
460+ trend = { weightedApyTrend }
461+ trendPositive = { true }
462+ />
463+ < PortfolioSummaryCard
464+ label = { t ( "portfolio.activePositions" ) }
465+ value = { holdings . filter ( h => h . status === 'active' ) . length . toString ( ) }
466+ icon = { < Briefcase size = { 20 } color = "var(--text-secondary)" /> }
467+ />
468+ < PortfolioSummaryCard
469+ label = {
470+ < span style = { { display : "flex" , alignItems : "center" , gap : "6px" } } >
471+ Referral Earnings
472+ < HelpIcon
473+ variant = "tooltip"
474+ content = { t ( "portfolio.referralTooltip" ) }
475+ />
476+ </ span >
477+ }
478+ value = { referralStats ? `$${ referralStats . total_reward_earned } ` : "$0.00" }
479+ icon = { < TrendingUp size = { 20 } color = "var(--accent-green)" /> }
480+ trend = { referralStats ? `${ referralStats . referral_count } referral${ referralStats . referral_count !== 1 ? 's' : '' } ` : "0 referrals" }
481+ trendPositive = { true }
482+ />
483+ < PortfolioSummaryCard
484+ label = { t ( "portfolio.shareReferralLink" ) }
485+ value = ""
486+ icon = { < Share2 size = { 20 } color = "var(--accent-cyan)" /> }
487+ onClick = { ( ) => setShowShareModal ( true ) }
488+ clickable = { true }
489+ />
490+ </ >
491+ ) }
477492 </ div >
478493
479494 < YieldBreakdownChart totalGain = { totalGain } />
0 commit comments