<goma-missions-hub>
The My Missions hub: an Active / Pending / Finished tab strip over a list of mission cards ("challenger cards"), with per-tab empty states whose illustrations are host-injectable.
Part 1 — UI only
The missions backend is not wired yet, so this widget is host-fed: you push the mission list in via the missions property (the same model as <goma-multi-banners>). A later release adds a live data source.
Tapping a card emits goma:mission-select so a sibling <goma-mission-details> can follow it — the same cooperation pattern as events-horizontal ↔ game-details.
Element tag
html
<goma-missions-hub></goma-missions-hub>Installation
bash
pnpm add @gomagaming/missions-hub vue pinia vue-router vue-i18n @vueuse/coreConfiguration
Set config for the runtime basics (all widgets share this shape):
| Key | Type | Default | Description |
|---|---|---|---|
locale | string | 'en' | i18n locale (en / fr / pt bundled). |
theme | object | Pulse theme | --goma-* token overrides. |
messages | object | — | Per-locale i18n overrides merged over the bundled copy. |
Data source
Host-fed only. Provide the mission list via the missions property (array) or the missions HTML attribute (JSON string).
Assumed Mission shape
js
{
id: 'm1',
platform: 'casino' | 'sports',
title: 'Wager to win top prizes',
imageUrl: 'https://…', // banner
status: null | 'new' | 'suspended' | 'forfeit',
statusLabel: 'New',
totalLevels: 4,
reward: 'Get an extra 100 spins…', // the "Get:" line
termsUrl: 'https://…',
tab: 'active' | 'pending' | 'finished',
joinState: 'active' | 'not-joined' | 'pending' | 'finished' | 'forfeited',
cta: 'start'|'deposit'|'resume'|'view', // optional override; else derived
currentLevel: 2, levelCount: 3, progress: 67, // in-progress badge + bar
endsAt: 1771761283000, // optional ms epoch → "Ends in …"
// finished-tab extras:
totalWon: '50 kr bonus +100 free spins',
levels: [{ level, state: 'completed'|'forfeited', reward, completedAt }],
}Props / attributes
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
missions | missions | Mission[] | [] | The mission list. |
activeTab | active-tab | 'active'|'pending'|'finished' | 'active' | Initial tab; updated when a pill is tapped. |
emptyStateImages | empty-state-images | { active?, pending?, finished? } | {} | Per-tab empty-state illustration URLs. |
offersUrl | offers-url | string | '' | Optional href hint carried in the empty-state CTA event. |
Events
All events are composed + bubbling (cross the Shadow DOM boundary).
| Event | detail | When |
|---|---|---|
goma:mission-select | { missionId, mission } | A mission card was tapped. |
goma:mission-cta | { missionId, action } | A card's CTA (start / deposit / resume / view) was pressed. |
goma:missions-offers | { tab, offersUrl } | The empty-state CTA link (e.g. "See current offers") was pressed. |
ready | {} | Mounted and rendered. |
error | { message, code } | Render error caught by the boundary. |
Embedding
Vanilla / CDN
html
<goma-missions-hub id="hub"></goma-missions-hub>
<script type="module">
import '@gomagaming/missions-hub'
const hub = document.getElementById('hub')
hub.config = { locale: 'en' }
hub.missions = [/* Mission[] */]
hub.emptyStateImages = {
active: 'https://…/goal.svg',
pending: 'https://…/stopwatch.svg',
finished: 'https://…/star.svg',
}
hub.addEventListener('goma:mission-select', (e) => console.log(e.detail.missionId))
</script>React
jsx
import '@gomagaming/missions-hub'
<goma-missions-hub
ref={(el) => {
if (!el) return
el.config = { locale: 'en' }
el.missions = missions
}}
onGoma:mission-select={(e) => openDetail(e.detail.missionId)}
/>Vue
vue
<script setup>
import '@gomagaming/missions-hub'
import { ref } from 'vue'
const missions = ref([/* Mission[] */])
</script>
<template>
<goma-missions-hub
:missions.prop="missions"
@goma:mission-select="onSelect"
/>
</template>Source layout
| Layer | File |
|---|---|
| Element class | packages/missions-hub/src/MissionsHubElement.js |
| App wrapper | packages/missions-hub/src/MissionsHubApp.vue |
| Tab strip | packages/missions-hub/src/components/MissionsHub/MissionsTabPills.vue |
| List | packages/missions-hub/src/components/MissionsHub/MissionsList.vue |
| Shared cards / helpers | packages/sports-domain/src/components/Missions/*, packages/sports-domain/src/composables/missions/useMissions.js |
| Playground manifest | packages/missions-hub/src/playground.manifest.js |
| Tests | packages/missions-hub/tests/{MissionsHub,playground-manifest}.test.js |