diff --git a/assets/pngs/capitol.png b/assets/pngs/capitol.png new file mode 100644 index 0000000..968a7bc Binary files /dev/null and b/assets/pngs/capitol.png differ diff --git a/lib/bloc/user/user_bloc.dart b/lib/bloc/user/user_bloc.dart index da677e9..3f686ad 100644 --- a/lib/bloc/user/user_bloc.dart +++ b/lib/bloc/user/user_bloc.dart @@ -8,6 +8,8 @@ import 'package:unit2/model/login_data/user_info/assigned_area.dart'; import 'package:unit2/model/login_data/user_info/role.dart'; import 'package:unit2/model/login_data/user_info/user_data.dart'; import 'package:unit2/model/login_data/version_info.dart'; +import 'package:unit2/model/offline/offlane_modules.dart'; +import 'package:unit2/model/offline/offline_profile.dart'; import 'package:unit2/screens/unit2/login/functions/get_app_version.dart'; import 'package:unit2/sevices/login_service/auth_service.dart'; import 'package:unit2/utils/global.dart'; @@ -15,6 +17,7 @@ import '../../utils/scanner.dart'; import '../../utils/text_container.dart'; part 'user_event.dart'; part 'user_state.dart'; + class UserBloc extends Bloc { UserData? _userData; VersionInfo? _versionInfo; @@ -38,15 +41,15 @@ class UserBloc extends Bloc { String apkVersion = await getAppVersion(); _apkVersion = apkVersion; final String? saved = CREDENTIALS?.get('saved'); - username = CREDENTIALS?.get('username'); - password = CREDENTIALS?.get('password'); - if(apkVersion != _versionInfo!.id ){ - emit(VersionLoaded( + username = CREDENTIALS?.get('username'); + password = CREDENTIALS?.get('password'); + if (apkVersion != _versionInfo!.id) { + emit(VersionLoaded( versionInfo: _versionInfo, apkVersion: _apkVersion, username: event.username, password: event.password)); - }else if (saved != null) { + } else if (saved != null) { save = true; add(UserLogin(username: username, password: password)); } else { @@ -57,9 +60,14 @@ class UserBloc extends Bloc { password: event.password)); } } catch (e) { - emit(UserError( - message: e.toString(), - )); + bool? offlineAvalable = await OFFLINE!.get('offline'); + if (offlineAvalable == true) { + emit(ErrorWithOfflineMode()); + } else { + emit(UserError( + message: e.toString(), + )); + } } }); ////Loading the current version of the app @@ -76,50 +84,95 @@ class UserBloc extends Bloc { on((event, emit) async { username = event.username; password = event.password; + bool? availableOffline; + List offlineCards = []; try { - Map response = await AuthService.instance - .webLogin(username: event.username, password: event.password); - if (response['status'] == true) { - UserData userData = UserData.fromJson(response['data']); - Role? estPointPerson; - if (userData.user?.login?.user?.roles != null && - userData.user!.login!.user!.roles!.isNotEmpty) { - userData.user!.login!.user!.roles!.forEach((element) { - if (element!.name!.toLowerCase() == 'establishment point-person') { - estPointPerson = element; - } - }); - if (estPointPerson != null && - estPointPerson!.assignedArea!.isNotEmpty) { - estPointPerson!.assignedArea!.forEach((element) { - establishmentPointPersonAssignedAreas.add(element!); + Map response = await AuthService.instance + .webLogin(username: event.username, password: event.password); + if (response['status'] == true) { + UserData userData = UserData.fromJson(response['data']); + Role? estPointPerson; + if (userData.user?.login?.user?.roles != null && + userData.user!.login!.user!.roles!.isNotEmpty) { + userData.user!.login!.user!.roles!.forEach((element) { + if (element!.name!.toLowerCase() == + 'establishment point-person') { + estPointPerson = element; + } }); + if (estPointPerson != null && + estPointPerson!.assignedArea!.isNotEmpty) { + estPointPerson!.assignedArea!.forEach((element) { + establishmentPointPersonAssignedAreas.add(element!); + }); + } } - } + ////Check offline availabilty + for (var role in userData.user!.login!.user!.roles!) { + if (role!.name!.toLowerCase() == 'field surveyor') { + availableOffline = true; + OfflineModules newOfflineModule = OfflineModules( + moduleName: role.modules!.first!.name!, + object: role.modules!.first!.objects!.first!, + roleName: role.name!, + roleId: role.id!); - emit(UserLoggedIn( - estPersonAssignedArea: establishmentPointPersonAssignedAreas, - userData: userData, - success: true, - message: response['message'], - savedCredentials: save)); - } else { - emit(UserLoggedIn( - estPersonAssignedArea: establishmentPointPersonAssignedAreas, - userData: null, - success: false, - message: response['message'], - savedCredentials: save)); - } - } - on TimeoutException catch (_) { + offlineCards.add(newOfflineModule); + OfflineProfile offlineProfile = OfflineProfile( + webuserId: userData.employeeInfo?.profile?.webuserId, + id: userData.employeeInfo?.profile?.id, + lastName: userData.employeeInfo?.profile?.lastName, + firstName: userData.employeeInfo?.profile?.lastName, + middleName: userData.employeeInfo?.profile?.middleName, + nameExtension: userData.employeeInfo?.profile?.nameExtension, + sex: userData.employeeInfo?.profile?.sex, + birthdate: userData.employeeInfo?.profile?.birthdate, + civilStatus: civilStatus, + bloodType: bloodType, + heightM: userData.employeeInfo?.profile?.heightM, + weightKg: userData.employeeInfo?.profile?.weightKg, + photoPath: userData.employeeInfo?.profile?.photoPath, + esigPath: userData.employeeInfo?.profile?.esigPath, + maidenName: userData.employeeInfo?.profile?.maidenName, + deceased: userData.employeeInfo?.profile?.deceased, + uuidQrcode: userData.employeeInfo?.profile?.uuidQrcode, + titlePrefix: userData.employeeInfo?.profile?.titlePrefix, + titleSuffix: userData.employeeInfo?.profile?.titleSuffix, + showTitleId: userData.employeeInfo?.profile?.showTitleId, + ethnicity: userData.employeeInfo?.profile?.ethnicity, + disability: userData.employeeInfo?.profile?.disability, + gender: userData.employeeInfo?.profile?.gender, + religion: userData.employeeInfo?.profile?.religion, + ip: userData.employeeInfo?.profile?.ip); + await OFFLINE!.put("offline_profile", offlineProfile); + break; + } + } + await OFFLINE!.put('modules', offlineCards); + await OFFLINE!.put('offline', availableOffline); + globalOfflineAvailable = availableOffline; + emit(UserLoggedIn( + estPersonAssignedArea: establishmentPointPersonAssignedAreas, + userData: userData, + success: true, + message: response['message'], + savedCredentials: save)); + } else { + emit(UserLoggedIn( + estPersonAssignedArea: establishmentPointPersonAssignedAreas, + userData: null, + success: false, + message: response['message'], + savedCredentials: save)); + } + } on TimeoutException catch (_) { emit(InternetTimeout(message: timeoutError)); } on SocketException catch (_) { emit(InternetTimeout(message: timeoutError)); } on Error catch (e) { emit(LoginErrorState(message: e.toString())); - }catch(e){ - emit(LoginErrorState(message: e.toString())); + } catch (e) { + emit(LoginErrorState(message: e.toString())); } }); on((event, emit) async { diff --git a/lib/bloc/user/user_state.dart b/lib/bloc/user/user_state.dart index c63fbf7..e0588ad 100644 --- a/lib/bloc/user/user_state.dart +++ b/lib/bloc/user/user_state.dart @@ -71,3 +71,7 @@ class LoginErrorState extends UserState{ final String message; LoginErrorState({required this.message}); } + +class ErrorWithOfflineMode extends UserState{ + +} diff --git a/lib/main.dart b/lib/main.dart index d88fa6c..cb06bfe 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,10 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:unit2/bloc/profile/profile_bloc.dart'; import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/login_data/user_info/module.dart'; +import 'package:unit2/model/login_data/user_info/module_object.dart'; +import 'package:unit2/model/offline/offlane_modules.dart'; +import 'package:unit2/model/offline/offline_profile.dart'; import 'package:unit2/utils/app_router.dart'; import 'package:unit2/utils/global_context.dart'; import 'package:path_provider/path_provider.dart' as path_provider; @@ -12,9 +16,16 @@ import './utils/global.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); var appDirectory = await path_provider.getApplicationDocumentsDirectory(); + await Hive.initFlutter(appDirectory.path); + Hive.registerAdapter(OfflineProfileAdapter()); + Hive.registerAdapter(ModuleAdapter()); + Hive.registerAdapter(ModuleObjectAdapter()); + Hive.registerAdapter(OfflineModulesAdapter()); CREDENTIALS = await Hive.openBox('credentials'); SOS = await Hive.openBox('soscontacts'); + OFFLINE = await Hive.openBox('offline'); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) .then((_) { runApp(MyApp()); diff --git a/lib/model/login_data/user_info/module.dart b/lib/model/login_data/user_info/module.dart index a72f278..f3762a8 100644 --- a/lib/model/login_data/user_info/module.dart +++ b/lib/model/login_data/user_info/module.dart @@ -1,4 +1,8 @@ -class Module { +import 'package:hive/hive.dart'; +import 'package:unit2/model/login_data/user_info/module_object.dart'; +part 'module.g.dart'; +@HiveType(typeId: 1) +class Module extends HiveObject { Module({ this.id, this.icon, @@ -6,11 +10,15 @@ class Module { this.slug, this.objects, }); - + @HiveField(0) int? id; + @HiveField(1) String? icon; + @HiveField(2) String? name; + @HiveField(3) String? slug; + @HiveField(4) List? objects; factory Module.fromJson(Map json) => Module( @@ -35,34 +43,3 @@ class Module { }; } -class ModuleObject { - ModuleObject({ - this.id, - this.name, - this.slug, - this.operations, - }); - - int? id; - String? name; - String? slug; - List? operations; - - factory ModuleObject.fromJson(Map json) => ModuleObject( - id: json["id"], - name: json["name"], - slug: json["slug"], - operations: json["operations"] == null - ? [] - : List.from(json["operations"]!.map((x) => x)), - ); - - Map toJson() => { - "id": id, - "name": name, - "slug": slug, - "operations": operations == null - ? [] - : List.from(operations!.map((x) => x)), - }; -} \ No newline at end of file diff --git a/lib/model/login_data/user_info/module.g.dart b/lib/model/login_data/user_info/module.g.dart new file mode 100644 index 0000000..3a906b8 --- /dev/null +++ b/lib/model/login_data/user_info/module.g.dart @@ -0,0 +1,53 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'module.dart'; + +// ************************************************************************** +// TypeAdapterGenerator +// ************************************************************************** + +class ModuleAdapter extends TypeAdapter { + @override + final int typeId = 1; + + @override + Module read(BinaryReader reader) { + final numOfFields = reader.readByte(); + final fields = { + for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), + }; + return Module( + id: fields[0] as int?, + icon: fields[1] as String?, + name: fields[2] as String?, + slug: fields[3] as String?, + objects: (fields[4] as List?)?.cast(), + ); + } + + @override + void write(BinaryWriter writer, Module obj) { + writer + ..writeByte(5) + ..writeByte(0) + ..write(obj.id) + ..writeByte(1) + ..write(obj.icon) + ..writeByte(2) + ..write(obj.name) + ..writeByte(3) + ..write(obj.slug) + ..writeByte(4) + ..write(obj.objects); + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is ModuleAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} diff --git a/lib/model/login_data/user_info/module_object.dart b/lib/model/login_data/user_info/module_object.dart new file mode 100644 index 0000000..4d36c15 --- /dev/null +++ b/lib/model/login_data/user_info/module_object.dart @@ -0,0 +1,37 @@ +import 'package:hive/hive.dart'; +part 'module_object.g.dart'; +@HiveType(typeId: 2) +class ModuleObject extends HiveObject { + ModuleObject({ + this.id, + this.name, + this.slug, + this.operations, + }); + @HiveField(0) + int? id; + @HiveField(1) + String? name; + @HiveField(2) + String? slug; + @HiveField(3) + List? operations; + + factory ModuleObject.fromJson(Map json) => ModuleObject( + id: json["id"], + name: json["name"], + slug: json["slug"], + operations: json["operations"] == null + ? [] + : List.from(json["operations"]!.map((x) => x)), + ); + + Map toJson() => { + "id": id, + "name": name, + "slug": slug, + "operations": operations == null + ? [] + : List.from(operations!.map((x) => x)), + }; +} diff --git a/lib/model/login_data/user_info/module_object.g.dart b/lib/model/login_data/user_info/module_object.g.dart new file mode 100644 index 0000000..c20151b --- /dev/null +++ b/lib/model/login_data/user_info/module_object.g.dart @@ -0,0 +1,50 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'module_object.dart'; + +// ************************************************************************** +// TypeAdapterGenerator +// ************************************************************************** + +class ModuleObjectAdapter extends TypeAdapter { + @override + final int typeId = 2; + + @override + ModuleObject read(BinaryReader reader) { + final numOfFields = reader.readByte(); + final fields = { + for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), + }; + return ModuleObject( + id: fields[0] as int?, + name: fields[1] as String?, + slug: fields[2] as String?, + operations: (fields[3] as List?)?.cast(), + ); + } + + @override + void write(BinaryWriter writer, ModuleObject obj) { + writer + ..writeByte(4) + ..writeByte(0) + ..write(obj.id) + ..writeByte(1) + ..write(obj.name) + ..writeByte(2) + ..write(obj.slug) + ..writeByte(3) + ..write(obj.operations); + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is ModuleObjectAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} diff --git a/lib/model/offline/offlane_modules.dart b/lib/model/offline/offlane_modules.dart new file mode 100644 index 0000000..fd25a6d --- /dev/null +++ b/lib/model/offline/offlane_modules.dart @@ -0,0 +1,18 @@ +import 'package:hive/hive.dart'; +import 'package:unit2/model/login_data/user_info/module.dart'; + +import '../login_data/user_info/module_object.dart'; +part 'offlane_modules.g.dart'; +@HiveType(typeId: 4) +class OfflineModules { + @HiveField(0) + final String roleName; + @HiveField(1) + final String moduleName; + @HiveField(2) + final ModuleObject object; + @HiveField(3) + final int roleId; + const OfflineModules( + {required this.moduleName, required this.object, required this.roleName,required this.roleId}); +} \ No newline at end of file diff --git a/lib/model/offline/offlane_modules.g.dart b/lib/model/offline/offlane_modules.g.dart new file mode 100644 index 0000000..55434b0 --- /dev/null +++ b/lib/model/offline/offlane_modules.g.dart @@ -0,0 +1,50 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'offlane_modules.dart'; + +// ************************************************************************** +// TypeAdapterGenerator +// ************************************************************************** + +class OfflineModulesAdapter extends TypeAdapter { + @override + final int typeId = 4; + + @override + OfflineModules read(BinaryReader reader) { + final numOfFields = reader.readByte(); + final fields = { + for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), + }; + return OfflineModules( + moduleName: fields[1] as String, + object: fields[2] as ModuleObject, + roleName: fields[0] as String, + roleId: fields[3] as int, + ); + } + + @override + void write(BinaryWriter writer, OfflineModules obj) { + writer + ..writeByte(4) + ..writeByte(0) + ..write(obj.roleName) + ..writeByte(1) + ..write(obj.moduleName) + ..writeByte(2) + ..write(obj.object) + ..writeByte(3) + ..write(obj.roleId); + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is OfflineModulesAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} diff --git a/lib/model/offline/offline_profile.dart b/lib/model/offline/offline_profile.dart new file mode 100644 index 0000000..1dd0575 --- /dev/null +++ b/lib/model/offline/offline_profile.dart @@ -0,0 +1,145 @@ +import 'package:hive/hive.dart'; + +import 'dart:convert'; + +import 'package:unit2/model/profile/family_backround.dart'; +part 'offline_profile.g.dart'; +OfflineProfile primaryInformationFromJson(String str) => OfflineProfile.fromJson(json.decode(str)); + +String primaryInformationToJson(OfflineProfile data) => json.encode(data.toJson()); +@HiveType(typeId: 0) +class OfflineProfile extends HiveObject { + @HiveField(0) + int? webuserId; + @HiveField(1) + int? id; + @HiveField(2) + String? lastName; + @HiveField(3) + String? firstName; + @HiveField(4) + String? middleName; + @HiveField(5) + String? nameExtension; + @HiveField(6) + String? sex; + @HiveField(7) + DateTime? birthdate; + @HiveField(8) + String? civilStatus; + @HiveField(9) + String? bloodType; + @HiveField(10) + double? heightM; + @HiveField(11) + double? weightKg; + @HiveField(12) + String? photoPath; + @HiveField(13) + String? esigPath; + @HiveField(14) + MaidenName? maidenName; + @HiveField(15) + bool? deceased; + @HiveField(16) + String? uuidQrcode; + @HiveField(17) + String? titlePrefix; + @HiveField(18) + String? titleSuffix; + @HiveField(19) + bool? showTitleId; + @HiveField(20) + String? ethnicity; + @HiveField(21) + String? disability; + @HiveField(22) + String? gender; + @HiveField(23) + String? religion; + @HiveField(24) + String? ip; + + OfflineProfile({ + required this.webuserId, + required this.id, + required this.lastName, + required this.firstName, + required this.middleName, + required this.nameExtension, + required this.sex, + required this.birthdate, + required this.civilStatus, + required this.bloodType, + required this.heightM, + required this.weightKg, + required this.photoPath, + required this.esigPath, + required this.maidenName, + required this.deceased, + required this.uuidQrcode, + required this.titlePrefix, + required this.titleSuffix, + required this.showTitleId, + required this.ethnicity, + required this.disability, + required this.gender, + required this.religion, + required this.ip, + }); + + factory OfflineProfile.fromJson(Map json) => OfflineProfile( + webuserId: null, + id: json["id"], + lastName: json["last_name"], + firstName: json["first_name"], + middleName: json["middle_name"], + nameExtension: json["name_extension"], + sex: json["sex"], + birthdate:json['birthdate'] ==null?null: DateTime.parse(json["birthdate"]), + civilStatus: json["civil_status"], + bloodType: json["blood_type"], + heightM: json["height_m"]?.toDouble(), + weightKg: json["weight_kg"]?.toDouble(), + photoPath: json["photo_path"], + esigPath: json["esig_path"], + maidenName: json["maiden_name"]==null?null:MaidenName.fromJson(json["maiden_name"]), + deceased: json["deceased"], + uuidQrcode: json["uuid_qrcode"], + titlePrefix: json["title_prefix"], + titleSuffix: json["title_suffix"], + showTitleId: json["show_title_id"], + ethnicity: json["ethnicity"]== null?null:json["ethnicity"]['name'], + disability: json["disability"] == null?null:json['disability']['name'], + gender: json["gender"] == null?null:json['gender']['name'], + religion: json["religion"] == null?null:json['religion']['name'], + ip: json["ip"]==null?null:json['ip']['name'], + ); + + Map toJson() => { + "id": id, + "last_name": lastName, + "first_name": firstName, + "middle_name": middleName, + "name_extension": nameExtension, + "sex": sex, + "birthdate": "${birthdate?.year.toString().padLeft(4, '0')}-${birthdate?.month.toString().padLeft(2, '0')}-${birthdate?.day.toString().padLeft(2, '0')}", + "civil_status": civilStatus, + "blood_type": bloodType, + "height_m": heightM, + "weight_kg": weightKg, + "photo_path": photoPath, + "esig_path": esigPath, + "maiden_name": maidenName, + "deceased": deceased, + "uuid_qrcode": uuidQrcode, + "title_prefix": titlePrefix, + "title_suffix": titleSuffix, + "show_title_id": showTitleId, + "ethnicity": ethnicity, + "disability": disability, + "gender": gender, + "religion": religion, + "ip": ip, + }; +} diff --git a/lib/model/offline/offline_profile.g.dart b/lib/model/offline/offline_profile.g.dart new file mode 100644 index 0000000..57c2d7a --- /dev/null +++ b/lib/model/offline/offline_profile.g.dart @@ -0,0 +1,113 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'offline_profile.dart'; + +// ************************************************************************** +// TypeAdapterGenerator +// ************************************************************************** + +class OfflineProfileAdapter extends TypeAdapter { + @override + final int typeId = 0; + + @override + OfflineProfile read(BinaryReader reader) { + final numOfFields = reader.readByte(); + final fields = { + for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), + }; + return OfflineProfile( + webuserId: fields[0] as int?, + id: fields[1] as int?, + lastName: fields[2] as String?, + firstName: fields[3] as String?, + middleName: fields[4] as String?, + nameExtension: fields[5] as String?, + sex: fields[6] as String?, + birthdate: fields[7] as DateTime?, + civilStatus: fields[8] as String?, + bloodType: fields[9] as String?, + heightM: fields[10] as double?, + weightKg: fields[11] as double?, + photoPath: fields[12] as String?, + esigPath: fields[13] as String?, + maidenName: fields[14] as MaidenName?, + deceased: fields[15] as bool?, + uuidQrcode: fields[16] as String?, + titlePrefix: fields[17] as String?, + titleSuffix: fields[18] as String?, + showTitleId: fields[19] as bool?, + ethnicity: fields[20] as String?, + disability: fields[21] as String?, + gender: fields[22] as String?, + religion: fields[23] as String?, + ip: fields[24] as String?, + ); + } + + @override + void write(BinaryWriter writer, OfflineProfile obj) { + writer + ..writeByte(25) + ..writeByte(0) + ..write(obj.webuserId) + ..writeByte(1) + ..write(obj.id) + ..writeByte(2) + ..write(obj.lastName) + ..writeByte(3) + ..write(obj.firstName) + ..writeByte(4) + ..write(obj.middleName) + ..writeByte(5) + ..write(obj.nameExtension) + ..writeByte(6) + ..write(obj.sex) + ..writeByte(7) + ..write(obj.birthdate) + ..writeByte(8) + ..write(obj.civilStatus) + ..writeByte(9) + ..write(obj.bloodType) + ..writeByte(10) + ..write(obj.heightM) + ..writeByte(11) + ..write(obj.weightKg) + ..writeByte(12) + ..write(obj.photoPath) + ..writeByte(13) + ..write(obj.esigPath) + ..writeByte(14) + ..write(obj.maidenName) + ..writeByte(15) + ..write(obj.deceased) + ..writeByte(16) + ..write(obj.uuidQrcode) + ..writeByte(17) + ..write(obj.titlePrefix) + ..writeByte(18) + ..write(obj.titleSuffix) + ..writeByte(19) + ..write(obj.showTitleId) + ..writeByte(20) + ..write(obj.ethnicity) + ..writeByte(21) + ..write(obj.disability) + ..writeByte(22) + ..write(obj.gender) + ..writeByte(23) + ..write(obj.religion) + ..writeByte(24) + ..write(obj.ip); + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is OfflineProfileAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} diff --git a/lib/screens/offline/homepage/drawer.dart b/lib/screens/offline/homepage/drawer.dart new file mode 100644 index 0000000..d0bc2c4 --- /dev/null +++ b/lib/screens/offline/homepage/drawer.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; +import 'package:unit2/model/offline/offlane_modules.dart'; +import 'package:unit2/screens/offline/homepage/menu_screen.dart'; +import 'package:unit2/screens/offline/homepage/module_screen.dart'; +import 'package:unit2/utils/global.dart'; +import '../../../../bloc/user/user_bloc.dart'; +import '../../../../widgets/splash_screen.dart'; + +class OfflineDrawerScreen extends StatefulWidget { + final List modules; + const OfflineDrawerScreen({Key? key ,required this.modules}) : super(key: key,); + @override + State createState() => _OfflineDrawerScreenState(); +} + +class _OfflineDrawerScreenState extends State { + + + final zoomDrawerController = ZoomDrawerController(); + @override + + @override + Widget build(BuildContext context) { + return ZoomDrawer( + controller: zoomDrawerController, + menuScreen: const OfflineMenuScreen(), + mainScreen: SizedBox( + height: MediaQuery.of(context).size.height, + child: OfflineModuleScreen(modules: widget.modules,)), + style: DrawerStyle.defaultStyle, + borderRadius: 24.0, + showShadow: false, + angle: -0.0, + slideWidth: MediaQuery.of(context).size.width * .90, + openCurve: Curves.fastOutSlowIn, + closeCurve: Curves.easeOut, + menuBackgroundColor: Colors.grey, + ); + } + +} diff --git a/lib/screens/offline/homepage/menu_screen.dart b/lib/screens/offline/homepage/menu_screen.dart new file mode 100644 index 0000000..9cd4b5a --- /dev/null +++ b/lib/screens/offline/homepage/menu_screen.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import '../../../../utils/global.dart'; + +class OfflineMenuScreen extends StatefulWidget { + const OfflineMenuScreen({super.key}); + + @override + State createState() => _OfflineMenuScreenState(); +} + +class _OfflineMenuScreenState extends State { + @override + Widget build(BuildContext context) { + return Drawer( + child: SizedBox( + height: screenHeight, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Column( + children: [ + UserAccountsDrawerHeader( + currentAccountPictureSize: const Size.square(90), + decoration: const BoxDecoration( + color: primary, + image: DecorationImage( + image: AssetImage('assets/pngs/bg.png'), + fit: BoxFit.cover)), + accountName: null, + accountEmail: null, + currentAccountPicture: CircleAvatar( + radius: 100, + backgroundColor: fifth, + child: CircleAvatar( + radius: 100, + backgroundColor: third, + child: Image.asset( + 'assets/pngs/capitol.png', + )), + ), + ), + ListTile( + dense: true, + leading: const Icon( + Icons.exit_to_app, + color: primary, + ), + title: const Text( + "Exit Offline Mode", + style: TextStyle(color: Colors.black), + ), + onTap: () async { + Navigator.pushReplacementNamed(context, '/'); + }, + ) + ], + ), + const Expanded(child: SizedBox()), + const Divider(), + const SizedBox( + height: 10, + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/offline/homepage/module_screen.dart b/lib/screens/offline/homepage/module_screen.dart new file mode 100644 index 0000000..b3a8996 --- /dev/null +++ b/lib/screens/offline/homepage/module_screen.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:unit2/model/offline/offlane_modules.dart'; +import 'package:unit2/screens/passo/passo_dashboard.dart'; +import 'package:unit2/screens/unit2/homepage.dart/components/dashboard/shared_card_label.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; + +class OfflineModuleScreen extends StatelessWidget { + final List modules; + const OfflineModuleScreen({super.key, required this.modules}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: primary, + title: const Text("Offline Mode"), + centerTitle: true, + leading: IconButton( + onPressed: () { + ZoomDrawer.of(context)!.toggle(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + ), + ), + ), + body: Padding( + padding: const EdgeInsets.all(24), + child: GridView.count( + shrinkWrap: true, + crossAxisCount: 4, + crossAxisSpacing: 8, + mainAxisSpacing: 10, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), + children: modules + .map((e) => CardLabel( + icon: FontAwesome5.eye, + title: "Field Surveyor", + ontap: () { + Navigator.push(context, MaterialPageRoute(builder: ((context) { + return PassoDashBoard(); + }))); + })) + .toList()), + )); + } +} diff --git a/lib/screens/unit2/basic-info/basic-info.dart b/lib/screens/unit2/basic-info/basic-info.dart index a75f9a2..af2c154 100644 --- a/lib/screens/unit2/basic-info/basic-info.dart +++ b/lib/screens/unit2/basic-info/basic-info.dart @@ -8,6 +8,7 @@ import 'package:intl/intl.dart'; import 'package:qr_flutter/qr_flutter.dart'; import 'package:unit2/model/login_data/user_info/user_data.dart'; import 'package:unit2/screens/unit2/basic-info/components/qr_image.dart'; + import 'package:unit2/theme-data.dart/btn-style.dart'; import 'package:unit2/utils/global.dart'; import 'package:unit2/utils/text_container.dart'; @@ -181,7 +182,7 @@ class BuildInformation extends StatelessWidget { return QRFullScreenImage(uuid: uuid); })); }, - child: QrImage( + child: QrImageView( data: uuid!, size: blockSizeVertical * 24, ), diff --git a/lib/screens/unit2/basic-info/components/qr_image.dart b/lib/screens/unit2/basic-info/components/qr_image.dart index 6cd2d39..b423bdd 100644 --- a/lib/screens/unit2/basic-info/components/qr_image.dart +++ b/lib/screens/unit2/basic-info/components/qr_image.dart @@ -1,6 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/src/widgets/framework.dart'; -import 'package:flutter/src/widgets/placeholder.dart'; import 'package:qr_flutter/qr_flutter.dart'; import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/utils/global.dart'; @@ -16,7 +14,7 @@ class QRFullScreenImage extends StatelessWidget { centerTitle: true, backgroundColor: primary,title: const Text("Profile QR Code"),), body: Center( - child: QrImage( + child: QrImageView( data: uuid, size: blockSizeVertical * 50 ), diff --git a/lib/screens/unit2/homepage.dart/components/drawer-screen.dart b/lib/screens/unit2/homepage.dart/components/drawer-screen.dart index 4f0d609..f621a67 100644 --- a/lib/screens/unit2/homepage.dart/components/drawer-screen.dart +++ b/lib/screens/unit2/homepage.dart/components/drawer-screen.dart @@ -14,7 +14,10 @@ class DrawerScreen extends StatefulWidget { } class _DrawerScreenState extends State { + + final zoomDrawerController = ZoomDrawerController(); + @override Widget build(BuildContext context) { return BlocBuilder( @@ -38,7 +41,7 @@ class _DrawerScreenState extends State { menuBackgroundColor: Colors.grey, ); } - return const UniTSplashScreen(); + return Container(); }, ); } diff --git a/lib/screens/unit2/homepage.dart/components/menu-screen.dart b/lib/screens/unit2/homepage.dart/components/menu-screen.dart index b5a0888..48c5614 100644 --- a/lib/screens/unit2/homepage.dart/components/menu-screen.dart +++ b/lib/screens/unit2/homepage.dart/components/menu-screen.dart @@ -1,7 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:unit2/model/offline/offlane_modules.dart'; +import 'package:unit2/screens/offline/homepage/drawer.dart'; +import 'package:unit2/screens/offline/homepage/menu_screen.dart'; +import 'package:unit2/screens/unit2/homepage.dart/components/drawer-screen.dart'; import 'package:unit2/theme-data.dart/colors.dart'; import 'package:fluttericon/web_symbols_icons.dart'; import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:unit2/utils/global_context.dart'; import '../../../../model/login_data/user_info/user_data.dart'; import 'menu.dart'; import '../../../../utils/global.dart'; @@ -17,10 +22,6 @@ class MenuScreen extends StatefulWidget { class _MenuScreenState extends State { @override Widget build(BuildContext context) { - final String firstName =globalFistname?? - widget.userData!.employeeInfo!.profile!.firstName!.toUpperCase(); - final String lastname = globalLastname?? - widget.userData!.employeeInfo!.profile!.lastName!.toUpperCase(); return Drawer( child: SizedBox( height: screenHeight, @@ -28,49 +29,69 @@ class _MenuScreenState extends State { mainAxisSize: MainAxisSize.max, children: [ Column( - // ignore: prefer_const_literals_to_create_immutables children: [ UserAccountsDrawerHeader( + currentAccountPictureSize: const Size.square(90), decoration: const BoxDecoration( color: primary, image: DecorationImage( image: AssetImage('assets/pngs/bg.png'), fit: BoxFit.cover)), - accountName: Text("$firstName $lastname"), + accountName: null, accountEmail: null, currentAccountPicture: CircleAvatar( - radius: 40, + radius: 100, backgroundColor: fifth, child: CircleAvatar( - radius: 33, - backgroundColor: third, - child: //Icon(Icons.person, size: 40, color: fifth), - Text( - firstName[0].toUpperCase(), - style: const TextStyle(fontSize: 45.0, color: fifth), - ), - ), + radius: 100, + backgroundColor: third, + child: Image.asset( + 'assets/pngs/capitol.png', + )), ), ), getTile(FontAwesome5.user, "Basic Info", '/basic-info', context, widget.userData!), const Divider(), - getTile(FontAwesome5.user_circle, "Profile", - '/profile', context, widget.userData!), - const Divider(), - getTile(FontAwesome5.life_ring, "Request SOS", '/sos', + getTile(FontAwesome5.user_circle, "Profile", '/profile', context, widget.userData!), - + const Divider(), + getTile(FontAwesome5.life_ring, "Request SOS", '/sos', context, + widget.userData!), + const Divider(), + SizedBox( + child: globalOfflineAvailable == true + ? ListTile( + dense: true, + leading: const Icon( + Icons.exit_to_app, + color: primary, + ), + title: const Text( + "Offline Mode", + style: TextStyle(color: Colors.black), + ), + onTap: () async { + List modules = await OFFLINE!.get('modules'); + Navigator.pushReplacement(NavigationService.navigatorKey.currentState!.context, + MaterialPageRoute(builder: ((context) { + return OfflineDrawerScreen(modules: modules,); + }))); + }, + ) + : Container()) ], ), - const Expanded(child: SizedBox()), - const Divider(), - Align( - alignment: FractionalOffset.bottomLeft, - child: getTile(WebSymbols.logout, "Logout", '/', context, - widget.userData!), - ), - const SizedBox(height: 10,), + const Expanded(child: SizedBox()), + const Divider(), + Align( + alignment: FractionalOffset.bottomLeft, + child: getTile( + WebSymbols.logout, "Logout", '/', context, widget.userData!), + ), + const SizedBox( + height: 10, + ), ], ), ), diff --git a/lib/screens/unit2/homepage.dart/module-screen.dart b/lib/screens/unit2/homepage.dart/module-screen.dart index f614ff0..a0e95c2 100644 --- a/lib/screens/unit2/homepage.dart/module-screen.dart +++ b/lib/screens/unit2/homepage.dart/module-screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; +import 'package:unit2/model/login_data/user_info/module_object.dart'; import 'package:unit2/screens/unit2/homepage.dart/components/dashboard/dashboard.dart'; import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/utils/text_container.dart'; diff --git a/lib/screens/unit2/login/login.dart b/lib/screens/unit2/login/login.dart index 06d94e8..427b7b8 100644 --- a/lib/screens/unit2/login/login.dart +++ b/lib/screens/unit2/login/login.dart @@ -7,6 +7,8 @@ import 'package:fluttericon/font_awesome5_icons.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:unit2/model/offline/offlane_modules.dart'; +import 'package:unit2/screens/offline/homepage/drawer.dart'; import 'package:unit2/screens/unit2/login/components/update_required.dart'; import 'package:unit2/screens/unit2/login/qr_login.dart'; import 'package:unit2/utils/alerts.dart'; @@ -36,22 +38,25 @@ class _UniT2LoginState extends State { bool _showPassword = true; String? password; String? username; - DateTime? ctime; + DateTime? ctime; @override Widget build(BuildContext context) { return WillPopScope( - onWillPop: () { - DateTime now = DateTime.now(); - if (ctime == null || now.difference(ctime!) > const Duration(seconds: 2)) { - ctime = now; - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Press Again to Exit',textAlign: TextAlign.center,)) - ); - return Future.value(false); - } + onWillPop: () { + DateTime now = DateTime.now(); + if (ctime == null || + now.difference(ctime!) > const Duration(seconds: 2)) { + ctime = now; + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text( + 'Press Again to Exit', + textAlign: TextAlign.center, + ))); + return Future.value(false); + } - return Future.value(true); - }, + return Future.value(true); + }, child: Scaffold( body: ProgressHUD( backgroundColor: Colors.black87, @@ -355,7 +360,7 @@ class _UniT2LoginState extends State { //New update available return Update( apkVersion: state.apkVersion!, - versionInfo: state.versionInfo!, + versionInfo: state.versionInfo!, ); } }); @@ -366,13 +371,54 @@ class _UniT2LoginState extends State { onpressed: () { BlocProvider.of( NavigationService.navigatorKey.currentContext!) - .add(LoadVersion(username: username, password: password)); + .add(LoadVersion(username: username, password: password)); return MaterialPageRoute(builder: (_) { return const UniT2Login(); }); }, ); } + if (state is ErrorWithOfflineMode) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SomethingWentWrong( + message: onError, + onpressed: () { + BlocProvider.of( + NavigationService.navigatorKey.currentContext!) + .add(LoadVersion( + username: username, password: password)); + return MaterialPageRoute(builder: (_) { + return const UniT2Login(); + }); + }, + ), + const SizedBox( + height: 14, + ), + SizedBox( + width: 200, + height: 50, + child: ElevatedButton.icon( + icon: const Icon(Icons.signal_cellular_alt), + style: mainBtnStyle(second, Colors.transparent, primary), + onPressed: () async { + List offlinemodules = await OFFLINE!.get('modules'); + Navigator.pushReplacement( + NavigationService + .navigatorKey.currentState!.context, + MaterialPageRoute(builder: ((context) { + return OfflineDrawerScreen( + modules: offlinemodules, + ); + }))); + }, + label: const Text("Offline Mode")), + ) + ], + ); + } if (state is InternetTimeout) { return const TimeOutError(); } @@ -385,14 +431,14 @@ class _UniT2LoginState extends State { onpressed: () { BlocProvider.of( NavigationService.navigatorKey.currentContext!) - .add(LoadVersion(username: username, password: password)); + .add(LoadVersion(username: username, password: password)); return MaterialPageRoute(builder: (_) { return const UniT2Login(); }); }, ); } - return Container(); + return Container(); }), ), ), diff --git a/lib/utils/app_router.dart b/lib/utils/app_router.dart index 163aaf2..089cb6e 100644 --- a/lib/utils/app_router.dart +++ b/lib/utils/app_router.dart @@ -92,6 +92,7 @@ class AppRouter { child: const RBACScreen(), ); }); + default: return MaterialPageRoute(builder: (context) { return Container(); diff --git a/lib/utils/global.dart b/lib/utils/global.dart index 49b3b28..91ebce2 100644 --- a/lib/utils/global.dart +++ b/lib/utils/global.dart @@ -1,4 +1,5 @@ import 'package:hive/hive.dart'; +import 'package:unit2/model/offline/offline_profile.dart'; import '../model/profile/basic_information/primary-information.dart'; @@ -12,25 +13,16 @@ double safeBlockHorizontal = 0; double safeBlockVertical = 0; const xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; const xClientSecret = "unitcYqAN7GGalyz"; - String? globalFistname; - String? globalLastname; - String? globalMiddleName; - DateTime? globalBday; - String? globalSex; +String? globalFistname; +String? globalLastname; +String? globalMiddleName; +DateTime? globalBday; +String? globalSex; Profile? globalCurrentProfile; - - -const String urlDownloadArmeabiv7aAPK = - "https://agusandelnorte.gov.ph/media/public/transparency/downloadables/UniT-App/v1.0.1/beta/unit_app_v1_0_1_beta_armeabi-v7a-release.apk?download"; - -const String urlDownloadX8664APK = -"https://agusandelnorte.gov.ph/media/public/transparency/downloadables/UniT-App/v1.0.1/beta/unit_app_v1_0_1_beta_x86_64-release.apk?download"; - -const String urlDownloadarm64v8aAPK = - "https://agusandelnorte.gov.ph/media/public/transparency/downloadables/UniT-App/v1.0.1/beta/unit_app_v1_0_1_beta_arm64-v8a-release.apk?download"; - - - +///offline data +bool? globalOfflineAvailable; +OfflineProfile? globalOfflineProfile; //// hive boxes Box? CREDENTIALS; -Box? SOS; \ No newline at end of file +Box? SOS; +Box? OFFLINE; diff --git a/lib/widgets/error_state.dart b/lib/widgets/error_state.dart index b23027f..672182c 100644 --- a/lib/widgets/error_state.dart +++ b/lib/widgets/error_state.dart @@ -36,6 +36,7 @@ class SomethingWentWrong extends StatelessWidget { height: 20, ), SizedBox( + width: 200, height: 50, child: ElevatedButton.icon( style: mainBtnStyle( diff --git a/pubspec.lock b/pubspec.lock index dc81921..e4f77a9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" + sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 url: "https://pub.dev" source: hosted - version: "47.0.0" + version: "64.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" + sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "6.2.0" animate_do: dependency: "direct main" description: @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: archive - sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + sha256: "06a96f1249f38a00435b3b0c9a3246d934d7dbc8183fc7c9e56989860edb99d4" url: "https://pub.dev" source: hosted - version: "3.3.7" + version: "3.4.4" args: dependency: transitive description: @@ -77,58 +77,58 @@ packages: dependency: "direct main" description: name: audioplayers - sha256: "8e94499b5c123df14cf17c16639de5ff3373e57e537f727e367487fbb7491363" + sha256: d9f6ca8e9b3e5af5e73d4c814404566f72698ee7ba35487bdf2baa6749e7503f url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.2.0" audioplayers_android: dependency: transitive description: name: audioplayers_android - sha256: "1c12b60cc10a3b8617ca3f88b927e7e03768f470d9b4f747efd3d58a8a07ee1b" + sha256: fb01b9481f431fe04ac60f1f97ce8158383f2dc754558820592f795d81ca9d53 url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.2" audioplayers_darwin: dependency: transitive description: name: audioplayers_darwin - sha256: "2fb6133ffcf28fb3f9d3e11f8a3ef190e5fedb2b7b95ea865b56a21d1163e670" + sha256: "3034e99a6df8d101da0f5082dcca0a2a99db62ab1d4ddb3277bed3f6f81afe08" url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "5.0.2" audioplayers_linux: dependency: transitive description: name: audioplayers_linux - sha256: cca3f272c7186dd2e0025b8864e1413ac5e081d74b17e28b02ceb2df4c110235 + sha256: "60787e73fefc4d2e0b9c02c69885402177e818e4e27ef087074cf27c02246c9e" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.1.0" audioplayers_platform_interface: dependency: transitive description: name: audioplayers_platform_interface - sha256: "47eae55e99ced11589998cf27e4eaabf5b475a7bd8bea7516ee6c2536a2e1abf" + sha256: "365c547f1bb9e77d94dd1687903a668d8f7ac3409e48e6e6a3668a1ac2982adb" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "6.1.0" audioplayers_web: dependency: transitive description: name: audioplayers_web - sha256: "9f155590c6ba9ba469df637f4729264e4234dc3941ece4690dad63ffac19b5af" + sha256: "22cd0173e54d92bd9b2c80b1204eb1eb159ece87475ab58c9788a70ec43c2a62" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.1.0" audioplayers_windows: dependency: transitive description: name: audioplayers_windows - sha256: "8813b712ba919bb324bde5e3ba97edc81bface945953a54a3dea70b5608bcc70" + sha256: "9536812c9103563644ada2ef45ae523806b0745f7a78e89d1b5fb1951de90e1a" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.1.0" auto_size_text: dependency: "direct main" description: @@ -197,10 +197,10 @@ packages: dependency: transitive description: name: build - sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" build_config: dependency: transitive description: @@ -213,34 +213,34 @@ packages: dependency: transitive description: name: build_daemon - sha256: "757153e5d9cd88253cb13f28c2fb55a537dc31fefd98137549895b5beb7c6169" + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "4.0.0" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" + sha256: "64e12b0521812d1684b1917bc80945625391cb9bdd4312536b1d69dcb6133ed8" url: "https://pub.dev" source: hosted - version: "2.0.10" + version: "2.4.1" build_runner: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.6" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "0671ad4162ed510b70d0eb4ad6354c249f8429cab4ae7a4cec86bbc2886eb76e" + sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 url: "https://pub.dev" source: hosted - version: "7.2.7+1" + version: "7.2.11" built_collection: dependency: transitive description: @@ -253,34 +253,34 @@ packages: dependency: transitive description: name: built_value - sha256: ff627b645b28fb8bdb69e645f910c2458fd6b65f6585c3a53e0626024897dedf + sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74 url: "https://pub.dev" source: hosted - version: "8.6.2" + version: "8.6.3" cached_network_image: dependency: "direct main" description: name: cached_network_image - sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 + sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f url: "https://pub.dev" source: hosted - version: "3.2.3" + version: "3.3.0" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 + sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "3.0.0" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 + sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" characters: dependency: transitive description: @@ -309,10 +309,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "315a598c7fbe77f22de1c9da7cfd6fd21816312f16ffa124453b4fc679e540f1" + sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677" url: "https://pub.dev" source: hosted - version: "4.6.0" + version: "4.7.0" collection: dependency: transitive description: @@ -365,10 +365,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + sha256: abd7625e16f51f554ea244d090292945ec4d4be7bfbaf2ec8cccea568919d334 url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.3.3" date_time_picker: dependency: "direct main" description: @@ -461,10 +461,10 @@ packages: dependency: transitive description: name: ffi - sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.0" file: dependency: transitive description: @@ -526,14 +526,6 @@ packages: url: "https://pub.dev" source: hosted version: "8.1.3" - flutter_blurhash: - dependency: transitive - description: - name: flutter_blurhash - sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6" - url: "https://pub.dev" - source: hosted - version: "0.7.0" flutter_cache_manager: dependency: transitive description: @@ -777,10 +769,10 @@ packages: dependency: transitive description: name: image - sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf + sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271" url: "https://pub.dev" source: hosted - version: "4.0.17" + version: "4.1.3" intl: dependency: "direct main" description: @@ -801,10 +793,10 @@ packages: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: dependency: transitive description: @@ -817,10 +809,10 @@ packages: dependency: transitive description: name: lints - sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.1" location: dependency: "direct main" description: @@ -953,10 +945,10 @@ packages: dependency: transitive description: name: octo_image - sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" + sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "2.0.0" package_config: dependency: transitive description: @@ -1057,10 +1049,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: f2543a236584a5e8be79076f858022f100ce690e31530e6fa4c32ac94f276d3a + sha256: ace7d15a3d1a4a0b91c041d01e5405df221edb9de9116525efc773c74e6fc790 url: "https://pub.dev" source: hosted - version: "11.0.3" + version: "11.0.5" permission_handler_apple: dependency: transitive description: @@ -1209,18 +1201,18 @@ packages: dependency: transitive description: name: qr - sha256: "5c4208b4dc0d55c3184d10d83ee0ded6212dc2b5e2ba17c5a0c0aab279128d21" + sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "3.0.1" qr_flutter: dependency: "direct main" description: name: qr_flutter - sha256: c5c121c54cb6dd837b9b9d57eb7bc7ec6df4aee741032060c8833a678c80b87e + sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.1.0" rive: dependency: transitive description: @@ -1390,18 +1382,18 @@ packages: dependency: transitive description: name: source_gen - sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" + sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 url: "https://pub.dev" source: hosted - version: "1.2.6" + version: "1.4.0" source_helper: dependency: transitive description: name: source_helper - sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" url: "https://pub.dev" source: hosted - version: "1.3.3" + version: "1.3.4" source_span: dependency: transitive description: @@ -1414,18 +1406,18 @@ packages: dependency: transitive description: name: sqflite - sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 + sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" url: "https://pub.dev" source: hosted - version: "2.2.8+4" + version: "2.3.0" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "8f7603f3f8f126740bc55c4ca2d1027aab4b74a1267a3e31ce51fe40e3b65b8f" + sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a" url: "https://pub.dev" source: hosted - version: "2.4.5+1" + version: "2.5.0" stack_trace: dependency: transitive description: @@ -1470,66 +1462,66 @@ packages: dependency: transitive description: name: syncfusion_flutter_core - sha256: aea119c8117953fa5decf4a313b431e556b0959cd35ff88f8fbdc0eda9bedb06 + sha256: "295954bc4bda923c88f361da35611801b56f4258179aa355730b236e4ae3ec60" url: "https://pub.dev" source: hosted - version: "23.1.36" + version: "23.1.38" syncfusion_flutter_pdf: dependency: transitive description: name: syncfusion_flutter_pdf - sha256: "76a50a1d580714c078e2827adbd8b00d5f5c606879d07c44c5d99f0e864edda1" + sha256: "567d42bd3421f1d3691c5c40741cc921e12b5fc4cc665be170716cca1c1ab824" url: "https://pub.dev" source: hosted - version: "23.1.36" + version: "23.1.38" syncfusion_flutter_pdfviewer: dependency: "direct main" description: name: syncfusion_flutter_pdfviewer - sha256: e5eaabd0a31fff16caead0d6d66d4c9946de7e46c89da7736de23cd4b2e6f676 + sha256: f3ae48a1b9d0c2a153be292751f84d3ff4f09a33ab38bc7d934340cb656c4e0c url: "https://pub.dev" source: hosted - version: "23.1.36" + version: "23.1.38" syncfusion_flutter_signaturepad: dependency: transitive description: name: syncfusion_flutter_signaturepad - sha256: ea6b218d127e0315b3309ee072a1d304c76aa7c497a196b3474f9c6b38c01f82 + sha256: f61d7fb1c8776f8acfb6dba48c9dd770e41a41759011729770a20671ee1e79ee url: "https://pub.dev" source: hosted - version: "23.1.36" + version: "23.1.38" syncfusion_pdfviewer_macos: dependency: transitive description: name: syncfusion_pdfviewer_macos - sha256: "6f928bee1f786b8d1939d3c4142c5cc2de2c13d19262d302878935a2bc33850c" + sha256: "083f31cea51c8ca1fe98ee8381e48117a892936ad480b5a1787ef9af4a14eac9" url: "https://pub.dev" source: hosted - version: "23.1.36" + version: "23.1.38" syncfusion_pdfviewer_platform_interface: dependency: transitive description: name: syncfusion_pdfviewer_platform_interface - sha256: "0251864fb82e2bd92a1b17e8562fe342e78cd530e26b0d2f54e94a441ccb4584" + sha256: acd26577d5b14b230521fc362e9acd0c1a9c8b1a60de89294689772819be5d9d url: "https://pub.dev" source: hosted - version: "23.1.36" + version: "23.1.38" syncfusion_pdfviewer_web: dependency: transitive description: name: syncfusion_pdfviewer_web - sha256: eb224f52e86326dbf08ea12978c3db0b4e376866a84d4fcb131fc06ec93cbe20 + sha256: "255ead74a256d7fdcee8b7eb48530beaa6373ef65cdb5db592b59e187fb505f2" url: "https://pub.dev" source: hosted - version: "23.1.36" + version: "23.1.38" syncfusion_pdfviewer_windows: dependency: transitive description: name: syncfusion_pdfviewer_windows - sha256: aca74797a97512f4d3ca2be0ed49193fae7e5fd29a9b1b1139429d39c9216bf9 + sha256: "5778d9005cd3d81d8a0324dba9676f33bb58ce1062b7ca726d1423b245197511" url: "https://pub.dev" source: hosted - version: "23.1.36" + version: "23.1.38" synchronized: dependency: transitive description: @@ -1638,10 +1630,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: ba140138558fcc3eead51a1c42e92a9fb074a1b1149ed3c73e66035b2ccd94f2 + sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5" url: "https://pub.dev" source: hosted - version: "2.0.19" + version: "2.0.20" url_launcher_windows: dependency: transitive description: @@ -1694,10 +1686,10 @@ packages: dependency: transitive description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" web: dependency: transitive description: @@ -1718,18 +1710,18 @@ packages: dependency: transitive description: name: win32 - sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0 + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" url: "https://pub.dev" source: hosted - version: "5.0.6" + version: "5.0.9" win32_registry: dependency: transitive description: name: win32_registry - sha256: e4506d60b7244251bc59df15656a3093501c37fb5af02105a944d73eb95be4c9 + sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" xdg_directories: dependency: transitive description: @@ -1756,4 +1748,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.1.0 <4.0.0" - flutter: ">=3.10.0" + flutter: ">=3.13.0"