add session-based connection management and React dashboard

Backend: adds JDBC session support, login/status/logout endpoints, and
new DTOs (AuthResponse, ConnectionStatusResponse, LoginResult). Frontend
replaces the Vite boilerplate with a Dashboard, ServiceCard, and
ConnectModal backed by a typed API client.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-10 03:30:36 +02:00
parent 0127706262
commit 43bbcece7a
30 changed files with 1307 additions and 350 deletions
+59
View File
@@ -0,0 +1,59 @@
import { useState, useEffect } from "react"
import { getStatuses, logout } from "../api/connections"
import type { ConnectionStatus } from "../types/connection"
import { ServiceCard } from "./ServiceCard"
import { ConnectModal } from "./ConnectModal"
import "./Dashboard.scss"
const SERVICES = [
{ serviceType: 'HOMEBOX', label: 'Homebox', icon: '📦' },
] as const
export function Dashboard() {
const [statuses, setStatuses] = useState<ConnectionStatus[]>([])
const [openModal, setOpenModal] = useState<string | null>(null)
const refresh = () => {
getStatuses().then(setStatuses).catch(() => { })
}
useEffect(() => { refresh() }, [])
const handleDisconnect = (serviceType: string) => {
logout(serviceType).then(refresh).catch(() => { })
}
const activeModal = SERVICES.find(s => s.serviceType === openModal)
return (
<div className="dashboard">
<div className="dashboard__header">
<h1 className="dashboard__title">Vaessl Dashboard</h1>
</div>
<p className="dashboard__section-label">Services</p>
<div className="dashboard__cards">
{SERVICES.map(({ serviceType, label, icon }) => (
<ServiceCard
key={serviceType}
serviceType={serviceType}
label={label}
icon={icon}
status={statuses.find(s => s.serviceType === serviceType) ?? null}
onConnect={() => setOpenModal(serviceType)}
onDisconnect={() => handleDisconnect(serviceType)}
/>
))}
</div>
{activeModal && (
<ConnectModal
serviceType={activeModal.serviceType}
label={activeModal.label}
onClose={() => setOpenModal(null)}
onSuccess={() => { setOpenModal(null); refresh() }}
/>
)}
</div>
)
}