43bbcece7a
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>
53 lines
1.7 KiB
TypeScript
53 lines
1.7 KiB
TypeScript
import type { ConnectionStatus } from '../types/connection'
|
|
import './ServiceCard.scss'
|
|
|
|
interface Props {
|
|
serviceType: string
|
|
label: string
|
|
icon: string
|
|
status: ConnectionStatus | null
|
|
onConnect: () => void
|
|
onDisconnect: () => void
|
|
}
|
|
|
|
export function ServiceCard({ serviceType: _serviceType, label, icon, status, onConnect, onDisconnect }: Readonly<Props>) {
|
|
const connected = status?.connected ?? false
|
|
|
|
const formatExpiry = (iso: string | null) => {
|
|
if (!iso) return null
|
|
const d = new Date(iso)
|
|
return d.toLocaleDateString(undefined, { dateStyle: 'medium' })
|
|
}
|
|
|
|
return (
|
|
<div className="service-card">
|
|
<div className="service-card__info">
|
|
<div className="service-card__icon">{icon}</div>
|
|
<div>
|
|
<p className="service-card__name">{label}</p>
|
|
<p className="service-card__meta">
|
|
<span className={`service-card__badge service-card__badge--${connected ? 'connected' : 'disconnected'}`}>
|
|
{connected ? 'Connected' : 'Not connected'}
|
|
</span>
|
|
{connected && status?.username && <span>{status.username}</span>}
|
|
{connected && status?.expiresAt && (
|
|
<span>· expires {formatExpiry(status.expiresAt)}</span>
|
|
)}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div className="service-card__actions">
|
|
{connected ? (
|
|
<button className="service-card__btn service-card__btn--disconnect" onClick={onDisconnect}>
|
|
Disconnect
|
|
</button>
|
|
) : (
|
|
<button className="service-card__btn service-card__btn--connect" onClick={onConnect}>
|
|
Connect
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|