diff --git a/README.md b/README.md index 8b13789..e69de29 100644 --- a/README.md +++ b/README.md @@ -1 +0,0 @@ - diff --git a/index.html b/index.html deleted file mode 100644 index e69de29..0000000 diff --git a/school-pokedex/admin-script.js b/school-pokedex/admin-script.js new file mode 100644 index 0000000..11a9710 --- /dev/null +++ b/school-pokedex/admin-script.js @@ -0,0 +1,114 @@ +document.addEventListener('DOMContentLoaded', () => { + const form = document.getElementById('pokemon-form'); + const pokemonList = document.getElementById('admin-pokemon-list'); + + const fetchPokemons = () => { + fetch('/school-pokedex/school-pokedex/api.php') + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.text().then(text => { + try { + return JSON.parse(text); + } catch (error) { + console.error('JSON parse error:', error, text); + throw error; + } + }); + }) + .then(pokemons => { + pokemonList.innerHTML = ''; + pokemons.forEach(pokemon => { + const card = document.createElement('div'); + card.className = 'pokemon-card'; + card.innerHTML = ` + ${pokemon.name} +

${pokemon.name}

+

Type: ${pokemon.type}

+

Stats: ${JSON.stringify(pokemon.stats)}

+

Info: ${pokemon.info}

+ + + `; + pokemonList.appendChild(card); + }); + }) + .catch(error => console.error('Fetch error:', error)); + }; + + form.addEventListener('submit', (e) => { + e.preventDefault(); + const id = document.getElementById('pokemon-id').value; + const name = document.getElementById('name').value; + const type = document.getElementById('type').value; + const image = document.getElementById('image').value; + const stats = JSON.parse(document.getElementById('stats').value); + const info = document.getElementById('info').value; + + const method = id ? 'PUT' : 'POST'; + const url = id ? `/school-pokedex/school-pokedex/api.php/${id}` : '/school-pokedex/school-pokedex/api.php'; + + fetch(url, { + method: method, + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ name, type, image, stats, info }) + }).then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.text().then(text => { + try { + return JSON.parse(text); + } catch (error) { + console.error('JSON parse error:', error, text); + throw error; + } + }); + }).then(() => { + form.reset(); + fetchPokemons(); + }).catch(error => console.error('Fetch error:', error)); + }); + + window.editPokemon = (id) => { + fetch(`/school-pokedex/school-pokedex/api.php/${id}`) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.text().then(text => { + try { + return JSON.parse(text); + } catch (error) { + console.error('JSON parse error:', error, text); + throw error; + } + }); + }) + .then(pokemon => { + document.getElementById('pokemon-id').value = pokemon.id; + document.getElementById('name').value = pokemon.name; + document.getElementById('type').value = pokemon.type; + document.getElementById('image').value = pokemon.image; + document.getElementById('stats').value = JSON.stringify(pokemon.stats); + document.getElementById('info').value = pokemon.info; + }) + .catch(error => console.error('Fetch error:', error)); + }; + + window.deletePokemon = (id) => { + fetch(`/school-pokedex/school-pokedex/api.php/${id}`, { method: 'DELETE' }) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + fetchPokemons(); + }) + .catch(error => console.error('Fetch error:', error)); + }; + + fetchPokemons(); +}); diff --git a/school-pokedex/admin.html b/school-pokedex/admin.html new file mode 100644 index 0000000..ccff0a5 --- /dev/null +++ b/school-pokedex/admin.html @@ -0,0 +1,29 @@ + + + + + + Admin - Pokédex + + + + +

Admin - Pokédex

+
+ + + + + + + + + + + + +
+
+ + + diff --git a/school-pokedex/api.php b/school-pokedex/api.php new file mode 100644 index 0000000..4f5548a --- /dev/null +++ b/school-pokedex/api.php @@ -0,0 +1,155 @@ +connect_error) { + error_log("Connection failed: " . $conn->connect_error); + die(json_encode(['error' => "Connection failed: " . $conn->connect_error])); +} + +header('Content-Type: application/json'); + +// Ensure the request is using JSON +if ($_SERVER['CONTENT_TYPE'] !== 'application/json') { + echo json_encode(['error' => 'Content-Type must be application/json']); + exit; +} + +$method = $_SERVER['REQUEST_METHOD']; +$request = explode('/', trim($_SERVER['PATH_INFO'], '/')); + +switch ($method) { + case 'GET': + if (isset($request[0]) && is_numeric($request[0])) { + $id = $request[0]; + $stmt = $conn->prepare("SELECT * FROM pokemons WHERE id = ?"); + $stmt->bind_param("i", $id); + $stmt->execute(); + $result = $stmt->get_result(); + if ($result->num_rows > 0) { + echo json_encode($result->fetch_assoc()); + } else { + echo json_encode(['error' => 'No record found']); + } + $stmt->close(); + } else { + $sql = "SELECT * FROM pokemons"; + $result = $conn->query($sql); + $pokemons = []; + while ($row = $result->fetch_assoc()) { + $pokemons[] = $row; + } + echo json_encode($pokemons); + } + break; + + case 'POST': + $data = json_decode(file_get_contents('php://input'), true); + if (!isset($data['name'], $data['type'], $data['image'], $data['stats'], $data['info'])) { + echo json_encode(['error' => 'Missing required fields']); + exit; + } + + $name = $data['name']; + $type = $data['type']; + $image = $data['image']; + $stats = json_encode($data['stats']); + $info = $data['info']; + + // Prepared statement to prevent SQL injection + $stmt = $conn->prepare("INSERT INTO pokemons (name, type, image, stats, info) VALUES (?, ?, ?, ?, ?)"); + $stmt->bind_param("sssss", $name, $type, $image, $stats, $info); + + if ($stmt->execute()) { + echo json_encode([ + 'id' => $conn->insert_id, + 'name' => $name, + 'type' => $type, + 'image' => $image, + 'stats' => $stats, + 'info' => $info + ]); + } else { + error_log("Insert error: " . $conn->error); + echo json_encode(['error' => 'Failed to insert record']); + } + + $stmt->close(); + break; + + case 'PUT': + if (!isset($request[0]) || !is_numeric($request[0])) { + echo json_encode(['error' => 'ID is required']); + exit; + } + + $id = $request[0]; + $data = json_decode(file_get_contents('php://input'), true); + + if (!isset($data['name'], $data['type'], $data['image'], $data['stats'], $data['info'])) { + echo json_encode(['error' => 'Missing required fields']); + exit; + } + + $name = $data['name']; + $type = $data['type']; + $image = $data['image']; + $stats = json_encode($data['stats']); + $info = $data['info']; + + // Prepared statement to prevent SQL injection + $stmt = $conn->prepare("UPDATE pokemons SET name=?, type=?, image=?, stats=?, info=? WHERE id=?"); + $stmt->bind_param("sssssi", $name, $type, $image, $stats, $info, $id); + + if ($stmt->execute()) { + echo json_encode([ + 'id' => $id, + 'name' => $name, + 'type' => $type, + 'image' => $image, + 'stats' => $stats, + 'info' => $info + ]); + } else { + error_log("Update error: " . $conn->error); + echo json_encode(['error' => 'Failed to update record']); + } + + $stmt->close(); + break; + + case 'DELETE': + if (!isset($request[0]) || !is_numeric($request[0])) { + echo json_encode(['error' => 'ID is required']); + exit; + } + + $id = $request[0]; + + // Prepared statement to prevent SQL injection + $stmt = $conn->prepare("DELETE FROM pokemons WHERE id = ?"); + $stmt->bind_param("i", $id); + + if ($stmt->execute()) { + echo json_encode(['id' => $id]); + } else { + error_log("Delete error: " . $conn->error); + echo json_encode(['error' => 'Failed to delete record']); + } + + $stmt->close(); + break; + + default: + echo json_encode(['error' => 'Invalid request method']); + break; +} + +$conn->close(); +?> diff --git a/school-pokedex/create_database.sql b/school-pokedex/create_database.sql new file mode 100644 index 0000000..2b1dd37 --- /dev/null +++ b/school-pokedex/create_database.sql @@ -0,0 +1,33 @@ +CREATE DATABASE IF NOT EXISTS pokedex; + +USE pokedex; + +CREATE TABLE IF NOT EXISTS pokemons ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + type VARCHAR(255) NOT NULL, + image VARCHAR(255) NOT NULL, + stats JSON NOT NULL, + info TEXT NOT NULL +); + +CREATE TABLE IF NOT EXISTS abilities ( + id INT AUTO_INCREMENT PRIMARY KEY, + pokemon_id INT NOT NULL, + ability VARCHAR(255) NOT NULL, + FOREIGN KEY (pokemon_id) REFERENCES pokemons(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS moves ( + id INT AUTO_INCREMENT PRIMARY KEY, + pokemon_id INT NOT NULL, + move VARCHAR(255) NOT NULL, + FOREIGN KEY (pokemon_id) REFERENCES pokemons(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS evolutions ( + id INT AUTO_INCREMENT PRIMARY KEY, + pokemon_id INT NOT NULL, + evolves_to VARCHAR(255) NOT NULL, + FOREIGN KEY (pokemon_id) REFERENCES pokemons(id) ON DELETE CASCADE +); diff --git a/school-pokedex/images/favicon.ico b/school-pokedex/images/favicon.ico new file mode 100644 index 0000000..06a7a43 Binary files /dev/null and b/school-pokedex/images/favicon.ico differ diff --git a/school-pokedex/index.html b/school-pokedex/index.html new file mode 100644 index 0000000..3d705c2 --- /dev/null +++ b/school-pokedex/index.html @@ -0,0 +1,15 @@ + + + + + + Pokédex + + + + +

Pokédex

+
+ + + diff --git a/school-pokedex/script.js b/school-pokedex/script.js new file mode 100644 index 0000000..9cd1121 --- /dev/null +++ b/school-pokedex/script.js @@ -0,0 +1,33 @@ +document.addEventListener('DOMContentLoaded', () => { + fetch('/school-pokedex/school-pokedex/api.php') + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.text().then(text => { + try { + return JSON.parse(text); + } catch (error) { + console.error('JSON parse error:', error, text); + throw error; + } + }); + }) + .then(pokemons => { + const pokemonList = document.getElementById('pokemon-list'); + pokemonList.innerHTML = ''; + pokemons.forEach(pokemon => { + const card = document.createElement('div'); + card.className = 'pokemon-card'; + card.innerHTML = ` + ${pokemon.name} +

${pokemon.name}

+

Type: ${pokemon.type}

+

Stats: ${JSON.stringify(pokemon.stats)}

+

Info: ${pokemon.info}

+ `; + pokemonList.appendChild(card); + }); + }) + .catch(error => console.error('Fetch error:', error)); +}); diff --git a/school-pokedex/server.js b/school-pokedex/server.js new file mode 100644 index 0000000..c3ace1e --- /dev/null +++ b/school-pokedex/server.js @@ -0,0 +1,42 @@ +const express = require('express'); +const bodyParser = require('body-parser'); +const app = express(); +const port = 3000; + +let pokemons = [ + { id: 1, name: 'Bulbasaur', type: 'Grass/Poison', image: 'https://img.pokemondb.net/artwork/bulbasaur.jpg' }, + // ...add more initial Pokémon data here... +]; + +app.use(bodyParser.json()); +app.use(express.static('school-pokedex')); + +app.get('/api/pokemons', (req, res) => { + res.json(pokemons); +}); + +app.get('/api/pokemons/:id', (req, res) => { + const pokemon = pokemons.find(p => p.id == req.params.id); + res.json(pokemon); +}); + +app.post('/api/pokemons', (req, res) => { + const newPokemon = { id: Date.now(), ...req.body }; + pokemons.push(newPokemon); + res.status(201).json(newPokemon); +}); + +app.put('/api/pokemons/:id', (req, res) => { + const index = pokemons.findIndex(p => p.id == req.params.id); + pokemons[index] = { id: parseInt(req.params.id), ...req.body }; + res.json(pokemons[index]); +}); + +app.delete('/api/pokemons/:id', (req, res) => { + pokemons = pokemons.filter(p => p.id != req.params.id); + res.status(204).end(); +}); + +app.listen(port, () => { + console.log(`Server running at http://localhost:${port}`); +}); diff --git a/school-pokedex/styles.css b/school-pokedex/styles.css new file mode 100644 index 0000000..25b6f39 --- /dev/null +++ b/school-pokedex/styles.css @@ -0,0 +1,32 @@ +body { + font-family: Arial, sans-serif; + margin: 0; + padding: 20px; + background-color: #f0f0f0; +} + +h1 { + text-align: center; +} + +#pokemon-list, #admin-pokemon-list { + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +.pokemon-card { + background-color: white; + border: 1px solid #ccc; + border-radius: 8px; + margin: 10px; + padding: 10px; + width: 200px; + text-align: center; +} + +.pokemon-card img { + max-width: 100%; + height: auto; + border-radius: 8px; +} diff --git a/school-pokedex/tutorial.md b/school-pokedex/tutorial.md new file mode 100644 index 0000000..8b648c7 --- /dev/null +++ b/school-pokedex/tutorial.md @@ -0,0 +1,61 @@ +# Pokémon Website Setup Tutorial + +Deze tutorial begeleidt je bij het opzetten en uitvoeren van de Pokémon-website en database. + +## Stap 1: Stel de MySQL-database in + +1. **Installeer XAMPP:** + - Download en installeer XAMPP van de officiële website: https://www.apachefriends.org/index.html + - Volg de installatie-instructies. + +2. **Start MySQL:** + - Open het XAMPP Configuratiescherm. + - Start de MySQL-module door op de knop "Start" naast MySQL te klikken. + +3. **Maak de database en tabellen aan:** + - Open phpMyAdmin door op de knop "Admin" naast MySQL in het XAMPP Configuratiescherm te klikken. + - Klik in phpMyAdmin op het tabblad "SQL". + - Voer het SQL-script uit om de database en tabellen aan te maken. + +## Stap 2: Stel de PHP-backend in + +1. **Installeer PHP (indien niet al geïnstalleerd met XAMPP):** + - PHP is inbegrepen bij XAMPP, dus je hoeft het niet apart te installeren. + +2. **Maak het PHP API-bestand:** + - Maak een bestand genaamd `api.php` in de map `/c:/xampp/htdocs/school-pokedex/school-pokedex`. + - Voeg de benodigde code toe om de API te maken die communiceert met de MySQL-database. + +## Stap 3: Stel de frontend in + +1. **Maak de HTML-bestanden:** + - Maak `index.html` en `admin.html` in de map `/c:/xampp/htdocs/school-pokedex/school-pokedex`. + - Voeg de benodigde HTML-code toe om de hoofdpagina en de beheerderspagina te maken. + +2. **Maak het CSS-bestand:** + - Maak een bestand genaamd `styles.css` in de map `/c:/xampp/htdocs/school-pokedex/school-pokedex`. + - Voeg de benodigde CSS-code toe om de pagina's op te maken. + +3. **Maak de JavaScript-bestanden:** + - Maak `script.js` en `admin-script.js` in de map `/c:/xampp/htdocs/school-pokedex/school-pokedex`. + - Voeg de benodigde JavaScript-code toe om de frontend te verbinden met de backend API. + +## Stap 4: Start de PHP-server + +1. **Start de ingebouwde PHP-server:** + - Open een terminal of opdrachtprompt. + - Navigeer naar de map `/c:/xampp/htdocs/school-pokedex/school-pokedex`. + - Voer het volgende commando uit om de ingebouwde PHP-server te starten: + ```sh + php -S localhost:8000 + ``` + +## Stap 5: Open de website + +1. **Open de hoofdpagina:** + - Open een webbrowser en ga naar `http://localhost:8000/index.html` om de hoofdpagina van de Pokédex te bekijken. + +2. **Open de beheerderspagina:** + - Open een webbrowser en ga naar `http://localhost:8000/admin.html` om de Pokémon te beheren. + +Je kunt nu Pokémon bekijken en beheren met de opgegeven frontend- en backend-setup. \ No newline at end of file