Auto-deploy: 2026-01-13 13:47:12 | 1 arquivo(s) alterado(s)
This commit is contained in:
parent
357e07063c
commit
3c54f529ce
|
|
@ -23,9 +23,12 @@ export const LoginView = () => {
|
|||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [step, setStep] = useState(1); // 1: Login, 2: Verification (Visual Demo)
|
||||
const [step, setStep] = useState(1); // 1: Login, 2: OTP
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [otp, setOtp] = useState(['', '', '', '', '', '']);
|
||||
const otpRefs = React.useRef([]);
|
||||
|
||||
const handleLogin = async (e) => {
|
||||
e.preventDefault();
|
||||
setIsLoading(true);
|
||||
|
|
@ -37,7 +40,7 @@ export const LoginView = () => {
|
|||
setTimeout(() => {
|
||||
if (allowedPasswords.includes(password)) {
|
||||
sessionStorage.setItem('workspace_access', 'granted');
|
||||
setStep(2); // Muda para o passo de verificação visual
|
||||
setStep(2);
|
||||
setIsLoading(false);
|
||||
} else {
|
||||
setError('Chave de acesso inválida ou expirada.');
|
||||
|
|
@ -46,6 +49,30 @@ export const LoginView = () => {
|
|||
}, 800);
|
||||
};
|
||||
|
||||
const handleOtpChange = (index, value) => {
|
||||
if (!/^\d*$/.test(value)) return;
|
||||
|
||||
const newOtp = [...otp];
|
||||
newOtp[index] = value.slice(-1);
|
||||
setOtp(newOtp);
|
||||
|
||||
// Auto focus next
|
||||
if (value && index < 5) {
|
||||
otpRefs.current[index + 1]?.focus();
|
||||
}
|
||||
|
||||
// Auto submit if full
|
||||
if (newOtp.every(digit => digit !== '')) {
|
||||
setTimeout(() => handleFinalize(), 600);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (index, e) => {
|
||||
if (e.key === 'Backspace' && !otp[index] && index > 0) {
|
||||
otpRefs.current[index - 1]?.focus();
|
||||
}
|
||||
};
|
||||
|
||||
const handleFinalize = () => {
|
||||
navigate('/plataforma/workspace');
|
||||
window.location.reload();
|
||||
|
|
@ -95,7 +122,7 @@ export const LoginView = () => {
|
|||
</div>
|
||||
|
||||
{/* Right Panel - Interactive Form */}
|
||||
<div className="flex-[0.8] flex items-center justify-center p-8 bg-[#0a0a0a] relative overflow-hidden">
|
||||
<div className="flex-[0.8] flex items-center justify-center p-8 bg-[var(--workspace-sec-5-dark)] relative overflow-hidden">
|
||||
{/* Decorative Grid */}
|
||||
<div className="absolute inset-0 opacity-[0.02] pointer-events-none"
|
||||
style={{ backgroundImage: 'radial-gradient(#fff 1px, transparent 0)', backgroundSize: '40px 40px' }}
|
||||
|
|
@ -186,33 +213,36 @@ export const LoginView = () => {
|
|||
</div>
|
||||
</motion.div>
|
||||
) : (
|
||||
/* Verification Step (Image 1 reference) */
|
||||
/* Step 2 - Digite o Código (Reference Image 1 style) */
|
||||
<motion.div
|
||||
key="step2"
|
||||
initial={{ opacity: 0, scale: 0.9 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
className="bg-[#0f1d2b] border border-[#22bb6c]/30 p-12 rounded-[40px] shadow-2xl shadow-emerald-950/40 flex flex-col items-center text-center max-w-[480px] w-full"
|
||||
className="bg-[#002137] p-16 rounded-[60px] shadow-2xl flex flex-col items-center text-center max-w-[600px] w-full border border-white/5"
|
||||
>
|
||||
<div className="w-20 h-20 bg-gradient-to-br from-[#22bb6c] to-[#22c0a3] rounded-3xl flex items-center justify-center mb-8 shadow-lg shadow-emerald-500/30">
|
||||
<ShieldCheck size={42} className="text-[#050505]" />
|
||||
</div>
|
||||
<h2 className="text-3xl font-black text-white italic tracking-tighter mb-4 uppercase">Chave Confirmada</h2>
|
||||
<p className="text-white/50 text-sm font-medium mb-12">O ambiente de teste do Workspace está liberado para o seu perfil administrativo.</p>
|
||||
<h2 className="text-5xl font-extrabold text-white tracking-tight mb-12">Digite o Código</h2>
|
||||
|
||||
{/* Decorative numeric placeholders (Image 1 style) */}
|
||||
<div className="flex gap-3 mb-12">
|
||||
{[1,2,3,4,5,6].map(i => (
|
||||
<div key={i} className="w-12 h-16 bg-white/5 border border-white/10 rounded-2xl flex items-center justify-center">
|
||||
<div className="w-2 h-2 bg-[#22bb6c] rounded-full animate-pulse" />
|
||||
</div>
|
||||
<div className="flex gap-4 mb-12">
|
||||
{otp.map((digit, i) => (
|
||||
<input
|
||||
key={i}
|
||||
ref={el => otpRefs.current[i] = el}
|
||||
type="text"
|
||||
maxLength={1}
|
||||
value={digit}
|
||||
onChange={(e) => handleOtpChange(i, e.target.value)}
|
||||
onKeyDown={(e) => handleKeyDown(i, e)}
|
||||
autoFocus={i === 0}
|
||||
className="w-16 h-20 bg-white rounded-[20px] text-[#002137] text-4xl font-black text-center outline-none focus:ring-4 focus:ring-[#22bb6c]/50 transition-all shadow-lg"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={handleFinalize}
|
||||
className="w-full bg-white text-[#050505] rounded-[20px] py-4 font-black uppercase tracking-widest hover:bg-[#22bb6c] hover:text-white transition-all shadow-xl"
|
||||
className="px-12 py-4 bg-white text-[#002137] rounded-2xl font-black text-xl hover:bg-[#22bb6c] hover:text-white transition-all shadow-xl hover:scale-105 active:scale-95"
|
||||
>
|
||||
Entrar no Sistema
|
||||
Enviar
|
||||
</button>
|
||||
</motion.div>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Reference in New Issue