Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
1dd0063
added .gitignore
N0Obitaz Feb 6, 2026
32fb672
feat: added Skeleton for the bullion-card
N0Obitaz Feb 6, 2026
088b614
feat: implemented matching skeleton loader
N0Obitaz Feb 6, 2026
3cd6f58
feat: added HoverCardSkeleton matching the hover-card
N0Obitaz Feb 6, 2026
52b7a6c
feat: added HoverCardSkeleton matching the hover-card
N0Obitaz Feb 6, 2026
730a8cc
feat: implemented Skeleton on BulltionCard
N0Obitaz Feb 6, 2026
dbda4fe
feat: implemented skeleton loader that matches with the hover card
N0Obitaz Feb 6, 2026
5637999
refactor: added CardSkeleton from the import
N0Obitaz Feb 6, 2026
e572dfb
fix: merge conflict from updated branch
N0Obitaz Feb 14, 2026
d7314f3
feat: imported Skeleton Component
N0Obitaz Feb 14, 2026
aa410d3
feat: added useState and useEffect from for skeletong loading
N0Obitaz Feb 14, 2026
d6e6bee
feat: aadded matching skeleton loader for Main grid
N0Obitaz Feb 14, 2026
65639fd
feat: Implemented skeleton loader for the main grid
N0Obitaz Feb 14, 2026
bebf248
feat: added Skeleton for the right Card (tokens)
N0Obitaz Feb 14, 2026
071daba
feat: implemented skeleton loader for Main content area
N0Obitaz Feb 14, 2026
d0c6ba0
feat: implemented skeleton loader in Live Security Field
N0Obitaz Feb 14, 2026
54a7bfb
refactor: added skeleton loader to the content
N0Obitaz Feb 14, 2026
d2bd5d8
refactor: added skeleton loader for the right grid
N0Obitaz Feb 14, 2026
a4a2a47
refactor: added HoverSkeleton on the import
N0Obitaz Feb 14, 2026
35d085c
refactor: nested div container separately for both left and right car…
N0Obitaz Feb 14, 2026
38b2be5
refactor: use of skeleton for the content of live security field
N0Obitaz Feb 14, 2026
b34a214
docs: renamed commentsfor ease of understanding
N0Obitaz Feb 14, 2026
dea7153
feat: utilized importing Skeleton
N0Obitaz Feb 6, 2026
74f29a7
feat: added skeleton loader on CardHeader
N0Obitaz Feb 6, 2026
bd919dc
feat: added skeleton loader on MainContent of the Card
N0Obitaz Feb 6, 2026
76e8085
feat: added skeleton loader on MainContent of the Card
N0Obitaz Feb 6, 2026
068178e
feat: added for addional assets
N0Obitaz Feb 6, 2026
970fa9a
feat: Added skeleton loader for the left column
N0Obitaz Feb 6, 2026
4a17d7a
feat: added Skeleton for Page Header
N0Obitaz Feb 10, 2026
9f8f645
feat: added Skeleton for Coming Soon Banner
N0Obitaz Feb 10, 2026
4ac1e37
feat: added Skeleton for how it works
N0Obitaz Feb 10, 2026
96ca515
feat: added skeleton loader for Info cards
N0Obitaz Feb 10, 2026
67c9e3d
feat: added skeleton for the final card component
N0Obitaz Feb 10, 2026
be816b1
feat: added ShariaViewSkeleton to be loaded first
N0Obitaz Feb 11, 2026
085d652
feat: added skeleton loader for the sharia hero banner
N0Obitaz Feb 11, 2026
8535b94
feat: added skeleton loader for compliance priciples
N0Obitaz Feb 11, 2026
61f4d0a
feat: added skeleton loader for advisory board
N0Obitaz Feb 11, 2026
765fe1f
feat: added skeleton loader for verification banner
N0Obitaz Feb 11, 2026
4a0e0c2
Merge remote-tracking branch 'origin' into feature/skeleton-loader
N0Obitaz Feb 16, 2026
72241c8
fix: missing BullionCardSkeleton import
N0Obitaz Feb 16, 2026
a6db9d3
Merge branch 'dev' into feature/skeleton-loader
avenolazo Feb 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts


.vscode/
68 changes: 49 additions & 19 deletions client/components/ui/bullion-card.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { cn } from "@/lib/utils";
import { Skeleton } from "@/components/ui/skeleton";

interface BullionCardProps {
type: "gold" | "silver" | "platinum";
Expand Down Expand Up @@ -51,25 +52,20 @@ const BullionCard: React.FC<BullionCardProps> = ({

const theme = metalStyles[type];

return (
return (
<>
{/* Animation Style Block */}
<style jsx global>{`
@keyframes pure-shimmer-loop {
0% { transform: translateX(-150%) skewX(-45deg); }
100% { transform: translateX(300%) skewX(-45deg); }
}
.group:hover .shimmer-effect {
/* A 1.5s loop where the shimmer takes 0.75s to cross, and waits 0.75s */
animation: pure-shimmer-loop 1.5s infinite cubic-bezier(0.4, 0, 0.2, 1);
}
animation: pure-shimmer-loop 1.5s infinite cubic-bezier(0.4, 0, 0.2, 1);
}
`}</style>

<div
className={cn(
"group relative w-full h-[340px]",
className
)}
className={cn("group relative w-full h-[340px]", className)}
style={{ perspective: "1000px" }}
>
{/* MAIN CARD SLAB */}
Expand All @@ -91,18 +87,17 @@ const BullionCard: React.FC<BullionCardProps> = ({
style={{ backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)' opacity='0.5'/%3E%3C/svg%3E")` }}
/>

{/* Layer B: Glass Reflection (Static) */}
{/* Layer B: Glass Reflection */}
<div className="absolute inset-0 z-20 rounded-xl bg-gradient-to-br from-white/40 via-transparent to-transparent opacity-80 mix-blend-soft-light pointer-events-none" />

{/* Layer C: Moving Sheen (Holographic Loop) */}
{/* Layer C: Moving Sheen */}
<div
className={cn(
"shimmer-effect absolute inset-0 z-20 -translate-x-[140%] skew-x-[-45deg]",

"bg-gradient-to-r from-transparent via-white/10 via-30% via-white/70 via-50% to-transparent",
"mix-blend-overlay"
)}
/>
className={cn(
"shimmer-effect absolute inset-0 z-20 -translate-x-[140%] skew-x-[-45deg]",
"bg-gradient-to-r from-transparent via-white/10 via-30% via-white/70 via-50% to-transparent",
"mix-blend-overlay"
)}
/>
{/* Layer D: Sharp Edge Highlights */}
<div className="absolute inset-0 z-20 border-t border-l border-white/50 rounded-xl mix-blend-overlay pointer-events-none" />

Expand All @@ -126,7 +121,7 @@ const BullionCard: React.FC<BullionCardProps> = ({
<h3
className={cn("text-5xl font-serif font-bold italic tracking-tighter", theme.text)}
style={{
textShadow: theme.engrave, // Applies the "pressed in" look
textShadow: theme.engrave,
opacity: 0.85
}}
>
Expand Down Expand Up @@ -166,4 +161,39 @@ const BullionCard: React.FC<BullionCardProps> = ({
);
};

export function BullionCardSkeleton({ className }: { className?: string }) {
return (
<div
className={cn(
"relative w-full h-[340px] rounded-xl border border-white/10 bg-neutral-900/50 shadow-sm overflow-hidden",
className
)}
>
<div className="absolute inset-4 rounded-lg border border-white/5 flex flex-col items-center justify-between p-6">
{/*Purity Mark */}
<div className="flex flex-col items-center gap-2 w-full pt-2">
<Skeleton className="h-2 w-16 bg-white/10" />
<Skeleton className="h-5 w-12 bg-white/10" />
</div>

{/* Circle & Text */}
<div className="flex flex-col items-center gap-4 w-full">
<Skeleton className="h-12 w-12 rounded-full bg-white/10" />
<Skeleton className="h-10 w-24 bg-white/10" />
</div>

{/* Price Tag*/ }
<div className="w-full pt-4 border-t border-white/5 flex justify-between items-end">
<div className="space-y-2">
<Skeleton className="h-2 w-12 bg-white/10" />
<Skeleton className="h-6 w-20 bg-white/10" />
</div>
<Skeleton className="h-6 w-6 rounded-full bg-white/10" />
</div>
</div>

<div className="absolute inset-0 bg-gradient-to-tr from-transparent via-white/5 to-transparent opacity-20" />
</div>
)
}
export default BullionCard;
31 changes: 31 additions & 0 deletions client/components/ui/card.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react'

import { cn } from '@/lib/utils'
import { Skeleton } from '@/components/ui/skeleton'

function Card({ className, ...props }: React.ComponentProps<'div'>) {
return (
Expand Down Expand Up @@ -81,6 +82,35 @@ function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
)
}


function CardSkeleton ({ className, ...props}: React.ComponentProps<'div'>) {
return (

<div
data-slot="card-skeleton"
className={cn(
'flex flex-col gap-6 py-6 shadow-sm rounded-xl border bg-card',
className
)}
{...props}
>
<div className="flex flex-col gap-2 px-6">
<Skeleton className="h-5 w-1/3" />
<Skeleton className="h-4 w-2/3" />
</div>

<div className="px-6 flex-1">
<Skeleton className="h-24 w-full"/>
</div>

<div className="px-6">
<Skeleton className="h-9 w-28"/>
</div>
</div>

)
}

export {
Card,
CardHeader,
Expand All @@ -89,4 +119,5 @@ export {
CardAction,
CardDescription,
CardContent,
CardSkeleton
}
33 changes: 32 additions & 1 deletion client/components/ui/hover-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import * as React from 'react'
import * as HoverCardPrimitive from '@radix-ui/react-hover-card'

import { Skeleton } from '@/components/ui/skeleton'

import { cn } from '@/lib/utils'

function HoverCard({
Expand Down Expand Up @@ -41,4 +43,33 @@ function HoverCardContent({
)
}

export { HoverCard, HoverCardTrigger, HoverCardContent }
function HoverCardSkeleton({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
className={cn("flex justify-between space-x-4", className)}
{...props}
>
{/* Avatar Placeholder */}
<Skeleton className="h-10 w-10 rounded-full shrink-0" />

<div className="space-y-2 flex-1">
{/* Title / Username */}
<Skeleton className="h-4 w-3/4" />

{/* Bio / Details */}
<div className="space-y-1">
<Skeleton className="h-3 w-full" />
<Skeleton className="h-3 w-5/6" />
</div>

{/* Optional: Meta row (e.g., 'Joined Dec 2023') */}
<div className="flex items-center pt-2">
<Skeleton className="h-3 w-3 rounded-full mr-2" />
<Skeleton className="h-3 w-16" />
</div>
</div>
</div>
)
}

export { HoverCard, HoverCardTrigger, HoverCardContent, HoverCardSkeleton}
1 change: 1 addition & 0 deletions client/components/ui/skeleton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ function Skeleton({ className, ...props }: React.ComponentProps<'div'>) {
}

export { Skeleton }

99 changes: 78 additions & 21 deletions client/components/views/dashboard-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import { AssetAllocationChart } from "@/components/asset-allocation-chart";
import { ShariaCertificationHub } from "@/components/sharia-certification-hub";
import { MetalPriceHistoryChart } from "@/components/charts/metal-price-history";
import BullionCard from '@/components/ui/bullion-card'
import { useEffect, useState } from 'react'
import { BullionCardSkeleton } from "@/components/ui/bullion-card";
import { HoverCard, HoverCardContent, HoverCardTrigger, HoverCardSkeleton} from "@/components/ui/hover-card"



export function DashboardView() {
const showroomItems = [
Expand All @@ -14,12 +19,20 @@ export function DashboardView() {
{ type: "platinum" as const, weight: "500 g", purity: "999.5", price: "$14,800.00" },
{ type: "gold" as const, weight: "100 g", purity: "999.9", price: "$7,450.00" },
];

const [isLoading, setIsLoading] = useState(true)

useEffect(() => {
const timer = setTimeout(() => setIsLoading(false), 2000)
return () => clearTimeout(timer)
}, [])

return (
<div className="space-y-4 md:space-y-6 max-w-7xl mx-auto overflow-hidden">
<div className="space-y-4 md:space-y-6 max-w-7xl mx-auto overflow-hidden">

{/* Live Ledger Ticker */}
<div className="w-full bg-[#1A1A1A]/50 border-y border-[#2A2A2A] overflow-hidden py-1.5 relative">
<div className="flex animate-ticker whitespace-nowrap gap-12 items-center">
<div className="group w-full bg-[#1A1A1A]/50 border-y border-[#2A2A2A] overflow-hidden py-1.5 relative">
<div className="flex animate-ticker whitespace-nowrap gap-12 items-center group-hover:[animation-play-state:paused]">
{[...Array(2)].map((_, i) => (
<div key={i} className="flex gap-12 items-center">
<div className="flex items-center gap-2">
Expand All @@ -28,10 +41,37 @@ export function DashboardView() {
Network Connectivity: 100%
</span>
</div>

<span className="text-terminal-sm">Latest Block: #8,421,093</span>
<span className="text-terminal-sm text-[#D4AF37]">
<HoverCard>
<HoverCardTrigger asChild>
<span className="text-terminal-sm text-[#D4AF37] cursor-help underline decoration-dotted underline-offset-4 decoration-[#D4AF37]/30 hover:text-[#FFD700] transition-colors">

Vault A1-X: Re-verified by Lead Auditor

</span>
</HoverCardTrigger>
<HoverCardContent className="w-80 border-[#D4AF37]/30 bg-[#1A1A1A] text-left whitespace-normal">
<div className="space-y-2">
<h4 className="text-sm font-semibold text-[#D4AF37] font-serif">Audit Certificate #8921</h4>
<p className="text-xs text-muted-foreground leading-relaxed">
Verified by <strong>Deloitte</strong> on Oct 14, 2024.
Gold purity confirmed via ultrasonic testing (ASTM E114).
</p>
<div className="flex items-center pt-2 border-t border-white/5 mt-2">
<div className="text-[10px] uppercase tracking-widest text-emerald-500 flex items-center gap-2">
<span className="relative flex h-2 w-2">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
<span className="relative inline-flex rounded-full h-2 w-2 bg-emerald-500"></span>
</span>
Verification Passed
</div>
</div>
</div>
</HoverCardContent>
</HoverCard>


<span className="text-terminal-sm">Last Synced: 2s ago</span>
</div>
))}
Expand Down Expand Up @@ -67,34 +107,51 @@ export function DashboardView() {
{/* Asset Allocation Charts */}
<AssetAllocationChart />

{/* Sharia Certification Hub - Moved inside grid for better density */}
{/* Sharia Certification Hub */}
<ShariaCertificationHub />
</div>
<div className="pt-8 space-y-6">

{/* Bullion Showroom & Testing Area */}
<div className="pt-8 space-y-6">
<div className="flex items-center justify-between px-4 sm:px-0">
<h2 className="text-xl md:text-2xl font-serif font-bold text-[#E8E8E8]">
Bullion Showroom
</h2>
<div className="flex items-center gap-4">
<h2 className="text-xl md:text-2xl font-serif font-bold text-[#E8E8E8]">
Bullion Showroom
</h2>
{/* Toggle Button for Skeleton Test */}
<button
onClick={() => setIsLoading(!isLoading)}
className="text-[10px] border border-white/20 px-2 py-1 rounded hover:bg-white/10 text-muted-foreground transition-colors"
>
{isLoading ? "Status: Loading (Skeleton Active)" : "Status: Loaded (Data Active)"}
</button>
</div>

<button className="text-xs text-[#D4AF37] hover:underline uppercase tracking-widest font-bold transition-colors hover:text-[#FCE798]">
View Vault Inventory →
</button>
</div>

<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 px-4 sm:px-0">
{showroomItems.map((item, idx) => (
<BullionCard
key={idx}
type={item.type}
weight={item.weight}
purity={item.purity}
price={item.price}
className="w-full" // Ensure card takes full width of grid cell
/>
))}
{isLoading ? (
Array.from({ length: 4 }).map((_, idx) => (
<BullionCardSkeleton key={idx} />
))
) : (
showroomItems.map((item, idx) => (
<BullionCard
key={idx}
type={item.type}
weight={item.weight}
purity={item.purity}
price={item.price}
className="w-full"
/>
))
)}
</div>
</div>


</div>
);
}
}
Loading