Merge branch 'auto-refresh-levelList' into 'master'
refactor: auto refresh after submit feedback and app configuration See merge request profile-image/kedaireka/polinema-adapative-learning/mobile-adaptive-learning!4
This commit is contained in:
commit
a1c271408a
|
|
@ -3,7 +3,7 @@
|
|||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<application
|
||||
android:label="english_learning"
|
||||
android:label="SEALS"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 8.5 KiB |
|
|
@ -1 +1 @@
|
|||
const String baseUrl = 'https://c62a-139-255-101-170.ngrok-free.app/';
|
||||
const String baseUrl = 'https://7558-114-6-25-184.ngrok-free.app/';
|
||||
|
|
|
|||
|
|
@ -51,9 +51,6 @@ class HistoryScreen extends StatelessWidget {
|
|||
}
|
||||
|
||||
Widget _buildContent(BuildContext context, HistoryProvider historyProvider) {
|
||||
print("isLoading: ${historyProvider.isLoading}");
|
||||
print("error: ${historyProvider.error}");
|
||||
print("historyLength: ${historyProvider.learningHistory.length}");
|
||||
if (historyProvider.isLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,12 +12,16 @@ class ExerciseScreen extends StatefulWidget {
|
|||
final String? levelId;
|
||||
final String studentLearningId;
|
||||
final bool isReview;
|
||||
final String topicId; // Tambahkan ini
|
||||
final String topicTitle; // Tambahkan ini
|
||||
|
||||
const ExerciseScreen({
|
||||
super.key,
|
||||
required this.levelId,
|
||||
required this.studentLearningId,
|
||||
this.isReview = false,
|
||||
required this.topicId,
|
||||
required this.topicTitle,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -142,6 +146,8 @@ class _ExerciseScreenState extends State<ExerciseScreen> {
|
|||
ExerciseNavigator(
|
||||
onScrollToTop: _scrollToTop,
|
||||
isReview: widget.isReview,
|
||||
topicId: widget.topicId,
|
||||
topicTitle: widget.topicTitle,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -11,11 +11,15 @@ import 'package:provider/provider.dart';
|
|||
class ExerciseNavigator extends StatelessWidget {
|
||||
final VoidCallback? onScrollToTop;
|
||||
final bool isReview;
|
||||
final String topicId;
|
||||
final String topicTitle;
|
||||
|
||||
const ExerciseNavigator({
|
||||
super.key,
|
||||
required this.onScrollToTop,
|
||||
this.isReview = false,
|
||||
required this.topicId,
|
||||
required this.topicTitle,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -43,6 +47,8 @@ class ExerciseNavigator extends StatelessWidget {
|
|||
score: int.tryParse(result['SCORE'].toString()) ?? 0,
|
||||
isCompleted: result['IS_PASS'] == 1,
|
||||
stdLearningId: result['STUDENT_LEARNING_ID']?.toString(),
|
||||
topicId: topicId,
|
||||
topicTitle: topicTitle,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,15 +2,20 @@ import 'package:english_learning/core/widgets/global_button.dart';
|
|||
import 'package:english_learning/core/utils/styles/theme.dart';
|
||||
import 'package:english_learning/features/learning/modules/exercises/providers/exercise_provider.dart';
|
||||
import 'package:english_learning/features/learning/modules/feedback/widgets/feedback_dialog.dart';
|
||||
import 'package:english_learning/features/learning/modules/level/screens/level_list_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class FeedbackScreen extends StatefulWidget {
|
||||
final String stdLearningId;
|
||||
final String topicId;
|
||||
final String topicTitle;
|
||||
|
||||
const FeedbackScreen({
|
||||
super.key,
|
||||
required this.stdLearningId,
|
||||
required this.topicId,
|
||||
required this.topicTitle,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -75,7 +80,16 @@ class _FeedbackScreenState extends State<FeedbackScreen> {
|
|||
return FeedbackDialog(
|
||||
onSubmit: () {
|
||||
Navigator.of(dialogContext).pop(); // Close the dialog
|
||||
Navigator.of(context).pop(); // Return to the previous screen
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => LevelListScreen(
|
||||
topicId: widget.topicId,
|
||||
topicTitle: widget.topicTitle,
|
||||
),
|
||||
),
|
||||
(route) => false, // This removes all previous routes
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
|
|
@ -189,16 +203,15 @@ class _FeedbackScreenState extends State<FeedbackScreen> {
|
|||
backgroundColor: Colors.transparent,
|
||||
borderColor: AppColors.blueColor,
|
||||
onPressed: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => LevelListScreen(
|
||||
// topicId: widget.topicId!,
|
||||
// topicTitle: widget.topicTitle!,
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
Navigator.of(context).pop(true);
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => LevelListScreen(
|
||||
topicId: widget.topicId,
|
||||
topicTitle: widget.topicTitle,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
|
|
|
|||
|
|
@ -46,31 +46,6 @@ class LevelProvider with ChangeNotifier {
|
|||
orElse: () => throw Exception('Pretest not found'));
|
||||
}
|
||||
|
||||
// int getLevelScore(String levelId) {
|
||||
// final level = _levels.firstWhere((level) => level.idLevel == levelId,
|
||||
// orElse: () => const Level(
|
||||
// idLevel: '',
|
||||
// idTopic: '',
|
||||
// idSection: '',
|
||||
// nameSection: '',
|
||||
// nameTopic: '',
|
||||
// nameLevel: '',
|
||||
// content: '',
|
||||
// isPretest: 0,
|
||||
// timeLevel: '',
|
||||
// ));
|
||||
// return level.score ?? 0;
|
||||
// }
|
||||
|
||||
// bool isLevelAllowed(String levelName) {
|
||||
// return _unlockedLevels.contains(levelName);
|
||||
// }
|
||||
|
||||
// bool isLevelCompleted(String levelId) {
|
||||
// return _lastCompletedLevel != null &&
|
||||
// _lastCompletedLevel!['ID_LEVEL'] == levelId;
|
||||
// }
|
||||
|
||||
bool isPretestFinished(String levelId) {
|
||||
return _levels.any(
|
||||
(level) => level.idLevel == levelId && level.idStudentLearning != null);
|
||||
|
|
@ -98,38 +73,4 @@ class LevelProvider with ChangeNotifier {
|
|||
return _levels.any(
|
||||
(level) => level.idLevel == levelId && level.idStudentLearning != null);
|
||||
}
|
||||
|
||||
// bool isLevelAllowed(String levelId) {
|
||||
// if (_lastCompletedLevel == null) {
|
||||
// // Jika tidak ada level yang selesai, hanya pretest yang diizinkan
|
||||
// return levelId == _levels.first.idLevel;
|
||||
// }
|
||||
|
||||
// String lastCompletedLevelId = _lastCompletedLevel!['ID_LEVEL'];
|
||||
// int lastCompletedIndex =
|
||||
// _levels.indexWhere((level) => level.idLevel == lastCompletedLevelId);
|
||||
// int currentIndex = _levels.indexWhere((level) => level.idLevel == levelId);
|
||||
|
||||
// // Level diizinkan jika indeksnya kurang dari atau sama dengan indeks terakhir yang selesai + 1
|
||||
// return currentIndex <= lastCompletedIndex + 1;
|
||||
// }
|
||||
|
||||
// bool isLevelAllowed(int levelIndex) {
|
||||
// if (levelIndex == 0) return true; // Pretest is always allowed
|
||||
// if (_lastCompletedLevel == null)
|
||||
// return levelIndex ==
|
||||
// 1; // If no level completed, only first level is allowed
|
||||
// String lastCompletedLevelId = _lastCompletedLevel!['ID_LEVEL'];
|
||||
// int lastCompletedIndex =
|
||||
// _levels.indexWhere((level) => level.idLevel == lastCompletedLevelId);
|
||||
// return levelIndex <= lastCompletedIndex + 2;
|
||||
// }
|
||||
|
||||
// bool isLevelFinished(int levelIndex) {
|
||||
// return _levels[levelIndex].idStudentLearning != null;
|
||||
// }
|
||||
|
||||
// int getLevelScore(int levelIndex) {
|
||||
// return _levels[levelIndex].score ?? 0;
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,9 @@ class _LevelListScreenState extends State<LevelListScreen> {
|
|||
.where((level) => level.isPretest == 0)
|
||||
.toList();
|
||||
|
||||
return Padding(
|
||||
return RefreshIndicator(
|
||||
onRefresh: _fetchLevels,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
@ -116,6 +118,7 @@ class _LevelListScreenState extends State<LevelListScreen> {
|
|||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -141,6 +141,8 @@ class LevelCard extends StatelessWidget {
|
|||
MaterialPageRoute(
|
||||
builder: (context) => MaterialScreen(
|
||||
levelId: level.idLevel,
|
||||
topicId: level.idTopic,
|
||||
topicTitle: level.nameTopic,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ class PretestCard extends StatelessWidget {
|
|||
levelId: pretest.idLevel,
|
||||
isReview: true,
|
||||
studentLearningId: pretest.idStudentLearning,
|
||||
topicId: pretest.idTopic,
|
||||
topicTitle: pretest.nameTopic,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -48,6 +50,8 @@ class PretestCard extends StatelessWidget {
|
|||
builder: (context) => MaterialScreen(
|
||||
levelId: pretest.idLevel,
|
||||
isReview: false,
|
||||
topicId: pretest.idTopic,
|
||||
topicTitle: pretest.nameTopic,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -141,31 +145,6 @@ class PretestCard extends StatelessWidget {
|
|||
width: double.infinity,
|
||||
height: 36,
|
||||
color: isFinished ? Colors.green : AppColors.yellowButtonColor,
|
||||
// onPressed: () {
|
||||
// if (!isCompleted) {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => MaterialScreen(
|
||||
// levelId: pretest.idLevel,
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// // Jika isCompleted true, tidak melakukan apa-apa
|
||||
// },
|
||||
// onPressed: isAllowed
|
||||
// ? () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => MaterialScreen(
|
||||
// levelId: pretest.idLevel,
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// : () {},
|
||||
onPressed: navigateToMaterial,
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -16,12 +16,16 @@ class MaterialScreen extends StatefulWidget {
|
|||
final String levelId;
|
||||
final bool isReview;
|
||||
final String? studentLearningId;
|
||||
final String topicId;
|
||||
final String topicTitle;
|
||||
|
||||
const MaterialScreen({
|
||||
super.key,
|
||||
required this.levelId,
|
||||
this.isReview = false,
|
||||
this.studentLearningId,
|
||||
required this.topicId,
|
||||
required this.topicTitle,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -100,6 +104,8 @@ class _MaterialScreenState extends State<MaterialScreen>
|
|||
levelId: widget.levelId,
|
||||
studentLearningId: studentLearningId,
|
||||
isReview: widget.isReview,
|
||||
topicId: widget.topicId,
|
||||
topicTitle: widget.topicTitle,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ class ResultScreen extends StatelessWidget {
|
|||
final int score;
|
||||
final bool isCompleted;
|
||||
final String? stdLearningId;
|
||||
final String topicId;
|
||||
final String topicTitle;
|
||||
|
||||
const ResultScreen({
|
||||
super.key,
|
||||
|
|
@ -18,6 +20,8 @@ class ResultScreen extends StatelessWidget {
|
|||
required this.score,
|
||||
required this.isCompleted,
|
||||
this.stdLearningId,
|
||||
required this.topicId,
|
||||
required this.topicTitle,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -37,18 +41,24 @@ class ResultScreen extends StatelessWidget {
|
|||
currentLevel: currentLevel,
|
||||
score: score,
|
||||
stdLearningId: stdLearningId ?? '',
|
||||
topicId: topicId, // Tambahkan ini
|
||||
topicTitle: topicTitle, // Tambahkan ini
|
||||
)
|
||||
else if (nextLevel != currentLevel)
|
||||
JumpResultWidget(
|
||||
nextLevel: nextLevel,
|
||||
score: score,
|
||||
stdLearningId: stdLearningId ?? '',
|
||||
topicId: topicId, // Tambahkan ini
|
||||
topicTitle: topicTitle, // Tambahkan ini
|
||||
)
|
||||
else
|
||||
DownResultWidget(
|
||||
nextLevel: nextLevel,
|
||||
score: score,
|
||||
stdLearningId: stdLearningId ?? '',
|
||||
topicId: topicId, // Tambahkan ini
|
||||
topicTitle: topicTitle, // Tambahkan ini
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -8,12 +8,16 @@ class CompleteResultWidget extends StatelessWidget {
|
|||
final String? currentLevel;
|
||||
final int? score;
|
||||
final String stdLearningId;
|
||||
final String topicId;
|
||||
final String topicTitle;
|
||||
|
||||
const CompleteResultWidget({
|
||||
super.key,
|
||||
required this.currentLevel,
|
||||
required this.score,
|
||||
required this.stdLearningId,
|
||||
required this.topicId,
|
||||
required this.topicTitle,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -57,6 +61,8 @@ class CompleteResultWidget extends StatelessWidget {
|
|||
MaterialPageRoute(
|
||||
builder: (context) => FeedbackScreen(
|
||||
stdLearningId: stdLearningId,
|
||||
topicId: topicId, // Tambahkan ini
|
||||
topicTitle: topicTitle, // Tambahkan ini
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,12 +8,16 @@ class DownResultWidget extends StatelessWidget {
|
|||
final String? nextLevel;
|
||||
final int? score;
|
||||
final String stdLearningId;
|
||||
final String topicId;
|
||||
final String topicTitle;
|
||||
|
||||
const DownResultWidget({
|
||||
super.key,
|
||||
required this.nextLevel,
|
||||
required this.score,
|
||||
required this.stdLearningId,
|
||||
required this.topicId,
|
||||
required this.topicTitle,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -67,6 +71,8 @@ class DownResultWidget extends StatelessWidget {
|
|||
MaterialPageRoute(
|
||||
builder: (context) => FeedbackScreen(
|
||||
stdLearningId: stdLearningId,
|
||||
topicId: topicId, // Tambahkan ini
|
||||
topicTitle: topicTitle, // Tambahkan ini
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,12 +8,17 @@ class JumpResultWidget extends StatelessWidget {
|
|||
final String? nextLevel;
|
||||
final int? score;
|
||||
final String stdLearningId;
|
||||
final String topicId;
|
||||
final String topicTitle;
|
||||
|
||||
const JumpResultWidget(
|
||||
{super.key,
|
||||
const JumpResultWidget({
|
||||
super.key,
|
||||
required this.nextLevel,
|
||||
required this.score,
|
||||
required this.stdLearningId});
|
||||
required this.stdLearningId,
|
||||
required this.topicId,
|
||||
required this.topicTitle,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -66,6 +71,8 @@ class JumpResultWidget extends StatelessWidget {
|
|||
MaterialPageRoute(
|
||||
builder: (context) => FeedbackScreen(
|
||||
stdLearningId: stdLearningId,
|
||||
topicId: topicId, // Tambahkan ini
|
||||
topicTitle: topicTitle, // Tambahkan ini
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ class _TopicsListScreenState extends State<TopicsListScreen> {
|
|||
child: Consumer<TopicProvider>(
|
||||
builder: (context, topicProvider, _) {
|
||||
if (topicProvider.topics.isEmpty) {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (topicProvider.error != null) {
|
||||
return const Center(child: Text('No topics available'));
|
||||
} else {
|
||||
|
|
@ -150,7 +150,7 @@ class _TopicsListScreenState extends State<TopicsListScreen> {
|
|||
description: topic.description,
|
||||
isCompleted: topic.isCompleted,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => LevelListScreen(
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user