/* ============================================================ Cadastro (Signup) page — full validation + persistence ============================================================ */ function CadastroPage() { const { signup, currentUser } = useAuth(); const { params } = useHashRoute(); const nextPath = params.next ? decodeURIComponent(params.next) : '/dashboard'; const isGated = !!params.next; const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [phone, setPhone] = useState(''); const [accept, setAccept] = useState(false); const [news, setNews] = useState(true); const [touched, setTouched] = useState({}); const [submitted, setSubmitted] = useState(false); const [serverError, setServerError] = useState(null); const [success, setSuccess] = useState(false); useEffect(() => { if (currentUser && !success) { // already logged in nav(nextPath); } }, [currentUser, success]); const errors = { name: !isValidFullName(name) ? 'Informe seu nome completo (nome e sobrenome).' : null, email: !isValidEmail(email) ? 'E-mail inválido.' : null, phone: !isValidPhoneBR(phone) ? 'Celular deve estar no formato (DD) NNNNN-NNNN.' : null, accept: !accept ? 'É necessário aceitar os termos.' : null, }; const hasErrors = Object.values(errors).some(Boolean); const onSubmit = (e) => { e.preventDefault(); setSubmitted(true); setServerError(null); if (hasErrors) return; const r = signup({ name: name.trim(), email: email.trim(), phone, news }); if (!r.ok) { setServerError(r.error); return; } setSuccess(true); setTimeout(() => nav(nextPath), 1400); }; const show = (field) => (submitted || touched[field]) && errors[field]; if (success) { return (
Cadastro realizado. Você será redirecionado em instantes.
Ir para o painel agora
); } return (
Início Cadastro

Criar conta

Acesso integral aos conteúdos, vídeo-aulas e ferramentas analíticas. Sem cobrança, sem cartão de crédito.

{isGated && (
Conteúdo exclusivo a membros. Crie sua conta gratuita para continuar.
)} {serverError && (
Não foi possível concluir o cadastro. {serverError}
)}
setName(e.target.value)} onBlur={() => setTouched(t => ({...t, name: true}))} placeholder="Maria de Souza Lima" autoComplete="name" /> {show('name') &&
{errors.name}
}
setEmail(e.target.value)} onBlur={() => setTouched(t => ({...t, email: true}))} placeholder="maria.lima@exemplo.com.br" autoComplete="email" /> {show('email') &&
{errors.email}
}
setPhone(maskPhoneBR(e.target.value))} onBlur={() => setTouched(t => ({...t, phone: true}))} placeholder="(11) 98765-4321" inputMode="tel" autoComplete="tel-national" maxLength={16} /> {show('phone') ? (
{errors.phone}
) : (
Formato (DD) NNNNN-NNNN. Usaremos apenas para comunicação institucional.
)}
{show('accept') &&
{errors.accept}
}

Já tem uma conta? Entrar

); } /* ============================================================ Login ============================================================ */ function LoginPage() { const { login, currentUser } = useAuth(); const { params } = useHashRoute(); const nextPath = params.next ? decodeURIComponent(params.next) : '/dashboard'; const isGated = !!params.next; const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [submitted, setSubmitted] = useState(false); const [serverError, setServerError] = useState(null); useEffect(() => { if (currentUser) nav(nextPath); }, [currentUser]); const onSubmit = (e) => { e.preventDefault(); setSubmitted(true); setServerError(null); if (!isValidEmail(email)) return; const r = login(email, password); if (!r.ok) { setServerError(r.error); return; } nav(nextPath); }; const cadastroHref = '/cadastro' + (isGated ? '?next=' + encodeURIComponent(nextPath) : ''); return (
Início Entrar

Entrar na sua conta

Use o e-mail cadastrado para acessar seu painel.

{isGated && (
Conteúdo exclusivo a membros. Entre na sua conta ou{' '} cadastre-se gratuitamente{' '} para continuar.
)} {serverError && (
Erro de autenticação. {serverError}
)}
setEmail(e.target.value)} autoComplete="email" /> {submitted && !isValidEmail(email) &&
E-mail inválido.
}
setPassword(e.target.value)} autoComplete="current-password" />
Protótipo: a senha não é verificada — basta usar o e-mail cadastrado.

Ainda não tem conta? Criar conta gratuita

); } window.CadastroPage = CadastroPage; window.LoginPage = LoginPage;