Files
speiseplan/frontend/src/components/InfoPage.tsx
clawd 3f9a043324 v0.4.5 — Alle Buttons und Funktionen verdrahtet
Fixes:
- UpdatePlanEntry Stub/Hook: 7 Parameter → 4 (passend zu Go-Signatur)
- AddPlanEntry: undefined → null für Go-Pointer-Parameter
- Wails-Stubs (App.js/App.d.ts): Alle Signaturen an Go-Backend angepasst
- ExportPDF: Go-Backend-Funktion hinzugefügt (Platzhalter mit Druckvorschau-Hinweis)
- Version: 0.4.3 → 0.4.5 in Go-Konstante und InfoPage
- Null-Safety: entries/special_days/products Arrays gegen null abgesichert
- Allergen/Additive-Listen gegen null von Go abgesichert
2026-02-20 11:17:02 +00:00

361 lines
16 KiB
TypeScript

import { useState } from 'react';
// Import der Wails-Funktionen (werden zur Laufzeit verfügbar sein)
// @ts-ignore - Wails-Bindings werden zur Laufzeit generiert
import { CheckForUpdate, DownloadUpdate } from '../../wailsjs/go/main/App';
interface UpdateInfo {
available: boolean;
current_version: string;
latest_version: string;
download_url?: string;
release_notes?: string;
}
export function InfoPage() {
const [updateInfo, setUpdateInfo] = useState<UpdateInfo | null>(null);
const [checking, setChecking] = useState(false);
const [downloading, setDownloading] = useState(false);
const [downloadComplete, setDownloadComplete] = useState(false);
const [error, setError] = useState<string | null>(null);
// Handle checking for updates
const handleCheckUpdate = async () => {
setChecking(true);
setError(null);
try {
const info = await CheckForUpdate();
setUpdateInfo(info);
} catch (err) {
setError(err instanceof Error ? err.message : 'Fehler beim Prüfen auf Updates');
} finally {
setChecking(false);
}
};
// Handle downloading update
const handleDownloadUpdate = async () => {
if (!updateInfo?.download_url) return;
setDownloading(true);
setError(null);
try {
await DownloadUpdate();
setDownloadComplete(true);
} catch (err) {
setError(err instanceof Error ? err.message : 'Fehler beim Herunterladen des Updates');
} finally {
setDownloading(false);
}
};
return (
<div className="max-w-4xl mx-auto">
{/* Header */}
<div className="mb-8">
<h1 className="text-2xl font-semibold text-gray-900">
Informationen
</h1>
<p className="mt-2 text-gray-600">
Version, Updates und Lizenzinformationen
</p>
</div>
<div className="grid gap-6">
{/* App Information */}
<section className="card p-6">
<h2 className="text-lg font-medium text-gray-900 mb-4">
Anwendungsinformationen
</h2>
<dl className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<dt className="text-sm font-medium text-gray-500">Anwendung</dt>
<dd className="mt-1 text-sm text-gray-900">Kita Speiseplan</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Version</dt>
<dd className="mt-1 text-sm text-gray-900 font-mono">
{updateInfo?.current_version || '0.4.5'}
</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Platform</dt>
<dd className="mt-1 text-sm text-gray-900">Windows Desktop</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Framework</dt>
<dd className="mt-1 text-sm text-gray-900">Wails 2 + React</dd>
</div>
</dl>
</section>
{/* Update Section */}
<section className="card p-6">
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-medium text-gray-900">
Software-Updates
</h2>
<button
onClick={handleCheckUpdate}
disabled={checking}
className="btn-primary"
aria-describedby="update-status"
>
{checking ? (
<span className="flex items-center">
<svg className="animate-spin -ml-1 mr-2 h-4 w-4" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="m4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Prüfen...
</span>
) : (
'Nach Updates suchen'
)}
</button>
</div>
{/* Update Status */}
<div id="update-status">
{error && (
<div className="bg-red-50 border border-red-200 rounded-md p-4">
<div className="flex">
<div className="flex-shrink-0">
<svg className="h-5 w-5 text-red-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.996-.833-2.764 0L3.732 16c-.77.833.192 2.5 1.732 2.5z" />
</svg>
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-red-800">
Fehler bei Update-Prüfung
</h3>
<div className="mt-2 text-sm text-red-700">
{error}
</div>
</div>
</div>
</div>
)}
{updateInfo && !updateInfo.available && (
<div className="bg-green-50 border border-green-200 rounded-md p-4">
<div className="flex">
<div className="flex-shrink-0">
<svg className="h-5 w-5 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-green-800">
Keine Updates verfügbar
</h3>
<div className="mt-2 text-sm text-green-700">
Sie verwenden bereits die neueste Version: {updateInfo.current_version}
</div>
</div>
</div>
</div>
)}
{updateInfo && updateInfo.available && !downloadComplete && (
<div className="bg-blue-50 border border-blue-200 rounded-md p-4">
<div className="flex">
<div className="flex-shrink-0">
<svg className="h-5 w-5 text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
</div>
<div className="ml-3 flex-1">
<h3 className="text-sm font-medium text-blue-800">
Update verfügbar
</h3>
<div className="mt-2 text-sm text-blue-700">
<p>
Aktuelle Version: <span className="font-mono">{updateInfo.current_version}</span>
</p>
<p>
Neue Version: <span className="font-mono">{updateInfo.latest_version}</span>
</p>
{updateInfo.release_notes && (
<div className="mt-3">
<p className="font-medium">Änderungen:</p>
<div className="mt-1 text-xs bg-white p-2 rounded border max-h-32 overflow-y-auto">
<pre className="whitespace-pre-wrap">{updateInfo.release_notes}</pre>
</div>
</div>
)}
</div>
{updateInfo.download_url && (
<div className="mt-4">
<button
onClick={handleDownloadUpdate}
disabled={downloading}
className="flex items-center space-x-2 px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
aria-label="Update herunterladen"
aria-describedby="download-status"
>
{downloading && (
<svg className="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="m4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
)}
<span>{downloading ? 'Wird heruntergeladen...' : 'Herunterladen'}</span>
</button>
{downloading && (
<div id="download-status" className="mt-2 text-xs text-blue-700" aria-live="polite">
Update wird heruntergeladen und verifiziert. Dies kann einige Minuten dauern...
</div>
)}
</div>
)}
</div>
</div>
</div>
)}
{/* Download Complete State */}
{downloadComplete && (
<div className="bg-green-50 border border-green-200 rounded-md p-4">
<div className="flex">
<div className="flex-shrink-0">
<svg className="h-5 w-5 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div className="ml-3 flex-1">
<h3 className="text-sm font-medium text-green-800">
Update heruntergeladen
</h3>
<div className="mt-2 text-sm text-green-700">
<p>
Das Update auf Version <span className="font-mono">{updateInfo?.latest_version}</span> wurde erfolgreich heruntergeladen und die SHA256-Prüfsumme wurde verifiziert.
</p>
<p className="mt-2 font-medium">
Bitte starten Sie die Anwendung neu, um das Update zu installieren.
</p>
</div>
<div className="mt-4 flex space-x-3">
<button
onClick={() => window.location.reload()}
className="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 transition-colors"
aria-label="Anwendung neu starten"
>
Neu starten
</button>
<button
onClick={() => setDownloadComplete(false)}
className="px-4 py-2 bg-gray-300 text-gray-700 rounded-md hover:bg-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 transition-colors"
aria-label="Später neu starten"
>
Später
</button>
</div>
</div>
</div>
</div>
)}
</div>
</section>
{/* License Information */}
<section className="card p-6">
<h2 className="text-lg font-medium text-gray-900 mb-4">
Lizenzinformationen
</h2>
<div className="space-y-4 text-sm text-gray-600">
<div>
<h3 className="font-medium text-gray-900">Kita Speiseplan</h3>
<p>© 2026 - Speziell entwickelt für Kindertageseinrichtungen im öffentlichen Sektor</p>
<p>Diese Software erfüllt die Anforderungen der BITV 2.0 (Barrierefreie Informationstechnik-Verordnung).</p>
</div>
<div>
<h3 className="font-medium text-gray-900">Verwendete Technologien</h3>
<ul className="list-disc list-inside space-y-1 mt-2">
<li><strong>Wails 2:</strong> MIT License - Cross-Platform Desktop Apps mit Go + Web</li>
<li><strong>React:</strong> MIT License - UI Framework von Meta</li>
<li><strong>TypeScript:</strong> Apache 2.0 License - Microsoft</li>
<li><strong>Tailwind CSS:</strong> MIT License - Utility-first CSS Framework</li>
<li><strong>Go:</strong> BSD-3-Clause License - Google</li>
</ul>
</div>
<div>
<h3 className="font-medium text-gray-900">Barrierefreiheit</h3>
<p>Diese Anwendung wurde nach den Richtlinien der BITV 2.0 entwickelt und bietet:</p>
<ul className="list-disc list-inside space-y-1 mt-2">
<li>Vollständige Tastaturnavigation</li>
<li>Screenreader-Unterstützung (NVDA, JAWS)</li>
<li>Hohe Farbkontraste (WCAG AA)</li>
<li>Große Schriftgrößen (min. 16px)</li>
<li>Touch-freundliche Bedienelemente</li>
<li>Semantisches HTML und ARIA-Labels</li>
</ul>
</div>
</div>
</section>
{/* System Requirements */}
<section className="card p-6">
<h2 className="text-lg font-medium text-gray-900 mb-4">
Systemanforderungen
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<h3 className="font-medium text-gray-900 mb-2">Minimum</h3>
<ul className="text-sm text-gray-600 space-y-1">
<li> Windows 10 (64-bit)</li>
<li> 4 GB RAM</li>
<li> 100 MB freier Speicher</li>
<li> Bildschirmauflösung: 1280x720</li>
</ul>
</div>
<div>
<h3 className="font-medium text-gray-900 mb-2">Empfohlen</h3>
<ul className="text-sm text-gray-600 space-y-1">
<li> Windows 11 (64-bit)</li>
<li> 8 GB RAM</li>
<li> 500 MB freier Speicher</li>
<li> Bildschirmauflösung: 1920x1080</li>
</ul>
</div>
</div>
</section>
{/* Support */}
<section className="card p-6">
<h2 className="text-lg font-medium text-gray-900 mb-4">
Support und Kontakt
</h2>
<div className="text-sm text-gray-600 space-y-2">
<p>
<strong>Version:</strong> 0.4.5 (Build 2026.02.20)
</p>
<p>
<strong>Support:</strong> Wenden Sie sich bei Fragen oder Problemen an Ihre IT-Abteilung
</p>
<p>
<strong>Dokumentation:</strong> Benutzerhandbuch ist über das Hilfe-Menü verfügbar
</p>
</div>
</section>
</div>
</div>
);
}