2026-07-24 22:35:35 +02:00
import React , { useState } from 'react' ;
2026-07-04 00:26:22 +00:00
import { useTranslation } from 'react-i18next' ;
2026-08-17 14:09:00 +02:00
import { Code , BookOpen , FileJson , HardDrive } from 'lucide-react' ;
2026-07-24 22:35:35 +02:00
import { SettingsMenuOrderPage } from './SettingsMenuOrder' ;
import { SettingsThemePage } from './SettingsTheme' ;
import { SettingsPluginsPage } from './SettingsPlugins' ;
2026-07-04 00:26:22 +00:00
export function SettingsSystemPage() {
const { t } = useTranslation ( ) ;
2026-07-24 22:35:35 +02:00
const [ activeTab , setActiveTab ] = useState ( 'menu' ) ;
2026-07-04 00:26:22 +00:00
2026-07-24 22:35:35 +02:00
const tabs = [
{ key : 'menu' , label : t ( 'settings.menuOrder' , 'Menü' ) } ,
{ key : 'theme' , label : t ( 'settings.theme' , 'Theme' ) } ,
{ key : 'plugins' , label : t ( 'settings.plugins' , 'Plugins' ) } ,
2026-08-17 14:09:00 +02:00
{ key : 'storage' , label : t ( 'settings.storage' , 'Storage' ) } ,
2026-07-26 03:08:26 +02:00
{ key : 'entwickler' , label : t ( 'settings.developer' , 'Entwickler' ) } ,
2026-07-24 22:35:35 +02:00
] ;
2026-07-04 00:26:22 +00:00
return (
< div className = "space-y-6" data-testid = "settings-system-page" >
2026-07-24 22:35:35 +02:00
< h1 className = "text-2xl font-bold text-secondary-900" > System < / h1 >
< div className = "border-b border-secondary-200" >
2026-08-27 01:43:06 +02:00
< nav className = "flex gap-4" role = "tablist" aria-label = { t ( 'settingsSystem.systemtabs' ) } >
2026-07-24 22:35:35 +02:00
{ tabs . map ( ( tab ) = > (
< button
key = { tab . key }
onClick = { ( ) = > setActiveTab ( tab . key ) }
role = "tab"
aria-selected = { activeTab === tab . key }
className = { ` px-4 py-2 text-sm font-medium border-b-2 transition-colors ${
activeTab === tab . key
? 'border-primary-500 text-primary-700'
: 'border-transparent text-secondary-600 hover:text-secondary-900 hover:border-secondary-300'
} ` }
>
{ tab . label }
< / button >
) ) }
< / nav >
< / div >
2026-07-04 00:26:22 +00:00
2026-07-24 22:35:35 +02:00
< div role = "tabpanel" >
{ activeTab === 'menu' && < SettingsMenuOrderPage / > }
{ activeTab === 'theme' && < SettingsThemePage / > }
{ activeTab === 'plugins' && < SettingsPluginsPage / > }
2026-08-17 14:09:00 +02:00
{ activeTab === 'storage' && (
< div className = "space-y-6" data-testid = "settings-storage-section" >
< div className = "bg-white rounded-lg border border-secondary-200 p-6" >
< div className = "flex items-center gap-3 mb-4" >
< div className = "w-10 h-10 rounded-lg bg-primary-50 text-primary-600 flex items-center justify-center" >
< HardDrive className = "w-5 h-5" / >
< / div >
< div >
< h3 className = "text-sm font-semibold text-secondary-900" > { t ( 'settings.storage.local' , 'Lokaler Storage' ) } < / h3 >
< p className = "text-xs text-secondary-500" > / data / storage < / p >
< / div >
< / div >
< p className = "text-sm text-secondary-600 mb-4" >
{ t ( 'settings.storage.localDesc' , 'Dateien werden lokal im Docker-Volume gespeichert. Bei Bedarf auf S3 oder externe Storage-Provider umstellbar.' ) }
< / p >
< div className = "grid grid-cols-2 gap-4 text-sm" >
< div >
< span className = "text-secondary-500" > Backend : < / span >
< span className = "ml-2 font-medium text-secondary-900" > Local < / span >
< / div >
< div >
< span className = "text-secondary-500" > Pfad : < / span >
< span className = "ml-2 font-medium text-secondary-900" > / data / storage < / span >
< / div >
< / div >
< / div >
< div className = "bg-white rounded-lg border border-secondary-200 p-6" >
< div className = "flex items-center gap-3 mb-4" >
< div className = "w-10 h-10 rounded-lg bg-warning-50 text-warning-600 flex items-center justify-center" >
< HardDrive className = "w-5 h-5" / >
< / div >
< div >
< h3 className = "text-sm font-semibold text-secondary-900" > { t ( 'settings.storage.s3' , 'S3 Storage' ) } < / h3 >
< p className = "text-xs text-secondary-500" > { t ( 'settings.storage.s3Desc' , 'S3-kompatibler Storage (AWS S3, MinIO, etc.)' ) } < / p >
< / div >
< / div >
< div className = "space-y-3 text-sm" >
< div className = "flex items-center justify-between p-3 bg-secondary-50 rounded-md" >
< span className = "text-secondary-600" > Status < / span >
< span className = "font-medium text-secondary-400" > { t ( 'settings.storage.notConfigured' , 'Nicht konfiguriert' ) } < / span >
< / div >
< p className = "text-xs text-secondary-500" >
{ t ( 'settings.storage.s3Hint' , 'S3 wird via Environment-Variablen konfiguriert: STORAGE_BACKEND=s3, S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY' ) }
< / p >
< / div >
< / div >
< div className = "bg-white rounded-lg border border-secondary-200 p-6" >
< div className = "flex items-center gap-3 mb-4" >
< div className = "w-10 h-10 rounded-lg bg-success-50 text-success-600 flex items-center justify-center" >
< HardDrive className = "w-5 h-5" / >
< / div >
< div >
< h3 className = "text-sm font-semibold text-secondary-900" > { t ( 'settings.storage.external' , 'Externe Storage-Provider' ) } < / h3 >
< p className = "text-xs text-secondary-500" > { t ( 'settings.storage.externalDesc' , 'WebDAV, Nextcloud, Google Drive, Dropbox' ) } < / p >
< / div >
< / div >
< div className = "space-y-3" >
< div className = "flex items-center justify-between p-3 bg-secondary-50 rounded-md" >
< span className = "text-sm text-secondary-600" > { t ( 'settings.storage.webdav' , 'WebDAV' ) } < / span >
< span className = "text-xs font-medium text-secondary-400" > { t ( 'settings.storage.comingSoon' , 'In Entwicklung' ) } < / span >
< / div >
< p className = "text-xs text-secondary-500" >
{ t ( 'settings.storage.externalHint' , 'Externe Storage-Provider werden als Plugins implementiert. In Zukunft hier konfigurierbar.' ) }
< / p >
< / div >
< / div >
< / div >
) }
2026-07-26 03:08:26 +02:00
{ activeTab === 'entwickler' && (
< div className = "space-y-4" data-testid = "settings-developer-section" >
< div className = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4" >
< a
href = "/docs"
target = "_blank"
rel = "noopener noreferrer"
className = "flex items-start gap-3 p-4 rounded-lg border border-secondary-200 bg-white hover:border-primary-300 hover:shadow-sm transition-all min-h-touch"
>
< div className = "flex-shrink-0 w-10 h-10 rounded-lg bg-primary-50 text-primary-600 flex items-center justify-center" >
< Code className = "w-5 h-5" aria-hidden = "true" strokeWidth = { 2 } / >
< / div >
< div className = "min-w-0" >
< p className = "text-sm font-semibold text-secondary-900" >
{ t ( 'settings.apiDocsSwagger' , 'API Dokumentation (Swagger)' ) }
< / p >
< p className = "text-xs text-secondary-500 mt-0.5" > / docs < / p >
< / div >
< / a >
< a
href = "/redoc"
target = "_blank"
rel = "noopener noreferrer"
className = "flex items-start gap-3 p-4 rounded-lg border border-secondary-200 bg-white hover:border-primary-300 hover:shadow-sm transition-all min-h-touch"
>
< div className = "flex-shrink-0 w-10 h-10 rounded-lg bg-primary-50 text-primary-600 flex items-center justify-center" >
< BookOpen className = "w-5 h-5" aria-hidden = "true" strokeWidth = { 2 } / >
< / div >
< div className = "min-w-0" >
< p className = "text-sm font-semibold text-secondary-900" >
{ t ( 'settings.apiDocsRedoc' , 'API Dokumentation (ReDoc)' ) }
< / p >
< p className = "text-xs text-secondary-500 mt-0.5" > / redoc < / p >
< / div >
< / a >
< a
href = "/openapi.json"
target = "_blank"
rel = "noopener noreferrer"
className = "flex items-start gap-3 p-4 rounded-lg border border-secondary-200 bg-white hover:border-primary-300 hover:shadow-sm transition-all min-h-touch"
>
< div className = "flex-shrink-0 w-10 h-10 rounded-lg bg-primary-50 text-primary-600 flex items-center justify-center" >
< FileJson className = "w-5 h-5" aria-hidden = "true" strokeWidth = { 2 } / >
< / div >
< div className = "min-w-0" >
< p className = "text-sm font-semibold text-secondary-900" >
{ t ( 'settings.openApiSchema' , 'OpenAPI Schema' ) }
< / p >
< p className = "text-xs text-secondary-500 mt-0.5" > / openapi . json < / p >
< / div >
< / a >
< / div >
< / div >
) }
2026-07-24 22:35:35 +02:00
< / div >
2026-07-04 00:26:22 +00:00
< / div >
) ;
}