Skip to content

Commit bf54c32

Browse files
fix managers, global overlay, bulk create users
1 parent c27bbbc commit bf54c32

21 files changed

Lines changed: 243 additions & 250 deletions

File tree

.claude/settings.local.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(cd \"H:\\\\code\\\\dabblingwithcode\\\\school_data_hub\\\\school_data_hub_flutter\" && flutter analyze lib/features/user/ 2>&1)"
5+
]
6+
}
7+
}

school_data_hub_flutter/lib/common/domain/filters/filters.dart

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
import 'package:flutter/material.dart';
2-
import 'package:flutter_it/flutter_it.dart';
3-
import 'package:school_data_hub_flutter/common/domain/filters/filters_state_manager.dart';
4-
import 'package:school_data_hub_flutter/features/_pupil/domain/filters/pupils_filter.dart';
52

63
abstract class Filter<T extends Object> with ChangeNotifier {
74
Filter({
@@ -22,33 +19,20 @@ abstract class Filter<T extends Object> with ChangeNotifier {
2219
bool _isActive = false;
2320
bool get isActive => _isActive;
2421

22+
/// Optional callback invoked after toggle. Set by the composition root
23+
/// (e.g. PupilsFilterImplementation) to wire filter state changes to
24+
/// global state managers without coupling the base class to DI.
25+
void Function(Filter<T> filter, bool isActive)? onToggle;
26+
2527
void reset() {
2628
_isActive = false;
2729
notifyListeners();
2830
}
2931

3032
void toggle(bool isActive) {
3133
_isActive = isActive;
32-
if (isActive) {
33-
di<FiltersStateManager>().setFilterState(
34-
filterState: FilterState.pupil,
35-
value: true,
36-
);
37-
} else {
38-
if (!(di<PupilsFilter>().groupFilters.any((filter) => filter.isActive) ||
39-
di<PupilsFilter>().schoolGradeFilters.any(
40-
(filter) => filter.isActive,
41-
) ||
42-
di<PupilsFilter>().textFilter.isActive)) {
43-
di<FiltersStateManager>().setFilterState(
44-
filterState: FilterState.pupil,
45-
value: false,
46-
);
47-
}
48-
}
49-
5034
notifyListeners();
51-
di<PupilsFilter>().refreshs();
35+
onToggle?.call(this, isActive);
5236
}
5337

5438
bool matches(T item);

school_data_hub_flutter/lib/common/domain/filters/filters_state_manager.dart

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,5 @@
11
import 'package:collection/collection.dart';
22
import 'package:flutter/foundation.dart';
3-
import 'package:flutter_it/flutter_it.dart';
4-
import 'package:school_data_hub_flutter/features/_attendance/domain/filters/attendance_pupil_filter.dart';
5-
import 'package:school_data_hub_flutter/features/_pupil/domain/filters/pupil_filter_manager.dart';
6-
import 'package:school_data_hub_flutter/features/_pupil/domain/filters/pupils_filter.dart';
7-
import 'package:school_data_hub_flutter/features/_school_lists/domain/filters/school_list_filter_manager.dart';
8-
import 'package:school_data_hub_flutter/features/_schoolday_events/domain/filters/schoolday_event_filter_manager.dart';
9-
import 'package:school_data_hub_flutter/features/_authorizations/domain/filters/authorization_filter_manager.dart';
10-
import 'package:school_data_hub_flutter/features/_authorizations/domain/filters/pupil_authorization_filter_manager.dart';
11-
import 'package:school_data_hub_flutter/features/books/domain/filters/pupil_book_lending_filter_manager.dart';
12-
import 'package:school_data_hub_flutter/features/learning_support/domain/filters/learning_support_filter_manager.dart';
13-
import 'package:school_data_hub_flutter/features/_pupil/domain/filters/pupil_media_auth_filters.dart';
143

154
enum FilterState {
165
pupil,
@@ -38,6 +27,13 @@ const Map<FilterState, bool> _initialFilterGlobalValues = {
3827
FilterState.pupilBookLending: false,
3928
};
4029

30+
/// Interface for filter managers that can be reset.
31+
/// Implemented by all feature-specific filter managers so they can
32+
/// register themselves with FiltersStateManager.
33+
abstract class Resettable {
34+
void resetFilters();
35+
}
36+
4137
abstract class FiltersStateManager {
4238
void dispose();
4339
bool getFilterState(FilterState filterState);
@@ -50,18 +46,21 @@ abstract class FiltersStateManager {
5046

5147
void markFiltersActive(bool filtersOn);
5248

49+
void registerFilterManager(Resettable manager);
50+
5351
void resetFilters();
5452
}
5553

5654
class FiltersStateManagerImplementation implements FiltersStateManager {
5755
FiltersStateManagerImplementation();
5856

57+
final List<Resettable> _registeredFilterManagers = [];
58+
5959
@override
6060
void dispose() {
6161
_filterStates.dispose();
6262
_filtersActive.dispose();
63-
64-
return;
63+
_registeredFilterManagers.clear();
6564
}
6665

6766
void init() {
@@ -109,18 +108,16 @@ class FiltersStateManagerImplementation implements FiltersStateManager {
109108
_filtersActive.value = filtersOn;
110109
}
111110

111+
@override
112+
void registerFilterManager(Resettable manager) {
113+
_registeredFilterManagers.add(manager);
114+
}
115+
112116
@override
113117
void resetFilters() {
114-
di<AttendancePupilFilterManager>().resetFilters();
115-
di<PupilsFilter>().resetFilters();
116-
di<PupilFilterManager>().resetFilters();
117-
di<SchooldayEventFilterManager>().resetFilters();
118-
di<SchoolListFilterManager>().resetFilters();
119-
di<AuthorizationFilterManager>().resetFilters();
120-
di<PupilAuthorizationFilterManager>().resetFilters();
121-
di<LearningSupportFilterManager>().resetFilters();
122-
di<PupilBookLendingFilterManager>().resetFilters();
123-
di<PupilMediaAuthFilterManager>().resetFilters();
118+
for (final manager in _registeredFilterManagers) {
119+
manager.resetFilters();
120+
}
124121

125122
_filterStates.value = {..._initialFilterGlobalValues};
126123
_filtersActive.value = false;

school_data_hub_flutter/lib/common/services/notification_service.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ class NotificationService {
4444
NotificationService();
4545

4646
void showSnackBar(NotificationType type, String message) {
47-
if (_loadingNewInstance.value) {
48-
return;
49-
}
5047
switch (type) {
5148
case NotificationType.success:
5249
_log.info('''SNACK BAR SUCCESS:

school_data_hub_flutter/lib/core/init/init_on_user_auth.dart

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -164,35 +164,57 @@ class InitOnUserAuth {
164164
);
165165

166166
di.registerSingletonWithDependencies<AuthorizationFilterManager>(
167-
() => AuthorizationFilterManager()..init(),
167+
() {
168+
final manager = AuthorizationFilterManager()..init();
169+
di<FiltersStateManager>().registerFilterManager(manager);
170+
return manager;
171+
},
168172
dependsOn: [AuthorizationManager],
169173
dispose: (m) => m.dispose(),
170174
);
171175

172176
di.registerSingletonWithDependencies<PupilAuthorizationFilterManager>(
173-
() => PupilAuthorizationFilterManager(),
177+
() {
178+
final manager = PupilAuthorizationFilterManager();
179+
di<FiltersStateManager>().registerFilterManager(manager);
180+
return manager;
181+
},
174182
dependsOn: [AuthorizationManager],
175183
dispose: (m) => m.dispose(),
176184
);
177185

186+
// Register FiltersStateManager before all filter managers so they can
187+
// register themselves during construction.
188+
di.registerSingleton<FiltersStateManager>(
189+
FiltersStateManagerImplementation(),
190+
dispose: (m) => m.dispose(),
191+
);
192+
178193
di.registerSingletonWithDependencies<PupilFilterManager>(
179-
() => PupilFilterManager(),
194+
() {
195+
final manager = PupilFilterManager();
196+
di<FiltersStateManager>().registerFilterManager(manager);
197+
return manager;
198+
},
180199
dependsOn: [PupilProxyManager],
181200
dispose: (m) => m.dispose(),
182201
);
183202
di.registerSingletonWithDependencies<PupilBookLendingFilterManager>(
184-
() => PupilBookLendingFilterManager(),
203+
() {
204+
final manager = PupilBookLendingFilterManager();
205+
di<FiltersStateManager>().registerFilterManager(manager);
206+
return manager;
207+
},
185208
dependsOn: [PupilBookLendingManager],
186209
dispose: (m) => m.dispose(),
187210
);
188211

189-
di.registerSingleton<FiltersStateManager>(
190-
FiltersStateManagerImplementation(),
191-
dispose: (m) => m.dispose(),
192-
);
193-
194212
di.registerSingletonWithDependencies<LearningSupportFilterManager>(
195-
() => LearningSupportFilterManager(),
213+
() {
214+
final manager = LearningSupportFilterManager();
215+
di<FiltersStateManager>().registerFilterManager(manager);
216+
return manager;
217+
},
196218
dependsOn: [PupilProxyManager, PupilFilterManager],
197219
dispose: (m) => m.dispose(),
198220
);
@@ -204,7 +226,11 @@ class InitOnUserAuth {
204226
);
205227

206228
di.registerSingletonWithDependencies<SchooldayEventFilterManager>(
207-
() => SchooldayEventFilterManager(),
229+
() {
230+
final manager = SchooldayEventFilterManager();
231+
di<FiltersStateManager>().registerFilterManager(manager);
232+
return manager;
233+
},
208234
dependsOn: [PupilProxyManager, PupilFilterManager, SchooldayEventManager],
209235
dispose: (m) => m.dispose(),
210236
);
@@ -216,13 +242,21 @@ class InitOnUserAuth {
216242
);
217243

218244
di.registerSingletonWithDependencies<AttendancePupilFilterManager>(
219-
() => AttendancePupilFilterManager().init(),
245+
() {
246+
final manager = AttendancePupilFilterManager().init();
247+
di<FiltersStateManager>().registerFilterManager(manager);
248+
return manager;
249+
},
220250
dependsOn: [AttendanceManager],
221251
dispose: (m) => m.dispose(),
222252
);
223253

224254
di.registerSingletonWithDependencies<PupilsFilter>(
225-
() => PupilsFilterImplementation(di<PupilProxyManager>()),
255+
() {
256+
final manager = PupilsFilterImplementation(di<PupilProxyManager>());
257+
di<FiltersStateManager>().registerFilterManager(manager);
258+
return manager;
259+
},
226260
dependsOn: [
227261
PupilProxyManager,
228262
PupilFilterManager,
@@ -234,7 +268,11 @@ class InitOnUserAuth {
234268
);
235269

236270
di.registerSingletonWithDependencies<PupilMediaAuthFilterManager>(
237-
() => PupilMediaAuthFilterManager(),
271+
() {
272+
final manager = PupilMediaAuthFilterManager();
273+
di<FiltersStateManager>().registerFilterManager(manager);
274+
return manager;
275+
},
238276
dependsOn: [PupilsFilter],
239277
dispose: (m) => m.dispose(),
240278
);
@@ -246,7 +284,11 @@ class InitOnUserAuth {
246284
);
247285

248286
di.registerSingletonWithDependencies<SchoolListFilterManager>(
249-
() => SchoolListFilterManager()..init(),
287+
() {
288+
final manager = SchoolListFilterManager()..init();
289+
di<FiltersStateManager>().registerFilterManager(manager);
290+
return manager;
291+
},
250292
dependsOn: [PupilsFilter, SchoolListManager],
251293
dispose: (m) => m.dispose(),
252294
);

school_data_hub_flutter/lib/features/_attendance/domain/filters/attendance_pupil_filter.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import 'package:school_data_hub_flutter/features/_pupil/domain/filters/pupils_fi
1010
import 'package:school_data_hub_flutter/features/_pupil/domain/models/pupil_proxy.dart';
1111
import 'package:school_data_hub_flutter/features/school_calendar/domain/school_calendar_manager.dart';
1212

13-
class AttendancePupilFilterManager {
13+
class AttendancePupilFilterManager implements Resettable {
1414
FiltersStateManager get _filterStateManager => di<FiltersStateManager>();
1515
PupilsFilter get _pupilsFilter => di<PupilsFilter>();
1616
SchoolCalendarManager get _schoolCalendarManager =>
@@ -67,6 +67,7 @@ class AttendancePupilFilterManager {
6767
_pupilsFilter.refreshs();
6868
}
6969

70+
@override
7071
void resetFilters() {
7172
_attendancePupilFilterState.value = {...initialAttendancePupilFilterValues};
7273
_filterStateManager.setFilterState(

school_data_hub_flutter/lib/features/_authorizations/domain/filters/authorization_filter_manager.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import 'package:school_data_hub_flutter/common/domain/filters/filters_state_mana
44
import 'package:school_data_hub_flutter/features/_authorizations/domain/authorization_manager.dart';
55
import 'package:flutter_it/flutter_it.dart';
66

7-
class AuthorizationFilterManager {
7+
class AuthorizationFilterManager implements Resettable {
88
AuthorizationManager get _authorizationManager => di<AuthorizationManager>();
99
FiltersStateManager get _filtersStateManager => di<FiltersStateManager>();
1010
final ValueNotifier<List<Authorization>> _filteredAuthorizations =
@@ -44,6 +44,7 @@ class AuthorizationFilterManager {
4444
}
4545
}
4646

47+
@override
4748
void resetFilters() {
4849
_filterState.value = false;
4950
_filteredAuthorizations.value = _authorizationManager.authorizations.value;

school_data_hub_flutter/lib/features/_authorizations/domain/filters/pupil_authorization_filter_manager.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ Map<AuthorizationFilter, bool> initialPupilAuthorizationFilterValues = {
137137
AuthorizationFilter.fileResponse: false,
138138
};
139139

140-
class PupilAuthorizationFilterManager {
140+
class PupilAuthorizationFilterManager implements Resettable {
141141
final _pupilAuthorizationFilterState =
142142
ValueNotifier<Map<AuthorizationFilter, bool>>(
143143
initialPupilAuthorizationFilterValues,
@@ -151,6 +151,7 @@ class PupilAuthorizationFilterManager {
151151
return;
152152
}
153153

154+
@override
154155
void resetFilters() {
155156
_pupilAuthorizationFilterState.value = {
156157
...initialPupilAuthorizationFilterValues,

school_data_hub_flutter/lib/features/_pupil/domain/filters/pupil_filter_manager.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import 'package:school_data_hub_flutter/features/_pupil/domain/pupil_proxy_manag
1212

1313
typedef PupilFilterRecord = ({PupilFilter filter, bool value});
1414

15-
class PupilFilterManager {
15+
class PupilFilterManager implements Resettable {
1616
// final _searchText = ValueNotifier<String>('');
1717
// ValueListenable<String> get searchText => _searchText;
1818

@@ -41,6 +41,7 @@ class PupilFilterManager {
4141
return;
4242
}
4343

44+
@override
4445
void resetFilters() {
4546
_pupilFilterState.value = {...initialPupilFilterValues};
4647

school_data_hub_flutter/lib/features/_pupil/domain/filters/pupil_media_auth_filters.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ extension PublicMediaAuthFilterX on PublicMediaAuthFilter {
5050
}
5151
}
5252

53-
class PupilMediaAuthFilterManager {
53+
class PupilMediaAuthFilterManager implements Resettable {
5454
FiltersStateManager get _filterStateManager => di<FiltersStateManager>();
5555
PupilsFilter get _pupilsFilter => di<PupilsFilter>();
5656

@@ -84,6 +84,7 @@ class PupilMediaAuthFilterManager {
8484
_pupilsFilter.refreshs();
8585
}
8686

87+
@override
8788
void resetFilters() {
8889
_publicMediaAuthFilterState.value = {...initialPublicMediaAuthFilterValues};
8990
_filterStateManager.setFilterState(

0 commit comments

Comments
 (0)