Ekran — Globus
Przegląd
Globus to ekran główny aplikacji po zalogowaniu dziecka. Wyświetla uproszczoną mapę 2D (ilustrowaną) z pinezkami oznaczającymi kraje (światy). Dziecko przesuwa mapę palcem i tapuje kraj, żeby wejść na jego mapę. Na dole ekranu znajduje się dolna nawigacja (bottom nav bar) prowadząca do 4 głównych sekcji.
Uwaga: Globus 3D planowany na przyszłą iterację. Na start używamy ilustrowanej mapy 2D.
Routing (GoRouter)
dart
// Globus jest root-em ShellRoute z bottom navigation
ShellRoute(
builder: (context, state, child) => MainShell(child: child),
routes: [
GoRoute(path: '/globe', builder: (_, __) => GlobeScreen()),
GoRoute(path: '/cosmos', builder: (_, __) => CosmosScreen()),
GoRoute(path: '/spaceship', builder: (_, __) => SpaceshipScreen()),
GoRoute(path: '/profile', builder: (_, __) => ProfileScreen()),
],
),Riverpod Providers
dart
// Lista światów z serwera
final worldsProvider = FutureProvider<List<World>>((ref) {
return ref.watch(worldRepositoryProvider).getWorlds();
});
// Aktualnie wybrany świat (po tapnięciu pinu)
final selectedWorldProvider = StateProvider<World?>((ref) => null);
// Stan pozycji mapy (pan offset + zoom level)
final mapPositionProvider = StateProvider<MapPosition>((ref) {
return MapPosition(offsetX: 0, offsetY: 0, zoom: 1.0); // Domyślnie: widok na Polskę
});
// Indeks aktywnej zakładki w bottom nav
final activeTabProvider = StateProvider<int>((ref) => 0);ASCII Wireframe
┌──────────────────────────────────┐
│ Lumos Islands 🔔 ⚙️ │
├──────────────────────────────────┤
│ │
│ │
│ ┌─────────────┐ │
│ / ___ \ │
│ / / \ [3] \ │
│ │ / PL \ │ │
│ │ │ [5] │ DE │ │
│ │ \ / [2] │ │
│ \ \____/ / │
│ \ ES / │
│ \ [4] FR / │
│ \ [3] / │
│ \_________/ │
│ │
│ (przesuń palcem) │
│ │
│ ┌────────────────────────────┐ │
│ │ 🇵🇱 Polska ▶ │ │
│ │ 5 lokacji · 12 zadań │ │
│ └────────────────────────────┘ │
│ │
├──────────────────────────────────┤
│ 🌍 🪐 🚀 👤 │
│ Globus Kosmos Statek Profil│
└──────────────────────────────────┘Stan po tapnięciu pinu
┌──────────────────────────────────┐
│ Lumos Islands 🔔 ⚙️ │
├──────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ / \ │
│ / ___ \ │
│ │ / PL \ │ │
│ │ │ [●5] │ │ │
│ \ \____/ / │
│ \_____________ / │
│ │
│ │
│ ┌────────────────────────────┐ │
│ │ │ │
│ │ 🇵🇱 Polska │ │
│ │ │ │
│ │ Lokacje: 5 │ │
│ │ Ukończone: 2/5 │ │
│ │ Zadania: 38 │ │
│ │ │ │
│ │ [ ODKRYWAJ → ] │ │
│ │ │ │
│ └────────────────────────────┘ │
│ │
├──────────────────────────────────┤
│ 🌍 🪐 🚀 👤 │
│ Globus Kosmos Statek Profil│
└──────────────────────────────────┘Komponenty
| Komponent | Opis |
|---|---|
IllustratedMapView | Ilustrowana mapa 2D z obsługą gestów (pan, zoom). Widget oparty na InteractiveViewer z custom-painted pinezkami |
CountryPin | Pinezka na mapie: flaga kraju + badge z liczbą lokacji |
CountryInfoCard | Karta wyświetlana po tapnięciu pinu: nazwa, flaga, statystyki, przycisk "ODKRYWAJ" |
GlobeAppBar | App bar z logo, ikoną powiadomień i ustawień |
BottomNavBar | Dolna nawigacja: Globus, Kosmos, Statek, Profil |
MapHint | Podpowiedź "Przesuń palcem" (znika po pierwszym geście) |
Logika
- Przy wejściu na ekran — pobranie listy światów (
GET /app/worlds) - Pinezki renderowane na mapie na podstawie współrzędnych z API
- Tap na pinezkę → wyświetlenie
CountryInfoCard(bottom sheet lub overlay) - Przycisk "ODKRYWAJ" → nawigacja do
/world/:id(ekran Mapa Kraju) - Bottom nav → przełączanie między głównymi sekcjami
Gesty mapy
| Gest | Akcja |
|---|---|
| Drag (1 palec) | Przesuwanie mapy (pan) |
| Pinch (2 palce) | Zoom in/out |
| Tap na pin | Wyświetlenie karty informacyjnej kraju |
| Tap na puste miejsce | Ukrycie karty informacyjnej |
| Double tap | Zoom in na punkt |
Endpoint
| Metoda | Endpoint | Opis |
|---|---|---|
| GET | /app/worlds | Lista wszystkich światów (krajów) |
Response:
json
{
"data": [
{
"id": "world-pl",
"name": "Polska",
"flag_emoji": "🇵🇱",
"flag_url": "https://...",
"lat": 52.0,
"lon": 21.0,
"location_count": 5,
"completed_locations": 2,
"task_count": 38,
"thumbnail_url": "https://..."
},
{
"id": "world-de",
"name": "Niemcy",
"flag_emoji": "🇩🇪",
"flag_url": "https://...",
"lat": 51.1,
"lon": 10.4,
"location_count": 3,
"completed_locations": 0,
"task_count": 22,
"thumbnail_url": "https://..."
}
]
}Bottom Navigation Bar
| Indeks | Ikona | Label | Route |
|---|---|---|---|
| 0 | Globe | Globus | /globe |
| 1 | Planet | Kosmos | /cosmos |
| 2 | Rocket | Statek | /spaceship |
| 3 | Person | Profil | /profile |
Aktywna zakładka wyróżniona kolorem brand-primary. Ikony z pakietu lucide_icons lub custom SVG.
Stany Ekranu
| Stan | Widok |
|---|---|
| Ładowanie | Mapa ze skeleton loader (pulsujące piny) |
| Dane | Pełna mapa z pinezkami |
| Błąd | Mapa bez pinezek + ErrorView z przyciskiem "Spróbuj ponownie" |
| Pusty | Mapa bez pinezek + komunikat "Wkrótce pojawią się nowe światy!" |
Uwagi Techniczne
- Mapa 2D oparta na
InteractiveViewer— lekka, działa płynnie na wszystkich urządzeniach - Początkowa pozycja mapy ustawiona na lokalizację użytkownika (jeśli dostępna) lub domyślnie wycentrowana na Polskę
- Pinezki cachowane lokalnie — odświeżanie pull-to-refresh lub przy powrocie na ekran
- Delikatna animacja przybliżenia przy pierwszym wejściu (zoom-in przez 1s na domyślny kraj)
- Globus 3D planowany na przyszłą iterację (potencjalnie
flutter_globelub custom shader)