From 8c718e93207abebae3e06fd189b6c2da2cce4763 Mon Sep 17 00:00:00 2001 From: Priggelpitt Date: Tue, 12 Nov 2019 14:13:42 -0600 Subject: [PATCH 1/6] First post-request for new nesting boxes --- .../repositories/nestingboxes_repository.dart | 12 ++++++++ .../nestingboxes_api_service.chopper.dart | 12 ++++++++ .../nestingboxes_api_service.dart | 6 ++++ lib/model/nestingbox.dart | 2 +- lib/model/nestingbox.g.dart | 6 ++-- lib/model/user.dart | 2 +- lib/model/user.g.dart | 25 +++++++++++----- lib/screens/boxinfo_screen.dart | 4 ++- pubspec.lock | 7 +++++ pubspec.yaml | 1 + test/api_test.dart | 30 +++++++++++++++++++ 11 files changed, 93 insertions(+), 14 deletions(-) diff --git a/lib/backend/repositories/nestingboxes_repository.dart b/lib/backend/repositories/nestingboxes_repository.dart index b63d42e6..ce601ec7 100644 --- a/lib/backend/repositories/nestingboxes_repository.dart +++ b/lib/backend/repositories/nestingboxes_repository.dart @@ -107,4 +107,16 @@ class NestingBoxesRepository { return null; } } + + Future addNewNestingBox(NestingBox nestingBox) async { + NestingBoxesApiService _nestingBoxesApi = + NestingBoxesApiService.create(_authBloc.domain); + var nestingBoxString = json.encode(nestingBox); + print(nestingBoxString); + final response = await _nestingBoxesApi.postNewNestingBox( + nestingBoxString, _authBloc.auth); + print(response.statusCode); + print(response.body); + return response.statusCode; + } } diff --git a/lib/backend/services/nestingboxes/nestingboxes_api_service.chopper.dart b/lib/backend/services/nestingboxes/nestingboxes_api_service.chopper.dart index 41d617e7..971ae363 100644 --- a/lib/backend/services/nestingboxes/nestingboxes_api_service.chopper.dart +++ b/lib/backend/services/nestingboxes/nestingboxes_api_service.chopper.dart @@ -57,4 +57,16 @@ class _$NestingBoxesApiService extends NestingBoxesApiService { final $request = Request('GET', $url, client.baseUrl, headers: $headers); return client.send($request); } + + Future postNewNestingBox(String nestingBox, String authHeader) { + final $url = '/nesting-boxes'; + final $headers = { + 'Authorization': authHeader, + 'Content-Type': 'application/json' + }; + final $body = nestingBox; + final $request = + Request('POST', $url, client.baseUrl, body: $body, headers: $headers); + return client.send($request); + } } diff --git a/lib/backend/services/nestingboxes/nestingboxes_api_service.dart b/lib/backend/services/nestingboxes/nestingboxes_api_service.dart index ad55c490..e443294d 100644 --- a/lib/backend/services/nestingboxes/nestingboxes_api_service.dart +++ b/lib/backend/services/nestingboxes/nestingboxes_api_service.dart @@ -41,6 +41,12 @@ abstract class NestingBoxesApiService extends ChopperService { @Header('Authorization') String authHeader, ]); + @Post(headers: {'Content-Type': 'application/json'}) + Future postNewNestingBox( + @Body() String nestingBox, + @Header('Authorization') String authHeader, + ); + static NestingBoxesApiService create(String url) { final client = ChopperClient( baseUrl: 'https://$url/api/v1', diff --git a/lib/model/nestingbox.dart b/lib/model/nestingbox.dart index aaee8e4c..dc3e2764 100644 --- a/lib/model/nestingbox.dart +++ b/lib/model/nestingbox.dart @@ -6,7 +6,7 @@ import 'package:nesteo_app/model/user.dart'; part 'nestingbox.g.dart'; -@JsonSerializable(nullable: true) +@JsonSerializable(nullable: true, explicitToJson: true) class NestingBox extends Equatable { final String id; final Region region; diff --git a/lib/model/nestingbox.g.dart b/lib/model/nestingbox.g.dart index 49a37c19..7fe50984 100644 --- a/lib/model/nestingbox.g.dart +++ b/lib/model/nestingbox.g.dart @@ -40,14 +40,14 @@ NestingBox _$NestingBoxFromJson(Map json) { Map _$NestingBoxToJson(NestingBox instance) => { 'id': instance.id, - 'region': instance.region, + 'region': instance.region?.toJson(), 'oldId': instance.oldId, 'foreignId': instance.foreignId, 'coordinateLongitude': instance.coordinateLongitude, 'coordinateLatitude': instance.coordinateLatitude, 'hangUpDate': instance.hangUpDate?.toIso8601String(), - 'hangUpUser': instance.hangUpUser, - 'owner': instance.owner, + 'hangUpUser': instance.hangUpUser?.toJson(), + 'owner': instance.owner?.toJson(), 'material': instance.material, 'holeSize': instance.holeSize, 'imageFileName': instance.imageFileName, diff --git a/lib/model/user.dart b/lib/model/user.dart index aed91436..b22e0f46 100644 --- a/lib/model/user.dart +++ b/lib/model/user.dart @@ -3,7 +3,7 @@ import 'package:json_annotation/json_annotation.dart'; part 'user.g.dart'; -@JsonSerializable(nullable: false) +@JsonSerializable(nullable: true, includeIfNull: false) class User extends Equatable { final String id; final String userName; diff --git a/lib/model/user.g.dart b/lib/model/user.g.dart index f6139064..15363402 100644 --- a/lib/model/user.g.dart +++ b/lib/model/user.g.dart @@ -17,11 +17,20 @@ User _$UserFromJson(Map json) { ); } -Map _$UserToJson(User instance) => { - 'id': instance.id, - 'userName': instance.userName, - 'firstName': instance.firstName, - 'lastName': instance.lastName, - 'email': instance.email, - 'phoneNumber': instance.phoneNumber, - }; +Map _$UserToJson(User instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('id', instance.id); + writeNotNull('userName', instance.userName); + writeNotNull('firstName', instance.firstName); + writeNotNull('lastName', instance.lastName); + writeNotNull('email', instance.email); + writeNotNull('phoneNumber', instance.phoneNumber); + return val; +} diff --git a/lib/screens/boxinfo_screen.dart b/lib/screens/boxinfo_screen.dart index 547b098d..382ec264 100644 --- a/lib/screens/boxinfo_screen.dart +++ b/lib/screens/boxinfo_screen.dart @@ -143,7 +143,9 @@ class BoxInfoScreen extends NesteoFullScreen { Table _informationTable = Table( children: [ _hangUpUserRow, - _hangUpDateRow, + boxDataBloc.nestingBox.hangUpDate != null + ? _hangUpDateRow + : null, _inspectionCountRow, _materialRow, _commentRow, diff --git a/pubspec.lock b/pubspec.lock index bf68f1ce..7f678439 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -190,6 +190,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.8" + english_words: + dependency: "direct main" + description: + name: english_words + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.5" equatable: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 4a3a613c..c43f62c9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -29,6 +29,7 @@ dependencies: datetime_picker_formfield: ^0.1.8 flutter_secure_storage: ^3.3.1+1 json_annotation: ^3.0.0 + english_words: dev_dependencies: mockito: ^4.1.1 flutter_launcher_icons: ^0.7.3 diff --git a/test/api_test.dart b/test/api_test.dart index c44ccc3a..59670de8 100644 --- a/test/api_test.dart +++ b/test/api_test.dart @@ -1,5 +1,7 @@ import 'dart:convert'; +import 'dart:math'; +import 'package:english_words/english_words.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:nesteo_app/backend/repositories/auth_repository.dart'; import 'package:nesteo_app/backend/repositories/inspections_repository.dart'; @@ -186,6 +188,34 @@ void main() { expect(inspections[0].containsEggs == null, true); } }); + + test('Test POST /nesting-boxes', () async { + String regionWord = WordPair.random().asPascalCase; + String ownerWord = WordPair.random().asPascalCase; + final newNestingBox = NestingBox( + hangUpUser: User( + id: "f80d95df-9e94-4646-9cbb-b4c7be679ce1", + userName: "Admin", + lastName: "Admin", + firstName: "Default", + email: null, + phoneNumber: null, + ), + coordinateLatitude: 42.963710 + Random().nextDouble(), + hangUpDate: DateTime.now(), + region: Region( + id: null, name: regionWord, nestingBoxIdPrefix: regionWord[0]), + owner: Owner(id: null, name: ownerWord), + coordinateLongitude: -85.888412 + Random().nextDouble(), + material: "TreatedWood", + holeSize: "Small", + comment: "Prost!", + lastUpdated: "2017-12-15T11:58:53.326536", + ); + + int response = await nestingBoxRepo.addNewNestingBox(newNestingBox); + expect(response == 201, true); + }); }); group('Inspection API tests', () { InspectionsRepository inspectionRepo; From ba3a1f2175756b25c1c138e8b8c28019ab46f497 Mon Sep 17 00:00:00 2001 From: Priggelpitt Date: Wed, 13 Nov 2019 10:32:26 -0500 Subject: [PATCH 2/6] Created boxsender bloc --- lib/blocs/boxsender_bloc/boxsender.dart | 3 +++ lib/blocs/boxsender_bloc/boxsender_bloc.dart | 26 +++++++++++++++++++ lib/blocs/boxsender_bloc/boxsender_event.dart | 15 +++++++++++ lib/blocs/boxsender_bloc/boxsender_state.dart | 10 +++++++ lib/screens/boxinfo_screen.dart | 13 +++++----- test/api_test.dart | 1 - 6 files changed, 60 insertions(+), 8 deletions(-) create mode 100644 lib/blocs/boxsender_bloc/boxsender.dart create mode 100644 lib/blocs/boxsender_bloc/boxsender_bloc.dart create mode 100644 lib/blocs/boxsender_bloc/boxsender_event.dart create mode 100644 lib/blocs/boxsender_bloc/boxsender_state.dart diff --git a/lib/blocs/boxsender_bloc/boxsender.dart b/lib/blocs/boxsender_bloc/boxsender.dart new file mode 100644 index 00000000..b8b77906 --- /dev/null +++ b/lib/blocs/boxsender_bloc/boxsender.dart @@ -0,0 +1,3 @@ +export 'boxsender_bloc.dart'; +export 'boxsender_event.dart'; +export 'boxsender_state.dart'; diff --git a/lib/blocs/boxsender_bloc/boxsender_bloc.dart b/lib/blocs/boxsender_bloc/boxsender_bloc.dart new file mode 100644 index 00000000..de918ef4 --- /dev/null +++ b/lib/blocs/boxsender_bloc/boxsender_bloc.dart @@ -0,0 +1,26 @@ +import 'dart:async'; +import 'package:bloc/bloc.dart'; +import 'package:nesteo_app/backend/repositories/auth_repository.dart'; +import 'package:nesteo_app/backend/repositories/nestingboxes_repository.dart'; +import 'package:nesteo_app/model/nestingbox.dart'; +import 'package:nesteo_app/model/user.dart'; +import './boxsender.dart'; + +class BoxSenderBloc extends Bloc { + @override + BoxSenderState get initialState => InitialBoxSenderState(); + + @override + Stream mapEventToState( + BoxSenderEvent event, + ) async* { + if (event is SendBoxEvent) { + var boxRepo = NestingBoxesRepository(event.authBloc); + var authRepo = AuthRepository(event.authBloc); + User user = await authRepo.getAuth(); + boxRepo.addNewNestingBox(NestingBox( + hangUpUser: User(), + )); + } + } +} diff --git a/lib/blocs/boxsender_bloc/boxsender_event.dart b/lib/blocs/boxsender_bloc/boxsender_event.dart new file mode 100644 index 00000000..590a68ac --- /dev/null +++ b/lib/blocs/boxsender_bloc/boxsender_event.dart @@ -0,0 +1,15 @@ +import 'package:equatable/equatable.dart'; +import 'package:nesteo_app/blocs/authentication_bloc/authentication_bloc.dart'; + +abstract class BoxSenderEvent extends Equatable { + const BoxSenderEvent(); +} + +class SendBoxEvent extends BoxSenderEvent { + final AuthenticationBloc authBloc; + + SendBoxEvent({this.authBloc}) : super(); + + @override + List get props => null; +} diff --git a/lib/blocs/boxsender_bloc/boxsender_state.dart b/lib/blocs/boxsender_bloc/boxsender_state.dart new file mode 100644 index 00000000..3adce99e --- /dev/null +++ b/lib/blocs/boxsender_bloc/boxsender_state.dart @@ -0,0 +1,10 @@ +import 'package:equatable/equatable.dart'; + +abstract class BoxSenderState extends Equatable { + const BoxSenderState(); +} + +class InitialBoxSenderState extends BoxSenderState { + @override + List get props => []; +} diff --git a/lib/screens/boxinfo_screen.dart b/lib/screens/boxinfo_screen.dart index 8fbe9e94..49bde335 100644 --- a/lib/screens/boxinfo_screen.dart +++ b/lib/screens/boxinfo_screen.dart @@ -38,10 +38,11 @@ class BoxInfoScreen extends NesteoFullScreen { if (state is BoxReadyState) { NestingBox nestingBox = boxDataBloc.nestingBox; int daysSinceLastInspection = 1; - if (nestingBox.lastInspected == null) { + if (nestingBox.lastInspected == null && + nestingBox.hangUpDate != null) { daysSinceLastInspection = DateTime.now().difference(nestingBox.hangUpDate).inDays; - } else { + } else if (nestingBox.lastInspected != null) { daysSinceLastInspection = DateTime.now().difference(nestingBox.lastInspected).inDays; } @@ -76,7 +77,7 @@ class BoxInfoScreen extends NesteoFullScreen { TableCell( child: ListTile( title: Text( - "${nestingBox.hangUpUser.firstName} ${nestingBox.hangUpUser.lastName}"), + "${nestingBox?.hangUpUser?.firstName} ${nestingBox?.hangUpUser?.lastName}"), ), ), ], @@ -93,7 +94,7 @@ class BoxInfoScreen extends NesteoFullScreen { TableCell( child: ListTile( title: Text( - "${nestingBox.hangUpDate.month}/${nestingBox.hangUpDate.day}/${nestingBox.hangUpDate.year}"), + "${nestingBox?.hangUpDate?.month}/${nestingBox?.hangUpDate?.day}/${nestingBox?.hangUpDate?.year}"), ), ), ], @@ -148,9 +149,7 @@ class BoxInfoScreen extends NesteoFullScreen { Table _informationTable = Table( children: [ _hangUpUserRow, - boxDataBloc.nestingBox.hangUpDate != null - ? _hangUpDateRow - : null, + _hangUpDateRow, _inspectionCountRow, _materialRow, _commentRow, diff --git a/test/api_test.dart b/test/api_test.dart index 59670de8..c7630355 100644 --- a/test/api_test.dart +++ b/test/api_test.dart @@ -210,7 +210,6 @@ void main() { material: "TreatedWood", holeSize: "Small", comment: "Prost!", - lastUpdated: "2017-12-15T11:58:53.326536", ); int response = await nestingBoxRepo.addNewNestingBox(newNestingBox); From 9ea180aa682f81a7786cc91ceef1135df62997fe Mon Sep 17 00:00:00 2001 From: Priggelpitt Date: Wed, 13 Nov 2019 11:33:02 -0500 Subject: [PATCH 3/6] Added states for box sending --- lib/blocs/boxsender_bloc/boxsender_bloc.dart | 36 ++++++++++++++++--- lib/blocs/boxsender_bloc/boxsender_event.dart | 25 ++++++++++++- lib/blocs/boxsender_bloc/boxsender_state.dart | 20 ++++++++++- lib/model/inspection.dart | 6 ++-- lib/model/inspection.g.dart | 4 +-- lib/model/nestingbox.dart | 6 ++-- lib/model/nestingbox.g.dart | 4 +-- lib/screens/newbox_screen.dart | 4 +-- test/api_test.dart | 12 ++----- 9 files changed, 89 insertions(+), 28 deletions(-) diff --git a/lib/blocs/boxsender_bloc/boxsender_bloc.dart b/lib/blocs/boxsender_bloc/boxsender_bloc.dart index de918ef4..b243175d 100644 --- a/lib/blocs/boxsender_bloc/boxsender_bloc.dart +++ b/lib/blocs/boxsender_bloc/boxsender_bloc.dart @@ -3,24 +3,50 @@ import 'package:bloc/bloc.dart'; import 'package:nesteo_app/backend/repositories/auth_repository.dart'; import 'package:nesteo_app/backend/repositories/nestingboxes_repository.dart'; import 'package:nesteo_app/model/nestingbox.dart'; +import 'package:nesteo_app/model/owner.dart'; +import 'package:nesteo_app/model/region.dart'; import 'package:nesteo_app/model/user.dart'; import './boxsender.dart'; class BoxSenderBloc extends Bloc { @override - BoxSenderState get initialState => InitialBoxSenderState(); + BoxSenderState get initialState => WaitingForSend(); @override Stream mapEventToState( BoxSenderEvent event, ) async* { - if (event is SendBoxEvent) { + if (event is SendBoxEvent && state is WaitingForSend) { + yield SendingBoxState(); var boxRepo = NestingBoxesRepository(event.authBloc); var authRepo = AuthRepository(event.authBloc); User user = await authRepo.getAuth(); - boxRepo.addNewNestingBox(NestingBox( - hangUpUser: User(), - )); + + int response = await boxRepo.addNewNestingBox( + NestingBox( + hangUpUser: user, + coordinateLatitude: event.coordinates.latitude, + coordinateLongitude: event.coordinates.longitude, + hangUpDate: event.hangUpDate, + region: Region( + id: null, + name: event.regionString, + nestingBoxIdPrefix: event.regionIdPrefixString, + ), + owner: Owner(id: null, name: event.ownerString), + material: event.material, + holeSize: event.holeSize, + comment: event.comment, + foreignId: event.foreignId, + oldId: event.oldId, + ), + ); + + if (response == 201) { + yield BoxSentState(); + } else { + yield SendErrorState(); + } } } } diff --git a/lib/blocs/boxsender_bloc/boxsender_event.dart b/lib/blocs/boxsender_bloc/boxsender_event.dart index 590a68ac..a3890323 100644 --- a/lib/blocs/boxsender_bloc/boxsender_event.dart +++ b/lib/blocs/boxsender_bloc/boxsender_event.dart @@ -1,4 +1,5 @@ import 'package:equatable/equatable.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:nesteo_app/blocs/authentication_bloc/authentication_bloc.dart'; abstract class BoxSenderEvent extends Equatable { @@ -7,8 +8,30 @@ abstract class BoxSenderEvent extends Equatable { class SendBoxEvent extends BoxSenderEvent { final AuthenticationBloc authBloc; + final LatLng coordinates; + final DateTime hangUpDate; + final String regionString; + final String regionIdPrefixString; + final String ownerString; + final String material; + final String holeSize; + final String comment; + final String oldId; + final String foreignId; - SendBoxEvent({this.authBloc}) : super(); + SendBoxEvent({ + this.authBloc, + this.coordinates, + this.hangUpDate, + this.regionString, + this.regionIdPrefixString, + this.ownerString, + this.material, + this.holeSize, + this.comment, + this.oldId, + this.foreignId, + }) : super(); @override List get props => null; diff --git a/lib/blocs/boxsender_bloc/boxsender_state.dart b/lib/blocs/boxsender_bloc/boxsender_state.dart index 3adce99e..c507f49e 100644 --- a/lib/blocs/boxsender_bloc/boxsender_state.dart +++ b/lib/blocs/boxsender_bloc/boxsender_state.dart @@ -4,7 +4,25 @@ abstract class BoxSenderState extends Equatable { const BoxSenderState(); } -class InitialBoxSenderState extends BoxSenderState { +class WaitingForSend extends BoxSenderState { @override List get props => []; } + +class SendingBoxState extends BoxSenderState { + @override + // TODO: implement props + List get props => null; +} + +class BoxSentState extends BoxSenderState { + @override + // TODO: implement props + List get props => null; +} + +class SendErrorState extends BoxSenderState { + @override + // TODO: implement props + List get props => null; +} diff --git a/lib/model/inspection.dart b/lib/model/inspection.dart index f538e86a..2b6cd335 100644 --- a/lib/model/inspection.dart +++ b/lib/model/inspection.dart @@ -24,7 +24,7 @@ class Inspection extends Equatable { final String femaleParentBirdDiscovery; final String maleParentBirdDiscovery; final Species species; - final String imageFileName; + final bool hasImage; final String comment; final String lastUpdated; final String nestingBoxId; @@ -46,7 +46,7 @@ class Inspection extends Equatable { this.femaleParentBirdDiscovery, this.maleParentBirdDiscovery, this.species, - this.imageFileName, + this.hasImage, this.comment, this.lastUpdated, this.nestingBoxId, @@ -70,7 +70,7 @@ class Inspection extends Equatable { femaleParentBirdDiscovery, maleParentBirdDiscovery, species, - imageFileName, + hasImage, comment, lastUpdated, nestingBoxId, diff --git a/lib/model/inspection.g.dart b/lib/model/inspection.g.dart index 41e7337a..7c5957d0 100644 --- a/lib/model/inspection.g.dart +++ b/lib/model/inspection.g.dart @@ -32,7 +32,7 @@ Inspection _$InspectionFromJson(Map json) { species: json['species'] == null ? null : Species.fromJson(json['species'] as Map), - imageFileName: json['imageFileName'] as String, + hasImage: json['hasImage'] as bool, comment: json['comment'] as String, lastUpdated: json['lastUpdated'] as String, nestingBoxId: json['nestingBoxId'] as String, @@ -57,7 +57,7 @@ Map _$InspectionToJson(Inspection instance) => 'femaleParentBirdDiscovery': instance.femaleParentBirdDiscovery, 'maleParentBirdDiscovery': instance.maleParentBirdDiscovery, 'species': instance.species, - 'imageFileName': instance.imageFileName, + 'hasImage': instance.hasImage, 'comment': instance.comment, 'lastUpdated': instance.lastUpdated, 'nestingBoxId': instance.nestingBoxId, diff --git a/lib/model/nestingbox.dart b/lib/model/nestingbox.dart index dc3e2764..fd30c2f2 100644 --- a/lib/model/nestingbox.dart +++ b/lib/model/nestingbox.dart @@ -19,7 +19,7 @@ class NestingBox extends Equatable { final Owner owner; final String material; final String holeSize; - final String imageFileName; + final bool hasImage; final String comment; final String lastUpdated; final int inspectionsCount; @@ -37,7 +37,7 @@ class NestingBox extends Equatable { this.owner, this.material, this.holeSize, - this.imageFileName, + this.hasImage, this.comment, this.lastUpdated, this.inspectionsCount, @@ -57,7 +57,7 @@ class NestingBox extends Equatable { owner, material, holeSize, - imageFileName, + hasImage, comment, lastUpdated, inspectionsCount, diff --git a/lib/model/nestingbox.g.dart b/lib/model/nestingbox.g.dart index 7fe50984..be1a40fa 100644 --- a/lib/model/nestingbox.g.dart +++ b/lib/model/nestingbox.g.dart @@ -27,7 +27,7 @@ NestingBox _$NestingBoxFromJson(Map json) { : Owner.fromJson(json['owner'] as Map), material: json['material'] as String, holeSize: json['holeSize'] as String, - imageFileName: json['imageFileName'] as String, + hasImage: json['hasImage'] as bool, comment: json['comment'] as String, lastUpdated: json['lastUpdated'] as String, inspectionsCount: json['inspectionsCount'] as int, @@ -50,7 +50,7 @@ Map _$NestingBoxToJson(NestingBox instance) => 'owner': instance.owner?.toJson(), 'material': instance.material, 'holeSize': instance.holeSize, - 'imageFileName': instance.imageFileName, + 'hasImage': instance.hasImage, 'comment': instance.comment, 'lastUpdated': instance.lastUpdated, 'inspectionsCount': instance.inspectionsCount, diff --git a/lib/screens/newbox_screen.dart b/lib/screens/newbox_screen.dart index 7c882d17..4d8bb5fe 100644 --- a/lib/screens/newbox_screen.dart +++ b/lib/screens/newbox_screen.dart @@ -37,7 +37,7 @@ class NewBoxData extends StatefulWidget { class _NewBoxDataState extends State { String id; String oldId; - DateTime hangDate; + DateTime hangUpDate; String material; String _dropDownMaterial; @@ -112,7 +112,7 @@ class _NewBoxDataState extends State { initialDate: DateTime.now(), editable: false, onChanged: (dt) { - setState(() => hangDate = dt); + setState(() => hangUpDate = dt); }, ), ))), diff --git a/test/api_test.dart b/test/api_test.dart index c7630355..8f66580c 100644 --- a/test/api_test.dart +++ b/test/api_test.dart @@ -192,21 +192,15 @@ void main() { test('Test POST /nesting-boxes', () async { String regionWord = WordPair.random().asPascalCase; String ownerWord = WordPair.random().asPascalCase; + User user = await authBloc.authRepository.getAuth(); final newNestingBox = NestingBox( - hangUpUser: User( - id: "f80d95df-9e94-4646-9cbb-b4c7be679ce1", - userName: "Admin", - lastName: "Admin", - firstName: "Default", - email: null, - phoneNumber: null, - ), + hangUpUser: user, coordinateLatitude: 42.963710 + Random().nextDouble(), + coordinateLongitude: -85.888412 + Random().nextDouble(), hangUpDate: DateTime.now(), region: Region( id: null, name: regionWord, nestingBoxIdPrefix: regionWord[0]), owner: Owner(id: null, name: ownerWord), - coordinateLongitude: -85.888412 + Random().nextDouble(), material: "TreatedWood", holeSize: "Small", comment: "Prost!", From 1fa978c1a9fdcc7ccc98474f00f8b3f2644ae7bc Mon Sep 17 00:00:00 2001 From: Priggelpitt Date: Wed, 13 Nov 2019 12:43:54 -0500 Subject: [PATCH 4/6] Added send events to new box screen --- lib/blocs/boxsender_bloc/boxsender_bloc.dart | 1 + lib/screens/newbox_screen.dart | 533 +++++++++++-------- 2 files changed, 299 insertions(+), 235 deletions(-) diff --git a/lib/blocs/boxsender_bloc/boxsender_bloc.dart b/lib/blocs/boxsender_bloc/boxsender_bloc.dart index b243175d..b3d79095 100644 --- a/lib/blocs/boxsender_bloc/boxsender_bloc.dart +++ b/lib/blocs/boxsender_bloc/boxsender_bloc.dart @@ -44,6 +44,7 @@ class BoxSenderBloc extends Bloc { if (response == 201) { yield BoxSentState(); + yield WaitingForSend(); } else { yield SendErrorState(); } diff --git a/lib/screens/newbox_screen.dart b/lib/screens/newbox_screen.dart index 24683ec8..2214c802 100644 --- a/lib/screens/newbox_screen.dart +++ b/lib/screens/newbox_screen.dart @@ -2,8 +2,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:intl/intl.dart'; +import 'package:intl/number_symbols_data.dart'; +import 'package:nesteo_app/blocs/authentication_bloc/authentication_bloc.dart'; import 'package:nesteo_app/blocs/boxdata_bloc/boxdata.dart'; +import 'package:nesteo_app/blocs/boxsender_bloc/boxsender.dart'; import 'package:nesteo_app/blocs/pagecontrol_bloc/pagecontrol.dart'; import 'package:nesteo_app/screens/nesteo_screen.dart'; import 'package:nesteo_app/generated/locale_base.dart'; @@ -42,7 +47,8 @@ class _NewBoxDataState extends State { String id; String oldId; DateTime hangUpDate; - String material; + + LatLng position; String _dropDownMaterial; double _slideHoleSize = 1; @@ -51,254 +57,311 @@ class _NewBoxDataState extends State { final loc = Localizations.of(context, LocaleBase); return GestureDetector( - child: Container( - child: SingleChildScrollView( - child: Column(children: [ - Card( - child: ListTile( - title: Row( - children: [ - Icon(FontAwesomeIcons.hashtag), - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("IDs")) - ], - ), - subtitle: Column( - children: [ - Container( - padding: EdgeInsets.all(7), - child: ClipRRect( - borderRadius: BorderRadius.circular(10), - child: TextFormField( - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "ID - optional", - filled: true, - fillColor: Colors.white, + child: BlocProvider( + builder: (BuildContext context) => BoxSenderBloc(), + child: BlocBuilder( + builder: (context, state) { + if (state is WaitingForSend) { + return Container( + child: SingleChildScrollView( + child: Column( + children: [ + Card( + child: ListTile( + title: Row( + children: [ + Icon(FontAwesomeIcons.hashtag), + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Text("IDs")) + ], + ), + subtitle: Column( + children: [ + Container( + padding: EdgeInsets.all(7), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: TextFormField( + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: "ID - optional", + filled: true, + fillColor: Colors.white, + ), + ), + ), + ), + Container( + padding: EdgeInsets.all(7), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: TextFormField( + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: "old ID - optional", + filled: true, + fillColor: Colors.white, + ), + ), + ), + ), + Container( + padding: EdgeInsets.all(7), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: TextFormField( + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: "foreign ID - optional", + filled: true, + fillColor: Colors.white, + ), + ), + ), + ), + ], ), ), ), - ), - Container( - padding: EdgeInsets.all(7), - child: ClipRRect( - borderRadius: BorderRadius.circular(10), - child: TextFormField( - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "old ID - optional", - filled: true, - fillColor: Colors.white, + Card( + child: ListTile( + title: Row(children: [ + Icon(FontAwesomeIcons.calendarAlt), + Padding( + padding: + EdgeInsets.fromLTRB(0, 20, 10, 10)), + Text("Date"), + ]), + subtitle: Padding( + padding: EdgeInsets.fromLTRB(0, 10, 0, 10), + child: DateTimePickerFormField( + decoration: InputDecoration( + labelText: "select Day", + filled: true, + fillColor: Colors.white, + ), + inputType: InputType.date, + format: DateFormat("yyyy-MM-dd"), + initialDate: DateTime.now(), + editable: false, + onChanged: (dt) { + setState(() => hangUpDate = dt); + }, + ), + ))), + Card( + child: ListTile( + title: Row( + children: [ + Icon(FontAwesomeIcons.box), + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Text("Box")) + ], ), + subtitle: Column(children: [ + Padding( + padding: EdgeInsets.fromLTRB(0, 10, 0, 10), + child: Row( + children: [ + Expanded(child: Text("Material:")), + _createMaterialSelection(context), + ], + )), + Row( + children: [ + Expanded( + child: Text("Hole size:"), + ), + _createHoleSizeSlider() + ], + ) + ]), ), ), - ), - Container( - padding: EdgeInsets.all(7), - child: ClipRRect( - borderRadius: BorderRadius.circular(10), - child: TextFormField( - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "foreign ID - optional", - filled: true, - fillColor: Colors.white, + Card( + child: ListTile( + title: Row( + children: [ + Icon(FontAwesomeIcons.globe), + Padding( + padding: + EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Text("Region")), + ], + ), + subtitle: Column(children: [ + TextFormField( + maxLines: 1, + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: "Region ID", + filled: true, + fillColor: Colors.white, + ), + ), + TextFormField( + maxLines: 1, + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: "Region Name", + filled: true, + fillColor: Colors.white, + ), + ), + ])), + ), + Card( + child: ListTile( + title: Row( + children: [ + Icon(FontAwesomeIcons.globeAmericas), + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Text("Position")), + ], + ), + subtitle: Column( + children: [ + TextFormField( + keyboardType: TextInputType.number, + maxLines: 1, + textAlign: TextAlign.left, + readOnly: true, + decoration: InputDecoration( + labelText: + "Latitude ${(position == null) ? "" : position.latitude}", + filled: true, + fillColor: Colors.white, + ), + ), + TextFormField( + keyboardType: TextInputType.number, + readOnly: true, + maxLines: 1, + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: + "Longitude ${(position == null) ? "" : position.longitude}", + filled: true, + fillColor: Colors.white, + ), + ), + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Row( + children: [ + Padding( + padding: + EdgeInsets.fromLTRB(10, 10, 10, 10), + child: (Text("Add GPS Data"))), + IconButton( + icon: Icon(Icons.gps_fixed), + onPressed: () async { + if (await Geolocator() + .isLocationServiceEnabled()) { + Position currentPosition = + await Geolocator() + .getCurrentPosition( + desiredAccuracy: + LocationAccuracy + .high); + + setState(() { + position = LatLng( + currentPosition.latitude, + currentPosition.longitude); + }); + } + }, + ) + ], + ), + ), + ], ), ), ), - ), - ], - ), - ), - ), - Card( - child: ListTile( - title: Row(children: [ - Icon(FontAwesomeIcons.calendarAlt), - Padding(padding: EdgeInsets.fromLTRB(0, 20, 10, 10)), - Text("Date"), - ]), - subtitle: Padding( - padding: EdgeInsets.fromLTRB(0, 10, 0, 10), - child: DateTimePickerFormField( - decoration: InputDecoration( - labelText: "select Day", - filled: true, - fillColor: Colors.white, + Card( + child: ListTile( + title: Row( + children: [ + Icon(FontAwesomeIcons.userAlt), + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Text("Owner")), + ], + ), + subtitle: TextFormField( + maxLines: 1, + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: "Owner", + filled: true, + fillColor: Colors.white, + ), + ), ), - inputType: InputType.date, - format: DateFormat("yyyy-MM-dd"), - initialDate: DateTime.now(), - editable: false, - onChanged: (dt) { - setState(() => hangUpDate = dt); - }, - ), - ))), - Card( - child: ListTile( - title: Row( - children: [ - Icon(FontAwesomeIcons.box), - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("Box")) - ], - ), - subtitle: Column(children: [ - Padding( - padding: EdgeInsets.fromLTRB(0, 10, 0, 10), - child: Row( - children: [ - Expanded(child: Text("Material:")), - _createMaterialSelection(context), - ], - )), - Row( - children: [ - Expanded( - child: Text("Hole size:"), - ), - _createHoleSizeSlider() - ], - ) - ]), - ), - ), - Card( - child: ListTile( - title: Row( - children: [ - Icon(FontAwesomeIcons.globe), - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("Region")), - ], - ), - subtitle: Column(children: [ - TextFormField( - maxLines: 1, - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "Region ID", - filled: true, - fillColor: Colors.white, - ), - ), - TextFormField( - maxLines: 1, - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "Region Name", - filled: true, - fillColor: Colors.white, - ), - ), - ])), - ), - Card( - child: ListTile( - title: Row( - children: [ - Icon(FontAwesomeIcons.globeAmericas), - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("Position")), - ], - ), - subtitle: Column( - children: [ - TextFormField( - keyboardType: TextInputType.number, - maxLines: 1, - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "Latitude", - filled: true, - fillColor: Colors.white, ), - ), - TextFormField( - keyboardType: TextInputType.number, - maxLines: 1, - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "Longitude", - filled: true, - fillColor: Colors.white, + Card( + child: ListTile( + title: Row( + children: [ + Icon(FontAwesomeIcons.comment), + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Text("Comment")) + ], + ), + subtitle: TextFormField( + maxLines: 3, + textAlign: TextAlign.left, + ), + ), ), - ), - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Row( - children: [ - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: (Text("Add GPS Data"))), - IconButton( - icon: Icon(Icons.gps_fixed), - onPressed: () {}, - ) - ], + RaisedButton( + color: Colors.blue, + onPressed: () { + BlocProvider.of(context).add( + SendBoxEvent( + authBloc: + BlocProvider.of(context), + material: _dropDownMaterial, + hangUpDate: (hangUpDate != null) + ? hangUpDate + : DateTime.now(), + oldId: oldId, + holeSize: getSliderLabel(_slideHoleSize), + comment: null, + coordinates: position, + foreignId: null, + ownerString: null, + regionIdPrefixString: null, + regionString: null, + ), + ); + }, + child: Text( + "Create new Nesting Box", + style: TextStyle( + fontSize: 20, + color: Colors.white, + ), + ), ), - ), - ], - ), - ), - ), - Card( - child: ListTile( - title: Row( - children: [ - Icon(FontAwesomeIcons.userAlt), - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("Owner")), - ], - ), - subtitle: TextFormField( - maxLines: 1, - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "Owner", - filled: true, - fillColor: Colors.white, + ], ), ), - ), - ), - Card( - child: ListTile( - title: Row( - children: [ - Icon(FontAwesomeIcons.comment), - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("Comment")) - ], - ), - subtitle: TextFormField( - maxLines: 3, - textAlign: TextAlign.left, - ), - ), - ), - RaisedButton( - color: Colors.blue, - onPressed: () { - BlocProvider.of(context) - .add(GoToNewBoxConfirmationEvent()); - }, - child: Text( - "Send", - style: TextStyle( - fontSize: 20, - color: Colors.white, - ), - ), - ), - ]), + ); + } + if (state is BoxSentState) { + BlocProvider.of(context) + .add(GoToNewBoxConfirmationEvent()); + BlocProvider.of(context) + .add(GetAllBoxPreviewEvent()); + } + }, ), ), ); @@ -333,7 +396,7 @@ class _NewBoxDataState extends State { ); } - Widget _createRegionIdSlection(BuildContext context) { + Widget _createRegionIdSelection(BuildContext context) { final loc = Localizations.of(context, LocaleBase); return Container( child: DropdownButton( From 431e0df20978bfc30b36e9cc41c291421f434061 Mon Sep 17 00:00:00 2001 From: Priggelpitt Date: Wed, 13 Nov 2019 15:26:03 -0500 Subject: [PATCH 5/6] Added new box screens --- .../repositories/nestingboxes_repository.dart | 9 +- lib/blocs/boxdata_bloc/boxdata_bloc.dart | 2 - lib/blocs/boxdata_bloc/boxdata_event.dart | 10 - lib/blocs/boxsender_bloc/boxsender_bloc.dart | 10 +- lib/blocs/boxsender_bloc/boxsender_event.dart | 5 + lib/main.dart | 4 + lib/screens/newbox_screen.dart | 595 +++++++++--------- lib/screens/newboxconfirmation_screen.dart | 44 +- 8 files changed, 348 insertions(+), 331 deletions(-) diff --git a/lib/backend/repositories/nestingboxes_repository.dart b/lib/backend/repositories/nestingboxes_repository.dart index ce601ec7..6e295fa0 100644 --- a/lib/backend/repositories/nestingboxes_repository.dart +++ b/lib/backend/repositories/nestingboxes_repository.dart @@ -108,7 +108,7 @@ class NestingBoxesRepository { } } - Future addNewNestingBox(NestingBox nestingBox) async { + Future addNewNestingBox(NestingBox nestingBox) async { NestingBoxesApiService _nestingBoxesApi = NestingBoxesApiService.create(_authBloc.domain); var nestingBoxString = json.encode(nestingBox); @@ -117,6 +117,11 @@ class NestingBoxesRepository { nestingBoxString, _authBloc.auth); print(response.statusCode); print(response.body); - return response.statusCode; + if (response.statusCode == 201) { + final Map result = json.decode(response.body); + return NestingBox.fromJson(result); + } else { + return null; + } } } diff --git a/lib/blocs/boxdata_bloc/boxdata_bloc.dart b/lib/blocs/boxdata_bloc/boxdata_bloc.dart index 6f912947..fadd1349 100644 --- a/lib/blocs/boxdata_bloc/boxdata_bloc.dart +++ b/lib/blocs/boxdata_bloc/boxdata_bloc.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nesteo_app/backend/repositories/nestingboxes_repository.dart'; import 'package:nesteo_app/blocs/authentication_bloc/authentication_bloc.dart'; -import 'package:nesteo_app/blocs/pagecontrol_bloc/pagecontrol.dart'; import 'package:nesteo_app/model/nestingbox.dart'; import './boxdata.dart'; @@ -57,7 +56,6 @@ class BoxDataBloc extends Bloc { // print(nestingBoxes.length); yield BoxReadyState(); } - if (event is NewBoxConfirmationEvent) {} if (event is SortBoxEvent) { if (this.state is! InitialBoxDataState) { yield BoxChangingState(); diff --git a/lib/blocs/boxdata_bloc/boxdata_event.dart b/lib/blocs/boxdata_bloc/boxdata_event.dart index 7f30b8cf..4cac33e0 100644 --- a/lib/blocs/boxdata_bloc/boxdata_event.dart +++ b/lib/blocs/boxdata_bloc/boxdata_event.dart @@ -39,13 +39,3 @@ class ChangeSortTypeEvent extends BoxDataEvent { @override List get props => []; } - -class NewBoxEvent extends BoxDataEvent { - @override - List get props => []; -} - -class NewBoxConfirmationEvent extends BoxDataEvent { - @override - List get props => []; -} diff --git a/lib/blocs/boxsender_bloc/boxsender_bloc.dart b/lib/blocs/boxsender_bloc/boxsender_bloc.dart index 7aaa8819..7f5c851a 100644 --- a/lib/blocs/boxsender_bloc/boxsender_bloc.dart +++ b/lib/blocs/boxsender_bloc/boxsender_bloc.dart @@ -9,6 +9,7 @@ import 'package:nesteo_app/model/user.dart'; import './boxsender.dart'; class BoxSenderBloc extends Bloc { + NestingBox lastNewBox; @override BoxSenderState get initialState => WaitingForSend(); @@ -22,7 +23,7 @@ class BoxSenderBloc extends Bloc { var authRepo = AuthRepository(event.authBloc); User user = await authRepo.getAuth(); - int response = await boxRepo.addNewNestingBox( + NestingBox response = await boxRepo.addNewNestingBox( NestingBox( hangUpUser: user, coordinateLatitude: event.coordinates.latitude, @@ -44,12 +45,15 @@ class BoxSenderBloc extends Bloc { ), ); - if (response == 201) { + if (response != null) { + lastNewBox = response; yield BoxSentState(); - yield WaitingForSend(); } else { yield SendErrorState(); } } + if (event is NewBoxDoneEvent) { + yield WaitingForSend(); + } } } diff --git a/lib/blocs/boxsender_bloc/boxsender_event.dart b/lib/blocs/boxsender_bloc/boxsender_event.dart index a3890323..2c45e2ed 100644 --- a/lib/blocs/boxsender_bloc/boxsender_event.dart +++ b/lib/blocs/boxsender_bloc/boxsender_event.dart @@ -6,6 +6,11 @@ abstract class BoxSenderEvent extends Equatable { const BoxSenderEvent(); } +class NewBoxDoneEvent extends BoxSenderEvent { + @override + List get props => null; +} + class SendBoxEvent extends BoxSenderEvent { final AuthenticationBloc authBloc; final LatLng coordinates; diff --git a/lib/main.dart b/lib/main.dart index cb28fc80..47d1aad6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:nesteo_app/blocs/authentication_bloc/authentication_bloc.dart'; import 'package:nesteo_app/blocs/authentication_bloc/authentication_event.dart'; +import 'package:nesteo_app/blocs/boxsender_bloc/boxsender.dart'; import 'package:nesteo_app/blocs/mapcontrol_bloc/mapcontrol.dart'; import 'package:nesteo_app/blocs/pagecontrol_bloc/pagecontrol.dart'; import 'package:nesteo_app/blocs/snackbar_bloc/snackbar.dart'; @@ -50,6 +51,9 @@ class MyApp extends StatelessWidget { builder: (BuildContext context) => InspectionDataBloc( BlocProvider.of(context)), ), + BlocProvider( + builder: (BuildContext context) => BoxSenderBloc(), + ) ], child: BlocBuilder( condition: (previousState, state) => diff --git a/lib/screens/newbox_screen.dart b/lib/screens/newbox_screen.dart index 3c870023..7e29132d 100644 --- a/lib/screens/newbox_screen.dart +++ b/lib/screens/newbox_screen.dart @@ -11,6 +11,7 @@ import 'package:nesteo_app/blocs/pagecontrol_bloc/pagecontrol.dart'; import 'package:nesteo_app/screens/nesteo_screen.dart'; import 'package:nesteo_app/generated/locale_base.dart'; import 'package:datetime_picker_formfield/datetime_picker_formfield.dart'; +import 'package:nesteo_app/screens/newboxconfirmation_screen.dart'; class NewBoxScreen extends NesteoFullScreen { NewBoxScreen(BuildContext context) @@ -42,12 +43,11 @@ class NewBoxData extends StatefulWidget { } class _NewBoxDataState extends State { - DateTime hangUpDate; LatLng position; String _id; String _oldId; String _foreignId; - DateTime _hangDate; + DateTime _hangUpDate; String _regionIdPrefix; String _regionName; String _owner; @@ -59,347 +59,346 @@ class _NewBoxDataState extends State { final loc = Localizations.of(context, LocaleBase); return GestureDetector( - child: BlocProvider( - builder: (BuildContext context) => BoxSenderBloc(), - child: BlocBuilder( - builder: (context, state) { - if (state is WaitingForSend) { - return Container( - child: SingleChildScrollView( - child: Column( - children: [ - Card( - child: ListTile( - title: Row( - children: [ - Icon(FontAwesomeIcons.hashtag), - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("IDs")) - ], - ), - subtitle: Column( - children: [ - Container( - padding: EdgeInsets.all(7), - child: ClipRRect( - borderRadius: BorderRadius.circular(10), - child: TextFormField( - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "ID - optional", - filled: true, - fillColor: Colors.white, - ), - onChanged: (String value) { - setState(() { - _id = value; - }); - }, - ), - ), - ), - Container( - padding: EdgeInsets.all(7), - child: ClipRRect( - borderRadius: BorderRadius.circular(10), - child: TextFormField( - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "old ID - optional", - filled: true, - fillColor: Colors.white, - ), - onChanged: (String value) { - setState(() { - _oldId = value; - }); - }, + child: BlocBuilder( + builder: (context, state) { + if (state is WaitingForSend) { + return Container( + child: SingleChildScrollView( + child: Column( + children: [ + Card( + child: ListTile( + title: Row( + children: [ + Icon(FontAwesomeIcons.hashtag), + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Text("IDs")) + ], + ), + subtitle: Column( + children: [ + Container( + padding: EdgeInsets.all(7), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: TextFormField( + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: "ID - optional", + filled: true, + fillColor: Colors.white, ), + onChanged: (String value) { + setState(() { + _id = value; + }); + }, ), ), - Container( - padding: EdgeInsets.all(7), - child: ClipRRect( - borderRadius: BorderRadius.circular(10), - child: TextFormField( - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "foreign ID - optional", - filled: true, - fillColor: Colors.white, - ), - onChanged: (String value) { - setState(() { - _foreignId = value; - }); - }, + ), + Container( + padding: EdgeInsets.all(7), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: TextFormField( + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: "old ID - optional", + filled: true, + fillColor: Colors.white, ), + onChanged: (String value) { + setState(() { + _oldId = value; + }); + }, ), ), - ], - ), - ), - ), - Card( - child: ListTile( - title: Row(children: [ - Icon(FontAwesomeIcons.calendarAlt), - Padding( - padding: - EdgeInsets.fromLTRB(0, 20, 10, 10)), - Text("Date"), - ]), - subtitle: Padding( - padding: EdgeInsets.fromLTRB(0, 10, 0, 10), - child: DateTimePickerFormField( + ), + Container( + padding: EdgeInsets.all(7), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: TextFormField( + textAlign: TextAlign.left, decoration: InputDecoration( - labelText: "select Day", + labelText: "foreign ID - optional", filled: true, fillColor: Colors.white, ), - inputType: InputType.date, - format: DateFormat("yyyy-MM-dd"), - initialDate: DateTime.now(), - editable: false, - onChanged: (dt) { - setState(() => hangUpDate = dt); + onChanged: (String value) { + setState(() { + _foreignId = value; + }); }, ), - ))), - Card( - child: ListTile( - title: Row( - children: [ - Icon(FontAwesomeIcons.box), - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("Box")) - ], - ), - subtitle: Column(children: [ - Padding( - padding: EdgeInsets.fromLTRB(0, 10, 0, 10), - child: Row( - children: [ - Expanded(child: Text("Material:")), - _createMaterialSelection(context), - ], - )), - Row( - children: [ - Expanded( - child: Text("Hole size:"), - ), - _createHoleSizeSlider() - ], - ) - ]), + ), + ), + ], ), ), - Card( + ), + Card( child: ListTile( - title: Row( - children: [ - Icon(FontAwesomeIcons.globe), - Padding( - padding: - EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("Region")), - ], - ), - subtitle: Column(children: [ - TextFormField( - maxLines: 1, - textAlign: TextAlign.left, + title: Row(children: [ + Icon(FontAwesomeIcons.calendarAlt), + Padding( + padding: EdgeInsets.fromLTRB(0, 20, 10, 10)), + Text("Date"), + ]), + subtitle: Padding( + padding: EdgeInsets.fromLTRB(0, 10, 0, 10), + child: DateTimePickerFormField( decoration: InputDecoration( - labelText: "Region ID Prefix", + labelText: "select Day", filled: true, fillColor: Colors.white, ), - onChanged: (String value) { - setState(() { - _regionIdPrefix = value; - }); + inputType: InputType.date, + format: DateFormat("yyyy-MM-dd"), + initialDate: DateTime.now(), + editable: false, + onChanged: (dt) { + setState(() => _hangUpDate = dt); }, ), - TextFormField( - maxLines: 1, - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "Region Name", - filled: true, - fillColor: Colors.white, - ), - onChanged: (String value) { - setState(() { - _regionName = value; - }); - }, + ))), + Card( + child: ListTile( + title: Row( + children: [ + Icon(FontAwesomeIcons.box), + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Text("Box")) + ], + ), + subtitle: Column(children: [ + Padding( + padding: EdgeInsets.fromLTRB(0, 10, 0, 10), + child: Row( + children: [ + Expanded(child: Text("Material:")), + _createMaterialSelection(context), + ], + )), + Row( + children: [ + Expanded( + child: Text("Hole size:"), ), - ])), + _createHoleSizeSlider() + ], + ) + ]), ), - Card( - child: ListTile( + ), + Card( + child: ListTile( title: Row( children: [ - Icon(FontAwesomeIcons.globeAmericas), + Icon(FontAwesomeIcons.globe), Padding( padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("Position")), + child: Text("Region")), ], ), - subtitle: Column( - children: [ - TextFormField( - keyboardType: TextInputType.number, - maxLines: 1, - textAlign: TextAlign.left, - readOnly: true, - decoration: InputDecoration( - labelText: - "Latitude ${(position == null) ? "" : position.latitude}", - filled: true, - fillColor: Colors.white, - ), + subtitle: Column(children: [ + TextFormField( + maxLines: 1, + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: "Region ID Prefix", + filled: true, + fillColor: Colors.white, ), - TextFormField( - keyboardType: TextInputType.number, - readOnly: true, - maxLines: 1, - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: - "Longitude ${(position == null) ? "" : position.longitude}", - filled: true, - fillColor: Colors.white, - ), + onChanged: (String value) { + setState(() { + _regionIdPrefix = value; + }); + }, + ), + TextFormField( + maxLines: 1, + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: "Region Name", + filled: true, + fillColor: Colors.white, ), - Padding( + onChanged: (String value) { + setState(() { + _regionName = value; + }); + }, + ), + ])), + ), + Card( + child: ListTile( + title: Row( + children: [ + Icon(FontAwesomeIcons.globeAmericas), + Padding( padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Row( - children: [ - Padding( - padding: - EdgeInsets.fromLTRB(10, 10, 10, 10), - child: (Text("Add GPS Data"))), - IconButton( - icon: Icon(Icons.gps_fixed), - onPressed: () async { - if (await Geolocator() - .isLocationServiceEnabled()) { - Position currentPosition = - await Geolocator() - .getCurrentPosition( - desiredAccuracy: - LocationAccuracy - .high); + child: Text("Position")), + ], + ), + subtitle: Column( + children: [ + TextFormField( + keyboardType: TextInputType.number, + maxLines: 1, + textAlign: TextAlign.left, + readOnly: true, + decoration: InputDecoration( + labelText: + "Latitude ${(position == null) ? "" : position.latitude}", + filled: true, + fillColor: Colors.white, + ), + ), + TextFormField( + keyboardType: TextInputType.number, + readOnly: true, + maxLines: 1, + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: + "Longitude ${(position == null) ? "" : position.longitude}", + filled: true, + fillColor: Colors.white, + ), + ), + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Row( + children: [ + Padding( + padding: + EdgeInsets.fromLTRB(10, 10, 10, 10), + child: (Text("Add GPS Data"))), + IconButton( + icon: Icon(Icons.gps_fixed), + onPressed: () async { + if (await Geolocator() + .isLocationServiceEnabled()) { + Position currentPosition = + await Geolocator() + .getCurrentPosition( + desiredAccuracy: + LocationAccuracy.high); - setState(() { - position = LatLng( - currentPosition.latitude, - currentPosition.longitude); - }); - } - }, - ) - ], - ), + setState(() { + position = LatLng( + currentPosition.latitude, + currentPosition.longitude); + }); + } + }, + ) + ], ), - ], - ), + ), + ], ), ), - Card( - child: ListTile( - title: Row( - children: [ - Icon(FontAwesomeIcons.userAlt), - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("Owner")), - ], - ), - subtitle: TextFormField( - maxLines: 1, - textAlign: TextAlign.left, - decoration: InputDecoration( - labelText: "Owner", - filled: true, - fillColor: Colors.white, - ), - onChanged: (String value) { - setState(() { - _owner = value; - }); - }, + ), + Card( + child: ListTile( + title: Row( + children: [ + Icon(FontAwesomeIcons.userAlt), + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Text("Owner")), + ], + ), + subtitle: TextFormField( + maxLines: 1, + textAlign: TextAlign.left, + decoration: InputDecoration( + labelText: "Owner", + filled: true, + fillColor: Colors.white, ), + onChanged: (String value) { + setState(() { + _owner = value; + }); + }, ), ), - Card( - child: ListTile( - title: Row( - children: [ - Icon(FontAwesomeIcons.comment), - Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 10), - child: Text("Comment")) - ], - ), - subtitle: TextFormField( - maxLines: 3, - textAlign: TextAlign.left, - onChanged: (String value) { - setState(() { - _comment = value; - }); - }, - ), + ), + Card( + child: ListTile( + title: Row( + children: [ + Icon(FontAwesomeIcons.comment), + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Text("Comment")) + ], + ), + subtitle: TextFormField( + maxLines: 3, + textAlign: TextAlign.left, + onChanged: (String value) { + setState(() { + _comment = value; + }); + }, ), ), - RaisedButton( - color: Colors.blue, - onPressed: () { - BlocProvider.of(context).add( - SendBoxEvent( - authBloc: - BlocProvider.of(context), - material: _dropDownMaterial, - hangUpDate: (hangUpDate != null) - ? hangUpDate - : DateTime.now(), - oldId: _oldId, - holeSize: getSliderLabel(_slideHoleSize), - comment: _comment, - coordinates: position, - foreignId: _foreignId, - ownerString: _owner, - regionIdPrefixString: _regionIdPrefix, - regionString: _regionName, - ), - ); - }, - child: Text( - "Create new Nesting Box", - style: TextStyle( - fontSize: 20, - color: Colors.white, + ), + RaisedButton( + color: Colors.blue, + onPressed: () { + BlocProvider.of(context).add( + SendBoxEvent( + authBloc: + BlocProvider.of(context), + material: "WoodConcrete", + hangUpDate: (_hangUpDate != null) + ? _hangUpDate + : DateTime.now(), + oldId: _oldId, + holeSize: "Other", + comment: _comment, + coordinates: position, + foreignId: _foreignId, + ownerString: _owner, + regionIdPrefixString: _regionIdPrefix, + regionString: _regionName, ), + ); + }, + child: Text( + "Create new Nesting Box", + style: TextStyle( + fontSize: 20, + color: Colors.white, ), ), - ], - ), + ), + ], ), - ); - } - if (state is BoxSentState) { - BlocProvider.of(context) - .add(GoToNewBoxConfirmationEvent()); - BlocProvider.of(context) - .add(GetAllBoxPreviewEvent()); - } - }, - ), + ), + ); + } + if (state is BoxSentState) { + BlocProvider.of(context).add(GetAllBoxPreviewEvent()); + BlocProvider.of(context) + .add(GoToNewBoxConfirmationEvent()); + return LinearProgressIndicator(); + } + if (state is SendingBoxState) { + return LinearProgressIndicator( + backgroundColor: Colors.green, + ); + } + }, ), ); } diff --git a/lib/screens/newboxconfirmation_screen.dart b/lib/screens/newboxconfirmation_screen.dart index 842b370a..7e5d749a 100644 --- a/lib/screens/newboxconfirmation_screen.dart +++ b/lib/screens/newboxconfirmation_screen.dart @@ -1,13 +1,16 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nesteo_app/blocs/boxsender_bloc/boxsender.dart'; import 'package:nesteo_app/screens/nesteo_screen.dart'; +import 'package:nesteo_app/blocs/pagecontrol_bloc/pagecontrol.dart'; class NewBoxConfirmationScreen extends NesteoFullScreen { NewBoxConfirmationScreen(BuildContext context) : super(context, hasAppBar: true, - appBarTitle: Text("New Box confirmation"), - appBarLeading: GoBackButton(), + appBarTitle: Text("Write this ID on your new box:"), + appBarLeading: null, appBarActions: null); @override Widget build(BuildContext context) { @@ -29,20 +32,29 @@ class NewBoxConfirmationData extends StatefulWidget { class _NewBoxConfirmationDataState extends State { Widget build(BuildContext context) { return Container( - child: SingleChildScrollView( - child: Column(children: [ - Card( - child: Column(children: [ - ListTile( - title: Text("Generated ID:"), + child: Center( + child: Column( + children: [ + Text( + BlocProvider.of(context).lastNewBox.id, + style: TextStyle( + fontFamily: 'Quicksand', + fontSize: 70, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + RaisedButton( + onPressed: () { + BlocProvider.of(context).add(NewBoxDoneEvent()); + BlocProvider.of(context) + .add(GoToBoxListEvent()); + }, + child: Text("Back to the List"), + ), + ], ), - ListTile( - title: FittedBox( - fit: BoxFit.contain, - child: Text("A00000"), - ), - ) - ])), - ]))); + ), + ); } } From d879901e1a5cecfaaddcc7ab846f46f2d1459240 Mon Sep 17 00:00:00 2001 From: Priggelpitt Date: Wed, 13 Nov 2019 15:29:57 -0500 Subject: [PATCH 6/6] Fixed test. Resolves #10 and #84 --- pubspec.lock | 14 ++++++++++++++ pubspec.yaml | 2 +- test/api_test.dart | 5 +++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 7f678439..6964a6dc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -230,6 +230,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + flutter_keyboard_visibility: + dependency: transitive + description: + name: flutter_keyboard_visibility + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.0" flutter_launcher_icons: dependency: "direct dev" description: @@ -254,6 +261,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_typeahead: + dependency: "direct main" + description: + name: flutter_typeahead + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" font_awesome_flutter: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 970351f2..8a87df7f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: nesteo_app description: Nesting box management app for ringing associations. -version: 0.3.15+18 +version: 0.3.16+19 environment: sdk: ">=2.1.0 <3.0.0" diff --git a/test/api_test.dart b/test/api_test.dart index 8f66580c..8cf32299 100644 --- a/test/api_test.dart +++ b/test/api_test.dart @@ -206,8 +206,9 @@ void main() { comment: "Prost!", ); - int response = await nestingBoxRepo.addNewNestingBox(newNestingBox); - expect(response == 201, true); + NestingBox response = + await nestingBoxRepo.addNewNestingBox(newNestingBox); + expect(response != null, true); }); }); group('Inspection API tests', () {