94 lines
2.7 KiB
TypeScript
Executable File
94 lines
2.7 KiB
TypeScript
Executable File
'use client';
|
|
|
|
import { clearExpiredSessionAction, loginAction, LoginResult } from '@/lib/actions/auth';
|
|
import { use, useActionState, useEffect } from 'react';
|
|
import type { HealthStatus } from '@/lib/api/server/health';
|
|
import { Badge } from '@/components/ui/Badge';
|
|
|
|
const initialState: LoginResult = {
|
|
message: '',
|
|
success: true
|
|
};
|
|
|
|
export default function LoginForm({
|
|
searchParams,
|
|
health
|
|
}: {
|
|
searchParams: Promise<{ expired: boolean | undefined }>;
|
|
health: HealthStatus;
|
|
}) {
|
|
const params = use(searchParams);
|
|
const expired = params.expired;
|
|
|
|
useEffect(() => {
|
|
if (expired) {
|
|
clearExpiredSessionAction();
|
|
}
|
|
}, [expired]);
|
|
const [state, formAction] = useActionState(loginAction, initialState);
|
|
return (
|
|
<div className="flex min-h-screen items-center justify-center bg-base px-4">
|
|
<div className="w-full max-w-md space-y-6 rounded-lg border border-border bg-canvas p-8 shadow-xl">
|
|
<div className="text-center">
|
|
<h1 className="text-xl font-bold text-primary">ACC Server Manager</h1>
|
|
<p className="mt-1 text-sm text-muted">Sign in to manage your servers</p>
|
|
<div className="mt-2 flex justify-center">
|
|
{health.healthy ? (
|
|
<Badge variant="green">API v{health.version}</Badge>
|
|
) : (
|
|
<Badge variant="red">API unreachable</Badge>
|
|
)}
|
|
</div>
|
|
</div>
|
|
{expired && (
|
|
<div className="rounded-md border border-yellow/30 bg-yellow-bg px-3 py-2 text-sm text-yellow">
|
|
Your session has expired. Please sign in again.
|
|
</div>
|
|
)}
|
|
{state?.success ? null : (
|
|
<div className="rounded-md border border-red/30 bg-red-bg px-3 py-2 text-sm text-red">
|
|
{state?.message}
|
|
</div>
|
|
)}
|
|
|
|
<form action={formAction} className="space-y-4">
|
|
<div>
|
|
<label htmlFor="username" className="mb-1.5 block text-sm font-medium text-secondary">
|
|
Username
|
|
</label>
|
|
<input
|
|
id="username"
|
|
name="username"
|
|
type="text"
|
|
autoComplete="username"
|
|
required
|
|
className="form-input"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label htmlFor="password" className="mb-1.5 block text-sm font-medium text-secondary">
|
|
Password
|
|
</label>
|
|
<input
|
|
id="password"
|
|
name="password"
|
|
type="password"
|
|
autoComplete="current-password"
|
|
required
|
|
className="form-input"
|
|
/>
|
|
</div>
|
|
|
|
<button
|
|
type="submit"
|
|
className="w-full rounded-md bg-btn-green border border-btn-green px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-btn-green-hover focus:outline-none focus:ring-2 focus:ring-blue focus:ring-offset-2 focus:ring-offset-base"
|
|
>
|
|
Sign in
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|