Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
18 views26 pages

React

The document is a React component that implements a messaging application with features like message creation, viewing, and deletion. It includes a user interface with navigation, dialogs, and forms for managing messages, as well as state management for dark mode and responsive design. Additionally, it generates sample messages and calculates various statistics related to message activity and security scores.

Uploaded by

Prasanna Krishna
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views26 pages

React

The document is a React component that implements a messaging application with features like message creation, viewing, and deletion. It includes a user interface with navigation, dialogs, and forms for managing messages, as well as state management for dark mode and responsive design. Additionally, it generates sample messages and calculates various statistics related to message activity and security scores.

Uploaded by

Prasanna Krishna
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 26

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">
&copy; {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">
&copy; {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;

You might also like