Files
galaxy-game/ui/frontend/src/lib/active-view/report/section-race-exit-warnings.svelte
T
Ilia Denisov 9e9977d5f1
Tests · Go / test (push) Successful in 2m29s
Tests · UI / test (push) Waiting to run
Tests · Go / test (pull_request) Successful in 2m17s
Tests · Integration / integration (pull_request) Successful in 1m53s
Tests · UI / test (pull_request) Successful in 3m37s
feat(game): race exit warnings in the turn report (#12)
Surface the inactivity-removal countdown the rules promise but the
engine never reported. A race within five turns of being auto-removed
for inactivity gets a personal warning in its own report; every race
within three turns is listed publicly to all participants.

- model: Report.PersonalExitWarning + RacesLeavingSoon ([]RaceExitNotice)
- fbs: RaceExitNotice table + Report.personal_exit_warning /
  races_leaving_soon (regenerated Go + TS bindings)
- transcoder: encode/decode both fields
- engine: ReportExitWarnings fills the recipient's TTL (1..5) and lists
  other non-extinct races with TTL 1..3, excluding the recipient itself
- ui: danger-styled personal banner + "races leaving soon" section
  (hidden when empty), wired into the report view, EN/RU i18n
- docs: rules.txt report-section list, FUNCTIONAL.md 6.4 + RU mirror

Voluntary quit and idle timeout share the TTL countdown and are not
distinguished, per the agreed scope.
2026-05-31 10:34:50 +02:00

71 lines
2.0 KiB
Svelte

<!--
Report View — races leaving soon section. Surfaces the public
`racesLeavingSoon` projection: every other race within three turns of
being auto-removed for inactivity, with the number of turns each has
left. This is the public counterpart to the personal exit-warning
banner the report view renders at the top for the local race.
Unlike the other report sections, this one hides entirely when the
list is empty rather than showing an empty-state line: an absent
notice is the normal, healthy case for an active game, so a permanent
"no races leaving" row would be noise. The section's TOC entry stays
registered; clicking it while the section is hidden is a silent no-op
through the table-of-contents' existing `getElementById` guard.
-->
<script lang="ts">
import { getContext } from "svelte";
import { i18n } from "$lib/i18n/index.svelte";
import {
RENDERED_REPORT_CONTEXT_KEY,
type RenderedReportSource,
} from "$lib/rendered-report.svelte";
const rendered = getContext<RenderedReportSource | undefined>(
RENDERED_REPORT_CONTEXT_KEY,
);
const report = $derived(rendered?.report ?? null);
const rows = $derived(report?.racesLeavingSoon ?? []);
</script>
{#if rows.length > 0}
<section
id="report-race-exit-warnings"
class="grid-section"
data-testid="report-section-race-exit-warnings"
>
<h2>{i18n.t("game.report.section.race_exit_warnings.title")}</h2>
<ul class="notices" data-testid="race-exit-warnings-list">
{#each rows as r (r.race)}
<li data-testid="race-exit-warnings-row" data-race={r.race}>
{i18n.t("game.report.section.race_exit_warnings.notice", {
race: r.race,
turns: String(r.turnsLeft),
})}
</li>
{/each}
</ul>
</section>
{/if}
<style>
.grid-section h2 {
margin: 0 0 0.5rem;
font-size: 1.05rem;
color: var(--color-text);
}
.notices {
margin: 0;
padding-left: 1.1rem;
display: flex;
flex-direction: column;
gap: 0.3rem;
font-size: 0.9rem;
color: var(--color-warning);
}
.notices li {
margin: 0;
}
</style>