Archive added

This commit is contained in:
marijo 2026-06-29 08:12:46 +00:00
parent 01a38ba145
commit 467f405f32
3 changed files with 97 additions and 25 deletions

96
app.js
View file

@ -24,6 +24,9 @@ const clearAllButton = document.querySelector("#clear-all");
const routeCount = document.querySelector("#route-count");
const emptyState = document.querySelector("#empty-state");
const routesList = document.querySelector("#routes-list");
const archiveSection = document.querySelector("#archive-section");
const archiveCount = document.querySelector("#archive-count");
const archivedRoutesList = document.querySelector("#archived-routes-list");
const template = document.querySelector("#route-card-template");
let routes = sortRoutes(loadRoutes());
@ -35,6 +38,7 @@ form.addEventListener("submit", saveRoute);
cancelEditButton.addEventListener("click", resetForm);
clearAllButton?.addEventListener("click", removeAllRoutes);
routesList.addEventListener("click", handleRouteAction);
archivedRoutesList.addEventListener("click", handleRouteAction);
document.addEventListener("click", closeMenusOnOutsideClick);
document.addEventListener("keydown", closeMenusOnEscape);
@ -93,8 +97,8 @@ function storeRoutes() {
function sortRoutes(routeList) {
return [...routeList].sort((a, b) => {
const dateA = a.date || "0000-00-00";
const dateB = b.date || "0000-00-00";
const dateA = a.date || "9999-99-99";
const dateB = b.date || "9999-99-99";
if (dateA !== dateB) {
return dateA.localeCompare(dateB);
@ -116,6 +120,7 @@ async function saveRoute(event) {
name: nameInput.value.trim(),
link: linkInput.value.trim(),
date: dateInput.value,
archived: existingRoute?.archived || false,
picture: existingRoute?.picture || "",
description: descriptionInput.value.trim(),
updatedAt: new Date().toISOString(),
@ -153,35 +158,56 @@ async function saveRoute(event) {
function renderRoutes() {
routesList.innerHTML = "";
archivedRoutesList.innerHTML = "";
const activeRoutes = routes.filter((route) => !route.archived);
const archivedRoutes = routes.filter((route) => route.archived);
routeCount.textContent = activeRoutes.length === 1 ? "1 route saved." : `${activeRoutes.length} routes saved.`;
emptyState.classList.toggle("hidden", activeRoutes.length > 0);
archiveSection.hidden = archivedRoutes.length === 0;
archiveCount.textContent = archivedRoutes.length;
if (!archivedRoutes.length) {
archiveSection.open = false;
}
routeCount.textContent = routes.length === 1 ? "1 route saved." : `${routes.length} routes saved.`;
emptyState.classList.toggle("hidden", routes.length > 0);
if (clearAllButton) {
clearAllButton.hidden = routes.length === 0;
}
for (const route of routes) {
const card = template.content.firstElementChild.cloneNode(true);
const image = card.querySelector(".route-image");
const meta = card.querySelector(".route-meta");
const title = card.querySelector(".route-title");
const description = card.querySelector(".route-description");
card.dataset.id = route.id;
meta.textContent = route.date ? formatDate(route.date) : "";
meta.hidden = !route.date;
title.textContent = route.name;
title.href = route.link;
description.textContent = route.description;
description.hidden = !route.description;
if (route.picture) {
image.hidden = false;
image.style.backgroundImage = `url("${cssUrlEscape(route.picture)}")`;
}
routesList.append(card);
for (const route of activeRoutes) {
routesList.append(createRouteCard(route));
}
for (const route of archivedRoutes) {
archivedRoutesList.append(createRouteCard(route));
}
}
function createRouteCard(route) {
const card = template.content.firstElementChild.cloneNode(true);
const image = card.querySelector(".route-image");
const meta = card.querySelector(".route-meta");
const title = card.querySelector(".route-title");
const description = card.querySelector(".route-description");
const archiveButton = card.querySelector(".archive-route");
card.dataset.id = route.id;
meta.textContent = route.date ? formatDate(route.date) : "";
meta.hidden = !route.date;
title.textContent = route.name;
title.href = route.link;
description.textContent = route.description;
description.hidden = !route.description;
archiveButton.textContent = route.archived ? "Unarchive" : "Archive";
if (route.picture) {
image.hidden = false;
image.style.backgroundImage = `url("${cssUrlEscape(route.picture)}")`;
}
return card;
}
function closeMenusOnOutsideClick(event) {
@ -227,6 +253,26 @@ function handleRouteAction(event) {
if (button.classList.contains("share-route")) {
shareRoute(route);
}
if (button.classList.contains("archive-route")) {
toggleArchive(route.id);
}
}
function toggleArchive(id) {
const route = routes.find((item) => item.id === id);
if (!route) {
return;
}
route.archived = !route.archived;
routes = sortRoutes(routes);
storeRoutes();
renderRoutes();
if (idInput.value === id) {
resetForm();
}
}
function startAddRoute() {

View file

@ -83,6 +83,11 @@
</div>
<div id="routes-list" class="routes-list" aria-live="polite"></div>
<details id="archive-section" class="archive-section" hidden>
<summary>Archived (<span id="archive-count">0</span>)</summary>
<div id="archived-routes-list" class="routes-list archived-routes-list" aria-live="polite"></div>
</details>
</section>
</main>
</div>
@ -99,6 +104,7 @@
<div class="menu-items">
<button type="button" class="share-route">Share</button>
<button type="button" class="edit-route">Edit</button>
<button type="button" class="archive-route">Archive</button>
<button type="button" class="danger remove-route">Delete</button>
</div>
</details>

View file

@ -336,6 +336,26 @@ textarea:focus {
background: var(--danger-dark);
}
.archive-section {
margin-top: 1rem;
}
.archive-section > summary {
padding: 0.85rem 0.2rem;
color: var(--muted);
font-weight: 800;
cursor: pointer;
list-style-position: inside;
}
.archived-routes-list {
margin-top: 0.5rem;
}
.archived-routes-list .route-card {
opacity: 0.82;
}
.empty-state {
padding: 1.5rem 1rem;
text-align: center;