feat: major UI overhaul with new components and enhanced UX
- Add comprehensive Company Wiki feature with complete state management - CompanyWikiManager, empty states, invite modals - Implement new Chat system with enhanced layout and components - ChatLayout, ChatSidebar, MessageThread, FileUploadInput - Create modern Login and OTP verification flows - LoginNew page, OTPVerification component - Add new Employee Forms system with enhanced controller - Introduce Figma-based design components and multiple choice inputs - Add new font assets (NeueMontreal) and robot images for onboarding - Enhance existing components with improved styling and functionality - Update build configuration and dependencies - Remove deprecated ModernLogin component
This commit is contained in:
122
pages/OTPVerification.tsx
Normal file
122
pages/OTPVerification.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
|
||||
const OTPVerification: React.FC = () => {
|
||||
const [otp, setOtp] = useState(['', '', '', '', '', '']);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { verifyOTP } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
const email = location.state?.email || '';
|
||||
|
||||
const handleOtpChange = (index: number, value: string) => {
|
||||
if (value.length <= 1) {
|
||||
const newOtp = [...otp];
|
||||
newOtp[index] = value;
|
||||
setOtp(newOtp);
|
||||
|
||||
// Auto-focus next input
|
||||
if (value && index < 5) {
|
||||
const nextInput = document.getElementById(`otp-${index + 1}`);
|
||||
nextInput?.focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (index: number, e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Backspace' && !otp[index] && index > 0) {
|
||||
const prevInput = document.getElementById(`otp-${index - 1}`);
|
||||
prevInput?.focus();
|
||||
}
|
||||
};
|
||||
|
||||
const handleVerify = async () => {
|
||||
const otpCode = otp.join('');
|
||||
if (otpCode.length !== 6) return;
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
await verifyOTP(email, otpCode);
|
||||
navigate('/company-wiki');
|
||||
} catch (error) {
|
||||
console.error('OTP verification failed:', error);
|
||||
// Reset OTP on error
|
||||
setOtp(['', '', '', '', '', '']);
|
||||
document.getElementById('otp-0')?.focus();
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-[1440px] h-[810px] bg-Neutrals-NeutralSlate0 inline-flex justify-start items-end overflow-hidden">
|
||||
<div className="flex-1 self-stretch px-32 py-48 flex justify-center items-center gap-2.5 overflow-hidden">
|
||||
<div className="flex-1 max-w-[464px] inline-flex flex-col justify-start items-start gap-6">
|
||||
<div className="w-12 h-12 relative bg-Brand-Orange rounded-xl outline outline-2 outline-offset-[-2px] outline-blue-400 overflow-hidden">
|
||||
<div className="w-12 h-12 left-0 top-0 absolute bg-gradient-to-b from-white/0 to-white/10" />
|
||||
<div className="left-[12px] top-[9.33px] absolute">
|
||||
<svg width="24" height="30" viewBox="0 0 24 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.5" fillRule="evenodd" clipRule="evenodd" d="M2.57425 17.8128C3.11852 18.3639 3.11851 19.2575 2.57423 19.8087L2.54635 19.8369C2.00207 20.3881 1.11963 20.3881 0.575357 19.8369C0.0310869 19.2857 0.0310953 18.3921 0.575376 17.841L0.603251 17.8128C1.14753 17.2616 2.02998 17.2616 2.57425 17.8128Z" fill="url(#paint0_linear_710_14140)" />
|
||||
<path opacity="0.7" fillRule="evenodd" clipRule="evenodd" d="M9.12599 18.2379C9.66928 18.7901 9.66769 19.6837 9.12243 20.2338L5.26187 24.1291C4.71661 24.6792 3.83416 24.6776 3.29087 24.1255C2.74758 23.5733 2.74918 22.6797 3.29444 22.1296L7.155 18.2343C7.70026 17.6842 8.5827 17.6858 9.12599 18.2379Z" fill="url(#paint1_linear_710_14140)" />
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_710_14140" x1="1.5748" y1="17.3994" x2="1.5748" y2="20.2503" gradientUnits="userSpaceOnUse">
|
||||
<stop stopColor="white" stopOpacity="0.8" />
|
||||
<stop offset="1" stopColor="white" stopOpacity="0.5" />
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_710_14140" x1="6.20843" y1="17.8228" x2="6.20843" y2="24.5406" gradientUnits="userSpaceOnUse">
|
||||
<stop stopColor="white" stopOpacity="0.8" />
|
||||
<stop offset="1" stopColor="white" stopOpacity="0.5" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div className="self-stretch flex flex-col justify-start items-start gap-3">
|
||||
<div className="self-stretch justify-start text-Neutrals-NeutralSlate950 text-2xl font-semibold font-['Inter'] leading-8">Verify your email</div>
|
||||
<div className="self-stretch justify-start text-Neutrals-NeutralSlate500 text-base font-normal font-['Inter'] leading-normal">
|
||||
Enter the 6-digit code sent to {email}
|
||||
</div>
|
||||
</div>
|
||||
<div className="self-stretch flex flex-col justify-start items-start gap-4">
|
||||
<div className="self-stretch flex flex-col justify-start items-start gap-2">
|
||||
<div className="self-stretch inline-flex justify-start items-center gap-0.5">
|
||||
<div className="justify-start text-Neutrals-NeutralSlate900 text-sm font-normal font-['Inter'] leading-tight">Verification Code</div>
|
||||
<div className="justify-start text-Brand-Orange text-sm font-medium font-['Inter'] leading-tight">*</div>
|
||||
</div>
|
||||
<div className="self-stretch flex justify-center items-center gap-3">
|
||||
{otp.map((digit, index) => (
|
||||
<input
|
||||
key={index}
|
||||
id={`otp-${index}`}
|
||||
type="text"
|
||||
value={digit}
|
||||
onChange={(e) => handleOtpChange(index, e.target.value)}
|
||||
onKeyDown={(e) => handleKeyDown(index, e)}
|
||||
className="w-12 h-12 bg-Neutrals-NeutralSlate100 rounded-xl text-center text-Neutrals-NeutralSlate950 text-lg font-semibold font-['Inter'] outline-none focus:bg-Neutrals-NeutralSlate200 focus:outline-2 focus:outline-Brand-Orange"
|
||||
maxLength={1}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleVerify}
|
||||
disabled={otp.join('').length !== 6 || isLoading}
|
||||
className="self-stretch px-6 py-3.5 bg-Brand-Orange rounded-[999px] inline-flex justify-center items-center gap-2 overflow-hidden disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<div className="justify-center text-Neutrals-NeutralSlate0 text-base font-medium font-['Inter'] leading-normal">
|
||||
{isLoading ? 'Verifying...' : 'Verify Code'}
|
||||
</div>
|
||||
</button>
|
||||
<div className="self-stretch text-center text-Neutrals-NeutralSlate500 text-sm font-normal font-['Inter'] leading-tight">
|
||||
Didn't receive the code? <button className="text-Brand-Orange font-medium">Resend</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OTPVerification;
|
||||
Reference in New Issue
Block a user