Browse Source

list stamp, create stamp

phase2_dev
Đại Võ 1 year ago
parent
commit
d9a8997c41
15 changed files with 710 additions and 28 deletions
  1. +47
    -0
      lib/data/repository/repository.dart
  2. +17
    -3
      lib/main.dart
  3. +69
    -0
      lib/presentation/screens/codes/bloc/stamp_bloc.dart
  4. +17
    -0
      lib/presentation/screens/codes/bloc/stamp_event.dart
  5. +33
    -0
      lib/presentation/screens/codes/bloc/stamp_state.dart
  6. +78
    -11
      lib/presentation/screens/codes/code_page.dart
  7. +201
    -0
      lib/presentation/screens/codes/create_stamp_page.dart
  8. +80
    -0
      lib/presentation/screens/codes/cubit/create_stamp_cubit.dart
  9. +22
    -0
      lib/presentation/screens/codes/cubit/create_stamp_state.dart
  10. +53
    -0
      lib/presentation/screens/codes/models/stamp.dart
  11. +33
    -0
      lib/presentation/screens/codes/models/stamp_request.dart
  12. +21
    -0
      lib/presentation/screens/codes/models/stamp_type.dart
  13. +20
    -5
      lib/presentation/screens/codes/widgets/item_code.dart
  14. +9
    -9
      lib/presentation/screens/tabbar/tabbar.dart
  15. +10
    -0
      lib/utils/formatter.dart

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

@@ -19,11 +19,15 @@ import 'package:farm_tpf/custom_model/user_request.dart';
import 'package:farm_tpf/data/api/dio_provider.dart';
import 'package:farm_tpf/data/api/rest_client.dart';
import 'package:farm_tpf/models/PagedResult.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp_request.dart';
import 'package:farm_tpf/utils/const_common.dart';
import 'package:flutter/material.dart';

import '../../presentation/screens/codes/models/stamp_type.dart';
import '../../presentation/screens/login/models/request_user.dart';
import '../../presentation/screens/login/models/response_user.dart';
import '../api/app_exception.dart';

class Repository {
final dio = DioProvider();
@@ -284,4 +288,47 @@ class Repository {
final client = RestClient(dio);
return client.getDetailActivityCommon(activityType, activityId);
}

// Stamp
Future<List<Stamp>> stamps({int page = 0, int size = 20}) async {
try {
var url = '${ConstCommon.baseUrl}/api/tb-codes/list?page=$page&size=$size&sort=id,desc';
var res = await dio.post(url, data: {});
return (res.data as List).map((e) => Stamp.fromJson(e)).toList();
} catch (e) {
rethrow;
}
}

Future<List<StampType>> stampTypes() async {
try {
var url = '${ConstCommon.baseUrl}/api/tb-example-stamp/dropdown-list';
var res = await dio.get(
url,
);
return (res.data as List).map((e) => StampType.fromJson(e)).toList();
} catch (e) {
rethrow;
}
}

Future<void> createStamp(
Function(dynamic) onSuccess,
Function(String) onError, {
required RequestStamp item,
}) async {
try {
var url = '${ConstCommon.baseUrl}/api/tb-codes';

await dio.post(url, data: item).then(
(value) {
onSuccess(value);
},
).catchError((e) {
onError(AppException.handleError(e));
});
} catch (e) {
onError(AppException.handleError(e));
}
}
}

+ 17
- 3
lib/main.dart View File

@@ -1,9 +1,12 @@
// import 'package:barcode_scan/barcode_scan.dart';
import 'dart:io';

import 'package:farm_tpf/data/repository/repository.dart';
import 'package:farm_tpf/presentation/screens/codes/bloc/stamp_bloc.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart';
import 'app.dart';
@@ -34,7 +37,18 @@ Future<void> main() async {
final appDocumentDirectory = await getApplicationDocumentsDirectory();
Hive..init(appDocumentDirectory.path);
await Hive.openBox('LocalDBName');
runApp(App(
authenticationRepository: AuthenticationRepository(),
));
runApp(
MultiBlocProvider(
providers: [
BlocProvider(
create: (_) => StampBloc(
Repository(),
),
),
],
child: App(
authenticationRepository: AuthenticationRepository(),
),
),
);
}

+ 69
- 0
lib/presentation/screens/codes/bloc/stamp_bloc.dart View File

@@ -0,0 +1,69 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';

import '../../../../data/api/app_exception.dart';
import '../../../../data/repository/repository.dart';

part 'stamp_event.dart';
part 'stamp_state.dart';

class StampBloc extends Bloc<StampEvent, StampState> {
final Repository repository;
int pageSize = 20;
StampBloc(this.repository) : super(StampInitial());

@override
Stream<StampState> mapEventToState(
StampEvent event,
) async* {
if (event is DataFetched && !(state is StampSuccess && ((state as StampSuccess).hasReachedMax ?? false))) {
try {
if (state is StampInitial) {
yield (StampLoading());
final response = await repository.stamps(page: 0);
yield StampSuccess(
items: response,
page: 0,
hasReachedMax: response.length < pageSize ? true : false,
);
}
if (state is StampSuccess) {
final currentState = state as StampSuccess;
int page = (currentState.page ?? 0) + 1;
final response = await repository.stamps(page: page);
yield response.isEmpty
? currentState.copyWith(hasReachedMax: true)
: StampSuccess(
items: (currentState.items ?? []) + response,
page: (currentState.page ?? 0) + 1,
hasReachedMax: false,
);
}
} catch (e) {
var errorString = AppException.handleError(e);
yield (StampFailure(errorString: errorString));
}
}
if (event is OnRefresh) {
try {
yield (StampLoading());
final response = await repository.stamps(page: 0);
yield StampSuccess(
items: response,
page: 0,
hasReachedMax: response.length < pageSize ? true : false,
);
} catch (e) {
yield (StampFailure(errorString: AppException.handleError(e)));
}
} else if (event is OnSearch) {
try {
yield (StampLoading());
final response = await repository.stamps(page: 0);
yield StampSuccess(items: response, page: 0, hasReachedMax: response.length < pageSize ? true : false);
} catch (e) {
yield (StampFailure(errorString: AppException.handleError(e)));
}
}
}
}

+ 17
- 0
lib/presentation/screens/codes/bloc/stamp_event.dart View File

@@ -0,0 +1,17 @@
part of 'stamp_bloc.dart';

abstract class StampEvent extends Equatable {
const StampEvent();

@override
List<Object> get props => [];
}

class DataFetched extends StampEvent {}

class OnRefresh extends StampEvent {}

class OnSearch extends StampEvent {
final String searchString;
OnSearch({required this.searchString});
}

+ 33
- 0
lib/presentation/screens/codes/bloc/stamp_state.dart View File

@@ -0,0 +1,33 @@
part of 'stamp_bloc.dart';

abstract class StampState extends Equatable {
const StampState();

@override
List<Object> get props => [];
}

class StampInitial extends StampState {}

class StampLoading extends StampState {}

class StampFailure extends StampState {
final String errorString;
StampFailure({required this.errorString});
}

class StampSuccess<T> extends StampState {
final List<T>? items;
final int? page;
final bool? hasReachedMax;

const StampSuccess({this.items, this.page, this.hasReachedMax});

StampSuccess copyWith({List<T>? items, int? page, bool? hasReachedMax}) {
return StampSuccess(
items: items ?? this.items,
page: page ?? this.page,
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
);
}
}

+ 78
- 11
lib/presentation/screens/codes/code_page.dart View File

@@ -1,14 +1,22 @@
import 'package:farm_tpf/data/repository/repository.dart';
import 'package:farm_tpf/presentation/custom_widgets/button/button_2_icon.dart';
import 'package:farm_tpf/presentation/custom_widgets/button/second_button.dart';
import 'package:farm_tpf/presentation/screens/codes/code_detail_page.dart';
import 'package:farm_tpf/presentation/screens/codes/create_stamp_page.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp.dart';
import 'package:farm_tpf/presentation/screens/codes/widgets/item_code.dart';
import 'package:farm_tpf/themes/app_colors.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get/get.dart';

import '../../../themes/styles_text.dart';
import '../../../utils/const_string.dart';
import '../../custom_widgets/bottom_loader.dart';
import '../../custom_widgets/loading_list_page.dart';
import '../plot/widget_search.dart';
import 'bloc/stamp_bloc.dart';

class CodePage extends StatefulWidget {
const CodePage({super.key});
@@ -19,6 +27,30 @@ class CodePage extends StatefulWidget {

class _CodePageState extends State<CodePage> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
StampBloc bloc = StampBloc(Repository());
final _scrollController = ScrollController();
final _scrollThreshold = 250.0;

@override
void initState() {
bloc.add(DataFetched());

_scrollController.addListener(() {
final maxScroll = _scrollController.position.maxScrollExtent;
final currentScroll = _scrollController.position.pixels;
if (maxScroll - currentScroll < _scrollThreshold) {
bloc.add(DataFetched());
}
});
super.initState();
}

@override
void dispose() {
_scrollController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
@@ -69,7 +101,13 @@ class _CodePageState extends State<CodePage> {
),
const Spacer(),
SecondButton(
onPressed: () {},
onPressed: () {
Get.to(() => CreateStampPage())?.then((value) {
if (value != null) {
bloc.add(OnRefresh());
}
});
},
title: 'Tạo tem',
leftIcon: CupertinoIcons.add,
color: AppColors.primary1,
@@ -79,20 +117,49 @@ class _CodePageState extends State<CodePage> {
],
),
Expanded(
child: ListView.builder(
itemBuilder: ((context, index) {
return ItemCode(
onPressed: () {
Get.to(() => CodeDetailPage());
},
);
}),
itemCount: 100,
),
child: mainBody(),
),
],
),
),
);
}

Widget mainBody() {
return BlocBuilder<StampBloc, StampState>(
bloc: bloc,
builder: (context, state) {
if (state is StampFailure) {
return Center(child: Text(state.errorString));
}
if (state is StampSuccess) {
if ((state.items ?? []).isEmpty) {
return Center(child: Text(label_list_empty));
}
return RefreshIndicator(
child: ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return index >= (state.items ?? []).length
? BottomLoader()
: ItemCode(
item: state.items?[index],
onPressed: () {
Get.to(() => CodeDetailPage());
},
);
},
itemCount: (state.hasReachedMax ?? false) ? (state.items ?? []).length : (state.items ?? []).length + 1,
controller: _scrollController,
),
onRefresh: () async {
bloc.add(OnRefresh());
});
}
return Center(
child: LoadingListPage(),
);
},
);
}
}

+ 201
- 0
lib/presentation/screens/codes/create_stamp_page.dart View File

@@ -0,0 +1,201 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:farm_tpf/models/item_dropdown.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp_type.dart';
import 'package:farm_tpf/presentation/screens/codes/widgets/item_column.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter/src/widgets/placeholder.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get/get.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';

import '../../../utils/utils.dart';
import '../../custom_widgets/app_bar_widget.dart';
import '../../custom_widgets/button_widget.dart';
import '../../custom_widgets/date_picker/date_picker_widget.dart';
import '../../custom_widgets/dropdown/dropdown_bottom_sheet.dart';
import '../../custom_widgets/textfield/text_field_normal.dart';
import 'cubit/create_stamp_cubit.dart';

class CreateStampPage extends StatefulWidget {
const CreateStampPage({
super.key,
});

@override
State<CreateStampPage> createState() => _CreateStampPageState();
}

class _CreateStampPageState extends State<CreateStampPage> {
final bloc = CreateStampCubit();

@override
void initState() {
super.initState();
bloc.preparedData();
}

@override
void dispose() {
bloc.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBarWidget(),
body: BlocListener<CreateStampCubit, CreateStampState>(
bloc: bloc,
listener: ((context, state) {
if (state is CreateStampLoading) {
SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
UtilWidget.showLoading();
});
} else if (state is CreateStampFailure) {
SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
UtilWidget.hideLoading();
// UtilWidget.showToastError(state.errorMessage);
});
} else if (state is CreateStampPrepareDataSuccessful) {
SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
UtilWidget.hideLoading();
});
}
}),
child: KeyboardDismisser(
child: Container(
child: Form(
key: bloc.formKey,
child: Column(
children: [
Expanded(
child: _widgetBody(),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: ButtonWidget(
title: 'Cập nhật',
onPressed: () {
bloc.onSubmit();
},
),
),
],
),
),
),
),
),
);
}

Widget _widgetBody() {
return Container(
padding: const EdgeInsets.all(16),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ItemColumnWidget(
title: 'Mô tả',
child: TextFieldNormal(
controller: bloc.descriptionCtl,
maxLines: 1,
hint: 'Mô tả',
),
),
const SizedBox(
height: 8,
),
ItemColumnWidget(
title: 'Số lượng tem',
child: TextFieldNormal(
controller: bloc.quantityCtl,
maxLines: 1,
hint: 'Số lượng tem',
),
),
const SizedBox(
height: 8,
),
ItemColumnWidget(
title: 'Hạn sử dụng (ngày)',
child: TextFieldNormal(
controller: bloc.expiredDateCtl,
maxLines: 1,
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
hint: 'Hạn sử dụng (ngày)',
),
),
const SizedBox(
height: 8,
),
ItemColumnWidget(
title: 'Mẫu tem',
child: ValueListenableBuilder<String>(
valueListenable: bloc.selectedStampType,
builder: (context, selected, _) {
return ValueListenableBuilder<List<ItemDropDown>>(
valueListenable: bloc.stampTypes,
builder: (context, types, _) {
return DropdownBottomSheet(
dataSources: types,
initValue: selected,
onSelected: (val) {
bloc.selectedStampType.value = val.key ?? '';
},
hint: 'Mẫu tem',
);
},
);
},
),
),
const SizedBox(
height: 8,
),
ValueListenableBuilder<String>(
valueListenable: bloc.selectedStampType,
builder: (context, selected, _) {
if (selected.isEmpty) {
return const SizedBox.shrink();
}
var stamp = bloc.stampTypeRaws.firstWhere(
(e) => selected == e.id?.toString(),
orElse: () => StampType(),
);
return Container(
child: CachedNetworkImage(
imageUrl: stamp.exampleStampImage ?? '',
width: Get.width,
height: Get.width / 2,
fit: BoxFit.contain,
placeholder: (context, url) => Icon(
Icons.image,
size: 100,
color: Colors.grey[200],
),
errorWidget: (context, url, _) => Icon(
Icons.image_not_supported,
size: 100,
color: Colors.grey[200],
),
),
);
},
),
const SizedBox(
height: 16,
),
],
),
),
);
}
}

+ 80
- 0
lib/presentation/screens/codes/cubit/create_stamp_cubit.dart View File

@@ -0,0 +1,80 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp_request.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp_type.dart';
import 'package:farm_tpf/utils/formatter.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../../../../data/api/app_exception.dart';
import '../../../../data/repository/repository.dart';
import '../../../../models/item_dropdown.dart';
import '../../../../utils/utils.dart';

part 'create_stamp_state.dart';

class CreateStampCubit extends Cubit<CreateStampState> {
CreateStampCubit() : super(CreateStampInitial());
final repository = Repository();
final formKey = GlobalKey<FormState>();
final descriptionCtl = TextEditingController();
final quantityCtl = TextEditingController();
final expiredDateCtl = TextEditingController();
var stampTypeRaws = <StampType>[];
var stampTypes = ValueNotifier(<ItemDropDown>[]);
var selectedStampType = ValueNotifier('');
// var existedCreateStamp = UpdateCreateStamp();

void dispose() {
descriptionCtl.dispose();
quantityCtl.dispose();
expiredDateCtl.dispose();
}

Future<void> preparedData() async {
try {
await Future.delayed(const Duration(seconds: 0));
emit(CreateStampLoading());
stampTypeRaws = await repository.stampTypes();
stampTypes.value = stampTypeRaws
.map(
(e) => ItemDropDown(key: e.id?.toString(), value: e.exampleStampName),
)
.toList();
emit(CreateStampPrepareDataSuccessful());
} catch (e) {
emit(CreateStampFailure(AppException.handleError(e)));
}
}

Future<void> onSubmit() async {
if (formKey.currentState!.validate()) {
var requestStamp = RequestStamp();
var stamp = stampTypeRaws.firstWhere(
(e) => selectedStampType.value == e.id?.toString(),
orElse: () => StampType(),
);
var expiredDate = DateTime.now().add(Duration(days: int.tryParse(expiredDateCtl.text) ?? 0));
requestStamp
..description = descriptionCtl.text
..quantity = int.tryParse(quantityCtl.text) ?? 0
..expiredDate = expiredDate.convertLocalDateTimeToStringUtcDateTime()
..tbExampleStampId = int.tryParse(selectedStampType.value);
print(requestStamp.toJson());
UtilWidget.showLoading();
await repository.createStamp(
(success) {
UtilWidget.hideDialog();
Get.back(result: 'ok');
Utils.showSnackBarSuccess();
},
(errorMessage) {
UtilWidget.hideDialog();
Utils.showSnackBarError();
},
item: requestStamp,
);
}
}
}

+ 22
- 0
lib/presentation/screens/codes/cubit/create_stamp_state.dart View File

@@ -0,0 +1,22 @@
part of 'create_stamp_cubit.dart';

class CreateStampState extends Equatable {
const CreateStampState();

@override
List<Object> get props => [];
}

class CreateStampInitial extends CreateStampState {}

class CreateStampLoading extends CreateStampState {}

class CreateStampFailure extends CreateStampState {
final String errorMessage;

CreateStampFailure(this.errorMessage);
}

class CreateStampPrepareDataSuccessful extends CreateStampState {
CreateStampPrepareDataSuccessful();
}

+ 53
- 0
lib/presentation/screens/codes/models/stamp.dart View File

@@ -0,0 +1,53 @@
import '../../../../custom_model/TbCropDTO.dart';

class Stamp {
int? id;
TbCropDTO? tbCropDTO;
String? code;
num? quantity;
String? description;
String? pathImage;
String? status;
String? expiredDate;
String? createdDate;

Stamp({
this.id,
this.tbCropDTO,
this.code,
this.quantity,
this.description,
this.pathImage,
this.status,
this.expiredDate,
this.createdDate,
});

Stamp.fromJson(Map<String, dynamic> json) {
id = json['id'];
tbCropDTO = json['TbCropDTO'] != null ? new TbCropDTO.fromJson(json['TbCropDTO']) : null;
code = json['code'];
quantity = json['quantity'];
description = json['description'];
pathImage = json['pathImage'];
status = json['status'];
expiredDate = json['expiredDate'];
createdDate = json['createdDate'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
if (this.tbCropDTO != null) {
data['TbCropDTO'] = this.tbCropDTO?.toJson();
}
data['code'] = this.code;
data['quantity'] = this.quantity;
data['description'] = this.description;
data['pathImage'] = this.pathImage;
data['status'] = this.status;
data['expiredDate'] = this.expiredDate;
data['createdDate'] = this.createdDate;
return data;
}
}

+ 33
- 0
lib/presentation/screens/codes/models/stamp_request.dart View File

@@ -0,0 +1,33 @@
class RequestStamp {
int? tBCropId;
int? tbExampleStampId;
int? quantity;
String? description;
String? expiredDate;

RequestStamp({
this.tBCropId,
this.tbExampleStampId,
this.quantity,
this.description,
this.expiredDate,
});

RequestStamp.fromJson(Map<String, dynamic> json) {
tBCropId = json['tBCropId'];
tbExampleStampId = json['tbExampleStampId'];
quantity = json['quantity'];
description = json['description'];
expiredDate = json['expiredDate'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['tBCropId'] = this.tBCropId;
data['tbExampleStampId'] = this.tbExampleStampId;
data['quantity'] = this.quantity;
data['description'] = this.description;
data['expiredDate'] = this.expiredDate;
return data;
}
}

+ 21
- 0
lib/presentation/screens/codes/models/stamp_type.dart View File

@@ -0,0 +1,21 @@
class StampType {
int? id;
String? exampleStampName;
String? exampleStampImage;

StampType({this.id, this.exampleStampName, this.exampleStampImage});

StampType.fromJson(Map<String, dynamic> json) {
id = json['id'];
exampleStampName = json['exampleStampName'];
exampleStampImage = json['exampleStampImage'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['exampleStampName'] = this.exampleStampName;
data['exampleStampImage'] = this.exampleStampImage;
return data;
}
}

+ 20
- 5
lib/presentation/screens/codes/widgets/item_code.dart View File

@@ -1,17 +1,32 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'package:flutter/material.dart';

import 'package:farm_tpf/presentation/screens/codes/models/stamp.dart';

import '../../../../themes/app_colors.dart';
import '../../../../themes/styles_text.dart';
import 'package:farm_tpf/utils/formatter.dart';

class ItemCode extends StatelessWidget {
final Stamp item;
final Function onPressed;
const ItemCode({
super.key,
ItemCode({
Key? key,
required this.item,
required this.onPressed,
});
}) : super(key: key);

@override
Widget build(BuildContext context) {
var expiredDate = item.expiredDate?.format_DDMMYY().toString() ?? '';
var quantity = item.quantity;
var status = 'mới';
switch (item.status) {
case 'NEW':
status = 'mới';
break;
default:
}
return GestureDetector(
onTap: () {
onPressed();
@@ -31,14 +46,14 @@ class ItemCode extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Cà chua đợt 1 5/2023',
item.description ?? '',
style: StylesText.body1,
),
const SizedBox(
height: 8,
),
Text(
'06/05/2023 - 1500 tem - mới',
'$expiredDate - $quantity tem - $status',
style: StylesText.body6,
),
],

+ 9
- 9
lib/presentation/screens/tabbar/tabbar.dart View File

@@ -42,8 +42,8 @@ class _TabbarScreenState extends State<TabbarScreen> {
final changeTabbar = Get.put(TabbarSelected());
List<TabbarItem> itemsTabbar = [
TabbarItem(icon: AppIcons.icPlot, title: 'Lô trồng', index: TabBarIndex.plot),
TabbarItem(icon: AppIcons.icDevice, title: 'Thiết bị', index: TabBarIndex.device),
// TabbarItem(icon: AppIcons.icQrManage, title: 'Quản lý QR', index: TabBarIndex.qrManage),
// TabbarItem(icon: AppIcons.icDevice, title: 'Thiết bị', index: TabBarIndex.device),
TabbarItem(icon: AppIcons.icQrManage, title: 'Quản lý QR', index: TabBarIndex.qrManage),
TabbarItem(icon: AppIcons.icQr, title: 'Quét QR', index: TabBarIndex.qr),
TabbarItem(icon: AppIcons.icNotification, title: 'Thông báo', index: TabBarIndex.notification),
TabbarItem(icon: AppIcons.icPerson, title: 'Cá nhân', index: TabBarIndex.account)
@@ -209,12 +209,12 @@ class _TabbarScreenState extends State<TabbarScreen> {
case TabBarIndex.plot:
return PlotListScreen();
break;
case TabBarIndex.device:
return ControlDeviceScreen();
break;
// case TabBarIndex.qrManage:
// return CodePage();
// case TabBarIndex.device:
// return ControlDeviceScreen();
// break;
case TabBarIndex.qrManage:
return CodePage();
break;
case TabBarIndex.qr:
return Container();
break;
@@ -351,8 +351,8 @@ class TabbarSelected extends GetxController {

enum TabBarIndex {
plot,
device,
// qrManage,
// device,
qrManage,
qr,
notification,
account,

+ 10
- 0
lib/utils/formatter.dart View File

@@ -45,6 +45,16 @@ extension ddMM_HHmm on String {
}
}

String format_DDMMYY() {
try {
final str = this.toString();
var dateFromString = DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(str, true).toLocal();
return DateFormat("dd/MM/yyyy").format(dateFromString);
} catch (_) {
return "";
}
}

DateTime convertStringServerDateTimeToLocalDateTime() {
try {
return DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(this, true).toLocal();

Loading…
Cancel
Save