diff --git a/application/src/pages/Login.tsx b/application/src/pages/Login.tsx index efaa951..37418d1 100644 --- a/application/src/pages/Login.tsx +++ b/application/src/pages/Login.tsx @@ -5,13 +5,15 @@ import { authService } from '@/services/authService'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { toast } from '@/components/ui/use-toast'; -import { Eye, EyeOff, Mail, LogIn, Settings } from "lucide-react"; +import { Alert, AlertDescription } from '@/components/ui/alert'; +import { Eye, EyeOff, Mail, LogIn, Settings, AlertCircle } from "lucide-react"; import { useLanguage } from '@/contexts/LanguageContext'; import { useTheme } from '@/contexts/ThemeContext'; import { API_ENDPOINTS, getCurrentEndpoint, setApiEndpoint } from '@/lib/pocketbase'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { Label } from '@/components/ui/label'; +import { ForgotPasswordDialog } from '@/components/auth/ForgotPasswordDialog'; const Login = () => { const [email, setEmail] = useState(''); @@ -19,6 +21,8 @@ const Login = () => { const [loading, setLoading] = useState(false); const [showPassword, setShowPassword] = useState(false); const [currentEndpoint, setCurrentEndpoint] = useState(getCurrentEndpoint()); + const [showForgotPassword, setShowForgotPassword] = useState(false); + const [loginError, setLoginError] = useState(''); const navigate = useNavigate(); const { t } = useLanguage(); const { theme } = useTheme(); @@ -42,6 +46,7 @@ const Login = () => { const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); + setLoginError(''); // Clear previous errors try { await authService.login({ email, password }); @@ -52,11 +57,31 @@ const Login = () => { navigate('/dashboard'); } catch (error) { console.error("Login error details:", error); + + // Set specific error message based on the error + if (error instanceof Error) { + if (error.message.includes('Failed to authenticate') || + error.message.includes('Authentication failed') || + error.message.includes('Invalid credentials') || + error.message.includes('invalid email or password')) { + setLoginError(t("invalidCredentials")); + } else { + setLoginError(error.message); + } + } else { + setLoginError(`${t("authenticationFailed")}. Server: ${currentEndpoint}`); + } + toast({ variant: "destructive", title: t("loginFailed"), description: error instanceof Error - ? error.message + ? (error.message.includes('Failed to authenticate') || + error.message.includes('Authentication failed') || + error.message.includes('Invalid credentials') || + error.message.includes('invalid email or password')) + ? t("invalidCredentials") + : error.message : `${t("authenticationFailed")}. Server: ${currentEndpoint}`, }); } finally { @@ -115,8 +140,8 @@ const Login = () => {
Checkcle Logo
@@ -127,6 +152,14 @@ const Login = () => { {/* Removed Google Sign in button section */}
+ {/* Error Alert */} + {loginError && ( + + + {loginError} + + )} +
@@ -138,7 +171,10 @@ const Login = () => { placeholder="your.email@provider.com" type="email" value={email} - onChange={(e) => setEmail(e.target.value)} + onChange={(e) => { + setEmail(e.target.value); + setLoginError(''); // Clear error when user starts typing + }} required className="pl-10 text-sm sm:text-base h-9 sm:h-10" /> @@ -148,7 +184,13 @@ const Login = () => {
- {t("forgot")} +
@@ -162,7 +204,10 @@ const Login = () => { placeholder="••••••••••••" type={showPassword ? 'text' : 'password'} value={password} - onChange={(e) => setPassword(e.target.value)} + onChange={(e) => { + setPassword(e.target.value); + setLoginError(''); // Clear error when user starts typing + }} required className="pl-10 text-sm sm:text-base h-9 sm:h-10" /> @@ -195,6 +240,11 @@ const Login = () => {

+ +
); };