Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/web/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const License = lazy(() => import("./pages/License").then(module => ({ default:
const LoginPage = lazy(() => import("./dashboard/LoginPage"));
const SettingsPage = lazy(() => import("./dashboard/SettingsPage"));
const UserSettingsPage = lazy(() => import("./dashboard/UserSettingsPage"));
const GuildSelectionPage = lazy(() => import("./dashboard/GuildSelectionPage"));
const AuthCallback = lazy(() => import("./pages/AuthCallback"));

const queryClient = new QueryClient();
Expand Down Expand Up @@ -64,6 +65,7 @@ const DashboardRoutes = () => {
<Route path="/dash/login" element={<LoginPage />} />
<Route path="/dash/auth/callback" element={<AuthCallback />} />
<Route path="/auth/callback" element={<AuthCallback />} />
<Route path="/dash/guilds" element={<GuildSelectionPage />} />
<Route path="/dash/settings" element={<SettingsPage />} />
<Route path="/dash" element={<LoginPage />} />
<Route path="/" element={<LoginPage />} />
Expand Down Expand Up @@ -108,6 +110,7 @@ const MainRoutes = () => {
<Route path="/leaderboard" element={<LeaderboardPage />} />
<Route path="/dash/auth/callback" element={<AuthCallback />} />
<Route path="/auth/callback" element={<AuthCallback />} />
<Route path="/dash/guilds" element={<GuildSelectionPage />} />
<Route path="/dash/settings" element={<SettingsPage />} />
<Route path="/dash/login" element={<LoginPage />} />
<Route path="/dash/user/settings" element={<UserSettingsPage />} />
Expand Down
21 changes: 13 additions & 8 deletions src/web/components/AuthProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,19 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
"X-Discord-Token": localStorage.getItem("discord_token") || ""
}
})
.then(res => res.status === 401 ? logout() : res.json())
.then(data => {
if (data?.user) setUser(data.user);
if (data?.guilds) {
setGuilds(data.guilds);
if (!selectedGuildId && data.guilds.length > 0) {
setSelectedGuildId(data.guilds[0].id);
localStorage.setItem("selectedGuildId", data.guilds[0].id);

.then(async (res) => {
if (res.status === 401) {
logout();
throw new Error("Session expired");
}
if (!res.ok) throw new Error("Failed to fetch user data");
return res.json();
})
.then(data => {
if (data.user) setUser(data.user);
if (data.guilds) {
setGuilds(data.guilds);
}
}
})
Expand Down
34 changes: 17 additions & 17 deletions src/web/components/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { memo } from "react";
import { motion } from "framer-motion";
import { Link } from "react-router-dom";
import { Shield, Users, MessageCircle, Sparkles, Zap, Activity, ArrowRight } from "lucide-react";
import { useStats } from "@/hooks/useStats";
import { useStats } from "../hooks/useStats";

export const Hero = memo(function Hero() {
const { data, isLoading } = useStats();
Expand Down Expand Up @@ -61,50 +61,50 @@ export const Hero = memo(function Hero() {

{/* Title */}
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1 }}
className="text-7xl md:text-9xl font-bold mb-8 tracking-tighter leading-tight"
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ type: "spring", damping: 20 }}
className="text-8xl md:text-[11rem] font-black mb-8 tracking-tighter leading-[0.85] select-none"
>
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>
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>
</motion.h1>

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

{/* Action Row */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
className="flex flex-col sm:flex-row items-center gap-5 mb-20"
className="flex flex-col sm:flex-row items-center gap-6 mb-24"
>
<motion.a
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
whileHover={{ scale: 1.05, y: -2 }}
whileTap={{ scale: 0.95 }}
href="https://discord.com/oauth2/authorize?client_id=1368201272624287754&permissions=1669118160151&integration_type=0&scope=bot"
target="_blank"
rel="noopener noreferrer"
className="btn-primary inline-flex items-center gap-3"
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)]"
>
<span>Bot einladen</span>
<ArrowRight className="w-5 h-5" />
<ArrowRight className="w-6 h-6" />
</motion.a>
<motion.a
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
whileHover={{ scale: 1.05, bg: "rgba(255,255,255,0.1)" }}
whileTap={{ scale: 0.95 }}
href="#features"
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"
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"
>
Features entdecken
Learn More
</motion.a>
</motion.div>

Expand Down
2 changes: 1 addition & 1 deletion src/web/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export function Navbar() {
<User className="w-5 h-5" />
</Link>
<Link
to="/dash/settings"
to="/dash/guilds"
className="btn-primary inline-flex items-center gap-2.5 !px-6 !py-2.5 !text-sm group"
>
<LayoutDashboard className="w-4 h-4 group-hover:rotate-12 transition-transform" />
Expand Down
83 changes: 67 additions & 16 deletions src/web/components/OverviewSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "./ui/
import { Users, MessageSquare, Zap, Activity, TrendingUp, ArrowUpRight, ArrowDownRight } from "lucide-react";
import { motion } from "framer-motion";
import OverviewCharts from "./OverviewCharts";
import { Badge } from "./ui/badge";
import { CheckCircle, XCircle } from "lucide-react";

interface OverviewSettingsProps {
guildId: string | null;
initialStats?: any;
settings?: any;
}

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

Expand Down Expand Up @@ -121,31 +124,79 @@ export default function OverviewSettings({ guildId, initialStats }: OverviewSett
/>
</div>

<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<Card className="bg-white/[0.03] border-white/5 backdrop-blur-xl rounded-[32px] overflow-hidden">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Activity className="w-5 h-5 text-primary" /> Nachrichten Volumen
</CardTitle>
<CardDescription>Aktivität der letzten 7 Tage</CardDescription>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* Bot Health & Activity Summary */}
<Card className="lg:col-span-2 glass border-white/10 shadow-2xl rounded-[2.5rem] overflow-hidden">
<CardHeader className="flex flex-row items-center justify-between">
<div className="space-y-1">
<CardTitle className="flex items-center gap-2">
<Activity className="w-5 h-5 text-primary" /> Command Center
</CardTitle>
<CardDescription>Live-Metriken deiner Server-Instanz</CardDescription>
</div>
<Badge variant="outline" className="bg-primary/10 text-primary border-primary/20 px-3 py-1">
Live updates
</Badge>
</CardHeader>
<CardContent>
<OverviewCharts data={messageData} type="messages" color="#3B82F6" />
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<div className="space-y-6">
<div className="p-5 rounded-3xl bg-white/5 border border-white/10">
<OverviewCharts data={messageData} type="messages" color="#DC2626" height={180} />
<p className="text-center text-[10px] font-bold uppercase tracking-widest text-muted-foreground mt-4">Nachrichten Volumen (7 Tage)</p>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<QuickStat title="Server Age" value="238d" />
<QuickStat title="Avg Activity" value="High" />
<QuickStat title="Staff Count" value="12" />
<QuickStat title="Uptime" value="99.9%" />
</div>
</div>
</CardContent>
</Card>

<Card className="bg-white/[0.03] border-white/5 backdrop-blur-xl rounded-[32px] overflow-hidden">
{/* Module Status Sidebar */}
<Card className="glass border-white/10 shadow-2xl rounded-[2.5rem] overflow-hidden">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Users className="w-5 h-5 text-emerald-400" /> Mitglieder Wachstum
</CardTitle>
<CardDescription>Wachstumstrend der Woche</CardDescription>
<CardTitle className="text-xl font-bold">Module Status</CardTitle>
<CardDescription>Aktive Bot-Funktionen</CardDescription>
</CardHeader>
<CardContent>
<OverviewCharts data={memberData} type="members" color="#10B981" />
<CardContent className="space-y-3">
<ModuleRow name="Level System" active={true} />
<ModuleRow name="Anti-Spam AI" active={true} />
<ModuleRow name="Welcome Suite" active={settings?.welcome_message ?? false} />
<ModuleRow name="Global Network" active={true} />
<ModuleRow name="Auto-Mod" active={settings?.auto_mod ?? true} />
<ModuleRow name="Logging" active={true} />
<ModuleRow name="Economy" active={false} />
</CardContent>
</Card>
</div>
</div>
);
}

const QuickStat = ({ title, value }: { title: string, value: string }) => (
<div className="p-4 rounded-2xl bg-white/5 border border-white/5 flex flex-col justify-center">
<span className="text-[10px] font-bold uppercase tracking-widest text-muted-foreground mb-1">{title}</span>
<span className="text-lg font-black text-white">{value}</span>
</div>
);

const ModuleRow = ({ name, active }: { name: string, active: boolean }) => (
<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">
<span className="text-sm font-bold text-white/80">{name}</span>
{active ? (
<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">
<CheckCircle className="w-3 h-3" />
<span className="text-[9px] font-black uppercase tracking-widest">Active</span>
</div>
) : (
<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">
<XCircle className="w-3 h-3" />
<span className="text-[9px] font-black uppercase tracking-widest">Disabled</span>
</div>
)}
</div>
);
Loading
Loading