diff --git a/.idea/Webshop.iml b/.idea/Webshop.iml index 8b332b7..018ea30 100644 --- a/.idea/Webshop.iml +++ b/.idea/Webshop.iml @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml index 935ffdb..35b7183 100644 --- a/.idea/dataSources.xml +++ b/.idea/dataSources.xml @@ -2,14 +2,12 @@ - mysql.8 + mariadb true - com.mysql.cj.jdbc.Driver - jdbc:mysql://localhost:3306 + org.mariadb.jdbc.Driver + jdbc:mariadb://localhost:3306 - - $ProjectFileDir$ diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml index 2f279b3..93218c2 100644 --- a/.idea/jsLibraryMappings.xml +++ b/.idea/jsLibraryMappings.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8ccc96d..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": { @@ -597,6 +599,7 @@ "version": "2.18.1", "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "license": "MIT", "dependencies": { "bignumber.js": "9.0.0", "readable-stream": "2.3.7", @@ -673,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", @@ -893,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/404.html b/public/404.html new file mode 100644 index 0000000..0d4597b --- /dev/null +++ b/public/404.html @@ -0,0 +1,27 @@ + + + + + + Seite nicht gefunden + + + + + +
+ +
+ +
+

đźš§ Seite nicht gefunden đźš§

+

Diese Seite existiert nicht oder befindet sich noch in Arbeit.

+ Zur Startseite +
+ + + + +
+ + \ No newline at end of file diff --git a/public/Warenkorb/warenkorb.html b/public/Warenkorb/warenkorb.html index 1a51dd8..762972d 100644 --- a/public/Warenkorb/warenkorb.html +++ b/public/Warenkorb/warenkorb.html @@ -4,8 +4,12 @@ Warenkorb + + + +

đź›’ Dein Warenkorb

@@ -26,8 +30,9 @@
- - +
+ + diff --git a/public/bestellformular/bestellformular.html b/public/bestellformular/bestellformular.html new file mode 100644 index 0000000..793c685 --- /dev/null +++ b/public/bestellformular/bestellformular.html @@ -0,0 +1,259 @@ + + + + + + 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/footer.html b/public/header_footer/footer.html new file mode 100644 index 0000000..4ab756a --- /dev/null +++ b/public/header_footer/footer.html @@ -0,0 +1,8 @@ + +
+

© 2025 Autohändler Webshop – Alle Rechte vorbehalten

+

+ Impressum | + Datenschutz +

+
diff --git a/public/header_footer/header.html b/public/header_footer/header.html new file mode 100644 index 0000000..20ec0f6 --- /dev/null +++ b/public/header_footer/header.html @@ -0,0 +1,34 @@ + +
+
+ Modellauto-Shop Logo +

Modellauto - Shop

+
+
+ +
+ + + + 0 + +
+
+
+ + diff --git a/public/login/login.html b/public/login/login.html index 3a14541..52d9e7a 100644 --- a/public/login/login.html +++ b/public/login/login.html @@ -4,30 +4,67 @@ + + Login -
-
-

Login

-
- - -
-
- - -
+ +
- +
+ +
+ + + + - - -
- diff --git a/public/registrieren/passwordValidation.js b/public/registrieren/passwordValidation.js deleted file mode 100644 index 3a6fbc2..0000000 --- a/public/registrieren/passwordValidation.js +++ /dev/null @@ -1,45 +0,0 @@ -// Funktion, um die Stärke des Passworts zu bewerten -function checkPasswordStrength(password) { - const strengthBar = document.getElementById('passwordStrengthBar'); - const passwordStrength = evaluatePasswordStrength(password); - - // Aktualisiere den Sicherheitsbalken basierend auf der Stärke - if (passwordStrength === 'weak') { - strengthBar.classList.remove('medium', 'strong'); - strengthBar.classList.add('weak'); - } else if (passwordStrength === 'medium') { - strengthBar.classList.remove('weak', 'strong'); - strengthBar.classList.add('medium'); - } else { - strengthBar.classList.remove('weak', 'medium'); - strengthBar.classList.add('strong'); - } -} - -// Funktion zur Beurteilung der Passwortstärke -function evaluatePasswordStrength(password) { - if (password.length >= 8 && /[A-Z]/.test(password) && /[0-9]/.test(password)) { - return 'strong'; - } else if (password.length >= 6) { - return 'medium'; - } else { - return 'weak'; - } -} - -// Event Listener für das Passwortfeld -document.getElementById('regPassword').addEventListener('input', function() { - checkPasswordStrength(this.value); -}); - -// Event Listener für das Bestätigungs-Passwortfeld -document.getElementById('confirmPassword').addEventListener('input', function() { - const password = document.getElementById('regPassword').value; - const confirmPassword = this.value; - - if (password !== confirmPassword) { - this.setCustomValidity("Die Passwörter stimmen nicht überein."); - } else { - this.setCustomValidity(""); - } -}); diff --git a/public/registrieren/registrieren.html b/public/registrieren/registrieren.html index f95b594..e2a34b5 100644 --- a/public/registrieren/registrieren.html +++ b/public/registrieren/registrieren.html @@ -4,48 +4,93 @@ + + Registrieren -
-
-

Registrieren

+
-
- - -
-
- - -
-
- - -
-
- - -
+ +
-
- - -
+ +
+
+ +

Registrieren

- -
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
- + + + + +
+
+ + + + - -
- diff --git a/public/shop/shop.html b/public/shop/shop.html new file mode 100644 index 0000000..37ae415 --- /dev/null +++ b/public/shop/shop.html @@ -0,0 +1,62 @@ + + + + + + Shop + + + + + + +
+ + +
+

Willkommen im Webshop

+
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/public/shop/shop_lkw.html b/public/shop/shop_lkw.html new file mode 100644 index 0000000..a8b105e --- /dev/null +++ b/public/shop/shop_lkw.html @@ -0,0 +1,69 @@ + + + + + + Shop - LKW's + + + + + +
+ +
+ + +
+
+

Unsere LKW Produkte

+
+ +
+ +
+
+ + + +
+ + + + + + + + \ No newline at end of file diff --git a/public/shop/shop_motorrad.html b/public/shop/shop_motorrad.html new file mode 100644 index 0000000..1570ecf --- /dev/null +++ b/public/shop/shop_motorrad.html @@ -0,0 +1,64 @@ + + + + + + Shop - Motorräder + + + + + +
+ +
+ + +
+
+

Unsere Motorrad Produkte

+
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/public/shop/shop_oldtimer.html b/public/shop/shop_oldtimer.html new file mode 100644 index 0000000..15f6f1f --- /dev/null +++ b/public/shop/shop_oldtimer.html @@ -0,0 +1,63 @@ + + + + + + Shop - Oldtimer + + + + + +
+ +
+ + +
+
+

Unsere Oldtimer Produkte

+
+ +
+ +
+
+ + + +
+ + + + \ No newline at end of file diff --git a/public/shop/shop_sportwagen.html b/public/shop/shop_sportwagen.html new file mode 100644 index 0000000..97d720c --- /dev/null +++ b/public/shop/shop_sportwagen.html @@ -0,0 +1,66 @@ + + + + + + Shop - Sportwagen + + + + + +
+ +
+ + +
+
+

Unsere Sportwagen Produkte

+
+ +
+ +
+
+ + + +
+ + + + + diff --git a/public/startseite/startseite.html b/public/startseite/startseite.html index 7e443f4..93f859d 100644 --- a/public/startseite/startseite.html +++ b/public/startseite/startseite.html @@ -3,85 +3,98 @@ - Autohändler Webshop - + Modellauto - Startseite + + - -
- -
-

Autohändler Webshop

- -
+
+ +
- - +
+ +
+

Willkommen beim Modellauto-Shop

+

Bei uns finden Sie hochwertige Modellautos – ob Oldtimer, Sportwagen, Lkw's oder Motorräder. + Perfekt für Sammler, Bastler und Fans. +

+
- -
- + +

Unsere Neusten Produkte:

+
+ +
+ + + + + + +
+
+ +

Versandkostenfrei ab 50€

+

Schneller & sicherer Versand mit Sendungsverfolgung.

+
+
+ +

Flexible Zahlungsmethoden

+

PayPal, Kreditkarte, Klarna, Vorkasse – Sie haben die Wahl.

+
+
+ +

14 Tage RĂĽckgaberecht

+

Unzufrieden? Kein Problem – Rückgabe einfach & unkompliziert.

+
+
+ +

Top-Bewertungen

+

Unsere Kunden lieben uns – überzeugen Sie sich selbst!

+
+
+
+ + + -
-
- Auto -

BMW 3er Limousine

-

Preis: 35.000€

-

Baujahr: 2020 | Kilometerstand: 20.000 km

- -
-
- Auto -

Audi Q5

-

Preis: 50.000€

-

Baujahr: 2022 | Kilometerstand: 10.000 km

- -
-
-
- - - diff --git a/scripts/einfĂĽgenHeaderFooter.js b/scripts/einfĂĽgenHeaderFooter.js new file mode 100644 index 0000000..08ad09d --- /dev/null +++ b/scripts/einfĂĽgenHeaderFooter.js @@ -0,0 +1,41 @@ +document.addEventListener("DOMContentLoaded", () => { + // Header laden + const headerTarget = document.getElementById("header-placeholder"); + if (headerTarget) { + fetch("/header") + .then(response => { + if (!response.ok) throw new Error("Header nicht gefunden"); + return response.text(); + }) + .then(data => { + headerTarget.innerHTML = data; + }) + .catch(error => { + headerTarget.innerHTML = ` +
+ Fehler beim Laden des Headers. +
`; + console.error(error); + }); + } + + // Footer laden + const footerTarget = document.getElementById("footer"); + if (footerTarget) { + fetch("/footer") + .then(response => { + if (!response.ok) throw new Error("Footer nicht gefunden"); + return response.text(); + }) + .then(data => { + footerTarget.innerHTML = data; + }) + .catch(error => { + footerTarget.innerHTML = ` +
+ Fehler beim Laden der FuĂźzeile. +
`; + console.error(error); + }); + } +}); diff --git a/scripts/routes/other/route-index.js b/scripts/routes/other/route-index.js index 1d6c308..3edcb01 100644 --- a/scripts/routes/other/route-index.js +++ b/scripts/routes/other/route-index.js @@ -1,6 +1,7 @@ const path = require('path'); const router = require('express').Router(); +// Route - Startseite router.get('/', (req, res) => { res.sendFile(path.join(__dirname, '../../../public/startseite/startseite.html')); }) @@ -9,15 +10,68 @@ router.get('/example', (req, res) => { res.sendFile(path.join(__dirname, '../../../public/example/index.html')); }) +// Route - Login router.get('/login', (req, res) => { res.sendFile(path.join(__dirname, '../../../public/login/login.html')); }) +// Route - Registrieren router.get('/registrieren', (req, res) => { res.sendFile(path.join(__dirname, '../../../public/registrieren/registrieren.html')); }) +// Route - HeaderFooter +router.get('/header_footer', (req, res) => { + res.sendFile(path.join(__dirname, '../../../scripts/einfĂĽgenHeaderFooter.js')); +}) + + // Route - Kopfzeile + router.get('/header', (req, res) => { + res.sendFile(path.join(__dirname, '../../../public/header_footer/header.html')); + }) + + // Route - FuĂźzeile + router.get('/footer', (req, res) => { + res.sendFile(path.join(__dirname, '../../../public/header_footer/footer.html')); + }) + +// Route - Shop (Alle Produkte) +router.get('/shop', (req, res) => { + res.sendFile(path.join(__dirname, '../../../public/shop/shop.html')); +}) + + // Route - Shop_Motorrad (Filtern nach Motorrad Produkten) + router.get('/shop/motorrad', (req, res) => { + res.sendFile(path.join(__dirname, '../../../public/shop/shop_motorrad.html')); + }) + + // Route - Shop_Oldtimer (Filtern nach Oldtimer Produkten) + router.get('/shop/oldtimer', (req, res) => { + res.sendFile(path.join(__dirname, '../../../public/shop/shop_oldtimer.html')); + }) + + // Route - Shop_Sportwagen (Filtern nach Sportwagen Produkten) + router.get('/shop/sportwagen', (req, res) => { + res.sendFile(path.join(__dirname, '../../../public/shop/shop_sportwagen.html')); + }) + + // Route - Shop_LKW (Filtern nach LKW Produkten) + router.get('/shop/lkw', (req, res) => { + res.sendFile(path.join(__dirname, '../../../public/shop/shop_lkw.html')); + }) + + router.get('/bestellformular', (req, res) => { + res.sendFile(path.join(__dirname, '../../../public/bestellformular/bestellformular.html')); + }) router.get('/Warenkorb', (req, res) => { res.sendFile(path.join(__dirname, '../../../public/warenkorb/warenkorb.html')); }) + +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 05079f0..59b3e21 100644 --- a/server.js +++ b/server.js @@ -3,9 +3,27 @@ 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'); + +// Datenbankverbindung +const db = mysql.createConnection({ + host: 'localhost', + user: 'root', + password: '', + database: 'webshop' +}); + +// Verbindung zur MySQL-Datenbank herstellen +db.connect(err => { + if (err) { + console.error('Fehler beim Verbinden zur Datenbank:', err); + return; + } + console.log('Mit der Datenbank verbunden'); +}); app.use(session({ secret: 'secret', @@ -14,14 +32,264 @@ 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'))); -const getIndexRoute = require('./scripts/routes/other/route-index'); +// API-Route fĂĽr Produkte +app.get('/api/products', (req, res) => { + // SQL-Abfrage fĂĽr Produktdaten + const sql = 'SELECT * FROM webshop.product'; + // Abfrage ausfĂĽhren + db.query(sql, (err, results) => { + if (err) { + console.error('Fehler beim Abrufen der Produkte:', err); + res.status(500).send('Fehler beim Abrufen der Produkte'); + return; + } + res.json(results); // RĂĽckgabe der Produktdaten als JSON + }); +}); + +app.get('/api/products/new', async (req, res) => { + // SQL-Abfrage fĂĽr Produktdaten + const sql = 'SELECT * FROM webshop.product ORDER BY created_at DESC LIMIT 4'; + + // Abfrage ausfĂĽhren + db.query(sql, (err, results) => { + if (err) { + console.error('Fehler beim Abrufen der Produkte:', err); + res.status(500).send('Fehler beim Abrufen der Produkte'); + return; + } + res.json(results); // RĂĽckgabe der Produktdaten als JSON + }); +}); + +app.get('/api/products/motorrad', async (req, res) => { + // SQL-Abfrage fĂĽr Produktdaten + const sql = 'SELECT * FROM webshop.product WHERE category_id = 4'; + + // Abfrage ausfĂĽhren + db.query(sql, (err, results) => { + if (err) { + console.error('Fehler beim Abrufen der Produkte:', err); + res.status(500).send('Fehler beim Abrufen der Produkte'); + return; + } + res.json(results); // RĂĽckgabe der Produktdaten als JSON + }); +}); + +app.get('/api/products/oldtimer', async (req, res) => { + // SQL-Abfrage fĂĽr Produktdaten + const sql = 'SELECT * FROM webshop.product WHERE category_id = 2'; + + // Abfrage ausfĂĽhren + db.query(sql, (err, results) => { + if (err) { + console.error('Fehler beim Abrufen der Produkte:', err); + res.status(500).send('Fehler beim Abrufen der Produkte'); + return; + } + res.json(results); // RĂĽckgabe der Produktdaten als JSON + }); +}); + +app.get('/api/products/lkw', async (req, res) => { + // SQL-Abfrage fĂĽr Produktdaten + const sql = 'SELECT * FROM webshop.product WHERE category_id = 3'; + + // Abfrage ausfĂĽhren + db.query(sql, (err, results) => { + if (err) { + console.error('Fehler beim Abrufen der Produkte:', err); + res.status(500).send('Fehler beim Abrufen der Produkte'); + return; + } + res.json(results); // RĂĽckgabe der Produktdaten als JSON + }); +}); + +app.get('/api/products/sportwagen', async (req, res) => { + // SQL-Abfrage fĂĽr Produktdaten + const sql = 'SELECT * FROM webshop.product WHERE category_id = 1'; + + // Abfrage ausfĂĽhren + db.query(sql, (err, results) => { + if (err) { + console.error('Fehler beim Abrufen der Produkte:', err); + res.status(500).send('Fehler beim Abrufen der Produkte'); + return; + } + res.json(results); // RĂĽckgabe der Produktdaten als JSON + }); +}); + +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); +app.use((req, res) => { + res.status(404).sendFile(path.join(__dirname, 'public', '404.html')); +}); + +// Sever starten app.listen(process.env.APP_PORT, () => { console.log("\x1b[32m"); console.log(`Server is running on http://localhost:${process.env.APP_PORT}`); diff --git a/static/Styles/Warenkorb/warenkorb.css b/static/Styles/Warenkorb/warenkorb.css index b1209d4..43ae701 100644 --- a/static/Styles/Warenkorb/warenkorb.css +++ b/static/Styles/Warenkorb/warenkorb.css @@ -6,7 +6,7 @@ body { } .warenkorb { - max-width: 500px; + max-width: 700px; margin: 0 auto; background: white; padding: 120px; @@ -43,7 +43,7 @@ body { } .remove { - background-color: #ff4d4f; + background-color: #ff6600; border: none; color: white; padding: 6px 12px; @@ -52,7 +52,7 @@ body { } .remove:hover { - background-color: #e60000; + background-color: #ff6600; } .summary { @@ -65,7 +65,7 @@ body { display: block; width: 100%; padding: 12px; - background-color: #4CAF50; + background-color: #ff6600; border: none; color: white; font-size: 16px; @@ -75,5 +75,90 @@ body { } .checkout:hover { - background-color: #45a049; + background-color: #ff6600; } + +.checkout { + display: inline-block; + background-color: #ff6600; + color: white; + padding: 10px 20px; + margin-top: 20px; + text-align: center; + text-decoration: none; + font-size: 16px; + border-radius: 5px; + transition: background-color 0.3s; +} + +body { + font-family: Arial, sans-serif; + background-color: #f2f2f2; + padding: 20px; +} + +.form-container { + max-width: 600px; + margin: auto; + background-color: #ffffff; + padding: 25px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0,0,0,0.1); +} + +form h2 { + text-align: center; + margin-bottom: 20px; +} + +label { + display: block; + margin-top: 15px; + font-weight: bold; +} + +input[type="text"], +input[type="tel"], +textarea { + width: 100%; + padding: 10px; + margin-top: 5px; + border: 1px solid #ccc; + border-radius: 4px; + box-sizing: border-box; +} + +input[type="submit"] { + margin-top: 20px; + background-color: #ff6600; + color: white; + border: none; + padding: 12px; + border-radius: 5px; + font-size: 16px; + cursor: pointer; + width: 100%; +} + +input[type="submit"]:hover { + background-color: #ff6600; +} + +.zurKasse { + display: block; + margin: 20px auto; + background-color: #ff6600; + color: white; + border: none; + padding: 12px 24px; + font-size: 16px; + border-radius: 8px; + cursor: pointer; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); +} + +.zurKasse:hover { + background-color: #ff6600; +} + + diff --git a/static/Styles/bestellformular/bestellformular.css b/static/Styles/bestellformular/bestellformular.css new file mode 100644 index 0000000..e19c126 --- /dev/null +++ b/static/Styles/bestellformular/bestellformular.css @@ -0,0 +1,64 @@ +body { + font-family: Arial, sans-serif; + background-color: #f2f2f2; + padding: 20px; + margin: 0; + display: flex; + flex-direction: column; + min-height: 100vh; +} + +.wrapper { + flex: 1; /* Der Hauptinhalt nimmt den verfĂĽgbaren Platz ein */ +} + +.form-container { + max-width: 600px; + margin: 20px auto; + background-color: #f5f5f5; + padding: 25px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0,0,0,0.1); +} + +form h2 { + text-align: center; + margin-bottom: 20px; +} + +label { + display: block; + margin-top: 15px; + font-weight: bold; +} + +input[type="text"], +input[type="tel"], +textarea { + width: 100%; + padding: 10px; + margin-top: 5px; + border: 1px solid #ccc; + border-radius: 4px; + box-sizing: border-box; +} + +/* NEU: Styling fĂĽr den Absende-Link */ +.button-submit { + display: inline-block; + margin-top: 20px; + background-color: #ff6600; + color: white; + 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 */ +} + +.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; +} + + diff --git a/static/Styles/example.css b/static/Styles/example.css deleted file mode 100644 index d9450fe..0000000 --- a/static/Styles/example.css +++ /dev/null @@ -1,234 +0,0 @@ -/* Allgemeine Einstellungen */ -* { - margin: 0; - padding: 0; - box-sizing: border-box; - font-family: "Poppins", sans-serif; -} - -body { - background: #f8f9fa; - color: #333; - min-height: 100vh; - display: flex; - flex-direction: column; -} - -/* Header */ -header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 15px 20px; - width: 100%; - background: #ffffff; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - position: sticky; - top: 0; - z-index: 1000; -} - -header h1 { - font-size: 28px; - color: #333; -} - -.header-right { - display: flex; - align-items: center; - gap: 15px; -} - -header .login-btn { - font-size: 14px; - text-decoration: none; - color: white; - background: #ff6600; - padding: 10px 20px; - border-radius: 25px; - transition: background 0.3s ease; -} - -header .login-btn:hover { - background: #e95b00; -} - -.cart { - display: flex; - align-items: center; - position: relative; - font-size: 24px; - color: #ff6600; - cursor: pointer; -} - -.cart-count { - position: absolute; - top: -5px; - right: -10px; - background: #ff6600; - color: white; - font-size: 12px; - width: 20px; - height: 20px; - border-radius: 50%; - display: flex; - justify-content: center; - align-items: center; -} - -/* Navigation */ -.menu { - background: #ffffff; - width: 100%; - margin-bottom: 20px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); -} - -.menu-list { - list-style: none; - display: flex; - justify-content: space-around; - padding: 15px 0; -} - -.menu-item { - position: relative; -} - -.menu-item a { - text-decoration: none; - color: #333; - font-size: 18px; - padding: 10px 20px; - transition: background 0.3s ease, color 0.3s ease; -} - -.menu-item a:hover { - background: #ff6600; - color: white; - border-radius: 10px; -} - -/* Submenu */ -.submenu { - position: absolute; - top: 100%; - left: 0; - background: #ffffff; - border-radius: 10px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - display: none; - list-style: none; - min-width: 200px; - z-index: 10; -} - -.submenu li { - padding: 10px 20px; -} - -.submenu li a { - color: #333; -} - -.submenu li a:hover { - color: white; - background: #ff6600; - border-radius: 5px; -} - -.menu-item:hover .submenu { - display: block; -} - -/* Suchleiste */ -.search-bar { - display: flex; - gap: 15px; - width: 100%; - padding: 20px; - background: #ffffff; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - position: sticky; - top: 65px; - z-index: 1000; -} - -.search-bar input, -.search-bar select { - padding: 12px; - font-size: 16px; - border: 1px solid #ddd; - border-radius: 5px; - flex: 1; -} - -.search-bar button { - padding: 12px 20px; - background: #ff6600; - color: white; - border: none; - border-radius: 5px; - cursor: pointer; - transition: background 0.3s ease; -} - -.search-bar button:hover { - background: #e95b00; -} - -/* Karten */ -.card-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); - gap: 20px; - width: 100%; - padding: 20px; -} - -.card { - background: #ffffff; - border-radius: 10px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - text-align: center; - padding: 20px; - height: 100%; - display: flex; - flex-direction: column; - justify-content: space-between; -} - -.card img { - max-width: 100%; - height: auto; - border-radius: 10px; - margin-bottom: 10px; -} - -.card h3 { - font-size: 20px; - color: #333; - margin: 10px 0; -} - -.card p { - font-size: 14px; - color: #666; - margin: 5px 0; -} - -.add-to-cart { - background: #ff6600; - color: white; - border: none; - padding: 12px 20px; - border-radius: 25px; - margin-top: 10px; - cursor: pointer; - transition: background 0.3s ease; -} - -.add-to-cart:hover { - background: #e95b00; -} diff --git a/static/Styles/login/login.css b/static/Styles/login/login.css index 7ff8038..8eae58a 100644 --- a/static/Styles/login/login.css +++ b/static/Styles/login/login.css @@ -1,109 +1,61 @@ -/* Allgemeine Einstellungen */ -* { - margin: 0; - padding: 0; - box-sizing: border-box; - font-family: "Poppins", sans-serif; -} - -body { - background: #f8f9fa; - color: #333; - min-height: 100vh; - display: flex; - justify-content: center; - align-items: center; -} - -/* Wrapper */ -.wrapper { - background: #ffffff; - padding: 40px; - border-radius: 10px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - max-width: 400px; +.login-container { + background-color: #fff; + padding: 40px 30px; + border-radius: 16px; + box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1); width: 100%; -} - -h1 { - font-size: 24px; + max-width: 400px; text-align: center; - color: #333; - margin-bottom: 20px; + margin: 50px auto; /* Zentriert das Formular */ } -/* Input-Box */ -.input-box { +.login-form .input-group { position: relative; margin-bottom: 20px; } -.input-box input { +.login-form input { width: 100%; - padding: 12px 40px 12px 15px; + padding: 12px 15px 12px 15px; border: 1px solid #ddd; - border-radius: 5px; + border-radius: 8px; font-size: 16px; - color: #333; + outline: none; } -/* Styling fĂĽr das Schloss-Icon */ -.input-box i { - position: absolute; - top: 50%; - right: 15px; - transform: translateY(-50%); - color: #888; - font-size: 20px; - cursor: pointer; +.login-form .icon { + display: none; } -/* Remember and Forgot */ -.remember-forgot { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 20px; - font-size: 14px; -} - -.remember-forgot a { - color: #ff6600; - text-decoration: none; -} - -.remember-forgot a:hover { - text-decoration: underline; -} - -/* Button */ -.btn { +.login-btn { width: 100%; - padding: 12px 20px; + padding: 12px; background: #ff6600; color: white; border: none; - border-radius: 5px; + border-radius: 25px; font-size: 16px; + font-weight: 600; cursor: pointer; transition: background 0.3s ease; } -.btn:hover { +.login-btn:hover { background: #e95b00; } -/* Register-Link */ -.register-link { - text-align: center; +.register-text { + margin-top: 20px; font-size: 14px; + color: #555; } -.register-link a { +.register-text a { color: #ff6600; text-decoration: none; + font-weight: 500; } -.register-link a:hover { +.register-text a:hover { text-decoration: underline; -} \ No newline at end of file +} diff --git a/static/Styles/registrieren/registrieren.css b/static/Styles/registrieren/registrieren.css index 1027480..de4ccbb 100644 --- a/static/Styles/registrieren/registrieren.css +++ b/static/Styles/registrieren/registrieren.css @@ -1,103 +1,72 @@ -/* Allgemeine Einstellungen */ -* { - margin: 0; - padding: 0; - box-sizing: border-box; - font-family: "Poppins", sans-serif; -} - -body { - background: #f8f9fa; - color: #333; - min-height: 100vh; +.page-container { display: flex; flex-direction: column; + min-height: 100vh; } -/* Wrapper fĂĽr das Formular */ -.wrapper { - width: 100%; +.register-wrapper { max-width: 400px; - margin: 50px auto; - padding: 20px; - background: #fff; - border-radius: 10px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + width: 100%; + padding: 30px; + background-color: #ffffff; + border: 1px solid #ddd; + border-radius: 12px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); } -h1 { +.content-wrapper { + flex: 1; + display: flex; + justify-content: center; + align-items: center; + padding: 40px 20px; +} + +.registration-container { + max-width: 400px; + margin: 60px auto; + padding: 30px; + background-color: #ffffff; + border: 1px solid #ddd; + border-radius: 12px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); +} + +.registration-container h2 { text-align: center; margin-bottom: 20px; - color: #333; + font-size: 1.8em; } -/* Eingabefelder */ -.input-box { - position: relative; - margin-bottom: 20px; -} - -/* Textfelder */ -.input-box input { +.registration-container input[type="text"], +.registration-container input[type="email"], +.registration-container input[type="password"] { width: 100%; - padding: 12px 15px; - font-size: 16px; - border: 1px solid #ddd; - border-radius: 5px; - outline: none; - padding-left: 40px; /* Platz fĂĽr das Icon */ + padding: 10px 12px; + margin-bottom: 15px; + border: 1px solid #ccc; + border-radius: 8px; + font-size: 1em; + box-sizing: border-box; } -/* Positionierung der Icons */ -.input-box i { - position: absolute; - top: 50%; - left: 10px; - transform: translateY(-50%); - font-size: 18px; - color: #888; +.register-link { + text-align: center; + font-size: 14px; + margin-top: 15px; } -/* Passwortfeld */ -.input-box input[type="password"] { - padding-right: 40px; /* Platz fĂĽr das Passwort-Symbol rechts */ +.register-link a { + color: #ff6600; + text-decoration: none; + font-weight: 500; } -/* Positionierung des Passwort-Symbols */ -#toggleRegPassword { - position: absolute; - top: 50%; - right: 10px; - transform: translateY(-50%); - font-size: 18px; - color: #888; - cursor: pointer; +.register-link a:hover { + text-decoration: underline; } -/* Passwort Sicherheitsbalken */ -.password-strength-bar { - width: 100%; - height: 5px; - background-color: #ddd; - border-radius: 5px; - margin-top: 10px; -} - -/* Sicherheitsstufen */ -.password-strength-bar.weak { - background-color: #f44336; /* Rot fĂĽr schwach */ -} - -.password-strength-bar.medium { - background-color: #ff9800; /* Orange fĂĽr mittel */ -} - -.password-strength-bar.strong { - background-color: #4caf50; /* GrĂĽn fĂĽr stark */ -} - -/* Button */ -.btn { +.register-btn { width: 100%; padding: 12px; background: #ff6600; @@ -105,25 +74,8 @@ h1 { border: none; border-radius: 25px; font-size: 16px; + font-weight: 600; cursor: pointer; transition: background 0.3s ease; } -.btn:hover { - background: #e95b00; -} - -/* Registrierung-Link */ -.register-link { - text-align: center; - margin-top: 20px; -} - -.register-link a { - text-decoration: none; - color: #ff6600; -} - -.register-link a:hover { - color: #e95b00; -} diff --git a/static/Styles/startseite/startseite.css b/static/Styles/startseite/startseite.css deleted file mode 100644 index d9450fe..0000000 --- a/static/Styles/startseite/startseite.css +++ /dev/null @@ -1,234 +0,0 @@ -/* Allgemeine Einstellungen */ -* { - margin: 0; - padding: 0; - box-sizing: border-box; - font-family: "Poppins", sans-serif; -} - -body { - background: #f8f9fa; - color: #333; - min-height: 100vh; - display: flex; - flex-direction: column; -} - -/* Header */ -header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 15px 20px; - width: 100%; - background: #ffffff; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - position: sticky; - top: 0; - z-index: 1000; -} - -header h1 { - font-size: 28px; - color: #333; -} - -.header-right { - display: flex; - align-items: center; - gap: 15px; -} - -header .login-btn { - font-size: 14px; - text-decoration: none; - color: white; - background: #ff6600; - padding: 10px 20px; - border-radius: 25px; - transition: background 0.3s ease; -} - -header .login-btn:hover { - background: #e95b00; -} - -.cart { - display: flex; - align-items: center; - position: relative; - font-size: 24px; - color: #ff6600; - cursor: pointer; -} - -.cart-count { - position: absolute; - top: -5px; - right: -10px; - background: #ff6600; - color: white; - font-size: 12px; - width: 20px; - height: 20px; - border-radius: 50%; - display: flex; - justify-content: center; - align-items: center; -} - -/* Navigation */ -.menu { - background: #ffffff; - width: 100%; - margin-bottom: 20px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); -} - -.menu-list { - list-style: none; - display: flex; - justify-content: space-around; - padding: 15px 0; -} - -.menu-item { - position: relative; -} - -.menu-item a { - text-decoration: none; - color: #333; - font-size: 18px; - padding: 10px 20px; - transition: background 0.3s ease, color 0.3s ease; -} - -.menu-item a:hover { - background: #ff6600; - color: white; - border-radius: 10px; -} - -/* Submenu */ -.submenu { - position: absolute; - top: 100%; - left: 0; - background: #ffffff; - border-radius: 10px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - display: none; - list-style: none; - min-width: 200px; - z-index: 10; -} - -.submenu li { - padding: 10px 20px; -} - -.submenu li a { - color: #333; -} - -.submenu li a:hover { - color: white; - background: #ff6600; - border-radius: 5px; -} - -.menu-item:hover .submenu { - display: block; -} - -/* Suchleiste */ -.search-bar { - display: flex; - gap: 15px; - width: 100%; - padding: 20px; - background: #ffffff; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - position: sticky; - top: 65px; - z-index: 1000; -} - -.search-bar input, -.search-bar select { - padding: 12px; - font-size: 16px; - border: 1px solid #ddd; - border-radius: 5px; - flex: 1; -} - -.search-bar button { - padding: 12px 20px; - background: #ff6600; - color: white; - border: none; - border-radius: 5px; - cursor: pointer; - transition: background 0.3s ease; -} - -.search-bar button:hover { - background: #e95b00; -} - -/* Karten */ -.card-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); - gap: 20px; - width: 100%; - padding: 20px; -} - -.card { - background: #ffffff; - border-radius: 10px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - text-align: center; - padding: 20px; - height: 100%; - display: flex; - flex-direction: column; - justify-content: space-between; -} - -.card img { - max-width: 100%; - height: auto; - border-radius: 10px; - margin-bottom: 10px; -} - -.card h3 { - font-size: 20px; - color: #333; - margin: 10px 0; -} - -.card p { - font-size: 14px; - color: #666; - margin: 5px 0; -} - -.add-to-cart { - background: #ff6600; - color: white; - border: none; - padding: 12px 20px; - border-radius: 25px; - margin-top: 10px; - cursor: pointer; - transition: background 0.3s ease; -} - -.add-to-cart:hover { - background: #e95b00; -} diff --git a/static/Styles/styles-main.css b/static/Styles/styles-main.css index b82692c..6af9077 100644 --- a/static/Styles/styles-main.css +++ b/static/Styles/styles-main.css @@ -1,26 +1,424 @@ - -/* -=============== -Fonts -=============== -*/ -@import url("https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap"); - -/* -=============== -Variables -=============== -*/ -:root { - --demo-clr: #ff0000; +/* ========== Allgemeine Einstellungen ========== */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: "Poppins", sans-serif; } -/* -=============== -Global Styles -=============== -*/ +html, body { + height: 100%; +} + +body { + background: #f8f9fa; + color: #333; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +.wrapper { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +/* ========== Header ========== */ +header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0px 20px; + width: 100%; + background: #ffffff; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + position: sticky; + top: 0; + z-index: 1000; +} + +.logo-container { + display: flex; + align-items: center; + text-decoration: none; + color: inherit; +} + +.logo-container h1 { + margin-left: 10px; + font-size: 1.8rem; +} + +.logo-img { + height: 70px; + object-fit: contain; +} + +header h1 { + font-size: 30px; + color: #333; +} + +.header-right { + display: flex; + align-items: center; + gap: 15px; +} + +.login-btn { + font-size: 14px; + text-decoration: none; + color: white; + background: #ff6600; + padding: 10px 20px; + border-radius: 25px; + transition: background 0.3s ease; +} + +.login-btn:hover { + background: #e95b00; +} + +/* ========== Warenkorb Icon ========== */ +.cart { + display: flex; + align-items: center; + position: relative; + font-size: 24px; + color: #ff6600; + cursor: pointer; +} + +.cart-count { + position: absolute; + top: -5px; + right: -10px; + background: #ff6600; + color: white; + font-size: 12px; + width: 20px; + height: 20px; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; +} + +/* ========== Navigation ========== */ +.menu { + background: #ffffff; + width: 100%; + margin-bottom: 20px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); +} + +.menu-list { + list-style: none; + display: flex; + justify-content: space-around; + padding: 15px 0; +} + +.menu-item { + position: relative; +} + +.menu-item a { + text-decoration: none; + color: #333; + font-size: 18px; + padding: 10px 20px; + transition: background 0.3s ease, color 0.3s ease; +} + +.menu-item a:hover { + background: #ff6600; + color: white; + border-radius: 10px; +} + +.submenu { + position: absolute; + top: 100%; + left: 0; + background: #ffffff; + border-radius: 10px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + display: none; + list-style: none; + min-width: 200px; + z-index: 10; +} + +.submenu li { + padding: 10px 20px; +} + +.submenu li a { + color: #333; +} + +.submenu li a:hover { + color: white; + background: #ff6600; + border-radius: 5px; +} + +.menu-item:hover .submenu { + display: block; +} + +/* ========== Suchleiste ========== */ +.search-bar { + display: flex; + gap: 15px; + width: 100%; + padding: 20px; + background: #ffffff; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + position: sticky; + top: 65px; + z-index: 1000; +} + +.search-bar input, +.search-bar select { + padding: 12px; + font-size: 16px; + border: 1px solid #ddd; + border-radius: 5px; + flex: 1; +} + +.search-bar button { + padding: 12px 20px; + background: #ff6600; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; + transition: background 0.3s ease; +} + +.search-bar button:hover { + background: #e95b00; +} + +/* ========== Karten ========== */ +.card-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 20px; + width: 100%; + padding: 20px; +} + +.card { + background: #ffffff; + border-radius: 10px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + text-align: center; + padding: 20px; + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.card img { + max-width: 100%; + height: auto; + border-radius: 10px; + margin-bottom: 10px; +} + +.card h3 { + font-size: 20px; + color: #333; + margin: 10px 0; +} + +.card p { + font-size: 14px; + color: #666; + margin: 5px 0; +} + +.add-to-cart { + background: #ff6600; + color: white; + border: none; + padding: 12px 20px; + border-radius: 25px; + margin-top: 10px; + cursor: pointer; + transition: background 0.3s ease; +} + +.add-to-cart:hover { + background: #e95b00; +} + +/* ========== Footer ========== */ +.footer { + background: #222; + color: #fff; + padding: 30px 20px; + text-align: center; + margin-top: 40px; + margin-top: auto; +} + +main { + flex: 1; +} + +.footer a { + color: #ff6600; + text-decoration: none; +} + +.footer a:hover { + text-decoration: underline; +} + +/* ========== Formulare und Buttons allgemein ========== */ +.input-box { + position: relative; + margin-bottom: 20px; +} + +.title { + font-size: 26px; + font-weight: 600; + margin-bottom: 25px; + color: #333; + text-align: center; +} + +.input-box input { + width: 100%; + padding: 12px 40px 12px 15px; + border: 1px solid #ddd; + border-radius: 5px; + font-size: 16px; + color: #333; +} + +.input-box i { + position: absolute; + top: 50%; + right: 15px; + transform: translateY(-50%); + color: #888; + font-size: 20px; +} + +.btn { + width: 100%; + padding: 12px 20px; + background: #ff6600; + color: white; + border: none; + border-radius: 10px; + font-size: 16px; + cursor: pointer; + transition: background 0.3s ease; +} + +.btn:hover { + background: #e95b00; +} h1 { - color: var(--demo-clr); -} \ No newline at end of file + font-size: 24px; + color: #333; + margin-top: 20px; + margin-bottom: 20px; +} + +.info-cards-section { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 30px; + padding: 50px 20px; + background: #f8f9fa; +} + +.info-card { + background: #ffffff; + border-radius: 15px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + padding: 30px 25px; + width: 320px; + min-height: 50px; + text-align: center; + transition: transform 0.3s ease; + display: flex; + flex-direction: column; + justify-content: center; +} + +.info-card:hover { + transform: translateY(-5px); +} + +.info-card i { + font-size: 50px; + color: #ff6600; + margin-bottom: 20px; +} + +.info-card h3 { + font-size: 22px; + color: #333; + margin-bottom: 10px; +} + +.info-card p { + font-size: 16px; + color: #555; +} + +/* ========== Error Nachricht (Header und Footer) ========== */ +.error-message { + max-width: 600px; + margin: 40px auto; + padding: 30px; + background-color: #fff5f5; + color: #b00020; + border: 1px solid #ffcccc; + border-radius: 12px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + text-align: center; + font-family: inherit; + animation: fadeIn 0.6s ease-in-out; +} + +.error-message h3 { + margin-bottom: 10px; + font-size: 1.5rem; +} + +.error-message p { + font-size: 1rem; + line-height: 1.5; +} + +/* Optional: weiche Animation beim Einblenden */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + + + + diff --git a/static/images/LoginBackround.jpg b/static/images/LoginBackround.jpg deleted file mode 100644 index 087be46..0000000 Binary files a/static/images/LoginBackround.jpg and /dev/null differ diff --git a/static/images/Logo.png b/static/images/Logo.png new file mode 100644 index 0000000..bf89a96 Binary files /dev/null and b/static/images/Logo.png differ