import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../../shared/models/permission_matrix_models.dart'; import '../../../../shared/models/user_management_models.dart'; import '../../data/repositories/role_repository_impl.dart'; import '../../domain/usecases/role_usecases.dart'; class RolesListState { const RolesListState({ this.roles = const [], this.search = '', }); final List roles; final String search; List get filteredRoles { if (search.isEmpty) return roles; final q = search.toLowerCase(); return roles .where( (role) => role.name.toLowerCase().contains(q) || (role.description?.toLowerCase().contains(q) ?? false), ) .toList(); } RolesListState copyWith({ List? roles, String? search, }) { return RolesListState( roles: roles ?? this.roles, search: search ?? this.search, ); } } final getRoleCardsUseCaseProvider = Provider((ref) { return GetRoleCardsUseCase(ref.watch(roleRepositoryProvider)); }); final deleteRoleUseCaseProvider = Provider((ref) { return DeleteRoleUseCase(ref.watch(roleRepositoryProvider)); }); final getPermissionCatalogUseCaseProvider = Provider((ref) { return GetPermissionCatalogUseCase(ref.watch(roleRepositoryProvider)); }); final getPermissionMatrixUseCaseProvider = Provider((ref) { return GetPermissionMatrixUseCase(ref.watch(roleRepositoryProvider)); }); final savePermissionMatrixUseCaseProvider = Provider((ref) { return SavePermissionMatrixUseCase(ref.watch(roleRepositoryProvider)); }); final permissionCatalogProvider = FutureProvider>((ref) async { final result = await ref.read(getPermissionCatalogUseCaseProvider)(); if (result.failure != null) throw result.failure!; return result.data ?? const []; }); final rolesListProvider = AsyncNotifierProvider(RolesListNotifier.new); class RolesListNotifier extends AsyncNotifier { @override Future build() async { ref.keepAlive(); return _load(); } Future _load({String? search}) async { final result = await ref.read(getRoleCardsUseCaseProvider)(search: search); if (result.failure != null) throw result.failure!; return RolesListState(roles: result.data ?? [], search: search ?? ''); } Future refresh() async { final current = state.valueOrNull; if (current == null) { state = const AsyncLoading(); } try { state = AsyncData(await _load(search: current?.search)); } catch (e, st) { state = AsyncError(e, st); } } Future deleteRole(String id) async { final result = await ref.read(deleteRoleUseCaseProvider)(id); if (result.failure != null) return false; await refresh(); return true; } void setSearch(String search) { final current = state.valueOrNull; if (current == null) return; state = AsyncData(current.copyWith(search: search)); } } final permissionMatrixProvider = AsyncNotifierProvider.family< PermissionMatrixNotifier, RolePermissionMatrix, String>(PermissionMatrixNotifier.new); class PermissionMatrixNotifier extends FamilyAsyncNotifier { @override Future build(String arg) async { final useCase = ref.read(getPermissionMatrixUseCaseProvider); final result = await useCase(arg); if (result.failure != null) throw result.failure!; return result.data!; } void toggleAction(String moduleId, String action, bool value) { final current = state.valueOrNull; if (current == null) return; final updated = current.modules.map((row) { if (row.moduleId != moduleId) return row; final granted = Map.from(row.granted); granted[action] = value; return row.copyWith(granted: granted); }).toList(); state = AsyncData(current.copyWith(modules: updated)); } Future save() async { final current = state.valueOrNull; if (current == null) return false; final useCase = ref.read(savePermissionMatrixUseCaseProvider); final result = await useCase(arg, current); if (result.failure != null) return false; ref.invalidateSelf(); await future; return true; } }