bug fixes

design_3.0_latest
muhammad.abbasi 1 year ago
parent d99a083792
commit 68a8dc250f

@ -0,0 +1,5 @@
<svg width="36" height="29" viewBox="0 0 36 29" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18.0002 10.8C14.6918 10.8 12.0002 13.4916 12.0002 16.8C12.0002 20.1084 14.6918 22.8 18.0002 22.8C21.3086 22.8 24.0002 20.1084 24.0002 16.8C24.0002 13.4916 21.3086 10.8 18.0002 10.8ZM21.6002 18C20.9366 18 20.4002 17.4624 20.4002 16.8C20.4002 15.4764 19.3238 14.4 18.0002 14.4C17.3366 14.4 16.8002 13.8624 16.8002 13.2C16.8002 12.5376 17.3366 12 18.0002 12C20.6474 12 22.8002 14.1528 22.8002 16.8C22.8002 17.4624 22.2638 18 21.6002 18Z" fill="#7D859A"/>
<path d="M24.636 3.6L23.964 0.9084C23.8296 0.3756 23.3508 0 22.8 0H13.2C12.6492 0 12.1704 0.3756 12.036 0.9084L11.364 3.6H24.636Z" fill="#7D859A"/>
<path d="M32.4 4.80005H24.936H11.064H3.6C1.6152 4.80005 0 6.41525 0 8.40005V25.2001C0 27.1849 1.6152 28.8 3.6 28.8H32.4C34.3848 28.8 36 27.1849 36 25.2001V8.40005C36 6.41525 34.3848 4.80005 32.4 4.80005ZM6 12C5.3364 12 4.8 11.4624 4.8 10.8C4.8 10.1376 5.3364 9.60005 6 9.60005C6.6636 9.60005 7.2 10.1376 7.2 10.8C7.2 11.4624 6.6636 12 6 12ZM18 25.2001C13.3692 25.2001 9.6 21.432 9.6 16.8C9.6 12.168 13.3692 8.40005 18 8.40005C22.6308 8.40005 26.4 12.168 26.4 16.8C26.4 21.432 22.6308 25.2001 18 25.2001Z" fill="#7D859A"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -0,0 +1,4 @@
<svg width="38" height="31" viewBox="0 0 38 31" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30.9216 7.65185H17.2118L14.4847 4.41067C14.393 4.3004 14.2555 4.23855 14.1122 4.24302H3.05118C1.36241 4.25532 0 5.62779 0 7.31655V27.2517C0.00204902 28.9462 1.37526 30.3194 3.0698 30.3215H30.9216C32.6161 30.3194 33.9893 28.9462 33.9914 27.2517V10.7217C33.9893 9.02711 32.6161 7.6539 30.9216 7.65185Z" fill="#7D859A"/>
<path d="M34.9489 3.68041H21.2354L18.5083 0.439236C18.4166 0.328962 18.2791 0.267118 18.1358 0.271589H7.07851C5.54622 0.274104 4.25049 1.40609 4.04224 2.92414H14.1271C14.656 2.92283 15.1581 3.15624 15.4981 3.5612L17.8266 6.32924H30.9217C33.3437 6.33334 35.3062 8.29583 35.3103 10.7179V26.3202C36.8459 26.1286 37.9989 24.8241 38.0001 23.2765V6.74649C37.9961 5.06061 36.6347 3.69271 34.9489 3.68041Z" fill="#7D859A"/>
</svg>

After

Width:  |  Height:  |  Size: 847 B

@ -0,0 +1,5 @@
<svg width="37" height="34" viewBox="0 0 37 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.63475 26.9799C7.16648 26.9799 4.97109 25.3996 4.17403 23.047L4.12007 22.8697C3.93198 22.2468 3.85335 21.7227 3.85335 21.1985V10.6871L0.113179 23.1719C-0.367833 25.008 0.728319 26.912 2.56757 27.4193L26.4069 33.8034C26.7045 33.8805 27.002 33.9175 27.295 33.9175C28.8305 33.9175 30.2335 32.8985 30.6266 31.3968L32.0157 26.9799H9.63475Z" fill="#7D859A"/>
<path d="M13.8744 10.7919C15.5749 10.7919 16.9578 9.40903 16.9578 7.70853C16.9578 6.00803 15.5749 4.62512 13.8744 4.62512C12.1739 4.62512 10.791 6.00803 10.791 7.70853C10.791 9.40903 12.1739 10.7919 13.8744 10.7919Z" fill="#7D859A"/>
<path d="M33.1458 0H10.0203C7.89581 0 6.16602 1.72979 6.16602 3.85426V20.813C6.16602 22.9375 7.89581 24.6673 10.0203 24.6673H33.1458C35.2703 24.6673 37.0001 22.9375 37.0001 20.813V3.85426C37.0001 1.72979 35.2703 0 33.1458 0ZM10.0203 3.08341H33.1458C33.5714 3.08341 33.9167 3.42875 33.9167 3.85426V14.7988L29.0464 9.1161C28.53 8.51021 27.7823 8.18645 26.979 8.16795C26.1804 8.17257 25.4312 8.52717 24.9193 9.14077L19.1934 16.0137L17.328 14.1528C16.2734 13.0983 14.5575 13.0983 13.5045 14.1528L9.24942 18.4064V3.85426C9.24942 3.42875 9.59477 3.08341 10.0203 3.08341Z" fill="#7D859A"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -0,0 +1,3 @@
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.50002 0C3.81317 0 0 3.81317 0 8.50002C0 13.1869 3.81317 17 8.50002 17C13.1869 17 17 13.1869 17 8.50002C17 3.81317 13.1868 0 8.50002 0ZM9.05292 13.5433C8.64909 13.6106 7.84555 13.7787 7.43751 13.8125C7.09211 13.8411 6.76618 13.6434 6.56749 13.3596C6.36828 13.0758 6.32055 12.7127 6.43881 12.3869L8.04554 7.96878H6.375C6.37357 7.04817 7.0641 6.37127 7.94728 6.11148C8.36875 5.98748 9.154 5.81778 9.56249 5.84379C9.80723 5.85935 10.2338 6.0129 10.4325 6.29671C10.6317 6.58049 10.6795 6.94366 10.5612 7.26946L8.95446 11.6875H10.6245C10.6248 12.6071 9.96003 13.3921 9.05292 13.5433ZM9.56249 5.31252C8.97567 5.31252 8.49998 4.83676 8.49998 4.25001C8.49998 3.66319 8.97567 3.1875 9.56249 3.1875C10.1493 3.1875 10.625 3.66319 10.625 4.25001C10.625 4.8368 10.1493 5.31252 9.56249 5.31252Z" fill="#7D859A"/>
</svg>

After

Width:  |  Height:  |  Size: 913 B

@ -0,0 +1,5 @@
<svg width="14" height="13" viewBox="0 0 14 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.95926 0.946552L0.159936 10.9905C0.0551801 11.1719 1.93882e-05 11.3777 5.11006e-09 11.5871C-1.93779e-05 11.7966 0.0551032 12.0024 0.159826 12.1838C0.264549 12.3652 0.415181 12.5158 0.596579 12.6205C0.777977 12.7253 0.983749 12.7804 1.19321 12.7804H12.7909C13.0004 12.7804 13.2062 12.7253 13.3876 12.6205C13.5689 12.5158 13.7196 12.3652 13.8243 12.1838C13.929 12.0024 13.9841 11.7966 13.9841 11.5871C13.9841 11.3777 13.929 11.1719 13.8242 10.9905L8.02549 0.946552C7.92079 0.765206 7.77019 0.614616 7.58884 0.509916C7.40749 0.405217 7.20178 0.350098 6.99238 0.350098C6.78297 0.350098 6.57726 0.405217 6.39591 0.509916C6.21456 0.614616 6.06397 0.765206 5.95926 0.946552Z" fill="#EE404C"/>
<path d="M7.06796 4.04431H6.91668C6.54424 4.04431 6.24231 4.34624 6.24231 4.71868V7.94207C6.24231 8.31452 6.54424 8.61644 6.91668 8.61644H7.06796C7.44041 8.61644 7.74233 8.31452 7.74233 7.94207V4.71868C7.74233 4.34624 7.44041 4.04431 7.06796 4.04431Z" fill="#FFF7ED"/>
<path d="M6.99232 11.1729C7.40654 11.1729 7.74233 10.8371 7.74233 10.4229C7.74233 10.0087 7.40654 9.67291 6.99232 9.67291C6.5781 9.67291 6.24231 10.0087 6.24231 10.4229C6.24231 10.8371 6.5781 11.1729 6.99232 11.1729Z" fill="#FFF7ED"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -39,6 +39,7 @@ class URLs {
static get getWorkOrderByIdUrl=> '$_baseUrl/ServiceRequest/GetWorkOrderById';
static get deleteActivitySparePartUrl=> '$_baseUrl/ServiceRequest/DeleteActivitySparePart';
static get createActivitySparePartUrl=> '$_baseUrl/ServiceRequest/CreateActivitySparePart';
static get createActivityAssetToBeRetiredUrl=> '$_baseUrl/ServiceRequest/CreateActivityAssetToBeRetired';
static get updateActivitySparePartUrl=> '$_baseUrl/ServiceRequest/UpdateActivitySparePart';
static get assignEngineerToWorkOrderUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToWorkOrder';
static get getDepartments => "$_baseUrl/Customer/GetDepartmentLookup"; // get

@ -70,7 +70,6 @@ class DashBoardProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) {
dashboardCount = DashboardCount.fromJson(json.decode(response.body));
}
notifyListeners();
isAllCountLoading = false;
notifyListeners();
return response.statusCode;
@ -98,6 +97,7 @@ class DashBoardProvider extends ChangeNotifier {
"pageNumber": pageNum,
"pageSize": pageItemNumber,
};
response = await ApiManager.instance.post(url, body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {

@ -10,6 +10,7 @@ import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/notifications_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/dashboard_latest/dashboard_provider.dart';
import 'package:test_sa/dashboard_latest/widgets/app_bar_widget.dart';
import 'package:test_sa/dashboard_latest/widgets/progress_fragment.dart';
import 'package:test_sa/dashboard_latest/widgets/requests_fragment.dart';
@ -38,6 +39,7 @@ class _DashboardViewState extends State<DashboardView> {
late SettingProvider settingProvider;
late UserProvider userProvider;
late AllRequestsProvider allRequestsProvider;
late DashBoardProvider dashBoardProvider;
late NotificationsProvider notificationsProvider;
late ScrollController _scrollController;
@ -54,13 +56,11 @@ class _DashboardViewState extends State<DashboardView> {
settingProvider = Provider.of<SettingProvider>(context, listen: false);
RequestDetailProvider requestDetailProvider = Provider.of<RequestDetailProvider>(context, listen: false);
allRequestsProvider = Provider.of<AllRequestsProvider>(context, listen: false);
dashBoardProvider = Provider.of<DashBoardProvider>(context, listen: false);
notificationsProvider = Provider.of<NotificationsProvider>(context, listen: false);
user = userProvider.user!;
log('user token i got is ${user.token}');
await dashBoardProvider.getDashBoardCount(usersType: user.type!);
await getAllRequests();
await requestDetailProvider.engineerRejectWorkOrder(id: '3', feedBack: 'Abcdef');
if (isFCM) {
FirebaseNotificationManger.initialized(context);
NotificationManger.initialisation((notificationDetails) {
@ -77,10 +77,12 @@ class _DashboardViewState extends State<DashboardView> {
allRequestsProvider.isFilterRequestLoading = true;
allRequestsProvider.currentListIndex = 0;
allRequestsProvider.filterRequest = null;
var tabs = RequestUtils.getTabs(userType: userProvider.user!.type!, context: context);
allRequestsProvider.status = tabs[0]['status'];
allRequestsProvider.getRequests();
allRequestsProvider.pageNum = 1;
dashBoardProvider.getRequestDetail(usersType: userProvider.user!.type!, status: tabs[0]['status']);
allRequestsProvider.getFilterRequests(showLoader: true, status: tabs[0]['status']).whenComplete(() {
allRequestsProvider.requestDetailList = allRequestsProvider.filterRequest;
});
@ -91,7 +93,7 @@ class _DashboardViewState extends State<DashboardView> {
void handleScroll() async {
_scrollController = ScrollController();
_scrollController.addListener(() async {
if (_scrollController?.position?.pixels == _scrollController?.position?.maxScrollExtent && !allRequestsProvider.isFilterRequestLoading) {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !allRequestsProvider.isFilterRequestLoading) {
allRequestsProvider.pageNum = allRequestsProvider.pageNum + 1;
await allRequestsProvider.getFilterRequests(showLoader: false, status: allRequestsProvider.status);
}

@ -154,6 +154,7 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/dashboard_latest/dashboard_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
@ -171,18 +172,19 @@ class ProgressFragment extends StatelessWidget {
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
bool isCurrentUserNotEngineer = (_userProvider.user!.type != UsersTypes.engineer);
return Consumer<AllRequestsProvider>(
return Consumer<DashBoardProvider>(
builder: (context, snapshot, _) {
int total = (snapshot.completedRequests?.total?.count ?? 0) + (snapshot.inProgressRequests?.total?.count ?? 0) + (isCurrentUserNotEngineer ? (snapshot.openRequests?.total?.count ?? 0) : 0);
int total = ((snapshot.dashboardCount?.data?.countComplete ?? 0) + (snapshot.dashboardCount?.data?.countInprogress ?? 0) + (isCurrentUserNotEngineer ? (snapshot.dashboardCount?.data?.countOpen ?? 0) : 0));
final List<ChartData> chartData = [
ChartData('Completed', snapshot.completedRequests?.total?.count?.toDouble() ?? 0.0, AppColor.green50),
ChartData('Completed', snapshot.dashboardCount?.data?.countComplete?.toDouble() ?? 0.0, AppColor.green50),
// snapshot.openRequests?.total?.count!=0? ChartData('Open', snapshot.openRequests?.total?.count?.toDouble() ?? 0.0, AppColor.blueStatus(context)),
ChartData('In Progress', snapshot.inProgressRequests?.total?.count?.toDouble() ?? 0.0, AppColor.orange70),
ChartData('In Progress', snapshot.dashboardCount?.data?.countInprogress?.toDouble() ?? 0.0, AppColor.orange70),
];
if (isCurrentUserNotEngineer) {
chartData.insert(1, ChartData('Open', snapshot.openRequests?.total?.count?.toDouble() ?? 0.0, AppColor.blueStatus(context)));
chartData.insert(1, ChartData('Open', snapshot.dashboardCount?.data?.countOpen?.toDouble() ?? 0.0, AppColor.blueStatus(context)));
}
return Column(
@ -199,7 +201,7 @@ class ProgressFragment extends StatelessWidget {
color: context.isDark ? const Color(0xFF111427) : const Color(0xffF7F9FB),
textStyle: context.isDark ? null : const TextStyle(color: Colors.black87, fontSize: 12),
),
legend: Legend(
legend: const Legend(
//isVisible: true,
),
series: <CircularSeries>[
@ -218,7 +220,7 @@ class ProgressFragment extends StatelessWidget {
//useSeriesColor: true,
),
)
]).toShimmer(isShow: snapshot.isInProgressLoading || snapshot.isCompleteLoading || snapshot.isOpenLoading, radius: 250).paddingAll(12).toShadowContainer(context),
]).toShimmer(isShow: snapshot.isAllCountLoading, radius: 250).paddingAll(12).toShadowContainer(context),
Column(
mainAxisSize: MainAxisSize.min,
children: [

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/dashboard_latest/dashboard_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
@ -17,7 +18,7 @@ class RequestsFragment extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<AllRequestsProvider>(
return Consumer<DashBoardProvider>(
builder: (context, snapshot, _) => GridView(
// padding: const EdgeInsets.only( bottom: 16),
physics: const NeverScrollableScrollPhysics(),
@ -25,18 +26,18 @@ class RequestsFragment extends StatelessWidget {
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4, childAspectRatio: 75 / 84, crossAxisSpacing: 2, mainAxisSpacing: 13),
children: [
listItem(
snapshot.highPriorityRequests?.total?.count ?? 0,
snapshot.dashboardCount?.data?.countHighPriority ?? 0,
"high_priority",
context.translation.highPriority,
context,
snapshot.isHighPriorityLoading,
snapshot.isAllCountLoading,
0,
context.isDark ? AppColor.redStatus(context) : AppColor.red50,
),
listItem(snapshot.overdueRequests?.total?.count ?? 0, "overdue", context.translation.overdue, context, snapshot.isOverdueLoading, 1, AppColor.yellowIcon(context)),
listItem(snapshot.openRequests?.total?.count ?? 0, "new_request", ApiManager.instance.user!.type == UsersTypes.engineer ? context.translation.inProgress : context.translation.newR, context,
snapshot.isOpenLoading, 2, AppColor.primary40),
listItem(snapshot.completedRequests?.total?.count ?? 0, "complete_request", context.translation.completed, context, snapshot.isCompleteLoading, 3, AppColor.greenStatus(context)),
listItem( snapshot.dashboardCount?.data?.countOverdue ?? 0, "overdue", context.translation.overdue, context, snapshot.isAllCountLoading, 1, AppColor.yellowIcon(context)),
listItem( snapshot.dashboardCount?.data?.countOpen ?? 0, "new_request", ApiManager.instance.user!.type == UsersTypes.engineer ? context.translation.inProgress : context.translation.newR, context,
snapshot.isAllCountLoading, 2, AppColor.primary40),
listItem( snapshot.dashboardCount?.data?.countComplete ?? 0, "complete_request", context.translation.completed, context, snapshot.isAllCountLoading, 3, AppColor.greenStatus(context)),
],
),
);

@ -77,12 +77,12 @@ extension WidgetExtensions on Widget {
).toShadowContainer(context)
: this;
Widget toShadowContainer(BuildContext context, {bool showShadow = true, double padding = 16}) => showShadow
Widget toShadowContainer(BuildContext context, {bool showShadow = true,Color? backgroundColor, double padding = 16}) => showShadow
? Container(
padding: EdgeInsets.all(padding),
width: double.infinity,
decoration: ShapeDecoration(
color: AppColor.background(context),
color: backgroundColor?? AppColor.background(context),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
shadows: [boxShadowR14],
),

@ -84,6 +84,10 @@
"workshop": "ورشة",
"activityStatus": "حالة النشاط",
"scanOrPickAsset": "امسح أو اختر الأصل",
"reScanOrPickAsset": "أعد المسح أو اختر الأصل",
"camera": "الكاميرا",
"gallery": "المعرض",
"files": "الملفات",
"takeAction": "اتخذ إجراء",
"pleaseConfirmTheIssueHasBeenResolved": "يرجى تأكيد أن المشكلة قد تم حلها",
"nurseAcknowledge": "أقر بإكمال أمر العمل هذا",

@ -71,6 +71,10 @@
"closed": "Closed",
"close": "Close",
"scanOrPickAsset": "Scan or Pick Asset",
"reScanOrPickAsset": "Re-Scan or Pick Asset",
"camera": "Camera",
"gallery": "Gallery",
"files": "Files",
"attachFiles": "Attach Files",
"activityStatus": "Activity Status",
"takeAction": "Take Action",

@ -0,0 +1,64 @@
class ActivityAssetRetiredModel {
int? id;
int? workOrderId;
int? retirmentReasonId;
String? retirementComment;
List<ActivityAssetToBeRetiredAttachments>?
activityAssetToBeRetiredAttachments;
ActivityAssetRetiredModel(
{this.id,
this.workOrderId,
this.retirmentReasonId,
this.retirementComment,
this.activityAssetToBeRetiredAttachments});
ActivityAssetRetiredModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
workOrderId = json['workOrderId'];
retirmentReasonId = json['retirmentReasonId'];
retirementComment = json['retirementComment'];
if (json['activityAssetToBeRetiredAttachments'] != null) {
activityAssetToBeRetiredAttachments =
<ActivityAssetToBeRetiredAttachments>[];
json['activityAssetToBeRetiredAttachments'].forEach((v) {
activityAssetToBeRetiredAttachments!
.add( ActivityAssetToBeRetiredAttachments.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['workOrderId'] = workOrderId;
data['retirmentReasonId'] = retirmentReasonId;
data['retirementComment'] = retirementComment;
if (activityAssetToBeRetiredAttachments != null) {
data['activityAssetToBeRetiredAttachments'] = this
.activityAssetToBeRetiredAttachments!
.map((v) => v.toJson())
.toList();
}
return data;
}
}
class ActivityAssetToBeRetiredAttachments {
int? id;
String? name;
ActivityAssetToBeRetiredAttachments({this.id, this.name});
ActivityAssetToBeRetiredAttachments.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['name'] = name;
return data;
}
}

@ -40,6 +40,7 @@ class AppColor {
static const Color white40 = Color(0xffE4EBEE);
static const Color white50 = Color(0xffECECEC);
static const Color white60 = Color(0xffEFEFEF);
static const Color white70 = Color(0xffF1F1F1);
//black
static const Color black10 = Color(0xff3B3D4A);

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart';
@ -17,12 +18,13 @@ class AppBottomNavigationBar extends StatelessWidget {
Widget build(BuildContext context) {
bool isEngineer = (Provider.of<UserProvider>(context, listen: false).user!.type) == UsersTypes.engineer;
return Container(
// height: 86.toScreenHeight,
height: 84.toScreenHeight,
decoration: BoxDecoration(
color: AppColor.background(context),
boxShadow: [boxShadowR14],
),
child: BottomNavigationBar(
backgroundColor: Colors.white,
items: <BottomNavigationBarItem>[
navBarItem(context, index: 0, iconName: "overview", label: context.translation.overview),
navBarItem(context, index: 1, iconName: "request_icon", label: context.translation.request),

@ -8,11 +8,14 @@ class AppFilledButton extends StatelessWidget {
final VoidCallback? onPressed;
final String label;
final bool maxWidth, loading;
final bool showIcon;
final Widget? icon;
final Color? buttonColor;
final Color? textColor;
final bool showBorder;
const AppFilledButton({ this.onPressed, required this.label, this.maxWidth = false, this.loading = false, this.showBorder = false, this.buttonColor, this.textColor, Key? key})
const AppFilledButton(
{this.onPressed, required this.label, this.maxWidth = false, this.showIcon = false, this.icon, this.loading = false, this.showBorder = false, this.buttonColor, this.textColor, Key? key})
: super(key: key);
@override
@ -28,14 +31,22 @@ class AppFilledButton extends StatelessWidget {
),
child: loading
? SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
color: textColor ?? AppColor.background(context),
strokeWidth: 2,
),
)
: label.heading6(context).custom(color: textColor ?? AppColor.background(context)),
width: 24,
height: 24,
child: CircularProgressIndicator(
color: textColor ?? AppColor.background(context),
strokeWidth: 2,
),
)
: showIcon && icon != null
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
icon!,
8.width,
label.heading6(context).custom(color: textColor ?? AppColor.background(context)),
])
: label.heading6(context).custom(color: textColor ?? AppColor.background(context)),
).onPress(onPressed);
}
}

@ -93,7 +93,7 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
isLoading: widget.loading ?? ((X == NullableLoadingProvider) ? false : provider?.loading ?? false),
// Provide default value if null
isFailedLoading: (X == NullableLoadingProvider) ? false : provider?.items == null,
stateCode: (X == NullableLoadingProvider) ? 200 : provider?.stateCode!,
stateCode: (X == NullableLoadingProvider) ? 200 : provider?.stateCode??0,
onRefresh: () async {
if (X != NullableLoadingProvider) {
provider?.reset();

@ -4,6 +4,7 @@ import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/helper_data_models/asset_retired/asset_retired_model.dart';
import 'package:test_sa/models/helper_data_models/spare_part/activity_spare_part_model.dart';
import 'package:test_sa/models/helper_data_models/workorder/fix_remotely_model.dart';
import 'package:test_sa/models/helper_data_models/workorder/mark_as_fixed_model.dart';
@ -61,6 +62,14 @@ class RequestDetailProvider extends ChangeNotifier {
NeedVisit ?_needVisitModel=NeedVisit();
MarkAsFixed ?_markAsFixed=MarkAsFixed();
ActivitySparePartModel ?_activitySparePartModel= ActivitySparePartModel();
ActivityAssetRetiredModel ?_activityAssetRetiredModel = ActivityAssetRetiredModel();
ActivityAssetRetiredModel? get activityAssetRetiredModel => _activityAssetRetiredModel;
set activityAssetRetiredModel(ActivityAssetRetiredModel ?value) {
_activityAssetRetiredModel = value;
notifyListeners();
}
ActivitySparePartModel ?get activitySparePartModel => _activitySparePartModel;
@ -212,7 +221,6 @@ class RequestDetailProvider extends ChangeNotifier {
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer fixremotely workorder ${commonResponseModel.toJson()}');
notifyListeners();
isLoading = false;
return commonResponseModel;
@ -288,7 +296,6 @@ class RequestDetailProvider extends ChangeNotifier {
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer assignEngineer workorder ${commonResponseModel.toJson()}');
notifyListeners();
isLoading = false;
return commonResponseModel;
@ -312,7 +319,6 @@ class RequestDetailProvider extends ChangeNotifier {
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of nurse confirmreopen workorder ${commonResponseModel.toJson()}');
notifyListeners();
isLoading = false;
return commonResponseModel;
@ -352,8 +358,6 @@ class RequestDetailProvider extends ChangeNotifier {
return CommonResponseModel();
}
}
Future<int> updateActivitySparePart({required ActivitySparePartModel activitySparePartModel}) async {
isLoading = true;
try {
@ -421,4 +425,25 @@ class RequestDetailProvider extends ChangeNotifier {
return -1;
}
}
Future<int> createActivityAssetToBeRetired({required ActivityAssetRetiredModel activityAssetRetiredModel}) async {
isLoading = true;
try {
final response = await ApiManager.instance.put(
URLs.createActivityAssetToBeRetiredUrl,
body: activityAssetRetiredModel.toJson(),
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// request.engineerName = employee.name;
notifyListeners();
}
isLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isLoading = false;
notifyListeners();
return -1;
}
}
}

@ -78,15 +78,15 @@ class ServiceRequestBottomSheet {
selectedTime.minute,
);
//serviceRequestProvider.currentSelectedRequest?.date
if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.currentSelectedRequest!.date!))) {
"Visit Date time must be greater then request date".showToast;
return;
}
if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.currentSelectedRequest!.date!))) {
"Visit Date time must be greater then request date".showToast;
return;
}
setState(() {
serviceRequestProvider.currentSelectedRequest?.startDate = selectedDateTime.toIso8601String();
});
print('start date i got is ${serviceRequestProvider.currentSelectedRequest?.startDate}');
setState(() {
serviceRequestProvider.currentSelectedRequest?.startDate = selectedDateTime.toIso8601String();
});
print('start date i got is ${serviceRequestProvider.currentSelectedRequest?.startDate}');
}
});
}
@ -112,7 +112,6 @@ class ServiceRequestBottomSheet {
return true;
},
),
),
8.height,
AppTextFormField(
@ -190,7 +189,7 @@ class ServiceRequestBottomSheet {
15.height,
ADatePicker(
label: context.translation.visitDate,
hideShadow: true,
hideShadow: true,
backgroundColor: AppColor.neutral100,
height: 70.toScreenHeight,
date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest?.visitDate ?? ""),
@ -210,11 +209,11 @@ class ServiceRequestBottomSheet {
selectedTime.hour,
selectedTime.minute,
);
if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.currentSelectedRequest!.date!))) {
"Visit Date time must be greater then request date".showToast;
return;
}
serviceRequestProvider.currentSelectedRequest?.visitDate = selectedDateTime?.toIso8601String();
if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.currentSelectedRequest!.date!))) {
"Visit Date time must be greater then request date".showToast;
return;
}
serviceRequestProvider.currentSelectedRequest?.visitDate = selectedDateTime?.toIso8601String();
}
});
}
@ -307,7 +306,6 @@ class ServiceRequestBottomSheet {
AppFilledButton(
label: context.translation.save,
buttonColor: AppColor.primary10,
loading: serviceRequestProvider.isLoading ?? false,
onPressed: () async {
_formKey.currentState?.save();
@ -338,7 +336,7 @@ class ServiceRequestBottomSheet {
child: SingleChildScrollView(
child: Column(
children: [
const SizedBox().indicatorWidget(),
const SizedBox().indicatorWidget(),
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.rejectionReason.heading4(context).paddingOnly(top: 21),
@ -349,7 +347,8 @@ class ServiceRequestBottomSheet {
backgroundColor: AppColor.neutral100,
height: 70.toScreenHeight,
title: context.translation.rejectionReason,
initialValue: serviceRequestProvider.currentSelectedRequest?.firstAction, //_serviceRequest.firstAction,
initialValue: serviceRequestProvider.currentSelectedRequest?.firstAction,
//_serviceRequest.firstAction,
onSelect: (value) {
serviceRequestProvider.currentSelectedRequest?.firstAction = value;
if (serviceRequestProvider.currentSelectedRequest?.firstAction?.value != 2) {
@ -410,7 +409,7 @@ class ServiceRequestBottomSheet {
),
// color: Colors.white,
child: ListTile(
minVerticalPadding:12.toScreenWidth,
minVerticalPadding: 12.toScreenWidth,
horizontalTitleGap: 2.toScreenHeight,
onTap: onTap,
contentPadding: const EdgeInsets.all(8),
@ -434,7 +433,6 @@ class ServiceRequestBottomSheet {
break;
case 1:
//push to specific screen...
// Navigator.push(
// context,
@ -476,7 +474,7 @@ class ServiceRequestBottomSheet {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox().indicatorWidget(),
const SizedBox().indicatorWidget(),
8.height,
Align(
alignment: AlignmentDirectional.centerStart,
@ -505,7 +503,7 @@ class ServiceRequestBottomSheet {
}));
}
static Future actionBottomSheet({required BuildContext context, required String title, String? button1Text, String ?button2Text, VoidCallback ?button1Tap, VoidCallback ?button2Tap}) {
static Future actionBottomSheet({required BuildContext context, required String title, String? button1Text, String? button2Text, VoidCallback? button1Tap, VoidCallback? button2Tap}) {
return showModalBottomSheet(
context: context,
useSafeArea: true,
@ -523,7 +521,7 @@ class ServiceRequestBottomSheet {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox().indicatorWidget(),
const SizedBox().indicatorWidget(),
8.height,
Align(
alignment: AlignmentDirectional.centerStart,
@ -559,6 +557,7 @@ class ServiceRequestBottomSheet {
);
}));
}
static Future feedBackBottomSheet({required BuildContext context}) {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
return showModalBottomSheet(
@ -567,57 +566,59 @@ class ServiceRequestBottomSheet {
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestProvider, child) {
return Container(
clipBehavior: Clip.antiAlias,
margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
decoration: BoxDecoration(
color: AppColor.background(context),
borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)),
),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 16.toScreenHeight),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: StatefulBuilder(builder: (context, setState) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox().indicatorWidget(),
8.height,
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.feedBack.bottomSheetHeadingTextStyle(context),
),
21.height,
AppTextFormField(
labelText: context.translation.comments,
textInputType: TextInputType.multiline,
showWithoutDecoration: true,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100,
alignLabelWithHint: true,
onChange: (text) {
serviceRequestProvider.currentSelectedRequest?.comments = text;
},
onSaved: (text) {
serviceRequestProvider.currentSelectedRequest?.comments = text;
},
),
16.height,
AppFilledButton(
label: context.translation.fixed,
buttonColor: AppColor.green70,
loading: false,
onPressed: () {},
),
],
);
}),
),
),
);
}));
return Container(
clipBehavior: Clip.antiAlias,
margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
decoration: BoxDecoration(
color: AppColor.background(context),
borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)),
),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 16.toScreenHeight),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: StatefulBuilder(builder: (context, setState) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox().indicatorWidget(),
8.height,
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.feedBack.bottomSheetHeadingTextStyle(context),
),
21.height,
AppTextFormField(
labelText: context.translation.comments,
textInputType: TextInputType.multiline,
showWithoutDecoration: true,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100,
alignLabelWithHint: true,
onChange: (text) {
serviceRequestProvider.currentSelectedRequest?.comments = text;
},
onSaved: (text) {
serviceRequestProvider.currentSelectedRequest?.comments = text;
},
),
16.height,
AppFilledButton(
label: context.translation.fixed,
buttonColor: AppColor.green70,
loading: false,
onPressed: () {},
),
],
);
}),
),
),
);
}));
}
static Future nurseTakeActionBottomSheet({required BuildContext context}) {
bool acknowledge = false;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
return showModalBottomSheet(
context: context,
@ -625,87 +626,91 @@ class ServiceRequestBottomSheet {
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestProvider, child) {
return Form(
key: _formKey,
child: SingleChildScrollView(
child: StatefulBuilder(builder: (context, setState) {
bool acknowledge = false;
Uint8List ?newSignature;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox().indicatorWidget(),
8.height,
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.pleaseConfirmTheIssueHasBeenResolved.bottomSheetHeadingTextStyle(context),
),
10.height,
Row(
children: [
Checkbox(
value: acknowledge,
activeColor: AppColor.blueStatus(context),
onChanged: (value) {
setState(() {
acknowledge = !value!;
});
print('acknowledge value is $acknowledge');
}),
context.translation.nurseAcknowledge.bodyText(context).custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral120),
],
),
17.height,
ESignature(
title: '',
oldSignature: '',
newSignature: newSignature,
backgroundColor: AppColor.neutral100,
showShadow: false,
onSaved: (signature) {
// if (signature == null || signature.isEmpty) {
// setState(() {});
// return;
// }
if (signature == null || signature.isEmpty) return;
newSignature = signature;
// _subWorkOrders.nurseSignature = signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}" : null;
},
),
16.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
return Form(
key: _formKey,
child: SingleChildScrollView(
child: StatefulBuilder(builder: (context, setState) {
Uint8List? newSignature;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AppFilledButton(
label: context.translation.reject,
maxWidth: true,
buttonColor: Colors.white54,
textColor: AppColor.red30,
showBorder: true,
onPressed: () async {
ServiceRequestBottomSheet.rejectRequestBottomSheet(context: context);
},
).expanded,
const SizedBox(
width: 20,
const SizedBox().indicatorWidget(),
8.height,
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.pleaseConfirmTheIssueHasBeenResolved.bottomSheetHeadingTextStyle(context),
),
AppFilledButton(
label: context.translation.confirm,
maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {
10.height,
Row(
children: [
InkWell(
child: acknowledge
? const Icon(
Icons.check_box,
color: AppColor.primary10,
)
:const Icon(
Icons.check_box_outline_blank,
color: AppColor.neutral120,
),
onTap: () {
setState(() {
acknowledge = !acknowledge;
});
},
),
6.width,
Flexible(child: context.translation.nurseAcknowledge.bodyText(context).custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral120)),
],
),
17.height,
ESignature(
title: '',
oldSignature: '',
newSignature: newSignature,
backgroundColor: AppColor.neutral100,
showShadow: false,
onSaved: (signature) {
// if (signature == null || signature.isEmpty) {
// setState(() {});
// return;
// }
if (signature == null || signature.isEmpty) return;
newSignature = signature;
// _subWorkOrders.nurseSignature = signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}" : null;
},
).expanded,
],
)
),
36.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
AppFilledButton(
label: context.translation.reject,
maxWidth: true,
buttonColor: Colors.white54,
textColor: AppColor.red30,
showBorder: true,
onPressed: () async {
],
);
}),
),
).bottomSheetContainer(context);
}));
},
).expanded,
const SizedBox(
width: 20,
),
AppFilledButton(
label: context.translation.confirm,
maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {},
).expanded,
],
)
],
);
}),
),
).bottomSheetContainer(context);
}));
}
}

@ -25,6 +25,7 @@ import 'package:test_sa/views/widgets/loaders/app_loading.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'package:test_sa/views/widgets/sound/sound_player.dart';
class RequestDetailView extends StatefulWidget {
static const String id = "/call-details";
ServiceRequest serviceRequest;
@ -53,12 +54,7 @@ class _RequestDetailViewState extends State<RequestDetailView> {
});
}
final GlobalKey _detailsCardKey = GlobalKey();
void createBreakPoint() {
// final RenderBox detailContainerBox = _detailsCardKey.currentContext?.findRenderObject() as RenderBox;
// final detailContainerHeight = detailContainerBox?.size?.height;
}
@override
Widget build(BuildContext context) {
@ -80,11 +76,8 @@ class _RequestDetailViewState extends State<RequestDetailView> {
}
Widget requestDetailCard({required ServiceRequestsProvider serviceRequestsProvider, required UserProvider userProvider}) {
if (!serviceRequestsProvider.isDetialLoading) {
createBreakPoint();
}
return SafeArea(
key: _detailsCardKey,
child: serviceRequestsProvider.isDetialLoading
? const ALoading().center
: serviceRequestsProvider.currentSelectedRequest == null
@ -332,8 +325,8 @@ class _RequestDetailViewState extends State<RequestDetailView> {
textColor: AppColor.red30,
showBorder: true,
onPressed: () async {
// ServiceRequestBottomSheet.nurseTakeActionBottomSheet(context: context);
Navigator.push(context, MaterialPageRoute(builder: (context) => AssetRetired()));
// Navigator.push(context, MaterialPageRoute(builder: (context) => CreateNewRequest()));
}),
);
}

@ -1,4 +1,4 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/cupertino.dart';
@ -6,70 +6,95 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/devices_provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/validator/validator.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/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/device/asset_search.dart';
import 'package:test_sa/models/service_request/pending_service_request_model.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart';
import 'package:test_sa/providers/service_request_providers/priority_provider.dart';
import 'package:test_sa/providers/service_request_providers/requested_through_provider.dart';
import 'package:test_sa/providers/service_request_providers/type_of_request_provider.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/views/pages/user/requests/pending_requests_screen.dart';
import 'package:test_sa/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart';
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/qr/scan_qr.dart';
import 'package:test_sa/views/widgets/sound/TextSpeechRecordWidget.dart';
import '../../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../../new_views/common_widgets/default_app_bar.dart';
class CreateNewRequest extends StatefulWidget {
static const String id = "/create-new-request";
const CreateNewRequest({Key ?key}) : super(key: key);
const CreateNewRequest({Key? key}) : super(key: key);
@override
_CreateNewRequestState createState() => _CreateNewRequestState();
}
class _CreateNewRequestState extends State<CreateNewRequest> with TickerProviderStateMixin {
AssetProvider? _devicesProvider;
bool _isLoading = false;
int _selectedEStatus = 1;
bool _isHighPriority = false;
String text='';
late TextEditingController _commentController;
late UserProvider _userProvider;
late SettingProvider _settingProvider;
late ServiceRequestsProvider _serviceRequestsProvider;
late ServiceRequest _serviceRequest;
final List<File> _deviceImages = [];
final bool _isLoading = false;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool isFirstActionSubmitted = false;
String text = '';
DateTime? _dateTime;
bool _showDatePicker = false;
PendingAssetServiceRequest? pendingAssetServiceRequest;
@override
void initState() {
super.initState();
if (context.mounted) {
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
Provider.of<ServiceReportLastCallsProvider>(context, listen: false).reset();
_devicesProvider = Provider.of<AssetProvider>(context, listen: false);
Provider.of<ReasonProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).serviceRequestId = serviceRequestsProvider.currentSelectedRequest?.id;
_commentController = TextEditingController();
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
_userProvider = Provider.of<UserProvider>(context, listen: false);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
if (_serviceRequestsProvider.currentSelectedRequest != null) {
_serviceRequest = _serviceRequestsProvider.currentSelectedRequest!;
_deviceImages.addAll(_serviceRequest.devicePhotos!.map((e) => File(e)).toList());
_showDatePicker = _serviceRequest.firstAction != null && _serviceRequest.firstAction?.name == "Need a visit";
if (_showDatePicker && _serviceRequest.visitDate != null) {
_dateTime = DateTime.tryParse(_serviceRequest.visitDate!);
}
} else {
_serviceRequest = ServiceRequest();
}
isFirstActionSubmitted = _serviceRequest.firstAction != null;
// _isLoading = true;
}
_getDevice(String? result, {bool isQr = false}) async {
if (result == null) return;
_devicesProvider!.reset();
await _devicesProvider!.getAssets(
search: AssetSearch(assetNo: result, assetSerialNumber: ""),
isQr: isQr,
);
@override
void dispose() {
// TODO: implement dispose
_commentController.dispose();
super.dispose();
}
bool _isLocalUrl(String url) {
if (url.isEmpty != false) return false;
return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\');
}
@override
Widget build(BuildContext context) {
final List<File> _files = [];
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(title: context.translation.createNewRequest),
@ -85,84 +110,56 @@ class _CreateNewRequestState extends State<CreateNewRequest> with TickerProvider
child: Column(
children: [
SingleChildScrollView(
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppFilledButton(
label: context.translation.scanOrPickAsset,
// showIcon: true,
// icon: "scan_asset".toSvgAsset(height: 20, fit: BoxFit.contain, color: Theme.of(context).scaffoldBackgroundColor),
buttonColor: AppColor.neutral50,
onPressed: () async {
String result = await Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const ScanQr()),
) as String;
_getDevice(result, isQr: true);
} ,
),
21.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
context.translation.highPriority.bodyText(context).custom(color: AppColor.black20),
CupertinoSwitch(
value: _isHighPriority,
onChanged: (value) {
setState(() {
// listingVm.listing[listingVm.listingParameter]['bayut'] = value;
_isHighPriority = value;
});
},
thumbColor: AppColor.red70,
activeColor: AppColor.red30.withOpacity(0.4),
),
],
),
20.height,
context.translation.equipmentStatus.bodyText(context).custom(color: AppColor.black20),
12.height,
assetStatusWidget(context),
8.height,
23.height,
MultiFilesPicker(label: context.translation.attachImage,
files: _files,
buttonColor: AppColor.primary10,
onlyImages: true,
buttonIcon: 'image-plus'?.toSvgAsset(color: AppColor.primary10),
),
AppTextFormField(
labelText: "Type any comment",
backgroundColor: AppColor.neutral30,
alignLabelWithHint: true,
showShadow: false,
validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredField,
textInputType: TextInputType.multiline,
suffixIcon: "comment_send".toSvgAsset().paddingOnly(end: 16).onPress(() {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
// final comment = Comment(id: 0, callRequestId: num.tryParse(widget.requestId ?? ""), comment: text);
// commentsProvider.addComment(context, comment: comment);
}
}),
onSaved: (value) {
text = value;
},
),
],
).paddingOnly(start:13,end: 13,top: 15,bottom: 16),
).paddingAll(16),
child: Column(
children: [
Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
scanAssetButton(),
if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) ...[
8.height,
Row(
children: [
const Icon(Icons.warning, color: Color(0xffEE404C), size: 14),
8.width,
Text(
"This asset already have ${pendingAssetServiceRequest!.details!.length} request pending",
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xff7D859A), decoration: TextDecoration.underline),
).expanded,
],
).onPress(() {
showPendingRequests();
}),
],
21.height,
highPriorityWidget(),
20.height,
equipmentStatusWidget(context),
24.height,
MultiFilesPicker(
label: context.translation.attachImage,
files: _deviceImages,
buttonColor: AppColor.primary10,
onlyImages: true,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
),
],
).paddingOnly(start: 13, end: 13, top: 15, bottom: 16),
).paddingAll(16),
commentWidget(serviceRequest: ServiceRequest()),
],
),
).expanded,
FooterActionButton.footerContainer(
child: AppFilledButton(
label: context.translation.submitRequest,
// label: context.translation.submitRequest,
buttonColor: AppColor.primary10,
onPressed: (){},
label: (pendingAssetServiceRequest != null && (pendingAssetServiceRequest!.details?.isNotEmpty ?? false))
? context.translation.duplicateRequest
: context.translation.createNewRequest,
onPressed: checkPendingRequest ? null : _submit,
// buttonColor: AppColor.primary10,
),
),
],
@ -173,43 +170,189 @@ class _CreateNewRequestState extends State<CreateNewRequest> with TickerProvider
}),
);
}
Widget assetStatusWidget(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
radioButtonWidget(label: context.translation.up_and_running, value: 1),
radioButtonWidget(label: context.translation.partially_down, value: 2),
radioButtonWidget(label: context.translation.fully_down, value: 3),
],
Widget equipmentStatusWidget(BuildContext context) {
return Consumer<EquipmentStatusProvider>(builder: (cxt, snapshot, _) {
try {
_serviceRequest.defectType ??= snapshot.items.first;
} catch (ex) {
print("snapshot.items:${snapshot.items.length}");
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
context.translation.equipmentStatus.bodyText(context).custom(color: AppColor.black20),
8.height,
Wrap(
runSpacing: 8,
spacing: 8,
children: [
for (var element in snapshot.items)
Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 24,
height: 24,
child: Radio(
value: element,
activeColor: Colors.red,
fillColor: WidgetStateColor.resolveWith((states) {
if (states.contains(WidgetState.selected)) return const Color(0xff3DA5E5);
return const Color(0xffE0E0E0);
}),
groupValue: _serviceRequest.defectType,
onChanged: (state) {
setState(() {
_serviceRequest.defectType = element;
});
}),
),
8.width,
Text(element.name!, style: Theme.of(context).textTheme.bodySmall),
],
)
],
).toShimmer(isShow: snapshot.loading),
],
);
});
}
Widget scanAssetButton() {
return AssetPicker(
device: _serviceRequest.device,
showLoading: checkPendingRequest,
borderColor: AppColor.black20,
onPick: (asset) async {
pendingAssetServiceRequest = null;
_serviceRequest.device = asset;
await checkAssetForPendingServiceRequest(asset.id!.toInt());
if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) {
showPendingRequestBottomSheet();
}
},
);
}
Widget radioButtonWidget({required String label, required dynamic value}) {
Widget highPriorityWidget() {
return Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 20.toScreenWidth,
height: 40.toScreenHeight,
//TODO use the type required according data..
child: Radio<int>(
activeColor: AppColor.primary10,
value: value,
groupValue: _selectedEStatus,
onChanged: (int? value) {
setState(() {
_selectedEStatus = value!;
});
},
),
),
8.width,
Text(
label,
style: AppTextStyles.tinyFont,
),
13.width,
context.translation.highPriority.bodyText(context).custom(color: AppColor.black20),
Consumer<PriorityProvider>(builder: (cxt, snapshot, _) {
_serviceRequest.priority ??= snapshot.items.firstWhere((element) => element.value == 0, orElse: null);
return CupertinoSwitch(
thumbColor: AppColor.red70,
activeColor: AppColor.red30.withOpacity(0.4),
value: _serviceRequest.priority?.value != 0,
onChanged: (state) {
if (state) {
_serviceRequest.priority = snapshot.items.firstWhere((element) => element.value == 1, orElse: null);
} else {
_serviceRequest.priority = snapshot.items.firstWhere((element) => element.value == 0, orElse: null);
}
setState(() {});
}).toShimmer(isShow: snapshot.loading);
}),
// CupertinoSwitch(
// value: _isHighPriority,
//
// onChanged: (value) {
// setState(() {
// // listingVm.listing[listingVm.listingParameter]['bayut'] = value;
// _isHighPriority = value;
// });
// },
// thumbColor: AppColor.red70,
// activeColor: AppColor.red30.withOpacity(0.4),
//
// ),
],
);
}
Widget commentWidget({required ServiceRequest? serviceRequest}) {
return TextSpeechRecordWidget(
initialMessage: serviceRequest?.callComments ?? '',
onMessageChange: (message) {
serviceRequest?.callComments = message;
},
onRecord: (audio) {
serviceRequest?.audio = audio;
},
enabled: serviceRequest == null ? true : false,
).paddingOnly(start: 16, end: 16,bottom: 16);
}
bool checkPendingRequest = false;
void showPendingRequests() {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => PendingServiceRequestScreen(pendingAssetServiceRequest!)));
}
void showPendingRequestBottomSheet() async {
bool view = (await showModalBottomSheet(
context: context,
isDismissible: false,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
clipBehavior: Clip.antiAliasWithSaveLayer,
builder: (BuildContext context) => PendingRequestBottomSheet(pendingAssetServiceRequest!, _serviceRequest.device!),
)) as bool;
if (view) {
showPendingRequests();
}
}
Future<void> checkAssetForPendingServiceRequest(int assetId) async {
checkPendingRequest = true;
setState(() {});
pendingAssetServiceRequest = await _serviceRequestsProvider.checkAssetPendingRequest(assetId);
await Future.delayed(const Duration(milliseconds: 250));
checkPendingRequest = false;
setState(() {});
}
Future<void> _submit() async {
_serviceRequest.requestedThrough = Provider.of<RequestedThroughProvider>(context, listen: false).items.firstWhere((element) => element.value == 3, orElse: null);
_serviceRequest.type = Provider.of<TypeOfRequestProvider>(context, listen: false).items.firstWhere((element) => element.value == 1, orElse: null);
// print("_serviceRequest?.requestedThrough:${_serviceRequest?.requestedThrough.toJson()}");
// print("_serviceRequest?.type:${_serviceRequest?.type.toJson()}");
// print("_serviceRequest?.priority:${_serviceRequest?.priority.toJson()}");
// return;
if (_formKey.currentState!.validate() && await _serviceRequest.validateNewRequest(context)) {
_formKey.currentState!.save();
// bool canSubmitRequest = await checkAssetForPendingServiceRequest(_serviceRequest.device.id);
// if (!canSubmitRequest) {
// return;
// }
_serviceRequest.devicePhotos = _deviceImages.map((e) => _isLocalUrl(e.path) ? "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}" : e.path).toList();
if (_serviceRequest.audio != null) {
if (_isLocalUrl(_serviceRequest.audio!)) {
final File file = File(_serviceRequest.audio!);
_serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}";
}
}
await _serviceRequestsProvider.createRequest(
context: context,
user: _userProvider.user!,
host: _settingProvider.host!,
serviceRequest: _serviceRequest,
);
}
}
}

@ -8,13 +8,12 @@ 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/service_request_latest/views/components/history_log_view.dart';
import 'package:test_sa/service_request_latest/views/components/initial_visit_card.dart';
import 'package:test_sa/views/pages/user/requests/service_request_details.dart';
import 'components/request_detail_view.dart';
class RequestDetailMain extends StatelessWidget {
final int requestId;
const RequestDetailMain({Key? key,required this.requestId}) : super(key: key);
const RequestDetailMain({Key? key, required this.requestId}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -48,14 +47,14 @@ class RequestDetailMain extends StatelessWidget {
),
),
12.height,
TabBarView(
TabBarView(
children: [
RequestDetailView(
serviceRequest: ServiceRequest(id: requestId.toString()),
fromTabView: true,
),
const HistoryLogView(),
],
const HistoryLogView(),
],
).expanded,
],
),

@ -103,7 +103,7 @@ class _ESignatureState extends State<ESignature> {
height: 135.toScreenHeight,
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.only(bottom: 8),
child: signature != null ? Image.memory(signature!) : ImageLoader(boxFit: BoxFit.contain, url: URLs.getFileUrl(widget.oldSignature)!),
child: signature != null ? Image.memory(signature!) : ImageLoader(boxFit: BoxFit.contain, url: URLs.getFileUrl(widget.oldSignature)??''),
)
: AbsorbPointer(
absorbing: !_editable,

@ -14,10 +14,11 @@ class AssetPicker extends StatelessWidget {
final Asset? device;
final bool editable;
final bool showAssetInfo;
final Color? borderColor;
final bool forPPM;
final bool showLoading;
const AssetPicker({Key? key, this.editable = true, this.device, this.onPick, this.showAssetInfo = true, this.forPPM = false, this.showLoading = false}) : super(key: key);
const AssetPicker({Key? key, this.editable = true, this.device, this.onPick,this.borderColor, this.showAssetInfo = true, this.forPPM = false, this.showLoading = false}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -36,7 +37,7 @@ class AssetPicker extends StatelessWidget {
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
"qr".toSvgAsset(height: 22, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.neutral20 : Colors.white),
"scan_asset".toSvgAsset(height: 22, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.neutral20 : Colors.white),
8.width,
"Scan or Pick Asset".bodyText(context).custom(color: context.isDark ? AppColor.neutral20 : Colors.white),
],
@ -52,16 +53,16 @@ class AssetPicker extends StatelessWidget {
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(10), border: Border.all(color: AppColor.blueStatus(context), width: 2),
color: Colors.white, borderRadius: BorderRadius.circular(10), border: Border.all(color:borderColor?? AppColor.blueStatus(context), width: 2),
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)],
),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
"qr".toSvgAsset(height: 22, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.neutral20 : Colors.black87),
"scan_asset".toSvgAsset(height: 22, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.neutral20 : AppColor.neutral120),
8.width,
"Re-Scan or Pick Asset".bodyText(context).custom(color: context.isDark ? AppColor.neutral20 : Colors.black87),
"Re-Scan or Pick Asset".bodyText(context).custom(color: context.isDark ? AppColor.neutral20 : AppColor.black20),
],
),
).onPress(() async {

@ -9,6 +9,7 @@ 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/new_views/app_style/app_color.dart';
import '../../../new_views/common_widgets/app_dashed_button.dart';
import 'multi_image_picker_item.dart';
@ -183,32 +184,89 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5);
return;
}
ImageSource source = await showDialog(
ImageSource? source = await showModalBottomSheet<ImageSource>(
context: context,
builder: (dialogContext) => CupertinoAlertDialog(
actions: <Widget>[
TextButton(
child: Text(context.translation.pickFromCamera),
onPressed: () {
Navigator.of(dialogContext).pop(ImageSource.camera);
},
),
TextButton(
child: Text(context.translation.pickFromGallery),
onPressed: () {
Navigator.of(dialogContext).pop(ImageSource.gallery);
},
),
TextButton(
child: Text(context.translation.pickFromFiles),
onPressed: () async {
await fromFilePicker();
Navigator.pop(context);
},
builder: (BuildContext context) {
Widget listCard({required String icon, required String label, required VoidCallback onTap}){
return GestureDetector(
onTap: onTap,
child: Container(
constraints: BoxConstraints(minWidth: 111.toScreenWidth,minHeight: 111.toScreenHeight),
padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth,vertical: 12.toScreenHeight),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(width: 1,color:AppColor.white70)
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
icon.toSvgAsset(),
24.height,
label.bodyText2(context).custom(color: AppColor.black20),
],
),
),
);
}
return Container(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
listCard(
icon: 'camera_icon',
label: '${context.translation.open}\n${context.translation.camera}',
onTap: () {
Navigator.of(context).pop(ImageSource.camera);
},
),
listCard(
icon: 'gallery_icon',
label: '${context.translation.open}\n${context.translation.gallery}',
onTap: () {
Navigator.of(context).pop(ImageSource.gallery);
},
),
listCard(
icon: 'file_icon',
label: '${context.translation.open}\n${context.translation.files}',
onTap: () async {
await fromFilePicker();
Navigator.pop(context);
},
),
],
),
],
),
);
},
);
// ImageSource source = await showDialog(
// context: context,
// builder: (dialogContext) => CupertinoAlertDialog(
// actions: <Widget>[
// TextButton(
// child: Text(context.translation.pickFromCamera),
// onPressed: () {
// Navigator.of(dialogContext).pop(ImageSource.camera);
// },
// ),
// TextButton(
// child: Text(context.translation.pickFromGallery),
// onPressed: () {
// Navigator.of(dialogContext).pop(ImageSource.gallery);
// },
// ),
// TextButton(
// child: Text(context.translation.pickFromFiles),
// onPressed: () async {
// await fromFilePicker();
// Navigator.pop(context);
// },
// ),
// ],
// ),
// );
if (source == null) return;
final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800);

@ -77,6 +77,7 @@ class _RecordSoundState extends State<TextSpeechRecordWidget> {
_commentController = TextEditingController();
node.unfocus();
_recorderIsOpened = true;
_settingProvider = Provider.of(context,listen: false);
// RecordMp3.instance.start(recordFilePath, (type) {
// // record fail callback
// });

@ -158,6 +158,7 @@ class _ASoundPlayerState extends State<ASoundPlayer> {
if (_audio != widget.audio) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
_audio = widget.audio;
print('audio position i got is $_audioPosition');
if (_isLocalFile) {
await _audioPlayer.setSourceDeviceFile(_audio);
} else {
@ -198,7 +199,7 @@ class _ASoundPlayerState extends State<ASoundPlayer> {
).paddingOnly(start: 8, end: 8).expanded,
_failedToLoad
? Text("Failed to load", style: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60))
: Text("${format(_audioPosition!)}/${format(_audioTime!)}", style: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
: Text("${format(_audioPosition??Duration.zero)}/${format(_audioTime??Duration.zero)}", style: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
],
),
],

Loading…
Cancel
Save