Migrates the React app from Create React App (CRA) to Vite for faster build times and improved development experience. Also updates all dependencies to their latest versions. BREAKING CHANGE: Removes react-scripts and CRA-related dependencies. The development and build processes now rely on Vite.
134 lines
5.1 KiB
JavaScript
134 lines
5.1 KiB
JavaScript
import React, { useState } from 'react';
|
|
|
|
const LoginPage = () => {
|
|
const [loginType, setLoginType] = useState('email'); // 'email' or 'phone'
|
|
const [identifier, setIdentifier] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
|
|
const handleLogin = (e) => {
|
|
e.preventDefault();
|
|
|
|
if (!identifier || !password) {
|
|
alert('Please fill in all fields.');
|
|
return;
|
|
}
|
|
|
|
if (loginType === 'email') {
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
if (!emailRegex.test(identifier)) {
|
|
alert('Please enter a valid email address.');
|
|
return;
|
|
}
|
|
} else {
|
|
// Basic phone number validation (e.g., starts with + and has digits)
|
|
const phoneRegex = /^\+?[0-9\s-]{8,}$/;
|
|
if (!phoneRegex.test(identifier)) {
|
|
alert('Please enter a valid phone number.');
|
|
return;
|
|
}
|
|
}
|
|
|
|
console.log(`Attempting to log in with ${loginType}: ${identifier}`);
|
|
// In a real application, you would make an API call here
|
|
alert(`Login successful with ${loginType}!`);
|
|
};
|
|
|
|
return (
|
|
<div className="flex items-center justify-center min-h-screen bg-gray-50 dark:bg-gray-900">
|
|
<div className="w-full max-w-md p-8 space-y-6 bg-white rounded-lg shadow-md dark:bg-gray-800">
|
|
<div className="text-center">
|
|
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">Welcome Back</h1>
|
|
<p className="mt-2 text-sm text-gray-500 dark:text-gray-400">
|
|
Login to access your account.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex border border-gray-300 dark:border-gray-600 rounded-lg p-1">
|
|
<button
|
|
onClick={() => setLoginType('email')}
|
|
className={`w-full py-2 text-sm font-medium rounded-md transition-all duration-300 ${
|
|
loginType === 'email'
|
|
? 'bg-blue-600 text-white'
|
|
: 'text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700'
|
|
}`}
|
|
>
|
|
Email
|
|
</button>
|
|
<button
|
|
onClick={() => setLoginType('phone')}
|
|
className={`w-full py-2 text-sm font-medium rounded-md transition-all duration-300 ${
|
|
loginType === 'phone'
|
|
? 'bg-blue-600 text-white'
|
|
: 'text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700'
|
|
}`}
|
|
>
|
|
Phone Number
|
|
</button>
|
|
</div>
|
|
|
|
<form className="space-y-4" onSubmit={handleLogin}>
|
|
<div>
|
|
<label htmlFor={loginType} className="sr-only">
|
|
{loginType === 'email' ? 'Email' : 'Phone Number'}
|
|
</label>
|
|
<input
|
|
id={loginType}
|
|
name={loginType}
|
|
type={loginType === 'email' ? 'email' : 'tel'}
|
|
autoComplete={loginType}
|
|
required
|
|
value={identifier}
|
|
onChange={(e) => setIdentifier(e.target.value)}
|
|
className="w-full px-4 py-2 text-gray-900 bg-white border border-gray-300 rounded-lg appearance-none focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white"
|
|
placeholder={loginType === 'email' ? 'name@company.com' : '+1 (555) 000-0000'}
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label htmlFor="password" className="sr-only">Password</label>
|
|
<input
|
|
id="password"
|
|
name="password"
|
|
type="password"
|
|
autoComplete="current-password"
|
|
required
|
|
value={password}
|
|
onChange={(e) => setPassword(e.target.value)}
|
|
className="w-full px-4 py-2 text-gray-900 bg-white border border-gray-300 rounded-lg appearance-none focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white"
|
|
placeholder="Password"
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center">
|
|
<input
|
|
id="remember-me"
|
|
name="remember-me"
|
|
type="checkbox"
|
|
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
|
|
/>
|
|
<label htmlFor="remember-me" className="ml-2 text-sm text-gray-600 dark:text-gray-300">
|
|
Remember me
|
|
</label>
|
|
</div>
|
|
|
|
<div className="text-sm">
|
|
<a href="#" className="font-medium text-blue-600 hover:underline dark:text-blue-500">
|
|
Forgot password?
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<button
|
|
type="submit"
|
|
className="w-full px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:focus:ring-offset-gray-800"
|
|
>
|
|
Sign In
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default LoginPage; |