268 lines
6.6 KiB
JavaScript
268 lines
6.6 KiB
JavaScript
import { getEvents } from "./services/eventService.js";
|
|
import { renderEventList } from "./ui/eventList.js";
|
|
import { getFilters } from "./ui/filters.js";
|
|
import { login, register } from "./auth.js";
|
|
|
|
// =========================
|
|
// STATE
|
|
// =========================
|
|
let currentUser = null;
|
|
let currentPassword = null;
|
|
|
|
window.currentUser = null;
|
|
window.currentPassword = null;
|
|
|
|
// =========================
|
|
// AUTH ELEMENTS
|
|
// =========================
|
|
const loginBtn = document.querySelector("#login-btn");
|
|
const registerBtn = document.querySelector("#register-btn");
|
|
|
|
// =========================
|
|
// NAVIGATION ELEMENTS
|
|
// =========================
|
|
const navEvents = document.querySelector("#nav-events");
|
|
const navSaved = document.querySelector("#nav-my-events");
|
|
const navInv = document.querySelector("#nav-invitations");
|
|
|
|
// =========================
|
|
// SECTIONS
|
|
// =========================
|
|
const searchSection = document.querySelector("#search-section");
|
|
const eventsSection = document.querySelector("#events-section");
|
|
const savedSection = document.querySelector("#saved-section");
|
|
const invSection = document.querySelector("#invitations-section");
|
|
|
|
// =========================
|
|
// AUTH UI
|
|
// =========================
|
|
const authArea = document.querySelector("#auth-area");
|
|
const userArea = document.querySelector("#user-area");
|
|
const userNameEl = document.querySelector("#user-name");
|
|
const logoutBtn = document.querySelector("#logout-btn");
|
|
|
|
// =========================
|
|
// LOGIN
|
|
// =========================
|
|
loginBtn.addEventListener("click", async () => {
|
|
|
|
const username = document.querySelector("#username").value;
|
|
const password = document.querySelector("#password").value;
|
|
|
|
const success = await login(username, password);
|
|
|
|
if (success) {
|
|
currentUser = username;
|
|
currentPassword = password;
|
|
|
|
window.currentUser = username;
|
|
window.currentPassword = password;
|
|
|
|
// UI switch
|
|
authArea.classList.add("d-none");
|
|
userArea.classList.remove("d-none");
|
|
|
|
userNameEl.textContent = `👤 ${username}`;
|
|
|
|
navSaved.classList.remove("d-none");
|
|
navInv.classList.remove("d-none");
|
|
|
|
} else {
|
|
alert("Login failed");
|
|
}
|
|
});
|
|
|
|
// =========================
|
|
// REGISTER
|
|
// =========================
|
|
registerBtn.addEventListener("click", async () => {
|
|
|
|
const username = document.querySelector("#username").value;
|
|
|
|
const data = await register(username);
|
|
|
|
alert(`User created. Password: ${data.password}`);
|
|
});
|
|
|
|
// =========================
|
|
// LOGOUT
|
|
// =========================
|
|
logoutBtn.addEventListener("click", () => {
|
|
|
|
currentUser = null;
|
|
currentPassword = null;
|
|
|
|
window.currentUser = null;
|
|
window.currentPassword = null;
|
|
|
|
authArea.classList.remove("d-none");
|
|
userArea.classList.add("d-none");
|
|
|
|
navSaved.classList.add("d-none");
|
|
navInv.classList.add("d-none");
|
|
|
|
showSection("events");
|
|
});
|
|
|
|
// =========================
|
|
// SEARCH
|
|
// =========================
|
|
const button = document.querySelector("#load-events");
|
|
const container = document.querySelector("#event-list");
|
|
const cityInput = document.querySelector("#city-input");
|
|
|
|
button.addEventListener("click", handleSearch);
|
|
|
|
cityInput.addEventListener("keydown", (event) => {
|
|
if (event.key === "Enter") handleSearch();
|
|
});
|
|
|
|
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);
|
|
}
|
|
|
|
// =========================
|
|
// FILTERS
|
|
// =========================
|
|
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;
|
|
});
|
|
}
|
|
|
|
// =========================
|
|
// NAVIGATION LOGIC
|
|
// =========================
|
|
navEvents.addEventListener("click", () => {
|
|
showSection("events");
|
|
});
|
|
|
|
navSaved.addEventListener("click", () => {
|
|
showSection("saved");
|
|
loadSavedEvents();
|
|
});
|
|
|
|
navInv.addEventListener("click", () => {
|
|
showSection("invitations");
|
|
loadInvitations();
|
|
});
|
|
|
|
function showSection(section) {
|
|
|
|
searchSection.classList.add("d-none");
|
|
eventsSection.classList.add("d-none");
|
|
savedSection.classList.add("d-none");
|
|
invSection.classList.add("d-none");
|
|
|
|
if (section === "events") {
|
|
searchSection.classList.remove("d-none");
|
|
eventsSection.classList.remove("d-none");
|
|
}
|
|
|
|
if (section === "saved") {
|
|
savedSection.classList.remove("d-none");
|
|
}
|
|
|
|
if (section === "invitations") {
|
|
invSection.classList.remove("d-none");
|
|
}
|
|
}
|
|
|
|
// =========================
|
|
// SAVED EVENTS
|
|
// =========================
|
|
function loadSavedEvents() {
|
|
|
|
const saved = JSON.parse(localStorage.getItem("savedEvents") || "[]");
|
|
const container = document.querySelector("#saved-list");
|
|
|
|
container.innerHTML = "";
|
|
|
|
if (saved.length === 0) {
|
|
container.innerHTML = "<p>No saved events yet.</p>";
|
|
return;
|
|
}
|
|
|
|
saved.forEach(event => {
|
|
const div = document.createElement("div");
|
|
div.textContent = event.name;
|
|
container.appendChild(div);
|
|
});
|
|
}
|
|
|
|
// =========================
|
|
// INVITATIONS
|
|
// =========================
|
|
async function loadInvitations() {
|
|
|
|
if (!currentUser) return;
|
|
|
|
const res = await fetch("http://localhost:3000/api/invitation", {
|
|
headers: {
|
|
"X-Username": currentUser
|
|
}
|
|
});
|
|
|
|
const data = await res.json();
|
|
const container = document.querySelector("#invitation-list");
|
|
|
|
container.innerHTML = "";
|
|
|
|
if (data.length === 0) {
|
|
container.innerHTML = "<p>No invitations.</p>";
|
|
return;
|
|
}
|
|
|
|
data.forEach(inv => {
|
|
|
|
const div = document.createElement("div");
|
|
|
|
div.innerHTML = `
|
|
<p><strong>${inv.fromUser}</strong> invited you to <em>${inv.eventName}</em></p>
|
|
<button onclick="accept(${inv.id})">Accept</button>
|
|
<button onclick="decline(${inv.id})">Decline</button>
|
|
`;
|
|
|
|
container.appendChild(div);
|
|
});
|
|
}
|
|
|
|
// =========================
|
|
// ACCEPT / DECLINE
|
|
// =========================
|
|
window.accept = async (id) => {
|
|
await fetch(`http://localhost:3000/api/invitation/${id}/accept`, {
|
|
method: "POST"
|
|
});
|
|
loadInvitations();
|
|
};
|
|
|
|
window.decline = async (id) => {
|
|
await fetch(`http://localhost:3000/api/invitation/${id}/decline`, {
|
|
method: "POST"
|
|
});
|
|
loadInvitations();
|
|
}; |