Merge branch 'design_3.0_TM_Module' into design_3.0_task_module_new_merge

# Conflicts:
#	lib/controllers/api_routes/urls.dart
#	lib/views/widgets/fullscreen_dialogs/selection_fullscreen_dialog.dart
design_3.0_TM_Module_snagsFix
WaseemAbbasi22 2 months ago
commit 9a332e86e2

@ -1,7 +1,7 @@
class URLs {
URLs._();
static const String appReleaseBuildNumber = "24";
static const String appReleaseBuildNumber = "25";
// static const host1 = "https://atomsm.hmg.com"; // production url
// static const host1 = "https://atomsmdev.hmg.com"; // local DEV url

@ -151,7 +151,7 @@ class WorkOrderData {
Lookup? serviceType;
Lookup? failureReasone;
FaultDescription? faultDescription;
Lookup? solution;
String? solution;
String? edd;
Lookup? cmFrame;
@ -237,7 +237,7 @@ class WorkOrderData {
serviceType: json["serviceType"] == null ? null : Lookup.fromJson(json["serviceType"]),
failureReasone: json["failureReasone"] == null ? null : Lookup.fromJson(json["failureReasone"]),
faultDescription: json["faultDescription"] == null ? null : FaultDescription.fromJson(json["faultDescription"]),
solution: json["solution"] == null ? null : Lookup.fromJson(json["solution"]),
solution: json["solution"],
totalWorkingHours: (json["totalWorkingHours"] ?? "").toString(),
workOrderHistory: json["workOrderHistory"] == null ? [] : List<WorkOrderHistory>.from(json["workOrderHistory"]!.map((x) => WorkOrderHistory.fromJson(x))),
activities: json["activities"] == null ? [] : List<Activities>.from(json["activities"]!.map((x) => Activities.fromJson(x))),
@ -290,7 +290,7 @@ class WorkOrderData {
"returnToService": returnToService,
"serviceType": serviceType?.toJson(),
"failureReasone": failureReasone?.toJson(),
"solution": solution?.toJson(),
"solution": solution,
"totalWorkingHours": totalWorkingHours,
"workOrderHistory": workOrderHistory.map((x) => x.toJson()).toList(),
"activities": activities.map((x) => x.toJson()).toList(),

@ -252,6 +252,7 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
} catch (e) {
log("getWorkOrder [error] : $e");
isLoading = false;
currentWorkOrder = null;
notifyListeners();
return null;
}

@ -137,43 +137,49 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
children: [
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (Provider.of<SettingProvider>(context, listen: false).showPriority) ...[
StatusLabel(
label: workOrder.priority?.name,
id: workOrder.priority!.id!,
radius: 4,
textColor: AppColor.getPriorityStatusTextColor(context, workOrder.priority!.id!),
backgroundColor: AppColor.getPriorityStatusColor(context, workOrder.priority!.id!),
),
8.width,
],
if (workOrder.itgFormWorkOrderStatus != null) ...[
StatusLabel(
label: workOrder.itgFormWorkOrderStatus,
id: 0,
radius: 4,
textColor: AppColor.getPriorityStatusTextColor(context, 82),
backgroundColor: AppColor.getPriorityStatusColor(context, 0),
),
8.width,
],
StatusLabel(
radius: 4,
label: workOrder.status!.name,
textColor: AppColor.getHistoryLogStatusTextColorByName(workOrder.status!.name!),
backgroundColor: AppColor.getHistoryLogStatusColorByName(workOrder.status!.name!),
),
if (workOrder.since != null) ...[
8.width,
StatusLabel(
radius: 4,
label: '${workOrder.since} days',
textColor: AppColor.neutral50,
backgroundColor: AppColor.orange30,
),
],
1.width.expanded,
Wrap(
// spacing: 8,
runSpacing: 8,
children: [
if (Provider.of<SettingProvider>(context, listen: false).showPriority) ...[
StatusLabel(
label: workOrder.priority?.name,
id: workOrder.priority!.id!,
radius: 4,
textColor: AppColor.getPriorityStatusTextColor(context, workOrder.priority!.id!),
backgroundColor: AppColor.getPriorityStatusColor(context, workOrder.priority!.id!),
),
8.width,
],
if (workOrder.itgFormWorkOrderStatus != null) ...[
StatusLabel(
label: workOrder.itgFormWorkOrderStatus,
id: 0,
radius: 4,
textColor: AppColor.getPriorityStatusTextColor(context, 82),
backgroundColor: AppColor.getPriorityStatusColor(context, 0),
),
8.width,
],
StatusLabel(
radius: 4,
label: workOrder.status!.name,
textColor: AppColor.getHistoryLogStatusTextColorByName(workOrder.status!.name!),
backgroundColor: AppColor.getHistoryLogStatusColorByName(workOrder.status!.name!),
),
if (workOrder.since != null) ...[
8.width,
StatusLabel(
radius: 4,
label: '${workOrder.since} days',
textColor: AppColor.neutral50,
backgroundColor: AppColor.orange30,
),
],
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
@ -181,7 +187,7 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
// context.translation.code.toSvgAsset(width: 48).onPress(() {
// // Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateServiceRequestPage(serviceRequest: serviceRequest)));
// }),
if (userProvider.user!.type == UsersTypes.engineer) 16.height,
// if (userProvider.user!.type == UsersTypes.engineer) 16.height,
Text(
workOrder.requestedDate!.toString().toServiceRequestCardFormat,
textAlign: TextAlign.end,
@ -191,6 +197,7 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
)
],
),
8.height,
Text(
context.translation.assetInformation,
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
@ -508,9 +515,7 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
).expanded,
if (!provider.isReadOnlyRequest)
"edit_icon".toSvgAsset(height: 21, width: 21,
color: context.isDark?AppColor.primary10:null
).onPress(() async {
"edit_icon".toSvgAsset(height: 21, width: 21, color: context.isDark ? AppColor.primary10 : null).onPress(() async {
provider.refreshTimer = false;
await Navigator.push(context, MaterialPageRoute(builder: (context) => CostDetailFormScreen(isEdit: true)));
provider.refreshTimer = true;

@ -16,6 +16,7 @@ class SingleItemDropDownMenu<T extends Base, X extends LoadingListNotifier> exte
final BuildContext context;
final Function(T?)? onSelect; // Now accepts nullable values
final T? initialValue;
final T? disableValue;
final bool enabled;
final bool showAsBottomSheet;
final bool showAsFullScreenDialog;
@ -35,6 +36,7 @@ class SingleItemDropDownMenu<T extends Base, X extends LoadingListNotifier> exte
required this.context,
this.onSelect,
this.initialValue,
this.disableValue,
this.enabled = true,
this.height,
this.showAsBottomSheet = false,
@ -160,11 +162,13 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
value: value,
child: Text(
value.name ?? "", // Null-aware operator for value.name
style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w500, color: context.isDark?AppColor.white10: AppColor.black10),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.white10 : AppColor.black10),
),
);
}).toList(),
).onPress(widget.showAsFullScreenDialog
).onPress(widget.enabled && widget.showAsFullScreenDialog
? () {
openDialog();
}
@ -220,6 +224,7 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
items: ((X == NullableLoadingProvider) ? widget.staticData : provider?.items as List<T>) ?? [],
// Provide default empty list if null
selectedItem: _selectedItem,
disableItem: widget.disableValue,
title: widget.title,
showCancel: widget.showCancel,
onSelect: (selectedT) {

@ -80,7 +80,7 @@ class _CreateDeviceTransferRequestState extends State<CreateDeviceTransferReques
_formKey.currentState!.save();
List<AssetTransferAttachment> attachement = [];
for (var item in attachments) {
String fileName = ServiceRequestUtils.isLocalUrl(item.name??'') ? ("${item.name??''.split("/").last}|${base64Encode(File(item.name??'').readAsBytesSync())}") :item.name??'';
String fileName = ServiceRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
attachement.add(AssetTransferAttachment(id: item.id, attachmentName: fileName));
}
_transferModel.attachments = attachement;
@ -135,19 +135,26 @@ class _CreateDeviceTransferRequestState extends State<CreateDeviceTransferReques
backgroundColor: AppColor.white936,
onPick: (asset) async {
_pickedAsset = asset;
if (_pickedAsset?.site != null && _transferModel.transferType?.value == 1) {
await _deviceTransferProvider.getSiteData(siteId: int.tryParse(_pickedAsset!.site!.id.toString()));
_assetDestination.site = _deviceTransferProvider.internalAssetDestination?.site;
_assetDestination.building = null;
_assetDestination.floor = null;
_assetDestination.department = null;
} else if (_pickedAsset?.site != null && _transferModel.transferType?.value == 2) {
_assetDestination.site = null;
_assetDestination.building = null;
_assetDestination.floor = null;
_assetDestination.department = null;
}
setState(() {});
}),
21.height,
requestTypeWidget(context),
12.height,
"Destination".bodyText(context).custom(color:context.isDark?Colors.white: AppColor.white936),
"Destination".bodyText(context).custom(color: context.isDark ? Colors.white : AppColor.white936),
12.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -156,6 +163,7 @@ class _CreateDeviceTransferRequestState extends State<CreateDeviceTransferReques
context: context,
title: context.translation.site,
initialValue: _assetDestination.site,
disableValue: isInternal ? null : _pickedAsset?.site,
showShadow: false,
loading: _deviceTransferProvider.isSiteLoading,
enabled: !isInternal,
@ -273,7 +281,7 @@ class _CreateDeviceTransferRequestState extends State<CreateDeviceTransferReques
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
context.translation.requestType.bodyText(context).custom(color:context.isDark?Colors.white: AppColor.white936),
context.translation.requestType.bodyText(context).custom(color: context.isDark ? Colors.white : AppColor.white936),
8.height,
Wrap(
runSpacing: 8,
@ -299,7 +307,17 @@ class _CreateDeviceTransferRequestState extends State<CreateDeviceTransferReques
onChanged: (state) {
_transferModel.transferType = element;
isInternal = !isInternal;
// _assetDestination = Asset();
if (isInternal) {
_assetDestination.site = _deviceTransferProvider.internalAssetDestination?.site;
_assetDestination.building = null;
_assetDestination.floor = null;
_assetDestination.department = null;
} else {
_assetDestination.site = null;
_assetDestination.building = null;
_assetDestination.floor = null;
_assetDestination.department = null;
}
setState(() {});
// });
@ -310,7 +328,7 @@ class _CreateDeviceTransferRequestState extends State<CreateDeviceTransferReques
],
)
],
).toShimmer(isShow: snapshot.loading,context: context),
).toShimmer(isShow: snapshot.loading, context: context),
],
);
});

@ -3,27 +3,29 @@ 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/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/models/base.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
typedef SelectionBuilderString = String Function(dynamic);
class SelectionFullScreenDialog<T> extends StatefulWidget {
class SelectionFullScreenDialog<T extends Base> extends StatefulWidget {
final List<T>? items;
final T? selectedItem; // Now nullable
final T? disableItem; // Now nullable
final String title;
final bool showCancel;
final SelectionBuilderString builderString;
final Function(T?) onSelect;
const SelectionFullScreenDialog({Key? key, this.items, this.selectedItem, this.title = "", required this.builderString, this.showCancel = false, required this.onSelect}) : super(key: key);
const SelectionFullScreenDialog({Key? key, this.items, this.selectedItem, this.disableItem, this.title = "", required this.builderString, this.showCancel = false, required this.onSelect})
: super(key: key);
@override
_SelectionBottomSheetState createState() => _SelectionBottomSheetState<T>();
}
class _SelectionBottomSheetState<T> extends State<SelectionFullScreenDialog<T>> {
class _SelectionBottomSheetState<T extends Base> extends State<SelectionFullScreenDialog<T>> {
T? _selectedValue; // Now nullable
String query = "";
@ -87,12 +89,12 @@ class _SelectionBottomSheetState<T> extends State<SelectionFullScreenDialog<T>>
backgroundColor: WidgetStateProperty.all<Color>(
AppColor.fieldBgColor(context), // Your custom background color
),
leading: Icon(Icons.search, color: AppColor.iconColor(context)),
leading: Icon(Icons.search, color: AppColor.iconColor(context)),
textStyle: WidgetStateProperty.all<TextStyle>(
TextStyle(color: AppColor.textColor(context), fontSize: 16.0),
TextStyle(color: AppColor.textColor(context), fontSize: 16.0),
),
hintStyle: WidgetStateProperty.all<TextStyle>(
TextStyle(color: AppColor.textColor(context), fontSize: 14.0),
TextStyle(color: AppColor.textColor(context), fontSize: 14.0),
),
hintText: 'Search by name',
onChanged: (queryString) {
@ -100,55 +102,79 @@ class _SelectionBottomSheetState<T> extends State<SelectionFullScreenDialog<T>>
setState(() {});
},
).paddingOnly(top: 16, start: 16, end: 16, bottom: 8),
// TextField(
// onChanged: (queryString) {
// query = queryString;
// setState(() {});
// },
// style: const TextStyle(fontSize: 14),
// focusNode: searchFocusNode,
// decoration: InputDecoration(
// hintText: 'Search by name',
// labelText: 'Search',
// hintStyle: const TextStyle(fontSize: 14),
// focusedBorder: OutlineInputBorder(
// borderSide: BorderSide(color: AppColor.blueStatus(context), width: 2.0),
// borderRadius: const BorderRadius.all(Radius.circular(12.0)),
// ),
// enabledBorder: OutlineInputBorder(
// borderSide: BorderSide(color: AppColor.blueStatus(context), width: 1.0),
// borderRadius: const BorderRadius.all(Radius.circular(12.0)),
// ),
// contentPadding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
// ),
// ),
8.height,
Expanded(
child: ListView.builder(
itemCount: filteredList?.length,
padding: EdgeInsets.zero,
itemBuilder: (cxt, index) =>Theme(
data: Theme.of(context).copyWith(
radioTheme: RadioThemeData(
fillColor: MaterialStateColor.resolveWith((states) {
if (states.contains(MaterialState.selected)) {
return AppColor.iconColor(context); // Active color
}
return Colors.grey; // Inactive color
}),
),
),
child: RadioListTile<T>(
// Specify type for RadioListTile
value: filteredList![index],
dense: true,
contentPadding: const EdgeInsets.only(left: 16, right: 16),
groupValue: _selectedValue,
activeColor: AppColor.iconColor(context),
hoverColor: Colors.transparent,
onChanged: (value) {
_selectedValue = value;
searchFocusNode.unfocus();
setState(() {});
},
title: Text(
widget.builderString(filteredList![index]).cleanupWhitespace.capitalizeFirstOfEach ?? "",
style: Theme.of(context).textTheme.bodyLarge,
),
),
),
),
itemCount: filteredList?.length,
padding: EdgeInsets.zero,
itemBuilder: (cxt, index) {
bool isDisabledItem = widget.disableItem != null && widget.disableItem?.identifier == filteredList![index].identifier;
return Theme(
data: Theme.of(context).copyWith(
radioTheme: RadioThemeData(
fillColor: MaterialStateColor.resolveWith((states) {
if (states.contains(MaterialState.selected)) {
return AppColor.iconColor(context); // Active color
}
return Colors.grey; // Inactive color
}),
),
),
child: RadioListTile<T>(
// Specify type for RadioListTile
value: filteredList![index],
dense: true,
contentPadding: const EdgeInsets.only(left: 16, right: 16),
groupValue: _selectedValue,
activeColor: AppColor.iconColor(context),
hoverColor: Colors.transparent,
onChanged: isDisabledItem
? null
: (value) {
_selectedValue = value;
searchFocusNode.unfocus();
setState(() {});
},
title: Text(
widget.builderString(filteredList![index]).cleanupWhitespace.capitalizeFirstOfEach ?? "",
style: Theme.of(context).textTheme.bodyLarge?.copyWith(color: isDisabledItem ? AppColor.neutral20:null),
),
),
);
}),
),
8.height,
if (_selectedValue != null)
FooterActionButton.footerContainer(
child: AppFilledButton(
label: context.translation.select,
maxWidth: true,
onPressed: () {
Navigator.pop(context);
widget.onSelect(_selectedValue);
},
), context: context,
),
AppFilledButton(
label: context.translation.select,
maxWidth: true,
onPressed: () {
Navigator.pop(context);
widget.onSelect(_selectedValue);
},
).paddingAll(16),
],
),
);

@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.3.8+27
version: 1.3.9+28
environment:
sdk: ">=3.5.0 <4.0.0"

Loading…
Cancel
Save