Ekran — Kosmos
Przegląd
Kosmos to ekran planet (custom worlds) tworzonych przez rodziców, szkoły lub moderatorów. Dziecko może przeglądać otwarte planety i do nich dołączać. Ekran ma dwie zakładki: "Otwarte" (public planets) i "Moje" (joined planets). Tap na planetę otwiera jej mapę (reuse ekranu Mapa Kraju).
Routing (GoRouter)
dart
// Kosmos jest częścią ShellRoute (bottom nav)
GoRoute(path: '/cosmos', builder: (_, __) => CosmosScreen()),
// Mapa planety reużywa MapScreen z parametrem "planet"
GoRoute(
path: '/planet/:planetId',
builder: (context, state) => MapScreen(
worldId: state.pathParameters['planetId']!,
isPlanet: true,
),
),Riverpod Providers
dart
// Otwarte planety (public, z paginacją)
final openPlanetsProvider = StateNotifierProvider<PlanetListNotifier, PaginatedList<Planet>>(
(ref) => PlanetListNotifier(
ref.watch(planetRepositoryProvider),
type: PlanetListType.open,
),
);
// Moje planety (joined, z paginacją)
final myPlanetsProvider = StateNotifierProvider<PlanetListNotifier, PaginatedList<Planet>>(
(ref) => PlanetListNotifier(
ref.watch(planetRepositoryProvider),
type: PlanetListType.mine,
),
);
// Aktywna zakładka (0 = Otwarte, 1 = Moje)
final cosmosTabProvider = StateProvider<int>((ref) => 0);
// Stan join/leave (loading per planet)
final planetActionProvider = StateProvider.family<AsyncValue<void>, String>(
(ref, planetId) => const AsyncValue.data(null),
);ASCII Wireframe
┌──────────────────────────────────┐
│ Kosmos 🔍 │
├──────────────────────────────────┤
│ ┌──────────────┬───────────────┐│
│ │ Otwarte │ Moje ││
│ │ (aktywna) │ ││
│ └──────────────┴───────────────┘│
│ │
│ ┌────────────────────────────┐ │
│ │ ┌────────┐ │ │
│ │ │ 🪐 │ Planeta Nauki │ │
│ │ │ (img) │ │ │
│ │ │ │ 👥 42 uczniów │ │
│ │ └────────┘ 📍 8 lokacji │ │
│ │ │ │
│ │ Planeta z zadaniami z │ │
│ │ matematyki i fizyki. │ │
│ │ │ │
│ │ [ DOŁĄCZ ] │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ ┌────────┐ │ │
│ │ │ 🌍 │ Szkoła ABC │ │
│ │ │ (img) │ │ │
│ │ │ │ 👥 128 uczniów │ │
│ │ └────────┘ 📍 12 lokacji │ │
│ │ │ │
│ │ Planeta klasy 3a z SP 12. │ │
│ │ │ │
│ │ [ DOŁĄCZ ] │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ ┌────────┐ │ │
│ │ │ 🔬 │ Lab Przyrody │ │
│ │ │ (img) │ │ │
│ │ │ │ 👥 67 uczniów │ │
│ │ └────────┘ 📍 5 lokacji │ │
│ │ │ │
│ │ Eksperymenty i odkrycia. │ │
│ │ │ │
│ │ [ DOŁĄCZ ] │ │
│ └────────────────────────────┘ │
│ │
│ (ładowanie kolejnych...) │
│ │
├──────────────────────────────────┤
│ 🌍 🪐 🚀 👤 │
│ Globus Kosmos Statek Profil│
└──────────────────────────────────┘Zakładka "Moje"
┌──────────────────────────────────┐
│ Kosmos 🔍 │
├──────────────────────────────────┤
│ ┌──────────────┬───────────────┐│
│ │ Otwarte │ Moje ││
│ │ │ (aktywna) ││
│ └──────────────┴───────────────┘│
│ │
│ ┌────────────────────────────┐ │
│ │ ┌────────┐ │ │
│ │ │ 🪐 │ Planeta Nauki │ │
│ │ │ (img) │ │ │
│ │ │ │ 👥 42 uczniów │ │
│ │ └────────┘ 📍 8 lokacji │ │
│ │ │ │
│ │ Postęp: ████████░░ 75% │ │
│ │ │ │
│ │ [ ODKRYWAJ ] [ OPUŚĆ ] │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ ┌────────┐ │ │
│ │ │ 📚 │ Klub Książki │ │
│ │ │ (img) │ │ │
│ │ │ │ 👥 15 uczniów │ │
│ │ └────────┘ 📍 3 lokacji │ │
│ │ │ │
│ │ Postęp: ██░░░░░░░░ 20% │ │
│ │ │ │
│ │ [ ODKRYWAJ ] [ OPUŚĆ ] │ │
│ └────────────────────────────┘ │
│ │
│ ── Koniec listy ── │
│ │
├──────────────────────────────────┤
│ 🌍 🪐 🚀 👤 │
│ Globus Kosmos Statek Profil│
└──────────────────────────────────┘Stan pusty (Moje)
┌──────────────────────────────────┐
│ Kosmos 🔍 │
├──────────────────────────────────┤
│ ┌──────────────┬───────────────┐│
│ │ Otwarte │ Moje ││
│ │ │ (aktywna) ││
│ └──────────────┴───────────────┘│
│ │
│ │
│ │
│ 🪐 │
│ │
│ Nie masz jeszcze │
│ żadnych planet. │
│ │
│ Przejdź do "Otwarte" │
│ i dołącz do planety! │
│ │
│ [ PRZEGLĄDAJ OTWARTE ] │
│ │
│ │
│ │
├──────────────────────────────────┤
│ 🌍 🪐 🚀 👤 │
│ Globus Kosmos Statek Profil│
└──────────────────────────────────┘Komponenty
| Komponent | Opis |
|---|---|
CosmosTabBar | Dwie zakładki: "Otwarte" i "Moje" |
PlanetCard | Karta planety: obrazek, nazwa, liczba uczniów, lokacji, opis |
PlanetCard.open | Wariant z przyciskiem "DOŁĄCZ" |
PlanetCard.joined | Wariant z postępem + "ODKRYWAJ" / "OPUŚĆ" |
JoinButton | Przycisk dołączania (z loading state) |
LeaveButton | Przycisk opuszczania (z dialogiem potwierdzenia) |
SearchBar | Pole wyszukiwania planet (ikona lupy w app bar) |
EmptyStateView | Widok pustej listy z ikoną i CTA |
InfiniteScrollList | ListView z lazy loading (cursor pagination) |
PlanetCardSkeleton | Skeleton loader karty planety |
Logika
- Domyślna zakładka: "Otwarte"
- Lista planet —
ListView.builderz infinite scroll (cursor pagination) - "DOŁĄCZ" →
POST /app/planets/:id/join→ przeniesienie karty na "Moje" - "OPUŚĆ" → dialog potwierdzenia →
POST /app/planets/:id/leave→ usunięcie z "Moje" - "ODKRYWAJ" → nawigacja do
/planet/:planetId(reuse MapScreen) - Pull-to-refresh w obu zakładkach
- Wyszukiwarka → filtr po nazwie (lokalnie) lub API search (jeśli dostępny)
Dialog opuszczania planety
┌────────────────────────────────┐
│ │
│ Opuścić planetę? │
│ │
│ Twój postęp zostanie │
│ zachowany. Możesz wrócić │
│ w każdej chwili. │
│ │
│ [ ANULUJ ] [ OPUŚĆ ] │
│ │
└────────────────────────────────┘Endpointy
| Metoda | Endpoint | Opis |
|---|---|---|
| GET | /app/planets/open | Lista otwartych planet |
| GET | /app/planets/mine | Lista moich planet |
| POST | /app/planets/:id/join | Dołącz do planety |
| POST | /app/planets/:id/leave | Opuść planetę |
Query params (lista):
| Param | Typ | Domyślnie | Opis |
|---|---|---|---|
cursor | string | – | Kursor paginacji |
limit | int | 20 | Maks. elementów |
search | string | – | Wyszukiwanie po nazwie |
Open Planets Response:
json
{
"data": [
{
"id": "planet-nauka",
"name": "Planeta Nauki",
"description": "Planeta z zadaniami z matematyki i fizyki.",
"image_url": "https://...",
"member_count": 42,
"location_count": 8,
"created_by": "Szkoła Podstawowa nr 5"
}
],
"next_cursor": "eyJpZCI6MjB9",
"has_more": true
}My Planets Response:
json
{
"data": [
{
"id": "planet-nauka",
"name": "Planeta Nauki",
"description": "Planeta z zadaniami z matematyki i fizyki.",
"image_url": "https://...",
"member_count": 42,
"location_count": 8,
"progress_percent": 75,
"created_by": "Szkoła Podstawowa nr 5"
}
],
"next_cursor": null,
"has_more": false
}Join Response:
json
{
"data": {
"joined": true,
"planet_id": "planet-nauka"
}
}Leave Response:
json
{
"data": {
"left": true,
"planet_id": "planet-nauka"
}
}Stany Ekranu
| Stan | Widok |
|---|---|
| Ładowanie | Skeleton karty planety (3 sztuki z shimmer) |
| Dane | Lista kart planet |
| Pusty (Otwarte) | "Brak dostępnych planet" |
| Pusty (Moje) | EmptyStateView z CTA do "Otwarte" |
| Błąd | ErrorView z przyciskiem retry |
| Join loading | Przycisk "DOŁĄCZ" z loading spinner |
| Leave loading | Przycisk "OPUŚĆ" z loading spinner |
Uwagi Techniczne
- Osobne providery dla "Otwarte" i "Moje" — niezależna paginacja
- Po join/leave → invalidacja obu list (
ref.invalidate) - Optimistic update: po "DOŁĄCZ" karta od razu przenosi się na "Moje" (rollback przy błędzie)
- Obrazki planet cachowane (CachedNetworkImage)
- Tab state zachowany przy przełączaniu zakładek (scroll position per tab)