Skip to content

Commit 2e1da12

Browse files
Merge pull request #195 from ManagerX-Development/dev-builds/2.0.0-dashboard
feat: implement dashboard web interface with guild selection, authent…
2 parents e14e75c + fb75652 commit 2e1da12

9 files changed

Lines changed: 303 additions & 48 deletions

File tree

src/web/App.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const License = lazy(() => import("./pages/License").then(module => ({ default:
1919
const LoginPage = lazy(() => import("./dashboard/LoginPage"));
2020
const SettingsPage = lazy(() => import("./dashboard/SettingsPage"));
2121
const UserSettingsPage = lazy(() => import("./dashboard/UserSettingsPage"));
22+
const GuildSelectionPage = lazy(() => import("./dashboard/GuildSelectionPage"));
2223
const AuthCallback = lazy(() => import("./pages/AuthCallback"));
2324

2425
const queryClient = new QueryClient();
@@ -64,6 +65,7 @@ const DashboardRoutes = () => {
6465
<Route path="/dash/login" element={<LoginPage />} />
6566
<Route path="/dash/auth/callback" element={<AuthCallback />} />
6667
<Route path="/auth/callback" element={<AuthCallback />} />
68+
<Route path="/dash/guilds" element={<GuildSelectionPage />} />
6769
<Route path="/dash/settings" element={<SettingsPage />} />
6870
<Route path="/dash" element={<LoginPage />} />
6971
<Route path="/" element={<LoginPage />} />
@@ -108,6 +110,7 @@ const MainRoutes = () => {
108110
<Route path="/leaderboard" element={<LeaderboardPage />} />
109111
<Route path="/dash/auth/callback" element={<AuthCallback />} />
110112
<Route path="/auth/callback" element={<AuthCallback />} />
113+
<Route path="/dash/guilds" element={<GuildSelectionPage />} />
111114
<Route path="/dash/settings" element={<SettingsPage />} />
112115
<Route path="/dash/login" element={<LoginPage />} />
113116
<Route path="/dash/user/settings" element={<UserSettingsPage />} />

src/web/components/AuthProvider.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,19 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
6868
"X-Discord-Token": localStorage.getItem("discord_token") || ""
6969
}
7070
})
71-
.then(res => res.status === 401 ? logout() : res.json())
72-
.then(data => {
73-
if (data?.user) setUser(data.user);
74-
if (data?.guilds) {
75-
setGuilds(data.guilds);
76-
if (!selectedGuildId && data.guilds.length > 0) {
77-
setSelectedGuildId(data.guilds[0].id);
78-
localStorage.setItem("selectedGuildId", data.guilds[0].id);
71+
72+
.then(async (res) => {
73+
if (res.status === 401) {
74+
logout();
75+
throw new Error("Session expired");
76+
}
77+
if (!res.ok) throw new Error("Failed to fetch user data");
78+
return res.json();
79+
})
80+
.then(data => {
81+
if (data.user) setUser(data.user);
82+
if (data.guilds) {
83+
setGuilds(data.guilds);
7984
}
8085
}
8186
})

src/web/components/Hero.tsx

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { memo } from "react";
22
import { motion } from "framer-motion";
33
import { Link } from "react-router-dom";
44
import { Shield, Users, MessageCircle, Sparkles, Zap, Activity, ArrowRight } from "lucide-react";
5-
import { useStats } from "@/hooks/useStats";
5+
import { useStats } from "../hooks/useStats";
66

77
export const Hero = memo(function Hero() {
88
const { data, isLoading } = useStats();
@@ -61,50 +61,50 @@ export const Hero = memo(function Hero() {
6161

6262
{/* Title */}
6363
<motion.h1
64-
initial={{ opacity: 0, y: 20 }}
65-
animate={{ opacity: 1, y: 0 }}
66-
transition={{ delay: 0.1 }}
67-
className="text-7xl md:text-9xl font-bold mb-8 tracking-tighter leading-tight"
64+
initial={{ opacity: 0, scale: 0.9 }}
65+
animate={{ opacity: 1, scale: 1 }}
66+
transition={{ type: "spring", damping: 20 }}
67+
className="text-8xl md:text-[11rem] font-black mb-8 tracking-tighter leading-[0.85] select-none"
6868
>
69-
Manager<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary to-accent drop-shadow-[0_0_30px_rgba(255,0,0,0.3)]">X</span>
69+
Manager<span className="text-transparent bg-clip-text bg-gradient-to-br from-primary via-primary to-accent drop-shadow-[0_0_50px_rgba(220,38,38,0.5)]">X</span>
7070
</motion.h1>
7171

7272
{/* Description */}
7373
<motion.p
7474
initial={{ opacity: 0, y: 20 }}
7575
animate={{ opacity: 1, y: 0 }}
7676
transition={{ delay: 0.2 }}
77-
className="text-xl md:text-2xl text-muted-foreground max-w-3xl mb-12 font-medium leading-relaxed"
77+
className="text-xl md:text-2xl text-muted-foreground max-w-2xl mb-14 font-medium leading-relaxed opacity-80"
7878
>
7979
Die nächste Generation der Discord Server-Verwaltung. <br className="hidden md:block" />
80-
<span className="text-foreground">Sicher, schnell und vollständig anpassbar.</span>
80+
<span className="text-white">Sicher, blitzschnell und grenzenlos anpassbar.</span>
8181
</motion.p>
8282

8383
{/* Action Row */}
8484
<motion.div
8585
initial={{ opacity: 0, y: 20 }}
8686
animate={{ opacity: 1, y: 0 }}
8787
transition={{ delay: 0.3 }}
88-
className="flex flex-col sm:flex-row items-center gap-5 mb-20"
88+
className="flex flex-col sm:flex-row items-center gap-6 mb-24"
8989
>
9090
<motion.a
91-
whileHover={{ scale: 1.02 }}
92-
whileTap={{ scale: 0.98 }}
91+
whileHover={{ scale: 1.05, y: -2 }}
92+
whileTap={{ scale: 0.95 }}
9393
href="https://discord.com/oauth2/authorize?client_id=1368201272624287754&permissions=1669118160151&integration_type=0&scope=bot"
9494
target="_blank"
9595
rel="noopener noreferrer"
96-
className="btn-primary inline-flex items-center gap-3"
96+
className="btn-primary inline-flex items-center gap-3 !px-12 !py-5 !text-xl shadow-[0_20px_50px_-12px_rgba(220,38,38,0.5)]"
9797
>
9898
<span>Bot einladen</span>
99-
<ArrowRight className="w-5 h-5" />
99+
<ArrowRight className="w-6 h-6" />
100100
</motion.a>
101101
<motion.a
102-
whileHover={{ scale: 1.02 }}
103-
whileTap={{ scale: 0.98 }}
102+
whileHover={{ scale: 1.05, bg: "rgba(255,255,255,0.1)" }}
103+
whileTap={{ scale: 0.95 }}
104104
href="#features"
105-
className="inline-flex items-center gap-2 px-10 py-4.5 rounded-2xl glass border border-white/10 font-bold text-lg text-white shadow-lg"
105+
className="inline-flex items-center gap-2 px-12 py-5 rounded-2xl glass border border-white/10 font-bold text-xl text-white shadow-xl transition-all"
106106
>
107-
Features entdecken
107+
Learn More
108108
</motion.a>
109109
</motion.div>
110110

src/web/components/Navbar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ export function Navbar() {
169169
<User className="w-5 h-5" />
170170
</Link>
171171
<Link
172-
to="/dash/settings"
172+
to="/dash/guilds"
173173
className="btn-primary inline-flex items-center gap-2.5 !px-6 !py-2.5 !text-sm group"
174174
>
175175
<LayoutDashboard className="w-4 h-4 group-hover:rotate-12 transition-transform" />

src/web/components/OverviewSettings.tsx

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "./ui/
44
import { Users, MessageSquare, Zap, Activity, TrendingUp, ArrowUpRight, ArrowDownRight } from "lucide-react";
55
import { motion } from "framer-motion";
66
import OverviewCharts from "./OverviewCharts";
7+
import { Badge } from "./ui/badge";
8+
import { CheckCircle, XCircle } from "lucide-react";
79

810
interface OverviewSettingsProps {
911
guildId: string | null;
1012
initialStats?: any;
13+
settings?: any;
1114
}
1215

13-
export default function OverviewSettings({ guildId, initialStats }: OverviewSettingsProps) {
16+
export default function OverviewSettings({ guildId, initialStats, settings }: OverviewSettingsProps) {
1417
const [stats, setStats] = useState<any>(initialStats || null);
1518
const [loading, setLoading] = useState(!initialStats);
1619

@@ -121,31 +124,79 @@ export default function OverviewSettings({ guildId, initialStats }: OverviewSett
121124
/>
122125
</div>
123126

124-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
125-
<Card className="bg-white/[0.03] border-white/5 backdrop-blur-xl rounded-[32px] overflow-hidden">
126-
<CardHeader>
127-
<CardTitle className="flex items-center gap-2">
128-
<Activity className="w-5 h-5 text-primary" /> Nachrichten Volumen
129-
</CardTitle>
130-
<CardDescription>Aktivität der letzten 7 Tage</CardDescription>
127+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
128+
{/* Bot Health & Activity Summary */}
129+
<Card className="lg:col-span-2 glass border-white/10 shadow-2xl rounded-[2.5rem] overflow-hidden">
130+
<CardHeader className="flex flex-row items-center justify-between">
131+
<div className="space-y-1">
132+
<CardTitle className="flex items-center gap-2">
133+
<Activity className="w-5 h-5 text-primary" /> Command Center
134+
</CardTitle>
135+
<CardDescription>Live-Metriken deiner Server-Instanz</CardDescription>
136+
</div>
137+
<Badge variant="outline" className="bg-primary/10 text-primary border-primary/20 px-3 py-1">
138+
Live updates
139+
</Badge>
131140
</CardHeader>
132141
<CardContent>
133-
<OverviewCharts data={messageData} type="messages" color="#3B82F6" />
142+
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
143+
<div className="space-y-6">
144+
<div className="p-5 rounded-3xl bg-white/5 border border-white/10">
145+
<OverviewCharts data={messageData} type="messages" color="#DC2626" height={180} />
146+
<p className="text-center text-[10px] font-bold uppercase tracking-widest text-muted-foreground mt-4">Nachrichten Volumen (7 Tage)</p>
147+
</div>
148+
</div>
149+
<div className="grid grid-cols-2 gap-4">
150+
<QuickStat title="Server Age" value="238d" />
151+
<QuickStat title="Avg Activity" value="High" />
152+
<QuickStat title="Staff Count" value="12" />
153+
<QuickStat title="Uptime" value="99.9%" />
154+
</div>
155+
</div>
134156
</CardContent>
135157
</Card>
136158

137-
<Card className="bg-white/[0.03] border-white/5 backdrop-blur-xl rounded-[32px] overflow-hidden">
159+
{/* Module Status Sidebar */}
160+
<Card className="glass border-white/10 shadow-2xl rounded-[2.5rem] overflow-hidden">
138161
<CardHeader>
139-
<CardTitle className="flex items-center gap-2">
140-
<Users className="w-5 h-5 text-emerald-400" /> Mitglieder Wachstum
141-
</CardTitle>
142-
<CardDescription>Wachstumstrend der Woche</CardDescription>
162+
<CardTitle className="text-xl font-bold">Module Status</CardTitle>
163+
<CardDescription>Aktive Bot-Funktionen</CardDescription>
143164
</CardHeader>
144-
<CardContent>
145-
<OverviewCharts data={memberData} type="members" color="#10B981" />
165+
<CardContent className="space-y-3">
166+
<ModuleRow name="Level System" active={true} />
167+
<ModuleRow name="Anti-Spam AI" active={true} />
168+
<ModuleRow name="Welcome Suite" active={settings?.welcome_message ?? false} />
169+
<ModuleRow name="Global Network" active={true} />
170+
<ModuleRow name="Auto-Mod" active={settings?.auto_mod ?? true} />
171+
<ModuleRow name="Logging" active={true} />
172+
<ModuleRow name="Economy" active={false} />
146173
</CardContent>
147174
</Card>
148175
</div>
149176
</div>
150177
);
151178
}
179+
180+
const QuickStat = ({ title, value }: { title: string, value: string }) => (
181+
<div className="p-4 rounded-2xl bg-white/5 border border-white/5 flex flex-col justify-center">
182+
<span className="text-[10px] font-bold uppercase tracking-widest text-muted-foreground mb-1">{title}</span>
183+
<span className="text-lg font-black text-white">{value}</span>
184+
</div>
185+
);
186+
187+
const ModuleRow = ({ name, active }: { name: string, active: boolean }) => (
188+
<div className="flex items-center justify-between p-3 rounded-xl bg-white/5 border border-white/5 group hover:bg-white/10 transition-all">
189+
<span className="text-sm font-bold text-white/80">{name}</span>
190+
{active ? (
191+
<div className="flex items-center gap-1.5 text-emerald-500 bg-emerald-500/10 px-2 py-0.5 rounded-full border border-emerald-500/20">
192+
<CheckCircle className="w-3 h-3" />
193+
<span className="text-[9px] font-black uppercase tracking-widest">Active</span>
194+
</div>
195+
) : (
196+
<div className="flex items-center gap-1.5 text-rose-500 bg-rose-500/10 px-2 py-0.5 rounded-full border border-rose-500/20">
197+
<XCircle className="w-3 h-3" />
198+
<span className="text-[9px] font-black uppercase tracking-widest">Disabled</span>
199+
</div>
200+
)}
201+
</div>
202+
);

0 commit comments

Comments
 (0)