feat: add local fishing plan page

This commit is contained in:
ik
2026-09-20 20:12:20 +07:00
parent 3f0a02a9b9
commit 5335255c5c
5 changed files with 62 additions and 2 deletions
+39
View File
@@ -0,0 +1,39 @@
---
import Layout from "../layouts/Layout.astro";
---
<Layout title="Мой план рыбалки — RF4 Spotter" description="Сохранённые точки рыбалки RF4 без аккаунта: координаты, наживки, свежесть и доверие." noindex>
<section class="plan-hero content-grid"><div><span class="eyebrow">Локально на этом устройстве</span><h1>Мой план<br/><em>рыбалки.</em></h1><p>Соберите до пяти точек, сравните их перед выездом и распечатайте список. Данные не отправляются на сервер.</p></div><div class="plan-hero__mark" aria-hidden="true">♢</div></section>
<section class="plan-toolbar content-grid" aria-label="Действия с планом"><span data-plan-count>0 из 5 точек</span><div><button data-action="secondary" type="button" data-plan-print>Печать / PDF</button><button data-action="quiet" type="button" data-plan-clear>Очистить план</button></div></section>
<section class="plan-content content-grid" data-plan-page aria-live="polite"><div class="plan-grid" data-plan-list></div><div class="state" data-plan-empty><h2>План пока пуст</h2><p>Сохраните точку на её detail-странице — она появится здесь.</p><a data-action="secondary" href="/">Посмотреть горячие точки</a></div></section>
</Layout>
<script>
const planStorageKey = "rf4spotter:fishing-plan";
const list = document.querySelector<HTMLElement>("[data-plan-list]");
const empty = document.querySelector<HTMLElement>("[data-plan-empty]");
const count = document.querySelector<HTMLElement>("[data-plan-count]");
const readPlan = (): Array<Record<string, string>> => {
try { const value = JSON.parse(localStorage.getItem(planStorageKey) || "[]"); return Array.isArray(value) ? value : []; }
catch { return []; }
};
const render = () => {
if (!list || !empty) return;
const plan = readPlan();
list.replaceChildren();
empty.hidden = plan.length > 0;
if (count) count.textContent = `${plan.length} из 5 точек`;
plan.forEach(item => {
const card = document.createElement("article"); card.className = "plan-card";
const heading = document.createElement("h2"); heading.textContent = item.waterbody || "Водоём не указан";
const coordinate = document.createElement("strong"); coordinate.textContent = item.coordinates || "Координаты не указаны";
const meta = document.createElement("p"); meta.textContent = item.baits ? `Наживка: ${item.baits.split("|").join(", ")}` : "Наживка не указана";
const facts = document.createElement("small"); facts.textContent = [item.freshness ? "Свежесть сохранена" : "Свежесть не указана", item.confidence ? `Доверие: ${item.confidence}%` : "Доверие не рассчитано"].join(" · ");
const link = document.createElement("a"); link.href = item.key || "/"; link.textContent = "Открыть точку";
const remove = document.createElement("button"); remove.type = "button"; remove.dataset.action = "quiet"; remove.textContent = "Убрать"; remove.addEventListener("click", () => { localStorage.setItem(planStorageKey, JSON.stringify(readPlan().filter(entry => entry.key !== item.key))); render(); });
const actions = document.createElement("div"); actions.className = "plan-card__actions"; actions.append(link, remove);
card.append(heading, coordinate, meta, facts, actions); list.append(card);
});
};
document.querySelector<HTMLButtonElement>("[data-plan-print]")?.addEventListener("click", () => window.print());
document.querySelector<HTMLButtonElement>("[data-plan-clear]")?.addEventListener("click", () => { localStorage.removeItem(planStorageKey); render(); });
render();
</script>