mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-04-15 10:01:31 +00:00
139 lines
4.1 KiB
TypeScript
139 lines
4.1 KiB
TypeScript
import { useCallback, useState } from 'react';
|
|
import type { FormEvent } from 'react';
|
|
import { useAuth } from '../context/AuthContext';
|
|
import AuthErrorAlert from './AuthErrorAlert';
|
|
import AuthInputField from './AuthInputField';
|
|
import AuthScreenLayout from './AuthScreenLayout';
|
|
|
|
type SetupFormState = {
|
|
username: string;
|
|
password: string;
|
|
confirmPassword: string;
|
|
};
|
|
|
|
const initialState: SetupFormState = {
|
|
username: '',
|
|
password: '',
|
|
confirmPassword: '',
|
|
};
|
|
|
|
/**
|
|
* Validates the account-setup form state.
|
|
* @returns An error message string if validation fails, or `null` when the
|
|
* form is valid.
|
|
*/
|
|
function validateSetupForm(formState: SetupFormState): string | null {
|
|
if (!formState.username.trim() || !formState.password || !formState.confirmPassword) {
|
|
return 'Please fill in all fields.';
|
|
}
|
|
|
|
if (formState.username.trim().length < 3) {
|
|
return 'Username must be at least 3 characters long.';
|
|
}
|
|
|
|
if (formState.password.length < 6) {
|
|
return 'Password must be at least 6 characters long.';
|
|
}
|
|
|
|
if (formState.password !== formState.confirmPassword) {
|
|
return 'Passwords do not match.';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Account setup / registration form.
|
|
* Uses `autoComplete="new-password"` on password fields so that password
|
|
* managers recognise this as a registration flow and offer to save the new
|
|
* credentials after submission.
|
|
*/
|
|
export default function SetupForm() {
|
|
const { register } = useAuth();
|
|
|
|
const [formState, setFormState] = useState<SetupFormState>(initialState);
|
|
const [errorMessage, setErrorMessage] = useState('');
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
|
|
const updateField = useCallback((field: keyof SetupFormState, value: string) => {
|
|
setFormState((previous) => ({ ...previous, [field]: value }));
|
|
}, []);
|
|
|
|
const handleSubmit = useCallback(
|
|
async (event: FormEvent<HTMLFormElement>) => {
|
|
event.preventDefault();
|
|
setErrorMessage('');
|
|
|
|
const validationError = validateSetupForm(formState);
|
|
if (validationError) {
|
|
setErrorMessage(validationError);
|
|
return;
|
|
}
|
|
|
|
setIsSubmitting(true);
|
|
const result = await register(formState.username.trim(), formState.password);
|
|
if (!result.success) {
|
|
setErrorMessage(result.error);
|
|
}
|
|
setIsSubmitting(false);
|
|
},
|
|
[formState, register],
|
|
);
|
|
|
|
return (
|
|
<AuthScreenLayout
|
|
title="Welcome to CloudCLI"
|
|
description="Set up your account to get started"
|
|
footerText="This is a single-user system. Only one account can be created."
|
|
logo={<img src="/logo.svg" alt="CloudCLI" className="h-16 w-16" />}
|
|
>
|
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
<AuthInputField
|
|
id="username"
|
|
name="username"
|
|
label="Username"
|
|
value={formState.username}
|
|
onChange={(value) => updateField('username', value)}
|
|
placeholder="Enter your username"
|
|
isDisabled={isSubmitting}
|
|
autoComplete="username"
|
|
/>
|
|
|
|
<AuthInputField
|
|
id="password"
|
|
name="password"
|
|
label="Password"
|
|
value={formState.password}
|
|
onChange={(value) => updateField('password', value)}
|
|
placeholder="Enter your password"
|
|
isDisabled={isSubmitting}
|
|
type="password"
|
|
autoComplete="new-password"
|
|
/>
|
|
|
|
<AuthInputField
|
|
id="confirmPassword"
|
|
name="confirmPassword"
|
|
label="Confirm Password"
|
|
value={formState.confirmPassword}
|
|
onChange={(value) => updateField('confirmPassword', value)}
|
|
placeholder="Confirm your password"
|
|
isDisabled={isSubmitting}
|
|
type="password"
|
|
autoComplete="new-password"
|
|
/>
|
|
|
|
<AuthErrorAlert errorMessage={errorMessage} />
|
|
|
|
<button
|
|
type="submit"
|
|
disabled={isSubmitting}
|
|
className="w-full rounded-md bg-blue-600 px-4 py-2 font-medium text-white transition-colors duration-200 hover:bg-blue-700 disabled:bg-blue-400"
|
|
>
|
|
{isSubmitting ? 'Setting up...' : 'Create Account'}
|
|
</button>
|
|
</form>
|
|
</AuthScreenLayout>
|
|
);
|
|
}
|