/* ┌──────────────────────────────────────────────────────────────────────────────┐ │ @author: Davidson Gomes │ │ @file: /app/login/page.tsx │ │ Developed by: Davidson Gomes │ │ Creation date: May 13, 2025 │ │ Contact: contato@evolution-api.com │ ├──────────────────────────────────────────────────────────────────────────────┤ │ @copyright © Evolution API 2025. All rights reserved. │ │ Licensed under the Apache License, Version 2.0 │ │ │ │ You may not use this file except in compliance with the License. │ │ You may obtain a copy of the License at │ │ │ │ http://www.apache.org/licenses/LICENSE-2.0 │ │ │ │ Unless required by applicable law or agreed to in writing, software │ │ distributed under the License is distributed on an "AS IS" BASIS, │ │ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ │ See the License for the specific language governing permissions and │ │ limitations under the License. │ ├──────────────────────────────────────────────────────────────────────────────┤ │ @important │ │ For any future changes to the code in this file, it is recommended to │ │ include, together with the modification, the information of the developer │ │ who changed it and the date of modification. │ └──────────────────────────────────────────────────────────────────────────────┘ */ "use client"; import type React from "react"; import { useState, useRef, useEffect } from "react"; import { useRouter } from "next/navigation"; import Image from "next/image"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { useToast } from "@/hooks/use-toast"; import Link from "next/link"; import { login, forgotPassword, getMe, register, resendVerification } from "@/services/authService"; import { CheckCircle2, AlertCircle } from "lucide-react"; export default function LoginPage() { const router = useRouter(); const { toast } = useToast(); const [isLoading, setIsLoading] = useState(false); const [activeTab, setActiveTab] = useState("login"); const [showRegisterSuccess, setShowRegisterSuccess] = useState(false); const [showForgotSuccess, setShowForgotSuccess] = useState(false); const [redirectSeconds, setRedirectSeconds] = useState(5); const redirectTimer = useRef(null); const [loginError, setLoginError] = useState(""); const [isEmailNotVerified, setIsEmailNotVerified] = useState(false); const [isResendingVerification, setIsResendingVerification] = useState(false); const [loginData, setLoginData] = useState({ email: "", password: "", }); const [registerData, setRegisterData] = useState({ email: "", password: "", confirmPassword: "", name: "", }); const [forgotEmail, setForgotEmail] = useState(""); const handleLogin = async (e: React.FormEvent) => { e.preventDefault(); setIsLoading(true); setLoginError(""); setIsEmailNotVerified(false); try { const response = await login({ email: loginData.email, password: loginData.password, }); if (response.data.access_token) { localStorage.setItem("access_token", response.data.access_token); document.cookie = `access_token=${ response.data.access_token }; path=/; max-age=${60 * 60 * 24 * 7}`; const meResponse = await getMe(); if (meResponse.data) { localStorage.setItem("user", JSON.stringify(meResponse.data)); document.cookie = `user=${encodeURIComponent( JSON.stringify(meResponse.data) )}; path=/; max-age=${60 * 60 * 24 * 7}`; } } router.push("/"); } catch (error: any) { let errorDetail = "Check your credentials and try again."; if (error?.response?.data) { if (typeof error.response.data.detail === 'string') { errorDetail = error.response.data.detail; } else if (error.response.data.detail) { errorDetail = JSON.stringify(error.response.data.detail); } } if (errorDetail === "Email not verified") { setIsEmailNotVerified(true); } setLoginError(errorDetail); } finally { setIsLoading(false); } }; const handleResendVerification = async () => { if (!loginData.email) return; setIsResendingVerification(true); try { await resendVerification({ email: loginData.email }); toast({ title: "Verification email sent", description: "Please check your inbox to verify your account.", }); } catch (error: any) { toast({ title: "Error sending verification email", description: error?.response?.data?.detail || "Unable to send verification email. Please try again.", variant: "destructive", }); } finally { setIsResendingVerification(false); } }; const handleRegister = async (e: React.FormEvent) => { e.preventDefault(); if (!registerData.password) { toast({ title: "Password required", description: "Please enter a password.", variant: "destructive", }); return; } if (registerData.password.length < 8) { toast({ title: "Password too short", description: "Password must be at least 8 characters long.", variant: "destructive", }); return; } if (registerData.password !== registerData.confirmPassword) { toast({ title: "Passwords don't match", description: "Please make sure your passwords match.", variant: "destructive", }); return; } setIsLoading(true); try { await register({ email: registerData.email, password: registerData.password, name: registerData.name, }); toast({ title: "Registration successful", description: "Please check your email to verify your account.", }); setShowRegisterSuccess(true); setRedirectSeconds(5); if (redirectTimer.current) clearTimeout(redirectTimer.current); redirectTimer.current = setInterval(() => { setRedirectSeconds((s) => s - 1); }, 1000); } catch (error: any) { let errorMessage = "Unable to register. Please try again."; if (error?.response?.data) { if (typeof error.response.data.detail === 'string') { errorMessage = error.response.data.detail; } else if (error.response.data.detail) { errorMessage = JSON.stringify(error.response.data.detail); } } toast({ title: "Error registering", description: errorMessage, variant: "destructive", }); } finally { setIsLoading(false); } }; useEffect(() => { if ((showRegisterSuccess || showForgotSuccess) && redirectSeconds === 0) { setShowRegisterSuccess(false); setShowForgotSuccess(false); setActiveTab("login"); setRedirectSeconds(5); if (redirectTimer.current) clearTimeout(redirectTimer.current); } }, [showRegisterSuccess, showForgotSuccess, redirectSeconds]); useEffect(() => { if (!(showRegisterSuccess || showForgotSuccess) && redirectTimer.current) { clearInterval(redirectTimer.current); } }, [showRegisterSuccess, showForgotSuccess]); const handleForgotPassword = async (e: React.FormEvent) => { e.preventDefault(); setIsLoading(true); try { await forgotPassword({ email: forgotEmail }); toast({ title: "Email sent", description: "Check your inbox to reset your password.", }); setShowForgotSuccess(true); setRedirectSeconds(5); if (redirectTimer.current) clearTimeout(redirectTimer.current); redirectTimer.current = setInterval(() => { setRedirectSeconds((s) => s - 1); }, 1000); } catch (error: any) { let errorMessage = "Unable to send the reset password email. Please try again."; if (error?.response?.data) { if (typeof error.response.data.detail === 'string') { errorMessage = error.response.data.detail; } else if (error.response.data.detail) { errorMessage = JSON.stringify(error.response.data.detail); } } toast({ title: "Error sending email", description: errorMessage, variant: "destructive", }); } finally { setIsLoading(false); } }; return (
Evolution API
{showRegisterSuccess ? (

Registration successful!

Please check your email to confirm your account.
Redirecting to login in {redirectSeconds} seconds...

) : showForgotSuccess ? (

Email sent!

Check your inbox to reset your password.
Redirecting to login in {redirectSeconds} seconds...

) : ( Login Register Forgot
Login Enter your credentials to access the system.
setLoginData({ ...loginData, email: e.target.value }) } className="bg-[#222] border-[#444] text-white" />
setLoginData({ ...loginData, password: e.target.value }) } className="bg-[#222] border-[#444] text-white" />
{loginError && (
{isEmailNotVerified ? (
{loginError}
) : ( loginError )}
)}
Register Create a new account to get started.
setRegisterData({ ...registerData, name: e.target.value }) } className="bg-[#222] border-[#444] text-white" />
setRegisterData({ ...registerData, email: e.target.value, }) } className="bg-[#222] border-[#444] text-white" />
setRegisterData({ ...registerData, password: e.target.value, }) } className="bg-[#222] border-[#444] text-white" />
setRegisterData({ ...registerData, confirmPassword: e.target.value, }) } className="bg-[#222] border-[#444] text-white" />
Forgot Password Enter your email to receive a password reset link.
setForgotEmail(e.target.value)} className="bg-[#222] border-[#444] text-white" />
)}

By using this service, you agree to our{" "} Terms of Service {" "} e{" "} Privacy Policy .

); }