Files
TIS_RMS/frontend/lib/ui/providers/setup_provider.dart
T
ssbg04 bd2a8acbfe feat(settings): clean academic setup buttons and rename screen to Academic & Class Management
- Update screen, settings card, and dashboard titles to 'Academic & Class Management'

- Clean and balance Academic Structure toolbar for mobile and desktop

- Remove redundant buttons on section cards in favor of interactive adviser chip

- Modernize teacher action button to OutlinedButton.icon 'Sections'

- Add responsive bulk academic structure import support across backend and frontend
2026-09-27 02:05:47 +08:00

300 lines
7.8 KiB
Dart

import 'dart:async';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../domain/entities/setup_models.dart';
import '../../domain/repositories/setup_repository.dart';
import 'auth_provider.dart';
import 'users_provider.dart';
final setupRepositoryProvider = Provider<SetupRepository>((ref) {
return SetupRepository();
});
final academicYearsListProvider = FutureProvider<List<AcademicYearModel>>((
ref,
) async {
final repo = ref.read(setupRepositoryProvider);
return repo.getAcademicYears();
});
final sectionsListProvider = FutureProvider<List<SectionModel>>((ref) async {
final repo = ref.read(setupRepositoryProvider);
final user = ref.watch(authProvider).value;
if (user?.role == 'teacher') {
return repo.getTeacherSections(user!.id);
}
return repo.getAllSections();
});
final gradeLevelsListProvider = FutureProvider<List<GradeLevelModel>>((
ref,
) async {
final repo = ref.read(setupRepositoryProvider);
return repo.getGradeLevels();
});
final teacherSectionsProvider = FutureProvider.family<List<SectionModel>, int>((
ref,
teacherId,
) async {
final repo = ref.read(setupRepositoryProvider);
return repo.getTeacherSections(teacherId);
});
// Setup mutation notifier for CRUD setup actions
final setupMutationProvider =
AsyncNotifierProvider<SetupMutationNotifier, void>(
SetupMutationNotifier.new,
);
class SetupMutationNotifier extends AsyncNotifier<void> {
@override
FutureOr<void> build() {}
// Academic Years
Future<void> createAcademicYear({
required String yearRange,
required String status,
String? startDate,
String? endDate,
}) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
await repo.createAcademicYear(
yearRange: yearRange,
status: status,
startDate: startDate,
endDate: endDate,
);
state = const AsyncData(null);
ref.invalidate(academicYearsListProvider);
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
Future<void> updateAcademicYear({
required int id,
required String yearRange,
required String status,
String? startDate,
String? endDate,
}) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
await repo.updateAcademicYear(
id: id,
yearRange: yearRange,
status: status,
startDate: startDate,
endDate: endDate,
);
state = const AsyncData(null);
ref.invalidate(academicYearsListProvider);
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
Future<Map<String, dynamic>> checkAutoGraduation() async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
final res = await repo.checkAutoGraduation();
state = const AsyncData(null);
ref.invalidate(academicYearsListProvider);
return res;
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
Future<void> deleteAcademicYear(int id) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
await repo.deleteAcademicYear(id);
state = const AsyncData(null);
ref.invalidate(academicYearsListProvider);
// Cascades delete sections
ref.invalidate(sectionsListProvider);
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
// Sections
Future<void> createSection({
required String name,
required int gradeLevel,
required int academicYearId,
int? teacherId,
}) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
await repo.createSection(
name: name,
gradeLevel: gradeLevel,
academicYearId: academicYearId,
teacherId: teacherId,
);
state = const AsyncData(null);
ref.invalidate(sectionsListProvider);
ref.invalidate(usersProvider);
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
Future<Map<String, dynamic>> bulkCreateAcademicStructure(
List<Map<String, dynamic>> rows,
) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
final res = await repo.bulkCreateAcademicStructure(rows);
state = const AsyncData(null);
ref.invalidate(academicYearsListProvider);
ref.invalidate(gradeLevelsListProvider);
ref.invalidate(sectionsListProvider);
ref.invalidate(usersProvider);
return res;
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
Future<void> updateSection({
required int id,
required String name,
required int gradeLevel,
required int academicYearId,
int? teacherId,
}) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
await repo.updateSection(
id: id,
name: name,
gradeLevel: gradeLevel,
academicYearId: academicYearId,
teacherId: teacherId,
);
state = const AsyncData(null);
ref.invalidate(sectionsListProvider);
ref.invalidate(usersProvider);
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
Future<void> setSectionAdviser({
required int sectionId,
int? teacherId,
}) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
await repo.setSectionAdviser(sectionId: sectionId, teacherId: teacherId);
state = const AsyncData(null);
ref.invalidate(sectionsListProvider);
ref.invalidate(usersProvider);
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
Future<void> deleteSection(int id) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
await repo.deleteSection(id);
state = const AsyncData(null);
ref.invalidate(sectionsListProvider);
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
// Grade Levels
Future<void> createGradeLevel({
required int level,
required String name,
}) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
await repo.createGradeLevel(level: level, name: name);
state = const AsyncData(null);
ref.invalidate(gradeLevelsListProvider);
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
Future<void> updateGradeLevel({
required int id,
required int level,
required String name,
}) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
await repo.updateGradeLevel(id: id, level: level, name: name);
state = const AsyncData(null);
ref.invalidate(gradeLevelsListProvider);
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
Future<void> deleteGradeLevel(int id) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
await repo.deleteGradeLevel(id);
state = const AsyncData(null);
ref.invalidate(gradeLevelsListProvider);
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
// Teacher Sections Assignment
Future<void> updateTeacherSections({
required int teacherId,
required List<int> sectionIds,
}) async {
state = const AsyncLoading();
try {
final repo = ref.read(setupRepositoryProvider);
await repo.updateTeacherSections(
teacherId: teacherId,
sectionIds: sectionIds,
);
state = const AsyncData(null);
ref.invalidate(teacherSectionsProvider(teacherId));
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
}