Browse Source

update feature task and crop

phase2_dev
Đại Võ 1 year ago
parent
commit
6f786cccb7
15 changed files with 479 additions and 124 deletions
  1. +6
    -6
      ios/Runner.xcodeproj/project.pbxproj
  2. +44
    -0
      lib/data/repository/repository.dart
  3. +6
    -0
      lib/main.dart
  4. +47
    -4
      lib/presentation/screens/plot/bloc/plot_bloc.dart
  5. +18
    -0
      lib/presentation/screens/plot/models/crop_filter_request.dart
  6. +108
    -104
      lib/presentation/screens/plot/sc_plot.dart
  7. +3
    -1
      lib/presentation/screens/task/bloc/task_bloc.dart
  8. +47
    -0
      lib/presentation/screens/task/cubit/task_detail_cubit.dart
  9. +23
    -0
      lib/presentation/screens/task/cubit/task_detail_state.dart
  10. +21
    -0
      lib/presentation/screens/task/models/supply_filter.dart
  11. +2
    -2
      lib/presentation/screens/task/models/task.dart
  12. +3
    -0
      lib/presentation/screens/task/models/task_filter_request.dart
  13. +139
    -0
      lib/presentation/screens/task/task_detail_page.dart
  14. +11
    -6
      lib/presentation/screens/task/task_page.dart
  15. +1
    -1
      pubspec.yaml

+ 6
- 6
ios/Runner.xcodeproj/project.pbxproj View File

@@ -369,7 +369,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 22;
CURRENT_PROJECT_VERSION = 23;
DEVELOPMENT_TEAM = C3DTD2JH94;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -385,7 +385,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.6;
MARKETING_VERSION = 1.1.7;
PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -511,7 +511,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 22;
CURRENT_PROJECT_VERSION = 23;
DEVELOPMENT_TEAM = C3DTD2JH94;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -527,7 +527,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.6;
MARKETING_VERSION = 1.1.7;
PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -547,7 +547,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 22;
CURRENT_PROJECT_VERSION = 23;
DEVELOPMENT_TEAM = C3DTD2JH94;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -563,7 +563,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.6;
MARKETING_VERSION = 1.1.7;
PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

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

@@ -25,7 +25,9 @@ import 'package:farm_tpf/presentation/screens/codes/models/stamp.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp_filter_request.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp_request.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp_timeline.dart';
import 'package:farm_tpf/presentation/screens/plot/models/crop_filter_request.dart';
import 'package:farm_tpf/presentation/screens/task/models/employee.dart';
import 'package:farm_tpf/presentation/screens/task/models/supply_filter.dart';
import 'package:farm_tpf/presentation/screens/task/models/task_request.dart';
import 'package:farm_tpf/utils/const_common.dart';
import 'package:flutter/material.dart';
@@ -459,6 +461,7 @@ class Repository {
var url = '${ConstCommon.baseUrl}/api/tb-todo-lists/list?page=$page&size=$size';
var res = await dio.post(url, data: {
// 'status': filter.status,
"crop_id": filter.cropId,
});

return (res.data as List).map((e) => Task.fromJson(e)).toList();
@@ -518,4 +521,45 @@ class Repository {
rethrow;
}
}

Future<List<SupplyFilter>> getSuppliesFilter() async {
try {
var url = '${ConstCommon.baseUrl}/api/tb-supplies/by-login-info/';
var res = await dio.get(
url,
);
return (res.data as List).map((e) => SupplyFilter.fromJson(e)).toList();
} catch (e) {
rethrow;
}
}

// Crop
Future<List<TbCropDTO>> crops({
int page = 0,
int size = 20,
required CropFilterRequest filter,
}) async {
try {
// var url = '${ConstCommon.baseUrl}/api/tb-todo-lists/list?page=$page&size=$size&sort=createdDate,${filter.sort ?? 'asc'}';
var url = '${ConstCommon.baseUrl}/api/tb-crops/list?page=$page&size=$size';
var res = await dio.post(url, data: {
'tbSuppliesIds': filter.supplyIds,
});

return (res.data as List).map((e) => TbCropDTO.fromJson(e)).toList();
} catch (e) {
rethrow;
}
}

Future<Task> getTaskDetail({required int id}) async {
try {
var url = '${ConstCommon.baseUrl}/api/tb-todo-lists/$id';
var res = await dio.get(url);
return Task.fromJson(res.data);
} catch (e) {
rethrow;
}
}
}

+ 6
- 0
lib/main.dart View File

@@ -4,6 +4,7 @@ import 'dart:io';
import 'package:farm_tpf/data/repository/repository.dart';
import 'package:farm_tpf/presentation/screens/codes/bloc/stamp_bloc.dart';
import 'package:farm_tpf/presentation/screens/codes/cubit/detail_stamp_cubit.dart';
import 'package:farm_tpf/presentation/screens/plot/bloc/plot_bloc.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -52,6 +53,11 @@ Future<void> main() async {
Repository(),
),
),
BlocProvider(
create: (_) => PlotBloc(
repository: Repository(),
),
),
BlocProvider(
create: (_) => DetailStampCubit(),
),

+ 47
- 4
lib/presentation/screens/plot/bloc/plot_bloc.dart View File

@@ -2,10 +2,16 @@ import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:farm_tpf/custom_model/TbCropDTO.dart';
import 'package:farm_tpf/data/api/app_exception.dart';
import 'package:farm_tpf/data/repository/repository.dart';
import 'package:farm_tpf/presentation/screens/plot/models/crop_filter_request.dart';
import 'package:farm_tpf/presentation/screens/task/models/supply_filter.dart';
import 'package:flutter/material.dart';
import 'package:meta/meta.dart';

import '../../../../models/item_dropdown.dart';

part 'plot_event.dart';
part 'plot_state.dart';

@@ -14,6 +20,10 @@ class PlotBloc extends Bloc<PlotEvent, PlotState> {
PlotBloc({required this.repository}) : super(PlotInitial());
static int pageSize = 20;

var supplyRaws = <SupplyFilter>[];
var supplies = ValueNotifier(<ItemDropDown>[]);
var selectedSupply = ValueNotifier(<ItemDropDown>[]);

@override
Stream<PlotState> mapEventToState(
PlotEvent event,
@@ -22,13 +32,16 @@ class PlotBloc extends Bloc<PlotEvent, PlotState> {
try {
if (state is PlotInitial) {
yield PlotLoading();
final response = await repository.getPlots(page: 0, size: pageSize, searchString: "");
final response = await getPlots(0);
yield PlotSuccess(items: response, page: 0, hasReachedMax: response.length < pageSize ? true : false);
}
if (state is PlotSuccess) {
final currentState = state as PlotSuccess;
if (currentState.hasReachedMax ?? false) {
return;
}
int page = (currentState.page ?? 0) + 1;
final response = await repository.getPlots(page: page, size: pageSize, searchString: "");
final response = await getPlots(page);
yield response.isEmpty
? currentState.copyWith(hasReachedMax: true)
: PlotSuccess(
@@ -45,7 +58,7 @@ class PlotBloc extends Bloc<PlotEvent, PlotState> {
if (event is OnRefresh) {
try {
yield PlotLoading();
final response = await repository.getPlots(page: 0, size: pageSize, searchString: "");
final response = await getPlots(0);
yield PlotSuccess(items: response, page: 0, hasReachedMax: response.length < pageSize ? true : false);
} catch (e) {
yield PlotFailure(errorString: AppException.handleError(e));
@@ -53,11 +66,41 @@ class PlotBloc extends Bloc<PlotEvent, PlotState> {
} else if (event is OnSearch) {
try {
yield PlotLoading();
final response = await repository.getPlots(page: 0, size: pageSize, searchString: event.searchString);
final response = await getPlots(0);
yield PlotSuccess(items: response, page: 0, hasReachedMax: response.length < pageSize ? true : false);
} catch (e) {
yield PlotFailure(errorString: AppException.handleError(e));
}
}
}

Future<List<TbCropDTO>> getPlots(int page) async {
var supplyIds = selectedSupply.value.length > 0
? selectedSupply.value
.map(
(e) => int.tryParse(e.key ?? '') ?? -1,
)
.toList()
: <int>[];
var filter = CropFilterRequest()..supplyIds = supplyIds;
return await repository.crops(page: 0, filter: filter);
}

Future<void> preparedData() async {
try {
await Future.delayed(const Duration(seconds: 0));
// emit(CreateStampLoading());

supplyRaws = await repository.getSuppliesFilter();
supplies.value = supplyRaws
.map(
(e) => ItemDropDown(key: e.id?.toString(), value: e.name),
)
.toList();
// emit(CreateStampPrepareDataSuccessful());
} catch (e) {
print(e);
// emit(CreateStampFailure(AppException.handleError(e)));
}
}
}

+ 18
- 0
lib/presentation/screens/plot/models/crop_filter_request.dart View File

@@ -0,0 +1,18 @@
class CropFilterRequest {
List<int>? supplyIds;
String? sort;

CropFilterRequest({this.supplyIds, this.sort});

CropFilterRequest.fromJson(Map<String, dynamic> json) {
supplyIds = json['tbSuppliesIds'].cast<String>();
sort = json['sort'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['tbSuppliesIds'] = this.supplyIds;
data['sort'] = this.sort;
return data;
}
}

+ 108
- 104
lib/presentation/screens/plot/sc_plot.dart View File

@@ -8,6 +8,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:farm_tpf/utils/const_string.dart';

import '../../../models/item_dropdown.dart';
import '../../../utils/helpers.dart';
import '../../custom_widgets/dropdown/multiple_select_bottom_sheet.dart';
import 'bloc/plot_bloc.dart';
import 'widgets/item_plot.dart';

@@ -17,126 +20,28 @@ class PlotListScreen extends StatefulWidget {
}

class _PlotListScreenState extends State<PlotListScreen> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
var pref = LocalPref();
var token;
var client;
String pushkey = "";
String currentFullName = "";

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

@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => PlotBloc(repository: Repository())..add(DataFetched()),
child: HoldInfinityWidget(),
);
}
}

class HoldInfinityWidget extends StatelessWidget {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(backgroundColor: Colors.white, key: _scaffoldKey, body: SafeArea(child: InfinityView()));
}
}

class InfinityView extends StatefulWidget {
@override
_InfinityViewState createState() => _InfinityViewState();
}

class _InfinityViewState extends State<InfinityView> {
PlotBloc bloc = PlotBloc(repository: Repository());
final _scrollController = ScrollController();
final _scrollThreshold = 250.0;
PlotBloc? _plotBloc;

@override
void initState() {
super.initState();
bloc.preparedData();
bloc.add(DataFetched());
_scrollController.addListener(() {
final maxScroll = _scrollController.position.maxScrollExtent;
final currentScroll = _scrollController.position.pixels;
if (maxScroll - currentScroll < _scrollThreshold) {
_plotBloc?.add(DataFetched());
bloc.add(DataFetched());
}
});
_plotBloc = BlocProvider.of<PlotBloc>(context);
super.initState();
}

@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 8,
),
Container(
padding: EdgeInsets.all(8),
color: Colors.white,
child: Text(
'Danh sách lô trồng',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22),
),
),
WidgetSearch(
searchController: TextEditingController(),
onPressed: (value) {
FocusScope.of(context).requestFocus(FocusNode());
BlocProvider.of<PlotBloc>(context).add(OnSearch(searchString: value));
},
),
Expanded(child: BlocBuilder<PlotBloc, PlotState>(
builder: (context, state) {
if (state is PlotFailure) {
return Center(child: Text(state.errorString));
}
if (state is PlotSuccess) {
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()
: ItemPlot(
item: state.items?[index],
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => PlotDetailScreen(
cropId: state.items?[index].id ?? -1,
initialIndex: 0,
cropType: state.items?[index].tbCropTypeId ?? -1,
),
),
);
},
);
},
itemCount: (state.hasReachedMax ?? false) ? (state.items ?? []).length : (state.items ?? []).length + 1,
controller: _scrollController,
),
onRefresh: () async {
_plotBloc?.add(OnRefresh());
},
);
}
return Center(
child: LoadingListPage(),
);
},
))
],
);
}

@override
@@ -144,4 +49,103 @@ class _InfinityViewState extends State<InfinityView> {
_scrollController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
key: _scaffoldKey,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 8,
),
Container(
padding: EdgeInsets.all(8),
color: Colors.white,
child: Text(
'Danh sách lô trồng',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22),
),
),
WidgetSearch(
searchController: TextEditingController(),
onPressed: (value) {
FocusScope.of(context).requestFocus(FocusNode());
BlocProvider.of<PlotBloc>(context).add(OnSearch(searchString: value));
},
),
ValueListenableBuilder<List<ItemDropDown>>(
valueListenable: bloc.selectedSupply,
builder: (context, selecteds, _) {
return ValueListenableBuilder<List<ItemDropDown>>(
valueListenable: bloc.supplies,
builder: (context, status, _) {
return MultipleSelectBottomSheet(
dataSources: status,
initValue: selecteds,
onSelected: (val) {
bloc.selectedSupply.value = val;
Helpers.hideKeyboard(context);
bloc.add(OnRefresh());
},
hint: 'Giống',
);
},
);
},
),
Expanded(
child: BlocBuilder<PlotBloc, PlotState>(
bloc: bloc,
builder: (context, state) {
if (state is PlotFailure) {
return Center(child: Text(state.errorString));
}
if (state is PlotSuccess) {
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()
: ItemPlot(
item: state.items?[index],
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => PlotDetailScreen(
cropId: state.items?[index].id ?? -1,
initialIndex: 0,
cropType: state.items?[index].tbCropTypeId ?? -1,
),
),
);
},
);
},
itemCount: (state.hasReachedMax ?? false) ? (state.items ?? []).length : (state.items ?? []).length + 1,
controller: _scrollController,
),
onRefresh: () async {
bloc.add(OnRefresh());
},
);
}
return Center(
child: LoadingListPage(),
);
},
))
],
),
),
);
}
}

+ 3
- 1
lib/presentation/screens/task/bloc/task_bloc.dart View File

@@ -37,6 +37,7 @@ class TaskBloc extends Bloc<TaskEvent, TaskState> {
.toList(),
);
var sort = ValueNotifier(describeEnum(SortType.asc));
var cropId = -1;

@override
Stream<TaskState> mapEventToState(
@@ -102,6 +103,7 @@ class TaskBloc extends Bloc<TaskEvent, TaskState> {

Future<List<Task>> getListTask(int page) async {
var filter = TaskFilterRequest()
..cropId = cropId
..sort = sort.value
..status = selectedStatus.value.map((e) => e.key ?? '').toList();
return await repository.tasks(page: 0, filter: filter);
@@ -116,7 +118,7 @@ class TaskBloc extends Bloc<TaskEvent, TaskState> {
await repository.updateTask(
(success) {
UtilWidget.hideDialog();
Utils.showSnackBarSuccess();
// Utils.showSnackBarSuccess();
onSuccess();
},
(errorMessage) {

+ 47
- 0
lib/presentation/screens/task/cubit/task_detail_cubit.dart View File

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

import '../../../../data/api/app_exception.dart';
import '../../../../data/repository/repository.dart';
import '../../../../utils/utils.dart';
import '../../../custom_widgets/widget_utils.dart';
import '../models/task.dart';
import '../models/task_update_request.dart';

part 'task_detail_state.dart';

class TaskDetailCubit extends Cubit<TaskDetailState> {
final repository = Repository();
TaskDetailCubit() : super(TaskDetailInitial());

Future<void> preparedData(int taskId) async {
try {
await Future.delayed(const Duration(seconds: 0));
emit(TaskDetailLoading());
var task = await repository.getTaskDetail(id: taskId);
emit(TaskDetailSuccessful(task));
} catch (e) {
emit(TaskDetailFailure(AppException.handleError(e)));
}
}

Future<void> updateStatusTask(
RequestTaskUpdate task,
) async {
print(task.toJson());
UtilWidget.showLoading();
await repository.updateTask(
(success) {
UtilWidget.hideDialog();
Get.back(result: 'ok');
// Utils.showSnackBarSuccess();
},
(errorMessage) {
UtilWidget.hideDialog();
Utils.showSnackBarError();
},
item: task,
);
}
}

+ 23
- 0
lib/presentation/screens/task/cubit/task_detail_state.dart View File

@@ -0,0 +1,23 @@
part of 'task_detail_cubit.dart';

abstract class TaskDetailState extends Equatable {
const TaskDetailState();

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

class TaskDetailInitial extends TaskDetailState {}

class TaskDetailLoading extends TaskDetailState {}

class TaskDetailFailure extends TaskDetailState {
final String errorMessage;

TaskDetailFailure(this.errorMessage);
}

class TaskDetailSuccessful extends TaskDetailState {
final Task task;
TaskDetailSuccessful(this.task);
}

+ 21
- 0
lib/presentation/screens/task/models/supply_filter.dart View File

@@ -0,0 +1,21 @@
class SupplyFilter {
int? id;
String? name;

SupplyFilter({
this.id,
this.name,
});

SupplyFilter.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}

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

+ 2
- 2
lib/presentation/screens/task/models/task.dart View File

@@ -22,7 +22,7 @@ class Task {
id = json['id'];
description = json['detail'];
dueDate = json['deadline'];
executeDate = json['executeDate'];
executeDate = json['completedAt'];
assigned = json['assigned'] != null ? new Assigned.fromJson(json['assigned']) : null;
isCompleted = json['completed'];
}
@@ -33,7 +33,7 @@ class Task {
data['title'] = this.title;
data['detail'] = this.description;
data['deadline'] = this.dueDate;
data['executeDate'] = this.executeDate;
data['completedAt'] = this.executeDate;
if (this.assigned != null) {
data['assigned'] = this.assigned?.toJson();
}

+ 3
- 0
lib/presentation/screens/task/models/task_filter_request.dart View File

@@ -1,18 +1,21 @@
class TaskFilterRequest {
List<String>? status;
String? sort;
int? cropId;

TaskFilterRequest({this.status, this.sort});

TaskFilterRequest.fromJson(Map<String, dynamic> json) {
status = json['status'].cast<String>();
sort = json['sort'];
cropId = json['cropId'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['sort'] = this.sort;
data['cropId'] = this.cropId;
return data;
}
}

+ 139
- 0
lib/presentation/screens/task/task_detail_page.dart View File

@@ -0,0 +1,139 @@
import 'package:farm_tpf/presentation/custom_widgets/checkbox/checkbox_widget.dart';
import 'package:farm_tpf/presentation/screens/task/models/task_update_request.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter/src/widgets/placeholder.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../../themes/styles_text.dart';
import '../../custom_widgets/app_bar_widget.dart';
import '../../custom_widgets/loading_list_page.dart';
import 'cubit/task_detail_cubit.dart';
import 'package:farm_tpf/utils/formatter.dart';

class TaskDetailPage extends StatefulWidget {
final int taskId;
const TaskDetailPage({super.key, required this.taskId});

@override
State<TaskDetailPage> createState() => _TaskDetailPageState();
}

class _TaskDetailPageState extends State<TaskDetailPage> {
var bloc = TaskDetailCubit();
@override
void initState() {
super.initState();
bloc.preparedData(widget.taskId);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBarWidget(),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Expanded(
child: BlocBuilder<TaskDetailCubit, TaskDetailState>(
bloc: bloc,
builder: (context, state) {
if (state is TaskDetailLoading) {
return Center(
child: LoadingListPage(),
);
} else if (state is TaskDetailFailure) {
return Center(child: Text(state.errorMessage));
} else if (state is TaskDetailSuccessful) {
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_itemTaskDetail(
title: '',
detail: state.task.title ?? '',
titleStyle: StylesText.body1,
detailStyle: StylesText.body1.copyWith(
color: Colors.blue,
),
),
_itemTaskDetail(title: 'Hạn chót : ', detail: state.task.dueDate?.format_DDMMYY().toString() ?? ''),
(state.task.isCompleted ?? false)
? _itemTaskDetail(title: 'Thời gian hoàn thành : ', detail: state.task.executeDate?.format_DDMMYY().toString() ?? '')
: const SizedBox.shrink(),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
child: Text(
'Mô tả công việc :',
style: StylesText.body2,
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
child: Text(
state.task.description ?? '',
style: StylesText.body3,
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
child: CheckboxWidget(
title: 'Hoàn thành',
style: StylesText.body2,
isChecked: state.task.isCompleted ?? false,
onChange: (status) {
bloc.updateStatusTask(
RequestTaskUpdate(
id: widget.taskId,
completed: status,
),
);
},
),
),
const SizedBox(
height: 8,
),
],
),
);
}
return const SizedBox.shrink();
},
)),
const SizedBox(
height: 8,
),
],
),
),
);
}

Widget _itemTaskDetail({
required String title,
required String detail,
TextStyle? titleStyle,
TextStyle? detailStyle,
}) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: titleStyle ?? StylesText.body2,
),
Expanded(
child: Text(
'$detail',
style: detailStyle ?? StylesText.body3,
),
)
],
),
);
}
}

+ 11
- 6
lib/presentation/screens/task/task_page.dart View File

@@ -24,6 +24,7 @@ import '../../custom_widgets/loading_list_page.dart';
import '../plot/widget_search.dart';
import 'bloc/task_bloc.dart';
import 'create_task_page.dart';
import 'task_detail_page.dart';
import 'widgets/task_item.dart';

class TaskPage extends StatefulWidget {
@@ -42,6 +43,7 @@ class _TaskPageState extends State<TaskPage> {

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

_scrollController.addListener(() {
@@ -157,12 +159,15 @@ class _TaskPageState extends State<TaskPage> {
: ItemTask(
item: state.items?[index],
onPressed: () {
// Get.to(
// () => TaskDetailPage(
// stampId: state.items?[index].id,
// stampTask: state.items?[index].code,
// ),
// );
Get.to(
() => TaskDetailPage(
taskId: state.items?[index].id,
),
)?.then((value) {
if (value != null) {
bloc.add(OnRefresh());
}
});
},
onChangedStatus: (status) {
bloc.updateStatusTask(

+ 1
- 1
pubspec.yaml View File

@@ -2,7 +2,7 @@ name: farm_tpf
description: A new Flutter project.

publish_to: 'none'
version: 1.1.7+23
version: 1.1.8+24

environment:
sdk: ">=2.17.0 <=3.0.0"

Loading…
Cancel
Save