OpChan/src/components/Header.tsx

245 lines
8.1 KiB
TypeScript
Raw Normal View History

2025-04-15 16:28:03 +05:30
import React from 'react';
import { Link } from 'react-router-dom';
2025-07-30 13:22:06 +05:30
import { useAuth } from '@/contexts/useAuth';
import { useForum } from '@/contexts/useForum';
2025-04-15 16:28:03 +05:30
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
2025-04-24 17:35:31 +05:30
import { ShieldCheck, LogOut, Terminal, Wifi, WifiOff, AlertTriangle, CheckCircle, Key, RefreshCw, CircleSlash } from 'lucide-react';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
2025-04-15 16:28:03 +05:30
const Header = () => {
const {
currentUser,
isAuthenticated,
verificationStatus,
connectWallet,
disconnectWallet,
verifyOrdinal,
delegateKey,
isDelegationValid,
delegationTimeRemaining
} = useAuth();
const { isNetworkConnected, isRefreshing } = useForum();
2025-04-15 16:28:03 +05:30
const handleConnect = async () => {
await connectWallet();
};
const handleDisconnect = () => {
disconnectWallet();
};
const handleVerify = async () => {
await verifyOrdinal();
};
2025-04-24 14:31:00 +05:30
const handleDelegateKey = async () => {
await delegateKey();
};
const formatDelegationTime = () => {
if (!isDelegationValid()) return null;
const timeRemaining = delegationTimeRemaining();
const hours = Math.floor(timeRemaining / (1000 * 60 * 60));
const minutes = Math.floor((timeRemaining % (1000 * 60 * 60)) / (1000 * 60));
2025-04-24 17:35:31 +05:30
return `${hours}h ${minutes}m`;
};
const renderDelegationButton = () => {
2025-04-24 17:35:31 +05:30
if (verificationStatus !== 'verified-owner') return null;
const hasValidDelegation = isDelegationValid();
const timeRemaining = formatDelegationTime();
return (
<Tooltip>
<TooltipTrigger asChild>
<Button
variant={hasValidDelegation ? "outline" : "default"}
size="sm"
2025-04-24 17:35:31 +05:30
className="flex items-center gap-1 text-xs px-2 h-7"
onClick={handleDelegateKey}
>
2025-04-24 17:35:31 +05:30
<Key className="w-3 h-3" />
{hasValidDelegation
2025-04-24 17:35:31 +05:30
? <span>KEY ACTIVE ({timeRemaining})</span>
: <span>DELEGATE KEY</span>}
</Button>
</TooltipTrigger>
2025-04-24 17:35:31 +05:30
<TooltipContent className="max-w-[260px] text-sm">
{hasValidDelegation ? (
2025-04-24 17:35:31 +05:30
<p>Browser key active for ~{timeRemaining}. Wallet signatures not needed for most actions.</p>
) : (
2025-04-24 17:35:31 +05:30
<p>Delegate a browser key for 24h to avoid constant wallet signing.</p>
)}
</TooltipContent>
</Tooltip>
);
};
2025-04-24 14:31:00 +05:30
const renderAccessBadge = () => {
if (verificationStatus === 'unverified') {
return (
2025-04-24 17:35:31 +05:30
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
size="sm"
onClick={handleVerify}
className="flex items-center gap-1 text-xs px-2 h-7 border-destructive text-destructive hover:bg-destructive/10"
>
<AlertTriangle className="w-3 h-3" />
<span>[UNVERIFIED] Verify</span>
</Button>
</TooltipTrigger>
<TooltipContent className="max-w-[260px] text-sm">
<p className="font-semibold mb-1">Action Required</p>
<p>Verify your Ordinal ownership to enable posting, commenting, and voting.</p>
</TooltipContent>
</Tooltip>
2025-04-24 14:31:00 +05:30
);
}
if (verificationStatus === 'verifying') {
return (
<Badge
variant="outline"
2025-04-24 17:35:31 +05:30
className="flex items-center gap-1 text-xs px-2 h-7"
2025-04-24 14:31:00 +05:30
>
<RefreshCw className="w-3 h-3 animate-spin" />
2025-04-24 17:35:31 +05:30
<span>[VERIFYING...]</span>
2025-04-24 14:31:00 +05:30
</Badge>
);
}
if (verificationStatus === 'verified-none') {
return (
2025-04-24 17:35:31 +05:30
<Tooltip>
<TooltipTrigger asChild>
<Badge
variant="secondary"
className="flex items-center gap-1 cursor-help text-xs px-2 h-7"
>
<CircleSlash className="w-3 h-3" />
<span>[VERIFIED | READ-ONLY]</span>
</Badge>
</TooltipTrigger>
<TooltipContent className="max-w-[260px] text-sm">
<p className="font-semibold mb-1">Wallet Verified - No Ordinals</p>
<p>No Ordinal Operators found. Read-only access granted.</p>
<Button size="sm" variant="link" onClick={handleVerify} className="p-0 h-auto mt-1 text-xs">Verify Again?</Button>
</TooltipContent>
</Tooltip>
2025-04-24 14:31:00 +05:30
);
}
2025-04-24 17:35:31 +05:30
// Verified - Ordinal Owner
2025-04-24 14:31:00 +05:30
if (verificationStatus === 'verified-owner') {
return (
2025-04-24 17:35:31 +05:30
<Tooltip>
<TooltipTrigger asChild>
<Badge
variant="default"
className="flex items-center gap-1 cursor-help text-xs px-2 h-7 bg-primary text-primary-foreground"
>
<CheckCircle className="w-3 h-3" />
<span>[OWNER ]</span>
</Badge>
</TooltipTrigger>
<TooltipContent className="max-w-[260px] text-sm">
<p className="font-semibold mb-1">Ordinal Owner Verified!</p>
<p>Full forum access granted.</p>
<Button size="sm" variant="link" onClick={handleVerify} className="p-0 h-auto mt-1 text-xs">Verify Again?</Button>
</TooltipContent>
</Tooltip>
2025-04-24 14:31:00 +05:30
);
}
return null;
};
2025-04-15 16:28:03 +05:30
return (
2025-04-24 17:35:31 +05:30
<header className="border-b border-cyber-muted bg-cyber-dark fixed top-0 left-0 right-0 z-50 h-16">
<div className="container mx-auto px-4 h-full flex justify-between items-center">
2025-04-15 16:28:03 +05:30
<div className="flex items-center gap-2">
<Terminal className="text-cyber-accent w-6 h-6" />
<Link to="/" className="text-xl font-bold text-glow text-cyber-accent">
OpChan
</Link>
2025-04-24 17:35:31 +05:30
2025-04-15 16:28:03 +05:30
</div>
2025-04-24 17:35:31 +05:30
<div className="flex gap-3 items-center">
<Tooltip>
<TooltipTrigger asChild>
2025-04-24 17:35:31 +05:30
<Badge
variant={isNetworkConnected ? "default" : "destructive"}
className="flex items-center gap-1 text-xs px-2 h-7 cursor-help"
>
{isNetworkConnected ? (
<>
<Wifi className="w-3 h-3" />
<span>WAKU: Connected</span>
</>
) : (
<>
<WifiOff className="w-3 h-3" />
<span>WAKU: Offline</span>
</>
)}
</Badge>
</TooltipTrigger>
2025-04-24 17:35:31 +05:30
<TooltipContent className="text-sm">
<p>{isNetworkConnected ? "Waku network connection active." : "Waku network connection lost."}</p>
{isRefreshing && <p>Refreshing data...</p>}
</TooltipContent>
</Tooltip>
2025-04-15 16:28:03 +05:30
{!currentUser ? (
<Button
variant="outline"
size="sm"
onClick={handleConnect}
2025-04-24 17:35:31 +05:30
className="text-xs px-2 h-7"
2025-04-15 16:28:03 +05:30
>
Connect Wallet
</Button>
) : (
2025-04-24 17:35:31 +05:30
<div className="flex gap-2 items-center">
2025-04-24 14:31:00 +05:30
{renderAccessBadge()}
{renderDelegationButton()}
2025-04-24 17:35:31 +05:30
<Tooltip>
<TooltipTrigger asChild>
<span className="hidden md:flex items-center text-xs text-muted-foreground cursor-default px-2 h-7">
{currentUser.address.slice(0, 5)}...{currentUser.address.slice(-4)}
</span>
</TooltipTrigger>
<TooltipContent className="text-sm">
<p>{currentUser.address}</p>
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
onClick={handleDisconnect}
className="w-7 h-7"
>
<LogOut className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent className="text-sm">Disconnect Wallet</TooltipContent>
</Tooltip>
</div>
2025-04-15 16:28:03 +05:30
)}
</div>
</div>
</header>
);
};
export default Header;