Update Saqel Platform: 2026-09-08 18:19:28
This commit is contained in:
@@ -7,6 +7,7 @@ import '../../data/repositories/teacher_repository.dart';
|
||||
abstract class TeacherAuthState {}
|
||||
|
||||
class TeacherAuthInitial extends TeacherAuthState {}
|
||||
|
||||
class TeacherAuthLoading extends TeacherAuthState {}
|
||||
|
||||
class TeacherAuthOtpSent extends TeacherAuthState {
|
||||
@@ -42,13 +43,16 @@ class TeacherAuthCubit extends Cubit<TeacherAuthState> {
|
||||
try {
|
||||
final token = await _storage.getToken();
|
||||
if (token == null || token.isEmpty) {
|
||||
AppLogger.log('No teacher token -> Unauthenticated', tag: 'TEACHER_AUTH');
|
||||
AppLogger.log('No teacher token -> Unauthenticated',
|
||||
tag: 'TEACHER_AUTH');
|
||||
emit(TeacherUnauthenticated());
|
||||
return;
|
||||
}
|
||||
|
||||
final profile = await repository.getProfileStatus();
|
||||
AppLogger.log('Teacher authenticated: ${profile.name} (${profile.specialization})', tag: 'TEACHER_AUTH');
|
||||
AppLogger.log(
|
||||
'Teacher authenticated: ${profile.name} (${profile.specialization})',
|
||||
tag: 'TEACHER_AUTH');
|
||||
emit(TeacherAuthenticated(profile: profile));
|
||||
} catch (e) {
|
||||
AppLogger.error('Session check failed', error: e, tag: 'TEACHER_AUTH');
|
||||
@@ -67,7 +71,8 @@ class TeacherAuthCubit extends Cubit<TeacherAuthState> {
|
||||
if (res['status'] == 'success') {
|
||||
emit(TeacherAuthOtpSent(phoneNumber: phoneNumber));
|
||||
} else {
|
||||
emit(TeacherAuthError(res['message']?.toString() ?? 'فشل إرسال رمز التحقق'));
|
||||
emit(TeacherAuthError(
|
||||
res['message']?.toString() ?? 'فشل إرسال رمز التحقق'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(TeacherAuthError(e.toString()));
|
||||
@@ -84,9 +89,13 @@ class TeacherAuthCubit extends Cubit<TeacherAuthState> {
|
||||
}) async {
|
||||
emit(TeacherAuthLoading());
|
||||
try {
|
||||
final res = await repository.verifyOtp(phoneNumber, otp, fullName: fullName);
|
||||
final res =
|
||||
await repository.verifyOtp(phoneNumber, otp, fullName: fullName);
|
||||
if (res['status'] == 'success') {
|
||||
if ((fullName ?? '').trim().isNotEmpty && (specialization ?? '').trim().isNotEmpty && (schoolName ?? '').trim().isNotEmpty && (gradesTaught?.isNotEmpty ?? false)) {
|
||||
if ((fullName ?? '').trim().isNotEmpty &&
|
||||
(specialization ?? '').trim().isNotEmpty &&
|
||||
(schoolName ?? '').trim().isNotEmpty &&
|
||||
(gradesTaught?.isNotEmpty ?? false)) {
|
||||
try {
|
||||
await repository.setupProfile(
|
||||
fullName: fullName!.trim(),
|
||||
@@ -100,7 +109,8 @@ class TeacherAuthCubit extends Cubit<TeacherAuthState> {
|
||||
final profile = await repository.getProfileStatus();
|
||||
emit(TeacherAuthenticated(profile: profile));
|
||||
} else {
|
||||
emit(TeacherAuthError(res['message']?.toString() ?? 'رمز التحقق غير صحيح'));
|
||||
emit(TeacherAuthError(
|
||||
res['message']?.toString() ?? 'رمز التحقق غير صحيح'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(TeacherAuthError(e.toString()));
|
||||
|
||||
@@ -63,7 +63,8 @@ class TeacherMonetizationState {
|
||||
bool? isLoading,
|
||||
}) {
|
||||
return TeacherMonetizationState(
|
||||
institutionalStudents: institutionalStudents ?? this.institutionalStudents,
|
||||
institutionalStudents:
|
||||
institutionalStudents ?? this.institutionalStudents,
|
||||
studentSubscribers: studentSubscribers ?? this.studentSubscribers,
|
||||
pricePerCourse: pricePerCourse ?? this.pricePerCourse,
|
||||
grossRevenue: grossRevenue ?? this.grossRevenue,
|
||||
@@ -86,7 +87,7 @@ class TeacherMonetizationCubit extends Cubit<TeacherMonetizationState> {
|
||||
|
||||
TeacherMonetizationCubit({required this.repository})
|
||||
: super(const TeacherMonetizationState(
|
||||
institutionalStudents: 83,
|
||||
institutionalStudents: 0,
|
||||
studentSubscribers: 0,
|
||||
pricePerCourse: 20.0,
|
||||
grossRevenue: 0.0,
|
||||
@@ -95,7 +96,7 @@ class TeacherMonetizationCubit extends Cubit<TeacherMonetizationState> {
|
||||
platformShare: 0.0,
|
||||
availableBalance: 0.0,
|
||||
totalWithdrawn: 0.0,
|
||||
cliqAlias: '0798583052@CLIQ',
|
||||
cliqAlias: '',
|
||||
courses: [],
|
||||
payoutRequests: [],
|
||||
isSubmittingPayout: false,
|
||||
@@ -108,20 +109,26 @@ class TeacherMonetizationCubit extends Cubit<TeacherMonetizationState> {
|
||||
final data = await repository.getMonetizationDashboard();
|
||||
final courses = await repository.getPublishedCourses();
|
||||
|
||||
final audience = data['audience_breakdown'] as Map<String, dynamic>? ?? {};
|
||||
final inst = audience['institutional_students'] as Map<String, dynamic>? ?? {};
|
||||
final mkt = audience['marketplace_students'] as Map<String, dynamic>? ?? {};
|
||||
final audience =
|
||||
data['audience_breakdown'] as Map<String, dynamic>? ?? {};
|
||||
final inst =
|
||||
audience['institutional_students'] as Map<String, dynamic>? ?? {};
|
||||
final mkt =
|
||||
audience['marketplace_students'] as Map<String, dynamic>? ?? {};
|
||||
final wallet = data['wallet'] as Map<String, dynamic>? ?? {};
|
||||
|
||||
final instCount = (inst['count'] as num?)?.toDouble() ?? 83.0;
|
||||
final instCount = (inst['count'] as num?)?.toDouble() ?? 0.0;
|
||||
final paidCount = (mkt['count'] as num?)?.toDouble() ?? 0.0;
|
||||
final gross = (data['gross_revenue_jod'] as num?)?.toDouble() ?? (paidCount * 20.0);
|
||||
final gross =
|
||||
(data['gross_revenue_jod'] as num?)?.toDouble() ?? (paidCount * 20.0);
|
||||
final tShare = gross * 0.55;
|
||||
final dShare = gross * 0.15;
|
||||
final pShare = gross * 0.30;
|
||||
final avail = (wallet['available_balance_jod'] as num?)?.toDouble() ?? tShare;
|
||||
final withdrawn = (wallet['total_withdrawn_jod'] as num?)?.toDouble() ?? 0.0;
|
||||
final alias = wallet['cliq_payout_alias']?.toString() ?? '0798583052@CLIQ';
|
||||
final avail =
|
||||
(wallet['available_balance_jod'] as num?)?.toDouble() ?? tShare;
|
||||
final withdrawn =
|
||||
(wallet['total_withdrawn_jod'] as num?)?.toDouble() ?? 0.0;
|
||||
final alias = wallet['cliq_payout_alias']?.toString() ?? '';
|
||||
|
||||
List<TeacherPayoutRequestModel> payouts = [];
|
||||
if (wallet['recent_payouts'] is List) {
|
||||
@@ -176,8 +183,11 @@ class TeacherMonetizationCubit extends Cubit<TeacherMonetizationState> {
|
||||
cliqAlias: cliqAlias,
|
||||
amountJod: amountJod,
|
||||
);
|
||||
final updatedList = List<TeacherPayoutRequestModel>.from(state.payoutRequests)..insert(0, req);
|
||||
final newAvail = (state.availableBalance - amountJod).clamp(0.0, double.infinity);
|
||||
final updatedList =
|
||||
List<TeacherPayoutRequestModel>.from(state.payoutRequests)
|
||||
..insert(0, req);
|
||||
final newAvail =
|
||||
(state.availableBalance - amountJod).clamp(0.0, double.infinity);
|
||||
final newWithdrawn = state.totalWithdrawn + amountJod;
|
||||
|
||||
emit(state.copyWith(
|
||||
|
||||
@@ -58,16 +58,21 @@ class TeacherQnACubit extends Cubit<TeacherQnAState> {
|
||||
|
||||
Future<void> loadQnA() async {
|
||||
emit(state.copyWith(isLoading: true));
|
||||
final hwList = await repository.getHomeworks();
|
||||
final doubtsList = await repository.getStudentDoubts();
|
||||
final conversationsList = await repository.getConversations();
|
||||
|
||||
emit(state.copyWith(
|
||||
homeworks: hwList,
|
||||
doubts: doubtsList,
|
||||
conversations: conversationsList,
|
||||
isLoading: false,
|
||||
));
|
||||
try {
|
||||
final results = await Future.wait([
|
||||
repository.getHomeworks(),
|
||||
repository.getStudentDoubts(),
|
||||
repository.getConversations(),
|
||||
]);
|
||||
emit(state.copyWith(
|
||||
homeworks: results[0] as List<TeacherHomeworkModel>,
|
||||
doubts: results[1] as List<StudentDoubtModel>,
|
||||
conversations: results[2] as List<ChatConversationModel>,
|
||||
isLoading: false,
|
||||
));
|
||||
} catch (_) {
|
||||
emit(state.copyWith(isLoading: false));
|
||||
}
|
||||
}
|
||||
|
||||
void dispatchNewHomework({
|
||||
@@ -86,14 +91,19 @@ class TeacherQnACubit extends Cubit<TeacherQnAState> {
|
||||
final target = state.doubts[targetIndex];
|
||||
final replyText = voiceText?.trim() ?? '';
|
||||
if (replyText.isEmpty) {
|
||||
throw StateError('لا يمكن تسجيل رد صوتي دون ملف صوت حقيقي؛ أرسل رداً نصياً حالياً.');
|
||||
throw StateError(
|
||||
'لا يمكن تسجيل رد صوتي دون ملف صوت حقيقي؛ أرسل رداً نصياً حالياً.');
|
||||
}
|
||||
await repository.sendMessage(
|
||||
receiverId: target.studentId,
|
||||
message: replyText,
|
||||
messageType: 'text',
|
||||
);
|
||||
final updated = state.doubts.map((doubt) => doubt.id == doubtId ? doubt.copyWith(replied: true, voiceReply: false) : doubt).toList();
|
||||
final updated = state.doubts
|
||||
.map((doubt) => doubt.id == doubtId
|
||||
? doubt.copyWith(replied: true, voiceReply: false)
|
||||
: doubt)
|
||||
.toList();
|
||||
emit(state.copyWith(doubts: updated));
|
||||
}
|
||||
|
||||
@@ -106,8 +116,8 @@ class TeacherQnACubit extends Cubit<TeacherQnAState> {
|
||||
final success = await repository.broadcastAnnouncement(
|
||||
title: title,
|
||||
message: explanationText,
|
||||
messageType: 'voice',
|
||||
mediaUrl: 'https://saqel.intaleqapp.com/assets/audio/teacher_broadcast.mp3',
|
||||
messageType: 'text',
|
||||
mediaUrl: null,
|
||||
gradeLevel: gradeLevel,
|
||||
);
|
||||
emit(state.copyWith(isBroadcasting: false));
|
||||
|
||||
@@ -17,6 +17,14 @@ class TeacherStudioState {
|
||||
final String lessonTitle;
|
||||
final double durationMinutes;
|
||||
final String gradeLevel;
|
||||
final Map<String, dynamic> curriculumTree;
|
||||
final String gradeKey;
|
||||
final String subjectKey;
|
||||
final String semesterKey;
|
||||
final String unitKey;
|
||||
final String lessonKey;
|
||||
final bool isCurriculumLoading;
|
||||
final String? errorMessage;
|
||||
final String? selectedFileName;
|
||||
final double? selectedFileSizeMb;
|
||||
final String? selectedFilePath;
|
||||
@@ -30,7 +38,15 @@ class TeacherStudioState {
|
||||
const TeacherStudioState({
|
||||
required this.lessonTitle,
|
||||
required this.durationMinutes,
|
||||
this.gradeLevel = 'الصف العاشر الأساسي',
|
||||
this.gradeLevel = '',
|
||||
this.curriculumTree = const {},
|
||||
this.gradeKey = '',
|
||||
this.subjectKey = '',
|
||||
this.semesterKey = '',
|
||||
this.unitKey = '',
|
||||
this.lessonKey = '',
|
||||
this.isCurriculumLoading = false,
|
||||
this.errorMessage,
|
||||
this.selectedFileName,
|
||||
this.selectedFileSizeMb,
|
||||
this.selectedFilePath,
|
||||
@@ -46,6 +62,15 @@ class TeacherStudioState {
|
||||
String? lessonTitle,
|
||||
double? durationMinutes,
|
||||
String? gradeLevel,
|
||||
Map<String, dynamic>? curriculumTree,
|
||||
String? gradeKey,
|
||||
String? subjectKey,
|
||||
String? semesterKey,
|
||||
String? unitKey,
|
||||
String? lessonKey,
|
||||
bool? isCurriculumLoading,
|
||||
String? errorMessage,
|
||||
bool clearError = false,
|
||||
String? selectedFileName,
|
||||
double? selectedFileSizeMb,
|
||||
String? selectedFilePath,
|
||||
@@ -60,6 +85,14 @@ class TeacherStudioState {
|
||||
lessonTitle: lessonTitle ?? this.lessonTitle,
|
||||
durationMinutes: durationMinutes ?? this.durationMinutes,
|
||||
gradeLevel: gradeLevel ?? this.gradeLevel,
|
||||
curriculumTree: curriculumTree ?? this.curriculumTree,
|
||||
gradeKey: gradeKey ?? this.gradeKey,
|
||||
subjectKey: subjectKey ?? this.subjectKey,
|
||||
semesterKey: semesterKey ?? this.semesterKey,
|
||||
unitKey: unitKey ?? this.unitKey,
|
||||
lessonKey: lessonKey ?? this.lessonKey,
|
||||
isCurriculumLoading: isCurriculumLoading ?? this.isCurriculumLoading,
|
||||
errorMessage: clearError ? null : errorMessage ?? this.errorMessage,
|
||||
selectedFileName: selectedFileName ?? this.selectedFileName,
|
||||
selectedFileSizeMb: selectedFileSizeMb ?? this.selectedFileSizeMb,
|
||||
selectedFilePath: selectedFilePath ?? this.selectedFilePath,
|
||||
@@ -78,8 +111,8 @@ class TeacherStudioCubit extends Cubit<TeacherStudioState> {
|
||||
|
||||
TeacherStudioCubit({required this.repository})
|
||||
: super(const TeacherStudioState(
|
||||
lessonTitle: 'شرح قاعدة لنتز والحث الكهرومغناطيسي — فيزياء 2008',
|
||||
durationMinutes: 13.0,
|
||||
lessonTitle: '',
|
||||
durationMinutes: 20.0,
|
||||
isAuditing: false,
|
||||
auditResult: null,
|
||||
));
|
||||
@@ -96,6 +129,137 @@ class TeacherStudioCubit extends Cubit<TeacherStudioState> {
|
||||
emit(state.copyWith(gradeLevel: grade));
|
||||
}
|
||||
|
||||
Map<String, dynamic> _map(dynamic value) =>
|
||||
value is Map ? Map<String, dynamic>.from(value) : {};
|
||||
Map<String, dynamic> get _subjects =>
|
||||
_map(state.curriculumTree[state.gradeKey]?['subjects']);
|
||||
Map<String, dynamic> get _semesters =>
|
||||
_map(_subjects[state.subjectKey]?['semesters']);
|
||||
Map<String, dynamic> get _units =>
|
||||
_map(_semesters[state.semesterKey]?['units']);
|
||||
|
||||
Future<void> loadCurriculum() async {
|
||||
if (state.curriculumTree.isNotEmpty || state.isCurriculumLoading) return;
|
||||
emit(state.copyWith(isCurriculumLoading: true, clearError: true));
|
||||
try {
|
||||
final results = await Future.wait(
|
||||
[repository.getCurriculumTree(), repository.getProfileStatus()]);
|
||||
final rawTree = Map<String, dynamic>.from(results[0] as Map);
|
||||
final profile = results[1] as TeacherProfileModel;
|
||||
final allowedGrades = profile.gradesTaught
|
||||
.map(_normalized)
|
||||
.where((e) => e.isNotEmpty)
|
||||
.toList();
|
||||
final specialization = _normalized(profile.specialization);
|
||||
final tree = <String, dynamic>{};
|
||||
for (final gradeEntry in rawTree.entries) {
|
||||
final gradeNode = _map(gradeEntry.value);
|
||||
final gradeName =
|
||||
_normalized(gradeNode['name']?.toString() ?? gradeEntry.key);
|
||||
if (allowedGrades.isNotEmpty &&
|
||||
!allowedGrades
|
||||
.any((g) => gradeName.contains(g) || g.contains(gradeName)))
|
||||
continue;
|
||||
final allSubjects = _map(gradeNode['subjects']);
|
||||
if (specialization.isNotEmpty) {
|
||||
final matched = Map<String, dynamic>.fromEntries(
|
||||
allSubjects.entries.where((entry) {
|
||||
final subjectName =
|
||||
_normalized('${entry.key} ${_map(entry.value)['name'] ?? ''}');
|
||||
return subjectName.contains(specialization) ||
|
||||
specialization.contains(subjectName) ||
|
||||
specialization.split(' ').any(
|
||||
(word) => word.length > 3 && subjectName.contains(word));
|
||||
}));
|
||||
if (matched.isNotEmpty) gradeNode['subjects'] = matched;
|
||||
}
|
||||
tree[gradeEntry.key] = gradeNode;
|
||||
}
|
||||
final key = tree.keys.isNotEmpty ? tree.keys.first : '';
|
||||
emit(state.copyWith(curriculumTree: tree, isCurriculumLoading: false));
|
||||
selectGrade(key);
|
||||
} catch (e) {
|
||||
emit(state.copyWith(
|
||||
isCurriculumLoading: false, errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
String _normalized(String value) => value
|
||||
.toLowerCase()
|
||||
.replaceAll(RegExp(r'[^\u0600-\u06ffa-z0-9]+'), ' ')
|
||||
.trim();
|
||||
|
||||
void selectGrade(String key) {
|
||||
final node = state.curriculumTree[key];
|
||||
final name = node is Map ? node['name']?.toString() ?? key : key;
|
||||
emit(state.copyWith(
|
||||
gradeKey: key,
|
||||
gradeLevel: name,
|
||||
subjectKey: '',
|
||||
semesterKey: '',
|
||||
unitKey: '',
|
||||
lessonKey: '',
|
||||
clearError: true));
|
||||
final values = _map(state.curriculumTree[key]?['subjects']);
|
||||
selectSubject(values.keys.isNotEmpty ? values.keys.first : '');
|
||||
}
|
||||
|
||||
void selectSubject(String key) {
|
||||
emit(state.copyWith(
|
||||
subjectKey: key,
|
||||
semesterKey: '',
|
||||
unitKey: '',
|
||||
lessonKey: '',
|
||||
clearError: true));
|
||||
final values = _map(_subjects[key]?['semesters']);
|
||||
selectSemester(values.keys.isNotEmpty ? values.keys.first : '');
|
||||
}
|
||||
|
||||
void selectSemester(String key) {
|
||||
emit(state.copyWith(
|
||||
semesterKey: key, unitKey: '', lessonKey: '', clearError: true));
|
||||
final values = _map(_semesters[key]?['units']);
|
||||
selectUnit(values.keys.isNotEmpty ? values.keys.first : '');
|
||||
}
|
||||
|
||||
void selectUnit(String key) {
|
||||
emit(state.copyWith(unitKey: key, lessonKey: '', clearError: true));
|
||||
final lessons = _units[key]?['lessons'];
|
||||
final id = lessons is List && lessons.isNotEmpty && lessons.first is Map
|
||||
? (lessons.first as Map)['id']?.toString() ?? ''
|
||||
: '';
|
||||
selectLesson(id);
|
||||
}
|
||||
|
||||
void selectLesson(String key) {
|
||||
String title = '';
|
||||
final lessons = _units[state.unitKey]?['lessons'];
|
||||
if (lessons is List)
|
||||
for (final item in lessons) {
|
||||
if (item is Map && item['id']?.toString() == key)
|
||||
title = item['title']?.toString() ?? '';
|
||||
}
|
||||
emit(state.copyWith(lessonKey: key, lessonTitle: title, clearError: true));
|
||||
}
|
||||
|
||||
String get selectedSubjectName {
|
||||
final node = _subjects[state.subjectKey];
|
||||
final name = node is Map
|
||||
? node['name']?.toString() ?? state.subjectKey
|
||||
: state.subjectKey;
|
||||
return name.replaceFirst(RegExp(r'\s*\([^)]*\)\s*$'), '').trim();
|
||||
}
|
||||
|
||||
String get curriculumKey => [
|
||||
state.gradeKey,
|
||||
state.subjectKey,
|
||||
state.semesterKey,
|
||||
state.unitKey,
|
||||
state.lessonKey
|
||||
].where((e) => e.isNotEmpty).join('/');
|
||||
void reportError(String message) =>
|
||||
emit(state.copyWith(errorMessage: message));
|
||||
|
||||
void selectVideoFile(
|
||||
String fileName,
|
||||
double sizeMb,
|
||||
@@ -115,20 +279,18 @@ class TeacherStudioCubit extends Cubit<TeacherStudioState> {
|
||||
}
|
||||
|
||||
Future<void> runQualityGate() async {
|
||||
emit(state.copyWith(isAuditing: true));
|
||||
try {
|
||||
final result = await repository.auditStudioVideo(
|
||||
title: state.lessonTitle,
|
||||
durationMinutes: state.durationMinutes,
|
||||
subject: 'الفيزياء',
|
||||
);
|
||||
if (state.selectedFileName == null ||
|
||||
(state.selectedFilePath == null && state.selectedFileBytes == null)) {
|
||||
emit(state.copyWith(
|
||||
isAuditing: false,
|
||||
auditResult: result,
|
||||
));
|
||||
} catch (_) {
|
||||
emit(state.copyWith(isAuditing: false));
|
||||
errorMessage: 'اختر ملف فيديو فعلياً قبل بدء فحص الجودة.'));
|
||||
return;
|
||||
}
|
||||
if (curriculumKey.isEmpty || state.lessonTitle.trim().isEmpty) {
|
||||
emit(state.copyWith(
|
||||
errorMessage: 'اختر الصف والمبحث والفصل والوحدة والدرس أولاً.'));
|
||||
return;
|
||||
}
|
||||
await uploadAndPublishLesson();
|
||||
}
|
||||
|
||||
Future<bool> uploadAndPublishLesson() async {
|
||||
@@ -136,28 +298,45 @@ class TeacherStudioCubit extends Cubit<TeacherStudioState> {
|
||||
(state.selectedFilePath == null && state.selectedFileBytes == null)) {
|
||||
return false;
|
||||
}
|
||||
emit(state.copyWith(isUploading: true));
|
||||
emit(state.copyWith(isUploading: true, isAuditing: true, clearError: true));
|
||||
try {
|
||||
final res = await repository.uploadLesson(
|
||||
title: state.lessonTitle,
|
||||
durationMinutes: state.durationMinutes,
|
||||
gradeLevel: state.gradeLevel,
|
||||
subject: 'الفيزياء والعلوم التطبيقية',
|
||||
fileName: state.selectedFileName ?? 'lentz_law_physics_2008.mp4',
|
||||
fileSizeMb: state.selectedFileSizeMb ?? 48.2,
|
||||
subject: selectedSubjectName,
|
||||
curriculumKey: curriculumKey,
|
||||
fileName: state.selectedFileName!,
|
||||
fileSizeMb: state.selectedFileSizeMb,
|
||||
filePath: state.selectedFilePath,
|
||||
fileBytes: state.selectedFileBytes,
|
||||
);
|
||||
|
||||
final msg = res['message']?.toString() ?? 'تم رفع ونشر الحصة بنجاح في المنهاج الوزاري وسوق صَقِل! 🚀';
|
||||
final data = res['data'] is Map
|
||||
? Map<String, dynamic>.from(res['data'] as Map)
|
||||
: <String, dynamic>{};
|
||||
final report = data['preflight_report'] is Map
|
||||
? Map<String, dynamic>.from(data['preflight_report'] as Map)
|
||||
: <String, dynamic>{};
|
||||
final result = TeacherLessonAuditModel.fromJson({
|
||||
...report,
|
||||
'lesson_title': state.lessonTitle,
|
||||
'subject': selectedSubjectName
|
||||
});
|
||||
final msg = res['message']?.toString() ?? 'تم اعتماد الحصة ورفعها بنجاح.';
|
||||
emit(state.copyWith(
|
||||
isAuditing: false,
|
||||
isUploading: false,
|
||||
isUploaded: true,
|
||||
auditResult: result,
|
||||
uploadSuccessMessage: msg,
|
||||
));
|
||||
return true;
|
||||
} catch (e) {
|
||||
emit(state.copyWith(isUploading: false));
|
||||
emit(state.copyWith(
|
||||
isAuditing: false,
|
||||
isUploading: false,
|
||||
errorMessage: e.toString().replaceFirst('Bad state: ', '')));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user