Flutter App
Tech Stack
| Technologia | Zastosowanie |
|---|---|
| Flutter / Dart | Framework UI |
| iOS (priorytet) + Android | Platformy docelowe |
| Riverpod | State management |
| GoRouter | Nawigacja / routing |
| Dio | HTTP client (API) |
| Widgetbook | Storybook dla komponentów |
| Flutter Secure Storage | Bezpieczne przechowywanie tokenów |
| flutter_test | Testy widgetów i integracyjne |
Struktura Projektu
app/
├── lib/
│ ├── main.dart # Entry point
│ ├── app.dart # MaterialApp + GoRouter
│ │
│ ├── core/ # Rdzeń aplikacji
│ │ ├── theme/ # Design system (kolory, typografia, spacing)
│ │ ├── router/ # Konfiguracja GoRouter
│ │ ├── network/ # Dio setup, interceptory, error handling
│ │ └── constants/ # Stałe (API URLs, konfiguracja)
│ │
│ ├── features/ # Funkcjonalności (feature-first)
│ │ ├── auth/ # Rejestracja, logowanie, kody
│ │ │ ├── data/ # Repository, modele, API calls
│ │ │ ├── domain/ # Logika biznesowa
│ │ │ └── presentation/ # Ekrany, widgety
│ │ │
│ │ ├── globe/ # Globus z krajami
│ │ ├── map/ # Mapa kraju z lokacjami
│ │ ├── location/ # Lokacja z zadaniami (Netflix-style)
│ │ ├── cosmos/ # Planety (custom worlds)
│ │ ├── spaceship/ # Statek (awatar, todo)
│ │ ├── profile/ # Profil, ustawienia
│ │ └── parent/ # Ekrany rodzica (powiązanie, kody)
│ │
│ ├── shared/ # Współdzielone elementy
│ │ ├── widgets/ # Reużywalne widgety
│ │ ├── models/ # Współdzielone modele danych
│ │ └── providers/ # Globalne providery Riverpod
│ │
│ └── gen/ # Generowany kod (build_runner)
│
├── test/ # Testy
│ ├── unit/
│ ├── widget/
│ └── integration/
│
├── widgetbook/ # Widgetbook (storybook)
│ └── lib/
│ └── main.dart
│
├── ios/ # Konfiguracja iOS
├── android/ # Konfiguracja Android
└── pubspec.yaml # ZależnościArchitektura
Feature-first
Każda funkcjonalność ma własny katalog z podziałem na warstwy:
feature/
├── data/ # Źródła danych
│ ├── models/ # Modele danych (fromJson, toJson)
│ ├── repositories/ # Implementacje repozytoriów
│ └── sources/ # API calls (Dio)
│
├── domain/ # Logika biznesowa (opcjonalnie)
│ └── usecases/ # Use cases
│
└── presentation/ # UI
├── screens/ # Pełne ekrany
├── widgets/ # Widgety specyficzne dla feature
└── providers/ # Riverpod providers dla featureState Management (Riverpod)
// Provider dla listy światów
final worldsProvider = FutureProvider<List<World>>((ref) {
final repository = ref.watch(worldRepositoryProvider);
return repository.getWorlds();
});
// Provider dla aktualnie wybranego świata
final selectedWorldProvider = StateProvider<World?>((ref) => null);
// Ekran korzystający z providera
class GlobeScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final worlds = ref.watch(worldsProvider);
return worlds.when(
data: (data) => GlobeView(worlds: data),
loading: () => LoadingIndicator(),
error: (err, stack) => ErrorView(error: err),
);
}
}Routing (GoRouter)
final router = GoRouter(
routes: [
GoRoute(path: '/', builder: (_, __) => GlobeScreen()),
GoRoute(path: '/world/:id', builder: (_, state) =>
MapScreen(worldId: state.pathParameters['id']!)),
GoRoute(path: '/location/:id', builder: (_, state) =>
LocationScreen(locationId: state.pathParameters['id']!)),
GoRoute(path: '/cosmos', builder: (_, __) => CosmosScreen()),
GoRoute(path: '/spaceship', builder: (_, __) => SpaceshipScreen()),
GoRoute(path: '/profile', builder: (_, __) => ProfileScreen()),
],
);Kluczowe Ekrany
1. Globus
Ekran główny po zalogowaniu. Uproszczona mapa 2D (ilustrowana) z pinezkami krajów do eksploracji.
- Przesuwanie (pan) i zoom mapy
- Piny na krajach z dostępnymi lokacjami
- Przejście do mapy kraju po tapnięciu
Uwaga: Globus 3D planowany na przyszłą iterację.
2. Mapa Kraju
Mapa z lokacjami (camp, biblioteka, fabryka, boisko...) rozmieszczonymi na niej.
- Piny na mapie oznaczające lokacje
- Status lokacji (odblokowana / zablokowana / ukończona)
- Przejście do lokacji po tapnięciu
3. Lokacja (Netflix-style)
Lista zadań w stylu Netflix — przewijalne kafelki z miniaturami.
- Sekcje: video, quizy, podcasty, gry
- Kafelki z miniaturami, tytułami, ikonami typu zadania
- Filtrowanie po grupie wiekowej
- Status zadania (nowe / w trakcie / ukończone)
4. Kosmos (Planety)
Widok planet (custom worlds) stworzonych przez rodziców / szkoły.
- Planety otwarte (open to join)
- Planety przypisane (assigned)
- Przejście do mapy planety
5. Statek
Osobista strefa dziecka.
- Pokój z awatarem (personalizacja)
- Todo lista (zadania od rodzica + własne)
- Odznaki i osiągnięcia
Integracja z Manager-Content
Flutter app komunikuje się z manager-content (Go server) przez endpointy /app/* (REST/JSON). Manager-content przechowuje dane i serwuje je dedykowanymi endpointami dla aplikacji mobilnej.
HTTP Client (Dio)
class ApiClient {
late final Dio _dio;
ApiClient() {
_dio = Dio(BaseOptions(
baseUrl: AppConstants.managerContentUrl, // URL manager-content
connectTimeout: Duration(seconds: 10),
receiveTimeout: Duration(seconds: 10),
));
_dio.interceptors.add(AuthInterceptor());
_dio.interceptors.add(LogInterceptor());
}
}Wzorzec Repository
abstract class WorldRepository {
Future<List<World>> getWorlds();
Future<World> getWorld(String id);
Future<List<Location>> getLocations(String worldId);
}
class WorldRepositoryImpl implements WorldRepository {
final ApiClient _client;
@override
Future<List<World>> getWorlds() async {
final response = await _client.get('/app/worlds');
return (response.data as List)
.map((json) => World.fromJson(json))
.toList();
}
}Design System
Flutter app ma własny design system oparty na:
- Tokeny — kolory, typografia, spacing, border radius
- Komponenty — przyciski, karty, inputy, nawigacja
- Widgetbook — interaktywny katalog komponentów
Szczegóły: Design Systemy
Internacjonalizacja (i18n)
Na start: polski + angielski.
flutter_localizations+ pliki ARB (app_pl.arb,app_en.arb)- Zmiana języka: ekran ustawień na statku
- Język zapisywany w profilu użytkownika (
PATCH /app/users/me) - Wszystkie stringi UI przez
AppLocalizations.of(context)
Szczegóły: Decyzje Techniczne — i18n
Offline i Cache
Minimalne wsparcie offline na start:
- Profil i stats — cache w SharedPreferences (odświeżane przy każdym otwarciu)
- Quizy — mogą być wykonywane offline, sync po reconnect
- Media (video, audio) — wymagają połączenia, brak offline cache
- Todo lista — cache lokalny, optimistic updates
Szczegóły: Decyzje Techniczne — Offline
Push Notifications
Firebase Cloud Messaging (FCM) + APNs:
firebase_messagingpackage- Typy: streak reminder, nowe zadania, parent approve, level up / badge
- Ikona dzwonka w top bar ekranu głównego (mapa)
- Notification history: nie na start, planowane
Szczegóły: Decyzje Techniczne — Push
Platformy
iOS (priorytet)
- Minimum iOS 16+
- Natywne integracje: Push Notifications, Keychain, Sign in with Apple
- Testowanie na symulatorze i fizycznych urządzeniach
Android
- Minimum API 24 (Android 7.0)
- Material Design 3 adaptacje
- Google Play deployment