/* Admin Settings with Database Import / Export functionality */ 'use client'; import { useState, useEffect } from 'react'; import { Switch } from '@/components/ui/switch'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Download, Upload, Database, AlertTriangle, Loader2, KeyRound, Server, CheckCircle2, XCircle, Eye, EyeOff, Wifi } from 'lucide-react'; import { createClient } from '@/lib/supabase/client'; import { saveLicServerConfig, testLicServerConnection } from '@/lib/actions/licserver-config'; import { useRouter } from 'next/navigation'; export default function AdminSettings() { const [demoActive, setDemoActive] = useState(true); const [exporting, setExporting] = useState(false); const [importing, setImporting] = useState(false); const [statusMsg, setStatusMsg] = useState(''); const [statusType, setStatusType] = useState<'success' | 'error' | 'info' | ''>(''); const [selectedFile, setSelectedFile] = useState(null); const [loading, setLoading] = useState(true); // LicServer Config State const [licUrl, setLicUrl] = useState(''); const [licKey, setLicKey] = useState(''); const [showKey, setShowKey] = useState(false); const [licSaving, setLicSaving] = useState(false); const [licTesting, setLicTesting] = useState(false); const [licStatus, setLicStatus] = useState<{ ok: boolean; message: string } | null>(null); const [licMsg, setLicMsg] = useState(''); const [licMsgType, setLicMsgType] = useState<'success' | 'error' | ''>(''); const router = useRouter(); useEffect(() => { async function checkAccess() { const supabase = createClient(); const { data: { user } } = await supabase.auth.getUser(); if (!user) { router.push('/auth/login'); return; } const { data: userData } = await supabase .from('users') .select('role') .eq('id', user.id) .single(); if (!userData || userData.role === 'verwaltung') { router.push('/admin'); } else { const state = localStorage.getItem('demo_banner_disabled') !== 'true'; setDemoActive(state); setLoading(false); // Load current LicServer config from DB const supabaseClient = createClient(); const { data: licRow } = await supabaseClient .from('settings') .select('licserver_base_url, licserver_api_key') .eq('id', 'licserver') .single(); if (licRow) { setLicUrl(licRow.licserver_base_url || ''); setLicKey(licRow.licserver_api_key || ''); } } } checkAccess(); }, [router]); const toggleDemo = (checked: boolean) => { setDemoActive(checked); localStorage.setItem('demo_banner_disabled', (!checked).toString()); window.dispatchEvent(new Event('storage_demo_changed')); }; const handleExport = async () => { setExporting(true); setStatusMsg('Export läuft...'); setStatusType('info'); try { const res = await fetch('/api/admin/db-backup'); if (!res.ok) throw new Error('Export fehlgeschlagen'); const blob = await res.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `webshop_backup_${new Date().toISOString().split('T')[0]}.zip`; document.body.appendChild(a); a.click(); a.remove(); window.URL.revokeObjectURL(url); setStatusMsg('Export erfolgreich abgeschlossen.'); setStatusType('success'); } catch (err: any) { console.error(err); setStatusMsg(`Fehler beim Export: ${err.message}`); setStatusType('error'); } finally { setExporting(false); } }; const handleImport = async () => { if (!selectedFile) return; if (!confirm('ACHTUNG: Dies löscht und überschreibt alle aktuellen Datenbankinhalte in dieser Instanz. Möchten Sie wirklich fortfahren?')) { return; } setImporting(true); setStatusMsg('Import läuft...'); setStatusType('info'); try { const formData = new FormData(); formData.append('file', selectedFile); const res = await fetch('/api/admin/db-backup', { method: 'POST', body: formData, }); const data = await res.json(); if (!res.ok) throw new Error(data.error || 'Import fehlgeschlagen'); setStatusMsg('Datenbank erfolgreich importiert!'); setStatusType('success'); setSelectedFile(null); } catch (err: any) { console.error(err); setStatusMsg(`Fehler beim Import: ${err.message}`); setStatusType('error'); } finally { setImporting(false); } }; if (loading) { return
; } return (
{/* Page Header */}

Admin Einstellungen

Verwalten Sie globale Shopeinstellungen.

{/* Allgemeine Einstellungen */}

Allgemeine Einstellungen

Demo-Warnmeldungen

Schaltet gelbe Banner ein oder aus.

{/* Datenimport & -export */}

Datenimport & -export

Sichern Sie Ihre gesamte Instanz oder stellen Sie Daten wieder her.

{statusMsg && (
{statusMsg}
)}
{/* Export Card */}

Daten exportieren

Lädt alle Kategorien, Produkte, Module, Firmen, Endkunden, Bestellungen und SMTP-Einstellungen als ZIP-Datei herunter.

{/* Import Card */}

Daten importieren

Warnung: Der Import überschreibt alle Daten dieser Instanz unwiderruflich!
setSelectedFile(e.target.files?.[0] || null)} disabled={exporting || importing} className="absolute inset-0 w-full h-full opacity-0 cursor-pointer disabled:cursor-not-allowed" />
{selectedFile ? ( {selectedFile.name} ) : ( "ZIP-Datei auswählen oder hierher ziehen" )}
{/* LicServer Konfiguration */}

LicServer Konfiguration

Verbindungseinstellungen zum CASPOS Lizenzserver (internes Container-Netz). Der API-Key wird verschlüsselt in der Datenbank gespeichert und nie an den Browser übertragen.

{/* Status Message */} {licMsg && (
{licMsg}
)} {/* Connection Test Result */} {licStatus && (
{licStatus.ok ? : } {licStatus.message}
)}
{/* Base URL */}
setLicUrl(e.target.value)} placeholder="http://192.168.178.174:9980" className="text-sm font-mono" />

Interne Container-URL ohne trailing slash

{/* API Key */}
setLicKey(e.target.value)} placeholder="Ihr X-Api-Key" className="text-sm font-mono pr-10" />

Wird als X-Api-Key Header an den LicServer gesendet

{/* Actions */}
); }