recurrent task timer improvements.

design_3.0_latest
Sikander Saleem 9 months ago
parent 86aeddc6c2
commit 4c328b2cba

@ -233,6 +233,10 @@ class AllRequestsProvider extends ChangeNotifier {
void updateRecurrentWoTimer({TimerModel? timer}) {
recurrentWoData?.recurrentWoTimerModel = timer;
if (timer?.startAt != null && timer?.endAt != null) {
recurrentWoData?.timerModelList = recurrentWoData?.timerModelList ?? [];
recurrentWoData?.timerModelList!.add(timer!);
}
notifyListeners();
}

@ -11,7 +11,6 @@ class DashboardDetail {
DashboardDetail.fromJson(Map<String, dynamic> json) {
totalRows = json['totalRows'];
print('total rows is $totalRows');
if (json['data'] != null) {
data = <Data>[];
json['data'].forEach((v) {

@ -52,6 +52,7 @@ class RecurrentWoData {
List<PlanRecurrentTaskTimers>? planRecurrentTaskTimers;
TimerModel? recurrentWoTimerModel = TimerModel();
double? totalWorkingHours = 0.0;
List<TimerModel>? timerModelList = [];
RecurrentWoData(
{this.id,
@ -68,6 +69,7 @@ class RecurrentWoData {
this.room,
this.planRecurrentMedicalTaskRooms,
this.planRecurrentTaskTimers,
this.timerModelList,
this.totalWorkingHours});
RecurrentWoData.fromJson(Map<String, dynamic> json) {

@ -51,8 +51,6 @@ class _RequestsListPageState extends State<RequestsListPage> {
_scrollController = ScrollController();
int pageNo = 1;
_scrollController.addListener(() async {
log('loading value i got is ${_dashBoardProvider.isDetailLoading}');
log('total rows i got is ${_dashBoardProvider.requestDetailList!.totalRows}');
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent &&
!_dashBoardProvider.isDetailLoading &&
(_dashBoardProvider.requestDetailList!.data!.length < _dashBoardProvider.requestDetailList!.totalRows!.toInt())) {

@ -46,9 +46,10 @@ class _MaintenanceRequestFormState extends State<MaintenanceRequestForm> with Si
@override
Widget build(BuildContext context) {
return Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) {
bool isUpdate = requestDetailProvider.activityMaintenanceHelperModel?.id != 0;
return Scaffold(
backgroundColor: AppColor.neutral110,
appBar: DefaultAppBar(title: context.translation.maintenanceRequest),
appBar: DefaultAppBar(title: isUpdate ? "Update Activity" : "New Activity"),
body: Stack(
children: [
DefaultTabController(

@ -1,15 +1,10 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:test_sa/dashboard_latest/dashboard_view.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/recurrent_task_inspection_data_type.dart';
import 'package:test_sa/models/ppm/recurrent_wo.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:toggle_switch/toggle_switch.dart';
class RoomInspectionCard extends StatefulWidget {
final PlanRecurrentMedicalTaskRoomTabs? inspectionModel;
@ -21,7 +16,8 @@ class RoomInspectionCard extends StatefulWidget {
}
class _RoomInspectionCardState extends State<RoomInspectionCard> {
int selectedIndex =0;
int selectedIndex = 0;
@override
void initState() {
super.initState();
@ -34,33 +30,28 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
children: [
widget.inspectionModel!.tabName!.bodyText(context).custom(color: AppColor.neutral50, fontWeight: FontWeight.w600),
8.height,
Column(
children: widget.inspectionModel!.planRecurrentMedicalTaskRoomTabAttributes?.asMap().entries.map<Widget>((entry) {
final model = entry.value;
final attribute = model.attribute;
switch (attribute?.dataTypeEnum) {
case RecurrentTaskInspectionDataTypeEnum.bool:
return inspectionStatusRadioWidget(
index: entry.key,
model: model,
context: context,
);
case RecurrentTaskInspectionDataTypeEnum.number:
return inspectionStatusNumberWidget(
index: entry.key,
model: model,
context: context,
);
default:
return const SizedBox.shrink(); // Handles any unexpected cases gracefully
}
}).toList() ??
[],
Container(
color: Colors.white10,
child: Column(
children: widget.inspectionModel!.planRecurrentMedicalTaskRoomTabAttributes?.asMap().entries.map<Widget>((entry) {
final model = entry.value;
final attribute = model.attribute;
switch (attribute?.dataTypeEnum) {
case RecurrentTaskInspectionDataTypeEnum.bool:
return inspectionStatusRadioWidget(index: entry.key, model: model, context: context);
case RecurrentTaskInspectionDataTypeEnum.number:
return inspectionStatusNumberWidget(index: entry.key, model: model, context: context);
default:
return const SizedBox.shrink(); // Handles any unexpected cases gracefully
}
}).toList() ??
[],
),
)
],
).toShadowContainer(context).paddingOnly(top: 12);
}
Widget inspectionStatusRadioWidget({
required int index,
required PlanRecurrentMedicalTaskRoomTabAttributes model,
@ -68,8 +59,8 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
}) {
bool status = model.attribute != null
? model.attributeValue == 'true'
? true
: false
? true
: false
: false;
return Row(
@ -79,17 +70,15 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 220.toScreenWidth,
child: Text(
model.attribute!.name!,
overflow: TextOverflow.ellipsis,
maxLines: 1, // Ensures text is limited to one line before ellipsis
),
Text(
model.attribute!.name!,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: AppTextStyles.bodyText2.copyWith(color: AppColor.white936),
),
(status ? 'Pass' : 'Fail').bodyText2(context).custom(color: AppColor.neutral120, fontWeight: FontWeight.w500),
],
),
).expanded,
GestureDetector(
onTap: () {
setState(() {
@ -102,7 +91,7 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
height: 30.toScreenHeight,
padding: EdgeInsetsDirectional.all(4.toScreenHeight),
decoration: BoxDecoration(
color:AppColor.white80,
color: AppColor.white80,
borderRadius: BorderRadius.circular(5),
),
child: Row(
@ -113,7 +102,7 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
isActive: status,
activeColor: AppColor.green20,
inactiveColor: Colors.transparent,
textColor: status ? AppColor.green50 :AppColor.black20,
textColor: status ? AppColor.green50 : AppColor.black20,
),
buildToggleOption(
label: "FAIL",
@ -127,8 +116,9 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
),
),
],
).paddingOnly(bottom: 12);
).paddingOnly(top: 6, bottom: 6);
}
Widget buildToggleOption({
required String label,
required bool isActive,
@ -148,7 +138,6 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
);
}
// Widget inspectionStatusRadioWidget({
// required int index,
// required PlanRecurrentMedicalTaskRoomTabAttributes model,
@ -195,11 +184,7 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
// ).paddingOnly(bottom: 12);
// }
Widget inspectionStatusNumberWidget({
required int index,
required PlanRecurrentMedicalTaskRoomTabAttributes model,
required BuildContext context,
}) {
Widget inspectionStatusNumberWidget({required int index, required PlanRecurrentMedicalTaskRoomTabAttributes model, required BuildContext context}) {
final border = OutlineInputBorder(
borderRadius: BorderRadius.circular(4), // Optional: Slight rounding
borderSide: const BorderSide(
@ -219,7 +204,7 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
contentPadding: EdgeInsets.symmetric(horizontal: 5.toScreenWidth),
filled: true,
fillColor: AppColor.neutral100,
constraints: BoxConstraints(
constraints: BoxConstraints(
maxWidth: 99.toScreenWidth,
maxHeight: 30.toScreenHeight,
),
@ -232,14 +217,10 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
},
),
],
).paddingOnly(bottom: 12);
).paddingOnly(bottom: 6, top: 6);
}
}
// // I need it here ....
// Container(
// padding: EdgeInsets.all(6.toScreenHeight),
@ -297,4 +278,4 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
// // onToggle: (index) {
// // print('switched to: $index');
// // },
// // ),
// // ),

@ -37,6 +37,7 @@ class _RoomTabsWidgetState extends State<RoomTabsWidget> {
child: ListView(
scrollDirection: Axis.horizontal,
// mainAxisAlignment: MainAxisAlignment.spaceAround,
padding: EdgeInsets.zero,
children: widget.model!.planRecurrentMedicalTaskRooms!.asMap().entries.map((task) {
final int index = task.key;
final String label = task.value.room!.roomId!;
@ -65,9 +66,7 @@ class _RoomTabsWidgetState extends State<RoomTabsWidget> {
color: selectedIndex == index ? (context.isDark ? AppColor.neutral60 : AppColor.neutral110) : Colors.transparent,
borderRadius: BorderRadius.circular(7),
),
child: label.bodyText(context).custom(
color: AppColor.white936,
),
child: label.bodyText(context).custom(color: AppColor.white936),
),
);
}).toList(),
@ -77,7 +76,7 @@ class _RoomTabsWidgetState extends State<RoomTabsWidget> {
? const ALoading().paddingOnly(top: 150)
: ListView(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero,
children: widget.model!.planRecurrentMedicalTaskRooms![selectedIndex].planRecurrentMedicalTaskRoomTabs!.map<Widget>((card) {
return RoomInspectionCard(inspectionModel: card);
}).toList(),

@ -22,7 +22,6 @@ class RecurrentTaskInfoWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
@ -39,7 +38,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget {
8.height,
model!.title!.bodyText(context).custom(color: AppColor.black10),
2.height,
'${context.translation.taskNo}: ${model!.taskNo!}'.bodyText2(context).custom(color: AppColor.neutral120),
'${context.translation.taskNo}: ${model!.taskNo!}'.bodyText2(context).custom(color: AppColor.neutral120),
'${context.translation.site}: ${model!.site!.siteName!}'.bodyText2(context).custom(color: AppColor.neutral120),
'${context.translation.assignEngineer}: ${model!.engineer!.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120),
'${context.translation.scheduledDate}: ${model!.scheduleDate!.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120),
@ -67,51 +66,43 @@ class RecurrentTaskInfoWidget extends StatelessWidget {
}
Widget _timerWidget(BuildContext context, double totalWorkingHours) {
return Consumer<AllRequestsProvider>(
builder: (context, snapshot,child) {
return Column(
children: [
AppTimer(
label: context.translation.timer,
timer: snapshot.recurrentWoData?.recurrentWoTimerModel,
width: double.infinity,
// enabled: snapshot.recurrentWoData?.recurrentWoTimerModel?.endAt == null,
decoration: BoxDecoration(
color: AppColor.neutral100,
borderRadius: BorderRadius.circular(10),
),
timerProgress: (isRunning) {},
onChange: (timer) async {
snapshot.updateRecurrentWoTimer(timer: timer);
return true;
},
return Consumer<AllRequestsProvider>(builder: (context, snapshot, child) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
AppTimer(
label: context.translation.timer,
timer: snapshot.recurrentWoData?.recurrentWoTimerModel,
width: double.infinity,
// enabled: snapshot.recurrentWoData?.recurrentWoTimerModel?.endAt == null,
decoration: BoxDecoration(
color: AppColor.neutral100,
borderRadius: BorderRadius.circular(10),
),
11.height,
if (totalWorkingHours > 0.0) ...[
timerProgress: (isRunning) {},
onChange: (timer) async {
snapshot.updateRecurrentWoTimer(timer: timer);
return true;
},
),
if (totalWorkingHours > 0.0) ...[
12.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
'Total Working Time:'.bodyText2(context).custom(color: AppColor.neutral120),
8.width,
Text(
"Total Working Time: ",
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: context.isDark ? null : AppColor.neutral20,
fontWeight: FontWeight.w500,
),
),
Text(
" ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}",
style: Theme.of(context).textTheme.bodyMedium,
ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()),
style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600),
),
],
),
],
8.height,
],
);
}
);
],
);
});
}
}

@ -13,11 +13,12 @@ import 'package:test_sa/service_request_latest/views/components/action_button/fo
import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart';
import 'package:test_sa/views/widgets/loaders/app_loading.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import '../../../../../../controllers/providers/api/all_requests_provider.dart';
import 'components/room_tabs_widget.dart';
class RecurrentWorkOrderView extends StatefulWidget {
static const String routeName = "/recurrent_wo";
static const String routeName = "/recurrent_wo";
final int? taskId;
RecurrentWorkOrderView({Key? key, required this.taskId}) : super(key: key);
@ -51,7 +52,7 @@ class _RecurrentWorkOrderViewState extends State<RecurrentWorkOrderView> {
body: allRequestsProvider!.isLoading
? const ALoading()
: requestProvider.recurrentWoData != null
? Stack (
? Stack(
children: [
SingleChildScrollView(
child: Column(
@ -64,9 +65,7 @@ class _RecurrentWorkOrderViewState extends State<RecurrentWorkOrderView> {
? Column(
children: [
8.height,
RoomTabsWidget(
model: requestProvider.recurrentWoData,
),
RoomTabsWidget(model: requestProvider.recurrentWoData),
],
)
: const SizedBox(),
@ -81,19 +80,13 @@ class _RecurrentWorkOrderViewState extends State<RecurrentWorkOrderView> {
label: context.translation.save,
buttonColor: AppColor.white60,
textColor: AppColor.black10,
onPressed: () => _updateTask(
context: context,
status: 0,
),
onPressed: () => _updateTask(context: context, status: 0),
).expanded,
12.width,
AppFilledButton(
label: context.translation.complete,
buttonColor: AppColor.primary10,
onPressed: () => _updateTask(
context: context,
status: 1,
),
onPressed: () => _updateTask(context: context, status: 1),
).expanded,
],
),
@ -107,37 +100,42 @@ class _RecurrentWorkOrderViewState extends State<RecurrentWorkOrderView> {
}
void _updateTask({required BuildContext context, required int status}) async {
AllRequestsProvider allRequestsProvider = Provider.of<AllRequestsProvider>(context, listen: false);
if(validate(model: allRequestsProvider.recurrentWoData!)){
if (validate(model: allRequestsProvider.recurrentWoData!)) {
allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers = allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers ?? [];
DateTime ?startTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt;
DateTime ?endTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.endAt;
final duration = (endTime?.difference(startTime!));
DateTime? startTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt;
DateTime? endTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.endAt;
// final duration = (endTime?.difference(startTime!));
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers?.add(
PlanRecurrentTaskTimers(
id: 0,
startTime: startTime?.toIso8601String(),
endTime: endTime?.toIso8601String(),
workingHours: (duration?.inSeconds ?? 0) / 60 / 60,
),
);
await allRequestsProvider.updateRecurrentWo(
allRequestsProvider.recurrentWoData?.timerModelList?.forEach((timer) {
int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds;
allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers?.add(
PlanRecurrentTaskTimers(
id: 0,
startTime: timer.startAt!.toIso8601String(), // Handle potential null
endTime: timer.endAt?.toIso8601String(), // Handle potential null
workingHours: ((durationInSecond) / 60 / 60),
),
);
});
await allRequestsProvider
.updateRecurrentWo(
status: status,
).whenComplete((){
if(status==1){// when click complete then this request remove from the list and status changes to closed..
)
.whenComplete(() {
if (status == 1) {
// when click complete then this request remove from the list and status changes to closed..
allRequestsProvider.reset();
allRequestsProvider.getAllRequests(context,typeTransaction: 5);
allRequestsProvider.getAllRequests(context, typeTransaction: 5);
}
allRequestsProvider.recurrentWoData?.recurrentWoTimerModel=null;
Navigator.pop(context);
Navigator.pop(context);
allRequestsProvider.recurrentWoData?.recurrentWoTimerModel = null;
Navigator.pop(context);
Navigator.pop(context);
});
}
}
bool validate({required RecurrentWoData model}) {

Loading…
Cancel
Save