refactor(ui): Modals & Unterseiten auf Primitives & dark: umgestellt

This commit is contained in:
Hitonabi
2026-07-24 16:04:46 +02:00
parent 7004d798d6
commit 90b708302e
10 changed files with 808 additions and 869 deletions
+43 -48
View File
@@ -1,7 +1,7 @@
import { useState, useEffect } from 'react'
import { Terminal, Play, CheckCircle, AlertCircle } from 'lucide-react'
import { api } from '../lib/api'
import { useDarkMode } from '../context/ThemeContext'
import { Card, CardHeader, CardTitle } from './ui/Card'
interface LiveLogEntry {
id: string
@@ -14,7 +14,6 @@ interface LiveLogEntry {
export default function LiveLogSection() {
const [logs, setLogs] = useState<LiveLogEntry[]>([])
const [currentJob, setCurrentJob] = useState<any>(null)
const { theme } = useDarkMode()
useEffect(() => {
const fetchJobs = async () => {
@@ -50,28 +49,28 @@ export default function LiveLogSection() {
const getStatusColor = (level: string) => {
switch (level) {
case 'error': return 'text-rose-500'
case 'warning': return 'text-amber-500'
case 'success': return 'text-emerald-500'
default: return 'text-blue-500'
case 'error': return 'text-rose-500 dark:text-rose-400'
case 'warning': return 'text-amber-500 dark:text-amber-400'
case 'success': return 'text-emerald-500 dark:text-emerald-400'
default: return 'text-sky-500 dark:text-sky-400'
}
}
const getStatusIcon = (level: string) => {
switch (level) {
case 'error': return <AlertCircle size={16} />
case 'warning': return <AlertCircle size={16} />
case 'success': return <CheckCircle size={16} />
default: return <Terminal size={16} />
case 'error': return <AlertCircle size={15} />
case 'warning': return <AlertCircle size={15} />
case 'success': return <CheckCircle size={15} />
default: return <Terminal size={15} />
}
}
return (
<div className={`rounded-xl shadow-sm border overflow-hidden transition-colors duration-300 ${theme === 'dark' ? 'bg-slate-800 border-slate-700' : 'bg-white border-slate-200'}`}>
<div className={`px-6 py-4 border-b transition-colors duration-300 ${theme === 'dark' ? 'border-slate-700' : 'border-slate-200'} flex items-center justify-between`}>
<Card className="overflow-hidden">
<CardHeader>
<div>
<h2 className={`text-lg font-semibold ${theme === 'dark' ? 'text-slate-100' : 'text-slate-900'}`}>Live-Log</h2>
<p className={`text-sm ${theme === 'dark' ? 'text-slate-400' : 'text-slate-500'}`}>
<CardTitle>Live-Log</CardTitle>
<p className="text-sm text-slate-500 dark:text-slate-400">
{currentJob
? `Aktiver Job: ${currentJob.type.toUpperCase()} (${currentJob.progress}%)`
: 'Kein aktiver Job'}
@@ -79,21 +78,19 @@ export default function LiveLogSection() {
</div>
{currentJob && (
<div className="flex items-center gap-2">
<div className={`px-3 py-1 rounded-full text-xs font-medium flex items-center gap-2 ${
<div className={`px-3 py-1 rounded-full text-xs font-medium flex items-center gap-2 border ${
currentJob.progress === 100
? theme === 'dark' ? 'bg-emerald-900/30 text-emerald-400' : 'bg-emerald-100 text-emerald-700'
: theme === 'dark' ? 'bg-blue-900/30 text-blue-400' : 'bg-blue-100 text-blue-700'
? 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-400 border-emerald-500/30'
: 'bg-sky-500/15 text-sky-600 dark:text-sky-400 border-sky-500/30'
}`}>
{currentJob.progress === 100 ? <CheckCircle size={12} /> : <Play size={12} />}
{currentJob.progress}%
</div>
</div>
)}
</div>
</CardHeader>
<div className={`max-h-[400px] overflow-y-auto p-4 space-y-2 transition-colors duration-300 font-mono text-xs ${
theme === 'dark' ? 'bg-slate-900' : 'bg-slate-50'
}`}>
<div className="max-h-[380px] overflow-y-auto p-4 space-y-2 font-mono text-xs bg-slate-900/90 text-slate-200 border-b border-slate-800">
{logs.length === 0 ? (
<div className="text-center py-8 text-slate-500">
<Terminal size={32} className="mx-auto mb-2 opacity-50" />
@@ -101,14 +98,14 @@ export default function LiveLogSection() {
</div>
) : (
logs.map((log) => (
<div key={log.id} className={`flex items-start gap-2 ${theme === 'dark' ? 'text-slate-300' : 'text-slate-700'}`}>
<div key={log.id} className="flex items-start gap-2 text-slate-300">
<span className="text-slate-500 whitespace-nowrap">
{new Date(log.timestamp).toLocaleTimeString('de-DE', { hour12: false })}
</span>
<span className={`font-bold ${getStatusColor(log.level)}`}>
[{log.source}]
</span>
<span className="flex-1">{log.message}</span>
<span className="flex-1 text-slate-200">{log.message}</span>
<span className={getStatusColor(log.level)}>
{getStatusIcon(log.level)}
</span>
@@ -118,30 +115,28 @@ export default function LiveLogSection() {
</div>
{/* Quick Stats */}
<div className={`px-6 py-3 border-t transition-colors duration-300 ${theme === 'dark' ? 'border-slate-700' : 'border-slate-200'} grid grid-cols-3 gap-4`}>
{currentJob && (
<>
<div>
<p className={`text-xs ${theme === 'dark' ? 'text-slate-500' : 'text-slate-400'}`}>Fortschritt</p>
<p className={`text-lg font-bold ${theme === 'dark' ? 'text-slate-100' : 'text-slate-900'}`}>
{currentJob.progress}%
</p>
</div>
<div>
<p className={`text-xs ${theme === 'dark' ? 'text-slate-500' : 'text-slate-400'}`}>Gerät</p>
<p className={`text-sm font-medium ${theme === 'dark' ? 'text-slate-300' : 'text-slate-700'}`}>
{currentJob.device || 'Unbekannt'}
</p>
</div>
<div>
<p className={`text-xs ${theme === 'dark' ? 'text-slate-500' : 'text-slate-400'}`}>Typ</p>
<p className={`text-sm font-medium ${theme === 'dark' ? 'text-slate-300' : 'text-slate-700'}`}>
{currentJob.type?.toUpperCase() || 'Unbekannt'}
</p>
</div>
</>
)}
</div>
</div>
{currentJob && (
<div className="px-6 py-3 grid grid-cols-3 gap-4 bg-slate-50/50 dark:bg-slate-900/50">
<div>
<p className="text-xs text-slate-500 dark:text-slate-400">Fortschritt</p>
<p className="text-lg font-bold text-slate-900 dark:text-slate-100">
{currentJob.progress}%
</p>
</div>
<div>
<p className="text-xs text-slate-500 dark:text-slate-400">Gerät</p>
<p className="text-sm font-medium text-slate-700 dark:text-slate-300">
{currentJob.device || 'Unbekannt'}
</p>
</div>
<div>
<p className="text-xs text-slate-500 dark:text-slate-400">Typ</p>
<p className="text-sm font-medium text-slate-700 dark:text-slate-300">
{currentJob.type?.toUpperCase() || 'Unbekannt'}
</p>
</div>
</div>
)}
</Card>
)
}