// ========================= // SUPABASE + PERSISTÊNCIA // ========================= let currentView = 'login-type' let currentUser = null let allUsers = [] let allWorkouts = [] let selectedWorkoutExercises = [] let generatedWorkoutCode = '' let currentExercisePerforming = null let currentSeriesIndex = 0 let restTimerInterval = null let customRestTime = 60 let editingUserId = null let exercicioSelecionado = null async function carregarDados() { const { data: users, error: usersError } = await supabase .from('users') .select('*') .order('created_at', { ascending: true }) const { data: workouts, error: workoutsError } = await supabase .from('workouts') .select('*') .order('created_at', { ascending: true }) if (usersError) { console.error('Erro users:', usersError) notificar('Erro ao carregar usuários', 'error') allUsers = [] } else { allUsers = users || [] } if (workoutsError) { console.error('Erro workouts:', workoutsError) notificar('Erro ao carregar treinos', 'error') allWorkouts = [] } else { allWorkouts = workouts || [] } } async function salvarDados() { await carregarDados() } function gerarCodigoTreino() { return 'FORJA-' + Math.random().toString(36).substring(2, 8).toUpperCase() } function notificar(msg, tipo = 'info') { const cores = { success: '#39FF14', error: '#ff4444', info: '#3498db' } const div = document.createElement('div') div.textContent = msg div.style.cssText = ` position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: ${cores[tipo] || cores.info}; color: #000; padding: 12px 24px; border-radius: 8px; z-index: 10000; font-weight: bold; ` document.body.appendChild(div) setTimeout(() => div.remove(), 3000) } async function solicitarResetSenha(email) { const { data: user, error } = await supabase .from('users') .select('*') .eq('email', email) .in('role', ['trainer', 'student']) .maybeSingle() if (error) { console.error(error) notificar('Erro ao buscar usuário', 'error') return false } if (!user) { notificar('E-mail não encontrado', 'error') return false } const novaSenha = Math.random().toString(36).slice(-6) const { error: updateError } = await supabase .from('users') .update({ password: novaSenha }) .eq('id', user.id) if (updateError) { console.error(updateError) notificar('Erro ao resetar senha', 'error') return false } await carregarDados() notificar(`Nova senha enviada para ${email}: ${novaSenha} (simulação)`, 'success') return true } async function buscarAlunoPorEmail(email) { const { data, error } = await supabase .from('users') .select('*') .eq('email', email) .eq('role', 'student') .maybeSingle() if (error) { console.error(error) return null } return data } async function buscarTreinoPorCodigo(codigo) { const { data, error } = await supabase .from('workouts') .select('*') .eq('workout_code', codigo) .maybeSingle() if (error) { console.error(error) return null } return data } async function vincularTreinoAoAluno(studentId, codigo) { const { error } = await supabase .from('users') .update({ workout_code: codigo }) .eq('id', studentId) if (error) { console.error(error) return false } return true } // ========================= // EVENTOS PRINCIPAIS // ========================= async function eventosClique() { document.getElementById('btnTrainer')?.addEventListener('click', () => { currentView = 'trainer-login' renderizar() }) document.getElementById('btnStudent')?.addEventListener('click', () => { currentView = 'student-login' renderizar() }) document.getElementById('btnAdmin')?.addEventListener('click', () => { currentView = 'admin-login' renderizar() }) document.getElementById('voltarLoginType')?.addEventListener('click', () => { currentView = 'login-type' renderizar() }) document.getElementById('voltarLogin')?.addEventListener('click', () => { currentView = 'login-type' renderizar() }) document.getElementById('voltarLoginTypeStudent')?.addEventListener('click', () => { currentView = 'login-type' renderizar() }) document.getElementById('voltarLoginTypeAdmin')?.addEventListener('click', () => { currentView = 'login-type' renderizar() }) document.getElementById('voltarReset')?.addEventListener('click', () => { currentView = 'trainer-login' renderizar() }) document.getElementById('voltarDashboard')?.addEventListener('click', () => { currentView = 'trainer-dashboard' renderizar() }) document.getElementById('voltarDashboardCreate')?.addEventListener('click', () => { currentView = 'trainer-dashboard' renderizar() }) document.getElementById('voltarDashboardFinal')?.addEventListener('click', () => { currentView = 'trainer-dashboard' renderizar() }) document.getElementById('voltarPerformance')?.addEventListener('click', () => { currentExercisePerforming = null currentView = 'client-dashboard' renderizar() }) document.getElementById('cancelarEdicao')?.addEventListener('click', () => { currentView = 'admin-dashboard' renderizar() }) // LOGIN ADMIN document.getElementById('fazerLoginAdmin')?.addEventListener('click', async () => { const email = document.getElementById('adminEmailLogin')?.value?.trim() const senha = document.getElementById('adminSenhaLogin')?.value?.trim() const { data: admin, error } = await supabase .from('users') .select('*') .eq('email', email) .eq('password', senha) .eq('role', 'admin') .maybeSingle() if (error) { console.error(error) notificar('Erro ao fazer login', 'error') return } if (admin) { currentUser = admin await carregarDados() currentView = 'admin-dashboard' renderizar() notificar('Login admin', 'success') } else { notificar('Credenciais inválidas', 'error') } }) // LOGIN PROFESSOR document.getElementById('fazerLoginTrainer')?.addEventListener('click', async () => { const email = document.getElementById('trainer_id')?.value?.trim() const senha = document.getElementById('trainerPassword')?.value?.trim() const { data: user, error } = await supabase .from('users') .select('*') .eq('email', email) .eq('password', senha) .eq('role', 'trainer') .maybeSingle() if (error) { console.error(error) notificar('Erro ao fazer login', 'error') return } if (!user) { notificar('Email ou senha incorretos', 'error') return } if (!user.approved) { notificar('Conta pendente de aprovação pelo admin', 'error') return } if (user.active === false) { notificar('Conta bloqueada. Contate o administrador.', 'error') return } currentUser = user await carregarDados() currentView = 'trainer-dashboard' renderizar() notificar(`Bem-vindo, ${user.name}!`, 'success') }) document.getElementById('irCadastro')?.addEventListener('click', () => { currentView = 'trainer-signup' renderizar() }) document.getElementById('esqueciSenhaTrainer')?.addEventListener('click', () => { currentView = 'forgot-password' renderizar() }) document.getElementById('esqueciSenhaStudent')?.addEventListener('click', () => { currentView = 'forgot-password' renderizar() }) document.getElementById('solicitarReset')?.addEventListener('click', async () => { const email = document.getElementById('resetEmail')?.value?.trim() if (!email) { notificar('Digite um e-mail', 'error') return } const ok = await solicitarResetSenha(email) if (ok) { currentView = 'trainer-login' renderizar() } }) // CADASTRO PROFESSOR document.getElementById('fazerCadastro')?.addEventListener('click', async () => { const nome = document.getElementById('cadastroNome')?.value?.trim() const email = document.getElementById('cadastroEmail')?.value?.trim() const senha = document.getElementById('cadastroSenha')?.value?.trim() if (!nome || !email || !senha) { notificar('Preencha todos os campos', 'error') return } if (senha.length < 4) { notificar('Senha mínima 4 caracteres', 'error') return } const { data: existente } = await supabase .from('users') .select('id') .eq('email', email) .maybeSingle() if (existente) { notificar('Email já existe', 'error') return } const { error } = await supabase.from('users').insert([{ name: nome, email, password: senha, role: 'trainer', active: true, approved: false }]) if (error) { console.error(error) notificar('Erro ao cadastrar', 'error') return } await carregarDados() notificar('Cadastro realizado! Aguarde aprovação do administrador.', 'success') currentView = 'trainer-login' renderizar() }) // LOGIN ALUNO document.getElementById('fazerLoginStudent')?.addEventListener('click', async () => { const email = document.getElementById('studentEmail')?.value?.trim() const codigo = document.getElementById('studentCode')?.value?.trim() const aluno = await buscarAlunoPorEmail(email) const treino = await buscarTreinoPorCodigo(codigo) if (!treino) { notificar('Código inválido', 'error') return } if (!aluno) { notificar('Aluno não encontrado', 'error') return } if (aluno.active === false) { notificar('Conta bloqueada', 'error') return } currentUser = aluno currentUser.workout_code = codigo await carregarDados() currentView = 'client-dashboard' renderizar() notificar(`Bem-vindo! Treino ${codigo}`, 'success') }) // SAIR document.getElementById('logoutTrainer')?.addEventListener('click', () => { currentUser = null currentView = 'login-type' renderizar() }) document.getElementById('sairAluno')?.addEventListener('click', () => { currentUser = null currentView = 'login-type' renderizar() }) document.getElementById('sairAlunoDashboard')?.addEventListener('click', () => { currentUser = null currentView = 'login-type' renderizar() }) document.getElementById('sairAdmin')?.addEventListener('click', () => { currentUser = null currentView = 'login-type' renderizar() }) // ADMIN CRIAR PROFESSOR document.getElementById('adminCriarProfessor')?.addEventListener('click', async () => { const nome = prompt('Nome do professor') const email = prompt('Email') const senha = prompt('Senha inicial') if (!nome || !email || !senha) return const { error } = await supabase.from('users').insert([{ name: nome, email, password: senha, role: 'trainer', active: true, approved: true }]) if (error) { console.error(error) notificar('Erro ao criar professor', 'error') return } await carregarDados() notificar('Professor criado e aprovado', 'success') renderizar() }) // ADMIN CRIAR ALUNO document.getElementById('adminCriarAluno')?.addEventListener('click', async () => { const nome = prompt('Nome do aluno') const email = prompt('Email') const treinadorEmail = prompt('Email do professor responsável (opcional)') if (!nome || !email) return let trainerId = null if (treinadorEmail) { const { data: treinador } = await supabase .from('users') .select('*') .eq('email', treinadorEmail) .eq('role', 'trainer') .maybeSingle() if (treinador) trainerId = treinador.id } const { error } = await supabase.from('users').insert([{ name: nome, email, password: '123456', role: 'student', active: true, approved: true, trainer_id: trainerId }]) if (error) { console.error(error) notificar('Erro ao criar aluno', 'error') return } await carregarDados() notificar('Aluno criado com senha 123456', 'success') renderizar() }) // APROVAR PROFESSOR document.querySelectorAll('.aprovarProfessorBtn').forEach(btn => { btn.addEventListener('click', async (e) => { const id = e.currentTarget.dataset.id const { error } = await supabase .from('users') .update({ approved: true }) .eq('id', id) if (error) { console.error(error) notificar('Erro ao aprovar professor', 'error') return } await carregarDados() notificar('Professor aprovado', 'success') renderizar() }) }) // BLOQUEIO / LIBERAÇÃO document.querySelectorAll('.toggleBloqueioBtn, .toggleBloqueioAlunoBtn').forEach(btn => { btn.addEventListener('click', async (e) => { const id = e.currentTarget.dataset.id const ativoAtual = e.currentTarget.dataset.active === 'true' const { error } = await supabase .from('users') .update({ active: !ativoAtual }) .eq('id', id) if (error) { console.error(error) notificar('Erro ao alterar status', 'error') return } await carregarDados() notificar(`Usuário ${!ativoAtual ? 'liberado' : 'bloqueado'}`, 'info') renderizar() }) }) // EDITAR USUÁRIO document.querySelectorAll('.editarUsuarioBtn').forEach(btn => { btn.addEventListener('click', (e) => { editingUserId = e.currentTarget.dataset.id currentView = 'admin-edit-user' renderizar() }) }) document.getElementById('salvarEdicaoUsuario')?.addEventListener('click', async () => { const user = allUsers.find(u => u.id == editingUserId) if (!user) return const payload = { name: document.getElementById('editNome')?.value?.trim(), email: document.getElementById('editEmail')?.value?.trim() } const novaSenha = document.getElementById('editSenha')?.value?.trim() if (novaSenha) payload.password = novaSenha if (user.role === 'student') { const trainer_id = document.getElementById('edittrainer_id')?.value?.trim() if (trainer_id) { const { data: trainer } = await supabase .from('users') .select('*') .eq('email', trainer_id) .eq('role', 'trainer') .maybeSingle() payload.trainer_id = trainer ? trainer.id : null } else { payload.trainer_id = null } } const { error } = await supabase .from('users') .update(payload) .eq('id', editingUserId) if (error) { console.error(error) notificar('Erro ao atualizar usuário', 'error') return } await carregarDados() notificar('Usuário atualizado', 'success') currentView = 'admin-dashboard' renderizar() }) // DELETAR USUÁRIO document.querySelectorAll('.deletarUsuarioBtn').forEach(btn => { btn.addEventListener('click', async (e) => { const id = e.currentTarget.dataset.id if (!confirm('Excluir usuário?')) return const { error } = await supabase .from('users') .delete() .eq('id', id) if (error) { console.error(error) notificar('Erro ao excluir usuário', 'error') return } await carregarDados() renderizar() }) }) // DELETAR TREINO document.querySelectorAll('.deletarTreinoAdminBtn').forEach(btn => { btn.addEventListener('click', async (e) => { const id = e.currentTarget.dataset.id if (!confirm('Excluir treino?')) return const { error } = await supabase .from('workouts') .delete() .eq('id', id) if (error) { console.error(error) notificar('Erro ao excluir treino', 'error') return } await carregarDados() renderizar() }) }) // AÇÕES PROFESSOR document.getElementById('cadastrarAlunoBtn')?.addEventListener('click', () => { currentView = 'register-student' renderizar() }) document.getElementById('criarTreinoBtn')?.addEventListener('click', () => { selectedWorkoutExercises = [] currentView = 'create-workout' renderizar() }) // CADASTRAR ALUNO document.getElementById('salvarNovoAluno')?.addEventListener('click', async () => { const nome = document.getElementById('novoAlunoNome')?.value?.trim() const email = document.getElementById('novoAlunoEmail')?.value?.trim() const whatsapp = document.getElementById('novoAlunoWhatsapp')?.value?.trim() if (!nome || !email) { notificar('Preencha nome e email', 'error') return } const { error } = await supabase.from('users').insert([{ name: nome, email, whatsapp, password: '123456', role: 'student', trainer_id: currentUser.id, active: true, approved: true }]) if (error) { console.error(error) notificar('Erro ao cadastrar aluno', 'error') return } await carregarDados() notificar('Aluno cadastrado', 'success') currentView = 'trainer-dashboard' renderizar() }) // ABAS EXERCÍCIOS document.getElementById('abaForca')?.addEventListener('click', () => { document.getElementById('abaForca')?.classList.add('text-green-400', 'border-b-2', 'border-green-500') document.getElementById('abaCardio')?.classList.remove('text-green-400', 'border-b-2', 'border-green-500') document.getElementById('listaExercicios').innerHTML = exerciseLibrary.strength.map(ex => `
${ex.name}
${ex.muscle}
`).join('') adicionarEventosExercicios() }) document.getElementById('abaCardio')?.addEventListener('click', () => { document.getElementById('abaCardio')?.classList.add('text-green-400', 'border-b-2', 'border-green-500') document.getElementById('abaForca')?.classList.remove('text-green-400', 'border-b-2', 'border-green-500') document.getElementById('listaExercicios').innerHTML = exerciseLibrary.cardio.map(ex => `
${ex.name}
${ex.duration}
`).join('') adicionarEventosExercicios() }) document.getElementById('adicionarExercicioBtn')?.addEventListener('click', () => { if (!exercicioSelecionado) return if (exercicioSelecionado.tipo === 'strength') { const series = document.getElementById('seriesInput')?.value || 3 const reps = document.getElementById('repsInput')?.value || 10 const rest = document.getElementById('restInput')?.value || 60 selectedWorkoutExercises.push({ name: exercicioSelecionado.nome, type: 'strength', series, reps, rest }) } else { const time = document.getElementById('tempoInput')?.value || 20 selectedWorkoutExercises.push({ name: exercicioSelecionado.nome, type: 'cardio', time }) } renderizar() }) document.querySelectorAll('.removerExercicio').forEach(btn => { btn.addEventListener('click', (e) => { const idx = e.currentTarget.dataset.idx if (idx !== undefined) { selectedWorkoutExercises.splice(parseInt(idx), 1) renderizar() } }) }) // SALVAR TREINO document.getElementById('salvarTreinoFinal')?.addEventListener('click', async () => { const alunoId = document.getElementById('alunoSelect')?.value const dias = Array.from(document.querySelectorAll('.diaCheckbox:checked')).map(cb => cb.value) if (!alunoId || selectedWorkoutExercises.length === 0) { notificar('Selecione aluno e adicione exercícios', 'error') return } const codigo = gerarCodigoTreino() const exerciciosStr = selectedWorkoutExercises .map(ex => ex.type === 'strength' ? `${ex.name} - ${ex.series}x${ex.reps} (${ex.rest}s)` : `${ex.name} - ${ex.time}min`) .join(', ') const { error: treinoError } = await supabase.from('workouts').insert([{ workout_code: codigo, trainer_id: currentUser.id, student_id: alunoId, exercises: exerciciosStr, workout_days: dias.join(',') }]) if (treinoError) { console.error(treinoError) notificar('Erro ao salvar treino', 'error') return } const ok = await vincularTreinoAoAluno(alunoId, codigo) if (!ok) { notificar('Treino salvo, mas erro ao vincular aluno', 'error') return } await carregarDados() generatedWorkoutCode = codigo currentView = 'workout-code' renderizar() }) // EXECUTAR TREINO document.querySelectorAll('.executarExercicioBtn').forEach(btn => { btn.addEventListener('click', (e) => { const nome = e.currentTarget.dataset.nome const info = e.currentTarget.dataset.info const tipo = e.currentTarget.dataset.tipo if (tipo === 'strength') { const [series, reps] = info.split('x') currentExercisePerforming = { name: nome, type: 'strength', series, reps, rest: 60 } } else { const time = info.replace('min', '') currentExercisePerforming = { name: nome, type: 'cardio', time, series: 1 } } currentSeriesIndex = 0 currentView = 'exercise-performance' renderizar() }) }) document.getElementById('concluirSerieBtn')?.addEventListener('click', () => { if (!currentExercisePerforming) return const total = parseInt(currentExercisePerforming.series) if (currentSeriesIndex + 1 < total) { currentSeriesIndex++ customRestTime = currentExercisePerforming.rest || 60 currentView = 'rest-timer' renderizar() iniciarTimerDescanso() } else { notificar('Treino concluído!', 'success') currentExercisePerforming = null currentView = 'client-dashboard' renderizar() } }) document.getElementById('pularDescansoBtn')?.addEventListener('click', () => { if (restTimerInterval) clearInterval(restTimerInterval) currentView = 'exercise-performance' renderizar() }) } function adicionarEventosExercicios() { document.querySelectorAll('.exercicioItem').forEach(el => { el.addEventListener('click', () => { exercicioSelecionado = { nome: el.dataset.nome, tipo: el.dataset.tipo, dica: el.dataset.dica } document.getElementById('infoExercicioSelecionado')?.classList.remove('hidden') document.getElementById('nomeExSelecionado').innerText = exercicioSelecionado.nome document.getElementById('dicaExSelecionado').innerText = exercicioSelecionado.dica if (exercicioSelecionado.tipo === 'strength') { document.getElementById('configForca')?.classList.remove('hidden') document.getElementById('configCardio')?.classList.add('hidden') } else { document.getElementById('configForca')?.classList.add('hidden') document.getElementById('configCardio')?.classList.remove('hidden') } document.getElementById('adicionarExercicioBtn').disabled = false }) }) } function iniciarTimerDescanso() { let tempo = customRestTime const timerEl = document.getElementById('timerDisplay') if (restTimerInterval) clearInterval(restTimerInterval) restTimerInterval = setInterval(() => { tempo-- if (timerEl) timerEl.innerText = tempo if (tempo <= 0) { clearInterval(restTimerInterval) currentView = 'exercise-performance' renderizar() } }, 1000) } // ==================== RENDERIZAÇÃO PRINCIPAL ==================== function renderizar() { const app = document.getElementById('app'); if (!app) return; let html = ''; if (currentView === 'login-type') html = telaLoginType(); else if (currentView === 'trainer-login') html = telaTrainerLogin(); else if (currentView === 'trainer-signup') html = telaTrainerSignup(); else if (currentView === 'student-login') html = telaStudentLogin(); else if (currentView === 'forgot-password') html = telaForgotPassword(); else if (currentView === 'trainer-dashboard') html = telaTrainerDashboard(); else if (currentView === 'client-dashboard') html = telaClientDashboard(); else if (currentView === 'create-workout') html = telaCreateWorkout(); else if (currentView === 'register-student') html = telaRegisterStudent(); else if (currentView === 'workout-code') html = telaWorkoutCode(); else if (currentView === 'admin-login') html = telaAdminLogin(); else if (currentView === 'admin-dashboard') html = telaAdminDashboard(); else if (currentView === 'admin-edit-user') html = telaAdminEditUser(); else if (currentView === 'exercise-performance') html = telaExercisePerformance(); else if (currentView === 'rest-timer') html = telaRestTimer(); app.innerHTML = html; if (window.lucide) lucide.createIcons(); eventosClique(); } // ==================== TELAS ==================== function telaLoginType() { return `

FORJA

PERSONAL TRAINING SYSTEM

`; } function telaAdminLogin() { return `

ÁREA ADMIN

Acesso restrito

`; } function telaTrainerLogin() { return `

FORJA

Login do Professor

`; } function telaTrainerSignup() { return `

CADASTRO

Crie sua conta (aguarde aprovação)

`; } function telaStudentLogin() { return `

ALUNO

Acesse seu treino

`; } function telaForgotPassword() { return `

Recuperar Senha

Digite seu e-mail. Enviaremos uma nova senha.

`; } function telaAdminDashboard() { const professores = allUsers.filter(u => u.role === 'trainer'); const alunos = allUsers.filter(u => u.role === 'student'); const treinos = allWorkouts; return `

Admin Dashboard

${currentUser?.name}

Professores (${professores.length})

${professores.map(p => `

${p.name}

${p.email}

${p.approved ? 'Aprovado' : 'Pendente'}${p.active === false ? 'Bloqueado' : ''}
${!p.approved ? `` : ''}
Alunos: ${alunos.filter(a => a.trainer_id === p.email).length}
`).join('') || '

Nenhum professor

'}

Alunos (${alunos.length})

${alunos.map(a => `

${a.name}

${a.email}

Professor: ${a.trainer_id || 'Não atribuído'}

${a.workoutCode ? `

Treino: ${a.workoutCode}

` : '

Sem treino

'}
`).join('') || '

Nenhum aluno

'}

Todos os Treinos (${treinos.length})

${treinos.map(t => `

${t.workoutCode}

Professor: ${t.trainer_id}

${t.exercises?.substring(0, 50)}

`).join('') || '

Nenhum treino

'}
`; } function telaAdminEditUser() { const user = allUsers.find(u => u.id == editingUserId); if (!user) return '
'; return `

Editar ${user.role === 'trainer' ? 'Professor' : 'Aluno'}

${user.role === 'student' ? `
` : ''}
`; } // Tela Register Student function telaRegisterStudent() { return `

Cadastrar Novo Aluno

`; } function telaCreateWorkout() { const meusAlunos = allUsers.filter(u => u.role === 'student' && u.trainer_id === currentUser?.id); const listaExercicios = selectedWorkoutExercises.map((ex, idx) => `
${ex.name} - ${ex.type === 'strength' ? `${ex.series}x${ex.reps} (${ex.rest}s)` : `${ex.time}min`}
`).join(''); return `

Criar Treino

${exerciseLibrary.strength.map(ex => `
${ex.name}
${ex.muscle}
`).join('')}

Configurar

Exercícios (${selectedWorkoutExercises.length})

${listaExercicios || '

Nenhum

'}

Atribuir

Dias:

${['Seg','Ter','Qua','Qui','Sex','Sab','Dom'].map((d,i)=>``).join('')}
`; } function telaWorkoutCode() { return `

Treino Criado!

${generatedWorkoutCode}

`; } function telaClientDashboard() { const treino = allWorkouts.find(w => w.workoutCode === currentUser?.workoutCode); if (!treino) return `

Treino não encontrado

`; const exercicios = treino.exercises.split(', ').map(ex => { const parts = ex.split('|'); return { nome: parts[0], info: parts[1], tipo: parts[1].includes('min') ? 'cardio' : 'strength' }; }); return `

FORJA

Seu Treino

Código: ${treino.workoutCode}

${exercicios.map((ex,idx)=>``).join('')}
`; } function telaExercisePerformance() { if (!currentExercisePerforming) return ''; const total = parseInt(currentExercisePerforming.series); return `

Executando

${currentExercisePerforming.name}

Série

${currentSeriesIndex+1}/${total}

${currentExercisePerforming.type==='strength'?'Repetições':'Minutos'}

${currentExercisePerforming.type==='strength'?currentExercisePerforming.reps:currentExercisePerforming.time}

${Array(total).fill().map((_,i)=>`
${i+1}
`).join('')}
`; } function telaRestTimer() { return `
${customRestTime}

DESCANSO

`; } // ==================== EVENTOS ==================== let exercicioSelecionado = null; function eventosClique() { // Navegação document.getElementById('btnTrainer')?.addEventListener('click', () => { currentView = 'trainer-login'; renderizar(); }); document.getElementById('btnStudent')?.addEventListener('click', () => { currentView = 'student-login'; renderizar(); }); document.getElementById('btnAdmin')?.addEventListener('click', () => { currentView = 'admin-login'; renderizar(); }); document.getElementById('voltarLoginType')?.addEventListener('click', () => { currentView = 'login-type'; renderizar(); }); document.getElementById('voltarLogin')?.addEventListener('click', () => { currentView = 'login-type'; renderizar(); }); document.getElementById('voltarLoginTypeStudent')?.addEventListener('click', () => { currentView = 'login-type'; renderizar(); }); document.getElementById('voltarLoginTypeAdmin')?.addEventListener('click', () => { currentView = 'login-type'; renderizar(); }); document.getElementById('voltarReset')?.addEventListener('click', () => { currentView = 'trainer-login'; renderizar(); }); document.getElementById('voltarDashboard')?.addEventListener('click', () => { currentView = 'trainer-dashboard'; renderizar(); }); document.getElementById('voltarDashboardCreate')?.addEventListener('click', () => { currentView = 'trainer-dashboard'; renderizar(); }); document.getElementById('voltarDashboardFinal')?.addEventListener('click', () => { currentView = 'trainer-dashboard'; renderizar(); }); document.getElementById('voltarPerformance')?.addEventListener('click', () => { currentExercisePerforming = null; currentView = 'client-dashboard'; renderizar(); }); document.getElementById('cancelarEdicao')?.addEventListener('click', () => { currentView = 'admin-dashboard'; renderizar(); }); // Admin login document.getElementById('fazerLoginAdmin')?.addEventListener('click', () => { const email = document.getElementById('adminEmailLogin')?.value; const senha = document.getElementById('adminSenhaLogin')?.value; const admin = allUsers.find(u => u.email === email && u.password === senha && u.role === 'admin'); if (admin) { currentUser = admin; currentView = 'admin-dashboard'; renderizar(); notificar('Login admin', 'success'); } else notificar('Credenciais inválidas', 'error'); }); // Trainer login document.getElementById('fazerLoginTrainer')?.addEventListener('click', () => { const email = document.getElementById('trainer_id')?.value; const senha = document.getElementById('trainerPassword')?.value; const user = allUsers.find(u => u.email === email && u.password === senha && u.role === 'trainer'); if (!user) { notificar('Email ou senha incorretos', 'error'); return; } if (!user.approved) { notificar('Conta pendente de aprovação pelo admin', 'error'); return; } if (user.active === false) { notificar('Conta bloqueada. Contate o administrador.', 'error'); return; } currentUser = user; currentView = 'trainer-dashboard'; renderizar(); notificar(`Bem-vindo, ${user.name}!`, 'success'); }); document.getElementById('irCadastro')?.addEventListener('click', () => { currentView = 'trainer-signup'; renderizar(); }); document.getElementById('esqueciSenhaTrainer')?.addEventListener('click', () => { currentView = 'forgot-password'; renderizar(); }); document.getElementById('esqueciSenhaStudent')?.addEventListener('click', () => { currentView = 'forgot-password'; renderizar(); }); document.getElementById('solicitarReset')?.addEventListener('click', () => { const email = document.getElementById('resetEmail')?.value; if (email) { solicitarResetSenha(email); currentView = 'trainer-login'; renderizar(); } else notificar('Digite um e-mail', 'error'); }); // Cadastro professor document.getElementById('fazerCadastro')?.addEventListener('click', () => { const nome = document.getElementById('cadastroNome')?.value; const email = document.getElementById('cadastroEmail')?.value; const senha = document.getElementById('cadastroSenha')?.value; if (!nome || !email || !senha) { notificar('Preencha todos os campos', 'error'); return; } if (senha.length < 4) { notificar('Senha mínima 4 caracteres', 'error'); return; } if (allUsers.find(u => u.email === email)) { notificar('Email já existe', 'error'); return; } allUsers.push({ id: Date.now(), name: nome, email, password: senha, role: 'trainer', active: true, approved: false }); salvarDados(); notificar('Cadastro realizado! Aguarde aprovação do administrador.', 'success'); currentView = 'trainer-login'; renderizar(); }); // Student login document.getElementById('fazerLoginStudent')?.addEventListener('click', () => { const email = document.getElementById('studentEmail')?.value; const codigo = document.getElementById('studentCode')?.value; const treino = allWorkouts.find(w => w.workoutCode === codigo); if (!treino) { notificar('Código inválido', 'error'); return; } const aluno = allUsers.find(u => u.email === email && u.role === 'student'); if (aluno && aluno.active === false) { notificar('Conta bloqueada', 'error'); return; } currentUser = { email, workoutCode: codigo, role: 'student', name: email.split('@')[0] }; currentView = 'client-dashboard'; renderizar(); notificar(`Bem-vindo! Treino ${codigo}`, 'success'); }); // Sair document.getElementById('logoutTrainer')?.addEventListener('click', () => { currentUser = null; currentView = 'login-type'; renderizar(); }); document.getElementById('sairAluno')?.addEventListener('click', () => { currentUser = null; currentView = 'login-type'; renderizar(); }); document.getElementById('sairAlunoDashboard')?.addEventListener('click', () => { currentUser = null; currentView = 'login-type'; renderizar(); }); document.getElementById('sairAdmin')?.addEventListener('click', () => { currentUser = null; currentView = 'login-type'; renderizar(); }); // Ações admin dashboard document.getElementById('adminCriarProfessor')?.addEventListener('click', () => { const nome = prompt('Nome do professor'); const email = prompt('Email'); const senha = prompt('Senha inicial'); if (nome && email && senha) { allUsers.push({ id: Date.now(), name: nome, email, password: senha, role: 'trainer', active: true, approved: true }); salvarDados(); notificar('Professor criado e aprovado', 'success'); renderizar(); } }); document.getElementById('adminCriarAluno')?.addEventListener('click', () => { const nome = prompt('Nome do aluno'); const email = prompt('Email'); const treinadorEmail = prompt('Email do professor responsável (opcional)'); if (nome && email) { allUsers.push({ id: Date.now(), name: nome, email, password: '123456', role: 'student', active: true, trainer_id: treinadorEmail || '' }); salvarDados(); notificar('Aluno criado com senha 123456', 'success'); renderizar(); } }); document.querySelectorAll('.aprovarProfessorBtn').forEach(btn => { btn.addEventListener('click', (e) => { const id = e.currentTarget.dataset.id; const prof = allUsers.find(u => u.id == id); if (prof) { prof.approved = true; salvarDados(); notificar('Professor aprovado', 'success'); renderizar(); } }); }); document.querySelectorAll('.toggleBloqueioBtn, .toggleBloqueioAlunoBtn').forEach(btn => { btn.addEventListener('click', (e) => { const id = e.currentTarget.dataset.id; const user = allUsers.find(u => u.id == id); if (user) { user.active = !(user.active === false); salvarDados(); notificar(`Usuário ${user.active ? 'liberado' : 'bloqueado'}`, 'info'); renderizar(); } }); }); document.querySelectorAll('.editarUsuarioBtn').forEach(btn => { btn.addEventListener('click', (e) => { editingUserId = e.currentTarget.dataset.id; currentView = 'admin-edit-user'; renderizar(); }); }); document.getElementById('salvarEdicaoUsuario')?.addEventListener('click', () => { const user = allUsers.find(u => u.id == editingUserId); if (user) { user.name = document.getElementById('editNome')?.value || user.name; user.email = document.getElementById('editEmail')?.value || user.email; const novaSenha = document.getElementById('editSenha')?.value; if (novaSenha) user.password = novaSenha; if (user.role === 'student') user.trainer_id = document.getElementById('edittrainer_id')?.value || ''; salvarDados(); notificar('Usuário atualizado', 'success'); currentView = 'admin-dashboard'; renderizar(); } }); document.querySelectorAll('.deletarUsuarioBtn').forEach(btn => { btn.addEventListener('click', (e) => { const id = e.currentTarget.dataset.id; if (confirm('Excluir usuário?')) { allUsers = allUsers.filter(u => u.id != id); salvarDados(); renderizar(); } }); }); document.querySelectorAll('.deletarTreinoAdminBtn').forEach(btn => { btn.addEventListener('click', (e) => { const id = e.currentTarget.dataset.id; if (confirm('Excluir treino?')) { allWorkouts = allWorkouts.filter(w => w.id != id); salvarDados(); renderizar(); } }); }); // Ações professor dashboard document.getElementById('cadastrarAlunoBtn')?.addEventListener('click', () => { currentView = 'register-student'; renderizar(); }); document.getElementById('criarTreinoBtn')?.addEventListener('click', () => { selectedWorkoutExercises = []; currentView = 'create-workout'; renderizar(); }); document.getElementById('gerenciarTreinosBtn')?.addEventListener('click', () => { currentView = 'manage-students'; renderizar(); }); document.getElementById('salvarNovoAluno')?.addEventListener('click', () => { const nome = document.getElementById('novoAlunoNome')?.value; const email = document.getElementById('novoAlunoEmail')?.value; const whatsapp = document.getElementById('novoAlunoWhatsapp')?.value; if (nome && email) { allUsers.push({ id: Date.now(), name: nome, email, whatsapp, role: 'student', trainer_id: currentUser.email, active: true }); salvarDados(); notificar('Aluno cadastrado', 'success'); currentView = 'trainer-dashboard'; renderizar(); } else notificar('Preencha nome e email', 'error'); }); document.querySelectorAll('.atribuirTreinoBtn').forEach(btn => { btn.addEventListener('click', (e) => { const email = e.currentTarget.dataset.email; const meusTreinos = allWorkouts.filter(w => w.trainer_id === currentUser?.email); if (!meusTreinos.length) { notificar('Crie um treino primeiro', 'error'); return; } const codigo = prompt('Código do treino:', meusTreinos[0].workoutCode); if (codigo) { const treino = allWorkouts.find(w => w.workoutCode === codigo && w.trainer_id === currentUser.email); if (treino) { const aluno = allUsers.find(u => u.email === email); if (aluno) { aluno.workoutCode = codigo; salvarDados(); notificar('Treino atribuído', 'success'); renderizar(); } } else notificar('Código inválido', 'error'); } }); }); document.querySelectorAll('.copiarCodigoBtn, #copiarCodigoFinal').forEach(btn => { btn.addEventListener('click', (e) => { const code = e.currentTarget.dataset.code || generatedWorkoutCode; if (code) { navigator.clipboard.writeText(code); notificar('Código copiado!', 'success'); } }); }); // Criação de treino document.getElementById('abaForca')?.addEventListener('click', () => { document.getElementById('abaForca').classList.add('text-green-400','border-b-2','border-green-500'); document.getElementById('abaCardio').classList.remove('text-green-400','border-b-2','border-green-500'); document.getElementById('listaExercicios').innerHTML = exerciseLibrary.strength.map(ex => `
${ex.name}
${ex.muscle}
`).join(''); adicionarEventosExercicios(); }); document.getElementById('abaCardio')?.addEventListener('click', () => { document.getElementById('abaCardio').classList.add('text-green-400','border-b-2','border-green-500'); document.getElementById('abaForca').classList.remove('text-green-400','border-b-2','border-green-500'); document.getElementById('listaExercicios').innerHTML = exerciseLibrary.cardio.map(ex => `
${ex.name}
${ex.duration}
`).join(''); adicionarEventosExercicios(); }); function adicionarEventosExercicios() { document.querySelectorAll('.exercicioItem').forEach(el => { el.addEventListener('click', () => { exercicioSelecionado = { nome: el.dataset.nome, tipo: el.dataset.tipo, dica: el.dataset.dica }; document.getElementById('infoExercicioSelecionado').classList.remove('hidden'); document.getElementById('nomeExSelecionado').innerText = exercicioSelecionado.nome; document.getElementById('dicaExSelecionado').innerText = exercicioSelecionado.dica || ''; if (exercicioSelecionado.tipo === 'strength') { document.getElementById('configForca').classList.remove('hidden'); document.getElementById('configCardio').classList.add('hidden'); } else { document.getElementById('configForca').classList.add('hidden'); document.getElementById('configCardio').classList.remove('hidden'); } document.getElementById('adicionarExercicioBtn').disabled = false; }); }); } adicionarEventosExercicios(); document.getElementById('adicionarExercicioBtn')?.addEventListener('click', () => { if (!exercicioSelecionado) return; if (exercicioSelecionado.tipo === 'strength') { const series = document.getElementById('seriesInput')?.value || 3; const reps = document.getElementById('repsInput')?.value || 10; const rest = document.getElementById('restInput')?.value || 60; selectedWorkoutExercises.push({ name: exercicioSelecionado.nome, type: 'strength', series, reps, rest }); } else { const time = document.getElementById('tempoInput')?.value || 20; selectedWorkoutExercises.push({ name: exercicioSelecionado.nome, type: 'cardio', time }); } renderizar(); }); document.querySelectorAll('.removerExercicio').forEach(btn => { btn.addEventListener('click', (e) => { const idx = e.currentTarget.dataset.idx; if (idx!==undefined) { selectedWorkoutExercises.splice(parseInt(idx),1); renderizar(); } }); }); document.getElementById('salvarTreinoFinal')?.addEventListener('click', () => { const alunoEmail = document.getElementById('alunoSelect')?.value; const dias = Array.from(document.querySelectorAll('.diaCheckbox:checked')).map(cb=>cb.value); if (!alunoEmail || selectedWorkoutExercises.length===0) { notificar('Selecione aluno e adicione exercícios','error'); return; } const codigo = gerarCodigoTreino(); const exerciciosStr = selectedWorkoutExercises.map(ex => ex.type==='strength'?`${ex.name}|${ex.series}x${ex.reps}|${ex.rest}s`:`${ex.name}|${ex.time}min`).join(', '); allWorkouts.push({ id: Date.now(), workoutCode: codigo, trainer_id: currentUser.email, exercises: exerciciosStr, workoutDays: dias.join(','), createdAt: new Date().toISOString() }); const aluno = allUsers.find(u=>u.email===alunoEmail); if (aluno) aluno.workoutCode = codigo; salvarDados(); generatedWorkoutCode = codigo; currentView = 'workout-code'; renderizar(); }); // Executar treino document.querySelectorAll('.executarExercicioBtn').forEach(btn => { btn.addEventListener('click', (e) => { const nome = e.currentTarget.dataset.nome; const info = e.currentTarget.dataset.info; const tipo = e.currentTarget.dataset.tipo; if (tipo === 'strength') { const [series, reps] = info.split('x'); currentExercisePerforming = { name: nome, type: 'strength', series, reps, rest: 60 }; } else { const time = info.replace('min',''); currentExercisePerforming = { name: nome, type: 'cardio', time, series: 1 }; } currentSeriesIndex = 0; currentView = 'exercise-performance'; renderizar(); }); }); document.getElementById('concluirSerieBtn')?.addEventListener('click', () => { if (!currentExercisePerforming) return; const total = parseInt(currentExercisePerforming.series); if (currentSeriesIndex+1 < total) { currentSeriesIndex++; customRestTime = currentExercisePerforming.rest || 60; currentView = 'rest-timer'; renderizar(); iniciarTimerDescanso(); } else { notificar('🏆 Treino concluído!','success'); currentExercisePerforming = null; currentView = 'client-dashboard'; renderizar(); } }); function iniciarTimerDescanso() { let tempo = customRestTime; const timerEl = document.getElementById('timerDisplay'); if (restTimerInterval) clearInterval(restTimerInterval); restTimerInterval = setInterval(() => { tempo--; if (timerEl) timerEl.innerText = tempo; if (tempo <= 0) { clearInterval(restTimerInterval); currentView = 'exercise-performance'; renderizar(); } }, 1000); } document.getElementById('pularDescansoBtn')?.addEventListener('click', () => { if (restTimerInterval) clearInterval(restTimerInterval); currentView = 'exercise-performance'; renderizar(); }); } // Inicialização carregarDados(); renderizar();