import { useState, useEffect, useRef } from "react";
import {
Home,
BarChart2,
Settings,
Search,
Bell,
User,
Moon,
Sun,
Menu,
X,
ChevronRight,
Shield,
Lock,
Key,
Activity,
Zap,
Plus,
File,
Clock,
Eye,
Link,
FileCheck,
AlertTriangle,
Copy,
ExternalLink,
Trash2,
Edit
} from "lucide-react";
import { useToast } from "@/components/ui/use-toast";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter
} from "@/components/ui/dialog";
import {
Drawer,
DrawerTrigger,
DrawerContent,
DrawerHeader,
DrawerTitle,
DrawerDescription,
DrawerFooter
} from "@/components/ui/drawer";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from
"@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";
// Sample data with more realistic values
const generateMessages = () => {
const types = ["Text", "File", "Image", "Video"];
const statuses = ["Active", "Viewed", "Expired"];
const creators = ["
[email protected]", "
[email protected]", "
[email protected]",
"
[email protected]", "
[email protected]"];
return Array.from({ length: 15 }, (_, i) => ({
id: `SEC-${Math.floor(1000 + Math.random() * 9000)}`,
type: types[Math.floor(Math.random() * types.length)],
status: statuses[Math.floor(Math.random() * statuses.length)],
expiresIn: Math.random() > 0.5 ?
`${Math.floor(1 + Math.random() * 24)} hours` :
"Expired",
creator: creators[Math.floor(Math.random() * creators.length)],
content: Math.random() > 0.7 ?
"Confidential document regarding Q4 financials" :
"Secure message with self-destruct timer",
createdAt: new Date(Date.now() - Math.floor(Math.random() * 7 * 24 * 60 * 60 *
1000)),
views: Math.floor(Math.random() * 5)
}));
};
const NAV_ITEMS = [
{ label: "Dashboard", icon: Home },
{ label: "Messages", icon: File },
{ label: "Analytics", icon: BarChart2 },
{ label: "Security", icon: Shield },
{ label: "Settings", icon: Settings },
];
const Index = () => {
const [activeTab, setActiveTab] = useState("Dashboard");
const [darkMode, setDarkMode] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const [notificationsOpen, setNotificationsOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const [showProfileMenu, setShowProfileMenu] = useState(false);
const [isDesktop, setIsDesktop] = useState(false);
const [messages, setMessages] = useState(generateMessages());
const [filteredMessages, setFilteredMessages] = useState([]);
const [selectedMessage, setSelectedMessage] = useState(null);
const [newMessageDialogOpen, setNewMessageDialogOpen] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [messageToDelete, setMessageToDelete] = useState(null);
const [messageForm, setMessageForm] = useState({
type: "Text",
content: "",
expiration: "24h",
oneTimeView: true,
password: ""
});
const { toast } = useToast();
const notificationsRef = useRef(null);
const profileRef = useRef(null);
// Close dropdowns when clicking outside
useEffect(() => {
const handleClickOutside = (event) => {
if (notificationsRef.current && !
notificationsRef.current.contains(event.target)) {
setNotificationsOpen(false);
}
if (profileRef.current && !profileRef.current.contains(event.target)) {
setShowProfileMenu(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
// Responsive detection
useEffect(() => {
const handleResize = () => {
setIsDesktop(window.innerWidth >= 768);
};
handleResize();
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
// Dark mode toggle
useEffect(() => {
if (darkMode) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}, [darkMode]);
// Filter messages based on search
useEffect(() => {
if (searchQuery.trim() === "") {
setFilteredMessages(messages);
} else {
const filtered = messages.filter(msg =>
msg.id.toLowerCase().includes(searchQuery.toLowerCase()) ||
msg.type.toLowerCase().includes(searchQuery.toLowerCase()) ||
msg.creator.toLowerCase().includes(searchQuery.toLowerCase())
);
setFilteredMessages(filtered);
}
}, [searchQuery, messages]);
// Activity data based on actual messages
const activityData = Array.from({ length: 9 }, (_, i) => {
const date = new Date();
date.setDate(date.getDate() - (8 - i));
return messages.filter(msg =>
new Date(msg.createdAt).toDateString() === date.toDateString()
).length * 10;
});
// Calculate stats from messages
const stats = {
total: messages.length,
active: messages.filter(msg => msg.status === "Active").length,
viewed: messages.filter(msg => msg.status === "Viewed").length,
expired: messages.filter(msg => msg.status === "Expired").length,
};
// Security score calculation
const securityScore = Math.min(
100,
80 + Math.floor(Math.random() * 20) // Simulate varying score
);
const handleCreateMessage = () => {
const newMessage = {
id: `SEC-${Math.floor(1000 + Math.random() * 9000)}`,
type: messageForm.type,
status: "Active",
expiresIn: messageForm.expiration === "24h" ? "24 hours" :
messageForm.expiration === "1h" ? "1 hour" : "7 days",
creator: "
[email protected]",
content: messageForm.content,
createdAt: new Date(),
views: 0
};
setMessages([newMessage, ...messages]);
setMessageForm({
type: "Text",
content: "",
expiration: "24h",
oneTimeView: true,
password: ""
});
setNewMessageDialogOpen(false);
toast({
title: "Message Created",
description: `Your secret message (${newMessage.id}) has been created.`,
});
};
const handleDeleteMessage = (id) => {
setMessages(messages.filter(msg => msg.id !== id));
setDeleteDialogOpen(false);
toast({
title: "Message Deleted",
description: "The message has been permanently removed.",
variant: "destructive"
});
};
const copyToClipboard = (text) => {
navigator.clipboard.writeText(text);
toast({
title: "Copied to Clipboard",
description: "The message link has been copied.",
});
};
const ActivityChart = ({ data }) => (
<div className="flex items-end h-40 gap-1 mt-2">
{data.map((value, index) => (
<div
key={index}
className="bg-gradient-to-t from-blue-500 to-blue-400 dark:from-blue-600
dark:to-blue-400 rounded-t-sm w-full relative group"
style={{ height: `${value}%` }}
>
<div className="absolute -top-8 left-1/2 transform -translate-x-1/2 bg-
zinc-800 text-white text-xs px-2 py-1 rounded opacity-0 group-hover:opacity-100
transition-opacity pointer-events-none">
{value / 10} messages
</div>
</div>
))}
</div>
);
const SecurityGauge = ({ score }) => (
<div className="relative flex items-center justify-center">
<svg className="w-32 h-32" viewBox="0 0 100 100">
<circle
cx="50" cy="50" r="45"
fill="none"
stroke="#e5e7eb"
strokeWidth="8"
className="dark:stroke-zinc-700"
/>
<circle
cx="50" cy="50" r="45"
fill="none"
stroke={score > 80 ? "#10b981" : score > 60 ? "#f59e0b" : "#ef4444"}
strokeWidth="8"
strokeDasharray={`${score * 2.83} 283`}
strokeLinecap="round"
transform="rotate(-90 50 50)"
/>
</svg>
<div className="absolute flex flex-col items-center">
<span className="text-3xl font-bold">{score}</span>
<span className="text-xs text-zinc-500 dark:text-zinc-400">Security
Score</span>
</div>
</div>
);
const NewMessageForm = () => (
<div className="space-y-4 py-4">
<div className="space-y-2">
<Label>Message Type</Label>
<Select
value={messageForm.type}
onValueChange={(value) => setMessageForm({...messageForm, type: value})}
>
<SelectTrigger>
<SelectValue placeholder="Select type" />
</SelectTrigger>
<SelectContent>
<SelectItem value="Text">Text</SelectItem>
<SelectItem value="File">File</SelectItem>
<SelectItem value="Image">Image</SelectItem>
<SelectItem value="Video">Video</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label>Message Content</Label>
<Textarea
value={messageForm.content}
onChange={(e) => setMessageForm({...messageForm, content:
e.target.value})}
placeholder="Enter your secure message here..."
className="min-h-[120px]"
/>
</div>
<div className="space-y-2">
<Label>Expiration</Label>
<Select
value={messageForm.expiration}
onValueChange={(value) => setMessageForm({...messageForm, expiration:
value})}
>
<SelectTrigger>
<SelectValue placeholder="Select expiration" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1h">1 Hour</SelectItem>
<SelectItem value="24h">24 Hours</SelectItem>
<SelectItem value="7d">7 Days</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex items-center justify-between space-x-2 pt-2">
<Label htmlFor="one-time">One-time view</Label>
<Switch
id="one-time"
checked={messageForm.oneTimeView}
onCheckedChange={(checked) => setMessageForm({...messageForm,
oneTimeView: checked})}
/>
</div>
<div className="space-y-2">
<Label>Password Protection (optional)</Label>
<Input
type="password"
value={messageForm.password}
onChange={(e) => setMessageForm({...messageForm, password:
e.target.value})}
placeholder="Set a password"
/>
</div>
</div>
);
const MessageViewDialog = () => (
<DialogContent className="sm:max-w-[600px]">
<DialogHeader>
<DialogTitle>Message Details: {selectedMessage?.id}</DialogTitle>
<DialogDescription>
{selectedMessage?.type} message created on
{selectedMessage?.createdAt.toLocaleString()}
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="grid grid-cols-2 gap-4">
<div>
<Label>Status</Label>
<div className="mt-1">
<Badge
variant={
selectedMessage?.status === 'Active' ? 'success' :
selectedMessage?.status === 'Viewed' ? 'info' : 'secondary'
}
>
{selectedMessage?.status}
</Badge>
</div>
</div>
<div>
<Label>Expires In</Label>
<p className="mt-1 text-sm">{selectedMessage?.expiresIn}</p>
</div>
<div>
<Label>Creator</Label>
<p className="mt-1 text-sm">{selectedMessage?.creator}</p>
</div>
<div>
<Label>Views</Label>
<p className="mt-1 text-sm">{selectedMessage?.views}</p>
</div>
</div>
<div>
<Label>Content</Label>
<div className="mt-1 p-3 bg-zinc-100 dark:bg-zinc-800 rounded-md">
<p className="text-sm">{selectedMessage?.content}</p>
</div>
</div>
<DialogContent>
<div>
{/* Your content inside DialogContent */}
</div>
</DialogContent>
{/* Now open the DialogFooter outside the div */}
<DialogFooter className="gap-2 sm:gap-0">
<Button
variant="outline"
onClick={() => {
copyToClipboard(`https://secreta.app/m/${selectedMessage?.id}`);
}}
>
<Copy className="mr-2 h-4 w-4" />
Copy Link
</Button>
<Button
variant="destructive"
onClick={() => {
setMessageToDelete(selectedMessage?.id);
setDeleteDialogOpen(true);
}}
>
<Trash2 className="mr-2 h-4 w-4" />
Delete
</Button>
</DialogFooter>
);
return (
<div className="flex min-h-screen bg-gray-50 dark:bg-zinc-900 text-zinc-800
dark:text-white transition-colors duration-300">
{/* Mobile menu overlay */}
{mobileMenuOpen && (
<div
className="fixed inset-0 bg-black/50 z-40 md:hidden"
onClick={() => setMobileMenuOpen(false)}
></div>
)}
{/* Sidebar - Mobile */}
<aside
className={`fixed inset-y-0 left-0 z-50 w-72 bg-white dark:bg-zinc-800
shadow-xl p-6 transform transition-transform duration-300 ease-in-out md:hidden ${
mobileMenuOpen ? 'translate-x-0' : '-translate-x-full'
}`}
>
<div className="flex items-center justify-between mb-8">
<h1 className="text-2xl font-extrabold tracking-tight text-blue-600
dark:text-white flex items-center">
<Lock className="mr-2" size={24} />
Secreta
</h1>
<button
onClick={() => setMobileMenuOpen(false)}
className="p-1 rounded-full hover:bg-zinc-100 dark:hover:bg-zinc-700"
>
<X size={24} />
</button>
</div>
<div className="mb-8">
<div className="flex items-center gap-3 p-3 mb-6 bg-blue-50 dark:bg-zinc-
700/50 rounded-xl">
<div className="w-10 h-10 rounded-full bg-blue-100 dark:bg-zinc-600
flex items-center justify-center text-blue-600 dark:text-blue-400">
<User size={20} />
</div>
<div>
<p className="font-medium">Abdul Kamil</p>
<p className="text-xs text-zinc-500 dark:text-zinc-
400">Administrator</p>
</div>
</div>
<nav className="flex flex-col gap-2">
{NAV_ITEMS.map(({ label, icon: Icon }) => (
<button
key={label}
onClick={() => {
setActiveTab(label);
setMobileMenuOpen(false);
}}
className={`flex items-center gap-3 px-4 py-3 rounded-xl text-sm
font-medium transition-all
${
activeTab === label
? "bg-gradient-to-r from-blue-600 to-blue-500 text-white
shadow-md shadow-blue-500/20"
: "hover:bg-zinc-100 dark:hover:bg-zinc-700/70"
}`}
aria-current={activeTab === label ? "page" : undefined}
>
<Icon size={18} strokeWidth={2} />
<span>{label}</span>
{activeTab === label && <ChevronRight size={16} className="ml-auto"
/>}
</button>
))}
</nav>
</div>
<div className="mt-auto">
<button
onClick={() => setDarkMode(!darkMode)}
className="flex items-center gap-3 px-4 py-3 w-full rounded-xl text-sm
font-medium hover:bg-zinc-100 dark:hover:bg-zinc-700/70"
>
{darkMode ? <Sun size={18} /> : <Moon size={18} />}
<span>{darkMode ? "Light Mode" : "Dark Mode"}</span>
</button>
<div className="text-xs text-zinc-500 dark:text-zinc-400 mt-8 text-
center">
© {new Date().getFullYear()} Secreta Inc.
</div>
</div>
</aside>
{/* Sidebar - Desktop */}
<aside className="w-72 bg-white dark:bg-zinc-800 shadow-md px-6 py-8 hidden
md:flex flex-col justify-between sticky top-0 h-screen">
<div>
<h1 className="text-2xl font-extrabold tracking-tight mb-10 text-blue-600
dark:text-white flex items-center">
<Lock className="mr-2" size={24} />
Secreta
</h1>
<div className="flex items-center gap-3 p-3 mb-6 bg-blue-50 dark:bg-zinc-
700/50 rounded-xl">
<div className="w-10 h-10 rounded-full bg-blue-100 dark:bg-zinc-600
flex items-center justify-center text-blue-600 dark:text-blue-400">
<User size={20} />
</div>
<div>
<p className="font-medium">Abdul Kamil</p>
<p className="text-xs text-zinc-500 dark:text-zinc-
400">Administrator</p>
</div>
</div>
<nav className="flex flex-col gap-2">
{NAV_ITEMS.map(({ label, icon: Icon }) => (
<button
key={label}
onClick={() => setActiveTab(label)}
className={`flex items-center gap-3 px-4 py-3 rounded-xl text-sm
font-medium transition-all
${
activeTab === label
? "bg-gradient-to-r from-blue-600 to-blue-500 text-white
shadow-md shadow-blue-500/20"
: "hover:bg-zinc-100 dark:hover:bg-zinc-700/70"
}`}
aria-current={activeTab === label ? "page" : undefined}
>
<Icon size={18} strokeWidth={2} />
<span>{label}</span>
{activeTab === label && <ChevronRight size={16} className="ml-auto"
/>}
</button>
))}
</nav>
</div>
<div>
<button
onClick={() => setDarkMode(!darkMode)}
className="flex items-center gap-3 px-4 py-3 w-full rounded-xl text-sm
font-medium hover:bg-zinc-100 dark:hover:bg-zinc-700/70"
>
{darkMode ? <Sun size={18} /> : <Moon size={18} />}
<span>{darkMode ? "Light Mode" : "Dark Mode"}</span>
</button>
<div className="text-xs text-zinc-500 dark:text-zinc-400 mt-8 text-
center">
© {new Date().getFullYear()} Secreta Inc.
</div>
</div>
</aside>
{/* Main Content */}
<div className="flex-1 flex flex-col">
{/* Header */}
<header className="sticky top-0 z-30 bg-white/80 dark:bg-zinc-800/80
backdrop-blur-md border-b border-zinc-200 dark:border-zinc-700 px-4 py-4 md:px-8">
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<button
className="p-2 rounded-full hover:bg-zinc-100 dark:hover:bg-zinc-
700 md:hidden"
onClick={() => setMobileMenuOpen(true)}
>
<Menu size={20} />
</button>
<div className="relative w-full sm:w-auto">
<div className="absolute inset-y-0 left-0 pl-3 flex items-center
pointer-events-none">
<Search className="h-4 w-4 text-zinc-400" />
</div>
<Input
type="text"
placeholder="Search messages..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10 w-full sm:w-64"
/>
</div>
</div>
<div className="flex items-center gap-2">
<div className="relative" ref={notificationsRef}>
<button
className="p-2 rounded-full hover:bg-zinc-100 dark:hover:bg-zinc-
700 relative"
onClick={() => setNotificationsOpen(!notificationsOpen)}
>
<Bell size={20} />
<span className="absolute top-1 right-1 w-2 h-2 bg-red-500
rounded-full"></span>
</button>
{/* Notifications dropdown */}
{notificationsOpen && (
<div className="absolute right-0 mt-2 w-80 bg-white dark:bg-zinc-
800 rounded-xl shadow-lg border border-zinc-200 dark:border-zinc-700 py-2 z-50">
<div className="px-4 py-2 border-b border-zinc-200 dark:border-
zinc-700 flex justify-between items-center">
<h3 className="font-medium">Notifications</h3>
<button className="text-xs text-blue-500 hover:text-blue-600
dark:text-blue-400">Mark all as read</button>
</div>
<div className="max-h-80 overflow-y-auto">
{[
{ id: 1, title: "New message created", time: "10 minutes
ago", read: false },
{ id: 2, title: "Message viewed by recipient", time: "1
hour ago", read: false },
{ id: 3, title: "Security scan completed", time: "3 days
ago", read: true },
{ id: 4, title: "System update available", time: "1 week
ago", read: true },
].map(notification => (
<div
key={notification.id}
className={`px-4 py-3 hover:bg-zinc-50 dark:hover:bg-
zinc-700/50 cursor-pointer flex items-start gap-3 ${
!notification.read ? 'bg-blue-50 dark:bg-blue-900/20' :
''
}`}
>
<div className={`w-2 h-2 rounded-full mt-2 ${!
notification.read ? 'bg-blue-500' : 'bg-transparent'}`}></div>
<div>
<p className="text-sm font-
medium">{notification.title}</p>
<p className="text-xs text-zinc-500 dark:text-zinc-
400">{notification.time}</p>
</div>
</div>
))}
</div>
<div className="px-4 py-2 border-t border-zinc-200 dark:border-
zinc-700">
<button className="text-xs text-blue-500 hover:text-blue-600
dark:text-blue-400 w-full text-center">
View all notifications
</button>
</div>
</div>
)}
</div>
<div className="relative" ref={profileRef}>
<button
className="w-9 h-9 rounded-full bg-blue-100 dark:bg-zinc-700 flex
items-center justify-center text-blue-600 dark:text-blue-400 hover:ring-2
hover:ring-blue-500 dark:hover:ring-blue-400 transition-all"
onClick={() => setShowProfileMenu(!showProfileMenu)}
>
<User size={18} />
</button>
{/* Profile dropdown */}
{showProfileMenu && (
<div className="absolute right-0 mt-2 w-48 bg-white dark:bg-zinc-
800 rounded-xl shadow-lg border border-zinc-200 dark:border-zinc-700 py-2 z-50">
<button className="px-4 py-2 text-sm w-full text-left hover:bg-
zinc-50 dark:hover:bg-zinc-700/50 flex items-center gap-2">
<User size={16} />
Profile
</button>
<button className="px-4 py-2 text-sm w-full text-left hover:bg-
zinc-50 dark:hover:bg-zinc-700/50 flex items-center gap-2">
<Settings size={16} />
Settings
</button>
<div className="border-t border-zinc-200 dark:border-zinc-700
my-1"></div>
<button className="px-4 py-2 text-sm w-full text-left hover:bg-
zinc-50 dark:hover:bg-zinc-700/50 text-red-500 flex items-center gap-2">
<Key size={16} />
Sign out
</button>
</div>
)}
</div>
</div>
</div>
</header>
<main className="flex-1 px-4 py-6 md:px-8 md:py-8 transition-all">
<div className="flex flex-col gap-6">
{/* Page header */}
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-
between gap-4">
<div>
<h2 className="text-3xl font-bold">{activeTab}</h2>
<p className="text-zinc-500 dark:text-zinc-400">
{activeTab === "Dashboard" && "Welcome back, Abdul. Manage your
secure messages."}
{activeTab === "Messages" && "View and manage all your secret
messages."}
{activeTab === "Analytics" && "Track your message activity and
statistics."}
{activeTab === "Security" && "Monitor your account security
settings."}
{activeTab === "Settings" && "Configure your account
preferences."}
</p>
</div>
{activeTab === "Messages" && (
isDesktop ? (
<Dialog open={newMessageDialogOpen}
onOpenChange={setNewMessageDialogOpen}>
<DialogTrigger asChild>
<Button className="flex items-center gap-2">
<Plus size={18} />
<span>New Message</span>
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Create a New Secret Message</DialogTitle>
<DialogDescription>
Create a secure, self-destructing message or file share
</DialogDescription>
</DialogHeader>
<NewMessageForm />
<DialogFooter>
<Button variant="outline" onClick={() =>
setNewMessageDialogOpen(false)}>
Cancel
</Button>
<Button onClick={handleCreateMessage}>
Create Message
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
) : (
<Drawer open={newMessageDialogOpen}
onOpenChange={setNewMessageDialogOpen}>
<DrawerTrigger asChild>
<Button className="flex items-center gap-2">
<Plus size={18} />
<span>New Message</span>
</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Create a New Secret Message</DrawerTitle>
<DrawerDescription>
Create a secure, self-destructing message or file share
</DrawerDescription>
</DrawerHeader>
<div className="px-4">
<NewMessageForm />
</div>
<DrawerFooter>
<Button variant="outline" onClick={() =>
setNewMessageDialogOpen(false)}>
Cancel
</Button>
<Button onClick={handleCreateMessage}>
Create Message
</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
)
)}
</div>
{/* Stats overview */}
{activeTab === "Dashboard" && (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-
6">
{[
{ label: "Total Messages", value: stats.total.toLocaleString(),
icon: File, change: "+5.2%", positive: true },
{ label: "Active Messages", value: stats.active.toLocaleString(),
icon: Clock, change: "+12.3%", positive: true },
{ label: "Viewed Messages", value: stats.viewed.toLocaleString(),
icon: Eye, change: "+8.7%", positive: true },
{ label: "Expired Messages", value:
stats.expired.toLocaleString(), icon: AlertTriangle, change: "-2.4%", positive:
false },
].map((stat, i) => (
<div
key={i}
className="bg-white dark:bg-zinc-800 p-6 rounded-2xl shadow-sm
hover:shadow-md transition-all border border-zinc-100 dark:border-zinc-700"
>
<div className="flex justify-between items-start mb-4">
<div className="p-2 rounded-xl bg-blue-50 dark:bg-zinc-700">
<stat.icon size={20} className="text-blue-600 dark:text-
blue-400" />
</div>
<span className={`text-xs font-medium ${stat.positive ?
'text-green-500' : 'text-red-500'}`}>
{stat.change}
</span>
</div>
<h3 className="text-2xl font-bold mb-1">{stat.value}</h3>
<p className="text-sm text-zinc-500 dark:text-zinc-
400">{stat.label}</p>
</div>
))}
</div>
)}
{/* Main content area */}
{activeTab === "Dashboard" && (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* Activity chart */}
<div className="bg-white dark:bg-zinc-800 p-6 rounded-2xl shadow-sm
border border-zinc-100 dark:border-zinc-700 lg:col-span-2">
<div className="flex justify-between items-center mb-6">
<h3 className="font-semibold">Message Activity</h3>
<div className="flex gap-2">
<button className="px-3 py-1 text-xs rounded-lg bg-blue-100
text-blue-600 dark:bg-blue-900/30 dark:text-blue-400">Daily</button>
<button className="px-3 py-1 text-xs rounded-lg hover:bg-
zinc-100 dark:hover:bg-zinc-700">Weekly</button>
<button className="px-3 py-1 text-xs rounded-lg hover:bg-
zinc-100 dark:hover:bg-zinc-700">Monthly</button>
</div>
</div>
<ActivityChart data={activityData} />
<div className="flex justify-between mt-4 text-xs text-zinc-500
dark:text-zinc-400">
{Array.from({ length: 9 }, (_, i) => {
const date = new Date();
date.setDate(date.getDate() - (8 - i));
return date.toLocaleDateString('en-US', { weekday:
'short' });
}).map((day, i) => (
<span key={i}>{day}</span>
))}
</div>
</div>
{/* Security score */}
<div className="bg-white dark:bg-zinc-800 p-6 rounded-2xl shadow-sm
border border-zinc-100 dark:border-zinc-700 flex flex-col items-center">
<h3 className="font-semibold self-start mb-4">Security Score</h3>
<SecurityGauge score={securityScore} />
<div className="mt-6 w-full">
<div className="flex justify-between items-center mb-2">
<span className="text-sm">Encryption</span>
<span className="text-sm font-medium">100%</span>
</div>
<div className="w-full bg-zinc-200 dark:bg-zinc-700 h-2
rounded-full">
<div className="bg-green-500 h-2 rounded-full"
style={{ width: '100%' }}></div>
</div>
</div>
<div className="mt-3 w-full">
<div className="flex justify-between items-center mb-2">
<span className="text-sm">Authentication</span>
<span className="text-sm font-medium">92%</span>
</div>
<div className="w-full bg-zinc-200 dark:bg-zinc-700 h-2
rounded-full">
<div className="bg-green-500 h-2 rounded-full"
style={{ width: '92%' }}></div>
</div>
</div>
<div className="mt-3 w-full">
<div className="flex justify-between items-center mb-2">
<span className="text-sm">Vulnerabilities</span>
<span className="text-sm font-medium">68%</span>
</div>
<div className="w-full bg-zinc-200 dark:bg-zinc-700 h-2
rounded-full">
<div className="bg-yellow-500 h-2 rounded-full"
style={{ width: '68%' }}></div>
</div>
</div>
</div>
</div>
)}
{/* Messages table */}
{(activeTab === "Messages" || activeTab === "Dashboard") && (
<div className="bg-white dark:bg-zinc-800 p-6 rounded-2xl shadow-sm
border border-zinc-100 dark:border-zinc-700">
<div className="flex justify-between items-center mb-6">
<h3 className="font-semibold">Recent Messages</h3>
<button className="text-sm text-blue-600 dark:text-blue-400
hover:underline">View all</button>
</div>
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-zinc-200
dark:divide-zinc-700">
<thead>
<tr>
<th className="py-3 px-4 text-left text-xs font-medium
text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">ID</th>
<th className="py-3 px-4 text-left text-xs font-medium
text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Type</th>
<th className="py-3 px-4 text-left text-xs font-medium
text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Status</th>
<th className="py-3 px-4 text-left text-xs font-medium
text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Expires In</th>
<th className="py-3 px-4 text-left text-xs font-medium
text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Creator</th>
<th className="py-3 px-4 text-left text-xs font-medium
text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody className="divide-y divide-zinc-200 dark:divide-zinc-
700">
{(activeTab === "Dashboard" ? filteredMessages.slice(0, 5) :
filteredMessages).map((message) => (
<tr key={message.id} className="hover:bg-zinc-50
dark:hover:bg-zinc-700/50 transition-colors">
<td className="py-4 px-4 text-sm font-
medium">{message.id}</td>
<td className="py-4 px-4 text-sm">
<Badge variant="outline" className="font-normal">
{message.type}
</Badge>
</td>
<td className="py-4 px-4 text-sm">
<Badge
variant={
message.status === 'Active' ? 'success' :
message.status === 'Viewed' ? 'info' : 'secondary'
}
>
{message.status}
</Badge>
</td>
<td className="py-4 px-4 text-sm">
{message.expiresIn === "Expired" ? (
<span className="text-zinc-500 dark:text-zinc-
400">Expired</span>
) : (
message.expiresIn
)}
</td>
<td className="py-4 px-4 text-sm">{message.creator}</td>
<td className="py-4 px-4 text-sm">
<div className="flex items-center gap-2">
<button
onClick={() => {
setSelectedMessage(message);
if (isDesktop) {
setDeleteDialogOpen(true);
} else {
setMessageToDelete(message.id);
setDeleteDialogOpen(true);
}
}}
className="p-1.5 rounded-lg hover:bg-zinc-100
dark:hover:bg-zinc-700"
>
<Trash2 size={16} className="text-zinc-500
hover:text-red-500" />
</button>
<button
onClick={() => {
copyToClipboard(`https://secreta.app/m/$
{message.id}`);
}}
className="p-1.5 rounded-lg hover:bg-zinc-100
dark:hover:bg-zinc-700"
>
<Copy size={16} className="text-zinc-500
hover:text-blue-500" />
</button>
<button
onClick={() => setSelectedMessage(message)}
className="p-1.5 rounded-lg hover:bg-zinc-100
dark:hover:bg-zinc-700"
>
<Eye size={16} className="text-zinc-500 hover:text-
blue-500" />
</button>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
{filteredMessages.length === 0 && (
<div className="text-center py-12">
<div className="flex justify-center">
<File className="w-12 h-12 text-zinc-400 dark:text-zinc-
500" />
</div>
<h3 className="mt-4 text-lg font-medium">No messages found</h3>
<p className="mt-2 text-zinc-500 dark:text-zinc-400 text-sm">
Create a new message or try adjusting your search.
</p>
</div>
)}
</div>
)}
{/* Security */}
{activeTab === "Security" && (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="bg-white dark:bg-zinc-800 p-6 rounded-2xl shadow-sm
border border-zinc-100 dark:border-zinc-700">
<div className="flex items-center gap-3 mb-4">
<div className="p-2 rounded-xl bg-blue-50 dark:bg-zinc-700">
<Shield size={20} className="text-blue-600 dark:text-blue-
400" />
</div>
<h3 className="font-semibold">Security Center</h3>
</div>
<div className="mt-6">
<SecurityGauge score={securityScore} />
<div className="mt-8 space-y-4">
<div className="flex justify-between items-center">
<div className="flex items-center gap-3">
<div className="p-2 rounded-lg bg-green-100 dark:bg-
green-900/30">
<Activity size={16} className="text-green-600
dark:text-green-400" />
</div>
<div>
<p className="text-sm font-medium">Two-factor
authentication</p>
<p className="text-xs text-zinc-500 dark:text-zinc-
400">Enabled for all logins</p>
</div>
</div>
<Switch checked={true} />
</div>
<div className="flex justify-between items-center">
<div className="flex items-center gap-3">
<div className="p-2 rounded-lg bg-blue-100 dark:bg-blue-
900/30">
<Lock size={16} className="text-blue-600 dark:text-
blue-400" />
</div>
<div>
<p className="text-sm font-medium">End-to-end
encryption</p>
<p className="text-xs text-zinc-500 dark:text-zinc-
400">All messages encrypted</p>
</div>
</div>
<Switch checked={true} />
</div>
<div className="flex justify-between items-center">
<div className="flex items-center gap-3">
<div className="p-2 rounded-lg bg-amber-100 dark:bg-
amber-900/30">
<AlertTriangle size={16} className="text-amber-600
dark:text-amber-400" />
</div>
<div>
<p className="text-sm font-medium">Login alerts</p>
<p className="text-xs text-zinc-500 dark:text-zinc-
400">Get notified of new logins</p>
</div>
</div>
<Switch checked={true} />
</div>
<div className="flex justify-between items-center">
<div className="flex items-center gap-3">
<div className="p-2 rounded-lg bg-zinc-100 dark:bg-zinc-
700">
<FileCheck size={16} className="text-zinc-600
dark:text-zinc-400" />
</div>
<div>
<p className="text-sm font-medium">Auto-delete expired
content</p>
<p className="text-xs text-zinc-500 dark:text-zinc-
400">Automatically remove expired messages</p>
</div>
</div>
<Switch checked={false} />
</div>
</div>
</div>
</div>
<div className="bg-white dark:bg-zinc-800 p-6 rounded-2xl shadow-sm
border border-zinc-100 dark:border-zinc-700 lg:col-span-2">
<div className="flex items-center gap-3 mb-6">
<div className="p-2 rounded-xl bg-blue-50 dark:bg-zinc-700">
<Key size={20} className="text-blue-600 dark:text-blue-
400" />
</div>
<h3 className="font-semibold">Access Log</h3>
</div>
<div className="space-y-4">
{[
{ event: "Login successful", location: "New York, USA", ip:
"192.168.1.1", time: "Today, 14:32", status: "success" },
{ event: "Password changed", location: "New York, USA", ip:
"192.168.1.1", time: "Today, 12:17", status: "success" },
{ event: "Failed login attempt", location: "Chicago, USA",
ip: "203.45.67.89", time: "Yesterday, 22:43", status: "warning" },
{ event: "New device authorized", location: "New York, USA",
ip: "192.168.1.5", time: "2 days ago", status: "success" },
{ event: "Security settings updated", location: "New York,
USA", ip: "192.168.1.1", time: "1 week ago", status: "success" },
].map((log, i) => (
<div key={i} className="flex items-center justify-between py-
3 border-b border-zinc-100 dark:border-zinc-700 last:border-0">
<div className="flex items-center gap-3">
<div className={`w-2 h-2 rounded-full ${
log.status === 'success' ? 'bg-green-500' :
log.status === 'warning' ? 'bg-amber-500' : 'bg-red-
500'
}`}></div>
<div>
<p className="text-sm font-medium">{log.event}</p>
<p className="text-xs text-zinc-500 dark:text-zinc-
400">{log.time}</p>
</div>
</div>
<div className="text-right">
<p className="text-sm">{log.location}</p>
<p className="text-xs text-zinc-500 dark:text-zinc-
400">{log.ip}</p>
</div>
</div>
))}
</div>
<div className="mt-6">
<Button variant="outline" className="w-full">View Full Activity
Log</Button>
</div>
</div>
</div>
)}
{/* Settings */}
{activeTab === "Settings" && (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2 bg-white dark:bg-zinc-800 p-6
rounded-2xl shadow-sm border border-zinc-100 dark:border-zinc-700">
<h3 className="font-semibold mb-6">General Settings</h3>
<div className="space-y-6">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="full-name">Full Name</Label>
<Input id="full-name" value="Abdul Kamil" />
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" value="[email protected]" />
</div>
</div>
<div className="space-y-2">
<Label htmlFor="timezone">Timezone</Label>
<Select defaultValue="america-new_york">
<SelectTrigger>
<SelectValue placeholder="Select timezone" />
</SelectTrigger>
<SelectContent>
<SelectItem value="america-new_york">America/New York
(UTC-05:00)</SelectItem>
<SelectItem value="america-los_angeles">America/Los
Angeles (UTC-08:00)</SelectItem>
<SelectItem value="europe-london">Europe/London
(UTC+00:00)</SelectItem>
<SelectItem value="asia-tokyo">Asia/Tokyo
(UTC+09:00)</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex items-center justify-between space-x-2">
<div>
<p className="font-medium">Dark Mode</p>
<p className="text-sm text-zinc-500 dark:text-zinc-400">Use
dark theme for the interface</p>
</div>
<Switch checked={darkMode} onCheckedChange={setDarkMode} />
</div>
<div className="flex items-center justify-between space-x-2">
<div>
<p className="font-medium">Email Notifications</p>
<p className="text-sm text-zinc-500 dark:text-zinc-
400">Receive email notifications</p>
</div>
<Switch defaultChecked />
</div>
<Button>Save Changes</Button>
</div>
</div>
<div className="bg-white dark:bg-zinc-800 p-6 rounded-2xl shadow-sm
border border-zinc-100 dark:border-zinc-700">
<h3 className="font-semibold mb-6">Account</h3>
<div className="space-y-6">
<div className="flex items-center gap-4">
<div className="w-16 h-16 rounded-full bg-blue-100 dark:bg-
zinc-700 flex items-center justify-center text-blue-600 dark:text-blue-400">
<User size={32} />
</div>
<div>
<p className="font-medium">Abdul Kamil</p>
<p className="text-sm text-zinc-500 dark:text-zinc-
400">Administrator</p>
</div>
</div>
<div className="flex items-center justify-between pt-4 border-t
border-zinc-200 dark:border-zinc-700">
<div>
<p className="font-medium">Security Level</p>
<p className="text-sm text-zinc-500 dark:text-zinc-
400">Enhanced Security</p>
</div>
<Button variant="outline" size="sm">Change</Button>
</div>
<div className="flex items-center justify-between pt-4 border-t
border-zinc-200 dark:border-zinc-700">
<div>
<p className="font-medium">Password</p>
<p className="text-sm text-zinc-500 dark:text-zinc-
400">Last changed 3 weeks ago</p>
</div>
<Button variant="outline" size="sm">Change</Button>
</div>
<div className="pt-4 border-t border-zinc-200 dark:border-zinc-
700">
<Button variant="destructive" className="w-full">
Delete Account
</Button>
</div>
</div>
</div>
</div>
)}
{/* Analytics */}
{activeTab === "Analytics" && (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2 bg-white dark:bg-zinc-800 p-6
rounded-2xl shadow-sm border border-zinc-100 dark:border-zinc-700">
<div className="flex items-center justify-between mb-6">
<h3 className="font-semibold">Message Statistics</h3>
<Select defaultValue="weekly">
<SelectTrigger className="w-32">
<SelectValue placeholder="Time period" />
</SelectTrigger>
<SelectContent>
<SelectItem value="daily">Daily</SelectItem>
<SelectItem value="weekly">Weekly</SelectItem>
<SelectItem value="monthly">Monthly</SelectItem>
</SelectContent>
</Select>
</div>
<ActivityChart data={[30, 45, 60, 70, 55, 80, 65, 90, 75]} />
<div className="mt-8 grid grid-cols-1 sm:grid-cols-3 gap-4">
{[
{ label: "Total Messages", value: stats.total, change:
"+8%" },
{ label: "Average Views", value: "2.4", change: "+12%" },
{ label: "View Rate", value: "76%", change: "+5%" },
].map((stat, i) => (
<div key={i} className="bg-zinc-50 dark:bg-zinc-800 p-4
rounded-xl border border-zinc-100 dark:border-zinc-700">
<p className="text-sm text-zinc-500 dark:text-zinc-
400">{stat.label}</p>
<div className="flex items-baseline gap-2 mt-1">
<p className="text-2xl font-bold">{stat.value}</p>
<span className="text-xs font-medium text-green-
500">{stat.change}</span>
</div>
</div>
))}
</div>
</div>
<div className="bg-white dark:bg-zinc-800 p-6 rounded-2xl shadow-sm
border border-zinc-100 dark:border-zinc-700">
<h3 className="font-semibold mb-6">Message Type Distribution</h3>
<div className="space-y-4">
{[
{ type: "Text", percentage: 45, color: "bg-blue-500" },
{ type: "File", percentage: 25, color: "bg-green-500" },
{ type: "Image", percentage: 20, color: "bg-yellow-500" },
{ type: "Video", percentage: 10, color: "bg-purple-500" },
].map((item, i) => (
<div key={i} className="space-y-1">
<div className="flex justify-between items-center">
<p className="text-sm">{item.type}</p>
<p className="text-sm font-medium">{item.percentage}%</p>
</div>
<div className="w-full bg-zinc-200 dark:bg-zinc-700 h-2
rounded-full">
<div className={`${item.color} h-2 rounded-full`}
style={{ width: `${item.percentage}%` }}></div>
</div>
</div>
))}
</div>
<div className="mt-8">
<h4 className="text-sm font-medium mb-4">Top Creators</h4>
<div className="space-y-3">
{[
{ user: "[email protected]", count: 24 },
{ user: "[email protected]", count: 18 },
{ user: "[email protected]", count: 15 },
{ user: "[email protected]", count: 10 },
].map((user, i) => (
<div key={i} className="flex items-center justify-between
py-2 border-b border-zinc-100 dark:border-zinc-700 last:border-0">
<p className="text-sm">{user.user}</p>
<Badge variant="outline">{user.count} messages</Badge>
</div>
))}
</div>
</div>
</div>
</div>
)}
</div>
</main>
</div>
{/* Message details dialog (desktop) */}
{isDesktop && selectedMessage && (
<Dialog open={!!selectedMessage} onOpenChange={() =>
setSelectedMessage(null)}>
<MessageViewDialog />
</Dialog>
)}
{/* Message details drawer (mobile) */}
{!isDesktop && selectedMessage && (
<Drawer open={!!selectedMessage} onOpenChange={() =>
setSelectedMessage(null)}>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Message Details: {selectedMessage?.id}</DrawerTitle>
<DrawerDescription>
{selectedMessage?.type} message created on
{selectedMessage?.createdAt.toLocaleString()}
</DrawerDescription>
</DrawerHeader>
<div className="px-4 py-2 space-y-4">
<div className="grid grid-cols-2 gap-4">
<div>
<Label>Status</Label>
<div className="mt-1">
<Badge
variant={
selectedMessage?.status === 'Active' ? 'success' :
selectedMessage?.status === 'Viewed' ? 'info' : 'secondary'
}
>
{selectedMessage?.status}
</Badge>
</div>
</div>
<div>
<Label>Expires In</Label>
<p className="mt-1 text-sm">{selectedMessage?.expiresIn}</p>
</div>
<div>
<Label>Creator</Label>
<p className="mt-1 text-sm">{selectedMessage?.creator}</p>
</div>
<div>
<Label>Views</Label>
<p className="mt-1 text-sm">{selectedMessage?.views}</p>
</div>
</div>
<div>
<Label>Content</Label>
<div className="mt-1 p-3 bg-zinc-100 dark:bg-zinc-800 rounded-md">
<p className="text-sm">{selectedMessage?.content}</p>
</div>
</div>
</div>
<DrawerFooter className="gap-2">
<Button
variant="outline"
onClick={() => {
copyToClipboard(`https://secreta.app/m/${selectedMessage?.id}`);
}}
>
<Copy className="mr-2 h-4 w-4" />
Copy Link
</Button>
<Button
variant="destructive"
onClick={() => {
setMessageToDelete(selectedMessage?.id);
setDeleteDialogOpen(true);
}}
>
<Trash2 className="mr-2 h-4 w-4" />
Delete
</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
)}
<Dialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Delete Message</DialogTitle>
<DialogDescription>
Are you sure you want to delete this message? This action cannot be undone.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline" onClick={() => setDeleteDialogOpen(false)}>
Cancel
</Button>
<Button
variant="destructive"
onClick={() => handleDeleteMessage(messageToDelete)}
>
Delete
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};
export default Index;