refactoring node 24

This commit is contained in:
2025-11-10 10:39:56 +01:00
parent 0515d3d714
commit dff35b8218
10 changed files with 1102 additions and 1019 deletions

View File

@@ -0,0 +1,196 @@
const NotificationPanel = ({
error,
message,
settings,
capabilities,
loading,
dirty,
saving,
onReset,
onSave,
onFieldChange,
onSendTest,
onCopyLink,
copyFeedback,
ntfyPreviewUrl
}) => {
return (
<div className="mb-6 border border-gray-200 rounded-lg p-4 bg-gray-50">
{error && (
<div className="mb-4 bg-red-100 border border-red-300 text-red-700 px-4 py-2 rounded">
{error}
</div>
)}
{message && (
<div className="mb-4 bg-green-100 border border-green-300 text-green-700 px-4 py-2 rounded">
{message}
</div>
)}
<div className="grid md:grid-cols-2 gap-4">
<div className="bg-white border border-gray-200 rounded-lg p-4 shadow-sm">
<div className="flex items-center justify-between mb-3">
<div>
<h3 className="text-lg font-semibold text-gray-800">ntfy</h3>
<p className="text-xs text-gray-500">
Push aufs Handy über die ntfy-App oder Browser (Themenkanal notwendig).
</p>
</div>
<label className="inline-flex items-center space-x-2 text-sm text-gray-700">
<input
type="checkbox"
checked={settings.ntfy.enabled}
onChange={(event) => onFieldChange('ntfy', 'enabled', event.target.checked)}
disabled={!capabilities.ntfy.enabled}
className="h-4 w-4 text-blue-600 rounded focus:ring-blue-500"
/>
<span>Aktiv</span>
</label>
</div>
{!capabilities.ntfy.enabled ? (
<p className="text-sm text-gray-500">
Diese Option wurde vom Admin deaktiviert. Bitte frage nach, wenn du ntfy nutzen möchtest.
</p>
) : (
<div className="space-y-3">
<div>
<label className="block text-xs font-semibold text-gray-600 mb-1">Topic / Kanal</label>
<input
type="text"
value={settings.ntfy.topic}
onChange={(event) => onFieldChange('ntfy', 'topic', event.target.value)}
placeholder="z. B. mein-pickup-topic"
className="border rounded p-2 w-full focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
disabled={!settings.ntfy.enabled}
/>
</div>
{capabilities.ntfy.serverUrl && (
<p className="text-xs text-gray-500">
Server: {capabilities.ntfy.serverUrl} (vom Admin festgelegt)
</p>
)}
{capabilities.ntfy.topicPrefix && (
<p className="text-xs text-gray-500">
Präfix: {capabilities.ntfy.topicPrefix} (Bindestrich wird automatisch ergänzt)
</p>
)}
{ntfyPreviewUrl && (
<div className="flex items-center gap-2 text-xs text-gray-600">
<a
href={ntfyPreviewUrl}
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:text-blue-800 break-all"
>
{ntfyPreviewUrl}
</a>
<button
type="button"
onClick={() => onCopyLink(ntfyPreviewUrl)}
className="border border-gray-300 rounded px-2 py-0.5 text-gray-600 hover:text-blue-700 hover:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-400"
title="In Zwischenablage kopieren"
>
Kopieren
</button>
</div>
)}
{copyFeedback && <p className="text-xs text-green-600">{copyFeedback}</p>}
<button
type="button"
onClick={() => onSendTest('ntfy')}
disabled={!settings.ntfy.enabled || saving}
className="text-sm text-blue-600 hover:text-blue-800"
>
Test senden
</button>
</div>
)}
</div>
<div className="bg-white border border-gray-200 rounded-lg p-4 shadow-sm">
<div className="flex items-center justify-between mb-3">
<div>
<h3 className="text-lg font-semibold text-gray-800">Telegram</h3>
<p className="text-xs text-gray-500">
Nutze den Bot des Admins, um Nachrichten direkt in Telegram zu erhalten.
</p>
</div>
<label className="inline-flex items-center space-x-2 text-sm text-gray-700">
<input
type="checkbox"
checked={settings.telegram.enabled}
onChange={(event) => onFieldChange('telegram', 'enabled', event.target.checked)}
disabled={!capabilities.telegram.enabled}
className="h-4 w-4 text-blue-600 rounded focus:ring-blue-500"
/>
<span>Aktiv</span>
</label>
</div>
{!capabilities.telegram.enabled ? (
<p className="text-sm text-gray-500">
Telegram-Benachrichtigungen sind derzeit deaktiviert oder der Bot ist nicht konfiguriert.
</p>
) : (
<div className="space-y-3">
<div>
<label className="block text-xs font-semibold text-gray-600 mb-1">Chat-ID</label>
<input
type="text"
value={settings.telegram.chatId}
onChange={(event) => onFieldChange('telegram', 'chatId', event.target.value)}
placeholder="z. B. 123456789"
className="border rounded p-2 w-full focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
disabled={!settings.telegram.enabled}
/>
<p className="text-xs text-gray-500 mt-1">
Tipp: Schreibe dem Telegram-Bot und nutze{' '}
<a
href="https://t.me/userinfobot"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:text-blue-800"
>
@userinfobot
</a>{' '}
oder ein Chat-ID-Tool.
</p>
</div>
<button
type="button"
onClick={() => onSendTest('telegram')}
disabled={!settings.telegram.enabled || saving}
className="text-sm text-blue-600 hover:text-blue-800"
>
Test senden
</button>
</div>
)}
</div>
</div>
<div className="flex items-center justify-end mt-4 gap-3">
<button
type="button"
onClick={onReset}
className="text-sm text-gray-600 hover:text-gray-900"
disabled={loading}
>
Zurücksetzen
</button>
<button
type="button"
onClick={onSave}
disabled={!dirty || saving}
className="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors disabled:opacity-60"
>
{saving ? 'Speichere...' : 'Benachrichtigungen speichern'}
</button>
</div>
</div>
);
};
export default NotificationPanel;