| @@ -0,0 +1,20 @@ | |||
| class LocationUnit { | |||
| int id; | |||
| String name; | |||
| bool isSelected; | |||
| LocationUnit({this.id, this.name}); | |||
| LocationUnit.fromJson(Map<String, dynamic> json) { | |||
| id = json['id']; | |||
| name = json['name']; | |||
| isSelected = false; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['id'] = this.id; | |||
| data['name'] = this.name; | |||
| return data; | |||
| } | |||
| } | |||
| @@ -3,6 +3,7 @@ import 'package:farm_tpf/custom_model/CropPlot.dart'; | |||
| import 'package:farm_tpf/custom_model/Device.dart'; | |||
| import 'package:farm_tpf/custom_model/EnvironmentParameter.dart'; | |||
| import 'package:farm_tpf/custom_model/Harvest.dart'; | |||
| import 'package:farm_tpf/custom_model/LocationUnit.dart'; | |||
| import 'package:farm_tpf/custom_model/Supply.dart'; | |||
| import 'package:farm_tpf/custom_model/UpdateNoti.dart'; | |||
| import 'package:farm_tpf/custom_model/WaterType.dart'; | |||
| @@ -70,6 +71,33 @@ abstract class RestClient { | |||
| @PUT("/api/notifications/update") | |||
| Future<void> updateNoti(@Body() UpdateNoti updateNoti); | |||
| @GET("/api/tb-countries?page={page}&size={size}&&sort=name,ASC") | |||
| Future<List<LocationUnit>> getCountries( | |||
| {@Path() int page = 0, | |||
| @Path() int size = 20, | |||
| @DioOptions() Options options}); | |||
| @GET( | |||
| "/api/tb-cities-by-country/{countryId}?page={page}&size={size}&&sort=name,ASC") | |||
| Future<List<LocationUnit>> getProvinces(@Path() int countryId, | |||
| {@Path() int page = 0, | |||
| @Path() int size = 20, | |||
| @DioOptions() Options options}); | |||
| @GET( | |||
| "/api/tb-districts-by-city/{provinceId}?page={page}&size={size}&&sort=name,ASC") | |||
| Future<List<LocationUnit>> getDistricts(@Path() int provinceId, | |||
| {@Path() int page = 0, | |||
| @Path() int size = 20, | |||
| @DioOptions() Options options}); | |||
| @GET( | |||
| "/api/tb-wards-by-district/{districtId}?page={page}&size={size}&&sort=name,ASC") | |||
| Future<List<LocationUnit>> getWards(@Path() int districtId, | |||
| {@Path() int page = 0, | |||
| @Path() int size = 20, | |||
| @DioOptions() Options options}); | |||
| //Crop | |||
| @GET( | |||
| "/api/tb-crops-detail-for-app/{cropId}?page={page}&size={size}&sort=executeDate,DESC") | |||
| @@ -317,6 +317,89 @@ class _RestClient implements RestClient { | |||
| return null; | |||
| } | |||
| @override | |||
| getCountries({page = 0, size = 20, options}) async { | |||
| const _extra = <String, dynamic>{}; | |||
| final queryParameters = <String, dynamic>{}; | |||
| queryParameters.removeWhere((k, v) => v == null); | |||
| final _data = <String, dynamic>{}; | |||
| final newOptions = newRequestOptions(options); | |||
| newOptions.extra.addAll(_extra); | |||
| newOptions.headers.addAll(<String, dynamic>{}); | |||
| final Response<List<dynamic>> _result = await _dio.request( | |||
| '/api/tb-countries?page=$page&size=$size&&sort=name,ASC', | |||
| queryParameters: queryParameters, | |||
| options: newOptions.merge(method: 'GET', baseUrl: baseUrl), | |||
| data: _data); | |||
| var value = _result.data | |||
| .map((dynamic i) => LocationUnit.fromJson(i as Map<String, dynamic>)) | |||
| .toList(); | |||
| return value; | |||
| } | |||
| @override | |||
| getProvinces(countryId, {page = 0, size = 20, options}) async { | |||
| ArgumentError.checkNotNull(countryId, 'countryId'); | |||
| const _extra = <String, dynamic>{}; | |||
| final queryParameters = <String, dynamic>{}; | |||
| queryParameters.removeWhere((k, v) => v == null); | |||
| final _data = <String, dynamic>{}; | |||
| final newOptions = newRequestOptions(options); | |||
| newOptions.extra.addAll(_extra); | |||
| newOptions.headers.addAll(<String, dynamic>{}); | |||
| final Response<List<dynamic>> _result = await _dio.request( | |||
| '/api/tb-cities-by-country/$countryId?page=$page&size=$size&&sort=name,ASC', | |||
| queryParameters: queryParameters, | |||
| options: newOptions.merge(method: 'GET', baseUrl: baseUrl), | |||
| data: _data); | |||
| var value = _result.data | |||
| .map((dynamic i) => LocationUnit.fromJson(i as Map<String, dynamic>)) | |||
| .toList(); | |||
| return value; | |||
| } | |||
| @override | |||
| getDistricts(provinceId, {page = 0, size = 20, options}) async { | |||
| ArgumentError.checkNotNull(provinceId, 'provinceId'); | |||
| const _extra = <String, dynamic>{}; | |||
| final queryParameters = <String, dynamic>{}; | |||
| queryParameters.removeWhere((k, v) => v == null); | |||
| final _data = <String, dynamic>{}; | |||
| final newOptions = newRequestOptions(options); | |||
| newOptions.extra.addAll(_extra); | |||
| newOptions.headers.addAll(<String, dynamic>{}); | |||
| final Response<List<dynamic>> _result = await _dio.request( | |||
| '/api/tb-districts-by-city/$provinceId?page=$page&size=$size&&sort=name,ASC', | |||
| queryParameters: queryParameters, | |||
| options: newOptions.merge(method: 'GET', baseUrl: baseUrl), | |||
| data: _data); | |||
| var value = _result.data | |||
| .map((dynamic i) => LocationUnit.fromJson(i as Map<String, dynamic>)) | |||
| .toList(); | |||
| return value; | |||
| } | |||
| @override | |||
| getWards(districtId, {page = 0, size = 20, options}) async { | |||
| ArgumentError.checkNotNull(districtId, 'districtId'); | |||
| const _extra = <String, dynamic>{}; | |||
| final queryParameters = <String, dynamic>{}; | |||
| queryParameters.removeWhere((k, v) => v == null); | |||
| final _data = <String, dynamic>{}; | |||
| final newOptions = newRequestOptions(options); | |||
| newOptions.extra.addAll(_extra); | |||
| newOptions.headers.addAll(<String, dynamic>{}); | |||
| final Response<List<dynamic>> _result = await _dio.request( | |||
| '/api/tb-wards-by-district/$districtId?page=$page&size=$size&&sort=name,ASC', | |||
| queryParameters: queryParameters, | |||
| options: newOptions.merge(method: 'GET', baseUrl: baseUrl), | |||
| data: _data); | |||
| var value = _result.data | |||
| .map((dynamic i) => LocationUnit.fromJson(i as Map<String, dynamic>)) | |||
| .toList(); | |||
| return value; | |||
| } | |||
| @override | |||
| getCropDetail(cropId, {page = 0, size = 20}) async { | |||
| ArgumentError.checkNotNull(cropId, 'cropId'); | |||
| @@ -6,6 +6,7 @@ import 'package:farm_tpf/custom_model/CropPlot.dart'; | |||
| import 'package:farm_tpf/custom_model/Device.dart'; | |||
| import 'package:farm_tpf/custom_model/EnvironmentParameter.dart'; | |||
| import 'package:farm_tpf/custom_model/Harvest.dart'; | |||
| import 'package:farm_tpf/custom_model/LocationUnit.dart'; | |||
| import 'package:farm_tpf/custom_model/NotificationDTO.dart'; | |||
| import 'package:farm_tpf/custom_model/NotificationObjectDTO.dart'; | |||
| import 'package:farm_tpf/custom_model/Supply.dart'; | |||
| @@ -115,6 +116,31 @@ class Repository { | |||
| return value; | |||
| } | |||
| Future<List<LocationUnit>> getLocationUnits( | |||
| {@required LocationType locationType, | |||
| int filterId, | |||
| int page = 0, | |||
| int size = 100}) { | |||
| final client = RestClient(dio); | |||
| var op = buildConfigurableCacheOptions( | |||
| forceRefresh: true, maxAge: Duration(days: ConstCommon.kMaxAgeCache)); | |||
| var response; | |||
| switch (locationType) { | |||
| case LocationType.province: | |||
| response = client.getProvinces(filterId, options: op); | |||
| break; | |||
| case LocationType.district: | |||
| response = client.getDistricts(filterId, options: op); | |||
| break; | |||
| case LocationType.ward: | |||
| response = client.getWards(filterId, options: op); | |||
| break; | |||
| default: | |||
| response = client.getCountries(); | |||
| } | |||
| return response; | |||
| } | |||
| Object getInstanceClass() { | |||
| var instanceClass; | |||
| if (1 == 1) { | |||
| @@ -0,0 +1,71 @@ | |||
| import 'dart:async'; | |||
| import 'package:bloc/bloc.dart'; | |||
| import 'package:equatable/equatable.dart'; | |||
| import 'package:farm_tpf/custom_model/LocationUnit.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:meta/meta.dart'; | |||
| part 'location_event.dart'; | |||
| part 'location_state.dart'; | |||
| class LocationBloc extends Bloc<LocationEvent, LocationState> { | |||
| final Repository repository; | |||
| LocationBloc({@required this.repository}) : super(LocationInitial()); | |||
| @override | |||
| Stream<LocationState> mapEventToState( | |||
| LocationEvent event, | |||
| ) async* { | |||
| if (event is DataFetched) { | |||
| try { | |||
| final response = await repository.getLocationUnits( | |||
| locationType: event.locationType, filterId: event.filterId); | |||
| List<LocationUnit> locations = response.map((location) { | |||
| if (location.id == event.selectedId) { | |||
| location.isSelected = true; | |||
| } | |||
| return location; | |||
| }).toList(); | |||
| yield LocationSuccess(items: locations); | |||
| } catch (_) { | |||
| yield LocationFailure(); | |||
| } | |||
| } else if (event is OnRefresh) { | |||
| try { | |||
| final response = await repository.getLocationUnits( | |||
| locationType: event.locationType, filterId: event.filterId); | |||
| List<LocationUnit> locations = response.map((location) { | |||
| if (location.id == event.selectedId) { | |||
| location.isSelected = true; | |||
| } | |||
| return location; | |||
| }).toList(); | |||
| yield LocationSuccess(items: locations); | |||
| } catch (_) { | |||
| yield LocationFailure(); | |||
| } | |||
| } else if (event is OnSearch) { | |||
| try { | |||
| final response = await repository.getLocationUnits( | |||
| locationType: event.locationType, filterId: event.filterId); | |||
| bool query(LocationUnit locationUnit) => | |||
| event.searchString.isEmpty || | |||
| locationUnit.name | |||
| .toLowerCase() | |||
| .contains(event.searchString.toLowerCase()); | |||
| final result = response.where(query).toList(); | |||
| List<LocationUnit> locations = result.map((location) { | |||
| if (location.id == event.selectedId) { | |||
| location.isSelected = true; | |||
| } | |||
| return location; | |||
| }).toList(); | |||
| yield LocationSuccess(items: locations); | |||
| } catch (_) { | |||
| yield LocationFailure(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,34 @@ | |||
| part of 'location_bloc.dart'; | |||
| abstract class LocationEvent extends Equatable { | |||
| const LocationEvent(); | |||
| @override | |||
| List<Object> get props => []; | |||
| } | |||
| class DataFetched extends LocationEvent { | |||
| final LocationType locationType; | |||
| final int selectedId; | |||
| final int filterId; | |||
| DataFetched({@required this.locationType, this.selectedId, this.filterId}); | |||
| } | |||
| class OnRefresh extends LocationEvent { | |||
| final LocationType locationType; | |||
| final int selectedId; | |||
| final int filterId; | |||
| OnRefresh({@required this.locationType, this.selectedId, this.filterId}); | |||
| } | |||
| class OnSearch extends LocationEvent { | |||
| final LocationType locationType; | |||
| final String searchString; | |||
| final int selectedId; | |||
| final int filterId; | |||
| OnSearch( | |||
| {@required this.locationType, | |||
| this.searchString, | |||
| this.selectedId, | |||
| this.filterId}); | |||
| } | |||
| @@ -0,0 +1,25 @@ | |||
| part of 'location_bloc.dart'; | |||
| abstract class LocationState extends Equatable { | |||
| const LocationState(); | |||
| @override | |||
| List<Object> get props => []; | |||
| } | |||
| class LocationInitial extends LocationState {} | |||
| class LocationFailure extends LocationState {} | |||
| class LocationSuccess<T> extends LocationState { | |||
| final List<T> items; | |||
| const LocationSuccess({this.items}); | |||
| LocationSuccess copyWith({List<T> items}) { | |||
| return LocationSuccess(items: items ?? this.items); | |||
| } | |||
| @override | |||
| List<Object> get props => [items]; | |||
| } | |||
| @@ -0,0 +1,165 @@ | |||
| import 'package:farm_tpf/custom_model/LocationUnit.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bottom_loader.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart'; | |||
| import 'package:farm_tpf/presentation/screens/location_unit/widget_search.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'bloc/location_bloc.dart'; | |||
| class LocationScreen extends StatefulWidget { | |||
| final LocationType type; | |||
| final int selectedId; | |||
| final int filterId; | |||
| final String titleName; | |||
| LocationScreen( | |||
| {@required this.titleName, | |||
| @required this.type, | |||
| @required this.selectedId, | |||
| @required this.filterId}); | |||
| @override | |||
| _LocationScreenState createState() => _LocationScreenState(); | |||
| } | |||
| class _LocationScreenState extends State<LocationScreen> { | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return BlocProvider( | |||
| create: (context) => LocationBloc(repository: Repository()) | |||
| ..add(DataFetched( | |||
| locationType: widget.type, | |||
| selectedId: widget.selectedId, | |||
| filterId: widget.filterId, | |||
| )), | |||
| child: HoldInfinityWidget( | |||
| type: widget.type, | |||
| selectedId: widget.selectedId, | |||
| filterId: widget.filterId, | |||
| titleName: widget.titleName, | |||
| ), | |||
| ); | |||
| } | |||
| } | |||
| class HoldInfinityWidget extends StatelessWidget { | |||
| final int selectedId; | |||
| final LocationType type; | |||
| final int filterId; | |||
| final String titleName; | |||
| HoldInfinityWidget( | |||
| {@required this.selectedId, | |||
| @required this.type, | |||
| @required this.filterId, | |||
| @required this.titleName}); | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return Scaffold( | |||
| key: _scaffoldKey, | |||
| appBar: AppBar(title: Text("Chọn $titleName")), | |||
| body: Column( | |||
| children: <Widget>[ | |||
| WidgetSearchLocation( | |||
| filterId: filterId, | |||
| type: type, | |||
| selectedId: selectedId, | |||
| ), | |||
| Expanded( | |||
| child: InfinityView( | |||
| selectedId: selectedId, | |||
| type: type, | |||
| filterId: filterId, | |||
| )) | |||
| ], | |||
| )); | |||
| } | |||
| } | |||
| class InfinityView extends StatefulWidget { | |||
| final int filterId; | |||
| final int selectedId; | |||
| final LocationType type; | |||
| InfinityView( | |||
| {@required this.selectedId, | |||
| @required this.type, | |||
| @required this.filterId}); | |||
| @override | |||
| _InfinityViewState createState() => _InfinityViewState(); | |||
| } | |||
| class _InfinityViewState extends State<InfinityView> { | |||
| LocationBloc _locationBloc; | |||
| @override | |||
| void initState() { | |||
| _locationBloc = BlocProvider.of<LocationBloc>(context); | |||
| _locationBloc.add(DataFetched( | |||
| locationType: widget.type, | |||
| selectedId: widget.selectedId, | |||
| filterId: widget.filterId)); | |||
| super.initState(); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return BlocBuilder<LocationBloc, LocationState>( | |||
| builder: (context, state) { | |||
| if (state is LocationFailure) { | |||
| return Center(child: Text(label_error_get_data)); | |||
| } | |||
| if (state is LocationSuccess) { | |||
| if (state.items.isEmpty) { | |||
| return Center(child: Text(label_list_empty)); | |||
| } | |||
| return RefreshIndicator( | |||
| child: ListView.builder( | |||
| itemBuilder: (BuildContext context, int index) { | |||
| return index >= state.items.length | |||
| ? BottomLoader() | |||
| : ItemInfinityWidget(item: state.items[index]); | |||
| }, | |||
| itemCount: state.items.length), | |||
| onRefresh: () async { | |||
| _locationBloc.add(OnRefresh( | |||
| locationType: widget.type, | |||
| selectedId: widget.selectedId, | |||
| filterId: widget.filterId)); | |||
| }); | |||
| } | |||
| return Center( | |||
| child: LoadingListPage(), | |||
| ); | |||
| }, | |||
| ); | |||
| } | |||
| @override | |||
| void dispose() { | |||
| super.dispose(); | |||
| } | |||
| } | |||
| class ItemInfinityWidget extends StatelessWidget { | |||
| final LocationUnit item; | |||
| const ItemInfinityWidget({Key key, @required this.item}) : super(key: key); | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return GestureDetector( | |||
| child: Card( | |||
| child: Material( | |||
| child: RadioListTile( | |||
| title: Text("${item.name}"), | |||
| value: item, | |||
| groupValue: item.isSelected == false ? null : item, | |||
| onChanged: (LocationUnit value) { | |||
| Navigator.of(context).pop(value); | |||
| }), | |||
| )), | |||
| onTap: () {}); | |||
| } | |||
| } | |||
| @@ -0,0 +1,94 @@ | |||
| import 'package:farm_tpf/presentation/screens/location_unit/bloc/location_bloc.dart'; | |||
| import 'package:farm_tpf/utils/const_color.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| class WidgetSearchLocation extends StatefulWidget { | |||
| final LocationType type; | |||
| final int filterId; | |||
| final int selectedId; | |||
| WidgetSearchLocation({this.type, this.selectedId, this.filterId}); | |||
| @override | |||
| _WidgetSearchLocationState createState() => _WidgetSearchLocationState(); | |||
| } | |||
| class _WidgetSearchLocationState extends State<WidgetSearchLocation> { | |||
| BuildContext _blocContext; | |||
| final _searchController = TextEditingController(); | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| _searchController.addListener(() { | |||
| final keyword = _searchController.text; | |||
| if (keyword.isNotEmpty) { | |||
| //search when text change | |||
| } | |||
| }); | |||
| } | |||
| Widget getSearchBarUI() { | |||
| _searchController.text = ""; | |||
| return Padding( | |||
| padding: const EdgeInsets.only(left: 16, right: 16, top: 4, bottom: 0), | |||
| child: Row( | |||
| children: <Widget>[ | |||
| Expanded( | |||
| child: Padding( | |||
| padding: const EdgeInsets.only(right: 8, top: 8, bottom: 0), | |||
| child: Container( | |||
| decoration: BoxDecoration( | |||
| color: Colors.white, | |||
| borderRadius: const BorderRadius.all( | |||
| Radius.circular(38.0), | |||
| ), | |||
| boxShadow: <BoxShadow>[ | |||
| BoxShadow( | |||
| color: Colors.grey.withOpacity(0.2), | |||
| offset: const Offset(0, 2), | |||
| blurRadius: 8.0), | |||
| ], | |||
| ), | |||
| child: Padding( | |||
| padding: const EdgeInsets.only( | |||
| left: 16, right: 16, top: 4, bottom: 4), | |||
| child: TextField( | |||
| textInputAction: TextInputAction.done, | |||
| controller: _searchController, | |||
| onChanged: (String txt) {}, | |||
| cursorColor: COLOR_CONST.GRAY1, | |||
| decoration: InputDecoration( | |||
| border: InputBorder.none, | |||
| hintText: 'Tìm kiếm ...', | |||
| ), | |||
| onSubmitted: (value) { | |||
| FocusScope.of(context).requestFocus(FocusNode()); | |||
| BlocProvider.of<LocationBloc>(_blocContext).add(OnSearch( | |||
| searchString: value, | |||
| locationType: widget.type, | |||
| selectedId: widget.selectedId, | |||
| filterId: widget.filterId)); | |||
| }, | |||
| ), | |||
| ), | |||
| ), | |||
| ), | |||
| ), | |||
| ], | |||
| ), | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| _blocContext = context; | |||
| return Container(child: getSearchBarUI()); | |||
| } | |||
| @override | |||
| void dispose() { | |||
| _searchController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -2,11 +2,16 @@ import 'package:farm_tpf/custom_model/account.dart'; | |||
| import 'package:farm_tpf/data/repository/user_repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_toast.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_supply.dart'; | |||
| import 'package:farm_tpf/presentation/screens/location_unit/sc_location.dart'; | |||
| import 'package:farm_tpf/presentation/screens/profile/sc_change_password.dart'; | |||
| import 'package:farm_tpf/utils/const_color.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:fluttertoast/fluttertoast.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:package_info/package_info.dart'; | |||
| @@ -140,6 +145,166 @@ class _UpdateProfileScreenState extends State<UpdateProfileScreen> { | |||
| ); | |||
| } | |||
| Widget _btnSelectCountry() { | |||
| return GetBuilder<ChangeSupply>(builder: (data) { | |||
| return FlatButton( | |||
| padding: | |||
| EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||
| onPressed: () { | |||
| Navigator.of(context) | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => LocationScreen( | |||
| titleName: "Quốc gia", | |||
| type: LocationType.country, | |||
| filterId: null, | |||
| selectedId: null), | |||
| fullscreenDialog: false)) | |||
| .then((value) { | |||
| if (value != null) {} | |||
| }); | |||
| }, | |||
| child: Container( | |||
| padding: EdgeInsets.only( | |||
| top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: kBorderTextField, | |||
| ), | |||
| child: Row( | |||
| children: [ | |||
| GetBuilder<ChangeSupply>( | |||
| builder: (_) => Expanded( | |||
| child: Text("sdfd" ?? "Quốc gia", | |||
| style: TextStyle( | |||
| fontSize: 14.0, color: Colors.black87)))), | |||
| Icon( | |||
| Icons.arrow_drop_down, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ))); | |||
| }); | |||
| } | |||
| Widget _btnSelectProvince() { | |||
| return GetBuilder<ChangeSupply>(builder: (data) { | |||
| return FlatButton( | |||
| padding: | |||
| EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||
| onPressed: () { | |||
| Navigator.of(context) | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => LocationScreen( | |||
| titleName: "Tỉnh/Thành phố", | |||
| type: LocationType.province, | |||
| filterId: 1, | |||
| selectedId: null), | |||
| fullscreenDialog: false)) | |||
| .then((value) { | |||
| if (value != null) {} | |||
| }); | |||
| }, | |||
| child: Container( | |||
| padding: EdgeInsets.only( | |||
| top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: kBorderTextField, | |||
| ), | |||
| child: Row( | |||
| children: [ | |||
| GetBuilder<ChangeSupply>( | |||
| builder: (_) => Expanded( | |||
| child: Text("sdfd" ?? "Tỉnh/Thành Phố", | |||
| style: TextStyle( | |||
| fontSize: 14.0, color: Colors.black87)))), | |||
| Icon( | |||
| Icons.arrow_drop_down, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ))); | |||
| }); | |||
| } | |||
| Widget _btnSelectDistrict() { | |||
| return GetBuilder<ChangeSupply>(builder: (data) { | |||
| return FlatButton( | |||
| padding: | |||
| EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||
| onPressed: () { | |||
| Navigator.of(context) | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => LocationScreen( | |||
| titleName: "Quận/Huyện", | |||
| type: LocationType.district, | |||
| filterId: 79, | |||
| selectedId: null), | |||
| fullscreenDialog: false)) | |||
| .then((value) { | |||
| if (value != null) {} | |||
| }); | |||
| }, | |||
| child: Container( | |||
| padding: EdgeInsets.only( | |||
| top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: kBorderTextField, | |||
| ), | |||
| child: Row( | |||
| children: [ | |||
| GetBuilder<ChangeSupply>( | |||
| builder: (_) => Expanded( | |||
| child: Text("sdfd" ?? "Quận/Huyện", | |||
| style: TextStyle( | |||
| fontSize: 14.0, color: Colors.black87)))), | |||
| Icon( | |||
| Icons.arrow_drop_down, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ))); | |||
| }); | |||
| } | |||
| Widget _btnSelectWard() { | |||
| return GetBuilder<ChangeSupply>(builder: (data) { | |||
| return FlatButton( | |||
| padding: | |||
| EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||
| onPressed: () { | |||
| Navigator.of(context) | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => LocationScreen( | |||
| titleName: "Phường/Xã", | |||
| type: LocationType.ward, | |||
| filterId: 760, | |||
| selectedId: null), | |||
| fullscreenDialog: false)) | |||
| .then((value) { | |||
| if (value != null) {} | |||
| }); | |||
| }, | |||
| child: Container( | |||
| padding: EdgeInsets.only( | |||
| top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: kBorderTextField, | |||
| ), | |||
| child: Row( | |||
| children: [ | |||
| GetBuilder<ChangeSupply>( | |||
| builder: (_) => Expanded( | |||
| child: Text("sdfd" ?? "Phường/Xã", | |||
| style: TextStyle( | |||
| fontSize: 14.0, color: Colors.black87)))), | |||
| Icon( | |||
| Icons.arrow_drop_down, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ))); | |||
| }); | |||
| } | |||
| Widget _addressField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| @@ -236,6 +401,49 @@ class _UpdateProfileScreenState extends State<UpdateProfileScreen> { | |||
| height: 8.0, | |||
| ), | |||
| _emailField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Quốc gia", | |||
| style: | |||
| TextStyle(color: Colors.black54, fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnSelectCountry(), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Tỉnh/Thành phố", | |||
| style: | |||
| TextStyle(color: Colors.black54, fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnSelectProvince(), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Quận/Huyện", | |||
| style: | |||
| TextStyle(color: Colors.black54, fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnSelectDistrict(), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Phường/Xã", | |||
| style: | |||
| TextStyle(color: Colors.black54, fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnSelectWard(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _addressField(), | |||
| SizedBox( | |||
| height: 16.0, | |||
| ), | |||
| @@ -254,4 +462,13 @@ class _UpdateProfileScreenState extends State<UpdateProfileScreen> { | |||
| } | |||
| }); | |||
| } | |||
| @override | |||
| void dispose() { | |||
| super.dispose(); | |||
| _userNameController.dispose(); | |||
| _emailController.dispose(); | |||
| _fullNameController.dispose(); | |||
| _addressController.dispose(); | |||
| } | |||
| } | |||
| @@ -85,3 +85,4 @@ class ConstCommon { | |||
| } | |||
| enum CRUDStatus { unknown, add, edit, delete } | |||
| enum LocationType { country, province, district, ward } | |||