sync
CI / backend-and-migrations (push) Canceled after 0s
CI / astro-build (push) Canceled after 0s
CI / dependency-audit (push) Canceled after 0s
CI / compose-e2e (push) Canceled after 0s

This commit is contained in:
ik
2026-09-17 07:35:04 +07:00
parent 5221442aeb
commit 722c88d436
25 changed files with 673 additions and 40 deletions
+2 -1
View File
@@ -8,6 +8,7 @@ import TackleGlyph from "./TackleGlyph.astro";
const { item } = Astro.props as { item: Activity };
const level = activityLevel(item.activity_score);
const limited = item.catches < 3;
const precision = { exact: "точные", approximate: "приблизительные", area: "район", missing: "не указаны" }[item.coordinate_precision];
---
<a class="spot-card" data-testid={`spot-${item.x}-${item.y}`} href={spotPath(item)}>
<span class="spot-rank">{String(item.activity_score).padStart(2,"0")}</span>
@@ -15,7 +16,7 @@ const limited = item.catches < 3;
<div class="spot-topline"><span>{item.waterbody}</span><span class="activity-pill" data-activity-level={level.short}><i></i>{level.short}</span>{limited && <span class="data-quality">Данных мало</span>}</div>
<h3>{item.fish}</h3>
<FishSilhouette name={item.fish}/>
<div class="spot-meta"><span><FishingIcon name="pin" size={14}/> {item.x}:{item.y}</span><span><FishingIcon name="clock" size={14}/> {ago(item.last_confirmed_at)}</span></div>
<div class="spot-meta"><span><FishingIcon name="pin" size={14}/> {item.x}:{item.y} · {precision}</span><span><FishingIcon name="clock" size={14}/> {ago(item.last_confirmed_at)}</span></div>
<p class="data-note">{item.explanation}</p>
<DataPassport sources={item.sources} observedAt={item.last_confirmed_at} confidence={item.confidence_score}/>
<div class="bait-line"><TackleGlyph name={item.best_bait}/><div><span>Работает сейчас</span><strong>{item.best_bait ?? "не указана"}</strong></div></div>
+7 -1
View File
@@ -4,6 +4,12 @@ import type { MediaAsset } from "../lib/api";
const { asset, compact = false, sourceLink = false } = Astro.props as { asset: MediaAsset; compact?: boolean; sourceLink?: boolean };
---
<figure class:list={["entity-media", { "entity-media--compact": compact }]}>
<span class="entity-media__frame"><img src={asset.image_url} alt={asset.label ?? "Иллюстрация RF4"} width={asset.width} height={asset.height} loading="lazy" decoding="async" /></span>
<span class="entity-media__frame"><picture>
{(["avif", "webp"] as const).map(format => {
const variants = (asset.variants ?? []).filter(item => item.format === format);
return variants.length ? <source type={`image/${format}`} srcset={variants.map(item => `${item.url} ${item.width}w`).join(", ")} sizes={compact ? "180px" : "(max-width: 720px) 100vw, 720px"} /> : null;
})}
<img src={asset.image_url} alt={asset.label ?? "Иллюстрация RF4"} width={asset.width} height={asset.height} loading="lazy" decoding="async" />
</picture></span>
<figcaption><SourceBadge source={asset.source_system} href={sourceLink ? asset.source_url : undefined} /><span>{asset.label ?? "Справочный материал"}</span></figcaption>
</figure>