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 [showPassword, setShowPassword] = useState(false);
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
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 navigate = useNavigate();
|
||||||
|
|
||||||
|
const [otp, setOtp] = useState(['', '', '', '', '', '']);
|
||||||
|
const otpRefs = React.useRef([]);
|
||||||
|
|
||||||
const handleLogin = async (e) => {
|
const handleLogin = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
@ -37,7 +40,7 @@ export const LoginView = () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (allowedPasswords.includes(password)) {
|
if (allowedPasswords.includes(password)) {
|
||||||
sessionStorage.setItem('workspace_access', 'granted');
|
sessionStorage.setItem('workspace_access', 'granted');
|
||||||
setStep(2); // Muda para o passo de verificação visual
|
setStep(2);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
} else {
|
} else {
|
||||||
setError('Chave de acesso inválida ou expirada.');
|
setError('Chave de acesso inválida ou expirada.');
|
||||||
|
|
@ -46,6 +49,30 @@ export const LoginView = () => {
|
||||||
}, 800);
|
}, 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 = () => {
|
const handleFinalize = () => {
|
||||||
navigate('/plataforma/workspace');
|
navigate('/plataforma/workspace');
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
|
|
@ -95,7 +122,7 @@ export const LoginView = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right Panel - Interactive Form */}
|
{/* 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 */}
|
{/* Decorative Grid */}
|
||||||
<div className="absolute inset-0 opacity-[0.02] pointer-events-none"
|
<div className="absolute inset-0 opacity-[0.02] pointer-events-none"
|
||||||
style={{ backgroundImage: 'radial-gradient(#fff 1px, transparent 0)', backgroundSize: '40px 40px' }}
|
style={{ backgroundImage: 'radial-gradient(#fff 1px, transparent 0)', backgroundSize: '40px 40px' }}
|
||||||
|
|
@ -186,33 +213,36 @@ export const LoginView = () => {
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
) : (
|
) : (
|
||||||
/* Verification Step (Image 1 reference) */
|
/* Step 2 - Digite o Código (Reference Image 1 style) */
|
||||||
<motion.div
|
<motion.div
|
||||||
key="step2"
|
key="step2"
|
||||||
initial={{ opacity: 0, scale: 0.9 }}
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
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">
|
<h2 className="text-5xl font-extrabold text-white tracking-tight mb-12">Digite o Código</h2>
|
||||||
<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>
|
|
||||||
|
|
||||||
{/* Decorative numeric placeholders (Image 1 style) */}
|
<div className="flex gap-4 mb-12">
|
||||||
<div className="flex gap-3 mb-12">
|
{otp.map((digit, i) => (
|
||||||
{[1,2,3,4,5,6].map(i => (
|
<input
|
||||||
<div key={i} className="w-12 h-16 bg-white/5 border border-white/10 rounded-2xl flex items-center justify-center">
|
key={i}
|
||||||
<div className="w-2 h-2 bg-[#22bb6c] rounded-full animate-pulse" />
|
ref={el => otpRefs.current[i] = el}
|
||||||
</div>
|
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>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={handleFinalize}
|
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>
|
</button>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue