import { ArrowRight, CircleHelp, KeyRound, Sparkles } from 'lucide-react' import { SyntheticEvent, useState } from 'react' import Logo from '../../components/layout/Logo' import { FormField } from '../../components/form' import { ErrorAlert, errorMessage } from '../../components/actions' import { ThemeControls } from '../../theme' import { api, authStorage } from '../../api/client' const LOGIN_PATH = '/api/auth/login' /** * The sign-in screen. * * Signing in happens at Go Loose, so the usual case is one button that hands the * browser over to it and comes back to the welcome page. That also means a person * who already signed in at another application passes straight through, because * Go Loose recognises the session it already holds and issues a code without * asking anything. * * The password form is only for a host where Go Loose login is not configured: * the API answers /api/auth/session with 404 there, and without a fallback the * application would be unreachable on a bare localhost. It is not offered where * the identity provider is in charge. */ export function LoginPage({ onLogin, sessionExpired, ssoAvailable, }: { onLogin: () => void sessionExpired: boolean /** null until the API has said whether Go Loose login is configured here. */ ssoAvailable: boolean | null }) { const [loading, setLoading] = useState(false) const [error, setError] = useState('') function beginExternalLogin() { setLoading(true) // A full navigation, not a router push: Go Loose answers with a redirect // chain across two origins that the router has no part in. window.location.assign(LOGIN_PATH) } async function submit(event: SyntheticEvent) { event.preventDefault() setLoading(true) setError('') const form = new FormData(event.currentTarget) try { const auth = await api.login(String(form.get('email')), String(form.get('password'))) authStorage.save(auth) onLogin() } catch (requestError) { setError(errorMessage(requestError)) } finally { setLoading(false) } } return (
Better hiring, clearly connected

Find the right person for every journey.

Bring roles, assessments, and candidate insight together in one workspace.

Skills-first matching Structured signals for confident decisions

Designed for fair, collaborative recruitment.

Welcome back

Sign in to your workspace

{sessionExpired && (
Your session is no longer active. Sign in again to continue.
)}

Use your work account to continue. If you are already signed in elsewhere, this takes you straight through.

{ssoAvailable === false ? (

Single sign-on is not configured for this host. Sign in with a local account.

{error && } ) : (
)}

Contact your administrator for access.

) }