Update Saqel Platform: 2026-09-05 22:08:42
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import '../models/directorate_models.dart';
|
||||
import '../../services/directorate_api_service.dart';
|
||||
|
||||
/// Repository for Directorate and School Principal operations
|
||||
class DirectorateRepository {
|
||||
final DirectorateApiService _apiService;
|
||||
|
||||
DirectorateRepository({DirectorateApiService? apiService})
|
||||
: _apiService = apiService ?? DirectorateApiService();
|
||||
|
||||
/// Fetch full directorate command dashboard
|
||||
Future<Map<String, dynamic>> getDirectorateDashboard() async {
|
||||
return await DirectorateApiService.fetchDirectorateDashboard();
|
||||
}
|
||||
|
||||
/// Fetch school principal dashboard by school ID
|
||||
Future<Map<String, dynamic>> getSchoolDashboard({int schoolId = 1}) async {
|
||||
return await DirectorateApiService.fetchSchoolDashboard(schoolId: schoolId);
|
||||
}
|
||||
|
||||
/// Record field lesson observation
|
||||
Future<Map<String, dynamic>> recordLesson({
|
||||
required int schoolId,
|
||||
required String teacherName,
|
||||
required String subject,
|
||||
required String topic,
|
||||
required double score,
|
||||
required String notes,
|
||||
}) async {
|
||||
return await DirectorateApiService.recordFieldObservation(
|
||||
schoolId: schoolId,
|
||||
teacherName: teacherName,
|
||||
subject: subject,
|
||||
topic: topic,
|
||||
score: score,
|
||||
notes: notes,
|
||||
);
|
||||
}
|
||||
|
||||
/// Push unified exam to computer lab
|
||||
Future<Map<String, dynamic>> pushExamToLab({
|
||||
required int schoolId,
|
||||
required String examTitle,
|
||||
required String labName,
|
||||
required int deviceCount,
|
||||
}) async {
|
||||
return await DirectorateApiService.pushExamToLab(
|
||||
schoolId: schoolId,
|
||||
examTitle: examTitle,
|
||||
labName: labName,
|
||||
deviceCount: deviceCount,
|
||||
);
|
||||
}
|
||||
|
||||
/// Evaluate session integrity
|
||||
Future<Map<String, dynamic>> evaluateIntegrity({
|
||||
required int sessionId,
|
||||
required String schoolCode,
|
||||
}) async {
|
||||
return await DirectorateApiService.evaluateSessionIntegrity(
|
||||
sessionId: sessionId,
|
||||
schoolCode: schoolCode,
|
||||
);
|
||||
}
|
||||
|
||||
/// Dispatch reports to parents via WhatsApp
|
||||
Future<Map<String, dynamic>> dispatchParentReports({
|
||||
required int schoolId,
|
||||
required String grade,
|
||||
}) async {
|
||||
return await DirectorateApiService.dispatchParentReports(
|
||||
schoolId: schoolId,
|
||||
grade: grade,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../data/models/directorate_models.dart';
|
||||
import '../../data/repositories/directorate_repository.dart';
|
||||
|
||||
abstract class DirectorateState {}
|
||||
|
||||
class DirectorateInitial extends DirectorateState {}
|
||||
|
||||
class DirectorateLoading extends DirectorateState {}
|
||||
|
||||
class DirectorateLoaded extends DirectorateState {
|
||||
final DirectorateOverview overview;
|
||||
final List<SchoolItem> schools;
|
||||
final Map<String, dynamic> rawData;
|
||||
|
||||
DirectorateLoaded({
|
||||
required this.overview,
|
||||
required this.schools,
|
||||
required this.rawData,
|
||||
});
|
||||
}
|
||||
|
||||
class SchoolPrincipalLoaded extends DirectorateState {
|
||||
final SchoolDetail school;
|
||||
final List<TeacherItem> teachers;
|
||||
final List<ComputerLabItem> labs;
|
||||
final Map<String, dynamic> rawData;
|
||||
|
||||
SchoolPrincipalLoaded({
|
||||
required this.school,
|
||||
required this.teachers,
|
||||
required this.labs,
|
||||
required this.rawData,
|
||||
});
|
||||
}
|
||||
|
||||
class DirectorateError extends DirectorateState {
|
||||
final String message;
|
||||
DirectorateError(this.message);
|
||||
}
|
||||
|
||||
class DirectorateActionSuccess extends DirectorateState {
|
||||
final String message;
|
||||
final dynamic result;
|
||||
DirectorateActionSuccess(this.message, [this.result]);
|
||||
}
|
||||
|
||||
/// Cubit managing state for Directorate and School Principal operations
|
||||
class DirectorateCubit extends Cubit<DirectorateState> {
|
||||
final DirectorateRepository _repository;
|
||||
|
||||
DirectorateCubit({DirectorateRepository? repository})
|
||||
: _repository = repository ?? DirectorateRepository(),
|
||||
super(DirectorateInitial());
|
||||
|
||||
/// Load directorate command overview
|
||||
Future<void> loadDirectorateOverview() async {
|
||||
emit(DirectorateLoading());
|
||||
try {
|
||||
final res = await _repository.getDirectorateDashboard();
|
||||
if (res['status'] == 'success' || res.containsKey('directorate')) {
|
||||
final overview = DirectorateOverview.fromJson(res['directorate'] ?? {});
|
||||
final schoolsList = (res['schools'] as List? ?? [])
|
||||
.map((s) => SchoolItem.fromJson(s))
|
||||
.toList();
|
||||
emit(DirectorateLoaded(
|
||||
overview: overview,
|
||||
schools: schoolsList,
|
||||
rawData: res,
|
||||
));
|
||||
} else {
|
||||
emit(DirectorateError(res['message'] ?? 'فشل تحميل بيانات المديرية'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(DirectorateError('خطأ في الاتصال: $e'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Load school principal dashboard
|
||||
Future<void> loadSchoolDashboard({int schoolId = 1}) async {
|
||||
emit(DirectorateLoading());
|
||||
try {
|
||||
final res = await _repository.getSchoolDashboard(schoolId: schoolId);
|
||||
if (res['status'] == 'success' || res.containsKey('school')) {
|
||||
final school = SchoolDetail.fromJson(res['school'] ?? {});
|
||||
final teachers = (res['teachers'] as List? ?? [])
|
||||
.map((t) => TeacherItem.fromJson(t))
|
||||
.toList();
|
||||
final labs = (res['computer_labs'] as List? ?? [])
|
||||
.map((l) => ComputerLabItem.fromJson(l))
|
||||
.toList();
|
||||
emit(SchoolPrincipalLoaded(
|
||||
school: school,
|
||||
teachers: teachers,
|
||||
labs: labs,
|
||||
rawData: res,
|
||||
));
|
||||
} else {
|
||||
emit(DirectorateError(res['message'] ?? 'فشل تحميل بيانات المدرسة'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(DirectorateError('خطأ في الاتصال: $e'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Push exam to lab
|
||||
Future<void> pushExam({
|
||||
required int schoolId,
|
||||
required String examTitle,
|
||||
required String labName,
|
||||
required int deviceCount,
|
||||
}) async {
|
||||
try {
|
||||
final res = await _repository.pushExamToLab(
|
||||
schoolId: schoolId,
|
||||
examTitle: examTitle,
|
||||
labName: labName,
|
||||
deviceCount: deviceCount,
|
||||
);
|
||||
emit(DirectorateActionSuccess('تم دفع الامتحان للمختبر بنجاح', res));
|
||||
// Reload dashboard
|
||||
await loadSchoolDashboard(schoolId: schoolId);
|
||||
} catch (e) {
|
||||
emit(DirectorateError('فشل دفع الامتحان: $e'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'screens/directorate_command_screen.dart';
|
||||
import 'screens/school_principal_screen.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'logic/cubits/directorate_cubit.dart';
|
||||
import 'presentation/screens/directorate_command_screen.dart';
|
||||
import 'presentation/screens/school_principal_screen.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const SaqelAdminApp());
|
||||
@@ -40,7 +42,10 @@ class SaqelAdminApp extends StatelessWidget {
|
||||
child: child ?? const SizedBox(),
|
||||
);
|
||||
},
|
||||
home: const UnifiedSupervisorShell(),
|
||||
home: BlocProvider(
|
||||
create: (context) => DirectorateCubit(),
|
||||
child: const UnifiedSupervisorShell(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/directorate_models.dart';
|
||||
import '../services/directorate_api_service.dart';
|
||||
import '../../data/models/directorate_models.dart';
|
||||
import '../../services/directorate_api_service.dart';
|
||||
|
||||
class DirectorateCommandScreen extends StatefulWidget {
|
||||
const DirectorateCommandScreen({super.key});
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/directorate_models.dart';
|
||||
import '../services/directorate_api_service.dart';
|
||||
import '../../data/models/directorate_models.dart';
|
||||
import '../../services/directorate_api_service.dart';
|
||||
|
||||
class SchoolPrincipalScreen extends StatefulWidget {
|
||||
const SchoolPrincipalScreen({super.key});
|
||||
@@ -340,10 +340,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
|
||||
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.18"
|
||||
version: "0.12.19"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -356,10 +356,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||
sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.0"
|
||||
version: "1.18.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -585,10 +585,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
|
||||
sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.9"
|
||||
version: "0.7.11"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -78,7 +78,7 @@ class TeacherRepository {
|
||||
}) async {
|
||||
try {
|
||||
final response = await _client.post(
|
||||
Uri.parse('$baseUrl/api/v1/cliq/payout'),
|
||||
Uri.parse('$baseUrl/api/teacher/payout/request'),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
|
||||
Reference in New Issue
Block a user