feat: add method and risk to fishing plans
This commit is contained in:
@@ -16,7 +16,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
if (!Array.isArray(value)) return [];
|
||||
return value.filter(item => item && typeof item === "object" && typeof item.key === "string" && item.key.startsWith("/spots/")).slice(0, 5).map(item => {
|
||||
const source = item as Record<string, unknown>;
|
||||
return Object.fromEntries(["key", "waterbody", "coordinates", "baits", "freshness", "confidence"].map(key => [key, typeof source[key] === "string" ? source[key] : ""]));
|
||||
return Object.fromEntries(["key", "waterbody", "coordinates", "baits", "method", "retrieve", "risk", "freshness", "confidence"].map(key => [key, typeof source[key] === "string" ? source[key] : ""]));
|
||||
});
|
||||
};
|
||||
const readPlan = (): Array<Record<string, string>> => {
|
||||
@@ -36,11 +36,12 @@ import Layout from "../layouts/Layout.astro";
|
||||
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 approach = document.createElement("p"); approach.textContent = [item.method, item.retrieve].filter(Boolean).join(" · ") || "Метод не указан";
|
||||
const facts = document.createElement("small"); facts.textContent = [item.risk ? `Риск: ${item.risk}` : "Риск не рассчитан", 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);
|
||||
card.append(heading, coordinate, meta, approach, facts, actions); list.append(card);
|
||||
});
|
||||
};
|
||||
document.querySelector<HTMLButtonElement>("[data-plan-share]")?.addEventListener("click", async () => {
|
||||
|
||||
@@ -26,6 +26,10 @@ try {
|
||||
}
|
||||
const level = activity ? activityLevel(activity.activity_score) : null;
|
||||
const coordinatePrecision = { exact: "точные", approximate: "приблизительные", area: "район", missing: "не указаны" } as const;
|
||||
const methodLabels: Record<string, string> = { spinning: "Спиннинг", bottom: "Донная", float: "Поплавочная" };
|
||||
const method = catches.map(item => item.fishing_method).find(Boolean) ?? "";
|
||||
const retrieve = catches.map(item => item.retrieve_method).find(Boolean) ?? "";
|
||||
const risk = activity ? activity.catches < 3 ? "Малая выборка" : activity.confidence_score < 50 ? "Низкая уверенность" : "Подтверждено" : "Нет оценки";
|
||||
const spotDescription = spot ? `Свежие уловы и активность на точке ${spot.x}:${spot.y}, ${spot.waterbody}: рыба, вес, приманки и источники данных.` : "Данные точки ловли Russian Fishing 4.";
|
||||
const breadcrumbs = spot ? { "@context": "https://schema.org", "@type": "BreadcrumbList", itemListElement: [
|
||||
{ "@type": "ListItem", position: 1, name: "Сейчас клюёт", item: "https://rf4spotter.ru/" },
|
||||
@@ -35,7 +39,7 @@ const breadcrumbs = spot ? { "@context": "https://schema.org", "@type": "Breadcr
|
||||
<Layout title={spot ? `Точка ${spot.x}:${spot.y}, ${spot.waterbody} — RF4 Spotter` : "Точка не найдена — RF4 Spotter"} description={spotDescription} noindex={!spot} structuredData={breadcrumbs} errorPage={!spot || unavailable}>
|
||||
<AtlasBreadcrumbs items={[{ label: "Сейчас клюёт", href: "/" }, ...(spot ? [{ label: spot.waterbody, href: `/waterbodies/${spot.waterbody_slug}` }, { label: `Точка ${spot.x}:${spot.y}` }] : [{ label: "Точка недоступна" }])]} />
|
||||
{unavailable || !spot ? <div class="state"><h1>Точка недоступна</h1><p>API не ответил или такой точки нет.</p></div> : <>
|
||||
<section class="spot-hero"><div><span class="eyebrow">{spot.waterbody}</span><h1>Точка {spot.x}:{spot.y}</h1><p>{spot.description}</p><p class="coordinate-precision">Точность координат: <strong>{coordinatePrecision[spot.coordinate_precision as keyof typeof coordinatePrecision] ?? "не указаны"}</strong></p><div class="spot-hero__actions"><button class="coordinate-copy" data-action="inverse" type="button" data-copy-coordinates={`${spot.x}:${spot.y}`}>Скопировать координаты</button><button class="plan-save" data-action="inverse" type="button" data-plan-save data-plan-key={Astro.url.pathname} data-plan-waterbody={spot.waterbody} data-plan-coordinates={`${spot.x}:${spot.y}`} data-plan-baits={spot.top_baits.join("|")} data-plan-freshness={activity?.last_confirmed_at ?? ""} data-plan-confidence={activity?.confidence_score ?? ""} aria-pressed="false">Сохранить в план</button><small class="copy-status" aria-live="polite"></small><small class="plan-status" aria-live="polite"></small></div></div><CoordinateRadar x={spot.x} y={spot.y}/></section>
|
||||
<section class="spot-hero"><div><span class="eyebrow">{spot.waterbody}</span><h1>Точка {spot.x}:{spot.y}</h1><p>{spot.description}</p><p class="coordinate-precision">Точность координат: <strong>{coordinatePrecision[spot.coordinate_precision as keyof typeof coordinatePrecision] ?? "не указаны"}</strong></p><div class="spot-hero__actions"><button class="coordinate-copy" data-action="inverse" type="button" data-copy-coordinates={`${spot.x}:${spot.y}`}>Скопировать координаты</button><button class="plan-save" data-action="inverse" type="button" data-plan-save data-plan-key={Astro.url.pathname} data-plan-waterbody={spot.waterbody} data-plan-coordinates={`${spot.x}:${spot.y}`} data-plan-baits={spot.top_baits.join("|")} data-plan-method={methodLabels[method] ?? method} data-plan-retrieve={retrieve} data-plan-risk={risk} data-plan-freshness={activity?.last_confirmed_at ?? ""} data-plan-confidence={activity?.confidence_score ?? ""} aria-pressed="false">Сохранить в план</button><small class="copy-status" aria-live="polite"></small><small class="plan-status" aria-live="polite"></small></div></div><CoordinateRadar x={spot.x} y={spot.y}/></section>
|
||||
<div class="periods"><div><strong>{spot.catches_24h}</strong><span>за 24 часа</span></div><div><strong>{spot.catches_3d}</strong><span>за 3 дня</span></div><div><strong>{spot.catches_7d}</strong><span>за 7 дней</span></div></div>
|
||||
<ActivityTimeline buckets={timeline}/>
|
||||
<div class="activity-legend" aria-label="Уровни активности"><span>Тихо</span><span>Есть сигналы</span><span>Горячо</span></div>
|
||||
@@ -76,7 +80,7 @@ const breadcrumbs = spot ? { "@context": "https://schema.org", "@type": "Breadcr
|
||||
const plan = readPlan();
|
||||
const index = plan.findIndex(item => item.key === key);
|
||||
if (index >= 0) { plan.splice(index, 1); if (status) status.textContent = "Удалено из плана"; }
|
||||
else { plan.unshift({ key, waterbody: button.dataset.planWaterbody || "", coordinates: button.dataset.planCoordinates || "", baits: button.dataset.planBaits || "", freshness: button.dataset.planFreshness || "", confidence: button.dataset.planConfidence || "" }); if (status) status.textContent = "Добавлено в план"; }
|
||||
else { plan.unshift({ key, waterbody: button.dataset.planWaterbody || "", coordinates: button.dataset.planCoordinates || "", baits: button.dataset.planBaits || "", method: button.dataset.planMethod || "", retrieve: button.dataset.planRetrieve || "", risk: button.dataset.planRisk || "", freshness: button.dataset.planFreshness || "", confidence: button.dataset.planConfidence || "" }); if (status) status.textContent = "Добавлено в план"; }
|
||||
localStorage.setItem(planStorageKey, JSON.stringify(plan.slice(0, 5)));
|
||||
sync();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user