Files
breakpilot-lehrer/website/app/admin/mac-mini/_components/PowerControls.tsx
Benjamin Admin b6983ab1dc [split-required] Split 500-1000 LOC files across all services
backend-lehrer (5 files):
- alerts_agent/db/repository.py (992 → 5), abitur_docs_api.py (956 → 3)
- teacher_dashboard_api.py (951 → 3), services/pdf_service.py (916 → 3)
- mail/mail_db.py (987 → 6)

klausur-service (5 files):
- legal_templates_ingestion.py (942 → 3), ocr_pipeline_postprocess.py (929 → 4)
- ocr_pipeline_words.py (876 → 3), ocr_pipeline_ocr_merge.py (616 → 2)
- KorrekturPage.tsx (956 → 6)

website (5 pages):
- mail (985 → 9), edu-search (958 → 8), mac-mini (950 → 7)
- ocr-labeling (946 → 7), audit-workspace (871 → 4)

studio-v2 (5 files + 1 deleted):
- page.tsx (946 → 5), MessagesContext.tsx (925 → 4)
- korrektur (914 → 6), worksheet-cleanup (899 → 6)
- useVocabWorksheet.ts (888 → 3)
- Deleted dead page-original.tsx (934 LOC)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 23:35:37 +02:00

128 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import type { MacMiniStatus } from '../types'
export default function PowerControls({
status,
loading,
actionLoading,
message,
error,
onWake,
onRestart,
onShutdown,
onRefresh,
}: {
status: MacMiniStatus | null
loading: boolean
actionLoading: string | null
message: string | null
error: string | null
onWake: () => void
onRestart: () => void
onShutdown: () => void
onRefresh: () => void
}) {
const getStatusBadge = (online: boolean) => {
return online
? 'px-3 py-1 rounded-full text-sm font-semibold bg-green-100 text-green-800'
: 'px-3 py-1 rounded-full text-sm font-semibold bg-red-100 text-red-800'
}
const getServiceStatus = (ok: boolean) => {
return ok
? 'flex items-center gap-2 text-green-600'
: 'flex items-center gap-2 text-red-500'
}
return (
<div className="bg-white rounded-xl border border-slate-200 p-6 mb-6">
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-4">
<div className="text-4xl">🖥</div>
<div>
<h2 className="text-xl font-bold text-slate-900">Mac Mini Headless</h2>
<p className="text-slate-500 text-sm">IP: {status?.ip || '192.168.178.100'}</p>
</div>
</div>
<span className={getStatusBadge(status?.online || false)}>
{loading ? 'Laden...' : status?.online ? 'Online' : 'Offline'}
</span>
</div>
{/* Power Buttons */}
<div className="flex items-center gap-4 mb-6">
<button
onClick={onWake}
disabled={actionLoading !== null}
className="px-4 py-2 bg-green-600 text-white rounded-lg font-medium hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
{actionLoading === 'wake' ? '...' : '⚡ Wake on LAN'}
</button>
<button
onClick={onRestart}
disabled={actionLoading !== null || !status?.online}
className="px-4 py-2 bg-yellow-600 text-white rounded-lg font-medium hover:bg-yellow-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
{actionLoading === 'restart' ? '...' : '🔄 Neustart'}
</button>
<button
onClick={onShutdown}
disabled={actionLoading !== null || !status?.online}
className="px-4 py-2 bg-red-600 text-white rounded-lg font-medium hover:bg-red-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
{actionLoading === 'shutdown' ? '...' : '⏻ Herunterfahren'}
</button>
<button
onClick={onRefresh}
disabled={loading}
className="px-4 py-2 border border-slate-300 text-slate-700 rounded-lg font-medium hover:bg-slate-50 disabled:opacity-50 transition-colors"
>
{loading ? '...' : '🔍 Status aktualisieren'}
</button>
{message && <span className="ml-4 text-sm text-green-600 font-medium">{message}</span>}
{error && <span className="ml-4 text-sm text-red-600 font-medium">{error}</span>}
</div>
{/* Service Status Grid */}
<div className="grid grid-cols-2 md:grid-cols-5 gap-4">
<div className="bg-slate-50 rounded-lg p-4">
<div className="text-sm text-slate-500 mb-1">Ping</div>
<div className={getServiceStatus(status?.ping || false)}>
<span className={`w-2 h-2 rounded-full ${status?.ping ? 'bg-green-500' : 'bg-red-500'}`}></span>
{status?.ping ? 'Erreichbar' : 'Nicht erreichbar'}
</div>
</div>
<div className="bg-slate-50 rounded-lg p-4">
<div className="text-sm text-slate-500 mb-1">SSH</div>
<div className={getServiceStatus(status?.ssh || false)}>
<span className={`w-2 h-2 rounded-full ${status?.ssh ? 'bg-green-500' : 'bg-red-500'}`}></span>
{status?.ssh ? 'Verbunden' : 'Getrennt'}
</div>
</div>
<div className="bg-slate-50 rounded-lg p-4">
<div className="text-sm text-slate-500 mb-1">Docker</div>
<div className={getServiceStatus(status?.docker || false)}>
<span className={`w-2 h-2 rounded-full ${status?.docker ? 'bg-green-500' : 'bg-red-500'}`}></span>
{status?.docker ? 'Aktiv' : 'Inaktiv'}
</div>
</div>
<div className="bg-slate-50 rounded-lg p-4">
<div className="text-sm text-slate-500 mb-1">Ollama</div>
<div className={getServiceStatus(status?.ollama || false)}>
<span className={`w-2 h-2 rounded-full ${status?.ollama ? 'bg-green-500' : 'bg-red-500'}`}></span>
{status?.ollama ? 'Bereit' : 'Nicht bereit'}
</div>
</div>
<div className="bg-slate-50 rounded-lg p-4">
<div className="text-sm text-slate-500 mb-1">Uptime</div>
<div className="font-semibold text-slate-700">
{status?.uptime || '-'}
</div>
</div>
</div>
</div>
)
}