commit stash

feature/passo/PASSO-#1-Sync-data-from-device-to-postgre-and-vice-versa
PGAN-MIS 2023-04-11 14:08:10 +08:00
parent 2ef9151258
commit 7f0f9009ec
11 changed files with 1868 additions and 4 deletions

View File

@ -0,0 +1,22 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:location/location.dart';
import 'package:unit2/sevices/sos/sos_service.dart';
part 'sos_event.dart';
part 'sos_state.dart';
class SosBloc extends Bloc<SosEvent, SosState> {
SosBloc() : super(SosInitial()) {
LocationData? locationData;
on<LoadUserLocation>((event, emit)async {
emit(LoadingState());
LocationData? newLocationData =
await SosService.instance.getUserLocation();
locationData = newLocationData;
// User location Loaded and there is no mobile numbers in cache
emit(UserLocationLoaded(locationData: locationData!));
});
}
}

View File

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

View File

@ -0,0 +1,27 @@
part of 'sos_bloc.dart';
abstract class SosState extends Equatable {
const SosState();
@override
List<Object> get props => [];
}
class SosInitial extends SosState {}
class UserLocationLoaded extends SosState {
final LocationData locationData;
const UserLocationLoaded({required this.locationData});
@override
List<Object> get props => [locationData];
}
class ErrorState extends SosState{
final String message;
const ErrorState({required this.message});
@override
List<Object> get props => [message];
}
class LoadingState extends SosState{
}

View File

@ -0,0 +1,136 @@
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_svg/svg.dart';
import 'package:unit2/screens/sos/components/request_sos.dart';
import 'package:unit2/theme-data.dart/text-styles.dart';
import 'package:unit2/utils/screen_info.dart';
import '../../../theme-data.dart/btn-style.dart';
import '../../../theme-data.dart/colors.dart';
import '../../../theme-data.dart/form-style.dart';
import '../../../utils/global.dart';
import '../../../utils/text_container.dart';
import '../../../utils/validators.dart';
import '../../../widgets/wave.dart';
class AddMobile extends StatelessWidget {
AddMobile({super.key});
final _formKey = GlobalKey<FormBuilderState>();
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
return true;
},
child: SafeArea(
child: Scaffold(
appBar: AppBar(
title: const Text("Add contact info"),
centerTitle: true,
backgroundColor: primary,
elevation: 0,
),
resizeToAvoidBottomInset: true,
body: SingleChildScrollView(
child: SizedBox(
height: screenHeight * .90,
child: Stack(
children: [
Wave(height: blockSizeVertical * 8),
Positioned(
bottom: 0,
right: 0,
child: WaveReverse(height: blockSizeVertical * 8)),
Container(
height: screenHeight,
padding: isMobile()
? const EdgeInsets.symmetric(horizontal: 24)
: const EdgeInsets.symmetric(horizontal: 60),
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: isMobile()
? screenHeight * .12
: screenHeight * .20),
SvgPicture.asset(
'assets/svgs/add_mobile.svg',
height: isMobile()
? blockSizeVertical * 22
: blockSizeVertical * 30,
allowDrawingOutsideViewBox: true,
),
const SizedBox(
height: 24,
),
Text(addMobile, style: titleTextStyle()),
const SizedBox(
height: 8,
),
Text(addMobileCaption,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.caption),
const SizedBox(
height: 24,
),
FormBuilder(
key: _formKey,
child: Column(
children: [
// Mobile number 1
FormBuilderTextField(
name: 'mobile1',
validator: mobileNumberValidator,
maxLength: 11,
decoration:
normalTextFieldStyle(mobile1, "+63")),
const SizedBox(
height: 12,
),
FormBuilderTextField(
name: 'mobile2',
maxLength: 11,
decoration:
normalTextFieldStyle(mobile2, "+63")),
SizedBox(
height: isMobile()
? blockSizeVertical * 3
: blockSizeHorizontal * 5),
SizedBox(
width: double.infinity,
height: screenHeight * .06,
child: ElevatedButton(
style: secondaryBtnStyle(second,
Colors.transparent, Colors.white54),
child: const Text(
submit,
style: TextStyle(color: Colors.white),
),
onPressed: () {
if (_formKey.currentState!
.saveAndValidate()) {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context){
return RequestSOS();
}));
}
// }
},
),
),
],
))
]),
),
],
),
),
),
),
),
);
}
}

View File

@ -0,0 +1,109 @@
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_svg/svg.dart';
import 'package:fluttericon/font_awesome5_icons.dart';
import 'package:fluttericon/typicons_icons.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:unit2/screens/sos/components/mobile.dart';
import 'package:unit2/theme-data.dart/colors.dart';
import 'package:unit2/utils/text_container.dart';
import '../../../theme-data.dart/btn-style.dart';
import '../../../theme-data.dart/form-style.dart';
import '../../../utils/global.dart';
class RequestSOS extends StatefulWidget {
const RequestSOS({super.key});
@override
State<RequestSOS> createState() => _RequestSOSState();
}
class _RequestSOSState extends State<RequestSOS> {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text(sOSTitle),
backgroundColor: second,
),
body: SingleChildScrollView(
child: Container(
height: screenHeight * .84,
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10),
child: Column(
children: [
SizedBox(
height: blockSizeVertical * 2,
),
SvgPicture.asset(
'assets/svgs/request_sos.svg',
height: blockSizeVertical * 22,
allowDrawingOutsideViewBox: true,
),
Mobile(
title: "09661548775",
subtitle: mobile1,
onPressed: () {}),
const Divider(),
Mobile(
title: "09661548775",
subtitle: mobile2,
onPressed: () {}),
const Divider(),
ListTile(
leading: const Icon(
Typicons.location,
color: second,
),
title: Text("Latitude/Longitude"),
subtitle: Text(
currentLocation,
style: Theme.of(context).textTheme.caption,
),
),
FormBuilderTextField(
name: "message",
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(
errorText: messageRequired)
]),
autovalidateMode: AutovalidateMode.onUserInteraction,
maxLines: 5,
decoration: normalTextFieldStyle("", sosMessage),
),
const Expanded(
child: SizedBox(),
),
SizedBox(
width: double.infinity,
height: screenHeight * .06,
child: ElevatedButton(
style: secondaryBtnStyle(
second, Colors.transparent, Colors.white54),
child: const Text(
submit,
style: TextStyle(color: Colors.white),
),
onPressed: () {
// if (_formKey.currentState.validate()) {
// _formKey.currentState.save();
// BlocProvider.of<UserBloc>(context)
// .add(UserWebLogin(
// password: password,
// username: username));
// }
},
),
),
],
)),
),
),
);
}
}

View File

@ -0,0 +1,133 @@
import 'package:animate_do/animate_do.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutter_svg/svg.dart';
import 'package:unit2/theme-data.dart/btn-style.dart';
import 'package:unit2/utils/text_container.dart';
import '../../../theme-data.dart/colors.dart';
import '../../../utils/global.dart';
class SOSreceived extends StatelessWidget {
final Function onpressed;
const SOSreceived({required Key key, required this.onpressed})
: super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 35),
height: screenHeight,
child: Stack(
children: [
Positioned(
bottom: 0,
child: SizedBox(
width: screenWidth,
height: screenHeight / 2,
child: Opacity(
opacity: .2,
child: Image.asset(
"assets/emergency.png",
fit: BoxFit.cover,
),
),
)),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: blockSizeVertical * 6,
),
Bounce(
from: 20,
infinite: true,
delay: const Duration(milliseconds: 800),
child: Stack(
alignment: AlignmentDirectional.topCenter,
children: [
Container(
margin: const EdgeInsets.only(top: 20),
child: CircleAvatar(
radius: blockSizeVertical * 8,
backgroundColor: second,
child: Container(
margin: const EdgeInsets.only(top: 25),
child: SvgPicture.asset(
'assets/sos.svg',
height: blockSizeHorizontal * 17,
color: Colors.white,
allowDrawingOutsideViewBox: true,
alignment: Alignment.bottomCenter,
),
),
),
),
Positioned(
top: blockSizeVertical * 3,
child: const SpinKitPulse(
color: primary,
size: 120,
),
),
],
),
),
const SizedBox(height: 16),
SlideInUp(
from: 50,
child: AutoSizeText(
sosReceived,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.displayMedium!.copyWith(
fontSize: 40,
color: third,
fontWeight: FontWeight.w500,
),
),
),
const SizedBox(
height: 8,
),
SlideInUp(
from: 50,
child: Container(
padding: const EdgeInsets.all(15),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(15))),
child: AutoSizeText(
sOSReceivedMessage,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.caption!.copyWith(
fontSize: 16,
color: Colors.black87,
),
),
),
),
const SizedBox(
height: 40,
),
Expanded(child: Container()),
SlideInUp(
child: SizedBox(
height: 50,
width: 200,
child: TextButton(
style: mainBtnStyle(second, Colors.transparent, second),
onPressed: () {},
child: const Text(cancelRequest,
style: TextStyle(
color: Colors.white,
)),
),
),
)
],
),
],
),
);
}
}

View File

@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter/src/widgets/placeholder.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:unit2/bloc/sos/sos_bloc.dart';
import 'package:unit2/screens/sos/components/add_mobile.dart';
import 'package:unit2/theme-data.dart/colors.dart';
class SosScreen extends StatefulWidget {
const SosScreen({super.key});
@override
State<SosScreen> createState() => _SosScreenState();
}
class _SosScreenState extends State<SosScreen> {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
title: const Text("SOS"),
centerTitle: true,
backgroundColor: primary,
),
body: ProgressHUD(
padding: const EdgeInsets.all(24),
backgroundColor: Colors.black87,
indicatorWidget: const SpinKitFadingCircle(color: Colors.white),
child: BlocConsumer<SosBloc,SosState>(
listener: (context, state) {
//// user location loaded
if (state is UserLocationLoaded) {
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return AddMobile();
}));
}
////loading state
if (state is LoadingState) {
final progress = ProgressHUD.of(context);
progress!.showWithText("Please wait...");
}
},
builder: (context, state) {
if (state is ErrorState) {}
return Container();
},
),
),
));
}
}

View File

@ -317,7 +317,7 @@ class _UniT2LoginState extends State<UniT2Login> {
Colors.transparent, Colors.transparent,
Colors.white38), Colors.white38),
onPressed: () { onPressed: () {
Navigator.pushNamed(context, '/sos');
}, },
label: const Text( label: const Text(
requestSOS, requestSOS,

View File

@ -0,0 +1,31 @@
import 'package:intl/intl.dart';
import 'package:location/location.dart';
class SosService{
static final SosService _instance = SosService();
static SosService get instance => _instance;
DateFormat todayFormat = DateFormat("yMdHms");
Future<LocationData?> getUserLocation() async {
Location location = Location();
LocationData? locationData;
bool serviceEnabled = false;
PermissionStatus permissionGranted;
serviceEnabled = await location.serviceEnabled();
if (!serviceEnabled) {
serviceEnabled = await location.requestService();
if (!serviceEnabled) {
return null;
}
}
permissionGranted = await location.hasPermission();
if (permissionGranted == PermissionStatus.denied) {
permissionGranted = await location.requestPermission();
if (permissionGranted != PermissionStatus.granted) {
return null;
}
}
LocationData newLocationData = await location.getLocation();
locationData = newLocationData;
return locationData;
}
}

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart'; import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/bloc/sos/sos_bloc.dart';
import 'package:unit2/screens/sos/index.dart';
import 'package:unit2/screens/unit2/homepage.dart/components/menu.dart'; import 'package:unit2/screens/unit2/homepage.dart/components/menu.dart';
import 'package:unit2/screens/unit2/login/login.dart'; import 'package:unit2/screens/unit2/login/login.dart';
import 'package:unit2/utils/global_context.dart'; import 'package:unit2/utils/global_context.dart';
@ -34,13 +36,21 @@ class AppRouter {
return const QRLogin(); return const QRLogin();
}); });
case '/profile': case '/profile':
ProfileArguments arguments = routeSettings.arguments as ProfileArguments; ProfileArguments arguments =
routeSettings.arguments as ProfileArguments;
BlocProvider.of<ProfileBloc>( BlocProvider.of<ProfileBloc>(
NavigationService.navigatorKey.currentContext!) NavigationService.navigatorKey.currentContext!)
.add(LoadProfile(token: arguments.token, userID: arguments.userID)); .add(LoadProfile(token: arguments.token, userID: arguments.userID));
return MaterialPageRoute(builder: (_) { return MaterialPageRoute(builder: (_) {
return const ProfileInfo(); return const ProfileInfo();
}); });
case '/sos':
return MaterialPageRoute(builder: (BuildContext context) {
return BlocProvider(
create: (context) => SosBloc()..add(LoadUserLocation()),
child: const SosScreen(),
);
});
default: default:
return MaterialPageRoute(builder: (context) { return MaterialPageRoute(builder: (context) {
return Container(); return Container();

1327
pubspec.lock 100644

File diff suppressed because it is too large Load Diff