diff --git a/shop/app/admin/tools/page.tsx b/shop/app/admin/tools/page.tsx index f09255f..a36073e 100644 --- a/shop/app/admin/tools/page.tsx +++ b/shop/app/admin/tools/page.tsx @@ -1,16 +1,15 @@ "use client"; import { useEffect, useState } from "react"; -import { - getDatabaseIntegrity, - repairDatabaseSchema, - optimizeDatabaseIndices +import { motion } from "framer-motion"; +import { + getDatabaseIntegrity, + repairDatabaseSchema, + optimizeDatabaseIndices } from "@/lib/actions/admin"; import { Button } from "@/components/ui/button"; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; -import { Loader2, RefreshCw, Wrench, Database, AlertTriangle, CheckCircle2, XCircle, Terminal, ArrowLeft } from "lucide-react"; -import Link from "next/link"; +import { Loader2, RefreshCw, Wrench, Database, CheckCircle2, XCircle, Terminal } from "lucide-react"; import { createClient } from "@/lib/supabase/client"; import { useRouter } from "next/navigation"; @@ -26,6 +25,19 @@ interface IntegrityData { }; } +const containerVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { staggerChildren: 0.1 } + } +}; + +const itemVariants = { + hidden: { opacity: 0, y: 15 }, + visible: { opacity: 1, y: 0, transition: { type: 'spring' as const, stiffness: 80, damping: 15 } } +}; + export default function AdminToolsPage() { const [integrity, setIntegrity] = useState(null); const [isLoading, setIsLoading] = useState(false); @@ -88,218 +100,145 @@ export default function AdminToolsPage() { useEffect(() => { async function checkAccess() { - const supabase = createClient(); - const { data: { user } } = await supabase.auth.getUser(); - if (!user) { - router.push('/auth/login'); - return; + try { + const supabase = createClient(); + const { data: { user } } = await supabase.auth.getUser(); + if (!user) { + router.push('/auth/login'); + return; + } + + const [userRes] = await Promise.all([ + supabase.from('users').select('role').eq('id', user.id).single(), + loadStatus(true) + ]); + + if (!userRes.data || userRes.data.role === 'verwaltung') { + router.push('/admin'); + return; + } + } catch (err) { + console.error("Fehler beim Laden von Admin Tools:", err); + } finally { + setLoading(false); } - const { data: userData } = await supabase - .from('users') - .select('role') - .eq('id', user.id) - .single(); - if (!userData || userData.role === 'verwaltung') { - router.push('/admin'); - return; - } - setLoading(false); - loadStatus(); } checkAccess(); }, [router]); if (loading) { - return
; + return
; } return ( -
- {/* Background decoration */} -
- - {/* Loading Overlay */} - {isLoading && ( -
- -

- {activeAction === "repair" - ? "Schema wird repariert..." - : activeAction === "optimize" - ? "Datenbank wird indexiert..." - : "Verbindung zur Datenbank wird aufgebaut..."} -

-
- )} +
+ {/* Header */} + +

+ + Datenbank Cockpit & Tools +

+

+ Verwalten und reparieren Sie Systemtabellen, Sicherheitsrichtlinien (RLS) und Datenbank-Indizes. +

+
-
- {/* Header */} -
- - - -
-

- - Admin Datenbank-Cockpit -

-

- Verwalten und reparieren Sie Systemtabellen, Sicherheitsrichtlinien (RLS) und Datenbank-Indizes. -

-
-
- - {/* Action Controls */} -
- - - - - Integritätsscan - - + {/* Bento Grid layout */} + + {/* Bento Card 1: Integritätsscan */} + +
+
+ +
+
+

Integritätsscan

+

Prüft die physische Existenz der Tabellen und zählt deren Zeilenanzahl. - - - - - - - - - - - - Schema reparieren - - - Erstellt fehlende Kerntabellen automatisch neu und konfiguriert die RLS-Rechte. - - - - - - - - - - - - Index optimieren - - - Baut korrupte Suchindizes im Schema public mittels REINDEX neu auf. - - - - - - -

- - {/* Tabellenstatus */} - - - Tabellen-Status & Diagnose - - -
- {integrity?.tables ? ( - Object.entries(integrity.tables).map(([name, status]) => ( -
- - {name.replace("_", " ")} - -
- Zeilen: {status.count} - {status.exists ? ( - - OK - - ) : ( - - Fehlt - - )} -
-
- )) - ) : ( -
- Lade Diagnosedaten... -
- )} +

+
+ +
- {/* Foreign Key Errors */} - {integrity && integrity.errors.foreign_keys > 0 && ( -
- -
-

Fremdschlüssel-Fehler gefunden!

-

- Es wurden {integrity.errors.foreign_keys} verwaiste Lizenzen ohne zugeordneten Endkunden in der Tabelle `licenses` detektiert. -

+ {/* Bento Card 2: Schema Reparieren */} + +
+
+ +
+
+

Schema Reparieren

+

+ Erstellt fehlende Kerntabellen automatisch neu und konfiguriert RLS-Rechte. +

+
+
+ +
+ + {/* Bento Card 3: Index Optimieren */} + +
+
+ +
+
+

Index Optimieren

+

+ Baut Suchindizes im Schema public mittels REINDEX neu auf für maximale Performance. +

+
+
+ +
+ + {/* Bento Card 4: Tabellen-Diagnose (2 Spalten) */} + +

Tabellen-Status & Diagnose

+
+ {integrity?.tables ? ( + Object.entries(integrity.tables).map(([name, status]) => ( +
+
+ {name.replace("_", " ")} + Zeilen: {status.count} +
+ {status.exists ? ( + OK + ) : ( + Fehlt + )}
-
+ )) + ) : ( +

Keine Diagnose-Daten geladen.

)} - - +
+ - {/* Console / Output logs */} - - - - - Diagnose-Konsole - - - - -
+ {/* Bento Card 5: Live Konsole / Logs (1 Spalte) */} + +
+

+ System-Konsole +

+
{logs.length === 0 ? ( - Konsole bereit. Führen Sie einen Scan aus. + Warte auf Aktionen... ) : ( - logs.map((log, index) => ( -
- {log} -
- )) + logs.map((log, i) =>
{log}
) )}
- - -
+
+ +
); }