Handle invalid credentails
This commit is contained in:
parent
9e5e260eb1
commit
5b255b1745
|
|
@ -2,15 +2,30 @@ import 'package:json_annotation/json_annotation.dart';
|
|||
|
||||
part 'entities.g.dart';
|
||||
|
||||
|
||||
@JsonSerializable()
|
||||
class ErrorResponse extends Object with _$ErrorResponseSerializerMixin {
|
||||
|
||||
final String message;
|
||||
|
||||
ErrorResponse(
|
||||
this.message,
|
||||
);
|
||||
|
||||
factory ErrorResponse.fromJson(Map<String, dynamic> json) => _$ErrorResponseFromJson(json);
|
||||
}
|
||||
|
||||
|
||||
@JsonSerializable()
|
||||
class BaseListResponse extends Object with _$BaseListResponseSerializerMixin {
|
||||
//final String message;
|
||||
|
||||
@JsonKey(name: "data")
|
||||
final List<dynamic> data;
|
||||
final ErrorResponse error;
|
||||
|
||||
BaseListResponse(
|
||||
this.data,
|
||||
this.error,
|
||||
);
|
||||
|
||||
factory BaseListResponse.fromJson(Map<String, dynamic> json) => _$BaseListResponseFromJson(json);
|
||||
|
|
@ -22,9 +37,11 @@ class BaseItemResponse extends Object with _$BaseItemResponseSerializerMixin {
|
|||
|
||||
@JsonKey(name: "data")
|
||||
final dynamic data;
|
||||
final ErrorResponse error;
|
||||
|
||||
BaseItemResponse(
|
||||
this.data,
|
||||
this.error,
|
||||
);
|
||||
|
||||
factory BaseItemResponse.fromJson(Map<String, dynamic> json) => _$BaseItemResponseFromJson(json);
|
||||
|
|
|
|||
|
|
@ -6,20 +6,42 @@ part of 'entities.dart';
|
|||
// Generator: JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ErrorResponse _$ErrorResponseFromJson(Map<String, dynamic> json) =>
|
||||
new ErrorResponse(json['message'] as String);
|
||||
|
||||
abstract class _$ErrorResponseSerializerMixin {
|
||||
String get message;
|
||||
Map<String, dynamic> toJson() => <String, dynamic>{'message': message};
|
||||
}
|
||||
|
||||
BaseListResponse _$BaseListResponseFromJson(Map<String, dynamic> json) =>
|
||||
new BaseListResponse(json['data'] as List);
|
||||
new BaseListResponse(
|
||||
json['data'] as List,
|
||||
json['error'] == null
|
||||
? null
|
||||
: new ErrorResponse.fromJson(
|
||||
json['error'] as Map<String, dynamic>));
|
||||
|
||||
abstract class _$BaseListResponseSerializerMixin {
|
||||
List<dynamic> get data;
|
||||
Map<String, dynamic> toJson() => <String, dynamic>{'data': data};
|
||||
ErrorResponse get error;
|
||||
Map<String, dynamic> toJson() =>
|
||||
<String, dynamic>{'data': data, 'error': error};
|
||||
}
|
||||
|
||||
BaseItemResponse _$BaseItemResponseFromJson(Map<String, dynamic> json) =>
|
||||
new BaseItemResponse(json['data']);
|
||||
new BaseItemResponse(
|
||||
json['data'],
|
||||
json['error'] == null
|
||||
? null
|
||||
: new ErrorResponse.fromJson(
|
||||
json['error'] as Map<String, dynamic>));
|
||||
|
||||
abstract class _$BaseItemResponseSerializerMixin {
|
||||
dynamic get data;
|
||||
Map<String, dynamic> toJson() => <String, dynamic>{'data': data};
|
||||
ErrorResponse get error;
|
||||
Map<String, dynamic> toJson() =>
|
||||
<String, dynamic>{'data': data, 'error': error};
|
||||
}
|
||||
|
||||
CompanyEntity _$CompanyEntityFromJson(Map<String, dynamic> json) =>
|
||||
|
|
|
|||
|
|
@ -35,26 +35,35 @@ class WebClient {
|
|||
|
||||
Future<dynamic> fetchItem(String url, String token) async {
|
||||
final http.Response response = await sendGetRequest(url, token);
|
||||
return BaseItemResponse
|
||||
.fromJson(json.decode(response.body))
|
||||
.data;
|
||||
final result = BaseItemResponse.fromJson(json.decode(response.body));
|
||||
|
||||
if (result.error.message != null) {
|
||||
throw(result.error.message);
|
||||
} else {
|
||||
return result.data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<List<dynamic>> fetchList(String url, String token) async {
|
||||
final http.Response response = await sendGetRequest(url, token);
|
||||
return BaseListResponse
|
||||
.fromJson(json.decode(response.body))
|
||||
.data
|
||||
.toList();
|
||||
}
|
||||
final result = BaseListResponse.fromJson(json.decode(response.body));
|
||||
|
||||
if (result.error.message != null) {
|
||||
throw(result.error.message);
|
||||
} else {
|
||||
return result.data.toList();
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<dynamic>> postList(String url, String token, var data) async {
|
||||
final http.Response response = await sendPostRequest(url, token, data);
|
||||
return BaseListResponse
|
||||
.fromJson(json.decode(response.body))
|
||||
.data
|
||||
.toList();
|
||||
final result = BaseListResponse.fromJson(json.decode(response.body));
|
||||
|
||||
if (result.error.message != null) {
|
||||
throw(result.error.message);
|
||||
} else {
|
||||
return result.data.toList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import 'package:invoiceninja/redux/app/app_state.dart';
|
|||
import 'package:invoiceninja/data/models/models.dart';
|
||||
|
||||
class UserLoginRequest {
|
||||
final dynamic context;
|
||||
final BuildContext context;
|
||||
final String email;
|
||||
final String password;
|
||||
final String url;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:invoiceninja/redux/auth/auth_actions.dart';
|
||||
|
|
@ -53,8 +54,18 @@ Middleware<AppState> _createLoginRequest(AuthRepository repository) {
|
|||
|
||||
Navigator.of(action.context).pushNamed(AppRoutes.dashboard);
|
||||
}
|
||||
).catchError((error) => store.dispatch(UserLoginFailure(error)));
|
||||
).catchError((error) {
|
||||
store.dispatch(UserLoginFailure(null));
|
||||
|
||||
final snackBar = new SnackBar(
|
||||
duration: Duration(seconds: 3),
|
||||
content: new Text('Error: ' + error.toString()),
|
||||
);
|
||||
|
||||
Scaffold.of(action.context).showSnackBar(snackBar);
|
||||
});
|
||||
|
||||
next(action);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,69 +47,68 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StoreConnector<AppState, dynamic>(
|
||||
converter: (Store<AppState> store) {
|
||||
return (BuildContext context, String email, String password, String url) {
|
||||
store.dispatch(UserLoginRequest(context, email, password, url));
|
||||
};
|
||||
}, builder: (BuildContext context, loginAction) {
|
||||
return Scaffold(
|
||||
return Scaffold(
|
||||
body: Form(
|
||||
key: _formKey,
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.only(left: 24.0, right: 24.0, top: 40.0),
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20.0, bottom: 20.0),
|
||||
child: new Image.asset('assets/images/logo.png', width: 100.0, height: 100.0),
|
||||
),
|
||||
TextFormField(
|
||||
controller: _emailTextController,
|
||||
decoration: InputDecoration(labelText: 'Email'),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
validator: (val) =>
|
||||
val.isEmpty ? 'Please enter your email.' : null,
|
||||
onSaved: (val) => _email = val,
|
||||
),
|
||||
TextFormField(
|
||||
controller: _passwordTextController,
|
||||
decoration: InputDecoration(labelText: 'Password'),
|
||||
validator: (val) =>
|
||||
val.isEmpty ? 'Please enter your password.' : null,
|
||||
onSaved: (val) => _password = val,
|
||||
obscureText: true,
|
||||
),
|
||||
TextFormField(
|
||||
controller: _urlTextController,
|
||||
decoration: InputDecoration(labelText: 'URL'),
|
||||
validator: (val) =>
|
||||
val.isEmpty ? 'Please enter your URL.' : null,
|
||||
onSaved: (val) => _url = val,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: Material(
|
||||
shadowColor: Colors.lightBlueAccent.shade100,
|
||||
elevation: 5.0,
|
||||
child: MaterialButton(
|
||||
minWidth: 200.0,
|
||||
height: 42.0,
|
||||
onPressed: () {
|
||||
_submit();
|
||||
loginAction(context, _email, _password, _url);
|
||||
//Navigator.of(context).pushNamed(HomeScreen.tag);
|
||||
},
|
||||
color: Colors.lightBlueAccent,
|
||||
child:
|
||||
Text('LOGIN', style: TextStyle(color: Colors.white)),
|
||||
),
|
||||
key: _formKey,
|
||||
child:
|
||||
StoreConnector<AppState, dynamic>(converter: (Store<AppState> store) {
|
||||
return (BuildContext context, String email, String password,
|
||||
String url) {
|
||||
store.dispatch(UserLoginRequest(context, email, password, url));
|
||||
};
|
||||
}, builder: (BuildContext context, loginAction) {
|
||||
return ListView(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.only(left: 24.0, right: 24.0, top: 40.0),
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20.0, bottom: 20.0),
|
||||
child: new Image.asset('assets/images/logo.png',
|
||||
width: 100.0, height: 100.0),
|
||||
),
|
||||
TextFormField(
|
||||
controller: _emailTextController,
|
||||
decoration: InputDecoration(labelText: 'Email'),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
validator: (val) =>
|
||||
val.isEmpty ? 'Please enter your email.' : null,
|
||||
onSaved: (val) => _email = val,
|
||||
),
|
||||
TextFormField(
|
||||
controller: _passwordTextController,
|
||||
decoration: InputDecoration(labelText: 'Password'),
|
||||
validator: (val) =>
|
||||
val.isEmpty ? 'Please enter your password.' : null,
|
||||
onSaved: (val) => _password = val,
|
||||
obscureText: true,
|
||||
),
|
||||
TextFormField(
|
||||
controller: _urlTextController,
|
||||
decoration: InputDecoration(labelText: 'URL'),
|
||||
validator: (val) => val.isEmpty ? 'Please enter your URL.' : null,
|
||||
onSaved: (val) => _url = val,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: Material(
|
||||
shadowColor: Colors.lightBlueAccent.shade100,
|
||||
elevation: 5.0,
|
||||
child: MaterialButton(
|
||||
minWidth: 200.0,
|
||||
height: 42.0,
|
||||
onPressed: () {
|
||||
_submit();
|
||||
loginAction(context, _email, _password, _url);
|
||||
//Navigator.of(context).pushNamed(HomeScreen.tag);
|
||||
},
|
||||
color: Colors.lightBlueAccent,
|
||||
child: Text('LOGIN', style: TextStyle(color: Colors.white)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue