diff --git a/src/api/dashboard/routes.py b/src/api/dashboard/routes.py index 9c0c4ed..f90150d 100644 --- a/src/api/dashboard/routes.py +++ b/src/api/dashboard/routes.py @@ -326,6 +326,60 @@ def calc_trend(today, yesterday): "messages_today": 0 } +@dashboard_main_router.get("/guilds/{guild_id}/mega-data") +async def get_mega_data(guild_id: int, user: dict = Depends(get_current_user)): + """Consolidated endpoint for dashboard landing page (Settings, Stats, Metadata).""" + if bot_instance is None: + raise HTTPException(status_code=503, detail="Bot-Verbindung nicht verfügbar") + + guild = bot_instance.get_guild(guild_id) + if not guild: + raise HTTPException(status_code=404, detail="Guild not found or bot not in guild") + + member = guild.get_member(int(user["id"])) + if not member or not (member.guild_permissions.manage_guild or member.guild_permissions.administrator): + raise HTTPException(status_code=403, detail="Insufficient permissions") + + try: + # 1. Fetch Stats (reuse logic) + try: + stats = await get_guild_stats(guild_id, user) + except: + stats = {} + + # 2. Fetch Settings + guild_lang = "de" + if hasattr(bot_instance, 'settings_db'): + guild_lang = bot_instance.settings_db.get_guild_language(guild_id) + + # 3. Fetch Metadata + channels = [{"id": str(c.id), "name": c.name} for c in guild.text_channels] + roles = [{"id": str(r.id), "name": r.name, "color": str(r.color)} for r in guild.roles if not r.is_default() and not r.managed] + categories = [{"id": str(c.id), "name": c.name} for c in guild.categories] + voice_channels = [{"id": str(c.id), "name": c.name} for c in guild.voice_channels] + + return { + "success": True, + "data": { + "settings": { + "bot_name": bot_instance.user.name, + "prefix": "!", + "auto_mod": True, + "welcome_message": False, + "language": guild_lang + }, + "stats": stats, + "metadata": { + "channels": channels, + "roles": roles, + "categories": categories, + "voice_channels": voice_channels + } + } + } + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + dashboard_main_router.include_router(auth_router) dashboard_main_router.include_router(settings_router) dashboard_main_router.include_router(user_router) diff --git a/src/web/components/OverviewSettings.tsx b/src/web/components/OverviewSettings.tsx index 7b806fc..bb8d3ac 100644 --- a/src/web/components/OverviewSettings.tsx +++ b/src/web/components/OverviewSettings.tsx @@ -7,13 +7,20 @@ import OverviewCharts from "./OverviewCharts"; interface OverviewSettingsProps { guildId: string | null; + initialStats?: any; } -export default function OverviewSettings({ guildId }: OverviewSettingsProps) { - const [stats, setStats] = useState(null); - const [loading, setLoading] = useState(true); +export default function OverviewSettings({ guildId, initialStats }: OverviewSettingsProps) { + const [stats, setStats] = useState(initialStats || null); + const [loading, setLoading] = useState(!initialStats); useEffect(() => { + if (initialStats) { + setStats(initialStats); + setLoading(false); + return; + } + const fetchStats = async () => { if (!guildId) return; const token = localStorage.getItem("token"); @@ -36,7 +43,7 @@ export default function OverviewSettings({ guildId }: OverviewSettingsProps) { setLoading(true); fetchStats(); } - }, [guildId]); + }, [guildId, initialStats]); // Prepare chart data from API history const messageData = (stats?.history || []).map((h: any) => ({ diff --git a/src/web/dashboard/SettingsPage.tsx b/src/web/dashboard/SettingsPage.tsx index c752944..96e8332 100644 --- a/src/web/dashboard/SettingsPage.tsx +++ b/src/web/dashboard/SettingsPage.tsx @@ -69,60 +69,51 @@ export default function SettingsPage() { const [theme, setTheme] = useState("dark"); const [language, setLanguage] = useState("de"); + const [stats, setStats] = useState(null); + React.useEffect(() => { - const fetchSettings = async () => { + const fetchAllData = async () => { if (!token || !guildId) return; + setIsLoading(true); try { const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; - // Fetch settings - const settingsRes = await fetch(`${baseUrl}/dashboard/settings/${guildId}`, { + // Fetch EVERYTHING in ONE call + const res = await fetch(`${baseUrl}/dashboard/guilds/${guildId}/mega-data`, { headers: { "Authorization": `Bearer ${token}` } }); - if (settingsRes.ok) { - const data = await settingsRes.json(); - if (data.success && data.data) { - setBotName(data.data.bot_name || "ManagerX"); - setPrefix(data.data.prefix || "!"); - setAutoMod(data.data.auto_mod ?? true); - setWelcomeMessage(data.data.welcome_message ?? false); - setLanguage(data.data.language || "de"); + + if (res.ok) { + const json = await res.json(); + if (json.success && json.data) { + const { settings, metadata, stats: guildStats } = json.data; + + // Set General Settings + setBotName(settings.bot_name || "ManagerX"); + setPrefix(settings.prefix || "!"); + setAutoMod(settings.auto_mod ?? true); + setWelcomeMessage(settings.welcome_message ?? false); + setLanguage(settings.language || "de"); + + // Set Guild Metadata + setGuildData({ + channels: metadata.channels || [], + roles: metadata.roles || [], + categories: metadata.categories || [], + voiceChannels: metadata.voice_channels || [] + }); + + // Set Stats + setStats(guildStats); } } - - // Fetch Guild Data (Channels, Roles, Categories, VoiceChannels) - const [channelsRes, rolesRes, catsRes, vcsRes] = await Promise.all([ - fetch(`${baseUrl}/dashboard/guilds/${guildId}/channels`, { - headers: { "Authorization": `Bearer ${token}` } - }), - fetch(`${baseUrl}/dashboard/guilds/${guildId}/roles`, { - headers: { "Authorization": `Bearer ${token}` } - }), - fetch(`${baseUrl}/dashboard/guilds/${guildId}/categories`, { - headers: { "Authorization": `Bearer ${token}` } - }), - fetch(`${baseUrl}/dashboard/guilds/${guildId}/voice_channels`, { - headers: { "Authorization": `Bearer ${token}` } - }) - ]); - - if (channelsRes.ok && rolesRes.ok && catsRes.ok && vcsRes.ok) { - const channels = await channelsRes.json(); - const roles = await rolesRes.json(); - const categories = await catsRes.json(); - const voiceChannels = await vcsRes.json(); - setGuildData({ - channels: channels.channels || [], - roles: roles.roles || [], - categories: categories.categories || [], - voiceChannels: voiceChannels.channels || [] - }); - } } catch (e) { - console.error("Failed to fetch guild data", e); + console.error("Failed to fetch consolidated dashboard data", e); + } finally { + setIsLoading(false); } }; - fetchSettings(); + fetchAllData(); }, [token, guildId]); const handleSave = async () => { diff --git a/src/web/dashboard/UserSettingsPage.tsx b/src/web/dashboard/UserSettingsPage.tsx index 9c3b276..7c0b2a0 100644 --- a/src/web/dashboard/UserSettingsPage.tsx +++ b/src/web/dashboard/UserSettingsPage.tsx @@ -434,6 +434,13 @@ export default function UserSettingsPage() {

Wähle deine bevorzugte Sprache für das Dashboard.

+