AgentIQ_Frontend/src/pages/login-page.tsx
SanaullasAzaan ab3bf2038b feat: improve responsiveness and refactor auth components
- Fix responsiveness at md (768px) and lg (1024px) breakpoints across all pages
- Reduce forgot-password-modal.tsx from 472 to 319 lines by extracting components
- Extract OTPInput and modal icons into separate files for better code organization
- Optimize card sizes and text scaling for lg (1024px) breakpoint
- Adjust login page layout: smaller card and reduced text sizes at lg breakpoint
- Improve responsive typography, spacing, and touch targets across all components
- Update all pages (login, sign-up, dashboard) with proper mobile-first responsive design
2025-12-24 11:02:55 +05:30

230 lines
8.4 KiB
TypeScript

/**
* Login Page Component
* @description Main authentication page with 2-column responsive layout.
* Left column displays branding/marketing content, right column contains auth form.
* Supports both Sign In and Register modes with animated transitions.
* Includes Forgot Password modal with OTP verification.
* Follows AgenticIQ Enterprise Coding Guidelines v1.0
*/
import { useState } from 'react';
import agenticiqLogo from '@/assets/images/logo/AgenticIQLogo.svg';
import topRightGlow from '@/assets/images/backgrounds/top-right-glow.svg';
import bottomLeftWave1 from '@/assets/images/backgrounds/bottom-left-wave1.svg';
import bottomLeftWave2 from '@/assets/images/backgrounds/bottom-left-wave2.svg';
import logoGlowBg from '@/assets/images/backgrounds/logo-glow-bg.svg';
import { AuthFormCard, ForgotPasswordModal } from '@/components/auth';
/**
* Register form data interface
*/
interface RegisterFormData {
firstName: string;
lastName: string;
email: string;
password: string;
}
/**
* LoginPage component
* @description Full-page login layout with responsive 2-column grid structure.
* Mobile-first design that stacks columns on smaller screens.
* @returns {JSX.Element} LoginPage element
*/
export function LoginPage(): JSX.Element {
const [showForgotPwd, setShowForgotPwd] = useState(false);
/**
* Handle sign in form submission
* @param {string} email - User email address
* @param {string} password - User password
*/
const handleSignIn = (email: string, password: string): void => {
// TODO(AUTH-001): Implement actual sign in API call
void Promise.resolve({ email, password });
};
/**
* Handle register form submission
* @param {RegisterFormData} data - Registration form data
*/
const handleRegister = (data: RegisterFormData): void => {
// TODO(AUTH-002): Implement actual registration API call
void Promise.resolve(data);
};
/**
* Handle Google OAuth authentication
*/
const handleGoogleAuth = (): void => {
// TODO(AUTH-003): Implement Google OAuth flow
};
/**
* Handle Azure OAuth authentication
*/
const handleAzureAuth = (): void => {
// TODO(AUTH-004): Implement Azure OAuth flow
};
/**
* Open forgot password modal
*/
const handleForgotPasswordClick = (): void => {
setShowForgotPwd(true);
};
/**
* Close forgot password modal
*/
const handleForgotPasswordClose = (): void => {
setShowForgotPwd(false);
};
/**
* Handle forgot password email submission
* @param {string} email - Email for password recovery
*/
const handleForgotPasswordSubmit = (email: string): void => {
// TODO(AUTH-005): Implement password recovery API call
void Promise.resolve(email);
};
/**
* Handle OTP verification submission
* @param {string} otp - 6-digit OTP code
*/
const handleOtpVerify = (otp: string): void => {
// TODO(AUTH-006): Implement OTP verification API call
void Promise.resolve(otp);
};
return (
<div className="login-page">
<div className="relative min-h-screen w-full overflow-hidden bg-white">
{/* Decorative Background Elements */}
<BackgroundDecorations />
{/* AgenticIQ Logo */}
<div className="absolute left-4 top-4 md:left-8 lg:left-12 xl:left-[80px] md:top-8 lg:top-8 xl:top-[54px] z-20">
<img
src={agenticiqLogo}
alt="AgenticIQ Logo"
className="h-16 w-auto md:h-24 lg:h-20 xl:h-[117px]"
/>
</div>
{/* Left Side Text Content */}
<LeftColumnText />
{/* Main Content Grid */}
<div className="relative z-10 grid min-h-screen grid-cols-1 md:grid-cols-1 lg:grid-cols-[1fr_480px] xl:grid-cols-[1fr_600px] 2xl:grid-cols-[1fr_620px]">
{/* Left Column - Branding/Marketing Content */}
<LeftColumn />
{/* Right Column - Auth Form Card */}
<div className="flex items-center justify-center md:justify-center lg:justify-start px-4 py-8 md:px-6 md:py-12 lg:px-4 lg:py-12 xl:px-0 xl:py-16">
<AuthFormCard
initialMode="signin"
onSignIn={handleSignIn}
onRegister={handleRegister}
onGoogleAuth={handleGoogleAuth}
onAzureAuth={handleAzureAuth}
onForgotPassword={handleForgotPasswordClick}
/>
</div>
</div>
</div>
{/* Forgot Password Modal */}
<ForgotPasswordModal
isOpen={showForgotPwd}
onClose={handleForgotPasswordClose}
onSubmit={handleForgotPasswordSubmit}
onVerify={handleOtpVerify}
/>
</div>
);
}
/**
* BackgroundDecorations component
* @description Renders decorative background images matching Figma design.
* All images are purely decorative and hidden from screen readers.
* @returns {JSX.Element} Background decoration elements
*/
function BackgroundDecorations(): JSX.Element {
return (
<div className="pointer-events-none absolute inset-0 z-0" aria-hidden="true">
{/* Logo glow background */}
<img
src={logoGlowBg}
alt=""
className="absolute left-0 top-0 h-auto w-auto opacity-[0.08] hidden md:block"
style={{ width: '550px', height: 'auto', maxHeight: '350px' }}
/>
{/* Top-right glow decoration */}
<img
src={topRightGlow}
alt=""
className="absolute right-0 top-0 h-auto w-auto opacity-[0.15] hidden md:block"
style={{ width: '515px', height: 'auto', maxHeight: '614px' }}
/>
{/* Bottom-left wave decoration 1 */}
<img
src={bottomLeftWave1}
alt=""
className="absolute bottom-0 left-0 h-auto w-auto opacity-[0.15] hidden md:block"
style={{ width: '559px', height: 'auto', maxHeight: '613px' }}
/>
{/* Bottom-left wave decoration 2 */}
<img
src={bottomLeftWave2}
alt=""
className="absolute bottom-0 left-0 h-auto w-auto opacity-[0.15] hidden md:block"
style={{ width: '350px', height: 'auto', maxHeight: '500px' }}
/>
</div>
);
}
/**
* LeftColumnText component
* @description Left side text content with heading and description.
* Positioned absolutely to match Figma design specifications.
* @returns {JSX.Element} Text elements positioned as per Figma
*/
function LeftColumnText(): JSX.Element {
return (
<>
<h1
className="hidden lg:block absolute text-2xl md:text-3xl lg:text-2xl xl:text-[36px] font-semibold text-black leading-tight lg:leading-tight xl:leading-normal whitespace-pre-wrap z-20 lg:left-12 lg:top-64 lg:w-80 xl:left-[110px] xl:top-[348px] xl:w-[513px]"
>
Engineering the Future with Intelligent Agents
</h1>
<p
className="hidden lg:block absolute text-sm md:text-base lg:text-sm xl:text-[24px] font-normal text-[rgba(0,0,0,0.75)] leading-relaxed lg:leading-relaxed xl:leading-normal whitespace-pre-wrap z-20 lg:left-12 lg:top-96 lg:w-80 xl:left-[110px] xl:top-[482px] xl:w-[607px]"
>
Deploy intelligent agents that automate complex workflows, enhance decision-making, and scale your operations. Built for enterprise reliability with seamless integration capabilities.
</p>
</>
);
}
/**
* LeftColumn component
* @description Empty container for left side content in the grid layout.
* Text content is positioned absolutely on the page level for precise control.
* @returns {JSX.Element} Left column container
*/
function LeftColumn(): JSX.Element {
return (
<div className="hidden md:hidden lg:flex flex-col justify-center px-6 py-12 md:px-12 lg:px-8 xl:px-20 2xl:px-28">
{/* Text content is positioned absolutely on page level */}
</div>
);
}