diff --git a/package-lock.json b/package-lock.json index d926216..b3c988d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "sniper", + "name": "webshop", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "sniper", + "name": "webshop", "version": "1.0.0", "license": "ISC", "dependencies": { @@ -15,7 +15,9 @@ "express-session": "^1.18.1", "mysql": "^2.18.1", "mysql2": "^3.12.0", - "path": "^0.12.7" + "node": "^22.15.0", + "path": "^0.12.7", + "server.js": "^1.0.0" } }, "node_modules/accepts": { @@ -674,6 +676,28 @@ "node": ">= 0.6" } }, + "node_modules/node": { + "version": "22.15.0", + "resolved": "https://registry.npmjs.org/node/-/node-22.15.0.tgz", + "integrity": "sha512-qrOEL83lNt+Jbh9pekl5xQrZK+QRJz51m2IGGCu2NENgbG6Go0D1QUBvjbejP8jB2eokQpX1AorDLbKQ/FxuYA==", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "node-bin-setup": "^1.0.0" + }, + "bin": { + "node": "bin/node" + }, + "engines": { + "npm": ">=5.0.0" + } + }, + "node_modules/node-bin-setup": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/node-bin-setup/-/node-bin-setup-1.1.3.tgz", + "integrity": "sha512-opgw9iSCAzT2+6wJOETCpeRYAQxSopqQ2z+N6BXwIMsQQ7Zj5M8MaafQY8JMlolRR6R1UXg2WmhKp0p9lSOivg==", + "license": "ISC" + }, "node_modules/object-inspect": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", @@ -894,6 +918,12 @@ "node": ">= 0.8.0" } }, + "node_modules/server.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/server.js/-/server.js-1.0.0.tgz", + "integrity": "sha512-fO4IvzkZ09bBB++XU/gWGuzxJs0OpghSd/34mlW8coMoakLzj/+W5d1pHX+I+7H52GkBKu96UQU0K5vptNjaqg==", + "license": "ISC" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", diff --git a/package.json b/package.json index a95f1e3..f34f8f5 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { - "name": "sniper", + "name": "webshop", "version": "1.0.0", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "start": "node server.js" + "start": "npm install && node server.js" }, "keywords": [], "author": "", @@ -12,13 +12,13 @@ "description": "Webshop Autohändler", "dependencies": { "app-root-path": "^3.1.0", - "dotenv": "^16.4.5", - "express": "^4.21.1", "dotenv": "^16.4.7", "express": "^4.21.2", "express-session": "^1.18.1", "mysql": "^2.18.1", "mysql2": "^3.12.0", - "path": "^0.12.7" + "node": "^22.15.0", + "path": "^0.12.7", + "server.js": "^1.0.0" } } diff --git a/public/bestellformular/bestellformular.html b/public/bestellformular/bestellformular.html index 3f353e3..793c685 100644 --- a/public/bestellformular/bestellformular.html +++ b/public/bestellformular/bestellformular.html @@ -1,54 +1,259 @@ - - - Bestellformular - - - + + + Bestellformular + + +
- -
+ +
-
-
-
-

Bestellformular

+
+
+ +

Bestellformular

- - + + - - + + - - + + - - + + - - + + - - + + - - + +
+ + + +
+
- - + + Bestellung absenden + +
+
+ + + +
diff --git a/public/bestellung/bestellung.html b/public/bestellung/bestellung.html new file mode 100644 index 0000000..0827942 --- /dev/null +++ b/public/bestellung/bestellung.html @@ -0,0 +1,104 @@ + + + + + + Ihre Bestellung + + + + + + +
+ +
+

Ihre Bestellung:

+
+ +
+

Kundennummer:

+

Produkt-ID:

+

Produktname:

+

Preis:

+
+
+
+ + + + +
+ + diff --git a/public/header_footer/header.html b/public/header_footer/header.html index b3968a6..20ec0f6 100644 --- a/public/header_footer/header.html +++ b/public/header_footer/header.html @@ -7,7 +7,7 @@
Login
- Login + 0 diff --git a/public/login/login.html b/public/login/login.html index 189bf4f..52d9e7a 100644 --- a/public/login/login.html +++ b/public/login/login.html @@ -15,17 +15,17 @@
-

Login

+

Login

- +
- +
- +

Noch keinen Account? Registrieren

@@ -33,7 +33,37 @@
- + +
diff --git a/public/registrieren/passwordValidation.js b/public/registrieren/passwordValidation.js deleted file mode 100644 index e69de29..0000000 diff --git a/public/registrieren/registrieren.html b/public/registrieren/registrieren.html index a66bfa3..e2a34b5 100644 --- a/public/registrieren/registrieren.html +++ b/public/registrieren/registrieren.html @@ -1,16 +1,16 @@ - - - - - - - Registrieren + + + + + + + Registrieren -
+
@@ -22,15 +22,15 @@

Registrieren

- +
- +
- +
@@ -44,7 +44,7 @@
- +

@@ -54,6 +54,40 @@
+
diff --git a/public/shop/shop.html b/public/shop/shop.html index 98d8e76..37ae415 100644 --- a/public/shop/shop.html +++ b/public/shop/shop.html @@ -41,6 +41,7 @@

${product.name}

Preis: ${product.price}€

${product.description}

+

Artikel Nr: ${product.id}

`; container.appendChild(card); diff --git a/public/shop/shop_lkw.html b/public/shop/shop_lkw.html index 6638048..a8b105e 100644 --- a/public/shop/shop_lkw.html +++ b/public/shop/shop_lkw.html @@ -36,15 +36,17 @@ container.innerHTML = ''; // sicherheitshalber leeren products.forEach(product => { - const card = document.createElement('div'); - card.classList.add('card'); - card.innerHTML = ` - ${product.name} -

${product.name}

-

Preis: ${product.price}€

-

${product.description}

- - `; + const card = document.createElement('div'); + card.classList.add('card'); + card.innerHTML = ` + ${product.name} +

${product.name}

+

Preis: ${product.price}€

+

${product.description}

+

Artikel Nr: ${product.id}

+ + `; + container.appendChild(card); }); }) .catch(err => { @@ -60,5 +62,8 @@ }); + +
+ \ No newline at end of file diff --git a/public/shop/shop_motorrad.html b/public/shop/shop_motorrad.html index 1f3d233..1570ecf 100644 --- a/public/shop/shop_motorrad.html +++ b/public/shop/shop_motorrad.html @@ -1,12 +1,12 @@ - - - Shop - Motorräder - - - + + + Shop - Motorräder + + +
@@ -24,28 +24,26 @@ - -
-
+ + +
+ - + \ No newline at end of file diff --git a/public/shop/shop_oldtimer.html b/public/shop/shop_oldtimer.html index b86aee5..15f6f1f 100644 --- a/public/shop/shop_oldtimer.html +++ b/public/shop/shop_oldtimer.html @@ -28,23 +28,24 @@
- - + \ No newline at end of file diff --git a/public/shop/shop_sportwagen.html b/public/shop/shop_sportwagen.html index 4bad795..97d720c 100644 --- a/public/shop/shop_sportwagen.html +++ b/public/shop/shop_sportwagen.html @@ -1,17 +1,17 @@ - - - Shop - Sportwagen - - - + + + Shop - Sportwagen + + +
- -
+ +
@@ -24,28 +24,29 @@
- -
+ +
+ diff --git a/scripts/routes/other/route-index.js b/scripts/routes/other/route-index.js index d8577e4..3edcb01 100644 --- a/scripts/routes/other/route-index.js +++ b/scripts/routes/other/route-index.js @@ -70,4 +70,8 @@ router.get('/Warenkorb', (req, res) => { router.get('/bestellformular', (req, res) => { res.sendFile(path.join(__dirname, '../../../public/bestellformular/bestellformular.html')); }) + +router.get('/bestellung', (req, res) => { + res.sendFile(path.join(__dirname, '../../../public/bestellung/bestellung.html')); +}) module.exports = router; \ No newline at end of file diff --git a/server.js b/server.js index 0619c03..59b3e21 100644 --- a/server.js +++ b/server.js @@ -3,7 +3,7 @@ const session = require('express-session'); const router = require('express').Router(); const path = require('path'); -require('dotenv').config({path:'process.env'}); +require('dotenv').config({path: 'process.env'}); const app = express(); const mysql = require('mysql'); @@ -32,7 +32,7 @@ app.use(session({ })); app.use(express.json()); -app.use(express.urlencoded({ extended: true })); +app.use(express.urlencoded({extended: true})); app.use(express.static(path.join(__dirname, '/scripts'))); app.use(express.static(path.join(__dirname, '/static'))); @@ -127,6 +127,161 @@ app.get('/api/products/sportwagen', async (req, res) => { }); }); +app.post('/api/user/registration', (req, res) => { + // SQL-Query für Nutzerregistration + const {name, lower_name, email, passwd} = req.body; + const sql = "INSERT INTO webshop.user (name, lower_name, email, passwd, passwd_hash_algo) VALUES (?, ?, ?, ?, 'none')" + + // Query abschicken + db.query(sql, [name, lower_name, email, passwd], (err, results) => { + if (err) { + console.error('Fehler beim Schreiben in die Datenbank: ', err); + res.status(500).send('Fehler beim Schreiben in die Datenbank'); + return; + } + res.status(201).json({message: 'Nutzer erfolgreich hinzugefügt', id: results.insertId}) + }) +}) + +app.post('/api/user/login', (req, res) => { + const {email, password} = req.body + const sql = 'SELECT * FROM user WHERE email = ?' + + db.query(sql, [email], (err, results) => { + if (err) { + console.error('Fehler beim Abrufen des Nutzers: ', err) + return res.status(500).json({message: 'Serverfehler'}) + } + if (results.length === 0) { + return res.status(401).json({message: 'E-Mail nicht gefunden'}) + } + const user = results[0] + + if (user.passwd !== password) { + return res.status(401).json({message: 'Falsches Passwort'}) + } + + req.session.userId = user.id; + req.session.email = user.email; + + res.json({message: 'Login erfolgreich', id: user.id}) + }) +}) + +app.post('/api/bestellung', (req, res) => { + const { user_id, produkte } = req.body; + // produkte erwartet als Array: [{product_id: 1, quantity: 2}, {product_id: 5, quantity: 1}, ...] + + if (!user_id || !Array.isArray(produkte) || produkte.length === 0) { + return res.status(400).json({ message: 'Ungültige Anfrage: user_id oder Produkte fehlen.' }); + } + + // Preise der Produkte abrufen + const productIds = produkte.map(p => p.product_id); + + const priceQuery = 'SELECT id, price FROM webshop.product WHERE id IN (?)'; + db.query(priceQuery, [productIds], (err, priceResults) => { + if (err) { + console.error('Fehler beim Abrufen der Produktpreise:', err); + return res.status(500).json({ message: 'Serverfehler beim Abrufen der Produktpreise.' }); + } + + if (priceResults.length !== productIds.length) { + return res.status(400).json({ message: 'Eines oder mehrere Produkte existieren nicht.' }); + } + + // Total berechnen + let total = 0; + produkte.forEach(p => { + const dbProduct = priceResults.find(pr => pr.id === p.product_id); + if (dbProduct) { + total += dbProduct.price * p.quantity; + } + }); + + const payment_id = 1; // Zahlungssystem-ID (z.B. 1 = Rechnung, 2 = PayPal, ...) + + const sqlOrder = 'INSERT INTO webshop.order_details (user_id, payment_id, total) VALUES (?, ?, ?)'; + db.query(sqlOrder, [user_id, payment_id, total], (err1, result1) => { + if (err1) { + console.error('Fehler beim Erstellen der Bestellung:', err1); + return res.status(500).json({ message: 'Fehler beim Erstellen der Bestellung.' }); + } + + const orderId = result1.insertId; + + const values = produkte.map(p => [user_id, p.product_id, p.quantity, orderId]); + const sqlItems = 'INSERT INTO webshop.order_items (user_id, product_id, quantity, order_id) VALUES ?'; + + db.query(sqlItems, [values], (err2, result2) => { + if (err2) { + console.error('Fehler beim Einfügen der Order-Items:', err2); + return res.status(500).json({ message: 'Fehler beim Hinzufügen der Produkte zur Bestellung.' }); + } + + res.status(201).json({ message: 'Bestellung erfolgreich!', order_id: orderId, total: total.toFixed(2) }); + }); + }); + }); +}); + +app.post('/api/bestellung/daten', (req, res) => { + const { user_id } = req.body; + + const sql = ` + SELECT + od.id AS order_id, + od.total AS order_total, + oi.product_id, + oi.quantity, + p.name AS product_name, + p.price AS product_price + FROM + webshop.order_details od + INNER JOIN + webshop.order_items oi ON od.id = oi.order_id + INNER JOIN + webshop.product p ON oi.product_id = p.id + WHERE + od.user_id = ? + ORDER BY + od.id DESC + `; + + db.query(sql, [user_id], (err, results) => { + if (err) { + console.error('Fehler beim Abrufen der Bestellungen: ', err); + return res.status(500).json({ message: 'Fehler beim Abrufen der Bestellungen' }); + } + + if (results.length === 0) { + return res.status(404).json({ message: 'Keine Bestellungen gefunden.' }); + } + + res.json(results); + }); +}); + +app.get('/api/pruefe-artikel', (req, res) => { + const artikelnummer = req.query.nummer; + + if (!artikelnummer) { + return res.status(400).json({ error: 'Keine Artikelnummer angegeben.' }); + } + + const query = 'SELECT id FROM product WHERE id = ?'; + + db.query(query, [artikelnummer], (err, results) => { + if (err) { + console.error('Fehler bei der Artikelsuche:', err); + return res.status(500).json({ error: 'Serverfehler bei der Artikelsuche.' }); + } + + const verfuegbar = results.length > 0; + res.json({ verfuegbar }); + }); +}); + const getIndexRoute = require('./scripts/routes/other/route-index'); app.use('/', getIndexRoute); diff --git a/static/Styles/bestellformular/bestellformular.css b/static/Styles/bestellformular/bestellformular.css index a252b41..e19c126 100644 --- a/static/Styles/bestellformular/bestellformular.css +++ b/static/Styles/bestellformular/bestellformular.css @@ -9,7 +9,7 @@ body { } .wrapper { - flex: 1; /* Der Hauptinhalt (Formular) nimmt den verfügbaren Platz ein */ + flex: 1; /* Der Hauptinhalt nimmt den verfügbaren Platz ein */ } .form-container { @@ -43,20 +43,22 @@ textarea { box-sizing: border-box; } -input[type="submit"] { +/* NEU: Styling für den Absende-Link */ +.button-submit { + display: inline-block; margin-top: 20px; background-color: #ff6600; color: white; - border: none; + text-decoration: none; padding: 12px; border-radius: 5px; font-size: 16px; cursor: pointer; width: 100%; + text-align: center; + box-sizing: border-box; /* Damit Breite + Padding sauber passen */ } -input[type="submit"]:hover { - background-color: #ff5500; /* Ein leicht dunklerer Farbton beim Hover */ +.button-submit:hover { + background-color: #ff6600; } - - diff --git a/static/Styles/bestellung/bestellung.css b/static/Styles/bestellung/bestellung.css new file mode 100644 index 0000000..849719f --- /dev/null +++ b/static/Styles/bestellung/bestellung.css @@ -0,0 +1,49 @@ +/* Allgemeine Layout-Stile */ +body { + font-family: Arial, sans-serif; + background-color: #f2f2f2; + padding: 20px; + margin: 0; + display: flex; + flex-direction: column; + min-height: 100vh; +} + +/* Container für die Bestellinformationen */ +#bestellung { + background-color: #fff; + padding: 20px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + margin-top: 20px; +} + +/* Titel */ +h2 { + text-align: center; + margin-bottom: 30px; + margin-top: 20px; +} + +/* Karte für Bestellinformationen */ +.bestell-info-card { + background-color: #fafafa; + padding: 15px; + border-radius: 8px; + margin-bottom: 15px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); +} + +/* Bestellinformationen formatieren */ +.bestell-info-card p { + font-size: 16px; + margin: 10px 0; +} + +/* Stile für die Label und Platzhalter */ +.bestell-info-card span { + font-weight: bold; + color: #333; +} + +