Files
Atlas/app/dashboard/settings/page.tsx
2025-11-12 20:21:32 +01:00

198 lines
8.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.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useState } from 'react';
import { useSession } from 'next-auth/react';
import DashboardSidebar from '@/components/DashboardSidebar';
import { FiCheck, FiX, FiRefreshCw, FiCloud } from 'react-icons/fi';
export default function SettingsPage() {
const { data: session } = useSession();
const [testResult, setTestResult] = useState<any>(null);
const [syncResult, setSyncResult] = useState<any>(null);
const [loading, setLoading] = useState(false);
const testConnection = async () => {
setLoading(true);
setTestResult(null);
try {
const response = await fetch('/api/calendar/sync', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'test-connection' }),
});
const data = await response.json();
setTestResult(data);
} catch (error) {
setTestResult({ success: false, error: 'Connection failed' });
} finally {
setLoading(false);
}
};
const syncAllBookings = async () => {
setLoading(true);
setSyncResult(null);
try {
const response = await fetch('/api/calendar/sync', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'sync-all' }),
});
const data = await response.json();
setSyncResult(data);
} catch (error) {
setSyncResult({ success: false, error: 'Sync failed' });
} finally {
setLoading(false);
}
};
return (
<div className="min-h-screen bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900">
<div className="flex">
<DashboardSidebar user={session?.user} />
<main className="flex-1 p-8">
<div className="max-w-4xl">
<h1 className="text-3xl font-bold text-white mb-8">Einstellungen</h1>
<div className="bg-gray-800/50 rounded-lg p-6 shadow-lg mb-6">
<div className="flex items-center gap-3 mb-4">
<FiCloud className="text-2xl text-blue-400" />
<h2 className="text-xl font-bold text-white">Nextcloud Kalender-Synchronisation</h2>
</div>
<div className="space-y-4">
<div className="flex gap-4">
<button
onClick={testConnection}
disabled={loading}
className="px-6 py-3 bg-blue-600 hover:bg-blue-500 text-white rounded-lg font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
>
{loading ? (
<>
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white"></div>
Teste...
</>
) : (
<>
<FiCheck />
Verbindung testen
</>
)}
</button>
<button
onClick={syncAllBookings}
disabled={loading}
className="px-6 py-3 bg-green-600 hover:bg-green-500 text-white rounded-lg font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
>
{loading ? (
<>
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white"></div>
Synchronisiere...
</>
) : (
<>
<FiRefreshCw />
Alle Buchungen synchronisieren
</>
)}
</button>
</div>
{testResult && (
<div
className={`p-4 rounded-lg ${
testResult.success
? 'bg-green-500/20 border border-green-500'
: 'bg-red-500/20 border border-red-500'
}`}
>
<div className="flex items-center gap-2 mb-2">
{testResult.success ? (
<>
<FiCheck className="text-green-400" />
<span className="font-semibold text-green-300">Verbindung erfolgreich!</span>
</>
) : (
<>
<FiX className="text-red-400" />
<span className="font-semibold text-red-300">Verbindung fehlgeschlagen</span>
</>
)}
</div>
{testResult.success && testResult.calendars && (
<div className="mt-2">
<p className="text-sm text-gray-300 mb-2">Gefundene Kalender:</p>
<ul className="space-y-1">
{testResult.calendars.map((cal: any, idx: number) => (
<li key={idx} className="text-sm text-gray-300 ml-4">
{cal.displayName} {cal.description && `(${cal.description})`}
</li>
))}
</ul>
</div>
)}
{!testResult.success && (
<p className="text-sm text-red-300 mt-2">
Fehler: {testResult.error || 'Unbekannter Fehler'}
</p>
)}
</div>
)}
{syncResult && (
<div
className={`p-4 rounded-lg ${
syncResult.success
? 'bg-green-500/20 border border-green-500'
: 'bg-red-500/20 border border-red-500'
}`}
>
<div className="flex items-center gap-2 mb-2">
{syncResult.success ? (
<>
<FiCheck className="text-green-400" />
<span className="font-semibold text-green-300">Synchronisation abgeschlossen!</span>
</>
) : (
<>
<FiX className="text-red-400" />
<span className="font-semibold text-red-300">Synchronisation fehlgeschlagen</span>
</>
)}
</div>
{syncResult.success && (
<div className="text-sm text-gray-300 space-y-1">
<p> Erfolgreich synchronisiert: {syncResult.synced}</p>
{syncResult.failed > 0 && (
<p className="text-red-300"> Fehlgeschlagen: {syncResult.failed}</p>
)}
<p>📊 Gesamt: {syncResult.total}</p>
</div>
)}
{!syncResult.success && (
<p className="text-sm text-red-300 mt-2">
Fehler: {syncResult.error || 'Unbekannter Fehler'}
</p>
)}
</div>
)}
<div className="mt-6 p-4 bg-gray-700/30 rounded-lg">
<h3 className="font-semibold text-white mb-2"> Hinweise:</h3>
<ul className="text-sm text-gray-300 space-y-1 ml-4">
<li> Stelle sicher, dass die Nextcloud-Zugangsdaten in der .env-Datei korrekt hinterlegt sind</li>
<li> Die Synchronisation erstellt/aktualisiert Events für alle RESERVED, CONFIRMED und TOUR_CREATED Buchungen</li>
<li> Bei Änderungen an Buchungen werden die Kalender-Events automatisch aktualisiert</li>
</ul>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
);
}