recurrent task, cleaner improvements.

export_module
Sikander Saleem 2 months ago
parent 68fcc444d9
commit 023a47f69f

@ -15,6 +15,8 @@ extension WidgetExtensions on Widget {
Widget get center => Center(child: this); Widget get center => Center(child: this);
Widget ignorePointer(bool value) => IgnorePointer(ignoring: value, child: this);
BoxShadow get boxShadowR14 => BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 5, offset: const Offset(0, 0), spreadRadius: 0); BoxShadow get boxShadowR14 => BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 5, offset: const Offset(0, 0), spreadRadius: 0);
Widget circle(double value) => ClipRRect(borderRadius: BorderRadius.circular(value), child: this); Widget circle(double value) => ClipRRect(borderRadius: BorderRadius.circular(value), child: this);
@ -202,4 +204,3 @@ extension WidgetExtensions on Widget {
extension DividerExtension on Divider { extension DividerExtension on Divider {
Divider defaultStyle(BuildContext context) => Divider(thickness: 1, color: context.isDarkNotListen ? AppColor.neutral20 : AppColor.neutral30); Divider defaultStyle(BuildContext context) => Divider(thickness: 1, color: context.isDarkNotListen ? AppColor.neutral20 : AppColor.neutral30);
} }

@ -70,7 +70,7 @@ class _CleanerSearchDetailsViewState extends State<CleanerSearchDetailsView> {
floorName: recurrentData.floor?.name, floorName: recurrentData.floor?.name,
departmentName: recurrentData.department?.name, departmentName: recurrentData.department?.name,
roomName: recurrentData.room?.name, roomName: recurrentData.room?.name,
locationDescription: null, // Not available in RecurrentWoData locationDescription: null,
createdDate: recurrentData.scheduleDate, createdDate: recurrentData.scheduleDate,
); );
} }
@ -101,51 +101,40 @@ class _CleanerSearchDetailsViewState extends State<CleanerSearchDetailsView> {
), ),
body: _isLoading body: _isLoading
? const Center(child: CircularProgressIndicator()) ? const Center(child: CircularProgressIndicator())
: Selector<CleanerProvider, bool>( : SafeArea(
selector: (_, model) => model.isLoading, child: Selector<CleanerProvider, bool>(
builder: (_, isLoading, __) { selector: (_, model) => model.isLoading,
if (isLoading) { builder: (_, isLoading, __) {
return const Center(child: CircularProgressIndicator()); if (isLoading) {
} return const Center(child: CircularProgressIndicator());
}
return Column( return Column(
children: [ children: [
Expanded( SingleChildScrollView(
child: SingleChildScrollView( padding: const EdgeInsets.all(16),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
18.height,
_buildCleanerRequestDetailCard(context), _buildCleanerRequestDetailCard(context),
20.height,
], ],
), ),
), ).expanded,
), FooterActionButton.footerContainer(
SafeArea(
top: false,
right: false,
left: false,
child: FooterActionButton.footerContainer(
context: context, context: context,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (!_isQRScanned) if (!_isQRScanned) ...[
Row( Row(
children: [ children: [
Icon( Icon(Icons.info_outline_rounded, size: 16, color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
Icons.info_outline,
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
size: 15,
),
8.width, 8.width,
Expanded( Expanded(
child: Text( child: Text(
'By scanning the QR code you will accept this task'.addTranslation, 'By scanning the QR code you will accept this task'.addTranslation,
textAlign: TextAlign.center, // textAlign: TextAlign.center,
style: AppTextStyles.bodyText.copyWith( style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120, color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
), ),
@ -153,7 +142,8 @@ class _CleanerSearchDetailsViewState extends State<CleanerSearchDetailsView> {
), ),
], ],
), ),
16.height, 8.height,
],
AppFilledButton( AppFilledButton(
label: _isQRScanned ? 'Update' : 'Scan QR Code', label: _isQRScanned ? 'Update' : 'Scan QR Code',
maxWidth: true, maxWidth: true,
@ -206,12 +196,12 @@ class _CleanerSearchDetailsViewState extends State<CleanerSearchDetailsView> {
}, },
), ),
], ],
).paddingOnly(start: 16, end: 16), ),
), ).toShadowContainer(context, padding: 0, showShadow: false, borderRadius: 0),
).toShadowContainer(context, padding: 0, showShadow: false, borderRadius: 0), ],
], );
); },
}, ),
), ),
); );
} }
@ -248,11 +238,9 @@ class _CleanerSearchDetailsViewState extends State<CleanerSearchDetailsView> {
), ),
if (taskResult.createdDate != null) if (taskResult.createdDate != null)
Text( Text(
taskResult.createdDate!.split('T').first, taskResult.createdDate!.toServiceRequestCardFormat,
textAlign: TextAlign.end, textAlign: TextAlign.end,
style: AppTextStyles.tinyFont.copyWith( style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
),
), ),
], ],
), ),
@ -260,51 +248,37 @@ class _CleanerSearchDetailsViewState extends State<CleanerSearchDetailsView> {
if (taskResult.taskNo != null && taskResult.taskNo!.isNotEmpty) if (taskResult.taskNo != null && taskResult.taskNo!.isNotEmpty)
Text( Text(
'Task No: ${taskResult.taskNo!}', 'Task No: ${taskResult.taskNo!}',
style: AppTextStyles.bodyText.copyWith( style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
if (taskResult.siteName != null && taskResult.siteName!.isNotEmpty) if (taskResult.siteName != null && taskResult.siteName!.isNotEmpty)
Text( Text(
'Site: ${taskResult.siteName}', 'Site: ${taskResult.siteName}',
style: AppTextStyles.bodyText.copyWith( style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
if (taskResult.buildingName != null && taskResult.buildingName!.isNotEmpty) if (taskResult.buildingName != null && taskResult.buildingName!.isNotEmpty)
Text( Text(
'Building: ${taskResult.buildingName}', 'Building: ${taskResult.buildingName}',
style: AppTextStyles.bodyText.copyWith( style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
if (taskResult.floorName != null && taskResult.floorName!.isNotEmpty) if (taskResult.floorName != null && taskResult.floorName!.isNotEmpty)
Text( Text(
'Floor: ${taskResult.floorName}', 'Floor: ${taskResult.floorName}',
style: AppTextStyles.bodyText.copyWith( style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
if (taskResult.departmentName != null && taskResult.departmentName!.isNotEmpty) if (taskResult.departmentName != null && taskResult.departmentName!.isNotEmpty)
Text( Text(
'Department: ${taskResult.departmentName}', 'Department: ${taskResult.departmentName}',
style: AppTextStyles.bodyText.copyWith( style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
if (taskResult.roomName != null && taskResult.roomName!.isNotEmpty) if (taskResult.roomName != null && taskResult.roomName!.isNotEmpty)
Text( Text(
'Room: ${taskResult.roomName}', 'Room: ${taskResult.roomName}',
style: AppTextStyles.bodyText.copyWith( style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
if (taskResult.locationDescription != null && taskResult.locationDescription!.isNotEmpty) if (taskResult.locationDescription != null && taskResult.locationDescription!.isNotEmpty)
Text( Text(
'Location: ${taskResult.locationDescription}', 'Location: ${taskResult.locationDescription}',
style: AppTextStyles.bodyText.copyWith( style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
], ],
).expanded, ).expanded,

@ -12,20 +12,16 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.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:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/views/widgets/buttons/app_back_button.dart';
class CleanerChecklistWidget extends StatefulWidget { class CleanerChecklistWidget extends StatefulWidget {
final List<ChecklistItem> checklistItems; final List<ChecklistItem> checklistItems;
final Function(List<ChecklistItem>)? onChecklistChanged; final Function(List<ChecklistItem>)? onChecklistChanged;
final String? capturedImageBase64; final String? capturedImageBase64;
final Function(String?)? onImageCaptured; final Function(String?)? onImageCaptured;
bool isClosed;
const CleanerChecklistWidget({ CleanerChecklistWidget({Key? key, required this.checklistItems, this.onChecklistChanged, this.capturedImageBase64, this.onImageCaptured, this.isClosed = false}) : super(key: key);
Key? key,
required this.checklistItems,
this.onChecklistChanged,
this.capturedImageBase64,
this.onImageCaptured,
}) : super(key: key);
@override @override
State<CleanerChecklistWidget> createState() => _CleanerChecklistWidgetState(); State<CleanerChecklistWidget> createState() => _CleanerChecklistWidgetState();
@ -50,82 +46,88 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
), ),
16.height, 16.height,
...widget.checklistItems.map((item) => _buildChecklistItem(context, item)).toList(), ...widget.checklistItems.map((item) => _buildChecklistItem(context, item)).toList(),
16.height, // 16.height,
_buildImageCaptureWidget(context), _buildImageCaptureWidget(context),
], ],
); );
} }
Widget _buildChecklistItem(BuildContext context, ChecklistItem item) { Widget _buildChecklistItem(BuildContext context, ChecklistItem item) {
return Column( return IgnorePointer(
crossAxisAlignment: CrossAxisAlignment.start, ignoring: widget.isClosed,
children: [ child: Column(
// Checkbox with title crossAxisAlignment: CrossAxisAlignment.start,
Row( mainAxisSize: MainAxisSize.min,
children: [ children: [
Checkbox( // Checkbox with title
value: item.isChecked, Row(
activeColor: AppColor.primary10, children: [
onChanged: (bool? value) { Checkbox(
setState(() { // visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0),
item.isChecked = value ?? false; materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
if (!item.isChecked) { value: item.isChecked,
item.commentController.clear(); activeColor: AppColor.primary10,
} onChanged: (bool? value) {
}); setState(() {
// Notify parent of changes item.isChecked = value ?? false;
widget.onChecklistChanged?.call(widget.checklistItems); if (!item.isChecked) {
}, item.commentController.clear();
), }
8.width, });
Expanded( // Notify parent of changes
child: RichText( widget.onChecklistChanged?.call(widget.checklistItems);
text: TextSpan( },
children: [ ),
TextSpan( 8.width,
text: item.title, Expanded(
style: AppTextStyles.bodyText.copyWith( child: RichText(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120, text: TextSpan(
fontWeight: FontWeight.w600, children: [
),
),
if (item.isMandatory)
TextSpan( TextSpan(
text: ' *', text: item.title,
style: AppTextStyles.bodyText.copyWith( style: AppTextStyles.bodyText.copyWith(
color: Colors.red, color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w500,
), ),
), ),
], if (item.isMandatory)
TextSpan(
text: ' *',
style: AppTextStyles.bodyText.copyWith(
color: Colors.red,
fontWeight: FontWeight.w500,
),
),
],
),
), ),
), ),
), ],
], ),
),
// Comment box - only visible when checked // Comment box - only visible when checked
if (item.isChecked) ...[ if (item.isChecked) ...[
16.height, 16.height,
AppTextFormField( AppTextFormField(
controller: item.commentController, controller: item.commentController,
labelText: context.translation.comment, labelText: context.translation.comment,
backgroundColor: AppColor.fieldBgColor(context), backgroundColor: AppColor.fieldBgColor(context),
showShadow: false, showShadow: false,
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith( labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(
color: context.isDark ? AppColor.white10 : AppColor.black10, color: context.isDark ? AppColor.white10 : AppColor.black10,
),
alignLabelWithHint: true,
textInputType: TextInputType.multiline,
onChange: (value) {
item.comment = value;
// Notify parent of changes
widget.onChecklistChanged?.call(widget.checklistItems);
},
), ),
alignLabelWithHint: true, ],
textInputType: TextInputType.multiline,
onChange: (value) {
item.comment = value;
// Notify parent of changes
widget.onChecklistChanged?.call(widget.checklistItems);
},
),
], ],
], ).toShadowContainer(context).paddingOnly(bottom: 16),
).toShadowContainer(context).paddingOnly(bottom: 16); );
} }
Widget _buildImageCaptureWidget(BuildContext context) { Widget _buildImageCaptureWidget(BuildContext context) {
@ -140,26 +142,7 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
), ),
), ),
8.height, 8.height,
GestureDetector( _buildImageWidget(context),
onTap: () async {
// Image capture logic
final pickedFile = await ImagePicker().pickImage(source: ImageSource.camera);
if (pickedFile != null) {
// Convert image to Base64 with filename prefix (same format as CM request)
final bytes = await pickedFile.readAsBytes();
final base64Image = base64Encode(bytes);
final fileName = pickedFile.path.split("/").last;
final formattedImage = "$fileName|$base64Image";
// Update parent with captured image
widget.onImageCaptured?.call(formattedImage);
}
},
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: _buildImageWidget(context),
),
),
], ],
).toShadowContainer(context); ).toShadowContainer(context);
} }
@ -180,9 +163,23 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
size: 48, size: 48,
color: context.isDark ? AppColor.white10 : AppColor.black10, color: context.isDark ? AppColor.white10 : AppColor.black10,
), ),
); ).onPress(() async {
final pickedFile = await ImagePicker().pickImage(source: ImageSource.camera, imageQuality: 70, maxWidth: 800, maxHeight: 800);
if (pickedFile != null) {
// Convert image to Base64 with filename prefix (same format as CM request)
final bytes = await pickedFile.readAsBytes();
final base64Image = base64Encode(bytes);
final fileName = pickedFile.path.split("/").last;
final formattedImage = "$fileName|$base64Image";
// Update parent with captured image
widget.onImageCaptured?.call(formattedImage);
}
});
} }
Widget imageWidget;
final imageString = widget.capturedImageBase64!; final imageString = widget.capturedImageBase64!;
// First check if it's base64 encoded (contains | separator) // First check if it's base64 encoded (contains | separator)
@ -190,17 +187,37 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
// Format: "filename|base64data" // Format: "filename|base64data"
try { try {
final base64Data = imageString.split('|').last; final base64Data = imageString.split('|').last;
return Container( imageWidget = Image.memory(base64Decode(base64Data), fit: BoxFit.cover);
height: 200, return Stack(
width: double.infinity, alignment: AlignmentDirectional.topEnd,
decoration: BoxDecoration( children: [
color: AppColor.fieldBgColor(context), Container(
borderRadius: BorderRadius.circular(8), height: 200,
), width: double.infinity,
child: Image.memory( decoration: BoxDecoration(
base64Decode(base64Data), color: AppColor.fieldBgColor(context),
fit: BoxFit.cover, borderRadius: BorderRadius.circular(8),
), ),
child: imageWidget)
.onPress(() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => Scaffold(
body: SafeArea(
child: Stack(
children: [
// InteractiveViewer(child: Image(image: getImageObject(itemIndex))).center,
InteractiveViewer(child: imageWidget).center,
const ABackButton(),
],
),
),
),
),
);
}),
_delete(),
],
); );
} catch (e) { } catch (e) {
debugPrint('Error decoding base64 image: $e'); debugPrint('Error decoding base64 image: $e');
@ -211,17 +228,37 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
// Check if it's a local file path // Check if it's a local file path
if (_isLocalUrl(imageString)) { if (_isLocalUrl(imageString)) {
try { try {
return Container( imageWidget = Image.file(File(imageString), fit: BoxFit.cover);
height: 200, return Stack(
width: double.infinity, alignment: AlignmentDirectional.topEnd,
decoration: BoxDecoration( children: [
color: AppColor.fieldBgColor(context), Container(
borderRadius: BorderRadius.circular(8), height: 200,
), width: double.infinity,
child: Image.file( decoration: BoxDecoration(
File(imageString), color: AppColor.fieldBgColor(context),
fit: BoxFit.cover, borderRadius: BorderRadius.circular(8),
), ),
child: imageWidget)
.onPress(() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => Scaffold(
body: SafeArea(
child: Stack(
children: [
// InteractiveViewer(child: Image(image: getImageObject(itemIndex))).center,
InteractiveViewer(child: imageWidget).center,
const ABackButton(),
],
),
),
),
),
);
}),
_delete(),
],
); );
} catch (e) { } catch (e) {
debugPrint('Error loading local file: $e'); debugPrint('Error loading local file: $e');
@ -232,34 +269,55 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
// If not local and not base64, it's a server filename - use NetworkImage with loading indicator // If not local and not base64, it's a server filename - use NetworkImage with loading indicator
final imageUrl = URLs.getFileUrl(imageString); final imageUrl = URLs.getFileUrl(imageString);
if (imageUrl != null) { if (imageUrl != null) {
return Container( imageWidget = Image.network(
height: 200, imageUrl,
width: double.infinity, fit: BoxFit.cover,
decoration: BoxDecoration( loadingBuilder: (context, child, loadingProgress) {
color: AppColor.fieldBgColor(context), if (loadingProgress == null) {
borderRadius: BorderRadius.circular(8), return child;
), }
child: Image.network( return Center(
imageUrl, child: CircularProgressIndicator(
fit: BoxFit.cover, color: AppColor.primary10,
loadingBuilder: (context, child, loadingProgress) { value: loadingProgress.expectedTotalBytes != null ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! : null,
if (loadingProgress == null) { ),
return child; );
} },
return Center( errorBuilder: (context, error, stackTrace) {
child: CircularProgressIndicator( debugPrint('Error loading network image: $error');
color: AppColor.primary10, return _buildCameraIcon(context);
value: loadingProgress.expectedTotalBytes != null },
? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! );
: null, return Stack(
alignment: AlignmentDirectional.topEnd,
children: [
Container(
height: 200,
width: double.infinity,
decoration: BoxDecoration(
color: AppColor.fieldBgColor(context),
borderRadius: BorderRadius.circular(8),
),
child: imageWidget)
.onPress(() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => Scaffold(
body: SafeArea(
child: Stack(
children: [
// InteractiveViewer(child: Image(image: getImageObject(itemIndex))).center,
InteractiveViewer(child: imageWidget).center,
const ABackButton(),
],
),
),
),
), ),
); );
}, }),
errorBuilder: (context, error, stackTrace) { _delete(),
debugPrint('Error loading network image: $error'); ],
return _buildCameraIcon(context);
},
),
); );
} }
@ -295,6 +353,26 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
// Note: Don't dispose controllers here as they're managed by ChecklistItem // Note: Don't dispose controllers here as they're managed by ChecklistItem
super.dispose(); super.dispose();
} }
Widget _delete() {
if (widget.isClosed) return const SizedBox();
return Container(
height: 45.toScreenHeight,
width: 45.toScreenHeight,
margin: const EdgeInsets.only(top: 4, right: 4),
decoration: BoxDecoration(
color: (context.isDark ? AppColor.neutral20 : AppColor.neutral40).withValues(alpha: 0.4),
border: Border.all(
color: (context.isDark ? AppColor.neutral20 : AppColor.neutral40).withValues(alpha: 0.7),
),
borderRadius: BorderRadius.circular(30),
//boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
),
child: const Icon(Icons.delete_rounded, color: Color(0xffF63939)))
.onPress(() {
widget.onImageCaptured?.call(null);
});
}
} }
/// Model class for checklist items /// Model class for checklist items

@ -18,8 +18,9 @@ import 'package:test_sa/views/widgets/total_working_time_detail_bottomsheet.dart
class RecurrentTaskInfoWidget extends StatefulWidget { class RecurrentTaskInfoWidget extends StatefulWidget {
final RecurrentWoData? model; final RecurrentWoData? model;
bool isClosed;
RecurrentTaskInfoWidget({super.key, required this.model}); RecurrentTaskInfoWidget({super.key, required this.model, this.isClosed = false});
@override @override
State<RecurrentTaskInfoWidget> createState() => _RecurrentTaskInfoWidgetState(); State<RecurrentTaskInfoWidget> createState() => _RecurrentTaskInfoWidgetState();
@ -90,15 +91,16 @@ class _RecurrentTaskInfoWidgetState extends State<RecurrentTaskInfoWidget> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
buildingInfoWidget(label: context.translation.department, value: widget.model!.department?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), buildingInfoWidget(label: context.translation.department, value: widget.model!.department?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context)
.ignorePointer(widget.isClosed),
8.height, 8.height,
buildingInfoWidget(label: context.translation.floor, value: widget.model!.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), buildingInfoWidget(label: context.translation.floor, value: widget.model!.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context).ignorePointer(widget.isClosed),
8.height, 8.height,
buildingInfoWidget(label: context.translation.room, value: widget.model!.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), buildingInfoWidget(label: context.translation.room, value: widget.model!.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context).ignorePointer(widget.isClosed),
8.height, 8.height,
_timerWidget(context, totalWorkingHours), _timerWidget(context, totalWorkingHours),
8.height, 8.height,
_commentWidget(context: context, model: widget.model) _commentWidget(context: context, model: widget.model).ignorePointer(widget.isClosed),
], ],
// ], // ],
).toShadowContainer(context, padding: 12) ).toShadowContainer(context, padding: 12)

@ -50,84 +50,96 @@ class _RecurrentWorkOrderViewState extends State<RecurrentWorkOrderView> {
super.dispose(); super.dispose();
} }
bool isClosed = false;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<AllRequestsProvider>(builder: (context, requestProvider, child) { return Consumer<AllRequestsProvider>(builder: (context, requestProvider, child) {
isClosed = requestProvider.recurrentWoData?.status?.value == 1;
return Scaffold( return Scaffold(
appBar: DefaultAppBar( appBar: DefaultAppBar(
title: context.translation.recurrentWo, title: context.translation.recurrentWo,
onWillPopScope: () { onWillPopScope: isClosed
_updateTask(context: context, status: 0); ? null
}, : () {
_updateTask(context: context, status: 0);
},
), ),
body: allRequestsProvider!.isLoading body: allRequestsProvider!.isLoading
? const ALoading() ? const ALoading()
: requestProvider.recurrentWoData != null : requestProvider.recurrentWoData != null
? Column( ? SafeArea(
children: [ child: Column(
SingleChildScrollView( children: [
padding: const EdgeInsets.all(16), SingleChildScrollView(
child: Column( padding: const EdgeInsets.all(16),
mainAxisSize: MainAxisSize.min, child: Column(
crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min,
children: [ crossAxisAlignment: CrossAxisAlignment.start,
RecurrentTaskInfoWidget(model: requestProvider.recurrentWoData),
requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms != null && requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty
? Column(
children: [
8.height,
RoomTabsWidget(model: requestProvider.recurrentWoData),
],
)
: const SizedBox(),
16.height,
requestProvider.recurrentWoData!.planRecurrentTaskCheckLists != null && requestProvider.recurrentWoData!.planRecurrentTaskCheckLists!.isNotEmpty
? CleanerChecklistWidget(
checklistItems: requestProvider.recurrentWoData!.planRecurrentTaskCheckLists ?? [],
onChecklistChanged: (value) {
setState(() {
requestProvider.recurrentWoData!.planRecurrentTaskCheckLists = value;
});
},
capturedImageBase64: requestProvider.recurrentWoData!.imageRoom,
onImageCaptured: (imageBase64) {
setState(() {
requestProvider.recurrentWoData!.imageRoom = imageBase64;
});
},
)
: const SizedBox(),
],
),
).expanded,
if (requestProvider.recurrentWoData?.status?.value != 1) ...[
FooterActionButton.footerContainer(
context: context,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
AppFilledButton( RecurrentTaskInfoWidget(isClosed: isClosed,model: requestProvider.recurrentWoData),
label: context.translation.save, IgnorePointer(
buttonColor: context.isDark ? AppColor.neutral20 : AppColor.white60, ignoring: isClosed,
textColor: context.isDark ? Colors.white : AppColor.black10, child: requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms != null && requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty
onPressed: () => _updateTask(context: context, status: 0), ? Column(
).expanded, children: [
12.width, 8.height,
AppFilledButton( RoomTabsWidget(model: requestProvider.recurrentWoData),
label: context.translation.complete, ],
buttonColor: AppColor.primary10, )
// textColor: context.isDark?Colors.white: AppColor.black10, : const SizedBox(),
onPressed: () => _updateTask(context: context, status: 1), ),
).expanded, 16.height,
requestProvider.recurrentWoData!.planRecurrentTaskCheckLists != null && requestProvider.recurrentWoData!.planRecurrentTaskCheckLists!.isNotEmpty
? CleanerChecklistWidget(
isClosed: isClosed,
checklistItems: requestProvider.recurrentWoData!.planRecurrentTaskCheckLists ?? [],
onChecklistChanged: (value) {
setState(() {
requestProvider.recurrentWoData!.planRecurrentTaskCheckLists = value;
});
},
capturedImageBase64: requestProvider.recurrentWoData!.imageRoom,
onImageCaptured: (imageBase64) {
setState(() {
requestProvider.recurrentWoData!.imageRoom = imageBase64;
});
},
)
: const SizedBox(),
], ],
), ),
), ).expanded,
] if (requestProvider.recurrentWoData?.status?.value != 1) ...[
], FooterActionButton.footerContainer(
context: context,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
AppFilledButton(
label: context.translation.save,
buttonColor: context.isDark ? AppColor.neutral20 : AppColor.white60,
textColor: context.isDark ? Colors.white : AppColor.black10,
onPressed: () => _updateTask(context: context, status: 0),
).expanded,
12.width,
AppFilledButton(
label: context.translation.complete,
buttonColor: AppColor.primary10,
// textColor: context.isDark?Colors.white: AppColor.black10,
onPressed: () => _updateTask(context: context, status: 1),
).expanded,
],
),
),
]
],
),
) )
: NoDataFound(message: context.translation.noDataFound).center, : NoDataFound(message: context.translation.noDataFound).center,
).handlePopScope( ).handlePopScope(
cxt: context, cxt: context,
showPopUp: !isClosed,
onSave: () { onSave: () {
_updateTask(context: context, status: 0); _updateTask(context: context, status: 0);
}); });

Loading…
Cancel
Save