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.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
<!--
|
||||
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>
|
||||
Reference in New Issue
Block a user