Create dashboard for Discord bot
Implement a dashboard interface to manage the Discord bot with a dark theme and a soothing purple primary color. The dashboard will facilitate interaction with the bot's functionalities across the user's Discord server(s). [skip gpt_engineer]
This commit is contained in:
45
src/components/dashboard/DashboardSidebar.tsx
Normal file
45
src/components/dashboard/DashboardSidebar.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Home, Server, Settings, Activity, HelpCircle } from "lucide-react";
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "@/components/ui/sidebar";
|
||||
|
||||
const menuItems = [
|
||||
{ title: "Overview", icon: Home, url: "/" },
|
||||
{ title: "Servers", icon: Server, url: "/servers" },
|
||||
{ title: "Activity", icon: Activity, url: "/activity" },
|
||||
{ title: "Settings", icon: Settings, url: "/settings" },
|
||||
{ title: "Help", icon: HelpCircle, url: "/help" },
|
||||
];
|
||||
|
||||
export function DashboardSidebar() {
|
||||
return (
|
||||
<Sidebar>
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Dashboard</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{menuItems.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url} className="flex items-center gap-3">
|
||||
<item.icon className="w-5 h-5" />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
</Sidebar>
|
||||
);
|
||||
}
|
||||
27
src/components/dashboard/ServerCard.tsx
Normal file
27
src/components/dashboard/ServerCard.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Server } from "lucide-react";
|
||||
import { Card } from "@/components/ui/card";
|
||||
|
||||
interface ServerCardProps {
|
||||
name: string;
|
||||
memberCount: number;
|
||||
botStatus: "online" | "offline";
|
||||
}
|
||||
|
||||
export const ServerCard = ({ name, memberCount, botStatus }: ServerCardProps) => {
|
||||
return (
|
||||
<Card className="glass-card hover-scale">
|
||||
<div className="p-6 flex items-start gap-4">
|
||||
<div className="p-3 rounded-full bg-primary/10">
|
||||
<Server className="w-6 h-6 text-primary" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="font-semibold text-lg">{name}</h3>
|
||||
<p className="text-muted-foreground">{memberCount} members</p>
|
||||
</div>
|
||||
<div className={`px-3 py-1 rounded-full text-sm ${botStatus === 'online' ? 'bg-green-500/20 text-green-400' : 'bg-destructive/20 text-destructive'}`}>
|
||||
{botStatus}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
17
src/components/dashboard/StatCard.tsx
Normal file
17
src/components/dashboard/StatCard.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
interface StatCardProps {
|
||||
title: string;
|
||||
value: string | number;
|
||||
icon: React.ReactNode;
|
||||
}
|
||||
|
||||
export const StatCard = ({ title, value, icon }: StatCardProps) => {
|
||||
return (
|
||||
<div className="stat-card">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-muted-foreground">{title}</p>
|
||||
<div className="text-primary">{icon}</div>
|
||||
</div>
|
||||
<p className="text-2xl font-semibold">{value}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
103
src/index.css
103
src/index.css
@@ -4,89 +4,35 @@
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
--background: 222 26% 13%;
|
||||
--foreground: 210 40% 98%;
|
||||
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
--card: 222 26% 15%;
|
||||
--card-foreground: 210 40% 98%;
|
||||
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
--popover: 222 26% 13%;
|
||||
--popover-foreground: 210 40% 98%;
|
||||
|
||||
--primary: 222.2 47.4% 11.2%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
--primary: 255 52% 75%;
|
||||
--primary-foreground: 222 26% 13%;
|
||||
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
--secondary: 222 26% 15%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
--muted: 222 26% 20%;
|
||||
--muted-foreground: 215 20.2% 65.1%;
|
||||
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
--accent: 255 52% 75%;
|
||||
--accent-foreground: 222 26% 13%;
|
||||
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--ring: 222.2 84% 4.9%;
|
||||
--border: 222 26% 20%;
|
||||
--input: 222 26% 20%;
|
||||
--ring: 255 52% 75%;
|
||||
|
||||
--radius: 0.5rem;
|
||||
|
||||
--sidebar-background: 0 0% 98%;
|
||||
|
||||
--sidebar-foreground: 240 5.3% 26.1%;
|
||||
|
||||
--sidebar-primary: 240 5.9% 10%;
|
||||
|
||||
--sidebar-primary-foreground: 0 0% 98%;
|
||||
|
||||
--sidebar-accent: 240 4.8% 95.9%;
|
||||
|
||||
--sidebar-accent-foreground: 240 5.9% 10%;
|
||||
|
||||
--sidebar-border: 220 13% 91%;
|
||||
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
|
||||
--card: 222.2 84% 4.9%;
|
||||
--card-foreground: 210 40% 98%;
|
||||
|
||||
--popover: 222.2 84% 4.9%;
|
||||
--popover-foreground: 210 40% 98%;
|
||||
|
||||
--primary: 210 40% 98%;
|
||||
--primary-foreground: 222.2 47.4% 11.2%;
|
||||
|
||||
--secondary: 217.2 32.6% 17.5%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
|
||||
--muted: 217.2 32.6% 17.5%;
|
||||
--muted-foreground: 215 20.2% 65.1%;
|
||||
|
||||
--accent: 217.2 32.6% 17.5%;
|
||||
--accent-foreground: 210 40% 98%;
|
||||
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
|
||||
--border: 217.2 32.6% 17.5%;
|
||||
--input: 217.2 32.6% 17.5%;
|
||||
--ring: 212.7 26.8% 83.9%;
|
||||
--sidebar-background: 240 5.9% 10%;
|
||||
--sidebar-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-primary: 224.3 76.3% 48%;
|
||||
--sidebar-primary-foreground: 0 0% 100%;
|
||||
--sidebar-accent: 240 3.7% 15.9%;
|
||||
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-border: 240 3.7% 15.9%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
--radius: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,8 +40,19 @@
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
|
||||
.glass-card {
|
||||
@apply bg-card/30 backdrop-blur-sm border border-white/10;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
@apply glass-card p-6 rounded-lg flex flex-col gap-2;
|
||||
}
|
||||
|
||||
.hover-scale {
|
||||
@apply transition-transform duration-200 hover:scale-[1.02];
|
||||
}
|
||||
@@ -1,14 +1,55 @@
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
import { Activity, MessageCircle, Server, Users } from "lucide-react";
|
||||
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar";
|
||||
import { DashboardSidebar } from "@/components/dashboard/DashboardSidebar";
|
||||
import { ServerCard } from "@/components/dashboard/ServerCard";
|
||||
import { StatCard } from "@/components/dashboard/StatCard";
|
||||
|
||||
const Index = () => {
|
||||
// Mock data - replace with actual data when integrating with Discord
|
||||
const stats = [
|
||||
{ title: "Total Servers", value: "12", icon: <Server className="w-5 h-5" /> },
|
||||
{ title: "Active Users", value: "1,234", icon: <Users className="w-5 h-5" /> },
|
||||
{ title: "Commands Used", value: "8,392", icon: <MessageCircle className="w-5 h-5" /> },
|
||||
{ title: "Uptime", value: "99.9%", icon: <Activity className="w-5 h-5" /> },
|
||||
];
|
||||
|
||||
const servers = [
|
||||
{ name: "Gaming Community", memberCount: 1234, botStatus: "online" as const },
|
||||
{ name: "Developer Hub", memberCount: 567, botStatus: "online" as const },
|
||||
{ name: "Music Lovers", memberCount: 890, botStatus: "offline" as const },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-100">
|
||||
<div className="text-center">
|
||||
<h1 className="text-4xl font-bold mb-4">Welcome to Your Blank App</h1>
|
||||
<p className="text-xl text-gray-600">Start building your amazing project here!</p>
|
||||
<SidebarProvider>
|
||||
<div className="min-h-screen flex w-full">
|
||||
<DashboardSidebar />
|
||||
<main className="flex-1 p-8">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold">Dashboard</h1>
|
||||
<p className="text-muted-foreground">Manage your Discord bot</p>
|
||||
</div>
|
||||
<SidebarTrigger />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
|
||||
{stats.map((stat) => (
|
||||
<StatCard key={stat.title} {...stat} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<h2 className="text-xl font-semibold mb-4">Connected Servers</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{servers.map((server) => (
|
||||
<ServerCard key={server.name} {...server} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</SidebarProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Index;
|
||||
export default Index;
|
||||
Reference in New Issue
Block a user