earwigmoth's picture
sign up
67eb5fb verified
Raw
History Blame Contribute Delete
7.43 kB
/* ============================================================
SpeakFlow AI – signup.js
============================================================ */
'use strict';
// Redirect if already logged in
(function(){
const s = JSON.parse(localStorage.getItem('sf_session')||'null');
if(s && s.loggedIn) window.location.href = 'index.html';
})();
/* ── Particles ─────────────────────────────────────────────── */
(function(){
const c = document.getElementById('authParticles');
for(let i=0;i<20;i++){
const p=document.createElement('div');p.className='particle';
const sz=Math.random()*5+2;
Object.assign(p.style,{width:sz+'px',height:sz+'px',left:Math.random()*100+'%',bottom:'-10px',animationDuration:(Math.random()*20+15)+'s',animationDelay:(Math.random()*10)+'s',opacity:Math.random()*.4+.1});
c.appendChild(p);
}
})();
/* ── DOM refs ──────────────────────────────────────────────── */
const form = document.getElementById('signupForm');
const nameInp = document.getElementById('signupName');
const emailInp = document.getElementById('signupEmail');
const passInp = document.getElementById('signupPass');
const confirmInp = document.getElementById('signupConfirm');
const nameErr = document.getElementById('nameErr');
const emailErr = document.getElementById('emailErr');
const passErr = document.getElementById('passErr');
const confirmErr = document.getElementById('confirmErr');
const globalErr = document.getElementById('globalErr');
const globalOk = document.getElementById('globalSuccess');
const btnText = document.getElementById('signupBtnText');
const btnLoader = document.getElementById('signupBtnLoader');
const strengthFill = document.getElementById('strengthFill');
const strengthLabel = document.getElementById('strengthLabel');
/* ── Show/Hide Password ────────────────────────────────────── */
function toggleVis(inputEl, btn){
btn.addEventListener('click',()=>{
const show = inputEl.type==='password';
inputEl.type = show?'text':'password';
btn.querySelector('i').className = show?'fas fa-eye-slash':'fas fa-eye';
});
}
toggleVis(passInp, document.getElementById('togglePass1'));
toggleVis(confirmInp, document.getElementById('togglePass2'));
/* ── Password Strength ─────────────────────────────────────── */
passInp.addEventListener('input',()=>{
const v = passInp.value;
let score = 0;
if(v.length>=8) score++;
if(/[A-Z]/.test(v)) score++;
if(/[0-9]/.test(v)) score++;
if(/[^A-Za-z0-9]/.test(v)) score++;
const levels = [
{pct:0, color:'transparent', label:'Enter password'},
{pct:25, color:'#EF4444', label:'Weak'},
{pct:50, color:'#F59E0B', label:'Fair'},
{pct:75, color:'#3B82F6', label:'Good'},
{pct:100, color:'#10B981', label:'Strong'},
];
const l = v.length===0 ? levels[0] : levels[Math.max(1,score)];
strengthFill.style.width = l.pct+'%';
strengthFill.style.background = l.color;
strengthLabel.textContent = l.label;
strengthLabel.style.color = l.color;
});
/* ── Validation helpers ────────────────────────────────────── */
function setErr(el,fgId,msg){
el.textContent=msg;
const fg=document.getElementById(fgId);
fg.classList.add('has-error');fg.classList.remove('has-ok');
}
function setOk(el,fgId){
el.textContent='';
const fg=document.getElementById(fgId);
fg.classList.remove('has-error');fg.classList.add('has-ok');
}
function clearState(el,fgId){
el.textContent='';
const fg=document.getElementById(fgId);
fg.classList.remove('has-error','has-ok');
}
function validateEmail(e){return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e);}
/* ── Submit ────────────────────────────────────────────────── */
form.addEventListener('submit',function(e){
e.preventDefault();
globalErr.textContent=''; globalOk.style.display='none';
let valid=true;
const name = nameInp.value.trim();
const email = emailInp.value.trim().toLowerCase();
const pass = passInp.value;
const confirm = confirmInp.value;
// Name
if(!name){setErr(nameErr,'fg-name','Full name is required.');valid=false;}
else if(name.length<2){setErr(nameErr,'fg-name','Name must be at least 2 characters.');valid=false;}
else setOk(nameErr,'fg-name');
// Email
if(!email){setErr(emailErr,'fg-email','Email is required.');valid=false;}
else if(!validateEmail(email)){setErr(emailErr,'fg-email','Enter a valid email address.');valid=false;}
else setOk(emailErr,'fg-email');
// Password
if(!pass){setErr(passErr,'fg-pass','Password is required.');valid=false;}
else if(pass.length<6){setErr(passErr,'fg-pass','Password must be at least 6 characters.');valid=false;}
else setOk(passErr,'fg-pass');
// Confirm
if(!confirm){setErr(confirmErr,'fg-confirm','Please confirm your password.');valid=false;}
else if(confirm!==pass){setErr(confirmErr,'fg-confirm','Passwords do not match.');valid=false;}
else setOk(confirmErr,'fg-confirm');
if(!valid) return;
// Prevent admin email
if(email==='admin@speakflow.ai'){globalErr.textContent='❌ This email is reserved.';return;}
// Check duplicate
const users = JSON.parse(localStorage.getItem('sf_users')||'[]');
if(users.find(u=>u.email===email)){globalErr.textContent='❌ An account with this email already exists.';return;}
// Show loader
btnText.style.display='none'; btnLoader.style.display='flex';
setTimeout(()=>{
const newUser = {
id: 'usr_'+Date.now(),
name, email, password:pass,
createdAt: new Date().toISOString()
};
users.push(newUser);
localStorage.setItem('sf_users',JSON.stringify(users));
// Auto-login after signup
const session = {loggedIn:true, name, email, id:newUser.id};
localStorage.setItem('sf_session',JSON.stringify(session));
globalOk.textContent='βœ… Account created! Redirecting...';
globalOk.style.display='block';
btnText.style.display='flex'; btnLoader.style.display='none';
setTimeout(()=>{ window.location.href='index.html'; },1000);
},900);
});
/* ── Live validation on blur ───────────────────────────────── */
nameInp.addEventListener('blur',()=>{ if(!nameInp.value.trim()) setErr(nameErr,'fg-name','Full name is required.'); });
emailInp.addEventListener('blur',()=>{
const v=emailInp.value.trim();
if(!v) setErr(emailErr,'fg-email','Email is required.');
else if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)) setErr(emailErr,'fg-email','Enter a valid email address.');
});
passInp.addEventListener('blur',()=>{ if(!passInp.value) setErr(passErr,'fg-pass','Password is required.'); });
confirmInp.addEventListener('blur',()=>{
if(confirmInp.value && confirmInp.value!==passInp.value) setErr(confirmErr,'fg-confirm','Passwords do not match.');
else if(!confirmInp.value) setErr(confirmErr,'fg-confirm','Please confirm your password.');
});