implement uiux changes on cleaner module

ui_ux_rollout_merge
WaseemAbbasi22 1 week ago
parent 3766c69368
commit 65335dca87

@ -7,8 +7,8 @@ class URLs {
// static const host1 = "https://atomsmdev.hmg.com"; // local DEV url // static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
static const host1 = "https://atomsmuat.hmg.com"; // local UAT url static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
// static final String _baseUrl = "$_host/mobile"; // host local UAT static final String _baseUrl = "$_host/mobile"; // host local UAT
static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis // static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
// static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM // static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM
// static final String _baseUrl = "$_host/v4/mobile"; // v4 for Demo module // static final String _baseUrl = "$_host/v4/mobile"; // v4 for Demo module
// static final String _baseUrl = "$_host/v5/mobile"; // v5 for data segregation // static final String _baseUrl = "$_host/v5/mobile"; // v5 for data segregation

@ -252,7 +252,7 @@ class _RequestCategoryFragmentState extends State<RequestCategoryFragment> with
snapshot.allRequestsAndCount?.requestsDetails ?? [], snapshot.allRequestsAndCount?.requestsDetails ?? [],
snapshot.isAllLoading, snapshot.isAllLoading,
disableScroll: true, disableScroll: true,
key: ValueKey('request_list_'), // Key changes on every tab click key: const ValueKey('request_list_'), // Key changes on every tab click
); );
}) })
: dashboardProvider.listIndex.length == 1 && dashboardProvider.isUnassignedTab(dashboardProvider.listIndex[0]) : dashboardProvider.listIndex.length == 1 && dashboardProvider.isUnassignedTab(dashboardProvider.listIndex[0])

@ -1,413 +0,0 @@
// UI: Cleaner Search Details View
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.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/default_app_bar.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/views/widgets/qr/scan_qr.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import '../models/cleaner_task_search_result.dart';
import '../provider/cleaner_provider.dart';
import '../../pm_module/recurrent_wo/recurrent_work_order_view.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:http/http.dart' as http;
class CleanerSearchDetailsView extends StatefulWidget {
static const String routeName = '/cleaner_search_details';
final int requestId;
final CleanerTaskSearchResult? taskResult;
const CleanerSearchDetailsView({
Key? key,
required this.requestId,
this.taskResult,
}) : super(key: key);
@override
_CleanerSearchDetailsViewState createState() => _CleanerSearchDetailsViewState();
}
class _CleanerSearchDetailsViewState extends State<CleanerSearchDetailsView> {
late CleanerProvider _cleanerProvider;
// bool _isQRScanned = false;
bool _isRequestOpen = false;
CleanerTaskSearchResult? _taskData;
RecurrentWoData? _recurrentWoData;
bool _isLoading = false;
@override
void initState() {
super.initState();
_cleanerProvider = Provider.of<CleanerProvider>(context, listen: false);
_taskData = widget.taskResult;
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
}
Future<void> getInitialData() async {
// If taskResult is null, fetch data from recurrent work order API
if (widget.taskResult == null) {
setState(() {
_isLoading = true;
});
try {
// Use direct API call to get better error messages
final result = await _getRecurrentWoByIdWithMessage(widget.requestId);
if (result["success"] == true && result["data"] != null) {
_recurrentWoData = result["data"];
_isRequestOpen = _recurrentWoData?.status?.value == 4;
_taskData = CleanerTaskSearchResult(
id: _recurrentWoData!.id,
taskNo: _recurrentWoData!.taskNo,
siteName: _recurrentWoData!.site?.siteName,
buildingName: _recurrentWoData!.building?.name,
floorName: _recurrentWoData!.floor?.name,
departmentName: _recurrentWoData!.department?.name,
roomName: _recurrentWoData!.room?.name,
locationDescription: null,
createdDate: _recurrentWoData!.scheduleDate,
);
} else {
// Show exact backend error message
if (mounted) {
_showErrorDialog(context, result["message"] ?? "Failed to load request details. Please try again.");
}
}
} catch (e) {
debugPrint('Error fetching recurrent work order: $e');
if (mounted) {
_showErrorDialog(context, "Failed to load request details. Please check your connection and try again.");
}
} finally {
setState(() {
_isLoading = false;
});
}
} else {
try {
await _cleanerProvider.getCleanerRequestById(id: widget.requestId);
} catch (e) {
debugPrint('Error fetching cleaner request: $e');
if (mounted) {
_showErrorDialog(context, "Failed to load request details. Please check your connection and try again.");
}
}
}
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: DefaultAppBar(
title: 'Request Details'.addTranslation,
onBackPress: () => Navigator.pop(context),
),
body: _isLoading
? const Center(child: CircularProgressIndicator())
: SafeArea(
child: Selector<CleanerProvider, bool>(
selector: (_, model) => model.isLoading,
builder: (_, isLoading, __) {
if (isLoading) {
return const Center(child: CircularProgressIndicator());
}
return Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildCleanerRequestDetailCard(context),
],
),
).expanded,
FooterActionButton.footerContainer(
context: context,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (_isRequestOpen) ...[
Row(
children: [
Icon(Icons.info_outline_rounded, size: 16, color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
8.width,
Expanded(
child: Text(
'By scanning the QR code you will accept this task'.addTranslation,
// textAlign: TextAlign.center,
style: AppTextStyles.bodyText2.copyWith(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
),
),
],
),
8.height,
],
AppFilledButton(
label: _isRequestOpen ? 'Scan QR Code' : 'Update',
maxWidth: true,
buttonColor: AppColor.primary10,
onPressed: () async {
if (_isRequestOpen) {
final result = await Navigator.push(context, MaterialPageRoute(builder: (context) => const ScanQr()));
if (result != null && result is String && result.isNotEmpty) {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
try {
final qrResult = await CleanerProvider().checkQRSameRoomWithMessage(planRecurrentTaskId: widget.requestId, qrCode: result);
if (mounted) Navigator.pop(context);
final isValid = qrResult["success"] ?? false;
final backendMessage = qrResult["message"] ?? "Unknown error occurred";
if (isValid) {
if (mounted) {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (_) => RecurrentWorkOrderView(taskId: widget.requestId)),
);
}
} else {
if (mounted) {
// Show exact backend error message instead of our custom message
_showErrorDialog(context, backendMessage);
}
}
} catch (e) {
if (mounted) Navigator.pop(context);
if (mounted) {
// Extract actual error message from the exception or use generic fallback
String errorMessage = _extractErrorMessage(e) ?? 'Failed to validate QR code. Please try again.';
_showErrorDialog(context, errorMessage);
}
}
}
} else {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => RecurrentWorkOrderView(taskId: widget.requestId)),
);
}
},
),
],
),
).toShadowContainer(context, padding: 0, showShadow: false, borderRadius: 0),
],
);
},
),
),
);
}
Widget _buildCleanerRequestDetailCard(BuildContext context) {
final taskResult = _taskData;
if (taskResult == null) {
return const SizedBox();
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Task Number and Date Row
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Text(
// 'Request Information',
// style: AppTextStyles.heading4.copyWith(
// color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
// ),
// ),
if (_recurrentWoData?.status?.name != null)
StatusLabel(
label: _recurrentWoData?.status?.name!,
textColor: AppColor.getRequestStatusTextColorByName(context, _recurrentWoData?.status?.name!),
backgroundColor: AppColor.getRequestStatusColorByName(context, _recurrentWoData?.status?.name!),
),
8.width,
// StatusLabel(
// label: taskModel?.taskJobStatus?.name ?? widget.requestDetails?.status!,
// textColor: AppColor.getRequestStatusTextColorByName(context, taskModel?.taskJobStatus?.name ?? widget.requestDetails?.status!),
// backgroundColor: AppColor.getRequestStatusColorByName(context, taskModel?.taskJobStatus?.name ?? widget.requestDetails?.status!),
// ),
if (taskResult.createdDate != null)
Text(
taskResult.createdDate!.toServiceRequestCardFormat,
textAlign: TextAlign.end,
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
],
),
8.height,
if (_recurrentWoData?.title?.isNotEmpty ?? false)
Text(
_recurrentWoData?.title ?? "",
style: AppTextStyles.heading4.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
),
),
if (taskResult.taskNo != null && taskResult.taskNo!.isNotEmpty)
Text(
'Task No: ${taskResult.taskNo!}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (taskResult.siteName != null && taskResult.siteName!.isNotEmpty)
Text(
'Site: ${taskResult.siteName}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (taskResult.buildingName != null && taskResult.buildingName!.isNotEmpty)
Text(
'Building: ${taskResult.buildingName}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (taskResult.floorName != null && taskResult.floorName!.isNotEmpty)
Text(
'Floor: ${taskResult.floorName}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (taskResult.departmentName != null && taskResult.departmentName!.isNotEmpty)
Text(
'Department: ${taskResult.departmentName}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (taskResult.roomName != null && taskResult.roomName!.isNotEmpty)
Text(
'Room: ${taskResult.roomName}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (taskResult.locationDescription != null && taskResult.locationDescription!.isNotEmpty)
Text(
'Location: ${taskResult.locationDescription}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],
).expanded,
],
),
],
).paddingOnly(start: 16, end: 16, top: 16, bottom: 8),
],
).toShadowContainer(context, padding: 0);
}
void _showErrorDialog(BuildContext context, String message) {
showDialog(
context: context,
builder: (context) => ConfirmDialog(
message: message,
title: 'Error',
onTap: () => Navigator.pop(context),
),
);
}
String? _extractErrorMessage(dynamic error) {
// Implement your logic to extract error message from the exception
// For example, if the error is a custom exception with a message property:
if (error is ExceptionWithMessage) {
return error.message;
} else if (error is String) {
// If the error is a string, return it directly
return error;
} else if (error is Map<String, dynamic>) {
// If the error is a Map (e.g., parsed JSON), extract the message field
return error['message'] ?? error.toString();
}
// Fallback to a generic error message
return 'An unexpected error occurred. Please try again.';
}
/// Custom method to get recurrent work order with proper error message extraction
Future<Map<String, dynamic>> _getRecurrentWoByIdWithMessage(int id) async {
try {
final response = await ApiManager.instance.get(
URLs.getRecurrentPlanByIdUrl + "?planRecurrentTaskId=$id",
enableToastMessage: false, // Disable automatic toast
);
final responseData = json.decode(response.body);
if (response.statusCode >= 200 && response.statusCode < 300) {
// Success response
final recurrentWoData = RecurrentWoData.fromJson(responseData["data"]);
// Apply the same processing as in AllRequestsProvider
recurrentWoData.planRecurrentMedicalTaskRooms?.forEach((element) {
element.planRecurrentMedicalTaskRoomTabs?.forEach((tabs) {
tabs.planRecurrentMedicalTaskRoomTabAttributes?.forEach((attribute) {
if (attribute.attribute?.type == "bool" && attribute.attributeValue == null) {
attribute.attributeValue = "true";
}
});
});
});
return {
"success": true,
"data": recurrentWoData,
"message": "Data loaded successfully",
};
} else {
// Error response - extract the exact error message from backend
return {
"success": false,
"data": null,
"message": responseData["message"] ?? "Failed to load request details",
};
}
} catch (error) {
debugPrint('Error in _getRecurrentWoByIdWithMessage: $error');
return {
"success": false,
"data": null,
"message": "Failed to load request details. Please check your connection and try again.",
};
}
}
}
class ExceptionWithMessage implements Exception {
final String message;
ExceptionWithMessage(this.message);
}

@ -16,6 +16,7 @@ import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.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/providers/loading_list_notifier.dart'; import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart'; import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/qr/scan_qr.dart'; import 'package:test_sa/views/widgets/qr/scan_qr.dart';
class CleanerSearchFormView extends StatefulWidget { class CleanerSearchFormView extends StatefulWidget {
@ -203,6 +204,7 @@ class _CleanerSearchFormViewState extends State<CleanerSearchFormView> {
), ),
// Scan QR Code Button // Scan QR Code Button
8.height,
GestureDetector( GestureDetector(
onTap: selectedTaskType != null ? _onScanQRCode : null, onTap: selectedTaskType != null ? _onScanQRCode : null,
child: Container( child: Container(
@ -223,20 +225,16 @@ class _CleanerSearchFormViewState extends State<CleanerSearchFormView> {
"scan_asset".toSvgAsset( "scan_asset".toSvgAsset(
height: 22, height: 22,
fit: BoxFit.fitHeight, fit: BoxFit.fitHeight,
color: selectedTaskType != null color: selectedTaskType != null ? (context.isDark ? AppColor.neutral20 : AppColor.neutral120) : Colors.grey,
? (context.isDark ? AppColor.neutral20 : AppColor.neutral120)
: Colors.grey,
), ),
8.width, 8.width,
//we can change the implementation when merge with uiux branch //we can change the implementation when merge with uiux branch
_scannedLocationData==null? "Scan QR Code".bodyText(context).custom( _scannedLocationData == null
color: selectedTaskType != null ? "Scan QR Code".bodyText(context).custom(
? (context.isDark ? AppColor.neutral20 : AppColor.black20) color: selectedTaskType != null ? (context.isDark ? AppColor.neutral20 : AppColor.black20) : Colors.grey,
: Colors.grey, )
):'Re Scan QR Code'.bodyText(context).custom( : 'Re Scan QR Code'.bodyText(context).custom(
color: selectedTaskType != null color: selectedTaskType != null ? (context.isDark ? AppColor.neutral20 : AppColor.black20) : Colors.grey,
? (context.isDark ? AppColor.neutral20 : AppColor.black20)
: Colors.grey,
), ),
], ],
), ),
@ -290,49 +288,45 @@ class _CleanerSearchFormViewState extends State<CleanerSearchFormView> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (locationData.siteName != null && locationData.siteName!.isNotEmpty) if (locationData.siteName != null && locationData.siteName!.isNotEmpty)
Text( InfoTextWidget(
'Site: ${locationData.siteName}', label: 'Site', value: locationData.siteName,
style: AppTextStyles.bodyText.copyWith( // style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120, // color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
), // ),
), ),
if (locationData.buildingName != null && locationData.buildingName!.isNotEmpty) if (locationData.buildingName != null && locationData.buildingName!.isNotEmpty)
Text( InfoTextWidget(
'Building: ${locationData.buildingName}', label: 'Building',
style: AppTextStyles.bodyText.copyWith( value: locationData.buildingName,
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
if (locationData.floorName != null && locationData.floorName!.isNotEmpty) if (locationData.floorName != null && locationData.floorName!.isNotEmpty)
Text( InfoTextWidget(
'Floor: ${locationData.floorName}', label: 'Floor',
style: AppTextStyles.bodyText.copyWith( value: locationData.floorName,
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
if (locationData.departmentName != null && locationData.departmentName!.isNotEmpty) if (locationData.departmentName != null && locationData.departmentName!.isNotEmpty)
Text( InfoTextWidget(
'Department: ${locationData.departmentName}', label: 'Department',
style: AppTextStyles.bodyText.copyWith( value: locationData.departmentName,
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
if (locationData.roomName != null && locationData.roomName!.isNotEmpty) if (locationData.roomName != null && locationData.roomName!.isNotEmpty)
Text( InfoTextWidget(
'Room: ${locationData.roomName}', label: 'Room',
style: AppTextStyles.bodyText.copyWith( value: locationData.roomName,
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
if (locationData.locationDescription != null && locationData.locationDescription!.isNotEmpty) if (locationData.locationDescription != null && locationData.locationDescription!.isNotEmpty)
Text( InfoTextWidget(
'Location Description: ${locationData.locationDescription}', label: 'Location Description',
style: AppTextStyles.bodyText.copyWith( value: locationData.locationDescription,
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
softWrap: true,
maxLines: null,
), ),
// Text(
// 'Location Description: ${locationData.locationDescription}',
// style: AppTextStyles.bodyText.copyWith(
// color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
// ),
// softWrap: true,
// maxLines: null,
// ),
], ],
).paddingOnly(start: 16, end: 16, top: 16, bottom: 16), ).paddingOnly(start: 16, end: 16, top: 16, bottom: 16),
], ],

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/modules/cleaner_module/models/one_time_task_data.dart'; import 'package:test_sa/modules/cleaner_module/models/one_time_task_data.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
@ -11,6 +10,8 @@ import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/views/widgets/images/files_list.dart'; import 'package:test_sa/views/widgets/images/files_list.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart'; import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/timer/app_timer.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart';
import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/models/timer_model.dart';
import 'dart:convert'; import 'dart:convert';
@ -102,24 +103,20 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( InfoHeader16Widget(
'Task Information', 'Task Information',
style: AppTextStyles.heading5.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
fontWeight: FontWeight.w600,
),
), ),
12.height, 12.height,
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (taskData.oneTimeSetting?.taskTypeName != null) _buildInfoRow(context, 'Task Type', taskData.oneTimeSetting!.taskTypeName!), if (taskData.oneTimeSetting?.taskTypeName != null) InfoTextWidget(label: 'Task Type', value: taskData.oneTimeSetting!.taskTypeName!),
if (taskData.siteName != null) _buildInfoRow(context, 'Site', taskData.siteName!), if (taskData.siteName != null) InfoTextWidget(label: 'Site', value: taskData.siteName!),
if (taskData.buildingName != null) _buildInfoRow(context, 'Building', taskData.buildingName!), if (taskData.buildingName != null) InfoTextWidget(label: 'Building', value: taskData.buildingName!),
if (taskData.floorName != null) _buildInfoRow(context, 'Floor', taskData.floorName!), if (taskData.floorName != null) InfoTextWidget(label: 'Floor', value: taskData.floorName!),
if (taskData.departmentName != null) _buildInfoRow(context, 'Department', taskData.departmentName!), if (taskData.departmentName != null) InfoTextWidget(label: 'Department', value: taskData.departmentName!),
if (taskData.roomName != null) _buildInfoRow(context, 'Room', taskData.roomName!), if (taskData.roomName != null) InfoTextWidget(label: 'Room', value: taskData.roomName!),
if (taskData.locationDescription != null) _buildInfoRow(context, 'Location', taskData.locationDescription!), if (taskData.locationDescription != null) InfoTextWidget(label: 'Location', value: taskData.locationDescription!),
], ],
).paddingAll(16), ).paddingAll(16),
], ],
@ -140,12 +137,8 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( InfoHeader16Widget(
'Working Hours', 'Working Hours',
style: AppTextStyles.heading5.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
fontWeight: FontWeight.w600,
),
), ),
12.height, 12.height,
if (timerStartTime != null) if (timerStartTime != null)
@ -156,7 +149,8 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
endAt: null, endAt: null,
durationInSecond: 0, durationInSecond: 0,
), ),
enabled: false, // Disable controls, just show the timer enabled: false,
// Disable controls, just show the timer
showTimer: true, showTimer: true,
decoration: BoxDecoration( decoration: BoxDecoration(
color: context.isDark ? AppColor.neutral20.withValues(alpha: 0.5) : AppColor.neutral10.withValues(alpha: 0.1), color: context.isDark ? AppColor.neutral20.withValues(alpha: 0.5) : AppColor.neutral10.withValues(alpha: 0.1),
@ -173,18 +167,11 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( InfoTextLabelWidget(
'Total Working Hours', label: 'Total Working Hours',
style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
), ),
), InfoHeader16Widget(
Text(
CMRequestUtils.formatTotalWorkingHours(totalWorkingHours), CMRequestUtils.formatTotalWorkingHours(totalWorkingHours),
style: AppTextStyles.heading6.copyWith(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
fontWeight: FontWeight.w600,
),
), ),
], ],
), ),
@ -203,19 +190,11 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( InfoHeader16Widget(
'Checklist', 'Checklist',
style: AppTextStyles.heading5.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
fontWeight: FontWeight.w600,
),
),
Text(
'${completedInstructions.length}/$totalInstructions',
style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
fontWeight: FontWeight.w600,
), ),
InfoTextLabelWidget(
label: '${completedInstructions.length}/$totalInstructions',
), ),
], ],
), ),
@ -234,18 +213,15 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Icon( const Icon(
Icons.check_circle, Icons.check_circle,
color: AppColor.primary10, color: AppColor.primary10,
size: 20, size: 20,
), ),
8.width, 8.width,
Expanded( Expanded(
child: Text( child: InfoTextLabelWidget(
instruction.instructionText ?? '', label: instruction.instructionText ?? '',
style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
), ),
], ],
@ -262,19 +238,12 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( InfoTextLabelWidget(
'Comment:', label: 'Comment:',
style: AppTextStyles.tinyFont.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
fontWeight: FontWeight.w600,
),
), ),
4.height, 4.height,
Text( InfoTextLabelWidget(
instruction.comment!, label: instruction.comment!,
style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
], ],
), ),
@ -293,12 +262,8 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( InfoHeader16Widget(
'Captured Images', 'Captured Images',
style: AppTextStyles.heading5.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
fontWeight: FontWeight.w600,
),
), ),
16.height, 16.height,
Wrap( Wrap(
@ -350,12 +315,8 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( InfoHeader16Widget(
'Attachments', 'Attachments',
style: AppTextStyles.heading5.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
fontWeight: FontWeight.w600,
),
), ),
FilesList( FilesList(
images: taskData.attachments!.map((attachment) => URLs.getFileUrl(attachment.name ?? '') ?? '').toList(), images: taskData.attachments!.map((attachment) => URLs.getFileUrl(attachment.name ?? '') ?? '').toList(),
@ -387,20 +348,13 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
children: [ children: [
SizedBox( SizedBox(
width: 100, width: 100,
child: Text( child: InfoTextLabelWidget(
'$label:', label:'$label:',
style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
),
), ),
), ),
Expanded( Expanded(
child: Text( child: InfoTextLabelWidget(
value, label: value,
style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
fontWeight: FontWeight.w500,
),
), ),
), ),
], ],

@ -18,6 +18,9 @@ import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/new_views/pages/land_page/land_page.dart'; import 'package:test_sa/new_views/pages/land_page/land_page.dart';
import 'package:test_sa/views/widgets/item_views/info_date_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart'; import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart';
@ -218,40 +221,32 @@ class _OneTimeTaskViewState extends State<OneTimeTaskView> {
textColor: AppColor.getHistoryLogStatusTextColorByName(context, _taskData!.statusName!), textColor: AppColor.getHistoryLogStatusTextColorByName(context, _taskData!.statusName!),
backgroundColor: AppColor.getHistoryLogStatusColorByName(context, _taskData!.statusName!), backgroundColor: AppColor.getHistoryLogStatusColorByName(context, _taskData!.statusName!),
), ),
if (_taskData?.createdDate != null) if (_taskData?.createdDate != null) InfoDateWidget(_taskData!.createdDate!.toString()),
Text(
_taskData!.createdDate!.toString().toServiceRequestCardFormat,
textAlign: TextAlign.end,
style: AppTextStyles.tinyFont.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
),
),
], ],
), ),
12.height, 12.height,
if (_taskData?.oneTimeSetting?.taskTypeName != null) if (_taskData?.oneTimeSetting?.taskTypeName != null)
Text( InfoTextLabelWidget(
_taskData!.oneTimeSetting!.taskTypeName!, label: _taskData!.oneTimeSetting!.taskTypeName!,
style: AppTextStyles.heading4.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
),
), ),
8.height,
// Text(
// _taskData!.oneTimeSetting!.taskTypeName!,
// style: AppTextStyles.heading4.copyWith(
// color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
// ),
// ),
// 8.height,
if (_taskData?.oneTimeSetting?.instructionDescriptionName != null) if (_taskData?.oneTimeSetting?.instructionDescriptionName != null)
Text( InfoTextLabelWidget(
_taskData!.oneTimeSetting!.instructionDescriptionName!, label: _taskData!.oneTimeSetting!.instructionDescriptionName!,
style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
), ),
8.height, if (_taskData?.siteName != null) InfoTextWidget(label: 'Site', value: _taskData!.siteName!),
if (_taskData?.siteName != null) _buildInfoRow('Site', _taskData!.siteName!), if (_taskData?.buildingName != null) InfoTextWidget(label: 'Building', value: _taskData!.buildingName!),
if (_taskData?.buildingName != null) _buildInfoRow('Building', _taskData!.buildingName!), if (_taskData?.floorName != null) InfoTextWidget(label: 'Floor', value: _taskData!.floorName!),
if (_taskData?.floorName != null) _buildInfoRow('Floor', _taskData!.floorName!), if (_taskData?.departmentName != null) InfoTextWidget(label: 'Department', value: _taskData!.departmentName!),
if (_taskData?.departmentName != null) _buildInfoRow('Department', _taskData!.departmentName!), if (_taskData?.roomName != null) InfoTextWidget(label: 'Room', value: _taskData!.roomName!),
if (_taskData?.roomName != null) _buildInfoRow('Room', _taskData!.roomName!), if (_taskData?.locationDescription != null) InfoTextWidget(label: 'Location', value: _taskData!.locationDescription!),
if (_taskData?.locationDescription != null) _buildInfoRow('Location', _taskData!.locationDescription!),
// Timer display using AppTimer widget
if (_timerStart != null && !isClosed) ...[ if (_timerStart != null && !isClosed) ...[
12.height, 12.height,
AppTimer( AppTimer(
@ -286,18 +281,6 @@ class _OneTimeTaskViewState extends State<OneTimeTaskView> {
).toShadowContainer(context, padding: 0); ).toShadowContainer(context, padding: 0);
} }
Widget _buildInfoRow(String label, String value) {
return Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Text(
'$label: $value',
style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
),
),
);
}
List<ChecklistItem> _convertInstructionsToChecklist() { List<ChecklistItem> _convertInstructionsToChecklist() {
// If checklist items are already created, reuse them // If checklist items are already created, reuse them
if (_checklistItems != null) { if (_checklistItems != null) {
@ -354,22 +337,15 @@ class _OneTimeTaskViewState extends State<OneTimeTaskView> {
// Validate that at least one image is captured // Validate that at least one image is captured
final capturedImages = _taskData?.imageRooms ?? []; final capturedImages = _taskData?.imageRooms ?? [];
print('DEBUG: Captured images count: ${capturedImages.length}');
print('DEBUG: Images: $capturedImages');
if (capturedImages.isEmpty) { if (capturedImages.isEmpty) {
_showErrorDialog(context, "Please capture at least one image before completing"); _showErrorDialog(context, "Please capture at least one image before completing");
return; return;
} }
// Calculate working hours
double totalWorkingHours = 0; double totalWorkingHours = 0;
if (_timerStart != null) { if (_timerStart != null) {
final duration = DateTime.now().difference(_timerStart!); final duration = DateTime.now().difference(_timerStart!);
totalWorkingHours = duration.inSeconds / 3600.0; totalWorkingHours = duration.inSeconds / 3600.0;
} }
// Navigate to preview screen
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (context) => OneTimeTaskPreviewScreen( builder: (context) => OneTimeTaskPreviewScreen(
@ -401,7 +377,6 @@ class _OneTimeTaskViewState extends State<OneTimeTaskView> {
}).toList() ?? }).toList() ??
[]; [];
// Convert images to attachments format
final attachmentsPayload = _taskData?.imageRooms?.map((imageString) { final attachmentsPayload = _taskData?.imageRooms?.map((imageString) {
// imageString format: "filename|base64data" // imageString format: "filename|base64data"
final parts = imageString.split('|'); final parts = imageString.split('|');

@ -11,6 +11,8 @@ import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart';
import 'package:test_sa/modules/cleaner_module/widgets/multi_image_picker.dart'; import 'package:test_sa/modules/cleaner_module/widgets/multi_image_picker.dart';
import 'package:test_sa/views/widgets/images/files_list.dart'; import 'package:test_sa/views/widgets/images/files_list.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
class CleanerChecklistWidget extends StatefulWidget { class CleanerChecklistWidget extends StatefulWidget {
final List<ChecklistItem> checklistItems; final List<ChecklistItem> checklistItems;
@ -19,14 +21,7 @@ class CleanerChecklistWidget extends StatefulWidget {
final Function(List<String>)? onImagesChanged; final Function(List<String>)? onImagesChanged;
final bool isClosed; final bool isClosed;
const CleanerChecklistWidget({ const CleanerChecklistWidget({Key? key, required this.checklistItems, this.onChecklistChanged, required this.capturedImages, this.onImagesChanged, this.isClosed = false}) : super(key: key);
Key? key,
required this.checklistItems,
this.onChecklistChanged,
required this.capturedImages,
this.onImagesChanged,
this.isClosed = false
}) : super(key: key);
@override @override
State<CleanerChecklistWidget> createState() => _CleanerChecklistWidgetState(); State<CleanerChecklistWidget> createState() => _CleanerChecklistWidgetState();
@ -43,12 +38,7 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( InfoHeader16Widget('Checklist'),
'Checklist'.addTranslation,
style: AppTextStyles.heading4.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
),
),
16.height, 16.height,
ListView.separated( ListView.separated(
shrinkWrap: true, shrinkWrap: true,
@ -93,10 +83,7 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
children: [ children: [
TextSpan( TextSpan(
text: item.title, text: item.title,
style: AppTextStyles.bodyText.copyWith( style: AppTextStyles.bodyText2.copyWith(color: AppColor.lightTextColor(context)),
color: context.isDark ? AppColor.neutral10 : AppColor.neutral120,
fontWeight: FontWeight.w500,
),
), ),
if (item.isMandatory) if (item.isMandatory)
TextSpan( TextSpan(
@ -175,9 +162,7 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
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,
color: context.isDark ? AppColor.white10 : AppColor.black10,
),
alignLabelWithHint: true, alignLabelWithHint: true,
textInputType: TextInputType.multiline, textInputType: TextInputType.multiline,
onChange: (value) { onChange: (value) {
@ -199,19 +184,7 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( InfoHeader16Widget('Captured Image'),
'Captured Image'.addTranslation,
style: AppTextStyles.heading6.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
),
),
// Text(
// '(${widget.capturedImages.length}/$maxImages)',
// style: AppTextStyles.bodyText.copyWith(
// color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
// fontWeight: FontWeight.w600,
// ),
// ),
], ],
), ),
8.height, 8.height,
@ -227,7 +200,9 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
if (widget.capturedImages.isEmpty) { if (widget.capturedImages.isEmpty) {
// Show add image button when no image // Show add image button when no image
return GestureDetector( return GestureDetector(
onTap: widget.isClosed ? null : () async { onTap: widget.isClosed
? null
: () async {
// Only allow camera - pick one image at a time // Only allow camera - pick one image at a time
final pickedFile = await ImagePicker().pickImage( final pickedFile = await ImagePicker().pickImage(
source: ImageSource.camera, source: ImageSource.camera,
@ -270,12 +245,14 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
color: context.isDark ? AppColor.white10 : AppColor.black10, color: context.isDark ? AppColor.white10 : AppColor.black10,
), ),
4.height, 4.height,
Text( InfoTextLabelWidget(label: 'Add Image'),
'Add Image',
style: AppTextStyles.tinyFont.copyWith( // Text(
color: context.isDark ? AppColor.white10 : AppColor.black10, // 'Add Image',
), // style: AppTextStyles.tinyFont.copyWith(
), // color: context.isDark ? AppColor.white10 : AppColor.black10,
// ),
// ),
], ],
), ),
), ),
@ -283,8 +260,7 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
} }
// Check if images are URLs from API (like ServiceRequestDetailView does) // Check if images are URLs from API (like ServiceRequestDetailView does)
final bool hasApiImages = widget.capturedImages.any((img) => final bool hasApiImages = widget.capturedImages.any((img) => img.startsWith('http://') || img.startsWith('https://'));
img.startsWith('http://') || img.startsWith('https://'));
// If images are from API (URLs), use FilesList widget like ServiceRequestDetailView // If images are from API (URLs), use FilesList widget like ServiceRequestDetailView
if (hasApiImages && widget.isClosed) { if (hasApiImages && widget.isClosed) {
@ -298,7 +274,8 @@ class _CleanerChecklistWidgetState extends State<CleanerChecklistWidget> {
return MultiImagePicker( return MultiImagePicker(
imageUrls: widget.capturedImages, imageUrls: widget.capturedImages,
enabled: !widget.isClosed, enabled: !widget.isClosed,
maxImages: 2, // Enforce max 2 images maxImages: 2,
// Enforce max 2 images
onImageTap: (index, imageUrl) { onImageTap: (index, imageUrl) {
// Handle image tap - show in full screen // Handle image tap - show in full screen
Navigator.of(context).push( Navigator.of(context).push(

@ -10,6 +10,9 @@ import 'package:test_sa/models/all_requests_and_count_model.dart';
import 'package:test_sa/models/new_models/dashboard_detail.dart'; import 'package:test_sa/models/new_models/dashboard_detail.dart';
import 'package:test_sa/modules/cleaner_module/pages/one_time_task_view.dart'; import 'package:test_sa/modules/cleaner_module/pages/one_time_task_view.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/views/widgets/item_views/info_date_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart';
class OneTimeTaskItemView extends StatelessWidget { class OneTimeTaskItemView extends StatelessWidget {
@ -34,33 +37,20 @@ class OneTimeTaskItemView extends StatelessWidget {
backgroundColor: AppColor.getRequestStatusColorByName(context, requestData!.statusName ?? ''), backgroundColor: AppColor.getRequestStatusColorByName(context, requestData!.statusName ?? ''),
), ),
1.width.expanded, 1.width.expanded,
Text( InfoDateWidget(requestData!.transactionDate ?? ""),
requestData!.transactionDate?.toServiceRequestCardFormat ?? "",
textAlign: TextAlign.end,
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
),
], ],
), ),
8.height, 8.height,
(requestData?.typeTransaction ?? context.translation.recurrentWo).heading5(context), InfoHeaderWidget(requestData?.typeTransaction ?? 'One Time Task'.addTranslation),
8.height, InfoTextWidget(label: context.translation.taskNo, value: requestData!.requestNo),
'${context.translation.taskNo}: ${requestData!.requestNo}'.bodyText(context), if (requestData?.siteName != null) InfoTextWidget(label: context.translation.site, value: requestData!.siteName),
if (requestData?.siteName != null) '${context.translation.site}: ${requestData!.siteName}'.bodyText(context), if (requestData!.buildingName != null) InfoTextWidget(label: context.translation.building, value: requestData!.buildingName),
if (requestData!.buildingName != null) '${context.translation.building}: ${requestData!.buildingName}'.bodyText(context), if (requestData!.departmentName != null) InfoTextWidget(label: context.translation.department, value: requestData!.departmentName),
if (requestData!.departmentName != null) '${context.translation.department}: ${requestData!.departmentName}'.bodyText(context), if (requestData!.floorName != null) InfoTextWidget(label: context.translation.floor, value: requestData!.floorName),
if (requestData!.floorName != null) '${context.translation.floor}: ${requestData!.floorName}'.bodyText(context), InfoTextWidget(
if (requestData!.roomName != null) '${context.translation.room}: ${requestData!.roomName}'.bodyText(context), label: context.translation.room,
8.height, value: requestData!.roomName,
Row( showArrow: true,
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.translation.viewDetails,
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
),
4.width,
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
],
), ),
], ],
).toShadowContainer(context, withShadow: showShadow).onPress(() { ).toShadowContainer(context, withShadow: showShadow).onPress(() {
@ -89,38 +79,23 @@ class OneTimeTaskItemView extends StatelessWidget {
backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails!.status!), backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails!.status!),
), ),
1.width.expanded, 1.width.expanded,
Text( InfoDateWidget(requestDetails!.date ?? ""),
requestDetails!.date?.toServiceRequestCardFormat ?? "",
textAlign: TextAlign.end,
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
),
], ],
), ),
8.height, 8.height,
(requestDetails?.nameOfType ?? context.translation.recurrentWo).heading5(context), InfoHeaderWidget(requestDetails?.nameOfType ?? 'One Time Task'.addTranslation),
8.height, InfoTextWidget(label: context.translation.taskNo, value: requestDetails!.requestNo),
'${context.translation.site}: ${requestDetails!.site}'.bodyText(context), if (requestDetails!.siteName != null) InfoTextWidget(label: context.translation.site, value: requestDetails!.siteName),
'${context.translation.taskNo}: ${requestDetails!.requestNo}'.bodyText(context), if (requestDetails!.buildingName != null) InfoTextWidget(label: context.translation.building, value: requestDetails!.buildingName),
if (requestDetails!.siteName != null) '${context.translation.site}: ${requestDetails!.siteName}'.bodyText(context), if (requestDetails!.departmentName != null) InfoTextWidget(label: context.translation.department, value: requestDetails!.departmentName),
if (requestDetails!.buildingName != null) '${context.translation.building}: ${requestDetails!.buildingName}'.bodyText(context), if (requestDetails!.floorName != null) InfoTextWidget(label: context.translation.floor, value: requestDetails!.floorName),
if (requestDetails!.departmentName != null) '${context.translation.department}: ${requestDetails!.departmentName}'.bodyText(context), InfoTextWidget(
if (requestDetails!.floorName != null) '${context.translation.floor}: ${requestDetails!.floorName}'.bodyText(context), label: context.translation.room,
if (requestDetails!.roomName != null) '${context.translation.room}: ${requestDetails!.roomName}'.bodyText(context), value: requestDetails!.roomName,
8.height, showArrow: true,
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.translation.viewDetails,
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
),
4.width,
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
],
), ),
], ],
).toShadowContainer(context, withShadow: showShadow).onPress(() async { ).toShadowContainer(context, withShadow: showShadow).onPress(() async {
// Navigate to editable view for in-progress tasks
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(

@ -1,14 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/all_requests_and_count_model.dart'; import 'package:test_sa/models/all_requests_and_count_model.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/new_models/dashboard_detail.dart'; import 'package:test_sa/models/new_models/dashboard_detail.dart';
import 'package:test_sa/modules/cleaner_module/pages/cleaner_search_details_view.dart';
import 'package:test_sa/modules/pm_module/recurrent_wo/recurrent_work_order_view.dart'; import 'package:test_sa/modules/pm_module/recurrent_wo/recurrent_work_order_view.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/views/widgets/item_views/info_date_widget.dart'; import 'package:test_sa/views/widgets/item_views/info_date_widget.dart';
@ -25,7 +20,6 @@ class RecurrentWoItemView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final user = Provider.of<UserProvider>(context, listen: false).user;
if (requestData != null) { if (requestData != null) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -49,15 +43,14 @@ class RecurrentWoItemView extends StatelessWidget {
], ],
), ),
8.height, 8.height,
InfoHeaderWidget(requestData?.typeTransaction ?? context.translation.recurrentWo), InfoHeaderWidget(requestData?.typeTransaction ?? context.translation.recurrentWo),
InfoTextWidget(label: context.translation.taskNo, value: requestData!.requestNo, showArrow: true), InfoTextWidget(label: context.translation.taskNo, value: requestData!.requestNo),
// todo @waseem replace below code to infotextwidget InfoTextWidget(label: context.translation.taskNo, value: requestData!.requestNo),
// if (requestData?.siteName != null) '${context.translation.site}: ${requestData!.siteName}'.bodyText(context), if (requestData?.siteName != null) InfoTextWidget(label: context.translation.site, value: requestData!.siteName),
// if (requestData!.buildingName != null) '${context.translation.building}: ${requestData!.buildingName}'.bodyText(context), if (requestData!.buildingName != null) InfoTextWidget(label: context.translation.building, value: requestData!.buildingName),
// if (requestData!.departmentName != null) '${context.translation.department}: ${requestData!.departmentName}'.bodyText(context), if (requestData!.departmentName != null) InfoTextWidget(label: context.translation.department, value: requestData!.departmentName),
// if (requestData!.floorName != null) '${context.translation.floor}: ${requestData!.floorName}'.bodyText(context), if (requestData!.floorName != null) InfoTextWidget(label: context.translation.floor, value: requestData!.floorName),
// if (requestData!.roomName != null) '${context.translation.room}: ${requestData!.roomName}'.bodyText(context), if (requestData!.roomName != null) InfoTextWidget(label: context.translation.room, value: requestData!.roomName, showArrow: true),
], ],
).toShadowContainer(context, withShadow: showShadow).onPress(() { ).toShadowContainer(context, withShadow: showShadow).onPress(() {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => RecurrentWorkOrderView(taskId: requestData!.id))); Navigator.of(context).push(MaterialPageRoute(builder: (_) => RecurrentWorkOrderView(taskId: requestData!.id)));
@ -88,15 +81,15 @@ class RecurrentWoItemView extends StatelessWidget {
), ),
8.height, 8.height,
InfoHeaderWidget(requestDetails?.nameOfType ?? context.translation.recurrentWo), InfoHeaderWidget(requestDetails?.nameOfType ?? context.translation.recurrentWo),
InfoTextWidget(label: context.translation.site, value: requestDetails!.site), InfoTextWidget(
InfoTextWidget(label: context.translation.taskNo, value: requestDetails!.requestNo, showArrow: true), label: context.translation.taskNo,
value: requestDetails!.requestNo,
// todo @waseem replace below code to infotextwidget ),
// if (requestDetails!.siteName != null) '${context.translation.site}: ${requestDetails!.siteName}'.bodyText(context), if (requestDetails!.siteName != null) InfoTextWidget(label: context.translation.site, value: requestDetails!.siteName),
// if (requestDetails!.buildingName != null) '${context.translation.building}: ${requestDetails!.buildingName}'.bodyText(context), if (requestDetails!.buildingName != null) InfoTextWidget(label: context.translation.building, value: requestDetails!.buildingName),
// if (requestDetails!.departmentName != null) '${context.translation.department}: ${requestDetails!.departmentName}'.bodyText(context), if (requestDetails!.departmentName != null) InfoTextWidget(label: context.translation.department, value: requestDetails!.departmentName),
// if (requestDetails!.floorName != null) '${context.translation.floor}: ${requestDetails!.floorName}'.bodyText(context), if (requestDetails!.floorName != null) InfoTextWidget(label: context.translation.floor, value: requestDetails!.floorName),
// if (requestDetails!.roomName != null) '${context.translation.room}: ${requestDetails!.roomName}'.bodyText(context), if (requestDetails!.roomName != null) InfoTextWidget(label: context.translation.room, value: requestDetails!.roomName, showArrow: true),
], ],
).toShadowContainer(context, withShadow: showShadow).onPress(() async { ).toShadowContainer(context, withShadow: showShadow).onPress(() async {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => RecurrentWorkOrderView(taskId: requestDetails!.id))); Navigator.of(context).push(MaterialPageRoute(builder: (_) => RecurrentWorkOrderView(taskId: requestDetails!.id)));

Loading…
Cancel
Save