Skip to content
Open
44 changes: 0 additions & 44 deletions Login.jsx

This file was deleted.

3 changes: 1 addition & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<title>CraftCode</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
<div id="root"></div> <script type="module" src="/src/main.jsx"></script>
</body>
</html>
97 changes: 62 additions & 35 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,94 @@
import React, { useState } from 'react'
import Login from './Login.jsx'
import React, { useState } from 'react';
import Login from './Login.jsx';
import Sobre from './Sobre.jsx';
import Cursos from './Cursos.jsx';

function App() {
const [paginaAtual, setPaginaAtual] = useState('home');
const [usuarioLogado, setUsuarioLogado] = useState(null);

const fazerLogout = () => setUsuarioLogado(null);
const irPara = (p) => setPaginaAtual(p);

// Renderização Condicional de Telas Inteiras
if (paginaAtual === 'login') {
return <Login voltar={() => setPaginaAtual('home')} />;
return (
<Login
voltar={() => irPara('home')}
aoLogarSucesso={(dados) => { setUsuarioLogado(dados); irPara('home'); }}
/>
);
}

if (paginaAtual === 'sobre') {
return <Sobre voltar={() => irPara('home')} />;
}

if (paginaAtual === 'cursos') {
return <Cursos voltar={() => irPara('home')} usuarioLogado={usuarioLogado} />;
}

// Tela Home (Padrão)
return (
<>
<div>
<header className="main-header">
<div className="container header-content">
<div className="logo" onClick={() => setPaginaAtual('home')} style={{cursor: 'pointer'}}>
CraftCode
</div>
<div className="logo">CraftCode</div>
<nav>
<ul className="nav-links">
<li><a href="#">Cursos</a></li>
<li><a href="#">Trilhas</a></li>
<li><a href="#">Sobre</a></li>
<li><a href="#" onClick={() => irPara('cursos')}>Cursos</a></li>
<li><a href="#" onClick={() => irPara('sobre')}>Sobre</a></li>
<li>
<button onClick={() => setPaginaAtual('login')} className="btn-entrar-header">
Entrar
</button>
{usuarioLogado ? (
<div style={{ display: 'flex', alignItems: 'center', gap: '15px' }}>
<span style={{ color: 'var(--primary-color)', fontWeight: 'bold' }}>Olá, {usuarioLogado.nome}!</span>
<button onClick={fazerLogout} className="btn-entrar-header" style={{ borderColor: '#FF8C00', color: '#FF8C00' }}>Sair</button>
</div>
) : (
<button onClick={() => irPara('login')} className="btn-entrar-header">Entrar</button>
)}
</li>
</ul>
</nav>
</div>
</header>

<main>
<section className="hero">
<div className="container">
<h1>Domine a arte do código</h1>
<p>Aprenda programação com projetos práticos e evolua sua carreira tech.</p>
<a href="#" className="btn-primary">Começar Agora</a>
</div>
</section>

<section className="courses-section">
<div className="container">
<h2>Cursos Populares</h2>
<div className="course-grid">
<div className="course-card">
<section className="hero">
<div className="container">
<h1>Domine a arte do código</h1>
<p>Aprenda programação com projetos práticos e evolua sua carreira tech.</p>
<button
onClick={() => usuarioLogado ? irPara('cursos') : irPara('login')}
className="btn-primary"
style={{ border: 'none', cursor: 'pointer' }}
>
{usuarioLogado ? 'Ver Meus Cursos' : 'Começar Agora'}
</button>
</div>
</section>

<section className="courses-section">
<div className="container">
<h2>Destaques</h2>
<div className="course-grid">
<article className="course-card">
<div className="card-image"></div>
<div className="card-content">
<h3>Lógica de Programação</h3>
<p>Fundamentos essenciais para iniciantes.</p>
<a href="#" onClick={(e) => { e.preventDefault(); irPara('cursos'); }} className="link-details">Saber mais &rarr;</a>
</div>
<div className="course-card">
<h3>Frontend Moderno</h3>
<p>HTML, CSS e JS avançado.</p>
</div>
</div>
</article>
</div>
</section>
</main>
</div>
</section>

<footer>
<div className="container">
<p>&copy; 2026 CraftCode. Todos os direitos reservados.</p>
</div>
</footer>
</>
</div>
);
}

Expand Down
50 changes: 50 additions & 0 deletions src/Cursos.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';

const LISTA_CURSOS = [
{ id: 1, titulo: "Lógica de Programação", desc: "O início de tudo. Algoritmos e estruturas.", nivel: "Iniciante" },
{ id: 2, titulo: "Frontend Moderno", desc: "Domine React, Vue e ecossistemas atuais.", nivel: "Intermediário" },
{ id: 3, titulo: "Backend com Node.js", desc: "Criando APIs escaláveis com TypeScript.", nivel: "Avançado" },
{ id: 4, titulo: "Banco de Dados SQL", desc: "Modelagem e consultas com PostgreSQL.", nivel: "Intermediário" },
{ id: 5, titulo: "UI/UX para Devs", desc: "Design focado em experiência do usuário.", nivel: "Iniciante" },
];

function Cursos({ voltar, usuarioLogado }) {
return (
<div className="cursos-page">
<header className="main-header">
<div className="container header-content">
<div className="logo" onClick={voltar} style={{cursor: 'pointer'}}>CraftCode</div>
<button onClick={voltar} className="btn-back" style={{margin: 0}}>← Voltar</button>
</div>
</header>

<section className="courses-section">
<div className="container">
<h2>{usuarioLogado ? `Catálogo para ${usuarioLogado.nome}` : 'Nossos Cursos'}</h2>
<p style={{color: 'var(--text-gray)', marginBottom: '30px'}}>
{usuarioLogado ? 'Continue de onde parou ou comece algo novo.' : 'Faça login para salvar seu progresso.'}
</p>

<div className="course-grid">
{LISTA_CURSOS.map(curso => (
<article key={curso.id} className="course-card">
<div className="card-image" style={{display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#555'}}>
{curso.nivel}
</div>
<div className="card-content">
<h3>{curso.titulo}</h3>
<p>{curso.desc}</p>
<button className="link-details" style={{background: 'none', border: 'none', cursor: 'pointer'}}>
{usuarioLogado ? 'Acessar Aulas →' : 'Ver Detalhes →'}
</button>
</div>
</article>
))}
</div>
</div>
</section>
</div>
);
}

export default Cursos;
123 changes: 123 additions & 0 deletions src/Login.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React, { useState } from 'react';

// Adicionamos a prop "aoLogarSucesso"
function Login({ voltar, aoLogarSucesso }) {
const [isLogin, setIsLogin] = useState(true);

const [nome, setNome] = useState('');
const [email, setEmail] = useState('');
const [senha, setSenha] = useState('');
const [mensagem, setMensagem] = useState('');

const handleSubmit = async (evento) => {
evento.preventDefault();

const endpoint = isLogin ? 'http://localhost:3000/login' : 'http://localhost:3000/cadastro';
const bodyData = isLogin ? { email, senha } : { nome, email, senha };

try {
const resposta = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(bodyData)
});

const dados = await resposta.json();

if (resposta.ok) {
setMensagem("🎉 " + dados.mensagem);

if (!isLogin) {
setNome('');
setIsLogin(true);
} else {
setSenha('');

// Espera 1 segundo para o utilizador ler a mensagem de sucesso
setTimeout(() => {
// Chama a função passando os dados que vieram do backend (nome, email, id)
aoLogarSucesso(dados.usuario);
}, 1000);
}
} else {
setMensagem("❌ " + dados.erro);
}
} catch (error) {
setMensagem("❌ Erro ao conectar com o servidor. O Back-end está a correr?");
}
};

const alternarModo = () => {
setIsLogin(!isLogin);
setMensagem('');
setNome('');
setSenha('');
};

return (
<div className="login-page">
<section className="login-section">
<div className="login-container container">
<button onClick={voltar} className="btn-back">
&larr; Voltar
</button>

<h2>{isLogin ? 'Entrar no CraftCode' : 'Crie a sua conta'}</h2>
<p>{isLogin ? 'Acesse sua conta para continuar evoluindo.' : 'Junte-se ao CraftCode e comece a construir o seu futuro.'}</p>

<form className="login-form" onSubmit={handleSubmit}>
{!isLogin && (
<div className="form-group">
<input
type="text"
placeholder="Seu nome"
className="input-craftcode"
value={nome}
onChange={(e) => setNome(e.target.value)}
required={!isLogin}
/>
</div>
)}

<div className="form-group">
<input
type="email"
placeholder="Seu e-mail"
className="input-craftcode"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>

<div className="form-group">
<input
type="password"
placeholder="Sua senha"
className="input-craftcode"
value={senha}
onChange={(e) => setSenha(e.target.value)}
required
/>
</div>

<button type="submit" className="btn-primary btn-submit">
{isLogin ? 'Entrar' : 'Registar'}
</button>
</form>

{mensagem && <p className="mensagem-aviso">{mensagem}</p>}

<p className="signup-text">
{isLogin ? 'Não tem conta? ' : 'Já tem uma conta? '}
<span onClick={alternarModo} className="link-acao">
{isLogin ? 'Cadastre-se' : 'Faça Login'}
</span>
</p>
</div>
</section>
</div>
);
}

export default Login;
Loading