Browse Source

update profile screen (doing)

master
daivph 5 years ago
parent
commit
baf82e51ca
11 changed files with 764 additions and 0 deletions
  1. +20
    -0
      lib/custom_model/LocationUnit.dart
  2. +28
    -0
      lib/data/api/rest_client.dart
  3. +83
    -0
      lib/data/api/rest_client.g.dart
  4. +26
    -0
      lib/data/repository/repository.dart
  5. +71
    -0
      lib/presentation/screens/location_unit/bloc/location_bloc.dart
  6. +34
    -0
      lib/presentation/screens/location_unit/bloc/location_event.dart
  7. +25
    -0
      lib/presentation/screens/location_unit/bloc/location_state.dart
  8. +165
    -0
      lib/presentation/screens/location_unit/sc_location.dart
  9. +94
    -0
      lib/presentation/screens/location_unit/widget_search.dart
  10. +217
    -0
      lib/presentation/screens/profile/sc_update_profile.dart
  11. +1
    -0
      lib/utils/const_common.dart

+ 20
- 0
lib/custom_model/LocationUnit.dart View File

@@ -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;
}
}

+ 28
- 0
lib/data/api/rest_client.dart View File

@@ -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")

+ 83
- 0
lib/data/api/rest_client.g.dart View File

@@ -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');

+ 26
- 0
lib/data/repository/repository.dart View File

@@ -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) {

+ 71
- 0
lib/presentation/screens/location_unit/bloc/location_bloc.dart View File

@@ -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();
}
}
}
}

+ 34
- 0
lib/presentation/screens/location_unit/bloc/location_event.dart View File

@@ -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});
}

+ 25
- 0
lib/presentation/screens/location_unit/bloc/location_state.dart View File

@@ -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];
}

+ 165
- 0
lib/presentation/screens/location_unit/sc_location.dart View File

@@ -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: () {});
}
}

+ 94
- 0
lib/presentation/screens/location_unit/widget_search.dart View File

@@ -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();
}
}

+ 217
- 0
lib/presentation/screens/profile/sc_update_profile.dart View File

@@ -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();
}
}

+ 1
- 0
lib/utils/const_common.dart View File

@@ -85,3 +85,4 @@ class ConstCommon {
}

enum CRUDStatus { unknown, add, edit, delete }
enum LocationType { country, province, district, ward }

Loading…
Cancel
Save