diff --git a/client/components/asset-allocation-chart.tsx b/client/components/asset-allocation-chart.tsx index 0eedb6b..e8486ad 100644 --- a/client/components/asset-allocation-chart.tsx +++ b/client/components/asset-allocation-chart.tsx @@ -3,6 +3,8 @@ import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from 'recharts' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { useAPAXStore, formatCurrency } from '@/lib/store' +import { Skeleton } from '@/components/ui/skeleton' +import {useEffect, useState } from 'react' const COLORS = { gold: '#D4AF37', @@ -50,6 +52,11 @@ export function AssetAllocationChart() { { name: 'Platinum', value: 10, color: COLORS.platinum } ] + + + + + const CustomTooltip = ({ active, payload }: { active?: boolean; payload?: Array<{ payload: typeof data[0] }> }) => { if (active && payload && payload.length) { const item = payload[0].payload @@ -64,11 +71,25 @@ export function AssetAllocationChart() { ) } return null + } + + const [isLoading, setIsLoading ] = useState(true); + + useEffect(() => + { + setTimeout(() => { + setIsLoading(false); + }, 2000); + }) + if (isLoading) { + return + } + return (
- {/* Your Holdings Chart */} + {/* Holdings Chart */} Your Asset Allocation @@ -213,3 +234,85 @@ export function AssetAllocationChart() {
) } + + +function AssetAllocationSkeleton() { + return ( +
+ + {/* 1. Left Card: Your Asset Allocation */} + + + {/* Title */} + {/* Desc */} + + + + {/* Donut Chart Placeholder */} +
+ +
+
+ + {/* Legend Grid Placeholder */} +
+
+ {[...Array(3)].map((_, i) => ( +
+
+ + +
+ + +
+ ))} +
+ {/* Divider Line */} +
+
+ + + + {/* Right Card: APX-i Index Token */} + + +
+ +
+ + +
+
+
+ + + {/* Donut Chart Placeholder */} +
+ +
+
+ +
+ {/* Legend Grid */} +
+ {[...Array(3)].map((_, i) => ( +
+
+ + +
+ +
+ ))} +
+ + {/* Bottom Holdings Box Placeholder */} + +
+ + + +
+ ) +} \ No newline at end of file diff --git a/client/components/portfolio-overview.tsx b/client/components/portfolio-overview.tsx index 00bccd6..7bdd7b2 100644 --- a/client/components/portfolio-overview.tsx +++ b/client/components/portfolio-overview.tsx @@ -1,8 +1,11 @@ 'use client' +import { useEffect, useState } from 'react' import { TrendUp, TrendDown, Wallet, Coins } from '@phosphor-icons/react' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { useAPAXStore, formatCurrency, formatWeight } from '@/lib/store' +import { Skeleton } from '@/components/ui/skeleton' +import React from 'react' export function PortfolioOverview() { const { userHoldings, metalPrices } = useAPAXStore() @@ -49,6 +52,17 @@ export function PortfolioOverview() { } ] + const [isLoading, setIsLoading ] = useState(true) + + useEffect(() => { + const timer = setTimeout(() => setIsLoading(false), 2000) + return () => clearTimeout(timer) + }, []) + + + if(isLoading) { + return + } return (
{/* Primary Card - Spans 2 cols for visibility */} @@ -122,3 +136,42 @@ export function PortfolioOverview() {
) } + + function PortfolioOverviewSkeleton() { + return ( +
+ + {/* 1. Primary Card Skeleton (Total Portfolio) */} + + + + + + + + + {/* Trend Badge & Subtext */} +
+ + +
+
+
+ + {/* Metal Token Cards Skeletons (Gold, Silver, Platinum) */} + {[...Array(3)].map((_, i) => ( + + + + + + + + + + + ))} + +
+ ) +} \ No newline at end of file diff --git a/client/components/sharia-certification-hub.tsx b/client/components/sharia-certification-hub.tsx index 6932a37..603b9cb 100644 --- a/client/components/sharia-certification-hub.tsx +++ b/client/components/sharia-certification-hub.tsx @@ -4,6 +4,9 @@ import { FileText, Download, Shield, CheckCircle, ExternalLink } from 'lucide-re import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' +import { Skeleton } from '@/components/ui/skeleton' +import {useEffect, useState } from 'react' + const certifications = [ { @@ -51,7 +54,25 @@ const typeIcons = { report: '📋' } + + + + + export function ShariaCertificationHub() { + + const [isLoading, setIsLoading ] = useState(true); + + useEffect(() => + { + setTimeout(() => { + setIsLoading(false); + }, 2000); + }) + + if (isLoading) { + return + } return ( @@ -153,3 +174,76 @@ export function ShariaCertificationHub() { ) } + +function ShariaCertificationHubSkeleton() { + return ( + + +
+
+ {/* Shield Icon Placeholder */} + + +
+ {/* Title Placeholder */} + + {/* Description Placeholder (Hidden on mobile to match real component) */} + +
+
+ + {/* Badge Placeholder */} + +
+
+ + + {/* Certificate Grid Skeleton */} +
+ {/* Generate 2 placeholders to match typical list size */} + {[...Array(2)].map((_, i) => ( +
+
+ {/* Certificate Icon */} + + +
+ {/* Cert Title */} + + {/* Cert Description (2 lines) */} +
+ + +
+ {/* Meta Row (Issuer | Date) */} + +
+
+ + {/* Action Buttons Row */} +
+ + +
+
+ ))} +
+ + {/* Bottom Verification Banner Skeleton */} +
+
+ +
+ + +
+ +
+
+
+
+ ) +} \ No newline at end of file