140 lines
5.1 KiB
TypeScript
140 lines
5.1 KiB
TypeScript
import React, { useState, useCallback } from 'react'
|
|
import { loginSchema, LoginFormData, FieldErrors } from '../validation'
|
|
import { ZodError } from 'zod'
|
|
|
|
interface UseLoginFormProps {
|
|
onSubmitSuccess?: (data: LoginFormData) => void // Optional callback for successful submission
|
|
}
|
|
|
|
export function useLoginForm({ onSubmitSuccess }: UseLoginFormProps = {}) {
|
|
const [formData, setFormData] = useState<LoginFormData>({
|
|
identifier: '', // Can hold email or username
|
|
password: '',
|
|
saveLogin: false,
|
|
savePassword: false,
|
|
})
|
|
const [errors, setErrors] = useState<FieldErrors<LoginFormData>>({})
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
const [submitError, setSubmitError] = useState<string | null>(null)
|
|
|
|
const handleChange = useCallback(
|
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const { name, value, type, checked } = e.target
|
|
setFormData(prev => ({
|
|
...prev,
|
|
[name]: type === 'checkbox' ? checked : value,
|
|
}))
|
|
// Clear error for the field being edited
|
|
if (errors[name as keyof LoginFormData]) {
|
|
setErrors(prev => ({ ...prev, [name]: undefined }))
|
|
}
|
|
// Clear general submission error
|
|
if (submitError) {
|
|
setSubmitError(null)
|
|
}
|
|
},
|
|
[errors, submitError],
|
|
)
|
|
|
|
const validateForm = useCallback(() => {
|
|
try {
|
|
loginSchema.parse(formData)
|
|
setErrors({})
|
|
return true
|
|
} catch (error) {
|
|
if (error instanceof ZodError) {
|
|
const fieldErrors: FieldErrors<LoginFormData> = {}
|
|
error.errors.forEach(err => {
|
|
if (err.path.length > 0) {
|
|
fieldErrors[err.path[0] as keyof LoginFormData] =
|
|
err.message
|
|
}
|
|
})
|
|
setErrors(fieldErrors)
|
|
} else {
|
|
console.error(
|
|
'An unexpected error occurred during validation:',
|
|
error,
|
|
)
|
|
setSubmitError('An unexpected validation error occurred.')
|
|
}
|
|
return false
|
|
}
|
|
}, [formData])
|
|
|
|
const handleSubmit = useCallback(
|
|
async (e: React.FormEvent<HTMLFormElement>) => {
|
|
e.preventDefault()
|
|
setSubmitError(null)
|
|
|
|
if (!validateForm()) {
|
|
return
|
|
}
|
|
|
|
setIsLoading(true)
|
|
console.log('Submitting login data:', formData)
|
|
|
|
// --- TODO: Replace with actual API call to your RageMP server ---
|
|
try {
|
|
// Example: Simulate API call
|
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
|
|
// Assuming API returns success:
|
|
console.log('Login successful!')
|
|
// Here you would typically receive a token or session info
|
|
// Handle 'saveLogin' and 'savePassword' (e.g., using localStorage/sessionStorage)
|
|
if (formData.saveLogin) {
|
|
localStorage.setItem('savedUsername', formData.identifier) // Example
|
|
} else {
|
|
localStorage.removeItem('savedUsername') // Example
|
|
}
|
|
// Password saving is generally discouraged for security reasons,
|
|
// but if required:
|
|
if (formData.savePassword) {
|
|
// Be VERY careful with storing passwords. Consider secure storage or tokens.
|
|
// localStorage.setItem('savedPassword', formData.password); // **Highly discouraged**
|
|
console.warn(
|
|
'Password saving enabled - ensure secure storage mechanism.',
|
|
)
|
|
}
|
|
|
|
setErrors({}) // Clear errors on success
|
|
if (onSubmitSuccess) {
|
|
onSubmitSuccess(formData) // Call success callback
|
|
}
|
|
// You might redirect the user or update application state here
|
|
|
|
// --- Mock Error Handling (remove in real implementation) ---
|
|
// if (formData.identifier === 'wrong') {
|
|
// throw new Error("Invalid credentials.");
|
|
// }
|
|
// --- End Mock Error Handling ---
|
|
} catch (apiError: unknown) {
|
|
console.error('Login API error:', apiError)
|
|
setSubmitError('Login failed. Please check your credentials.')
|
|
} finally {
|
|
setIsLoading(false)
|
|
}
|
|
// --- End API call section ---
|
|
},
|
|
[formData, validateForm, onSubmitSuccess],
|
|
)
|
|
|
|
// Effect to potentially load saved username on initial render (example)
|
|
// useEffect(() => {
|
|
// const savedUser = localStorage.getItem('savedUsername');
|
|
// if (savedUser) {
|
|
// setFormData(prev => ({ ...prev, identifier: savedUser, saveLogin: true }));
|
|
// }
|
|
// }, []);
|
|
|
|
return {
|
|
formData,
|
|
errors,
|
|
isLoading,
|
|
submitError,
|
|
handleChange,
|
|
handleSubmit,
|
|
}
|
|
}
|