MISSIONS tab: mission generation, accept & complete #10

Closed
opened 2026-09-28 23:13:30 +02:00 by kamilkrzywda · 1 comment
Owner

Goal

Make the MISSIONS tab functional: missions generated from the world (deliver to a system, explore N planets, find something), accepted and completed for rewards.

Scope

  • DB: missions table (id, type, description, target/condition, reward, state: AVAILABLE/ACTIVE/DONE). Generated on new game + refreshed as the player jumps/explores.
  • Actions: POST /api/missions/{id}/accept; completion checked after relevant actions (jump to target system, exploration count, etc.); rewards granted (resources/parts) and event written.
  • API: GET /api/missions, accept endpoint. Update OpenAPI spec.
  • Frontend: real mission cards with state badges; ACCEPT button on AVAILABLE missions; no placeholder data for this tab.

Acceptance criteria

  • Unit tests: generation, acceptance (one active at a time or as designed), completion conditions, reward application.
  • e2e: accept a mission → complete it by performing the required action → DONE + reward visible in inventory; persists across restart.
  • Local verify green: tsc / vitest / playwright --list (+ build DOM check).

Dependencies

After WORLD MAP (targets are systems); explore-type missions need LOCAL SYSTEM.

## Goal Make the MISSIONS tab functional: missions generated from the world (deliver to a system, explore N planets, find something), accepted and completed for rewards. ## Scope - **DB:** `missions` table (id, type, description, target/condition, reward, state: AVAILABLE/ACTIVE/DONE). Generated on new game + refreshed as the player jumps/explores. - **Actions:** `POST /api/missions/{id}/accept`; completion checked after relevant actions (jump to target system, exploration count, etc.); rewards granted (resources/parts) and event written. - **API:** `GET /api/missions`, accept endpoint. Update OpenAPI spec. - **Frontend:** real mission cards with state badges; ACCEPT button on AVAILABLE missions; no placeholder data for this tab. ## Acceptance criteria - Unit tests: generation, acceptance (one active at a time or as designed), completion conditions, reward application. - e2e: accept a mission → complete it by performing the required action → DONE + reward visible in inventory; persists across restart. - Local verify green: tsc / vitest / playwright --list (+ build DOM check). ## Dependencies After WORLD MAP (targets are systems); explore-type missions need LOCAL SYSTEM.
Author
Owner

Done in v0.8.0 (PR #17, merge commit 6c828e4), deployed to https://space-wanderer.dev.kkhost.pl — verified /api/version → 0.8.0 and the live save backfilled its mission board via schema step v6 (no DB wipe).

What shipped:

  • DB: new missions table (type/description/target_system_id/condition_kind/progress_target/progress/reward/state); deterministic seeded generation anchored by turn (missionRng(seed, turn) — same style as world expansion); board topped up to ≥3 AVAILABLE after every action; one ACTIVE at a time. Backfill step v6 (SCHEMA_VERSION 5→6) — old saves get their board on first read.
  • Types: DELIVER (jump to target system — discovered non-current only), EXPLORE (scan N = 2–4 bodies), FIND (haul in an item of one kind). Completion hooks inside jumpToSystem/explorePlanet before persist → completion + reward + top-up land in one atomic write; rewards granted as inventory rows.
  • API: GET /api/missions, POST /api/missions/{id}/accept (400 non-integer id, 404 unknown, 409 wrong-state/active-conflict — no mutation on failure); accepting costs a turn + writes an event. OpenAPI now documents 14 paths.
  • UI: live mission cards with state badges, objective/reward lines and EXPLORE progress; ACCEPT enabled only when AVAILABLE and nothing else is ACTIVE; refetch on tab open, responses applied directly (no polling). Placeholder removed.
  • Tests: unit 59 → 73 (generation determinism over 200 draws, top-up idempotency/floor, v6 backfill, accept validation + turn/event, per-type completion incl. wrong-system non-completion and reward accumulation); e2e 13 → 14 (accept in UI → complete via scan loop/BFS jump path → DONE + reward in hold; board deep-equal across restart).
  • CI note: first run failed on an e2e locator bug — the ACTIVE badge renders a "●" dot prefix so getByText('ACTIVE', {exact:true}) could never match, and the test wasn't idempotent across retries sharing the CI DB. Fixed e2e-only (non-exact match + tolerate leftover ACTIVE mission); no app code touched.
Done in **v0.8.0** (PR #17, merge commit `6c828e4`), deployed to https://space-wanderer.dev.kkhost.pl — verified `/api/version` → 0.8.0 and the live save backfilled its mission board via schema step v6 (no DB wipe). What shipped: - **DB:** new `missions` table (type/description/target_system_id/condition_kind/progress_target/progress/reward/state); deterministic seeded generation anchored by turn (`missionRng(seed, turn)` — same style as world expansion); board topped up to ≥3 AVAILABLE after every action; one ACTIVE at a time. Backfill step v6 (`SCHEMA_VERSION` 5→6) — old saves get their board on first read. - **Types:** DELIVER (jump to target system — discovered non-current only), EXPLORE (scan N = 2–4 bodies), FIND (haul in an item of one kind). Completion hooks inside `jumpToSystem`/`explorePlanet` before persist → completion + reward + top-up land in one atomic write; rewards granted as inventory rows. - **API:** `GET /api/missions`, `POST /api/missions/{id}/accept` (400 non-integer id, 404 unknown, 409 wrong-state/active-conflict — no mutation on failure); accepting costs a turn + writes an event. OpenAPI now documents 14 paths. - **UI:** live mission cards with state badges, objective/reward lines and EXPLORE progress; ACCEPT enabled only when AVAILABLE and nothing else is ACTIVE; refetch on tab open, responses applied directly (no polling). Placeholder removed. - **Tests:** unit 59 → 73 (generation determinism over 200 draws, top-up idempotency/floor, v6 backfill, accept validation + turn/event, per-type completion incl. wrong-system non-completion and reward accumulation); e2e 13 → 14 (accept in UI → complete via scan loop/BFS jump path → DONE + reward in hold; board deep-equal across restart). - **CI note:** first run failed on an e2e locator bug — the ACTIVE badge renders a "●" dot prefix so `getByText('ACTIVE', {exact:true})` could never match, and the test wasn't idempotent across retries sharing the CI DB. Fixed e2e-only (non-exact match + tolerate leftover ACTIVE mission); no app code touched.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OpenCode/SpaceWanderer#10