Skip to content

Ekran — Wykonanie Zadania

Przegląd

Ekran wykonania zadania obsługuje 5 typow zadan, kazdy z dedykowanym layoutem: quiz, video, podcast, kreatywne, gra. Wszystkie typy dzielą wspólny progress bar, podgląd XP do zdobycia oraz animację ukończenia (confetti, XP, odznaka, level up).

Routing (GoRouter)

dart
GoRoute(
  path: '/task/:taskId',
  builder: (context, state) => TaskScreen(
    taskId: state.pathParameters['taskId']!,
  ),
),

Riverpod Providers

dart
// Pełne dane zadania
final taskDetailProvider = FutureProvider.family<TaskDetail, String>((ref, taskId) {
  return ref.watch(taskRepositoryProvider).getTask(taskId);
});

// Stan wykonania zadania (odpowiedzi, postęp)
final taskProgressProvider = StateNotifierProvider.family<TaskProgressNotifier, TaskProgress, String>(
  (ref, taskId) => TaskProgressNotifier(taskId),
);

// Aktualny krok/pytanie w zadaniu
final currentStepProvider = StateProvider.family<int, String>((ref, taskId) => 0);

// Wynik po ukończeniu (XP, badge, level up)
final taskResultProvider = StateProvider<TaskResult?>((ref) => null);

// Stan audio/video playera
final mediaPlayerProvider = StateNotifierProvider<MediaPlayerNotifier, MediaPlayerState>(
  (ref) => MediaPlayerNotifier(),
);

Layouty per Typ Zadania

1. Quiz

┌──────────────────────────────────┐
│  ← Quiz                    ✕    │
├──────────────────────────────────┤
│  ████████░░░░░░░░ 4/10          │
│                                  │
│  +50 XP                         │
│                                  │
│  ┌────────────────────────────┐  │
│  │  Pytanie 4:                │  │
│  │                            │  │
│  │  Jak nazywa się najwyższa  │  │
│  │  góra w Polsce?            │  │
│  │                            │  │
│  │  (opcjonalnie: obrazek)    │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │  ○  Rysy                   │  │
│  └────────────────────────────┘  │
│  ┌────────────────────────────┐  │
│  │  ○  Giewont                │  │
│  └────────────────────────────┘  │
│  ┌────────────────────────────┐  │
│  │  ●  Śnieżka        ← wyb. │  │
│  └────────────────────────────┘  │
│  ┌────────────────────────────┐  │
│  │  ○  Kasprowy Wierch        │  │
│  └────────────────────────────┘  │
│                                  │
│  [ SPRAWDŹ ]                     │
│                                  │
└──────────────────────────────────┘

Po sprawdzeniu (poprawna):

┌──────────────────────────────────┐
│  ┌────────────────────────────┐  │
│  │  ✅ Rysy         ← poprawna│  │
│  └────────────────────────────┘  │
│  ┌────────────────────────────┐  │
│  │  ○  Giewont                │  │
│  └────────────────────────────┘  │
│  ┌────────────────────────────┐  │
│  │  ❌ Śnieżka       ← błędna│  │
│  └────────────────────────────┘  │
│  ┌────────────────────────────┐  │
│  │  ○  Kasprowy Wierch        │  │
│  └────────────────────────────┘  │
│                                  │
│  💡 Rysy (2499 m) to najwyższy  │
│  szczyt w polskich Tatrach.      │
│                                  │
│  [ NASTĘPNE → ]                  │
└──────────────────────────────────┘

2. Video

┌──────────────────────────────────┐
│  ← Video                   ✕    │
├──────────────────────────────────┤
│                                  │
│  ┌────────────────────────────┐  │
│  │                            │  │
│  │                            │  │
│  │     ▶  (video player)     │  │
│  │                            │  │
│  │                            │  │
│  │  ▶ ████████░░ 5:32 / 8:00 │  │
│  └────────────────────────────┘  │
│                                  │
│  Dinozaury i ich świat           │
│  +50 XP                         │
│                                  │
│  ── Po obejrzeniu ──             │
│                                  │
│  Pytanie 1/3:                    │
│  Kiedy wyginęły dinozaury?       │
│                                  │
│  ○ 65 mln lat temu               │
│  ○ 100 mln lat temu              │
│  ○ 10 mln lat temu               │
│                                  │
│  [ SPRAWDŹ ]                     │
│                                  │
└──────────────────────────────────┘

3. Podcast

┌──────────────────────────────────┐
│  ← Podcast                 ✕    │
├──────────────────────────────────┤
│  ████████████████ ukończony      │
│                                  │
│  ┌────────────────────────────┐  │
│  │                            │  │
│  │      (cover art)           │  │
│  │                            │  │
│  └────────────────────────────┘  │
│                                  │
│  Tajemnice oceanu                │
│  +30 XP                         │
│                                  │
│  ┌────────────────────────────┐  │
│  │  ◀◀   ▶ / ⏸   ▶▶         │  │
│  │  ████████░░░░ 12:30/20:00 │  │
│  │  1x  1.5x  2x             │  │
│  └────────────────────────────┘  │
│                                  │
│  📜 Transkrypt                   │
│  ┌────────────────────────────┐  │
│  │ [12:30] Oceany pokrywają   │  │
│  │ ponad 70% powierzchni      │  │
│  │ Ziemi. W głębinach żyją    │  │
│  │ stworzenia, których...     │  │
│  │                            │  │
│  │ [13:15] Najgłębszy punkt   │  │
│  │ to Rów Mariański...        │  │
│  └────────────────────────────┘  │
│                                  │
│  [ UKOŃCZ PODCAST ]              │
│                                  │
└──────────────────────────────────┘

4. Zadanie Kreatywne

┌──────────────────────────────────┐
│  ← Kreatywne                ✕   │
├──────────────────────────────────┤
│  +40 XP                         │
│                                  │
│  Narysuj swoje wymarzone         │
│  zwierzę!                        │
│                                  │
│  Opisz, jakie ma cechy           │
│  i gdzie mieszka.                │
│                                  │
│  ┌────────────────────────────┐  │
│  │                            │  │
│  │  Wybierz sposób:           │  │
│  │                            │  │
│  │  ┌──────┐ ┌──────┐        │  │
│  │  │  📷  │ │  🎨  │        │  │
│  │  │Zdjęcie│ │Rysunek│       │  │
│  │  └──────┘ └──────┘        │  │
│  │  ┌──────┐                 │  │
│  │  │  📝  │                 │  │
│  │  │ Tekst│                 │  │
│  │  └──────┘                 │  │
│  │                            │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ Opis (opcjonalnie):       │  │
│  │ _________________________ │  │
│  │ _________________________ │  │
│  └────────────────────────────┘  │
│                                  │
│  [ WYŚLIJ PRACĘ ]                │
│                                  │
└──────────────────────────────────┘

5. Mini-gra

┌──────────────────────────────────┐
│  ← Gra                     ✕    │
├──────────────────────────────────┤
│  Labirynt Wiedzy       +60 XP   │
│                                  │
│  ┌────────────────────────────┐  │
│  │                            │  │
│  │                            │  │
│  │                            │  │
│  │   (embedded mini-game      │  │
│  │    WebView / Flutter       │  │
│  │    canvas / Flame)         │  │
│  │                            │  │
│  │                            │  │
│  │                            │  │
│  │                            │  │
│  │                            │  │
│  │                            │  │
│  │                            │  │
│  └────────────────────────────┘  │
│                                  │
│  Czas: 02:45    Wynik: 850      │
│                                  │
└──────────────────────────────────┘

Animacja Ukończenia

Po zakończeniu zadania (dowolny typ) wyświetlany jest ekran z wynikami:

┌──────────────────────────────────┐
│                                  │
│        🎉 CONFETTI 🎉           │
│                                  │
│                                  │
│          ⭐ ŚWIETNIE! ⭐         │
│                                  │
│                                  │
│       ┌──────────────┐           │
│       │   +50 XP     │           │
│       └──────────────┘           │
│                                  │
│       XP: 1240 → 1290           │
│       ██████████████░░ Lvl 5     │
│                                  │
│  ┌────────────────────────────┐  │
│  │  🏅 Nowa odznaka!          │  │
│  │  "Odkrywca Dinozaurów"     │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │  🎉 LEVEL UP!              │  │
│  │  Poziom 5 → 6              │  │
│  └────────────────────────────┘  │
│                                  │
│  [ KONTYNUUJ ]                   │
│                                  │
└──────────────────────────────────┘

Komponenty

Wspólne (wszystkie typy)

KomponentOpis
TaskAppBarApp bar z nazwą typu, przyciskiem back i close
TaskProgressBarPasek postępu (np. pytanie 4/10)
XpPreviewBadge "+50 XP" widoczny podczas zadania
CompletionOverlayPełnoekranowy overlay z wynikami po ukończeniu
ConfettiAnimationAnimacja confetti (particle system)
XpCounterAnimowany licznik XP (count up)
BadgeEarnedCardKarta zdobytej odznaki
LevelUpCardKarta awansu na wyższy poziom
CloseConfirmDialog"Czy na pewno chcesz wyjść? Postęp zostanie zapisany."

Quiz

KomponentOpis
QuestionCardTreść pytania (tekst + opcjonalny obrazek)
AnswerOptionOpcja odpowiedzi (radio — single choice, checkbox — multi choice)
AnswerFeedbackFeedback: poprawna (zielona), błędna (czerwona) + wyjaśnienie
CheckButtonPrzycisk "SPRAWDŹ" (aktywny po wybraniu odpowiedzi)
NextButtonPrzycisk "NASTĘPNE" (po sprawdzeniu)

Video

KomponentOpis
VideoPlayerPlayer z kontrolkami (play/pause, seek, fullscreen)
VideoProgressBarPasek postępu video
ComprehensionQuizQuiz wyświetlany po obejrzeniu (reuse QuestionCard + AnswerOption)

Podcast

KomponentOpis
AudioPlayerPlayer: play/pause, prev/next 15s, seek bar
SpeedSelectorWybór prędkości: 1x, 1.5x, 2x
CoverArtOkładka podcastu
TranscriptViewPrzewijalny transkrypt z timestampami (auto-scroll do aktualnego)

Kreatywne

KomponentOpis
CreativePromptTreść polecenia
InputMethodPickerWybór: zdjęcie, rysunek, tekst
CameraCaptureEkran aparatu (camera plugin)
DrawingCanvasProsty canvas do rysowania (CustomPainter)
TextInputPole tekstowe (multiline)
SubmitButtonPrzycisk "WYŚLIJ PRACĘ"

Mini-gra

KomponentOpis
GameContainerKontener gry (WebView lub Flutter canvas / Flame)
GameHUDCzas, wynik, życia (overlay nad grą)
GameOverScreenEkran końca gry z wynikiem

Logika

Przepływ ogólny

  1. Wejście na ekran → GET /app/tasks/:id (pobranie danych)
  2. POST /app/tasks/:id/start (oznaczenie rozpoczęcia, timestamp)
  3. Wykonanie zadania (quiz, video, itp.)
  4. POST /app/tasks/:id/complete (wysyłka wyników) lub POST /app/tasks/:id/submit-creative
  5. Animacja ukończenia (confetti, XP, badge, level up)
  6. Przycisk "KONTYNUUJ" → powrót do lokacji (context.pop())

Quiz — szczegóły

  • Single choice: radio buttons, 1 poprawna odpowiedź
  • Multi choice: checkboxy, 1+ poprawnych odpowiedzi
  • Po "SPRAWDŹ" → feedback (poprawna/błędna) + wyjaśnienie
  • Nawet przy błędnej odpowiedzi → przejście dalej (nauka, nie egzamin)
  • Wynik = poprawne / wszystkie (przesyłany w complete)

Video — szczegóły

  • Video musi być obejrzane w min. 90% żeby odblokować quiz
  • Quiz (comprehension) po obejrzeniu: 2-3 pytania
  • Jeśli brak quizu → video samo w sobie jest wystarczające

Zadanie kreatywne — szczegóły

  • Upload: zdjęcie (JPEG, max 5MB), rysunek (PNG z canvas), tekst
  • Wysyłka jako multipart/form-data na /app/tasks/:id/submit-creative
  • Brak automatycznej oceny — review przez rodzica/moderatora (async)
  • XP przyznawane za wysłanie (nie za ocenę)

Endpointy

MetodaEndpointOpis
GET/app/tasks/:idPełne dane zadania
POST/app/tasks/:id/startOznacz rozpoczęcie
POST/app/tasks/:id/completeUkończ zadanie (wynik)
POST/app/tasks/:id/submit-creativeWyślij pracę kreatywną

Task Detail Response (quiz):

json
{
  "data": {
    "id": "task-q1",
    "title": "Zwierzęta Polski",
    "type": "quiz",
    "xp_reward": 40,
    "thumbnail_url": "https://...",
    "questions": [
      {
        "id": "q1",
        "text": "Jak nazywa się najwyższa góra w Polsce?",
        "image_url": null,
        "type": "single_choice",
        "answers": [
          { "id": "a1", "text": "Rysy" },
          { "id": "a2", "text": "Giewont" },
          { "id": "a3", "text": "Śnieżka" },
          { "id": "a4", "text": "Kasprowy Wierch" }
        ],
        "correct_answer_ids": ["a1"],
        "explanation": "Rysy (2499 m) to najwyższy szczyt w polskich Tatrach."
      }
    ]
  }
}

Task Detail Response (video):

json
{
  "data": {
    "id": "task-v1",
    "title": "Dinozaury i ich świat",
    "type": "video",
    "xp_reward": 50,
    "video_url": "https://...",
    "duration_seconds": 480,
    "thumbnail_url": "https://...",
    "comprehension_questions": [
      {
        "id": "cq1",
        "text": "Kiedy wyginęły dinozaury?",
        "type": "single_choice",
        "answers": [
          { "id": "a1", "text": "65 mln lat temu" },
          { "id": "a2", "text": "100 mln lat temu" },
          { "id": "a3", "text": "10 mln lat temu" }
        ],
        "correct_answer_ids": ["a1"]
      }
    ]
  }
}

Complete Request:

json
{
  "score": 8,
  "max_score": 10,
  "answers": [
    { "question_id": "q1", "answer_ids": ["a1"] },
    { "question_id": "q2", "answer_ids": ["a3"] }
  ],
  "duration_seconds": 245
}

Complete Response:

json
{
  "data": {
    "xp_earned": 50,
    "total_xp": 1290,
    "level_before": 5,
    "level_after": 6,
    "level_up": true,
    "badges_earned": [
      {
        "id": "badge-dino",
        "name": "Odkrywca Dinozaurów",
        "icon_url": "https://...",
        "description": "Ukończ wszystkie zadania o dinozaurach"
      }
    ]
  }
}

Submit Creative Request (multipart):

POST /app/tasks/:id/submit-creative
Content-Type: multipart/form-data

file: (binary — image/jpeg, image/png)
description: "Moje wymarzone zwierzę to smok..."
input_type: "photo" | "drawing" | "text"

Stany Ekranu

StanWidok
ŁadowanieSkeleton z shimmer
W trakcieLayout odpowiedni dla typu zadania
ZakończoneCompletionOverlay z wynikami
BłądErrorView z przyciskiem retry
WychodzenieCloseConfirmDialog (jeśli zadanie w trakcie)

Uwagi Techniczne

  • Video player: video_player + chewie (kontrolki)
  • Audio player: just_audio + custom UI
  • Rysunek: CustomPainter z GestureDetector (kolorowe pędzle, gumka, cofnij)
  • Mini-gry: flutter_inappwebview (WebView) lub Flame engine (natywne)
  • Upload plików: Dio multipart + progress indicator
  • Postęp quizu zapisywany lokalnie (na wypadek przerwania) — sync z serwerem przy complete
  • WillPopScope / PopScope → dialog potwierdzenia wyjścia

Lumos Islands v2 - Dokumentacja Projektowa