Browse Source

update activity stamp

bugfix/20250501
Đại Võ 1 year ago
parent
commit
b7fa73253f
7 changed files with 245 additions and 37 deletions
  1. +34
    -0
      lib/data/repository/repository.dart
  2. +4
    -2
      lib/presentation/screens/codes/code_detail_page.dart
  3. +83
    -0
      lib/presentation/screens/codes/cubit/update_activity_cubit.dart
  4. +22
    -0
      lib/presentation/screens/codes/cubit/update_activity_state.dart
  5. +27
    -0
      lib/presentation/screens/codes/models/activity_request.dart
  6. +21
    -0
      lib/presentation/screens/codes/models/activity_type.dart
  7. +54
    -35
      lib/presentation/screens/codes/update_activity_page.dart

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

import 'package:farm_tpf/data/api/dio_provider.dart'; import 'package:farm_tpf/data/api/dio_provider.dart';
import 'package:farm_tpf/data/api/rest_client.dart'; import 'package:farm_tpf/data/api/rest_client.dart';
import 'package:farm_tpf/models/PagedResult.dart'; import 'package:farm_tpf/models/PagedResult.dart';
import 'package:farm_tpf/presentation/screens/codes/models/activity_request.dart';
import 'package:farm_tpf/presentation/screens/codes/models/activity_type.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp.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/presentation/screens/codes/models/stamp_request.dart';
import 'package:farm_tpf/utils/const_common.dart'; import 'package:farm_tpf/utils/const_common.dart';
onError(AppException.handleError(e)); onError(AppException.handleError(e));
} }
} }

Future<List<ActivityType>> activityTypes() async {
try {
var url = '${ConstCommon.baseUrl}/api/tb-activity-types-dropdown-list-after-harvest';
var res = await dio.get(
url,
);
return (res.data as List).map((e) => ActivityType.fromJson(e)).toList();
} catch (e) {
rethrow;
}
}

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

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

+ 4
- 2
lib/presentation/screens/codes/code_detail_page.dart View File

import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart';
import 'package:farm_tpf/presentation/custom_widgets/button/second_button.dart'; import 'package:farm_tpf/presentation/custom_widgets/button/second_button.dart';
import 'package:farm_tpf/presentation/screens/codes/code_update_timeline_page.dart';
import 'package:farm_tpf/presentation/screens/codes/update_activity_page.dart';
import 'package:farm_tpf/presentation/screens/codes/widgets/item_code_timeline.dart'; import 'package:farm_tpf/presentation/screens/codes/widgets/item_code_timeline.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
appBar: AppBarWidget( appBar: AppBarWidget(
action: IconButton( action: IconButton(
onPressed: () { onPressed: () {
Get.to(() => CodeUpdateTimelinePage());
Get.to(() => UpdateActivityPage(
stampCode: 'AC_494D9D90',
));
}, },
icon: Icon( icon: Icon(
Icons.edit, Icons.edit,

+ 83
- 0
lib/presentation/screens/codes/cubit/update_activity_cubit.dart View File

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:farm_tpf/presentation/screens/codes/models/activity_request.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';
import '../../../custom_widgets/widget_utils.dart';
import '../models/activity_type.dart';

part 'update_activity_state.dart';

class UpdateActivityCubit extends Cubit<UpdateActivityState> {
UpdateActivityCubit() : super(UpdateActivityInitial());
final repository = Repository();
final formKey = GlobalKey<FormState>();
var actionDate = ValueNotifier(DateTime.now());
final descriptionCtl = TextEditingController();
final locationCtl = TextEditingController();
final expiredDateCtl = TextEditingController();
var activityTypeRaws = <ActivityType>[];
var activityTypes = ValueNotifier(<ItemDropDown>[]);
var selectedActivityType = ValueNotifier('');
// var existedUpdateActivity = UpdateUpdateActivity();

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

Future<void> preparedData() async {
try {
await Future.delayed(const Duration(seconds: 0));
emit(UpdateActivityLoading());
activityTypeRaws = await repository.activityTypes();
activityTypes.value = activityTypeRaws
.map(
(e) => ItemDropDown(key: e.id?.toString(), value: e.description),
)
.toList();
emit(UpdateActivityPrepareDataSuccessful());
} catch (e) {
emit(UpdateActivityFailure(AppException.handleError(e)));
}
}

Future<void> onSubmit(String stampCode) async {
if (formKey.currentState!.validate()) {
var requestActivity = ActivityRequest();

var activity = activityTypeRaws.firstWhere(
(e) => selectedActivityType.value == e.id?.toString(),
orElse: () => ActivityType(),
);

requestActivity
..code = stampCode
..description = descriptionCtl.text
..location = locationCtl.text
..executeDate = actionDate.value.convertLocalDateTimeToStringUtcDateTime()
..activityTypeId = activity.id;
print(requestActivity.toJson());
UtilWidget.showLoading();
await repository.updateActivity(
(success) {
UtilWidget.hideDialog();
Get.back(result: 'ok');
Utils.showSnackBarSuccess();
},
(errorMessage) {
UtilWidget.hideDialog();
Utils.showSnackBarError();
},
item: requestActivity,
);
}
}
}

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

part of 'update_activity_cubit.dart';

class UpdateActivityState extends Equatable {
const UpdateActivityState();

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

class UpdateActivityInitial extends UpdateActivityState {}

class UpdateActivityLoading extends UpdateActivityState {}

class UpdateActivityFailure extends UpdateActivityState {
final String errorMessage;

UpdateActivityFailure(this.errorMessage);
}

class UpdateActivityPrepareDataSuccessful extends UpdateActivityState {
UpdateActivityPrepareDataSuccessful();
}

+ 27
- 0
lib/presentation/screens/codes/models/activity_request.dart View File

class ActivityRequest {
String? code;
int? activityTypeId;
String? executeDate;
String? description;
String? location;

ActivityRequest({this.code, this.activityTypeId, this.executeDate, this.description, this.location});

ActivityRequest.fromJson(Map<String, dynamic> json) {
code = json['code'];
activityTypeId = json['activityTypeId'];
executeDate = json['executeDate'];
description = json['description'];
location = json['location'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['code'] = this.code;
data['activityTypeId'] = this.activityTypeId;
data['executeDate'] = this.executeDate;
data['description'] = this.description;
data['location'] = this.location;
return data;
}
}

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

class ActivityType {
int? id;
String? name;
String? description;

ActivityType({this.id, this.name, this.description});

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

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

lib/presentation/screens/codes/code_update_timeline_page.dart → lib/presentation/screens/codes/update_activity_page.dart View File

import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart';
import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart';
import 'package:farm_tpf/presentation/screens/codes/cubit/code_update_timeline_cubit.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart'; import 'package:keyboard_dismisser/keyboard_dismisser.dart';


import '../../../models/item_dropdown.dart';
import '../../../utils/utils.dart'; import '../../../utils/utils.dart';
import '../../custom_widgets/date_picker/date_picker_widget.dart'; import '../../custom_widgets/date_picker/date_picker_widget.dart';
import '../../custom_widgets/dropdown/dropdown_bottom_sheet.dart'; import '../../custom_widgets/dropdown/dropdown_bottom_sheet.dart';
import '../../custom_widgets/textfield/text_field_normal.dart'; import '../../custom_widgets/textfield/text_field_normal.dart';
import 'cubit/update_activity_cubit.dart';
import 'widgets/item_column.dart'; import 'widgets/item_column.dart';


class CodeUpdateTimelinePage extends StatefulWidget {
const CodeUpdateTimelinePage({super.key});
class UpdateActivityPage extends StatefulWidget {
final String stampCode;
const UpdateActivityPage({super.key, required this.stampCode});


@override @override
State<CodeUpdateTimelinePage> createState() => _CodeUpdateTimelinePageState();
State<UpdateActivityPage> createState() => _UpdateActivityPageState();
} }


class _CodeUpdateTimelinePageState extends State<CodeUpdateTimelinePage> {
final bloc = CodeUpdateTimelineCubit();
class _UpdateActivityPageState extends State<UpdateActivityPage> {
final bloc = UpdateActivityCubit();


@override @override
void initState() { void initState() {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBarWidget(), appBar: AppBarWidget(),
body: BlocListener<CodeUpdateTimelineCubit, CodeUpdateTimelineState>(
body: BlocListener<UpdateActivityCubit, UpdateActivityState>(
bloc: bloc, bloc: bloc,
listener: ((context, state) { listener: ((context, state) {
if (state is CodeUpdateTimelineLoading) {
if (state is UpdateActivityLoading) {
SchedulerBinding.instance.addPostFrameCallback((timeStamp) { SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
UtilWidget.showLoading(); UtilWidget.showLoading();
}); });
} else if (state is CodeUpdateTimelineFailure) {
} else if (state is UpdateActivityFailure) {
SchedulerBinding.instance.addPostFrameCallback((timeStamp) { SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
UtilWidget.hideLoading(); UtilWidget.hideLoading();
// UtilWidget.showToastError(state.errorMessage); // UtilWidget.showToastError(state.errorMessage);
}); });
} else if (state is CodeUpdateTimelinePrepareDataSuccessful) {
} else if (state is UpdateActivityPrepareDataSuccessful) {
SchedulerBinding.instance.addPostFrameCallback((timeStamp) { SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
UtilWidget.hideLoading(); UtilWidget.hideLoading();
}); });
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: ButtonWidget( child: ButtonWidget(
title: 'Cập nhật', title: 'Cập nhật',
onPressed: () {},
onPressed: () {
bloc.onSubmit(widget.stampCode);
},
), ),
), ),
], ],
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ItemColumnWidget(
title: 'Hoạt động',
child: ValueListenableBuilder<String>(
valueListenable: bloc.selectedActivityType,
builder: (context, selected, _) {
return ValueListenableBuilder<List<ItemDropDown>>(
valueListenable: bloc.activityTypes,
builder: (context, types, _) {
return DropdownBottomSheet(
dataSources: types,
initValue: selected,
onSelected: (val) {
bloc.selectedActivityType.value = val.key ?? '';
},
hint: 'Hoạt động',
);
},
);
}),
),
const SizedBox(
height: 8,
),
ItemColumnWidget(
title: 'Mô tả',
child: TextFieldNormal(
controller: bloc.descriptionCtl,
maxLines: 1,
hint: 'Mô tả',
),
),
SizedBox(
height: 8,
),
ValueListenableBuilder<DateTime>( ValueListenableBuilder<DateTime>(
valueListenable: bloc.actionDate, valueListenable: bloc.actionDate,
builder: (context, actionDate, _) { builder: (context, actionDate, _) {
return ItemColumnWidget( return ItemColumnWidget(
title: 'Ngày nhập',
title: 'Ngày cập nhập',
child: DatePickerWidget( child: DatePickerWidget(
initDateTime: actionDate, initDateTime: actionDate,
onUpdateDateTime: (selectedDate) { onUpdateDateTime: (selectedDate) {
height: 8, height: 8,
), ),
ItemColumnWidget( ItemColumnWidget(
title: 'Hoạt động',
child: ValueListenableBuilder<String>(
valueListenable: bloc.selectedActionType,
builder: (context, selected, _) {
return DropdownBottomSheet(
dataSources: bloc.actionTypes,
initValue: selected,
onSelected: (val) {
bloc.selectedActionType.value = val.key ?? '';
},
hint: 'Hoạt động',
);
},
),
),
const SizedBox(
height: 8,
),
ItemColumnWidget(
title: 'Mô tả',
title: 'Vị trí',
child: TextFieldNormal( child: TextFieldNormal(
controller: bloc.descriptionCtl,
maxLines: 2,
hint: 'Mô tả',
controller: bloc.locationCtl,
maxLines: 1,
hint: 'Vị trí',
), ),
), ),
const SizedBox( const SizedBox(

Loading…
Cancel
Save