Compare commits

..

5 Commits

8 changed files with 128 additions and 54 deletions

View File

@ -89,14 +89,18 @@ footer {
.search__controls { .search__controls {
flex-direction: row; flex-direction: row;
align-items: center;
} }
.search__controls input { .search__controls input,
.search__controls select {
flex: 1; flex: 1;
min-width: 120px;
} }
.search__controls button { .search__controls button {
width: 150px; flex: 0 0 auto;
min-width: 120px;
} }
#event-list { #event-list {

View File

@ -42,12 +42,13 @@
<main class="container mt-4"> <main class="container mt-4">
<!-- SEARCH / FILTER SECTION --> <!-- SEARCH / FILTER SECTION -->
<section class="event-search mb-4"> <section class="search mb-4">
<h2>Find Events</h2> <h2>Find Events</h2>
<div class="search__controls"> <div class="search__controls">
<!-- City -->
<input <input
id="city-input" id="city-input"
type="text" type="text"
@ -55,6 +56,22 @@
placeholder="Enter city (e.g. Zurich)" placeholder="Enter city (e.g. Zurich)"
> >
<!-- Date -->
<label for="date-from">From</label>
<input id="date-from" type="date">
<label for="date-to">To</label>
<input id="date-to" type="date">
<!-- Category -->
<select id="category-input" class="form-control">
<option value="">All categories</option>
<option value="music">Music</option>
<option value="sports">Sports</option>
<option value="arts & theatre">Arts & Theatre</option>
</select>
<!-- Button -->
<button <button
id="load-events" id="load-events"
class="btn btn-primary" class="btn btn-primary"

View File

@ -1,39 +1,46 @@
import { fetchEvents } from "./api/ticketmaster.js"; import { getEvents } from "./services/eventService.js";
import { createEventCard } from "./ui/eventCard.js"; import { renderEventList } from "./ui/eventList.js";
import { getFilters } from "./ui/filters.js";
const button = document.querySelector("#load-events"); const button = document.querySelector("#load-events");
const container = document.querySelector("#event-list"); const container = document.querySelector("#event-list");
const cityInput = document.querySelector("#city-input"); const cityInput = document.querySelector("#city-input");
button.addEventListener("click", async () => { button.addEventListener("click", handleSearch);
const city = cityInput.value.trim();
if (!city) {
container.innerHTML = "Please enter a city.";
return;
}
container.innerHTML = "Loading events...";
const events = await fetchEvents(city);
container.innerHTML = "";
if (events.length === 0) {
container.innerHTML = "No events found.";
return;
}
events.forEach(event => {
const card = createEventCard(event);
container.appendChild(card);
});
});
cityInput.addEventListener("keydown", (event) => { cityInput.addEventListener("keydown", (event) => {
if (event.key === "Enter") { if (event.key === "Enter") handleSearch();
button.click();
}
}); });
async function handleSearch() {
const { city, dateFrom, dateTo, category } = getFilters();
if (!city) {
container.innerHTML = "<p class='text-danger'>Please enter a city.</p>";
return;
}
container.innerHTML = "<p class='text-muted'>Loading events...</p>";
const events = await getEvents(city);
const filteredEvents = applyFilters(events, dateFrom, dateTo, category);
renderEventList(filteredEvents, container);
}
function applyFilters(events, dateFrom, dateTo, category) {
return events.filter(event => {
const matchDateFrom = dateFrom ? event.date >= dateFrom : true;
const matchDateTo = dateTo ? event.date <= dateTo : true;
const matchCategory = category
? event.category && event.category.includes(category)
: true;
return matchDateFrom && matchDateTo && matchCategory;
});
}

View File

@ -6,7 +6,11 @@ export async function getEvents(city) {
return events.map(event => ({ return events.map(event => ({
id: event.id, id: event.id,
name: event.name, name: event.name,
date: event.dates.start.localDate, date: event.dates?.start?.localDate || null,
venue: event._embedded?.venues[0]?.name time: event.dates?.start?.localTime || null,
venue: event._embedded?.venues?.[0]?.name || "Unknown venue",
category: event.classifications?.[0]?.segment?.name
? event.classifications[0].segment.name.toLowerCase()
: null
})); }));
} }

View File

@ -1,17 +1,37 @@
export function createEventCard(event) { export function createEventCard(event) {
const article = document.createElement("article"); const article = document.createElement("article");
article.className = "event-card"; article.className = "event-card";
const name = event.name; const title = document.createElement("h3");
const date = event.dates.start.localDate; title.className = "event-card__title";
const venue = event._embedded?.venues[0]?.name; title.textContent = event.name;
article.innerHTML = ` const formattedDate = event.date
<h3 class="event-card__title">${name}</h3> ? new Date(event.date).toLocaleDateString("de-CH", {
<p class="event-card__date">${date}</p> day: "2-digit",
<p class="event-card__venue">${venue}</p> month: "2-digit",
`; year: "numeric"
})
: "Date not available";
return article; const formattedTime = event.time
} ? event.time.slice(0, 5)
: "";
const dateTime = formattedTime
? `${formattedDate}, ${formattedTime}`
: formattedDate;
const date = document.createElement("p");
date.className = "event-card__date";
date.textContent = dateTime;
const venue = document.createElement("p");
venue.className = "event-card__venue";
venue.textContent = event.venue;
article.append(title, date, venue);
return article;
}

View File

@ -0,0 +1,17 @@
import { createEventCard } from "./eventCard.js";
export function renderEventList(events, container) {
container.innerHTML = "";
if (events.length === 0) {
container.innerHTML = "No events found.";
return;
}
events.forEach(event => {
const card = createEventCard(event);
container.appendChild(card);
});
}

View File

@ -0,0 +1,8 @@
export function getFilters() {
const city = document.querySelector("#city-input").value.trim();
const dateFrom = document.querySelector("#date-from").value;
const dateTo = document.querySelector("#date-to").value;
const category = document.querySelector("#category-input").value;
return { city, dateFrom, dateTo, category };
}

View File

@ -1,3 +0,0 @@
export function formatDate(date) {
return new Date(date).toLocaleDateString();
}