add userbloc and perform version info check

feature/passo/PASSO-#1-Sync-data-from-device-to-postgre-and-vice-versa
rodolfobacuinjr 2023-01-18 15:54:44 +08:00
parent f973820a3b
commit 224b5ce7ac
23 changed files with 1118 additions and 240 deletions

View File

@ -0,0 +1,26 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:unit2/model/login_data/version_info.dart';
import 'package:unit2/sevices/login_service/auth_service.dart';
import 'package:unit2/widgets/error_state.dart';
part 'user_event.dart';
part 'user_state.dart';
class UserBloc extends Bloc<UserEvent, UserState> {
UserBloc() : super(UserInitial()) {
on<GetApkVersion>((event, emit) async {
debugPrint("getApkEvent is called");
try {
emit(SplashScreen());
VersionInfo versionInfo = await AuthService.instance.getVersionInfo();
emit(VersionLoaded(versionInfo: versionInfo));
} catch (e) {
emit(UserError(
message: e.toString(),
));
}
});
}
}

View File

@ -0,0 +1,13 @@
part of 'user_bloc.dart';
abstract class UserEvent extends Equatable {
const UserEvent();
@override
List<Object> get props => [];
}
class GetApkVersion extends UserEvent{
@override
List<Object> get props => [];
}

View File

@ -0,0 +1,36 @@
part of 'user_bloc.dart';
abstract class UserState extends Equatable {
const UserState();
@override
List<Object> get props => [];
}
class UserInitial extends UserState {}
class UserLoading extends UserState {
final String? message;
const UserLoading({this.message});
@override
List<Object> get props => [message!];
}
class SplashScreen extends UserState {
@override
List<Object> get props => [];
}
class UserError extends UserState {
final String? message;
const UserError({this.message});
@override
List<Object> get props => [];
}
class VersionLoaded extends UserState {
final VersionInfo? versionInfo;
const VersionLoaded({this.versionInfo});
@override
List<Object> get props => [versionInfo!];
}

View File

@ -2,6 +2,8 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:device_preview/device_preview.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:unit2/bloc/bloc/user_bloc.dart';
import './utils/router.dart';
import './utils/global.dart';
@ -35,23 +37,26 @@ class MyApp extends StatelessWidget {
safeBlockHorizontal = (screenWidth - safeAreaHorizontal) / 100;
safeBlockVertical = (screenHeight - safeAreaVertical) / 100;
return MaterialApp.router(
// useInheritedMediaQuery: true,
// locale: DevicePreview.locale(context),
// builder: DevicePreview.appBuilder,
routeInformationParser: goRouter.routeInformationParser,
routerDelegate: goRouter.routerDelegate,
// routeInformationProvider: goRouter.routeInformationProvider,
title: 'uniT2 - Universal Tracker and Tracer',
theme: ThemeData(
appBarTheme: const AppBarTheme(
systemOverlayStyle: SystemUiOverlayStyle(
statusBarBrightness: Brightness.dark,
statusBarColor: Colors.black),
return BlocProvider(
create: (context) => UserBloc(),
child: MaterialApp.router(
// useInheritedMediaQuery: true,
// locale: DevicePreview.locale(context),
// builder: DevicePreview.appBuilder,
routeInformationParser: goRouter.routeInformationParser,
routerDelegate: goRouter.routerDelegate,
// routeInformationProvider: goRouter.routeInformationProvider,
title: 'uniT2 - Universal Tracker and Tracer',
theme: ThemeData(
appBarTheme: const AppBarTheme(
systemOverlayStyle: SystemUiOverlayStyle(
statusBarBrightness: Brightness.dark,
statusBarColor: Colors.black),
),
fontFamily: 'LexendDeca',
),
fontFamily: 'LexendDeca',
debugShowCheckedModeBanner: false,
),
debugShowCheckedModeBanner: false,
);
}
}

View File

@ -0,0 +1,41 @@
import 'package:unit2/model/login_data/employee_info/head.dart';
class Department {
Department({
this.id,
this.code,
this.head,
this.name,
this.acronym,
this.parentStationId,
this.fullCode,
});
int? id;
String? code;
Head? head;
String? name;
int? acronym;
int? parentStationId;
String? fullCode;
factory Department.fromJson(Map<String, dynamic> json) => Department(
id: json["id"],
code: json["code"],
head: json["head"],
name: json["name"],
acronym: json["acronym"],
parentStationId: json["parent_station_id"],
fullCode: json["full_code"],
);
Map<String, dynamic> toJson() => {
"id": id,
"code": code,
"head": head,
"name": name,
"acronym": acronym,
"parent_station_id": parentStationId,
"full_code": fullCode,
};
}

View File

@ -0,0 +1,137 @@
import 'package:unit2/model/login_data/employee_info/office.dart';
class EmployeeInfo {
EmployeeInfo({
this.employeeId,
this.empid,
this.classid,
this.uuid,
this.office,
this.profile,
});
String? employeeId;
int? empid;
String? classid;
String? uuid;
Office? office;
Profile? profile;
factory EmployeeInfo.fromJson(Map<String, dynamic> json) => EmployeeInfo(
employeeId: json["employee_id"],
empid: json["empid"],
classid: json["classid"],
uuid: json["uuid"],
office: Office.fromJson(json["office"]),
profile: Profile.fromJson(json["profile"]),
);
Map<String, dynamic> toJson() => {
"employee_id": employeeId,
"empid": empid,
"classid": classid,
"uuid": uuid,
"office": office!.toJson(),
"profile": profile!.toJson(),
};
}
class Profile {
Profile({
this.id,
this.sex,
this.gender,
this.deceased,
this.heightM,
this.birthdate,
this.esigPath,
this.fullName,
this.lastName,
this.weightKg,
this.bloodType,
this.firstName,
this.photoPath,
this.maidenName,
this.middleName,
this.uuidQrcode,
this.civilStatus,
this.titlePrefix,
this.titleSuffix,
this.showTitleId,
this.lastFullName,
this.nameExtension,
});
int? id;
String? sex;
dynamic gender;
bool? deceased;
double? heightM;
DateTime? birthdate;
String? esigPath;
String? fullName;
String? lastName;
int? weightKg;
String? bloodType;
String? firstName;
String? photoPath;
String? maidenName;
String? middleName;
String? uuidQrcode;
String? civilStatus;
String? titlePrefix;
String? titleSuffix;
bool? showTitleId;
String? lastFullName;
String? nameExtension;
factory Profile.fromJson(Map<String, dynamic> json) => Profile(
id: json["id"],
sex: json["sex"],
gender: json["gender"],
deceased: json["deceased"],
heightM: json["height_m"].toDouble(),
birthdate: DateTime.parse(json["birthdate"]),
esigPath: json["esig_path"],
fullName: json["full_name"],
lastName: json["last_name"],
weightKg: json["weight_kg"],
bloodType: json["blood_type"],
firstName: json["first_name"],
photoPath: json["photo_path"],
maidenName: json["maiden_name"],
middleName: json["middle_name"],
uuidQrcode: json["uuid_qrcode"],
civilStatus: json["civil_status"],
titlePrefix: json["title_prefix"],
titleSuffix: json["title_suffix"],
showTitleId: json["show_title_id"],
lastFullName: json["last_full_name"],
nameExtension: json["name_extension"],
);
Map<String, dynamic> toJson() => {
"id": id,
"sex": sex,
"gender": gender,
"deceased": deceased,
"height_m": heightM,
"birthdate":
"${birthdate!.year.toString().padLeft(4, '0')}-${birthdate!.month.toString().padLeft(2, '0')}-${birthdate!.day.toString().padLeft(2, '0')}",
"esig_path": esigPath,
"full_name": fullName,
"last_name": lastName,
"weight_kg": weightKg,
"blood_type": bloodType,
"first_name": firstName,
"photo_path": photoPath,
"maiden_name": maidenName,
"middle_name": middleName,
"uuid_qrcode": uuidQrcode,
"civil_status": civilStatus,
"title_prefix": titlePrefix,
"title_suffix": titleSuffix,
"show_title_id": showTitleId,
"last_full_name": lastFullName,
"name_extension": nameExtension,
};
}

View File

@ -0,0 +1,44 @@
class Head {
Head({
this.id,
this.title,
this.classid,
this.fullName,
this.personId,
this.employeeid,
this.officeposid,
this.lastFullName,
});
int? id;
String? title;
String? classid;
String? fullName;
int? personId;
String? employeeid;
int? officeposid;
String? lastFullName;
factory Head.fromJson(Map<String, dynamic> json) => Head(
id: json["id"],
title: json["title"],
classid: json["classid"],
fullName: json["full_name"],
personId: json["person_id"],
employeeid: json["employeeid"],
officeposid: json["officeposid"],
lastFullName: json["last_full_name"],
);
Map<String, dynamic> toJson() => {
"id": id,
"title": title,
"classid": classid,
"full_name": fullName,
"person_id": personId,
"employeeid": employeeid,
"officeposid": officeposid,
"last_full_name": lastFullName,
};
}

View File

@ -0,0 +1,47 @@
import 'department.dart';
import 'position_class.dart';
class Office {
Office({
this.unit,
this.section,
this.division,
this.posstatid,
this.department,
this.stationId,
this.positionClass,
this.positionSpecificrole,
});
Department? unit;
Department? section;
Department? division;
int? posstatid;
Department? department;
int? stationId;
PositionClass? positionClass;
PositionSpecificrole? positionSpecificrole;
factory Office.fromJson(Map<String, dynamic> json) => Office(
unit: Department.fromJson(json["unit"]),
section: Department.fromJson(json["section"]),
division: Department.fromJson(json["division"]),
posstatid: json["posstatid"],
department: Department.fromJson(json["department"]),
stationId: json["station_id"],
positionClass: PositionClass.fromJson(json["position_class"]),
positionSpecificrole:
PositionSpecificrole.fromJson(json["position_specificrole"]),
);
Map<String, dynamic> toJson() => {
"unit": unit!.toJson(),
"section": section!.toJson(),
"division": division!.toJson(),
"posstatid": posstatid,
"department": department!.toJson(),
"station_id": stationId,
"position_class": positionClass!.toJson(),
"position_specificrole": positionSpecificrole!.toJson(),
};
}

View File

@ -0,0 +1,65 @@
class PositionClass {
PositionClass({
this.level,
this.classid,
this.groupcode,
this.salarygrade,
this.classSuffix,
this.classTitleid,
this.qualificationid,
this.competencyModelId,
});
int? level;
String? classid;
String? groupcode;
int? salarygrade;
String? classSuffix;
PositionSpecificrole? classTitleid;
int? qualificationid;
int? competencyModelId;
factory PositionClass.fromJson(Map<String, dynamic> json) => PositionClass(
level: json["level"],
classid: json["classid"],
groupcode: json["groupcode"],
salarygrade: json["salarygrade"],
classSuffix: json["class_suffix"],
classTitleid: PositionSpecificrole.fromJson(json["class_titleid"]),
qualificationid: json["qualificationid"],
competencyModelId: json["competency_model_id"],
);
Map<String, dynamic> toJson() => {
"level": level,
"classid": classid,
"groupcode": groupcode,
"salarygrade": salarygrade,
"class_suffix": classSuffix,
"class_titleid": classTitleid!.toJson(),
"qualificationid": qualificationid,
"competency_model_id": competencyModelId,
};
}
class PositionSpecificrole {
PositionSpecificrole({
this.title,
this.titleid,
});
String? title;
int? titleid;
factory PositionSpecificrole.fromJson(Map<String, dynamic> json) =>
PositionSpecificrole(
title: json["title"],
titleid: json["titleid"],
);
Map<String, dynamic> toJson() => {
"title": title,
"titleid": titleid,
};
}

View File

@ -0,0 +1,31 @@
class AssignedArea {
AssignedArea({
this.id,
this.areaid,
this.isactive,
this.areaName,
this.areaTypeName,
});
int? id;
String? areaid;
bool? isactive;
String? areaName;
String? areaTypeName;
factory AssignedArea.fromJson(Map<String, dynamic> json) => AssignedArea(
id: json["id"],
areaid: json["areaid"],
isactive: json["isactive"],
areaName: json["area_name"],
areaTypeName: json["area_type_name"],
);
Map<String, dynamic> toJson() => {
"id": id,
"areaid": areaid,
"isactive": isactive,
"area_name": areaName,
"area_type_name": areaTypeName,
};
}

View File

@ -0,0 +1,48 @@
import 'role.dart';
class LoginUser {
LoginUser({
this.id,
this.profileId,
this.firstName,
this.lastName,
this.username,
this.email,
this.staff,
this.roles,
});
int? id;
int? profileId;
String? firstName;
String? lastName;
String? username;
String? email;
bool? staff;
List<Role?>? roles;
factory LoginUser.fromJson(Map<String, dynamic> json) => LoginUser(
id: json["id"],
profileId: json["profile_id"],
firstName: json["first_name"],
lastName: json["last_name"],
username: json["username"],
email: json["email"],
staff: json["staff"],
roles: json["roles"] == null
? []
: List<Role?>.from(json["roles"]!.map((x) => Role.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"profile_id": profileId,
"first_name": firstName,
"last_name": lastName,
"username": username,
"email": email,
"staff": staff,
"roles": roles == null
? []
: List<dynamic>.from(roles!.map((x) => x!.toJson())),
};
}

View File

@ -0,0 +1,68 @@
class Module {
Module({
this.id,
this.icon,
this.name,
this.slug,
this.objects,
});
int? id;
String? icon;
String? name;
String? slug;
List<Object?>? objects;
factory Module.fromJson(Map<String, dynamic> json) => Module(
id: json["id"],
icon: json["icon"],
name: json["name"],
slug: json["slug"],
objects: json["objects"] == null
? []
: List<Object?>.from(
json["objects"]!.map((x) => Object.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"icon": icon,
"name": name,
"slug": slug,
"objects": objects == null
? []
: List<dynamic>.from(objects!.map((x) => x!.toJson())),
};
}
class Object {
Object({
this.id,
this.name,
this.slug,
this.operations,
});
int? id;
String? name;
String? slug;
List<String?>? operations;
factory Object.fromJson(Map<String, dynamic> json) => Object(
id: json["id"],
name: json["name"],
slug: json["slug"],
operations: json["operations"] == null
? []
: List<String?>.from(json["operations"]!.map((x) => x)),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"slug": slug,
"operations": operations == null
? []
: List<dynamic>.from(operations!.map((x) => x)),
};
}

View File

@ -0,0 +1,74 @@
import 'assigned_area.dart';
import 'modue.dart';
class Role {
Role({
this.id,
this.name,
this.modules,
this.assignedArea,
});
int? id;
String? name;
List<Module?>? modules;
List<AssignedArea?>? assignedArea;
factory Role.fromJson(Map<String, dynamic> json) => Role(
id: json["id"],
name: json["name"],
modules: json["modules"] == null
? []
: List<Module?>.from(
json["modules"]!.map((x) => Module.fromJson(x))),
assignedArea: json["assigned_area"] == null
? []
: json["assigned_area"] == null
? []
: List<AssignedArea?>.from(json["assigned_area"]!
.map((x) => AssignedArea.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"modules": modules == null
? []
: List<dynamic>.from(modules!.map((x) => x!.toJson())),
"assigned_area": assignedArea == null
? []
: assignedArea == null
? []
: List<dynamic>.from(assignedArea!.map((x) => x!.toJson())),
};
}class Object {
Object({
this.id,
this.name,
this.slug,
this.operations,
});
int? id;
String? name;
String? slug;
List<String?>? operations;
factory Object.fromJson(Map<String, dynamic> json) => Object(
id: json["id"],
name: json["name"],
slug: json["slug"],
operations: json["operations"] == null
? []
: List<String?>.from(json["operations"]!.map((x) => x)),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"slug": slug,
"operations": operations == null
? []
: List<dynamic>.from(operations!.map((x) => x)),
};
}

View File

@ -0,0 +1,71 @@
import 'dart:convert';
import 'package:unit2/model/login_data/employee_info/employee_info.dart';
import 'login_user.dart';
UserData? userDataFromJson(String str) => UserData.fromJson(json.decode(str));
String userDataToJson(UserData? data) => json.encode(data!.toJson());
class UserData {
UserData({
this.user,
this.employeeInfo,
});
UserDataUser? user;
EmployeeInfo? employeeInfo;
factory UserData.fromJson(Map<String, dynamic> json) => UserData(
user: UserDataUser.fromJson(json["user"]),
employeeInfo: EmployeeInfo.fromJson(json["employee_info"]),
);
Map<String, dynamic> toJson() => {
"user": user!.toJson(),
"employee_info": employeeInfo!.toJson(),
};
}
class UserDataUser {
UserDataUser({
this.login,
});
Login? login;
factory UserDataUser.fromJson(Map<String, dynamic> json) => UserDataUser(
login: Login.fromJson(json["login"]),
);
Map<String, dynamic> toJson() => {
"login": login!.toJson(),
};
}
class Login {
Login({
this.dateTime,
this.token,
this.user,
});
DateTime? dateTime;
String? token;
LoginUser? user;
factory Login.fromJson(Map<String, dynamic> json) => Login(
dateTime: DateTime.parse(json["date_time"]),
token: json["token"],
user: LoginUser.fromJson(json["user"]),
);
Map<String, dynamic> toJson() => {
"date_time": dateTime?.toIso8601String(),
"token": token,
"user": user!.toJson(),
};
}

View File

@ -0,0 +1,48 @@
class VersionInfo {
VersionInfo({
this.version,
this.versionInfo,
this.dateReleased,
this.development,
this.production,
this.downloadUrl,
this.arm64v8aDownloadUrl,
this.armeabiv7aDownloadUrl,
this.x8664DownloadUrl,
});
String? version;
String? versionInfo;
DateTime? dateReleased;
bool? development;
bool? production;
String? downloadUrl;
String? arm64v8aDownloadUrl;
String? armeabiv7aDownloadUrl;
String? x8664DownloadUrl;
factory VersionInfo.fromJson(Map<String, dynamic> json) => VersionInfo(
version: json["version"],
versionInfo: json["version_info"],
dateReleased: DateTime.parse(json["date_released"]),
development: json["development"],
production: json["production"],
downloadUrl: json["download_url"],
arm64v8aDownloadUrl: json["arm64_v8a_download_url"],
armeabiv7aDownloadUrl: json["armeabi_v7a_download_url"],
x8664DownloadUrl: json["x86_64_down_download_url"],
);
Map<String, dynamic> toJson() => {
"version": version,
"version_info": versionInfo,
"date_released":
"${dateReleased!.year.toString().padLeft(4, '0')}-${dateReleased!.month.toString().padLeft(2, '0')}-${dateReleased!.day.toString().padLeft(2, '0')}",
"development": development,
"production": production,
"download_url": downloadUrl,
"arm64_v8a_download_url": arm64v8aDownloadUrl,
"armeabi_v7a_download_url": armeabiv7aDownloadUrl,
"x86_64_down_download_url": x8664DownloadUrl,
};
}

View File

@ -1,5 +1,6 @@
import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:fluttericon/font_awesome5_icons.dart';
@ -7,10 +8,13 @@ import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:unit2/bloc/bloc/user_bloc.dart';
import 'package:unit2/utils/alerts.dart';
import 'package:unit2/utils/scanner.dart';
import 'package:unit2/utils/text_container.dart';
import 'package:unit2/widgets/error_state.dart';
import '../../../widgets/splash_screen.dart';
import '../../../widgets/wave.dart';
import '../../../utils/global.dart';
import '../../../theme-data.dart/colors.dart';
@ -36,236 +40,258 @@ class _UniT2LoginState extends State<UniT2Login> {
onWillPop: pressAgainToExit,
child: Scaffold(
body: ProgressHUD(
child: Builder(builder: (context) {
return SizedBox(
child: SingleChildScrollView(
child: Stack(
children: [
Positioned(
bottom: 0,
right: 0,
child: WaveReverse(height: blockSizeVertical * 7)),
SizedBox(
height: blockSizeVertical * 100,
child: FormBuilder(
key: _formKey,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 25),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(height: blockSizeVertical * 7),
SvgPicture.asset(
'assets/svgs/logo.svg',
height: blockSizeVertical * 16,
allowDrawingOutsideViewBox: true,
color: primary,
),
Text(
welcome,
style: TextStyle(
fontSize: blockSizeVertical * 5,
fontWeight: FontWeight.w600),
),
Text(unitApp,
style: TextStyle(
fontSize: blockSizeVertical * 8,
fontWeight: FontWeight.w800,
letterSpacing: .2,
height: 1,
color: primary)),
Text(
loginToContinue,
style: TextStyle(
fontSize: blockSizeVertical * 2,
height: 1.5,
fontWeight: FontWeight.w600),
),
SizedBox(
height: blockSizeVertical * 1.5,
),
// USERNAME
FormBuilderTextField(
name: 'username',
validator: FormBuilderValidators.required(
errorText: usernameRequired),
autofocus: false,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87),
decoration: loginTextFieldStyle().copyWith()),
SizedBox(
height: blockSizeVertical * 1.5,
),
// PASSWORD
FormBuilderTextField(
name: 'password',
validator: FormBuilderValidators.required(
errorText: passwordRequired),
// initialValue: state.password,
onChanged: (value) {
value!.isEmpty
? setState(() {
showSuffixIcon = false;
})
: setState(() {
showSuffixIcon = true;
});
},
autofocus: false,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87),
decoration: loginTextFieldStyle().copyWith(
suffixIcon: Visibility(
visible: showSuffixIcon,
child: _showPassword
? IconButton(
icon: Icon(FontAwesome5.eye_slash,
size: 24,
color: Theme.of(context)
.textTheme
.displayLarge
?.color),
onPressed: () {
setState(() {
_showPassword = false;
});
},
)
: IconButton(
onPressed: () {
setState(() {
_showPassword = true;
});
},
icon: Icon(FontAwesome5.eye,
size: 24,
color: Theme.of(context)
.textTheme
.displayLarge
?.color)),
),
prefixIcon: const Icon(
Icons.lock,
color: primary,
),
labelText: "Password",
hintText: enterPassword),
obscureText: _showPassword ? true : false,
),
SizedBox(
height: blockSizeVertical * 2,
),
SizedBox(
height: blockSizeVertical * 7,
// Login Button
child: SizedBox(
width: MediaQuery.of(context).size.width,
child: ElevatedButton(
style: mainBtnStyle(second,
Colors.transparent, Colors.white54),
child: const Text(
login,
style: TextStyle(color: Colors.white),
),
onPressed: () {
final progress = ProgressHUD.of(context);
progress?.showWithText(
'Logging in...',
);
FocusScope.of(context).unfocus();
Future.delayed(const Duration(seconds: 5),
() {
progress!.dismiss();
context.goNamed("home");
});
// if (_formKey.currentState!
// .saveAndValidate()) {
// context.go(context.namedLocation('home'));
// }
// if (_formKey.currentState.validate()) {
// _formKey.currentState.save();
// BlocProvider.of<UserBloc>(context)
// .add(UserWebLogin(
// password: password,
// username: username));
// }
},
child: BlocConsumer<UserBloc, UserState>(listener: (context, state) {
if (state is UserLoading) {
final progress = ProgressHUD.of(context);
progress?.showWithText(
'Logging in...',
);
}
}, builder: (context, state) {
if (state is VersionLoaded) {
return Builder(builder: (context) {
return SizedBox(
child: SingleChildScrollView(
child: Stack(
children: [
Positioned(
bottom: 0,
right: 0,
child: WaveReverse(height: blockSizeVertical * 7)),
SizedBox(
height: blockSizeVertical * 100,
child: FormBuilder(
key: _formKey,
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 25),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(height: blockSizeVertical * 7),
SvgPicture.asset(
'assets/svgs/logo.svg',
height: blockSizeVertical * 16,
allowDrawingOutsideViewBox: true,
color: primary,
),
),
),
SizedBox(
height: blockSizeVertical * 1.5,
),
SizedBox(
height: blockSizeVertical * 7,
child: SizedBox(
Text(
welcome,
style: TextStyle(
fontSize: blockSizeVertical * 5,
fontWeight: FontWeight.w600),
),
Text(unitApp,
style: TextStyle(
fontSize: blockSizeVertical * 8,
fontWeight: FontWeight.w800,
letterSpacing: .2,
height: 1,
color: primary)),
Text(
loginToContinue,
style: TextStyle(
fontSize: blockSizeVertical * 2,
height: 1.5,
fontWeight: FontWeight.w600),
),
SizedBox(
height: blockSizeVertical * 1.5,
),
// USERNAME
FormBuilderTextField(
name: 'username',
validator: FormBuilderValidators.required(
errorText: usernameRequired),
autofocus: false,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87),
decoration:
loginTextFieldStyle().copyWith()),
SizedBox(
height: blockSizeVertical * 1.5,
),
// PASSWORD
FormBuilderTextField(
name: 'password',
validator: FormBuilderValidators.required(
errorText: passwordRequired),
// initialValue: state.password,
onChanged: (value) {
value!.isEmpty
? setState(() {
showSuffixIcon = false;
})
: setState(() {
showSuffixIcon = true;
});
},
autofocus: false,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87),
decoration: loginTextFieldStyle().copyWith(
suffixIcon: Visibility(
visible: showSuffixIcon,
child: _showPassword
? IconButton(
icon: Icon(
FontAwesome5.eye_slash,
size: 24,
color: Theme.of(context)
.textTheme
.displayLarge
?.color),
onPressed: () {
setState(() {
_showPassword = false;
});
},
)
: IconButton(
onPressed: () {
setState(() {
_showPassword = true;
});
},
icon: Icon(FontAwesome5.eye,
size: 24,
color: Theme.of(context)
.textTheme
.displayLarge
?.color)),
),
prefixIcon: const Icon(
Icons.lock,
color: primary,
),
labelText: "Password",
hintText: enterPassword),
obscureText: _showPassword ? true : false,
),
SizedBox(
height: blockSizeVertical * 2,
),
SizedBox(
height: blockSizeVertical * 7,
// Login Button
child: SizedBox(
width: MediaQuery.of(context).size.width,
child: ElevatedButton(
style: mainBtnStyle(second,
Colors.transparent, Colors.white54),
child: const Text(
login,
style: TextStyle(color: Colors.white),
),
onPressed: () {
FocusScope.of(context).unfocus();
// Future.delayed(
// const Duration(seconds: 5), () {
// progress!.dismiss();
// context.goNamed("home");
// });
// if (_formKey.currentState!
// .saveAndValidate()) {
// context.go(context.namedLocation('home'));
// }
// if (_formKey.currentState.validate()) {
// _formKey.currentState.save();
// BlocProvider.of<UserBloc>(context)
// .add(UserWebLogin(
// password: password,
// username: username));
// }
},
),
),
),
SizedBox(
height: blockSizeVertical * 1.5,
),
SizedBox(
height: blockSizeVertical * 7,
child: SizedBox(
width:
MediaQuery.of(context).size.width,
child: ElevatedButton.icon(
style: mainBtnStyle(Colors.white,
second, primary.withOpacity(.4)),
icon: const Icon(
Icons.qr_code,
color: second,
),
label: const Text(
loginViaQr,
style: TextStyle(color: second),
),
onPressed: () async {
context.goNamed('register');
// ScanResult result =
// await QRCodeBarCodeScanner.instance
// .scanner();
// debugPrint(result.type.toString());
// debugPrint(
// result.rawContent.toString());
// BlocProvider.of<UserBloc>(context)
// .add(QRCodelogin());
},
),
)),
SizedBox(
height: blockSizeVertical * 1,
),
const LoginViaQr(text: emergencyReponseLabel),
SizedBox(
height: blockSizeVertical * 1,
),
// REQUEST SOS
SizedBox(
height: screenHeight * .07,
width: MediaQuery.of(context).size.width,
child: ElevatedButton.icon(
style: mainBtnStyle(Colors.white, second,
primary.withOpacity(.4)),
icon: const Icon(
Icons.qr_code,
color: second,
),
label: const Text(
loginViaQr,
style: TextStyle(color: second),
),
onPressed: () async {
context.goNamed('register');
// ScanResult result =
// await QRCodeBarCodeScanner.instance
// .scanner();
// debugPrint(result.type.toString());
// debugPrint(
// result.rawContent.toString());
// BlocProvider.of<UserBloc>(context)
// .add(QRCodelogin());
},
),
)),
SizedBox(
height: blockSizeVertical * 1,
icon: const Icon(
FontAwesome5.life_ring,
color: Colors.white,
),
style: mainBtnStyle(third,
Colors.transparent, Colors.white38),
onPressed: () {
context.goNamed('add-mobile');
},
label: const Text(
requestSOS,
style: TextStyle(color: Colors.white),
)),
)
],
),
const LoginViaQr(text: emergencyReponseLabel),
SizedBox(
height: blockSizeVertical * 1,
),
// REQUEST SOS
SizedBox(
height: screenHeight * .07,
width: MediaQuery.of(context).size.width,
child: ElevatedButton.icon(
icon: const Icon(
FontAwesome5.life_ring,
color: Colors.white,
),
style: mainBtnStyle(third,
Colors.transparent, Colors.white38),
onPressed: () {
context.goNamed('add-mobile');
},
label: const Text(
requestSOS,
style: TextStyle(color: Colors.white),
)),
)
],
),
),
),
),
],
),
],
),
),
),
);
});
}
if (state is UserError) {
return ErrorState(
message: state.message,
);
}
if (state is SplashScreen) {
return const UniTSplashScreen();
}
return Center(
child: Text("Default"),
);
}),
),

View File

@ -0,0 +1,39 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:unit2/model/login_data/version_info.dart';
import 'package:http/http.dart' as http;
import '../../utils/text_container.dart';
import '../../utils/urls.dart';
class AuthService {
static final AuthService _instance = AuthService();
static AuthService get instance => _instance;
Future<VersionInfo> getVersionInfo() async {
VersionInfo versionInfo = VersionInfo();
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
HttpHeaders.authorizationHeader: 'UniT2',
'X-User': ""
};
try {
http.Response response = await http.get(
Uri.https('unitylb1.agusandelnorte.gov.ph',
'/unit2/api/sys/apk_version/latest/'),
headers: headers);
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
versionInfo = VersionInfo.fromJson(data['data']);
}
} on TimeoutException catch (e) {
throw (timeoutError);
} on SocketException catch (e) {
throw (timeoutError);
} catch (e) {
throw (e.toString());
}
return versionInfo;
}
}

View File

@ -1,4 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:unit2/bloc/bloc/user_bloc.dart';
import 'package:unit2/screens/unit2/login/register.dart';
import 'package:unit2/screens/unit2/roles/qr_code_scanner.dart/scan.dart';
import 'package:unit2/screens/unit2/roles/qr_code_scanner.dart/settings_screen.dart';
@ -17,7 +20,11 @@ final GoRouter goRouter = GoRouter(routes: <GoRoute>[
GoRoute(
path: '/',
name: 'login',
builder: (context, state) => UniT2Login(),
builder: (context, state) {
debugPrint("login bloc called");
BlocProvider.of<UserBloc>(context).add(GetApkVersion());
return const UniT2Login();
},
routes: [
GoRoute(
name: 'register',

View File

@ -1,7 +1,6 @@
class Url{
static final Url _instance = Url();
static Url get instance => instance;
static Url get instance => _instance;
String host(){
return '192.168.10.219:3000';
@ -10,4 +9,9 @@ class Url{
String authentication(){
return '/api/account/auth/login';
}
String apkUrl(){
return "";
}
}

View File

@ -0,0 +1,13 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
class ErrorState extends StatelessWidget {
final String? message;
const ErrorState({super.key,this.message});
@override
Widget build(BuildContext context) {
return Center(child: Text(message!));
}
}

View File

@ -0,0 +1,12 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
class UniTSplashScreen extends StatelessWidget {
const UniTSplashScreen({super.key});
@override
Widget build(BuildContext context) {
return const Center(child: Text("Splash Screen"),);
}
}

View File

@ -50,6 +50,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.3"
bloc:
dependency: transitive
description:
name: bloc
url: "https://pub.dartlang.org"
source: hosted
version: "8.1.0"
boolean_selector:
dependency: transitive
description:
@ -148,6 +155,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
equatable:
dependency: "direct main"
description:
name: equatable
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
fake_async:
dependency: transitive
description:
@ -188,6 +202,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_bloc:
dependency: "direct main"
description:
name: flutter_bloc
url: "https://pub.dartlang.org"
source: hosted
version: "8.1.1"
flutter_blurhash:
dependency: transitive
description:

View File

@ -60,6 +60,8 @@ dependencies:
signature: ^5.3.0
awesome_dialog: ^3.0.2
system_info2: ^2.0.4
flutter_bloc: ^8.1.1
equatable: ^2.0.5
dev_dependencies:
flutter_test: