Update Saqel Platform: 2026-09-08 17:51:07

This commit is contained in:
Hamza-Ayed
2026-09-08 17:51:07 +03:00
parent 902cf00152
commit 75451ebc3f
12 changed files with 84 additions and 39 deletions
@@ -4,6 +4,7 @@ import '../utils/app_logger.dart';
/// Ultra-Resilient Storage Service for Teacher Studio
class StorageService {
static final Map<String, String> _volatileStore = <String, String>{};
final FlutterSecureStorage _secureStorage;
StorageService({FlutterSecureStorage? secureStorage})
@@ -21,6 +22,7 @@ class StorageService {
static const String _keyUser = 'saqel_teacher_user_data';
Future<void> _writeSafe(String key, String value) async {
_volatileStore[key] = value;
try {
await _secureStorage.write(key: key, value: value);
} on PlatformException catch (e) {
@@ -34,13 +36,15 @@ class StorageService {
if (val != null && val.isNotEmpty) return val;
} catch (_) {}
return null;
return _volatileStore[key];
}
Future<void> saveToken(String token) async => await _writeSafe(_keyToken, token);
Future<String?> getToken() async => await _readSafe(_keyToken);
Future<void> clearSession() async {
_volatileStore.remove(_keyToken);
_volatileStore.remove(_keyUser);
try {
await _secureStorage.delete(key: _keyToken);
await _secureStorage.delete(key: _keyUser);
@@ -184,20 +184,20 @@ class TeacherProfileModel {
grades = [profile['grades_taught'].toString()];
}
if (grades.isEmpty) {
grades = ['الصف العاشر الأساسي', 'الأول ثانوي العلمي'];
grades = [];
}
return TeacherProfileModel(
id: user['id'] is int ? user['id'] : 1,
uuid: user['uuid']?.toString() ?? '',
name: user['full_name']?.toString() ?? 'الأستاذ المعتمد',
specialization: profile['specialization']?.toString() ?? 'الفيزياء',
schoolName: profile['school_name']?.toString() ?? 'مدرسة الملك عبد الله الثاني للتميز',
name: user['full_name']?.toString() ?? 'حساب معلم غير مكتمل',
specialization: profile['specialization']?.toString() ?? 'بانتظار استكمال التخصص',
schoolName: profile['school_name']?.toString() ?? '',
gradesTaught: grades,
bio: profile['bio']?.toString() ?? 'معلم معتمد في منصة صَقِل',
rating: 4.9,
studentsCount: 42,
lessonsCount: 28,
bio: profile['bio']?.toString() ?? '',
rating: 0,
studentsCount: 0,
lessonsCount: 0,
);
}
@@ -56,7 +56,7 @@ class TeacherRepository {
'phone_number': phoneNumber,
'role': 'teacher',
}),
).timeout(const Duration(seconds: 6));
).timeout(const Duration(seconds: 30));
return json.decode(response.body);
} catch (e) {
@@ -78,7 +78,7 @@ class TeacherRepository {
if (fullName != null) 'full_name': fullName,
'device_fingerprint': 'saqel_teacher_flutter',
}),
).timeout(const Duration(seconds: 6));
).timeout(const Duration(seconds: 30));
final decoded = json.decode(response.body);
if (decoded['status'] == 'success' && decoded['data']?['token'] != null) {
@@ -86,14 +86,14 @@ class TeacherAuthCubit extends Cubit<TeacherAuthState> {
try {
final res = await repository.verifyOtp(phoneNumber, otp, fullName: fullName);
if (res['status'] == 'success') {
if (specialization != null || schoolName != null || gradesTaught != null) {
if ((fullName ?? '').trim().isNotEmpty && (specialization ?? '').trim().isNotEmpty && (schoolName ?? '').trim().isNotEmpty && (gradesTaught?.isNotEmpty ?? false)) {
try {
await repository.setupProfile(
fullName: fullName ?? 'المعلم المعتمد',
specialization: specialization ?? 'الفيزياء والعلوم التطبيقية',
schoolName: schoolName ?? 'مدرسة الملك عبد الله الثاني للتميز',
gradesTaught: gradesTaught ?? ['الصف العاشر الأساسي'],
bio: 'معلم معتمد في منصة صقل للتعليم التفاعلي',
fullName: fullName!.trim(),
specialization: specialization!.trim(),
schoolName: schoolName!.trim(),
gradesTaught: gradesTaught!,
bio: '',
);
} catch (_) {}
}
@@ -24,12 +24,12 @@ class TeacherAuthScreen extends StatefulWidget {
}
class _TeacherAuthScreenState extends State<TeacherAuthScreen> {
final TextEditingController _phoneController = TextEditingController(text: '0798583052');
final TextEditingController _phoneController = TextEditingController();
final TextEditingController _otpController = TextEditingController();
final TextEditingController _fullNameController = TextEditingController(text: 'المهندس حمزة الغويريين');
final TextEditingController _schoolController = TextEditingController(text: 'مدرسة الملك عبد الله الثاني للتميز');
final TextEditingController _fullNameController = TextEditingController();
final TextEditingController _schoolController = TextEditingController();
String _selectedSubject = 'الفيزياء والعلوم التطبيقية';
String? _selectedSubject;
final List<String> _availableSubjects = [
'الفيزياء والعلوم التطبيقية',
'الرياضيات العلمي',
@@ -39,10 +39,7 @@ class _TeacherAuthScreenState extends State<TeacherAuthScreen> {
'اللغة العربية ومشترك التوجيهي',
];
final Set<String> _selectedGrades = {
'الصف العاشر الأساسي',
'الأول ثانوي العلمي',
};
final Set<String> _selectedGrades = {};
final List<String> _allGrades = [
'الصف التاسع الأساسي',
@@ -79,6 +76,10 @@ class _TeacherAuthScreenState extends State<TeacherAuthScreen> {
SaqelToast.showError(context, 'يرجى إدخال رمز التحقق المكون من 6 أرقام');
return;
}
if (_fullNameController.text.trim().isEmpty || _selectedSubject == null || _schoolController.text.trim().isEmpty || _selectedGrades.isEmpty) {
SaqelToast.showError(context, 'أكمل الاسم والمادة والمدرسة وصفًا واحدًا على الأقل قبل التحقق');
return;
}
context.read<TeacherAuthCubit>().verifyOtp(
phone,
otp,
@@ -211,13 +211,13 @@ class _TeacherMainShellState extends State<TeacherMainShell> {
builder: (context, authState) {
TeacherProfileModel profile = widget.initialProfile ??
const TeacherProfileModel(
id: 1,
uuid: 'tch-01',
name: 'المهندس حمزة الغويريين',
specialization: 'الفيزياء والعلوم التطبيقية',
schoolName: 'مدرسة الملك عبد الله الثاني للتميز',
gradesTaught: ['الصف العاشر الأساسي', 'الأول ثانوي العلمي'],
bio: 'معلم معتمد في منصة صَقِل',
id: 0,
uuid: '',
name: 'حساب معلم غير مكتمل',
specialization: 'بانتظار استكمال الملف',
schoolName: '',
gradesTaught: [],
bio: '',
);
if (authState is TeacherAuthenticated) {
+6
View File
@@ -1,6 +1,8 @@
PODS:
- device_info_plus (0.0.1):
- FlutterMacOS
- file_picker (0.0.1):
- FlutterMacOS
- flutter_secure_storage_macos (6.1.3):
- FlutterMacOS
- FlutterMacOS (1.0.0)
@@ -10,6 +12,7 @@ PODS:
DEPENDENCIES:
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
@@ -17,6 +20,8 @@ DEPENDENCIES:
EXTERNAL SOURCES:
device_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
file_picker:
:path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos
flutter_secure_storage_macos:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos
FlutterMacOS:
@@ -26,6 +31,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
device_info_plus: a56e6e74dbbd2bb92f2da12c64ddd4f67a749041
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb