feat(auth): Convert login system to use email as username

- Backend login now accepts 'email' field (with backward compatibility)
- User creation (signup, invitation, customer) uses email as username
- Frontend login form updated with email input and validation
- Updated test users to use email addresses as usernames
- Updated all translation files (en, es, fr, de)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-04 10:38:53 -05:00
parent a2f74ee769
commit dbe91ec2ff
10 changed files with 71 additions and 86 deletions

View File

@@ -11,11 +11,11 @@ import SmoothScheduleLogo from '../components/SmoothScheduleLogo';
import OAuthButtons from '../components/OAuthButtons';
import LanguageSelector from '../components/LanguageSelector';
import { DevQuickLogin } from '../components/DevQuickLogin';
import { AlertCircle, Loader2, User, Lock, ArrowRight } from 'lucide-react';
import { AlertCircle, Loader2, Mail, Lock, ArrowRight } from 'lucide-react';
const LoginPage: React.FC = () => {
const { t } = useTranslation();
const [username, setUsername] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
@@ -27,7 +27,7 @@ const LoginPage: React.FC = () => {
setError('');
loginMutation.mutate(
{ username, password },
{ email, password },
{
onSuccess: (data) => {
// Check if MFA is required
@@ -202,25 +202,25 @@ const LoginPage: React.FC = () => {
<form className="space-y-6" onSubmit={handleSubmit}>
<div className="space-y-4">
{/* Username */}
{/* Email */}
<div>
<label htmlFor="username" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
{t('auth.username')}
<label htmlFor="email" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
{t('auth.email')}
</label>
<div className="relative rounded-md shadow-sm">
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<User className="h-5 w-5 text-gray-400" aria-hidden="true" />
<Mail className="h-5 w-5 text-gray-400" aria-hidden="true" />
</div>
<input
id="username"
name="username"
type="text"
autoComplete="username"
id="email"
name="email"
type="email"
autoComplete="email"
required
className="focus:ring-brand-500 focus:border-brand-500 block w-full pl-10 sm:text-sm border-gray-300 dark:border-gray-700 rounded-lg py-3 bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-400 transition-colors"
placeholder={t('auth.enterUsername')}
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder={t('auth.enterEmail')}
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
</div>