Vibecoded basic filter system based on wireframe layout using json and js. rearragend folder strcuture in this branch.

This commit is contained in:
viiivo 2026-03-23 17:43:03 +01:00
parent 7cebec338e
commit 4da3c0741a
6 changed files with 209 additions and 0 deletions

View File

@ -0,0 +1,54 @@
:root {
--black: #000;
--white: #fff;
--gray-bg: #f4f4f4;
--border: 1px solid #000;
}
body { font-family: Arial, sans-serif; margin: 0; padding: 0; }
.container { max-width: 1100px; margin: 0 auto; padding: 20px; }
/* Navbar & Filter */
.navbar { display: flex; justify-content: space-between; padding: 20px 5%; border-bottom: var(--border); }
.category-group { display: flex; gap: 20px; margin-bottom: 40px; flex-wrap: wrap; }
.category-item { cursor: pointer; text-align: center; font-size: 11px; font-weight: bold; }
.square { width: 50px; height: 50px; border: var(--border); margin-bottom: 5px; }
.category-item.active .square { background: var(--black); }
/* Event Cards */
.event-list { display: flex; flex-direction: column; gap: 20px; }
.event-card {
display: grid;
grid-template-columns: 200px 1fr 150px 150px 50px;
border: var(--border);
align-items: center;
}
.event-image { height: 150px; background-size: cover; background-position: center; border-right: var(--border); }
.event-content, .event-info, .event-cta { padding: 15px; }
.tag { border: var(--border); padding: 3px 10px; border-radius: 15px; font-size: 10px; margin-right: 5px; }
.btn-primary { background: var(--black); color: var(--white); border: none; padding: 10px; width: 100%; cursor: pointer; font-weight: bold; }
/* Empty State Style */
.empty-state {
text-align: center;
padding: 50px 20px;
border: 2px dashed #ccc;
background: var(--gray-bg);
margin-top: 20px;
}
.btn-outline {
background: transparent;
border: 2px solid var(--black);
padding: 12px 25px;
font-weight: bold;
cursor: pointer;
margin-top: 15px;
transition: 0.3s;
}
.btn-outline:hover { background: var(--black); color: var(--white); }
/* Responsive */
@media (max-width: 850px) {
.event-card { grid-template-columns: 1fr; }
.event-image { border-right: none; border-bottom: var(--border); width: 100%; }
}

38
data/events.json Normal file
View File

@ -0,0 +1,38 @@
[
{
"id": 1,
"title": "Italienische Tavolata",
"location": "LUZERN",
"date": "19. MÄR. 2026",
"time": "18:30 UHR",
"category": "DINNER",
"cuisine": "ITALIENISCH",
"diet": "VEGGIE",
"spots": 4,
"image": "https://via.placeholder.com/300x200"
},
{
"id": 2,
"title": "Noche Peruana",
"location": "LUZERN",
"date": "11. APR. 2026",
"time": "19:00 UHR",
"category": "DINNER",
"cuisine": "PERUANISCH",
"diet": "FLEISCH",
"spots": 2,
"image": "https://via.placeholder.com/300x200"
},
{
"id": 3,
"title": "Japanese Delight",
"location": "ZÜRICH",
"date": "02. MAI. 2026",
"time": "12:30 UHR",
"category": "LUNCH",
"cuisine": "JAPANISCH",
"diet": "FISCH",
"spots": 8,
"image": "https://via.placeholder.com/300x200"
}
]

36
event_overview.html Normal file
View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event_Overview</title>
<link rel="stylesheet" href="css/event_overview_stylesheet.css">
</head>
<body>
<header class="navbar">
<div class="logo">SOCIAL COOKING</div>
<nav>
<span>Events</span>
<div class="user-profile">M</div>
</nav>
</header>
<main class="container">
<h1>Invité Events</h1>
<section class="filter-section">
<p class="filter-label">WORAUF HAST DU LUST</p>
<div class="category-group">
<div class="category-item" data-cat="BRUNCH"><div class="square"></div><span>BRUNCH</span></div>
<div class="category-item" data-cat="LUNCH"><div class="square"></div><span>LUNCH</span></div>
<div class="category-item" data-cat="DINNER"><div class="square"></div><span>DINNER</span></div>
<div class="category-item" data-cat="COFFEE"><div class="square"></div><span>COFFEE</span></div>
<div class="category-item active" data-cat="ALLE"><div class="square"></div><span>ALLE</span></div>
</div>
</section>
<section id="event-grid" class="event-list"></section>
</main>
<script src="js/event_overview_script.js"></script>
</body>
</html>

View File

@ -0,0 +1,81 @@
document.addEventListener('DOMContentLoaded', () => {
const eventGrid = document.getElementById('event-grid');
const filterButtons = document.querySelectorAll('.category-item');
let allEvents = [];
// 1. Daten laden
async function fetchEvents() {
try {
// Pfad an deine Ordnerstruktur angepasst
const response = await fetch('data/events.json');
allEvents = await response.json();
renderEvents(allEvents);
} catch (error) {
console.error("Fehler:", error);
eventGrid.innerHTML = "<p>Events konnten nicht geladen werden.</p>";
}
}
// 2. Events rendern + "Empty State" Logik
function renderEvents(events) {
eventGrid.innerHTML = '';
// PRÜFUNG: Wenn keine Events vorhanden sind
if (events.length === 0) {
eventGrid.innerHTML = `
<div class="empty-state">
<h3>Schade! Aktuell gibt es hier keine Events.</h3>
<p>Möchtest du vielleicht selbst Gastgeber sein?</p>
<button class="btn-outline" onclick="alert('Hier gehts zum Formular!')">Eigenes Event erstellen</button>
</div>
`;
return;
}
// Wenn Events da sind, Karten bauen
events.forEach(event => {
const card = document.createElement('article');
card.className = 'event-card';
card.innerHTML = `
<div class="event-image" style="background-image: url('${event.image}')"></div>
<div class="event-content">
<small>📍 ${event.location}</small>
<h2 style="margin: 5px 0;">${event.title}</h2>
<div>
<span class="tag">${event.cuisine}</span>
<span class="tag">${event.category}</span>
</div>
</div>
<div class="event-info">
<strong>${event.date}</strong><br>
<span>🕒 ${event.time}</span>
</div>
<div class="event-cta">
<div style="font-size: 12px; margin-bottom: 8px;">🥗 ${event.diet}</div>
<button class="btn-primary">Anmelden</button>
<p style="font-size: 10px; margin-top: 8px;">${event.spots} PLÄTZE FREI</p>
</div>
<div style="text-align: center;"></div>
`;
eventGrid.appendChild(card);
});
}
// 3. Filter-Logik
filterButtons.forEach(button => {
button.addEventListener('click', () => {
filterButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
const selectedCat = button.getAttribute('data-cat');
const filtered = selectedCat === 'ALLE'
? allEvents
: allEvents.filter(e => e.category === selectedCat);
renderEvents(filtered);
});
});
fetchEvents();
});