Browse Source

detail stamp, timeline, update stamp status

phase2_dev
Đại Võ 1 year ago
parent
commit
72495786ef
12 changed files with 339 additions and 154 deletions
  1. +42
    -0
      lib/data/repository/repository.dart
  2. +4
    -0
      lib/main.dart
  3. +3
    -3
      lib/presentation/screens/codes/bloc/stamp_state.dart
  4. +95
    -38
      lib/presentation/screens/codes/code_detail_page.dart
  5. +6
    -1
      lib/presentation/screens/codes/code_page.dart
  6. +0
    -67
      lib/presentation/screens/codes/cubit/code_update_timeline_cubit.dart
  7. +0
    -22
      lib/presentation/screens/codes/cubit/code_update_timeline_state.dart
  8. +54
    -0
      lib/presentation/screens/codes/cubit/detail_stamp_cubit.dart
  9. +24
    -0
      lib/presentation/screens/codes/cubit/detail_stamp_state.dart
  10. +8
    -0
      lib/presentation/screens/codes/models/stamp.dart
  11. +87
    -0
      lib/presentation/screens/codes/models/stamp_timeline.dart
  12. +16
    -23
      lib/presentation/screens/codes/widgets/item_code_timeline.dart

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

@@ -23,6 +23,7 @@ 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_request.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp_timeline.dart';
import 'package:farm_tpf/utils/const_common.dart';
import 'package:flutter/material.dart';

@@ -365,4 +366,45 @@ class Repository {
onError(AppException.handleError(e));
}
}

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

Future<StampTimeline> getStampTimeline({required int stampId}) async {
try {
var url = '${ConstCommon.baseUrl}/api/tb-codes-timeline/$stampId';
var res = await dio.get(url);
return StampTimeline.fromJson(res.data);
} catch (e) {
rethrow;
}
}

Future<void> updateStampStatus(
Function(dynamic) onSuccess,
Function(String) onError, {
required int stampId,
required String status,
}) async {
try {
var url = '${ConstCommon.baseUrl}/api/tb-codes/update/$stampId/status/$status';

await dio.put(url).then(
(value) {
onSuccess(value);
},
).catchError((e) {
onError(AppException.handleError(e));
});
} catch (e) {
onError(AppException.handleError(e));
}
}
}

+ 4
- 0
lib/main.dart View File

@@ -3,6 +3,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:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -45,6 +46,9 @@ Future<void> main() async {
Repository(),
),
),
BlocProvider(
create: (_) => DetailStampCubit(),
),
],
child: App(
authenticationRepository: AuthenticationRepository(),

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

@@ -16,14 +16,14 @@ class StampFailure extends StampState {
StampFailure({required this.errorString});
}

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

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

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

+ 95
- 38
lib/presentation/screens/codes/code_detail_page.dart View File

@@ -1,29 +1,49 @@
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/screens/codes/cubit/detail_stamp_cubit.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp_timeline.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:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get/get.dart';
import 'package:farm_tpf/utils/formatter.dart';

import '../../../themes/styles_text.dart';
import '../../custom_widgets/loading_list_page.dart';

class CodeDetailPage extends StatefulWidget {
const CodeDetailPage({super.key});
final int stampId;
final String stampCode;
const CodeDetailPage({
super.key,
required this.stampId,
required this.stampCode,
});

@override
State<CodeDetailPage> createState() => _CodeDetailPageState();
}

class _CodeDetailPageState extends State<CodeDetailPage> {
var bloc = DetailStampCubit();
@override
void initState() {
super.initState();
bloc.preparedData(widget.stampId);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBarWidget(
action: IconButton(
onPressed: () {
Get.to(() => UpdateActivityPage(
stampCode: 'AC_494D9D90',
));
// Get.to(
// () => UpdateActivityPage(
// stampCode: widget.stampCode,
// ),
// );
},
icon: Icon(
Icons.edit,
@@ -36,39 +56,54 @@ class _CodeDetailPageState extends State<CodeDetailPage> {
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
_itemCodeDetail(
title: 'Tên sản phẩm',
detail: 'Cà rốt',
titleStyle: StylesText.body4,
detailStyle: StylesText.body4.copyWith(
color: Colors.blue,
),
child: BlocBuilder<DetailStampCubit, DetailStampState>(
bloc: bloc,
builder: (context, state) {
if (state is DetailStampLoading) {
return Center(
child: LoadingListPage(),
);
} else if (state is DetailStampFailure) {
return Center(child: Text(state.errorMessage));
} else if (state is DetailStampSuccessful) {
var stamp = state.stamp;
return SingleChildScrollView(
child: Column(
children: [
_itemCodeDetail(
title: 'Tên sản phẩm',
detail: 'Cà rốt',
titleStyle: StylesText.body4,
detailStyle: StylesText.body4.copyWith(
color: Colors.blue,
),
),
_itemCodeDetail(title: 'Mô tả', detail: stamp.description ?? ''),
_itemCodeDetail(title: 'Số lượng tem', detail: stamp.quantity?.formatNumtoStringDecimal().toString() ?? ''),
_itemCodeDetail(title: 'Trạng thái', detail: stamp.status ?? ''),
_itemCodeDetail(title: 'Hạn sử dụng', detail: stamp.expiredDate?.format_DDMMYY().toString() ?? ''),
_itemCodeDetail(title: 'Mẫu tem', detail: stamp.stampType?.exampleStampName ?? ''),
const SizedBox(
height: 8,
),
Text(
'Timeline hoạt động',
style: StylesText.body1,
),
const SizedBox(
height: 8,
),
_timelineWidget(state.timeline),
],
),
_itemCodeDetail(title: 'Mô tả', detail: 'detail'),
_itemCodeDetail(title: 'Số lượng tem', detail: 'detail'),
_itemCodeDetail(title: 'Trạng thái', detail: 'detail'),
_itemCodeDetail(title: 'Hạn sử dụng', detail: 'detail'),
_itemCodeDetail(title: 'Mẫu tem', detail: 'detail'),
Text(
'Timeline hoạt động',
style: StylesText.body1,
),
_timelineWidget(),
],
),
),
),
);
}
return const SizedBox.shrink();
},
)),
const SizedBox(
height: 8,
),
// Container(
// width: 100,
// height: 100,
// color: Colors.red,
// ),
_actionButtonWidget(),
],
),
@@ -76,14 +111,16 @@ class _CodeDetailPageState extends State<CodeDetailPage> {
);
}

Widget _timelineWidget() {
Widget _timelineWidget(StampTimeline timeline) {
if ((timeline.content?.length ?? 0) == 0) return const SizedBox.shrink();
return ListView.builder(
itemBuilder: (context, index) {
return ItemCodeTimeline(
item: timeline.content![index],
onPressed: () {},
);
},
itemCount: 20,
itemCount: timeline.content?.length ?? 0,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
);
@@ -97,7 +134,12 @@ class _CodeDetailPageState extends State<CodeDetailPage> {
children: [
Expanded(
child: SecondButton(
onPressed: () {},
onPressed: () {
bloc.updateStampStatus(
stampId: widget.stampId,
status: 'ACTIVE',
);
},
title: 'Kích hoạt toàn bộ',
borderColor: Colors.blue,
textColor: Colors.blue,
@@ -107,7 +149,12 @@ class _CodeDetailPageState extends State<CodeDetailPage> {
),
Expanded(
child: SecondButton(
onPressed: () {},
onPressed: () {
bloc.updateStampStatus(
stampId: widget.stampId,
status: 'CANCELED',
);
},
title: 'Huỷ toàn bộ',
borderColor: Colors.red,
textColor: Colors.white,
@@ -125,7 +172,17 @@ class _CodeDetailPageState extends State<CodeDetailPage> {
children: [
Expanded(
child: SecondButton(
onPressed: () {},
onPressed: () {
Get.to(
() => UpdateActivityPage(
stampCode: widget.stampCode,
),
)?.then((value) {
if (value != null) {
bloc.preparedData(widget.stampId);
}
});
},
title: 'Cập nhật hoạt động',
borderColor: Colors.green,
textColor: Colors.green,

+ 6
- 1
lib/presentation/screens/codes/code_page.dart View File

@@ -145,7 +145,12 @@ class _CodePageState extends State<CodePage> {
: ItemCode(
item: state.items?[index],
onPressed: () {
Get.to(() => CodeDetailPage());
Get.to(
() => CodeDetailPage(
stampId: state.items?[index].id,
stampCode: state.items?[index].code,
),
);
},
);
},

+ 0
- 67
lib/presentation/screens/codes/cubit/code_update_timeline_cubit.dart View File

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

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

part 'code_update_timeline_state.dart';

class CodeUpdateTimelineCubit extends Cubit<CodeUpdateTimelineState> {
CodeUpdateTimelineCubit() : super(CodeUpdateTimelineInitial());

final repository = Repository();
final formKey = GlobalKey<FormState>();
var actionDate = ValueNotifier(DateTime.now());
final descriptionCtl = TextEditingController();
var actionTypes = [
ItemDropDown(key: 'hoat dong 1', value: 'hoat dong 1'),
ItemDropDown(key: 'hoat dong 2', value: 'hoat dong 2'),
];
var selectedActionType = ValueNotifier('');
// var existedCodeUpdateTimeline = UpdateCodeUpdateTimeline();

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

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

emit(CodeUpdateTimelinePrepareDataSuccessful());
} catch (e) {
emit(CodeUpdateTimelineFailure(AppException.handleError(e)));
}
}

Future<void> onSubmit() async {
if (formKey.currentState!.validate()) {
// var gioiTinh = gioiTinhs.firstWhere(
// (element) => selectedGioiTinh.value == element.key,
// orElse: () => ItemDropDown(),
// );

// existedCodeUpdateTimeline
// ..gioiTinhBe = gioiTinh.value
// ..ghiChu = noteCtl.text
// ..ngayTiemUngKhiThan = ungKhiThanDate.value.convertLocalDateTimeToServer();

// UtilWidget.showLoading();
// await repository.updateCodeUpdateTimeline(
// (success) {
// UtilWidget.hideDialog();
// UtilWidget.showToastSuccess('Thêm thành công');
// Get.back();
// },
// (errorMessage) {
// UtilWidget.hideDialog();
// UtilWidget.showToastError(errorMessage);
// },
// item: existedCodeUpdateTimeline,
// );
}
}
}

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

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

abstract class CodeUpdateTimelineState extends Equatable {
const CodeUpdateTimelineState();

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

class CodeUpdateTimelineInitial extends CodeUpdateTimelineState {}

class CodeUpdateTimelineLoading extends CodeUpdateTimelineState {}

class CodeUpdateTimelineFailure extends CodeUpdateTimelineState {
final String errorMessage;

CodeUpdateTimelineFailure(this.errorMessage);
}

class CodeUpdateTimelinePrepareDataSuccessful extends CodeUpdateTimelineState {
CodeUpdateTimelinePrepareDataSuccessful();
}

+ 54
- 0
lib/presentation/screens/codes/cubit/detail_stamp_cubit.dart View File

@@ -0,0 +1,54 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:farm_tpf/presentation/screens/codes/models/stamp_timeline.dart';

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

part 'detail_stamp_state.dart';

class DetailStampCubit extends Cubit<DetailStampState> {
final repository = Repository();
DetailStampCubit() : super(DetailStampInitial());

Future<void> preparedData(int stampId) async {
try {
await Future.delayed(const Duration(seconds: 0));
emit(DetailStampLoading());
var stamp = await repository.getStampDetail(id: stampId);
var timeline = await repository.getStampTimeline(stampId: stampId);
// stampTypeRaws = await repository.stampTypes();
// stampTypes.value = stampTypeRaws
// .map(
// (e) => ItemDropDown(key: e.id?.toString(), value: e.exampleStampName),
// )
// .toList();
emit(DetailStampSuccessful(stamp, timeline));
} catch (e) {
emit(DetailStampFailure(AppException.handleError(e)));
}
}

Future<void> updateStampStatus({
required int stampId,
required String status,
}) async {
UtilWidget.showLoading();
await repository.updateStampStatus(
(success) {
UtilWidget.hideDialog();
Utils.showSnackBarSuccess();
preparedData(stampId);
},
(errorMessage) {
UtilWidget.hideDialog();
Utils.showSnackBarError();
},
stampId: stampId,
status: status,
);
}
}

+ 24
- 0
lib/presentation/screens/codes/cubit/detail_stamp_state.dart View File

@@ -0,0 +1,24 @@
part of 'detail_stamp_cubit.dart';

abstract class DetailStampState extends Equatable {
const DetailStampState();

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

class DetailStampInitial extends DetailStampState {}

class DetailStampLoading extends DetailStampState {}

class DetailStampFailure extends DetailStampState {
final String errorMessage;

DetailStampFailure(this.errorMessage);
}

class DetailStampSuccessful extends DetailStampState {
final Stamp stamp;
final StampTimeline timeline;
DetailStampSuccessful(this.stamp, this.timeline);
}

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

@@ -1,3 +1,5 @@
import 'package:farm_tpf/presentation/screens/codes/models/stamp_type.dart';

import '../../../../custom_model/TbCropDTO.dart';

class Stamp {
@@ -10,6 +12,7 @@ class Stamp {
String? status;
String? expiredDate;
String? createdDate;
StampType? stampType;

Stamp({
this.id,
@@ -21,6 +24,7 @@ class Stamp {
this.status,
this.expiredDate,
this.createdDate,
this.stampType,
});

Stamp.fromJson(Map<String, dynamic> json) {
@@ -33,6 +37,7 @@ class Stamp {
status = json['status'];
expiredDate = json['expiredDate'];
createdDate = json['createdDate'];
stampType = json['tbExampleStamp'] != null ? new StampType.fromJson(json['tbExampleStamp']) : null;
}

Map<String, dynamic> toJson() {
@@ -48,6 +53,9 @@ class Stamp {
data['status'] = this.status;
data['expiredDate'] = this.expiredDate;
data['createdDate'] = this.createdDate;
if (this.stampType != null) {
data['tbExampleStamp'] = this.stampType?.toJson();
}
return data;
}
}

+ 87
- 0
lib/presentation/screens/codes/models/stamp_timeline.dart View File

@@ -0,0 +1,87 @@
class StampTimeline {
List<ContentTimeline>? content;

StampTimeline({this.content});

StampTimeline.fromJson(Map<String, dynamic> json) {
if (json['content'] != null) {
content = <ContentTimeline>[];
json['content'].forEach((v) {
content?.add(new ContentTimeline.fromJson(v));
});
}
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.content != null) {
data['content'] = this.content?.map((v) => v.toJson()).toList();
}
return data;
}
}

class ContentTimeline {
int? id;
int? ageDay;
int? cropId;
String? executeDate;
String? description;
String? createdDate;
int? createdById;
String? createdByName;
int? activityTypeId;
String? activityTypeName;
String? activityTypeDescription;
String? codeId;
bool? afterHarvest;

ContentTimeline(
{this.id,
this.ageDay,
this.cropId,
this.executeDate,
this.description,
this.createdDate,
this.createdById,
this.createdByName,
this.activityTypeId,
this.activityTypeName,
this.activityTypeDescription,
this.codeId,
this.afterHarvest});

ContentTimeline.fromJson(Map<String, dynamic> json) {
id = json['id'];
ageDay = json['ageDay'];
cropId = json['cropId'];
executeDate = json['executeDate'];
description = json['description'];
createdDate = json['createdDate'];
createdById = json['createdById'];
createdByName = json['createdByName'];
activityTypeId = json['activityTypeId'];
activityTypeName = json['activityTypeName'];
activityTypeDescription = json['activityTypeDescription'];
codeId = json['codeId'];
afterHarvest = json['afterHarvest'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['ageDay'] = this.ageDay;
data['cropId'] = this.cropId;
data['executeDate'] = this.executeDate;
data['description'] = this.description;
data['createdDate'] = this.createdDate;
data['createdById'] = this.createdById;
data['createdByName'] = this.createdByName;
data['activityTypeId'] = this.activityTypeId;
data['activityTypeName'] = this.activityTypeName;
data['activityTypeDescription'] = this.activityTypeDescription;
data['codeId'] = this.codeId;
data['afterHarvest'] = this.afterHarvest;
return data;
}
}

+ 16
- 23
lib/presentation/screens/codes/widgets/item_code_timeline.dart View File

@@ -1,13 +1,17 @@
import 'package:farm_tpf/utils/formatter.dart';
import 'package:flutter/material.dart';

import '../../../../themes/app_colors.dart';
import '../../../../themes/styles_text.dart';
import '../models/stamp_timeline.dart';

class ItemCodeTimeline extends StatelessWidget {
final Function onPressed;
final ContentTimeline item;
const ItemCodeTimeline({
super.key,
required this.onPressed,
required this.item,
});

@override
@@ -73,11 +77,11 @@ class ItemCodeTimeline extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
'ss - ',
'${item.activityTypeDescription ?? ''} - ',
style: StylesText.body5,
),
Text(
'20/22/2202',
'${item.executeDate?.format_DDMMYY()}',
style: StylesText.caption3.copyWith(),
)
],
@@ -86,9 +90,9 @@ class ItemCodeTimeline extends StatelessWidget {
height: 8,
),
_widgetItemInfoCompleted(
title: 'title',
actionDate: '2/2/2023',
nguoiThucHiens: 'nguoi thuc hien',
title: 'Mô tả',
actionDate: item.description ?? '',
location: 'dsfsdfsd f sdf dsf sd fds ',
),
],
),
@@ -98,7 +102,7 @@ class ItemCodeTimeline extends StatelessWidget {
Widget _widgetItemInfoCompleted({
required String title,
required String actionDate,
String? nguoiThucHiens,
String? location,
}) {
return Container(
padding: const EdgeInsets.all(8),
@@ -108,6 +112,7 @@ class ItemCodeTimeline extends StatelessWidget {
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
@@ -129,23 +134,11 @@ class ItemCodeTimeline extends StatelessWidget {
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
children: [
Expanded(
child: Text(
'Người thực hiện',
style: StylesText.caption2.copyWith(
color: AppColors.neutral1,
),
),
),
Text(
nguoiThucHiens ?? '',
style: StylesText.caption3.copyWith(
color: AppColors.neutral1,
),
),
],
child: Text(
location ?? '',
style: StylesText.caption3.copyWith(
color: AppColors.neutral1,
),
),
),
],

Loading…
Cancel
Save