modcomms/frontend/components/Login.tsx
2025-12-18 16:51:27 +00:00

189 lines
9.5 KiB
TypeScript
Executable file

import React, { useState } from 'react';
import { useMsal } from '@azure/msal-react';
import { BarclaysLogo } from './icons/BarclaysLogo';
import { XIcon } from './icons/XIcon';
import { MicrosoftLogo } from './icons/MicrosoftLogo';
import { loginRequest } from '../services/authConfig';
const SupportModal: React.FC<{
isOpen: boolean;
onClose: () => void;
onSubmit: (query: string) => void;
}> = ({ isOpen, onClose, onSubmit }) => {
if (!isOpen) return null;
const [query, setQuery] = useState('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (query.trim()) {
onSubmit(query);
}
};
return (
<div
className="fixed inset-0 bg-black bg-opacity-60 flex items-center justify-center z-50 transition-opacity duration-300"
onClick={onClose}
>
<div
className="bg-white rounded-lg shadow-xl p-6 sm:p-8 w-full max-w-lg transform transition-all"
onClick={(e) => e.stopPropagation()}
>
<div className="flex justify-between items-start mb-4">
<h3 className="text-xl font-bold text-brand-dark-blue">Contact Support</h3>
<button onClick={onClose} className="-mt-2 -mr-2 p-2 rounded-full hover:bg-gray-200 transition-colors">
<XIcon className="h-6 w-6 text-gray-600" />
</button>
</div>
<form onSubmit={handleSubmit}>
<p className="text-gray-600 mb-4">Please describe your issue or query below. A member of our team will be in touch shortly.</p>
<textarea
value={query}
onChange={(e) => setQuery(e.target.value)}
className="w-full p-3 border border-gray-300 rounded-md focus:ring-2 focus:ring-brand-accent focus:border-brand-accent transition"
rows={5}
placeholder="Type your message here..."
required
/>
<div className="mt-6 flex justify-end gap-3">
<button
type="button"
onClick={onClose}
className="bg-gray-200 text-gray-800 font-semibold py-2 px-4 rounded-md hover:bg-gray-300 transition-colors duration-300"
>
Cancel
</button>
<button
type="submit"
className="bg-brand-accent text-white font-semibold py-2 px-4 rounded-md hover:bg-brand-dark-blue transition-colors duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed"
disabled={!query.trim()}
>
Submit Query
</button>
</div>
</form>
</div>
</div>
);
};
export const Login: React.FC = () => {
const { instance } = useMsal();
const [isSupportModalOpen, setIsSupportModalOpen] = useState(false);
const [isLoggingIn, setIsLoggingIn] = useState(false);
const [loginError, setLoginError] = useState<string | null>(null);
const handleSupportSubmit = (query: string) => {
console.log("Support query submitted:", query);
alert("Thank you for your query. A member of the support team will be in touch with you shortly.");
setIsSupportModalOpen(false);
};
const handleMicrosoftLogin = async () => {
setIsLoggingIn(true);
setLoginError(null);
try {
await instance.loginPopup(loginRequest);
// Success - MSAL Provider will detect the login and re-render App
} catch (error: unknown) {
console.error('Login failed:', error);
if (error instanceof Error) {
// Handle user cancellation differently from errors
if (error.message.includes('user_cancelled')) {
setLoginError(null); // Don't show error for cancellation
} else {
setLoginError('Login failed. Please try again or contact support.');
}
}
} finally {
setIsLoggingIn(false);
}
};
return (
<>
<SupportModal
isOpen={isSupportModalOpen}
onClose={() => setIsSupportModalOpen(false)}
onSubmit={handleSupportSubmit}
/>
<div className="fixed inset-0 overflow-y-auto bg-[#0f172a] flex items-center justify-center font-sans p-4">
{/* Modern Glassy Background */}
<div className="absolute inset-0 overflow-hidden pointer-events-none">
{/* Top Left Blob */}
<div className="absolute -top-[20%] -left-[10%] w-[70%] h-[70%] rounded-full bg-gradient-to-br from-brand-accent/30 to-purple-600/30 blur-[120px] animate-pulse" style={{ animationDuration: '8s' }}></div>
{/* Bottom Right Blob */}
<div className="absolute -bottom-[20%] -right-[10%] w-[70%] h-[70%] rounded-full bg-gradient-to-tl from-brand-light-blue/30 to-emerald-500/30 blur-[120px] animate-pulse" style={{ animationDuration: '10s', animationDelay: '1s' }}></div>
{/* Noise Texture */}
<div className="absolute inset-0 bg-[url('https://grainy-gradients.vercel.app/noise.svg')] opacity-20 mix-blend-soft-light"></div>
</div>
{/* Login Card */}
<div className="relative z-10 bg-white/90 backdrop-blur-xl p-8 sm:p-12 shadow-2xl rounded-3xl w-full max-w-md flex flex-col items-center text-center border border-white/50 ring-1 ring-white/50">
<div className="mb-8 transform transition-transform hover:scale-105 duration-300">
<BarclaysLogo className="h-12 w-auto text-brand-dark-blue" />
</div>
<h1 className="text-3xl font-extrabold text-brand-dark-blue mb-2 tracking-tight">Mod Comms</h1>
<p className="text-slate-500 mb-8 font-medium">Proof Review &amp; Compliance Platform</p>
<div className="w-full space-y-6">
<div className="p-5 bg-blue-50/80 rounded-xl border border-blue-100 text-left">
<p className="text-sm text-blue-900 leading-relaxed">
<span className="font-bold block mb-1 flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-blue-500 animate-pulse"></span>
Enterprise Sign-In
</span>
This application is connected to Azure Active Directory. Please sign in using your corporate Microsoft account.
</p>
</div>
{loginError && (
<div className="w-full p-3 bg-red-50 border border-red-200 rounded-lg text-red-700 text-sm">
{loginError}
</div>
)}
<button
onClick={handleMicrosoftLogin}
disabled={isLoggingIn}
className="w-full flex items-center justify-center gap-3 bg-white hover:bg-gray-50 text-slate-700 font-bold py-4 px-6 rounded-xl border border-gray-200 shadow-lg shadow-gray-200/50 hover:shadow-xl hover:border-gray-300 transition-all duration-300 group disabled:opacity-70 disabled:cursor-wait transform hover:-translate-y-0.5"
>
{isLoggingIn ? (
<svg className="animate-spin h-5 w-5 text-brand-accent" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
) : (
<>
<MicrosoftLogo className="h-5 w-5" />
<span>Sign in with Microsoft</span>
</>
)}
</button>
</div>
<div className="mt-10 pt-6 border-t border-gray-200/60 w-full">
<button
type="button"
onClick={() => setIsSupportModalOpen(true)}
className="text-sm text-slate-500 hover:text-brand-accent transition-colors font-medium"
>
Having trouble signing in? Contact Support
</button>
</div>
</div>
<footer className="absolute bottom-0 left-0 right-0 text-center p-6 z-10">
<p className="text-xs text-slate-400/80 font-medium">&copy; {new Date().getFullYear()} OLIVER Agency Mod Comms. All rights reserved.</p>
</footer>
</div>
</>
);
};