// frontend\src\components\ui\PostgresUrlModal.tsx 'use client' import { useMemo, useState } from 'react' import Modal from './Modal' import Button from './Button' type Props = { open: boolean onClose: () => void initialUrl?: string initialHasPassword?: boolean onApply: (v: { databaseUrl: string; dbPassword: string }) => void } function safeInt(v: any, fallback: number) { const n = Number(v) return Number.isFinite(n) && n > 0 ? Math.floor(n) : fallback } function buildPostgresUrl(opts: { user: string host: string port: number db: string sslmode: string }) { const user = (opts.user || '').trim() || 'postgres' const host = (opts.host || '').trim() || '127.0.0.1' const port = safeInt(opts.port, 5432) const db = (opts.db || '').trim() || 'postgres' const sslmode = (opts.sslmode || '').trim() || 'disable' // Passwort absichtlich NICHT in URL return `postgres://${encodeURIComponent(user)}@${host}:${port}/${encodeURIComponent(db)}?sslmode=${encodeURIComponent( sslmode )}` } export default function PostgresUrlModal({ open, onClose, initialUrl, initialHasPassword, onApply, }: Props) { // Defaults (du kannst später optional initialUrl parsen, ist aber nicht nötig) const [host, setHost] = useState('127.0.0.1') const [port, setPort] = useState(5432) const [db, setDb] = useState('nsfwapp') const [user, setUser] = useState('postgres') const [password, setPassword] = useState('') const [sslmode, setSslmode] = useState<'disable' | 'require' | 'verify-full'>('disable') const preview = useMemo(() => buildPostgresUrl({ user, host, port, db, sslmode }), [user, host, port, db, sslmode]) const footer = ( <> Abbrechen { onApply({ databaseUrl: preview, dbPassword: password }) onClose() }} > Übernehmen > ) return ( Passwort wird verschlüsselt gespeichert (nicht in der URL). {initialUrl ? ( <> Aktuelle URL: {initialUrl} > ) : null} {initialHasPassword ? Passwort: ✅ gespeichert : null} Host setHost(e.target.value)} className="sm:col-span-9 rounded-lg px-3 py-2 text-sm bg-white text-gray-900 ring-1 ring-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-white/10 dark:text-white dark:ring-white/10" placeholder="127.0.0.1" /> Port setPort(safeInt(e.target.value, 5432))} className="sm:col-span-9 rounded-lg px-3 py-2 text-sm bg-white text-gray-900 ring-1 ring-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-white/10 dark:text-white dark:ring-white/10" /> Datenbank setDb(e.target.value)} className="sm:col-span-9 rounded-lg px-3 py-2 text-sm bg-white text-gray-900 ring-1 ring-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-white/10 dark:text-white dark:ring-white/10" placeholder="nsfwapp" /> User setUser(e.target.value)} className="sm:col-span-9 rounded-lg px-3 py-2 text-sm bg-white text-gray-900 ring-1 ring-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-white/10 dark:text-white dark:ring-white/10" placeholder="postgres" /> Passwort setPassword(e.target.value)} type="password" className="sm:col-span-9 rounded-lg px-3 py-2 text-sm bg-white text-gray-900 ring-1 ring-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-white/10 dark:text-white dark:ring-white/10" placeholder="••••••••" /> SSL setSslmode(e.target.value as any)} className="sm:col-span-9 h-10 rounded-lg px-3 text-sm bg-white text-gray-900 ring-1 ring-gray-200 shadow-sm dark:border-white/10 dark:bg-gray-900 dark:text-gray-100 dark:[color-scheme:dark]" > disable require verify-full Vorschau {preview} ) }
{initialUrl}
{preview}