Refactor: refactored code to remove print statements, updated widget constructors, and fixe minor issus in various screens and providers
This commit is contained in:
parent
e6a56686ed
commit
28e8383662
|
|
@ -8,8 +8,8 @@ class DioClient {
|
||||||
|
|
||||||
DioClient() {
|
DioClient() {
|
||||||
_dio.options.baseUrl = baseUrl;
|
_dio.options.baseUrl = baseUrl;
|
||||||
_dio.options.connectTimeout = const Duration(seconds: 5);
|
_dio.options.connectTimeout = const Duration(seconds: 10);
|
||||||
_dio.options.receiveTimeout = const Duration(seconds: 10);
|
_dio.options.receiveTimeout = const Duration(seconds: 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Response> refreshAccessToken(String refreshToken) async {
|
Future<Response> refreshAccessToken(String refreshToken) async {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:english_learning/core/services/dio_client.dart';
|
import 'package:english_learning/core/services/dio_client.dart';
|
||||||
import 'package:english_learning/features/home/models/completed_topics_model.dart';
|
import 'package:english_learning/features/home/models/completed_topics_model.dart';
|
||||||
|
|
||||||
|
|
@ -8,38 +7,28 @@ class CompletedTopicsRepository {
|
||||||
CompletedTopicsRepository(this._dioClient);
|
CompletedTopicsRepository(this._dioClient);
|
||||||
|
|
||||||
Future<List<CompletedTopic>> getCompletedTopics(String token) async {
|
Future<List<CompletedTopic>> getCompletedTopics(String token) async {
|
||||||
try {
|
final response = await _dioClient.getCompletedTopics(token);
|
||||||
final response = await _dioClient.getCompletedTopics(token);
|
|
||||||
|
|
||||||
// Tambahkan pengecekan status code dan payload
|
// Tambahkan pengecekan status code dan payload
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
// Cek apakah payload null atau bukan list
|
// Cek apakah payload null atau bukan list
|
||||||
if (response.data['payload'] == null) {
|
if (response.data['payload'] == null) {
|
||||||
return []; // Kembalikan list kosong jika payload null
|
return []; // Kembalikan list kosong jika payload null
|
||||||
}
|
|
||||||
|
|
||||||
// Pastikan payload adalah list
|
|
||||||
final dynamic payloadData = response.data['payload'];
|
|
||||||
|
|
||||||
if (payloadData is List) {
|
|
||||||
return payloadData
|
|
||||||
.map((data) => CompletedTopic.fromJson(data))
|
|
||||||
.toList();
|
|
||||||
} else {
|
|
||||||
return []; // Kembalikan list kosong jika payload bukan list
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Tangani status code selain 200
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
} on DioException catch (e) {
|
|
||||||
// Log error jika perlu
|
// Pastikan payload adalah list
|
||||||
print('Network error: ${e.message}');
|
final dynamic payloadData = response.data['payload'];
|
||||||
return []; // Kembalikan list kosong untuk error jaringan
|
|
||||||
} catch (e) {
|
if (payloadData is List) {
|
||||||
// Log error tidak terduga
|
return payloadData
|
||||||
print('Unexpected error: $e');
|
.map((data) => CompletedTopic.fromJson(data))
|
||||||
return []; // Kembalikan list kosong untuk error lainnya
|
.toList();
|
||||||
|
} else {
|
||||||
|
return []; // Kembalikan list kosong jika payload bukan list
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Tangani status code selain 200
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ class LevelRepository {
|
||||||
throw Exception('Failed to load levels: ${response.statusCode}');
|
throw Exception('Failed to load levels: ${response.statusCode}');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error in LevelRepository: $e');
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ class SectionRepository {
|
||||||
throw Exception('Failed to load sections: ${response.statusCode}');
|
throw Exception('Failed to load sections: ${response.statusCode}');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error in SectionRepository: $e');
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ class TopicRepository {
|
||||||
throw Exception('Failed to load topics: ${response.statusCode}');
|
throw Exception('Failed to load topics: ${response.statusCode}');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error in TopicRepository: $e');
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ class UserRepository {
|
||||||
}
|
}
|
||||||
return await dioClient.updateUserProfile(id, formData, token);
|
return await dioClient.updateUserProfile(id, formData, token);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Update Profile error: $e');
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +66,6 @@ class UserRepository {
|
||||||
};
|
};
|
||||||
return await dioClient.updatePassword(id, data, token);
|
return await dioClient.updatePassword(id, data, token);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Update Password error: $e');
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,11 @@ class ConfirmPasswordFieldWidget extends StatefulWidget {
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ConfirmPasswordFieldWidgetState createState() =>
|
ConfirmPasswordFieldWidgetState createState() =>
|
||||||
_ConfirmPasswordFieldWidgetState();
|
ConfirmPasswordFieldWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ConfirmPasswordFieldWidgetState
|
class ConfirmPasswordFieldWidgetState
|
||||||
extends State<ConfirmPasswordFieldWidget> {
|
extends State<ConfirmPasswordFieldWidget> {
|
||||||
late FocusNode _focusNode;
|
late FocusNode _focusNode;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,10 @@ class EmailFieldWidget extends StatefulWidget {
|
||||||
{super.key, required this.labelText, required this.hintText});
|
{super.key, required this.labelText, required this.hintText});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_EmailFieldWidgetState createState() => _EmailFieldWidgetState();
|
EmailFieldWidgetState createState() => EmailFieldWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _EmailFieldWidgetState extends State<EmailFieldWidget> {
|
class EmailFieldWidgetState extends State<EmailFieldWidget> {
|
||||||
late FocusNode _focusNode;
|
late FocusNode _focusNode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ class FullNameFieldWidget extends StatefulWidget {
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_FullNameFieldWidgetState createState() => _FullNameFieldWidgetState();
|
FullNameFieldWidgetState createState() => FullNameFieldWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FullNameFieldWidgetState extends State<FullNameFieldWidget> {
|
class FullNameFieldWidgetState extends State<FullNameFieldWidget> {
|
||||||
late FocusNode _focusNode;
|
late FocusNode _focusNode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ class NISNFieldWidget extends StatefulWidget {
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_NISNFieldWidgetState createState() => _NISNFieldWidgetState();
|
NISNFieldWidgetState createState() => NISNFieldWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _NISNFieldWidgetState extends State<NISNFieldWidget> {
|
class NISNFieldWidgetState extends State<NISNFieldWidget> {
|
||||||
late FocusNode _focusNode;
|
late FocusNode _focusNode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,10 @@ class PasswordFieldWidget extends StatefulWidget {
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_PasswordFieldWidgetState createState() => _PasswordFieldWidgetState();
|
PasswordFieldWidgetState createState() => PasswordFieldWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PasswordFieldWidgetState extends State<PasswordFieldWidget> {
|
class PasswordFieldWidgetState extends State<PasswordFieldWidget> {
|
||||||
late FocusNode _focusNode;
|
late FocusNode _focusNode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -29,18 +29,14 @@ class UserProvider with ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadLoginStatus() async {
|
Future<void> _loadLoginStatus() async {
|
||||||
try {
|
_jwtToken = await _userRepository.getToken();
|
||||||
_jwtToken = await _userRepository.getToken();
|
if (_jwtToken != null) {
|
||||||
if (_jwtToken != null) {
|
if (JwtDecoder.isExpired(_jwtToken!)) {
|
||||||
if (JwtDecoder.isExpired(_jwtToken!)) {
|
await logout();
|
||||||
await logout();
|
} else {
|
||||||
} else {
|
_isLoggedIn = true;
|
||||||
_isLoggedIn = true;
|
await _loadUserData();
|
||||||
await _loadUserData();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
print('Error loading login status: $e');
|
|
||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
@ -53,18 +49,14 @@ class UserProvider with ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refreshUserData() async {
|
Future<void> refreshUserData() async {
|
||||||
try {
|
if (_jwtToken != null) {
|
||||||
if (_jwtToken != null) {
|
final response = await _userRepository.getMe(_jwtToken!);
|
||||||
final response = await _userRepository.getMe(_jwtToken!);
|
if (response.statusCode == 200) {
|
||||||
if (response.statusCode == 200) {
|
_userData = response.data['payload'];
|
||||||
_userData = response.data['payload'];
|
// Save all user data securely
|
||||||
// Save all user data securely
|
await _userRepository.saveUserData(_userData!);
|
||||||
await _userRepository.saveUserData(_userData!);
|
notifyListeners();
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
print('Error refreshing user data: $e');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,13 +88,11 @@ class UserProvider with ChangeNotifier {
|
||||||
await refreshUserData();
|
await refreshUserData();
|
||||||
return true;
|
return true;
|
||||||
} else if (response.statusCode == 403) {
|
} else if (response.statusCode == 403) {
|
||||||
print('User is not validated: ${response.data['message']}');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Login error: $e');
|
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
@ -130,7 +120,6 @@ class UserProvider with ChangeNotifier {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Registration error: $e');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +140,6 @@ class UserProvider with ChangeNotifier {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Logout error: $e');
|
|
||||||
_isLoggedIn = false;
|
_isLoggedIn = false;
|
||||||
_jwtToken = null;
|
_jwtToken = null;
|
||||||
_userData = null;
|
_userData = null;
|
||||||
|
|
@ -168,15 +156,12 @@ class UserProvider with ChangeNotifier {
|
||||||
final response = await _userRepository.forgotPassword(email);
|
final response = await _userRepository.forgotPassword(email);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
print("Password reset email sent successfully!");
|
|
||||||
return true;
|
return true;
|
||||||
} else if (response.statusCode == 404) {
|
} else if (response.statusCode == 404) {
|
||||||
print("Email is not registered!");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Forgot Password error: $e');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -205,7 +190,6 @@ class UserProvider with ChangeNotifier {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error refreshing token: $e');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +209,6 @@ class UserProvider with ChangeNotifier {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error in getValidToken: $e');
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -251,7 +234,6 @@ class UserProvider with ChangeNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error updating user profile: $e');
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -273,13 +255,11 @@ class UserProvider with ChangeNotifier {
|
||||||
token,
|
token,
|
||||||
);
|
);
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
print("Password updated successfully!");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error updating password: $e');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -290,13 +270,11 @@ class UserProvider with ChangeNotifier {
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
final response = await _userRepository.reportIssue(report, token);
|
final response = await _userRepository.reportIssue(report, token);
|
||||||
if (response.statusCode == 201) {
|
if (response.statusCode == 201) {
|
||||||
print("Issue reported successfully!");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error reporting issue: $e');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class _ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => SigninScreen(),
|
builder: (context) => const SigninScreen(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -145,7 +145,7 @@ class _ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => SigninScreen()),
|
builder: (context) => const SigninScreen()),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,9 @@ class _SigninScreenState extends State<SigninScreen> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final mediaQuery = MediaQuery.of(context);
|
||||||
|
final screenHeight = mediaQuery.size.height;
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => FocusScope.of(context).unfocus(),
|
onTap: () => FocusScope.of(context).unfocus(),
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
|
|
@ -133,7 +136,7 @@ class _SigninScreenState extends State<SigninScreen> {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 24),
|
SizedBox(height: screenHeight * 0.02),
|
||||||
Hero(
|
Hero(
|
||||||
tag: 'welcome_text',
|
tag: 'welcome_text',
|
||||||
child: Material(
|
child: Material(
|
||||||
|
|
@ -155,6 +158,7 @@ class _SigninScreenState extends State<SigninScreen> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 26),
|
const SizedBox(height: 26),
|
||||||
|
// SizedBox(height: screenHeight * 0.05),
|
||||||
Center(
|
Center(
|
||||||
child: Hero(
|
child: Hero(
|
||||||
tag: 'login_illustration',
|
tag: 'login_illustration',
|
||||||
|
|
@ -165,6 +169,7 @@ class _SigninScreenState extends State<SigninScreen> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
|
// SizedBox(height: screenHeight * 0.05),
|
||||||
CustomFieldWidget(
|
CustomFieldWidget(
|
||||||
fieldName: 'login',
|
fieldName: 'login',
|
||||||
controller: _loginController,
|
controller: _loginController,
|
||||||
|
|
@ -314,7 +319,7 @@ class _SigninScreenState extends State<SigninScreen> {
|
||||||
PageRouteBuilder(
|
PageRouteBuilder(
|
||||||
pageBuilder: (context, animation,
|
pageBuilder: (context, animation,
|
||||||
secondaryAnimation) =>
|
secondaryAnimation) =>
|
||||||
SignupScreen(),
|
const SignupScreen(),
|
||||||
transitionsBuilder: (context, animation,
|
transitionsBuilder: (context, animation,
|
||||||
secondaryAnimation, child) {
|
secondaryAnimation, child) {
|
||||||
return FadeTransition(
|
return FadeTransition(
|
||||||
|
|
@ -341,7 +346,7 @@ class _SigninScreenState extends State<SigninScreen> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
SizedBox(height: screenHeight * 0.02),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ class LoginPasswordField extends StatefulWidget {
|
||||||
const LoginPasswordField({super.key});
|
const LoginPasswordField({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_LoginPasswordFieldState createState() => _LoginPasswordFieldState();
|
LoginPasswordFieldState createState() => LoginPasswordFieldState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LoginPasswordFieldState extends State<LoginPasswordField> {
|
class LoginPasswordFieldState extends State<LoginPasswordField> {
|
||||||
late FocusNode _focusNode;
|
late FocusNode _focusNode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class SignupScreen extends StatefulWidget {
|
class SignupScreen extends StatefulWidget {
|
||||||
SignupScreen({super.key});
|
const SignupScreen({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SignupScreen> createState() => _SignupScreenState();
|
State<SignupScreen> createState() => _SignupScreenState();
|
||||||
|
|
@ -88,7 +88,7 @@ class _SignupScreenState extends State<SignupScreen> {
|
||||||
// Navigate to login screen
|
// Navigate to login screen
|
||||||
Navigator.of(dialogContext).pushAndRemoveUntil(
|
Navigator.of(dialogContext).pushAndRemoveUntil(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => SigninScreen(),
|
builder: (context) => const SigninScreen(),
|
||||||
),
|
),
|
||||||
(Route<dynamic> route) => false,
|
(Route<dynamic> route) => false,
|
||||||
);
|
);
|
||||||
|
|
@ -288,7 +288,7 @@ class _SignupScreenState extends State<SignupScreen> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 16),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -303,7 +303,7 @@ class _SignupScreenState extends State<SignupScreen> {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => SigninScreen()),
|
builder: (context) => const SigninScreen()),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class _HistoryScreenState extends State<HistoryScreen> {
|
||||||
try {
|
try {
|
||||||
await historyProvider.fetchLearningHistory(userProvider.jwtToken!);
|
await historyProvider.fetchLearningHistory(userProvider.jwtToken!);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error initializing history: $e');
|
rethrow;
|
||||||
} finally {
|
} finally {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isInitialLoading = false;
|
_isInitialLoading = false;
|
||||||
|
|
@ -109,7 +109,6 @@ class _HistoryScreenState extends State<HistoryScreen> {
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 16.0,
|
horizontal: 16.0,
|
||||||
vertical: 30.0,
|
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ class NoProgressCard extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
decoration: BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: AppColors.whiteColor,
|
color: AppColors.whiteColor,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,6 @@ class ExerciseProvider extends ChangeNotifier {
|
||||||
|
|
||||||
void _selectRightOption(int exerciseIndex, String option) {
|
void _selectRightOption(int exerciseIndex, String option) {
|
||||||
if (_activeLeftOption == null) {
|
if (_activeLeftOption == null) {
|
||||||
print("Please select a left option first.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,30 +249,23 @@ class ExerciseProvider extends ChangeNotifier {
|
||||||
void goToExercise(int index) {
|
void goToExercise(int index) {
|
||||||
if (index >= 0 && index < _exercises.length) {
|
if (index >= 0 && index < _exercises.length) {
|
||||||
_currentExerciseIndex = index;
|
_currentExerciseIndex = index;
|
||||||
print('Going to exercise: $_currentExerciseIndex'); // Debug print
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nextQuestion() {
|
void nextQuestion() {
|
||||||
print('Current index before next: $_currentExerciseIndex'); // Debug print
|
|
||||||
if (_currentExerciseIndex <
|
if (_currentExerciseIndex <
|
||||||
(_exercises.isNotEmpty
|
(_exercises.isNotEmpty
|
||||||
? _exercises.length - 1
|
? _exercises.length - 1
|
||||||
: _reviewExercises.length - 1)) {
|
: _reviewExercises.length - 1)) {
|
||||||
_currentExerciseIndex++;
|
_currentExerciseIndex++;
|
||||||
print('Moving to next question: $_currentExerciseIndex'); // Debug print
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void previousQuestion() {
|
void previousQuestion() {
|
||||||
print(
|
|
||||||
'Current index before previous: $_currentExerciseIndex'); // Debug print
|
|
||||||
if (_currentExerciseIndex > 0) {
|
if (_currentExerciseIndex > 0) {
|
||||||
_currentExerciseIndex--;
|
_currentExerciseIndex--;
|
||||||
print(
|
|
||||||
'Moving to previous question: $_currentExerciseIndex'); // Debug print
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -334,7 +326,7 @@ class ExerciseProvider extends ChangeNotifier {
|
||||||
_answers = List.generate(_exercises.length, (index) => '');
|
_answers = List.generate(_exercises.length, (index) => '');
|
||||||
initializeAnswers();
|
initializeAnswers();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error fetching exercises: $e');
|
rethrow;
|
||||||
} finally {
|
} finally {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
@ -383,7 +375,6 @@ class ExerciseProvider extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error fetching review exercises: $e');
|
|
||||||
rethrow;
|
rethrow;
|
||||||
} finally {
|
} finally {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
|
|
@ -480,12 +471,9 @@ class ExerciseProvider extends ChangeNotifier {
|
||||||
'No answers to submit. Please answer at least one question.');
|
'No answers to submit. Please answer at least one question.');
|
||||||
}
|
}
|
||||||
|
|
||||||
print('Submitting answers to repository');
|
|
||||||
final result = await _repository.submitAnswersAndGetScore(
|
final result = await _repository.submitAnswersAndGetScore(
|
||||||
answersToSubmit, _studentLearningId!, token);
|
answersToSubmit, _studentLearningId!, token);
|
||||||
|
|
||||||
print('Repository response: $result');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'CURRENT_LEVEL_NAME': result['CURRENT_LEVEL_NAME'],
|
'CURRENT_LEVEL_NAME': result['CURRENT_LEVEL_NAME'],
|
||||||
'NEXT_LEARNING_NAME': result['NEXT_LEARNING_NAME'],
|
'NEXT_LEARNING_NAME': result['NEXT_LEARNING_NAME'],
|
||||||
|
|
@ -493,7 +481,6 @@ class ExerciseProvider extends ChangeNotifier {
|
||||||
'IS_PASS': result['IS_PASS'],
|
'IS_PASS': result['IS_PASS'],
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error in submitAnswersAndGetScore: $e');
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -507,13 +494,10 @@ class ExerciseProvider extends ChangeNotifier {
|
||||||
if (_studentLearningId == null) {
|
if (_studentLearningId == null) {
|
||||||
throw Exception('Student Learning ID is not set');
|
throw Exception('Student Learning ID is not set');
|
||||||
}
|
}
|
||||||
print('Submitting feedback for stdLearningId: $_studentLearningId');
|
|
||||||
final result = await _repository.submitFeedback(
|
final result = await _repository.submitFeedback(
|
||||||
_studentLearningId!, feedback, token);
|
_studentLearningId!, feedback, token);
|
||||||
print('Feedback submitted successfully');
|
|
||||||
return result;
|
return result;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error submitting feedback: $e');
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ class ExerciseNavigator extends StatelessWidget {
|
||||||
Future<void> submitAnswers() async {
|
Future<void> submitAnswers() async {
|
||||||
try {
|
try {
|
||||||
final result = await exerciseProvider.submitAnswersAndGetScore();
|
final result = await exerciseProvider.submitAnswersAndGetScore();
|
||||||
print('Submit result: $result');
|
|
||||||
|
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
Navigator.of(context).pushReplacement(
|
Navigator.of(context).pushReplacement(
|
||||||
|
|
@ -55,7 +54,6 @@ class ExerciseNavigator extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error submitting answers: $e');
|
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
CustomSnackBar.show(
|
CustomSnackBar.show(
|
||||||
context,
|
context,
|
||||||
|
|
|
||||||
|
|
@ -363,7 +363,7 @@ class _MatchingPairsQuestionState extends State<MatchingPairsQuestion> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,10 +80,7 @@ class _FeedbackScreenState extends State<FeedbackScreen> {
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final exerciseProvider =
|
Provider.of<ExerciseProvider>(context, listen: false);
|
||||||
Provider.of<ExerciseProvider>(context, listen: false);
|
|
||||||
final result =
|
|
||||||
await exerciseProvider.submitFeedback(_controller.text.trim());
|
|
||||||
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
||||||
|
|
@ -91,27 +88,19 @@ class _FeedbackScreenState extends State<FeedbackScreen> {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result != null) {
|
await showDialog(
|
||||||
await showDialog(
|
context: context,
|
||||||
context: context,
|
barrierDismissible: false,
|
||||||
barrierDismissible: false,
|
builder: (BuildContext dialogContext) => PopScope(
|
||||||
builder: (BuildContext dialogContext) => PopScope(
|
canPop: false,
|
||||||
canPop: false,
|
child: FeedbackDialog(
|
||||||
child: FeedbackDialog(
|
onSubmit: () {
|
||||||
onSubmit: () {
|
Navigator.pop(dialogContext);
|
||||||
Navigator.pop(dialogContext);
|
_navigateToLevelList();
|
||||||
_navigateToLevelList();
|
},
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
} else {
|
);
|
||||||
CustomSnackBar.show(
|
|
||||||
context,
|
|
||||||
message: 'Failed to submit feedback. Please try again.',
|
|
||||||
isError: true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,6 @@ class VideoPlayerWidgetState extends State<VideoPlayerWidget> {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error extracting YouTube ID: $e');
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:english_learning/core/services/constants.dart';
|
import 'package:english_learning/core/services/constants.dart';
|
||||||
|
import 'package:english_learning/core/widgets/custom_snackbar.dart';
|
||||||
import 'package:english_learning/core/widgets/loading/shimmer_loading_widget.dart';
|
import 'package:english_learning/core/widgets/loading/shimmer_loading_widget.dart';
|
||||||
import 'package:english_learning/features/auth/provider/user_provider.dart';
|
import 'package:english_learning/features/auth/provider/user_provider.dart';
|
||||||
import 'package:english_learning/features/learning/modules/level/screens/level_list_screen.dart';
|
import 'package:english_learning/features/learning/modules/level/screens/level_list_screen.dart';
|
||||||
|
|
@ -46,12 +47,15 @@ class _TopicsListScreenState extends State<TopicsListScreen> {
|
||||||
try {
|
try {
|
||||||
await Provider.of<TopicProvider>(context, listen: false)
|
await Provider.of<TopicProvider>(context, listen: false)
|
||||||
.fetchTopics(widget.sectionId, token);
|
.fetchTopics(widget.sectionId, token);
|
||||||
print('Topics fetched successfully');
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error fetching topics: $e');
|
rethrow;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print('No valid token found. User might need to log in.');
|
CustomSnackBar.show(
|
||||||
|
context,
|
||||||
|
message: 'No valid token found. User might need to log in.',
|
||||||
|
isError: true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import 'package:flutter/foundation.dart';
|
||||||
class SectionProvider extends ChangeNotifier {
|
class SectionProvider extends ChangeNotifier {
|
||||||
final SectionRepository _repository = SectionRepository();
|
final SectionRepository _repository = SectionRepository();
|
||||||
List<Section> _sections = [];
|
List<Section> _sections = [];
|
||||||
bool _isLoading = false;
|
final bool _isLoading = false;
|
||||||
dynamic _error;
|
dynamic _error;
|
||||||
|
|
||||||
List<Section> get sections => _sections;
|
List<Section> get sections => _sections;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class _LearningScreenState extends State<LearningScreen>
|
||||||
await sectionProvider.fetchSections(token);
|
await sectionProvider.fetchSections(token);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error initializing sections: $e');
|
rethrow;
|
||||||
} finally {
|
} finally {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isInitialLoading = false;
|
_isInitialLoading = false;
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ class _OnBoardingScreenState extends State<OnBoardingScreen> {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => SignupScreen()),
|
builder: (context) => const SignupScreen()),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,8 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
|
||||||
Navigator.pushAndRemoveUntil(
|
Navigator.pushAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => SigninScreen()),
|
builder: (context) =>
|
||||||
|
const SigninScreen()),
|
||||||
(route) => false,
|
(route) => false,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -23,14 +23,6 @@ class SettingsScreen extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SettingsScreenState extends State<SettingsScreen> {
|
class _SettingsScreenState extends State<SettingsScreen> {
|
||||||
// @override
|
|
||||||
// void initState() {
|
|
||||||
// super.initState();
|
|
||||||
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
// Provider.of<UserProvider>(context, listen: false).refreshUserData();
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
|
@ -186,7 +178,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||||
if (success) {
|
if (success) {
|
||||||
Navigator.of(context).pushAndRemoveUntil(
|
Navigator.of(context).pushAndRemoveUntil(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => SigninScreen()),
|
builder: (context) =>
|
||||||
|
const SigninScreen()),
|
||||||
(Route<dynamic> route) => false,
|
(Route<dynamic> route) => false,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user