Initial commit: Website
This commit is contained in:
commit
3a8948c60c
5
.gitignore
vendored
Executable file
5
.gitignore
vendored
Executable file
@ -0,0 +1,5 @@
|
||||
/vendor/
|
||||
/node_modules/
|
||||
.env
|
||||
*.log
|
||||
.cache/
|
||||
9
.htaccess
Executable file
9
.htaccess
Executable file
@ -0,0 +1,9 @@
|
||||
AuthType Basic
|
||||
AuthName "Geschützter Bereich"
|
||||
AuthUserFile /FSST/Website/.htpasswd
|
||||
Require valid-user
|
||||
|
||||
# .htpasswd vor Auslieferung schützen
|
||||
<Files ".htpasswd">
|
||||
Require all denied
|
||||
</Files>
|
||||
0
account.php
Executable file
0
account.php
Executable file
0
footer.php
Executable file
0
footer.php
Executable file
169
index.php
Executable file
169
index.php
Executable file
@ -0,0 +1,169 @@
|
||||
<?php
|
||||
// ======================================
|
||||
// Fehleranzeige (DEV)
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
// ======================================
|
||||
// DB-Verbindung
|
||||
$con = mysqli_connect("localhost", "FSST", "L9wUNZZ9Qkbt", "FSST");
|
||||
mysqli_set_charset($con, "utf8");
|
||||
|
||||
if (!$con) {
|
||||
die("DB Fehler: " . mysqli_connect_error());
|
||||
}
|
||||
|
||||
// ======================================
|
||||
// GET-Parameter
|
||||
$categoryID = isset($_GET['category']) ? (int)$_GET['category'] : 0;
|
||||
$maxPrice = isset($_GET['maxPrice']) ? (float)$_GET['maxPrice'] : 0;
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preisvergleich – Demo</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="stylesheet" href="style.css">
|
||||
|
||||
|
||||
|
||||
|
||||
<?php include 'navbar.php'; ?>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>💻 Preisvergleich – Beispielanwendung</h1>
|
||||
|
||||
<?php
|
||||
// ======================================
|
||||
// Kategorien laden
|
||||
$categories = mysqli_query($con, "
|
||||
SELECT categoryID, name
|
||||
FROM categories
|
||||
WHERE parentCategoryID IS NOT NULL
|
||||
ORDER BY name
|
||||
");
|
||||
?>
|
||||
|
||||
<form method="get">
|
||||
Kategorie:
|
||||
<select name="category">
|
||||
<option value="0">Alle</option>
|
||||
<?php while ($c = mysqli_fetch_assoc($categories)): ?>
|
||||
<option value="<?= $c['categoryID'] ?>"
|
||||
<?= $categoryID === (int)$c['categoryID'] ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($c['name']) ?>
|
||||
</option>
|
||||
<?php endwhile; ?>
|
||||
</select>
|
||||
|
||||
Max Preis (€):
|
||||
<input type="number" step="1" name="maxPrice" value="<?= htmlspecialchars($maxPrice) ?>">
|
||||
|
||||
<button type="submit">Anzeigen</button>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
// ======================================
|
||||
// Produkte + günstigster Preis
|
||||
$sql = "
|
||||
SELECT
|
||||
p.productID,
|
||||
p.model,
|
||||
b.name AS brand,
|
||||
c.name AS category,
|
||||
MIN(o.price + o.shippingCost) AS bestPrice
|
||||
FROM products p
|
||||
JOIN brands b ON p.brandID = b.brandID
|
||||
JOIN categories c ON p.categoryID = c.categoryID
|
||||
JOIN offers o ON o.productID = p.productID
|
||||
WHERE 1
|
||||
";
|
||||
|
||||
$params = [];
|
||||
$types = "";
|
||||
|
||||
if ($categoryID > 0) {
|
||||
$sql .= " AND p.categoryID = ?";
|
||||
$params[] = $categoryID;
|
||||
$types .= "i";
|
||||
}
|
||||
|
||||
if ($maxPrice > 0) {
|
||||
$sql .= " AND (o.price + o.shippingCost) <= ?";
|
||||
$params[] = $maxPrice;
|
||||
$types .= "d";
|
||||
}
|
||||
|
||||
$sql .= " GROUP BY p.productID ORDER BY bestPrice ASC";
|
||||
|
||||
$stmt = mysqli_prepare($con, $sql);
|
||||
if ($params) {
|
||||
mysqli_stmt_bind_param($stmt, $types, ...$params);
|
||||
}
|
||||
mysqli_stmt_execute($stmt);
|
||||
$result = mysqli_stmt_get_result($stmt);
|
||||
|
||||
// ======================================
|
||||
// Ausgabe
|
||||
while ($p = mysqli_fetch_assoc($result)):
|
||||
?>
|
||||
<div class="product">
|
||||
<strong><?= htmlspecialchars($p['brand']) ?> <?= htmlspecialchars($p['model']) ?></strong><br>
|
||||
Kategorie: <?= htmlspecialchars($p['category']) ?><br>
|
||||
💰 Ab <?= number_format($p['bestPrice'], 2, ',', '.') ?> €
|
||||
|
||||
<div class="spec">
|
||||
<strong>Specs:</strong><br>
|
||||
<?php
|
||||
$specs = mysqli_query($con, "
|
||||
SELECT a.name, a.unit,
|
||||
pa.valueString, pa.valueNumber, pa.valueBool
|
||||
FROM productAttributes pa
|
||||
JOIN attributes a ON pa.attributeID = a.attributeID
|
||||
WHERE pa.productID = {$p['productID']}
|
||||
");
|
||||
|
||||
while ($s = mysqli_fetch_assoc($specs)) {
|
||||
echo htmlspecialchars($s['name']) . ": ";
|
||||
|
||||
if ($s['valueString'] !== null) echo htmlspecialchars($s['valueString']);
|
||||
elseif ($s['valueNumber'] !== null) echo htmlspecialchars($s['valueNumber']) . " " . $s['unit'];
|
||||
elseif ($s['valueBool'] !== null) echo $s['valueBool'] ? "Ja" : "Nein";
|
||||
|
||||
echo "<br>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="offer">
|
||||
<strong>Angebote:</strong><br>
|
||||
<?php
|
||||
$offers = mysqli_query($con, "
|
||||
SELECT s.name, o.price, o.shippingCost
|
||||
FROM offers o
|
||||
JOIN shops s ON o.shopID = s.shopID
|
||||
WHERE o.productID = {$p['productID']}
|
||||
ORDER BY o.price ASC
|
||||
");
|
||||
|
||||
while ($o = mysqli_fetch_assoc($offers)) {
|
||||
$total = $o['price'] + $o['shippingCost'];
|
||||
echo htmlspecialchars($o['name']) . ": "
|
||||
. number_format($total, 2, ',', '.') . " €<br>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endwhile; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?php mysqli_close($con); ?>
|
||||
19
navbar.php
Executable file
19
navbar.php
Executable file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
$currentPage = basename($_SERVER['PHP_SELF']);
|
||||
?>
|
||||
|
||||
<nav class="navbar">
|
||||
<ul>
|
||||
<input type="text" name="q" placeholder="Produkt Suchen..." required>
|
||||
<button type="submit">Suchen</button>
|
||||
<li class="<?= $currentPage === 'index.php' ? 'active' : '' ?>">
|
||||
<a href="index.php">Wunschliste</a>
|
||||
</li>
|
||||
<li class="<?= $currentPage === 'produkte.php' ? 'active' : '' ?>">
|
||||
<a href="produkte.php">Wahrenkorb</a>
|
||||
</li>
|
||||
<li class="<?= $currentPage === 'kontakt.php' ? 'active' : '' ?>">
|
||||
<a href="kontakt.php">Account</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
258
style.css
Executable file
258
style.css
Executable file
@ -0,0 +1,258 @@
|
||||
/* ================================
|
||||
Modernes Preisvergleich-Stylesheet
|
||||
================================ */
|
||||
|
||||
/* --- CSS Reset (leichtgewichtig) --- */
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* --- Root-Variablen --- */
|
||||
:root {
|
||||
--bg-main: #f4f6f8;
|
||||
--bg-card: #ffffff;
|
||||
--color-primary: #2563eb;
|
||||
--color-secondary: #64748b;
|
||||
--color-text: #0f172a;
|
||||
--color-muted: #475569;
|
||||
--border-radius: 10px;
|
||||
--shadow-soft: 0 6px 20px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
/* --- Grundlayout --- */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 32px;
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, sans-serif;
|
||||
background-color: var(--bg-main);
|
||||
color: var(--color-text);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* --- Überschrift --- */
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 24px;
|
||||
font-size: 1.8rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* --- Formular --- */
|
||||
form {
|
||||
background: var(--bg-card);
|
||||
padding: 16px 20px;
|
||||
margin-bottom: 28px;
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow: var(--shadow-soft);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
form label {
|
||||
font-size: 0.9rem;
|
||||
color: var(--color-muted);
|
||||
}
|
||||
|
||||
select,
|
||||
input[type="number"] {
|
||||
padding: 8px 10px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #cbd5f5;
|
||||
font-size: 0.95rem;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
select:focus,
|
||||
input:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* --- Button --- */
|
||||
button {
|
||||
padding: 9px 16px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
background-color: var(--color-primary);
|
||||
color: #fff;
|
||||
font-size: 0.95rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #1d4ed8;
|
||||
}
|
||||
|
||||
/* --- Produktkarte --- */
|
||||
.product {
|
||||
background: var(--bg-card);
|
||||
padding: 18px 22px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow: var(--shadow-soft);
|
||||
}
|
||||
|
||||
/* Produkt-Titel */
|
||||
.product > strong {
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
/* --- Preis --- */
|
||||
.product .price {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* --- Specs --- */
|
||||
.spec {
|
||||
margin-top: 12px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
font-size: 0.9rem;
|
||||
color: var(--color-muted);
|
||||
}
|
||||
|
||||
/* --- Angebote --- */
|
||||
.offer {
|
||||
margin-top: 12px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px dashed #e5e7eb;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* --- Responsive Feinschliff --- */
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
form {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* ======================================
|
||||
Elegant Dark Mode – refined UI
|
||||
====================================== */
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
/* Background Layers */
|
||||
--bg-main: #0b0f19; /* App-Hintergrund */
|
||||
--bg-card: #111827; /* Cards */
|
||||
--bg-input: #020617; /* Inputs */
|
||||
|
||||
/* Text */
|
||||
--color-text: #e5e7eb;
|
||||
--color-muted: #9ca3af;
|
||||
|
||||
/* Accent */
|
||||
--color-primary: #60a5fa; /* sanfteres Blau */
|
||||
|
||||
/* Borders & Shadow */
|
||||
--border-soft: #1e293b;
|
||||
--shadow-soft: 0 12px 40px rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
|
||||
body {
|
||||
background:
|
||||
radial-gradient(1200px at top, #111827 0%, var(--bg-main) 60%);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
/* Cards */
|
||||
form,
|
||||
.product {
|
||||
background:
|
||||
linear-gradient(
|
||||
180deg,
|
||||
rgba(255,255,255,0.02),
|
||||
rgba(0,0,0,0.15)
|
||||
),
|
||||
var(--bg-card);
|
||||
box-shadow: var(--shadow-soft);
|
||||
border: 1px solid var(--border-soft);
|
||||
}
|
||||
|
||||
/* Inputs */
|
||||
select,
|
||||
input[type="number"] {
|
||||
background: var(--bg-input);
|
||||
color: var(--color-text);
|
||||
border: 1px solid var(--border-soft);
|
||||
}
|
||||
|
||||
select:focus,
|
||||
input:focus {
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 0 0 1px var(--color-primary);
|
||||
}
|
||||
|
||||
/* Button */
|
||||
button {
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
#60a5fa,
|
||||
#3b82f6
|
||||
);
|
||||
color: #020617;
|
||||
box-shadow: 0 4px 12px rgba(96, 165, 250, 0.35);
|
||||
}
|
||||
|
||||
button:hover {
|
||||
filter: brightness(1.08);
|
||||
}
|
||||
|
||||
/* Produkttext */
|
||||
.product > strong {
|
||||
color: #f8fafc;
|
||||
}
|
||||
|
||||
/* Specs / Offers */
|
||||
.spec,
|
||||
.offer {
|
||||
border-top: 1px solid var(--border-soft);
|
||||
color: var(--color-muted);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------NAV-BAR-----------------------*/
|
||||
|
||||
.navbar {
|
||||
background: #1e1e1e;
|
||||
padding: 12px 24px;
|
||||
}
|
||||
|
||||
.navbar ul {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.navbar a {
|
||||
color: #ddd;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.navbar li.active a {
|
||||
color: #4fc3f7;
|
||||
border-bottom: 2px solid #4fc3f7;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*/
|
||||
Loading…
Reference in New Issue
Block a user