Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions app/(dashboard)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";
import { AccountOverview } from "@/components/dashboard/account-overview";
import DepositMethods from "@/components/dashboard/deposit";
import { KYCStatusBanner } from "@/components/dashboard/kyc-status-banner";
import { MarketOverview } from "@/components/dashboard/market-overview";
import { RecentTransactions } from "@/components/dashboard/recent-transactions";
import { WithdrawalModal } from "@/components/dashboard/withdrawal/WithdrawalModal";
Expand All @@ -18,6 +19,7 @@ export default function DashboardPage() {
return (
<div className="flex flex-col gap-5 md:gap-10">
<WithdrawalModal />
<KYCStatusBanner />
{openDeposit ? (
<DepositMethods toggleDeposit={toggleDeposit} />
) : (
Expand Down
70 changes: 70 additions & 0 deletions components/dashboard/kyc-status-banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'use client';

import { getProfile } from '@/lib/api/users';
import { X } from 'lucide-react';
import Link from 'next/link';
import { useEffect, useState } from 'react';

const DISMISS_KEY = 'kyc-banner-dismissed';

export function KYCStatusBanner() {
const [kycStatus, setKycStatus] = useState<string | null>(null);
const [loading, setLoading] = useState(true);
const [dismissed, setDismissed] = useState(false);

useEffect(() => {
const load = async () => {
try {
const profile = await getProfile();
setKycStatus(profile.kycStatus ?? null);
} catch {
setKycStatus(null);
} finally {
setLoading(false);
}
};
load();
}, []);

if (loading) return null;

const isVerified = kycStatus === 'Verified';
if (isVerified) return null;

const isDismissed =
dismissed || localStorage.getItem(DISMISS_KEY) === 'true';
if (isDismissed) return null;

const handleDismiss = () => {
localStorage.setItem(DISMISS_KEY, 'true');
setDismissed(true);
};

return (
<div className="relative overflow-hidden rounded-xl bg-gradient-to-r from-amber-50 to-orange-100 dark:from-amber-950/20 dark:to-orange-950/20 p-4 shadow-sm border border-amber-200 dark:border-amber-800">
<button
onClick={handleDismiss}
className="absolute top-2 right-2 text-muted-foreground hover:text-foreground transition-colors"
aria-label="Dismiss"
>
<X className="size-4" />
</button>
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 pr-6">
<div className="space-y-0.5">
<p className="text-sm font-semibold text-foreground">
Your account is not yet verified
</p>
<p className="text-xs text-muted-foreground">
Complete KYC to unlock full transaction limits.
</p>
</div>
<Link
href="/settings"
className="whitespace-nowrap rounded-md bg-primary px-5 py-2 text-xs font-semibold text-black transition-colors hover:bg-primary/90 active:scale-95"
>
Verify Now
</Link>
</div>
</div>
);
}
79 changes: 79 additions & 0 deletions components/dashboard/settings/kyc-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
'use client';

import { getProfile } from '@/lib/api/users';
import { BadgeCheck, AlertTriangle } from 'lucide-react';
import Link from 'next/link';
import { useEffect, useState } from 'react';

export function KycSection() {
const [kycStatus, setKycStatus] = useState<string | null>(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
const load = async () => {
try {
const profile = await getProfile();
setKycStatus(profile.kycStatus ?? null);
} catch {
setKycStatus(null);
} finally {
setLoading(false);
}
};
load();
}, []);

if (loading) {
return (
<div className="bg-card rounded-xl border border-border/50 p-6 animate-pulse">
<div className="h-5 w-40 bg-muted rounded mb-3" />
<div className="h-4 w-60 bg-muted rounded" />
</div>
);
}

const isVerified = kycStatus === 'Verified';

return (
<div className="bg-card rounded-xl border border-border/50 p-6">
<h3 className="text-lg font-semibold text-foreground mb-4">
KYC Verification
</h3>

{isVerified ? (
<div className="flex items-center gap-3">
<BadgeCheck className="size-6 text-green-500 shrink-0" />
<div className="space-y-0.5">
<span className="inline-flex items-center rounded-full px-3 py-0.5 text-xs font-medium bg-green-100 text-green-700 border border-green-200 dark:bg-green-900/30 dark:text-green-400 dark:border-green-800">
Verified
</span>
<p className="text-sm text-muted-foreground">
Your identity has been verified
</p>
</div>
</div>
) : (
<div className="flex items-center gap-3">
<AlertTriangle className="size-6 text-red-500 shrink-0" />
<div className="space-y-0.5">
<span className="inline-flex items-center rounded-full px-3 py-0.5 text-xs font-medium bg-red-100 text-red-700 border border-red-200 dark:bg-red-900/30 dark:text-red-400 dark:border-red-800">
Unverified
</span>
<p className="text-sm text-muted-foreground">
Verification required
</p>
</div>
</div>
)}

{!isVerified && (
<Link
href="#"
className="mt-4 inline-block rounded-md bg-primary px-5 py-2 text-xs font-semibold text-black transition-colors hover:bg-primary/90 active:scale-95"
>
Start Verification
</Link>
)}
</div>
);
}
2 changes: 2 additions & 0 deletions components/settings/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useState } from "react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { AccountIcon, SecurityIcon, IdentityIcon } from "../icons";
import { AccountInfo } from "./account-info";
import { KycSection } from "../dashboard/settings/kyc-section";
import { Security } from "./security";
import { Notification } from "./notification";
import { ProfileOverview } from "../profile/profile-overview";
Expand Down Expand Up @@ -72,6 +73,7 @@ export function TabsSettings() {
{/* Right Column: Content Stack */}
<div className="space-y-6">
<PersonalInfo />
<KycSection />
<VerificationBanner />
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions lib/api/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface UserProfile {
phone?: string;
avatarUrl?: string;
isVerified?: boolean;
kycStatus?: string;
walletAddress?: string;
}

Expand Down