fix(reports, students): fix reports yearly comparison layout overflow and students tab active year filter
This commit is contained in:
1 parent
bd1a712b40
commit
c993937314
6 files changed
+74
-15
No files matched your search
@@ -1132,6 +1132,10 @@ Files backup/restore - mirror mode or zip -->
|
||||
# REPORTS SCREEN
|
||||
- [x] compliance tab student document compliance search bar not visible make it visible for all theme
|
||||
- [x] make the space consume, make the analytics prominently visible with minimal scrolling
|
||||
- [x] fix layout overflow in compliance tab yearly comparison chart on Windows app (adjusted card height to 360, dynamic chart height calculation, and wrapped scrollable chart in Expanded on desktop)
|
||||
|
||||
# STUDENT SCREEN
|
||||
- [x] fix students tab showing all students on re-click: preserved active academic year in studentQueryProvider reset and fail-safe fallback in studentPageProvider for enrolled tab
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -383,6 +383,7 @@ class _AndroidBottomNavLayoutState extends ConsumerState<AndroidBottomNavLayout>
|
||||
ref.invalidate(dashboardDataProvider);
|
||||
break;
|
||||
case 'Students':
|
||||
ref.read(studentViewTabProvider.notifier).state = StudentViewTab.enrolled;
|
||||
ref.read(studentQueryProvider.notifier).reset();
|
||||
ref.invalidate(studentPageProvider);
|
||||
break;
|
||||
|
||||
@@ -97,6 +97,7 @@ class _WindowsSidebarLayoutState extends ConsumerState<WindowsSidebarLayout> {
|
||||
ref.invalidate(dashboardDataProvider);
|
||||
break;
|
||||
case 'Students':
|
||||
ref.read(studentViewTabProvider.notifier).state = StudentViewTab.enrolled;
|
||||
ref.read(studentQueryProvider.notifier).reset();
|
||||
ref.invalidate(studentPageProvider);
|
||||
break;
|
||||
|
||||
@@ -5,7 +5,9 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import '../../core/network/api_constants.dart';
|
||||
import '../../domain/repositories/student_repository.dart';
|
||||
import '../../domain/entities/student_model.dart';
|
||||
import '../../domain/entities/setup_models.dart';
|
||||
import '../../domain/entities/dashboard_models.dart' show RecentActivity;
|
||||
import 'setup_provider.dart';
|
||||
|
||||
// ============================================================
|
||||
// Academic Years Model
|
||||
@@ -207,7 +209,21 @@ class StudentQueryNotifier extends Notifier<StudentQueryParams> {
|
||||
);
|
||||
}
|
||||
|
||||
void reset() => state = const StudentQueryParams();
|
||||
void reset({String? schoolYear}) {
|
||||
String sy = schoolYear ?? '';
|
||||
if (sy.isEmpty) {
|
||||
final tab = ref.read(studentViewTabProvider);
|
||||
if (tab == StudentViewTab.enrolled) {
|
||||
final years = ref.read(academicYearsListProvider).asData?.value ?? [];
|
||||
try {
|
||||
sy = years.firstWhere((y) => y.status.toLowerCase() == 'active').yearRange;
|
||||
} catch (_) {
|
||||
if (years.isNotEmpty) sy = years.first.yearRange;
|
||||
}
|
||||
}
|
||||
}
|
||||
state = StudentQueryParams(schoolYear: sy);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
@@ -258,6 +274,7 @@ final studentPageProvider = FutureProvider.autoDispose<StudentPage>((
|
||||
ref,
|
||||
) async {
|
||||
final query = ref.watch(studentQueryProvider);
|
||||
final tab = ref.watch(studentViewTabProvider);
|
||||
final repo = ref.read(studentRepositoryProvider);
|
||||
|
||||
final sub = repo.onStudentChanged.listen((_) {
|
||||
@@ -266,6 +283,25 @@ final studentPageProvider = FutureProvider.autoDispose<StudentPage>((
|
||||
|
||||
ref.onDispose(() => sub.cancel());
|
||||
|
||||
String effectiveSchoolYear = query.schoolYear;
|
||||
if (tab == StudentViewTab.enrolled &&
|
||||
effectiveSchoolYear.isEmpty &&
|
||||
query.search.isEmpty) {
|
||||
List<AcademicYearModel> years =
|
||||
ref.watch(academicYearsListProvider).asData?.value ?? [];
|
||||
if (years.isEmpty) {
|
||||
try {
|
||||
years = await ref.watch(academicYearsListProvider.future);
|
||||
} catch (_) {}
|
||||
}
|
||||
try {
|
||||
effectiveSchoolYear =
|
||||
years.firstWhere((y) => y.status.toLowerCase() == 'active').yearRange;
|
||||
} catch (_) {
|
||||
if (years.isNotEmpty) effectiveSchoolYear = years.first.yearRange;
|
||||
}
|
||||
}
|
||||
|
||||
return repo.getStudents(
|
||||
search: query.search,
|
||||
page: query.page,
|
||||
@@ -273,7 +309,7 @@ final studentPageProvider = FutureProvider.autoDispose<StudentPage>((
|
||||
gradeLevel: query.gradeLevel,
|
||||
status: query.status,
|
||||
section: query.section,
|
||||
schoolYear: query.schoolYear,
|
||||
schoolYear: effectiveSchoolYear,
|
||||
is4ps: query.is4Ps,
|
||||
lrn: query.lrn,
|
||||
sortBy: query.sortBy,
|
||||
|
||||
@@ -3691,7 +3691,7 @@ class _ReportsScreenState extends ConsumerState<ReportsScreen> {
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
height: isDesktop ? 300 : null,
|
||||
height: isDesktop ? 360 : null,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 14),
|
||||
decoration: _cardDecoration(),
|
||||
child: Column(
|
||||
@@ -4092,13 +4092,12 @@ class _ReportsScreenState extends ConsumerState<ReportsScreen> {
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
height: isDesktop ? 300 : null,
|
||||
height: isDesktop ? 360 : null,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 14),
|
||||
decoration: _cardDecoration(),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// ── Chart Title & Filter Row ──────────────────────────────────────
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -4266,14 +4265,15 @@ class _ReportsScreenState extends ConsumerState<ReportsScreen> {
|
||||
|
||||
final chartContent = LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final bool hasScroll = constraints.maxWidth < (data.length * 150.0);
|
||||
final double minYearWidth = isDesktop ? 100.0 : 130.0;
|
||||
final double requiredWidth = data.length * minYearWidth;
|
||||
final bool hasScroll = constraints.maxWidth < requiredWidth;
|
||||
final double chartWidth = hasScroll
|
||||
? (data.length * 150.0)
|
||||
? requiredWidth
|
||||
: constraints.maxWidth;
|
||||
final double scrollExtras = hasScroll ? 36.0 : 0.0;
|
||||
final double chartHeight = isDesktop
|
||||
? (hasScroll
|
||||
? (constraints.maxHeight - 48).clamp(140.0, 220.0)
|
||||
: constraints.maxHeight.clamp(160.0, 220.0))
|
||||
? (constraints.maxHeight - scrollExtras).clamp(80.0, 220.0)
|
||||
: 250;
|
||||
final Widget chartWidget = SizedBox(
|
||||
width: chartWidth,
|
||||
@@ -4417,15 +4417,20 @@ class _ReportsScreenState extends ConsumerState<ReportsScreen> {
|
||||
return Center(child: chartWidget);
|
||||
}
|
||||
|
||||
final scrollableChart = SingleChildScrollView(
|
||||
controller: _chartHorizontalScrollController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: chartWidget,
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
controller: _chartHorizontalScrollController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: chartWidget,
|
||||
),
|
||||
if (isDesktop)
|
||||
Expanded(child: scrollableChart)
|
||||
else
|
||||
scrollableChart,
|
||||
const SizedBox(height: 4),
|
||||
_CustomHorizontalScrollBar(
|
||||
controller: _chartHorizontalScrollController,
|
||||
|
||||
@@ -1053,6 +1053,18 @@ class _StudentsScreenState extends ConsumerState<StudentsScreen> {
|
||||
}
|
||||
});
|
||||
|
||||
ref.listen<StudentViewTab>(studentViewTabProvider, (previous, next) {
|
||||
if (mounted && _viewTab != next) {
|
||||
setState(() => _viewTab = next);
|
||||
}
|
||||
});
|
||||
|
||||
ref.listen<StudentQueryParams>(studentQueryProvider, (previous, next) {
|
||||
if (next.search.isEmpty && _searchController.text.isNotEmpty) {
|
||||
_searchController.clear();
|
||||
}
|
||||
});
|
||||
|
||||
ref.listen<AsyncValue<List<AcademicYearModel>>>(academicYearsListProvider, (prev, next) {
|
||||
if (!mounted) return;
|
||||
final years = next.asData?.value;
|
||||
|
||||
Reference in new issue
Block a user