Merge branch 'zaid-development' into 'master'

Recoding Login Task & Upgrade Flutter Version

See merge request haroon6138/cloudsolutions-atoms!11
merge-requests/12/merge
Sikander Saleem 3 years ago
commit 7b31efc2ab

@ -71,6 +71,7 @@ android {
signingConfig signingConfigs.release signingConfig signingConfigs.release
} }
} }
namespace 'com.example.test_sa'
} }
flutter { flutter {

@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android">
package="com.example.test_sa">
<!-- The INTERNET permission is required for development. Specifically, <!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.

@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android">
package="com.example.test_sa">
<!-- The INTERNET permission is required for development. Specifically, <!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.

@ -1,12 +1,12 @@
buildscript { buildscript {
ext.kotlin_version = '1.6.10' ext.kotlin_version = '1.6.21'
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.1.2' classpath 'com.android.tools.build:gradle:7.4.2'
classpath 'com.google.gms:google-services:4.3.13' classpath 'com.google.gms:google-services:4.3.13'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip

@ -0,0 +1,233 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart';
import 'package:http/io_client.dart';
import '../exceptions/api_exception.dart';
typedef FactoryConstructor<U> = U Function(dynamic);
class APIError {
int? errorCode;
String? errorMessage;
APIError(this.errorCode, this.errorMessage);
Map<String, dynamic> toJson() => {'errorCode': errorCode, 'errorMessage': errorMessage};
@override
String toString() {
return jsonEncode(this);
}
}
APIException _throwAPIException(Response response) {
switch (response.statusCode) {
case 200:
APIError? apiError;
if (response.body.isNotEmpty) {
var jsonError = jsonDecode(response.body);
debugPrint(jsonError);
apiError = APIError(response.statusCode, jsonError[0]);
}
return APIException(APIException.BAD_REQUEST, error: apiError);
case 400:
APIError? apiError;
if (response.body.isNotEmpty) {
var jsonError = jsonDecode(response.body);
debugPrint("json error : $jsonError");
apiError = APIError(response.statusCode, jsonError[0]);
}
return APIException(APIException.BAD_REQUEST, error: apiError);
case 401:
return const APIException(APIException.UNAUTHORIZED);
case 403:
return const APIException(APIException.FORBIDDEN);
case 404:
return const APIException(APIException.NOT_FOUND);
case 500:
return const APIException(APIException.INTERNAL_SERVER_ERROR);
case 444:
var downloadUrl = response.headers["location"];
return APIException(APIException.UPGRADE_REQUIRED, arguments: downloadUrl);
default:
return const APIException(APIException.OTHER);
}
}
class ApiClient {
static final ApiClient _instance = ApiClient._internal();
ApiClient._internal();
factory ApiClient() => _instance;
Future<U> postJsonForObject<T, U>(FactoryConstructor<U> factoryConstructor, String url, T jsonObject,
{String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = false}) async {
var defaultHeaders = {'Accept': 'application/json'};
if (headers != null && headers.isNotEmpty) {
defaultHeaders.addAll(headers);
}
if (!kReleaseMode) {
debugPrint("Url:$url");
var bodyJson = json.encode(jsonObject);
debugPrint("body:$bodyJson");
}
var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes, isFormData: isFormData);
try {
var jsonData = jsonDecode(response.body);
if (jsonData != null) {
debugPrint(jsonData.runtimeType.toString());
return factoryConstructor(jsonData);
} else {
APIError? apiError;
apiError = APIError(response.statusCode, jsonData[0]);
throw APIException(APIException.BAD_REQUEST, error: apiError);
}
} catch (ex) {
if (ex is APIException) {
rethrow;
} else {
throw APIException(APIException.BAD_RESPONSE_FORMAT, arguments: ex);
}
}
}
Future<Response> postJsonForResponse<T>(String url, T jsonObject,
{String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = false}) async {
int currentRetryTime = retryTimes;
String? requestBody;
late Map<String, String> stringObj;
if (jsonObject != null) {
requestBody = jsonEncode(jsonObject);
if (headers == null) {
headers = {'Content-Type': 'application/json'};
} else {
headers['Content-Type'] = 'application/json';
}
}
if (isFormData) {
headers = {'Content-Type': 'application/x-www-form-urlencoded'};
stringObj = ((jsonObject ?? {}) as Map<String, dynamic>).map((key, value) => MapEntry(key, value?.toString() ?? ""));
}
Future<Response> retry(APIException exception) async {
if (currentRetryTime > 0) {
currentRetryTime -= 1;
debugPrint('will retry after 3 seconds...');
await Future.delayed(const Duration(seconds: 3));
return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers);
} else {
throw exception;
}
}
try {
return await _postForResponse(url, isFormData ? stringObj : requestBody, token: token, queryParameters: queryParameters, headers: headers);
} on SocketException catch (e) {
return await retry(APIException(APIException.OTHER, arguments: e));
} on HttpException catch (e) {
return await retry(APIException(APIException.OTHER, arguments: e));
} on TimeoutException catch (e) {
throw APIException(APIException.TIMEOUT, arguments: e);
} on ClientException catch (e) {
return await retry(APIException(APIException.OTHER, arguments: e));
}
}
Future<Response> _postForResponse(String url, requestBody, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers}) async {
var defaultHeaders = <String, String>{};
if (token != null) {
defaultHeaders['Authorization'] = 'Bearer $token';
}
if (headers != null && headers.isNotEmpty) {
defaultHeaders.addAll(headers);
}
if (queryParameters != null) {
var queryString = Uri(queryParameters: queryParameters).query;
url = '$url?$queryString';
}
var response = await _post(Uri.parse(url), body: requestBody, headers: defaultHeaders).timeout(const Duration(seconds: 120));
if (response.statusCode >= 200 && response.statusCode < 300) {
return response;
} else {
throw _throwAPIException(response);
}
}
Future<Response> getJsonForResponse<T>(String url, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async {
int currentRetryTime = retryTimes;
if (headers == null) {
headers = {'Content-Type': 'application/json'};
} else {
headers['Content-Type'] = 'application/json';
}
Future<Response> retry(APIException exception) async {
if (currentRetryTime > 0) {
currentRetryTime -= 1;
debugPrint('will retry after 3 seconds...');
await Future.delayed(const Duration(seconds: 3));
return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers);
} else {
throw exception;
}
}
try {
return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers);
} on SocketException catch (e) {
return await retry(APIException(APIException.OTHER, arguments: e));
} on HttpException catch (e) {
return await retry(APIException(APIException.OTHER, arguments: e));
} on TimeoutException catch (e) {
throw APIException(APIException.TIMEOUT, arguments: e);
} on ClientException catch (e) {
return await retry(APIException(APIException.OTHER, arguments: e));
}
}
Future<Response> _getForResponse(String url, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers}) async {
var defaultHeaders = <String, String>{};
if (token != null) {
defaultHeaders['Authorization'] = 'Bearer $token';
}
if (headers != null && headers.isNotEmpty) {
defaultHeaders.addAll(headers);
}
if (queryParameters != null) {
var queryString = Uri(queryParameters: queryParameters).query;
url = '$url?$queryString';
}
var response = await _get(Uri.parse(url), headers: defaultHeaders).timeout(const Duration(seconds: 60));
if (response.statusCode >= 200 && response.statusCode < 300) {
return response;
} else {
throw _throwAPIException(response);
}
}
Future<Response> _get(url, {Map<String, String>? headers}) => _withClient((client) => client.get(url, headers: headers));
bool _certificateCheck(X509Certificate cert, String host, int port) => true;
Future<T> _withClient<T>(Future<T> Function(Client) fn) async {
var httpClient = HttpClient()..badCertificateCallback = _certificateCheck;
var client = IOClient(httpClient);
try {
return await fn(client);
} finally {
client.close();
}
}
Future<Response> _post(url, {Map<String, String>? headers, body, Encoding? encoding}) => _withClient((client) => client.post(url, headers: headers, body: body, encoding: encoding));
}

@ -0,0 +1,81 @@
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/user.dart';
import 'api_client.dart';
class UserApiClient {
static final UserApiClient _instance = UserApiClient._internal();
/// ### This instance will be [NULL] until the login or registration process completed successfully by calling [login] or [register] functions
User? user;
UserApiClient._internal();
factory UserApiClient() => _instance;
/// - [user] object have to contains username & password
/// - If the request completed successfully the [UserApiClient.user] object inside [UserApiClient] class won't be null and will contains the data comes from the response.
/// - Returns exception of type [APIException] if any error happened.
///
///#### lib\client\user_api_client.dart
Future login({required User user}) async {
return await ApiClient().postJsonForObject(
(json) {
this.user = User.fromJson(json[0]);
},
"${URLs.host1}${URLs.login}",
await user.toLoginJson(), //body
isFormData: true,
);
}
/// - [newUser] object have to contains the new user data [email, phone, ...]
/// - If the request completed successfully the [user] object inside [UserApiClient] class won't be null and will contains the data comes from the response.
/// - Returns exception of type [APIException] if any error happened.
///
///#### lib\client\user_api_client.dart
Future register({required User newUser}) async {
return await ApiClient().postJsonForObject(
(json) {
user = User.fromJson(json);
},
"${URLs.host1}${URLs.register}",
await newUser.toRegisterJson(), //body
);
}
/// [updatedUser] have to contains the new data for the current user
/// - If the request completed successfully the [user] object inside [UserApiClient] class won't be null and will contains the data comes from the response.
/// - Returns exception of type [APIException] if any error happened.
///
///#### lib\client\user_api_client.dart
Future updateProfile({required User updatedUser}) async {
return await ApiClient().postJsonForObject(
(json) {
user = User.fromJson(json);
},
"${URLs.host1}${URLs.updateProfile}",
updatedUser.toUpdateProfileJson(), //body
);
// Map<String, dynamic> jsonObject = {};
// jsonObject["uid"] = user.id;
// jsonObject["token"] = user.token;
// if (user.department?.id != user.department?.id) {
// jsonObject["department"] = user.department?.id;
// }
// if (user.whatsApp != user.whatsApp) {
// jsonObject["whatsapp"] = user.whatsApp;
// }
// if (user.phoneNumber != user.phoneNumber) {
// jsonObject["phone"] = user.phoneNumber;
// }
// final response = await ApiClient().postJsonForResponse(URLs.updateProfile, jsonObject);
//
// if (response.statusCode >= 200 && response.statusCode < 300) {
// // client's request was successfully received
// this.user = User.fromJson(jsonDecode(utf8.decode(response.bodyBytes))[0]);
// this.user?.hospital = user.hospital;
// this.user?.department = user.department;
// }
}
}

@ -1,4 +1,4 @@
class URLs{ class URLs {
URLs._(); URLs._();
static const host2 = "http://194.163.164.213/atoms/api"; static const host2 = "http://194.163.164.213/atoms/api";
static const host1 = "https://atoms.hmg.com/api"; static const host1 = "https://atoms.hmg.com/api";
@ -63,5 +63,4 @@ class URLs{
static const getPentryStatus = "/return/pentry/status/list"; // get static const getPentryStatus = "/return/pentry/status/list"; // get
// contacts // contacts
static const getPentryContacts = "/handle/return/all/contacts"; // get static const getPentryContacts = "/handle/return/all/contacts"; // get
} }

@ -11,28 +11,28 @@ class HttpStatusManger {
return "careful null status"; return "careful null status";
} }
if (status == -1) { if (status == -1) {
return subtitle?.currentlyServiceNotAvailable??""; return subtitle?.currentlyServiceNotAvailable ?? "";
} }
if (status == -2) { if (status == -2) {
// client's request in process // client's request in process
return subtitle?.waitUntilYourRequestComplete??""; return subtitle?.waitUntilYourRequestComplete ?? "";
} else if (status >= 200 && status < 300) { } else if (status >= 200 && status < 300) {
// client's request was successfully received // client's request was successfully received
return messageFor200 ?? subtitle?.requestCompleteSuccessfully??""; return messageFor200 ?? subtitle?.requestCompleteSuccessfully ?? "";
} else if (status >= 400 && status < 500) { } else if (status >= 400 && status < 500) {
// client's request have error // client's request have error
switch (status) { switch (status) {
case 400: case 400:
return messageFor400 ?? subtitle?.failedToCompleteRequest??""; return messageFor400 ?? subtitle?.failedToCompleteRequest ?? "";
default: default:
return subtitle?.failedToCompleteRequest??""; return subtitle?.failedToCompleteRequest ?? "";
} }
} else if (status >= 500) { } else if (status >= 500) {
// server error // server error
return subtitle?.currentlyServiceNotAvailable??""; return subtitle?.currentlyServiceNotAvailable ?? "";
} else { } else {
// no error match so return default error // no error match so return default error
return subtitle?.failedToCompleteRequest??""; return subtitle?.failedToCompleteRequest ?? "";
} }
} }
} }

@ -5,8 +5,6 @@ import 'package:flutter/services.dart';
import '../../models/subtitle.dart'; import '../../models/subtitle.dart';
class AppLocalization { class AppLocalization {
AppLocalization(this.locale); AppLocalization(this.locale);
@ -21,18 +19,15 @@ class AppLocalization {
Subtitle? get subtitle => _subtitle; Subtitle? get subtitle => _subtitle;
Future<void> load() async { Future<void> load() async {
String jsonStringValues = await rootBundle String jsonStringValues = await rootBundle.loadString('assets/subtitles/${locale.languageCode}_subtitle.json');
.loadString('assets/subtitles/${locale.languageCode}_subtitle.json');
_subtitle = Subtitle.fromJson(json.decode(jsonStringValues)); _subtitle = Subtitle.fromJson(json.decode(jsonStringValues));
} }
// static member to have simple access to the delegate from Material App // static member to have simple access to the delegate from Material App
static const LocalizationsDelegate<AppLocalization> delegate = static const LocalizationsDelegate<AppLocalization> delegate = _DemoLocalizationsDelegate();
_DemoLocalizationsDelegate();
} }
class _DemoLocalizationsDelegate class _DemoLocalizationsDelegate extends LocalizationsDelegate<AppLocalization> {
extends LocalizationsDelegate<AppLocalization> {
const _DemoLocalizationsDelegate(); const _DemoLocalizationsDelegate();
@override @override

@ -57,7 +57,7 @@ class FirebaseNotificationManger {
AppNotification notification = AppNotification.fromJson(message.data); AppNotification notification = AppNotification.fromJson(message.data);
Navigator.pushNamed( Navigator.pushNamed(
context, context,
notification.path??"", notification.path ?? "",
arguments: notification.requestId, arguments: notification.requestId,
); );
}); });
@ -67,7 +67,7 @@ class FirebaseNotificationManger {
NotificationManger.showNotification( NotificationManger.showNotification(
title: message.notification?.title, title: message.notification?.title,
subtext: message.notification?.body, subtext: message.notification?.body,
hashcode: int.tryParse(notification.requestId??"0") ?? 1, hashcode: int.tryParse(notification.requestId ?? "0") ?? 1,
payload: json.encode(message.data), payload: json.encode(message.data),
); );
return; return;

@ -6,35 +6,24 @@ class NotificationManger {
// private constructor to avoid create object // private constructor to avoid create object
NotificationManger._(); NotificationManger._();
static FlutterLocalNotificationsPlugin localNotificationsPlugin = static FlutterLocalNotificationsPlugin localNotificationsPlugin = FlutterLocalNotificationsPlugin();
FlutterLocalNotificationsPlugin();
/// initialisation setting for all platform /// initialisation setting for all platform
/// onNotificationPressed action when notification pressed to open tap /// onNotificationPressed action when notification pressed to open tap
/// onIOSNotificationPressed action when notification pressed /// onIOSNotificationPressed action when notification pressed
/// to open tap in iOS versions older than 10 /// to open tap in iOS versions older than 10
static initialisation(Function(NotificationResponse) onNotificationPressed, static initialisation(Function(NotificationResponse) onNotificationPressed, DidReceiveLocalNotificationCallback onIOSNotificationPressed) async {
DidReceiveLocalNotificationCallback onIOSNotificationPressed) async { FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project // initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
const AndroidInitializationSettings initializationSettingsAndroid = const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings(
AndroidInitializationSettings(
'app_icon', 'app_icon',
); );
final DarwinInitializationSettings initializationSettingsDarwin = final DarwinInitializationSettings initializationSettingsDarwin = DarwinInitializationSettings(onDidReceiveLocalNotification: onIOSNotificationPressed);
DarwinInitializationSettings(
onDidReceiveLocalNotification: onIOSNotificationPressed);
final InitializationSettings initializationSettings = final InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsDarwin, macOS: initializationSettingsDarwin);
InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsDarwin,
macOS: initializationSettingsDarwin);
await flutterLocalNotificationsPlugin.initialize(initializationSettings, await flutterLocalNotificationsPlugin.initialize(initializationSettings, onDidReceiveNotificationResponse: onNotificationPressed);
onDidReceiveNotificationResponse: onNotificationPressed);
} }
// push new notification // push new notification
@ -44,8 +33,7 @@ class NotificationManger {
required int hashcode, required int hashcode,
String? payload, String? payload,
}) async { }) async {
const AndroidNotificationDetails androidChannel = const AndroidNotificationDetails androidChannel = AndroidNotificationDetails(
AndroidNotificationDetails(
'com.newtrack.testsa', 'com.newtrack.testsa',
'Test SA', 'Test SA',
channelDescription: 'Push notification service for Test SA', channelDescription: 'Push notification service for Test SA',
@ -62,8 +50,7 @@ class NotificationManger {
groupKey: 'com.newtrack.testsa', groupKey: 'com.newtrack.testsa',
); );
const DarwinNotificationDetails iosNotificationDetails = const DarwinNotificationDetails iosNotificationDetails = DarwinNotificationDetails(
DarwinNotificationDetails(
categoryIdentifier: "testSA", categoryIdentifier: "testSA",
); );

@ -53,11 +53,8 @@ class DepartmentsProvider extends ChangeNotifier {
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List listJson = List listJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); departments = listJson.map((department) => Department.fromJson(department)).toList();
departments = listJson
.map((department) => Department.fromJson(department))
.toList();
} }
isLoading = false; isLoading = false;
notifyListeners(); notifyListeners();

@ -28,7 +28,7 @@ class DeviceTransferProvider extends ChangeNotifier {
bool? nextPage = true; bool? nextPage = true;
// list of user requests // list of user requests
List<DeviceTransfer> items=[]; List<DeviceTransfer> items = [];
// when requests in-process _loading = true // when requests in-process _loading = true
// done _loading = true // done _loading = true
@ -72,12 +72,9 @@ class DeviceTransferProvider extends ChangeNotifier {
stateCode = response.statusCode; stateCode = response.statusCode;
if (stateCode != null && stateCode! >= 200 && stateCode! < 300) { if (stateCode != null && stateCode! >= 200 && stateCode! < 300) {
// client's request was successfully received // client's request was successfully received
List listJson = List listJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
print(listJson); print(listJson);
List<DeviceTransfer> itemsPage = listJson List<DeviceTransfer> itemsPage = listJson.map((request) => DeviceTransfer.fromJson(request)).toList();
.map((request) => DeviceTransfer.fromJson(request))
.toList();
print(itemsPage.length); print(itemsPage.length);
items.clear(); items.clear();
items.addAll(itemsPage); items.addAll(itemsPage);
@ -121,10 +118,7 @@ class DeviceTransferProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
final items = this.items; final items = this.items;
if (items != null) { if (items != null) {
items.insert( items.insert(0, DeviceTransfer.fromJson(json.decode(utf8.decode(response.bodyBytes))[0]));
0,
DeviceTransfer.fromJson(
json.decode(utf8.decode(response.bodyBytes))[0]));
notifyListeners(); notifyListeners();
} }
} }

@ -57,9 +57,7 @@ class GasRefillProvider extends ChangeNotifier {
if (stateCode != null && stateCode! >= 200 && stateCode! < 300) { if (stateCode != null && stateCode! >= 200 && stateCode! < 300) {
// client's request was successfully received // client's request was successfully received
List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); List requestsListJson = json.decode(utf8.decode(response.bodyBytes));
List<GasRefillModel> itemsPage = requestsListJson List<GasRefillModel> itemsPage = requestsListJson.map((request) => GasRefillModel.fromJson(request)).toList();
.map((request) => GasRefillModel.fromJson(request))
.toList();
items ??= []; items ??= [];
items?.addAll(itemsPage); items?.addAll(itemsPage);
if (itemsPage.length == pageItemNumber) { if (itemsPage.length == pageItemNumber) {
@ -110,10 +108,7 @@ class GasRefillProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
final items = this.items; final items = this.items;
if (items != null) { if (items != null) {
items.insert( items.insert(0, GasRefillModel.fromJson(json.decode(utf8.decode(response.bodyBytes))[0]));
0,
GasRefillModel.fromJson(
json.decode(utf8.decode(response.bodyBytes))[0]));
notifyListeners(); notifyListeners();
} }
} }

@ -75,9 +75,7 @@ class HospitalsProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
List<Hospital> page = categoriesListJson List<Hospital> page = categoriesListJson.map((category) => Hospital.fromJson(category)).toList();
.map((category) => Hospital.fromJson(category))
.toList();
if (hospitals == null) _hospitals = []; if (hospitals == null) _hospitals = [];
_hospitals?.addAll(page); _hospitals?.addAll(page);
@ -117,9 +115,7 @@ class HospitalsProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
page = categoriesListJson page = categoriesListJson.map((category) => Hospital.fromJson(category)).toList();
.map((category) => Hospital.fromJson(category))
.toList();
} }
return page; return page;
} catch (error) { } catch (error) {

@ -61,9 +61,7 @@ class NotificationsProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); List requestsListJson = json.decode(utf8.decode(response.bodyBytes));
List<AppNotification> serviceRequestsPage = requestsListJson List<AppNotification> serviceRequestsPage = requestsListJson.map((request) => AppNotification.fromJson(request)).toList();
.map((request) => AppNotification.fromJson(request))
.toList();
notifications.addAll(serviceRequestsPage); notifications.addAll(serviceRequestsPage);
if (serviceRequestsPage.length == pageItemNumber) { if (serviceRequestsPage.length == pageItemNumber) {
nextPage = true; nextPage = true;
@ -95,18 +93,13 @@ class NotificationsProvider extends ChangeNotifier {
//userId = 397.toString(); // testing id to view data //userId = 397.toString(); // testing id to view data
try { try {
response = await get( response = await get(Uri.parse("$host${URLs.getNotifications}?uid=${user.id}&token=${user.token}"), headers: {"Content-Type": "application/json; charset=utf-8"});
Uri.parse(
"$host${URLs.getNotifications}?uid=${user.id}&token=${user.token}"),
headers: {"Content-Type": "application/json; charset=utf-8"});
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); List requestsListJson = json.decode(utf8.decode(response.bodyBytes));
List<AppNotification> recentNotifications = requestsListJson List<AppNotification> recentNotifications = requestsListJson.map((request) => AppNotification.fromJson(request)).toList();
.map((request) => AppNotification.fromJson(request))
.toList();
return recentNotifications; return recentNotifications;
} }
return null; return null;

@ -73,8 +73,7 @@ class PartsProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
List<Part> page = List<Part> page = categoriesListJson.map((part) => Part.fromJson(part)).toList();
categoriesListJson.map((part) => Part.fromJson(part)).toList();
if (parts == null) _parts = []; if (parts == null) _parts = [];
_parts?.addAll(page); _parts?.addAll(page);
@ -107,11 +106,7 @@ class PartsProvider extends ChangeNotifier {
}) async { }) async {
Response response; Response response;
try { try {
response = await get( response = await get(Uri.parse(host + URLs.getPartNumber + (title == null || title.isEmpty ? "" : "?name=$title")), headers: {"Content-Type": "application/json; charset=utf-8"});
Uri.parse(host +
URLs.getPartNumber +
(title == null || title.isEmpty ? "" : "?name=$title")),
headers: {"Content-Type": "application/json; charset=utf-8"});
List<Part> page = []; List<Part> page = [];
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received

@ -69,8 +69,7 @@ class PreventiveMaintenanceVisitsProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); List requestsListJson = json.decode(utf8.decode(response.bodyBytes));
List<Visit> visits = List<Visit> visits = requestsListJson.map((request) => Visit.fromJson(request)).toList();
requestsListJson.map((request) => Visit.fromJson(request)).toList();
visits.addAll(visits); visits.addAll(visits);
if (visits.length == pageItemNumber) { if (visits.length == pageItemNumber) {
nextPage = true; nextPage = true;
@ -95,8 +94,8 @@ class PreventiveMaintenanceVisitsProvider extends ChangeNotifier {
}) async { }) async {
Response response; Response response;
Map<String, String> body = group.toJson(); Map<String, String> body = group.toJson();
body["token"] = user.token??""; body["token"] = user.token ?? "";
body["uid"] = user.id??""; body["uid"] = user.id ?? "";
//userId = 397.toString(); // testing id to view data //userId = 397.toString(); // testing id to view data
try { try {
response = await post( response = await post(
@ -107,7 +106,7 @@ class PreventiveMaintenanceVisitsProvider extends ChangeNotifier {
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
for (var visit in (group.visits??[])) { for (var visit in (group.visits ?? [])) {
visit.status = group.status; visit.status = group.status;
visit.actualDate = group.date.toString().split(" ").first; visit.actualDate = group.date.toString().split(" ").first;
} }

@ -68,11 +68,8 @@ class ServiceRequestsProvider extends ChangeNotifier {
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List requestsListJson = List requestsListJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); List<ServiceRequest> _serviceRequestsPage = requestsListJson.map((request) => ServiceRequest.fromJson(request)).toList();
List<ServiceRequest> _serviceRequestsPage = requestsListJson
.map((request) => ServiceRequest.fromJson(request))
.toList();
serviceRequests ??= []; serviceRequests ??= [];
serviceRequests?.addAll(_serviceRequestsPage); serviceRequests?.addAll(_serviceRequestsPage);
if (_serviceRequestsPage.length == pageItemNumber) { if (_serviceRequestsPage.length == pageItemNumber) {
@ -108,23 +105,17 @@ class ServiceRequestsProvider extends ChangeNotifier {
'$host${URLs.getSingleServiceRequest}?call_nid=$requestId$userData', '$host${URLs.getSingleServiceRequest}?call_nid=$requestId$userData',
)); ));
} catch (error) { } catch (error) {
throw (HttpStatusManger.getStatusMessage( throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle) ?? '');
status: -1, subtitle: subtitle) ??
'');
} }
// If the call to the server was successful, parse the JSON. // If the call to the server was successful, parse the JSON.
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// If the call to the server was successful, parse the JSON. // If the call to the server was successful, parse the JSON.
List jsonList = List jsonList = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); List<ServiceRequest> requests = jsonList.map((i) => ServiceRequest.fromJson(i)).toList();
List<ServiceRequest> requests =
jsonList.map((i) => ServiceRequest.fromJson(i)).toList();
return requests[0]; return requests[0];
} else { } else {
throw (HttpStatusManger.getStatusMessage( throw (HttpStatusManger.getStatusMessage(status: response.statusCode, subtitle: subtitle) ?? "");
status: response.statusCode, subtitle: subtitle) ??
"");
} }
} }
@ -320,12 +311,9 @@ class ServiceRequestsProvider extends ChangeNotifier {
body["uid"] = user.id ?? ""; body["uid"] = user.id ?? "";
body["token"] = user.token ?? ""; body["token"] = user.token ?? "";
body["job_id"] = request.id ?? ''; body["job_id"] = request.id ?? '';
body["start_time"] = ((timer.startAt?.millisecondsSinceEpoch ?? 0) / 1000) body["start_time"] = ((timer.startAt?.millisecondsSinceEpoch ?? 0) / 1000).toStringAsFixed(0);
.toStringAsFixed(0); body["end_time"] = ((timer.endAt?.millisecondsSinceEpoch ?? 0) / 1000).toStringAsFixed(0);
body["end_time"] = body["working_hours"] = ((timer.durationInSecond ?? 0) / 60 / 60).toStringAsFixed(5);
((timer.endAt?.millisecondsSinceEpoch ?? 0) / 1000).toStringAsFixed(0);
body["working_hours"] =
((timer.durationInSecond ?? 0) / 60 / 60).toStringAsFixed(5);
body["report_id"] = request.reportID ?? ''; body["report_id"] = request.reportID ?? '';
try { try {
response = await post( response = await post(
@ -360,16 +348,13 @@ class ServiceRequestsProvider extends ChangeNotifier {
'$host${URLs.getServiceReport}?report_id=$reportId$userData', '$host${URLs.getServiceReport}?report_id=$reportId$userData',
)); ));
} catch (error) { } catch (error) {
throw (HttpStatusManger.getStatusMessage( throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle) ?? '');
status: -1, subtitle: subtitle) ??
'');
} }
// If the call to the server was successful, parse the JSON. // If the call to the server was successful, parse the JSON.
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// If the call to the server was successful, parse the JSON. // If the call to the server was successful, parse the JSON.
return ServiceReport.fromJson( return ServiceReport.fromJson(json.decode(utf8.decode(response.bodyBytes)), reportId);
json.decode(utf8.decode(response.bodyBytes)), reportId);
} else { } else {
throw (HttpStatusManger.getStatusMessage( throw (HttpStatusManger.getStatusMessage(
status: response.statusCode, status: response.statusCode,

@ -58,8 +58,7 @@ class EmployeesProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
_items = _items = categoriesListJson.map((type) => Lookup.fromJson(type)).toList();
categoriesListJson.map((type) => Lookup.fromJson(type)).toList();
} }
_loading = false; _loading = false;
notifyListeners(); notifyListeners();

@ -64,8 +64,7 @@ class GasCylinderSizesProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
_items = _items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
} }
_loading = false; _loading = false;
notifyListeners(); notifyListeners();

@ -57,8 +57,7 @@ class GasStatusProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
_items = _items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
} }
_loading = false; _loading = false;
notifyListeners(); notifyListeners();

@ -57,8 +57,7 @@ class GasTypesProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
_items = _items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
} }
_loading = false; _loading = false;
notifyListeners(); notifyListeners();

@ -59,9 +59,7 @@ class PentryTaskStatusProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
_items = categoriesListJson _items = categoriesListJson.map((type) => Lookup.fromIntIdJson(type)).toList();
.map((type) => Lookup.fromIntIdJson(type))
.toList();
} }
_loading = false; _loading = false;
notifyListeners(); notifyListeners();

@ -58,18 +58,14 @@ class ServiceReportLastCallsProvider extends ChangeNotifier {
try { try {
response = await get( response = await get(
Uri.parse( Uri.parse(
(host ?? '') + (host ?? '') + URLs.getServiceReportLastCalls + (serviceStatus == null ? "" : "?service_status=$serviceStatus"),
URLs.getServiceReportLastCalls +
(serviceStatus == null ? "" : "?service_status=$serviceStatus"),
), ),
); );
_stateCode = response.statusCode; _stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
_calls = categoriesListJson _calls = categoriesListJson.map((type) => Lookup.fromIntIdJson(type)).toList();
.map((type) => Lookup.fromIntIdJson(type))
.toList();
} }
_loading = false; _loading = false;
notifyListeners(); notifyListeners();

@ -58,9 +58,7 @@ class ServiceReportReasonsProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
_reasons = categoriesListJson _reasons = categoriesListJson.map((type) => Lookup.fromIntIdJson(type)).toList();
.map((type) => Lookup.fromIntIdJson(type))
.toList();
} }
_loading = false; _loading = false;
notifyListeners(); notifyListeners();

@ -58,9 +58,7 @@ class ServiceReportStatusProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
_status = categoriesListJson _status = categoriesListJson.map((type) => Lookup.fromIntIdJson(type)).toList();
.map((type) => Lookup.fromIntIdJson(type))
.toList();
} }
_loading = false; _loading = false;
notifyListeners(); notifyListeners();

@ -58,9 +58,7 @@ class ServiceReportTypesProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
_types = categoriesListJson _types = categoriesListJson.map((type) => Lookup.fromIntIdJson(type)).toList();
.map((type) => Lookup.fromIntIdJson(type))
.toList();
} }
_loading = false; _loading = false;
notifyListeners(); notifyListeners();

@ -58,8 +58,7 @@ class ServiceStatusProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); List categoriesListJson = json.decode(utf8.decode(response.bodyBytes));
_statuses = _statuses = categoriesListJson.map((e) => Lookup.fromIntIdJson(e)).toList();
categoriesListJson.map((e) => Lookup.fromIntIdJson(e)).toList();
} }
_loading = false; _loading = false;
notifyListeners(); notifyListeners();

@ -1,162 +0,0 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import '../../../models/user.dart';
import '../../api_routes/urls.dart';
class UserProvider extends ChangeNotifier {
//reset provider data
void reset() {
_user = null;
_loading = false;
}
// contain user data
// when user not login or register _user = null
User? _user;
User? get user => _user;
set user(User? user) {
_user = user;
notifyListeners();
}
// when login or register in-process _login = true
// when login or register is done or not start = false
bool _loading = false;
bool get isLoading => _loading;
set isLoading(bool isLoading) {
_loading = isLoading;
notifyListeners();
}
/// sign in with user - need (email or phone) and password;
/// return -2 if request in progress
/// return -1 if error happen when sending request
/// return state code if request complete may be 200, 404 or 403
/// for more details check http state manager
/// lib\controllers\http_status_manger\http_status_manger.dart
Future<int> login({
required String host,
required User user,
}) async {
if (_loading == true) {
return -2;
}
_loading = true;
notifyListeners();
Response response;
try {
response = await post(
Uri.parse(host + URLs.login),
body: await user.toLoginJson(),
);
_loading = false;
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received
_user = User.fromJson(jsonDecode(utf8.decode(response.bodyBytes))[0]);
return response.statusCode;
}
notifyListeners();
return response.statusCode;
} catch (error) {
_loading = false;
notifyListeners();
return -1;
}
}
/// sign up with User object;
/// return -2 if request in progress
/// return -1 if error happen when sending request
/// return state code if request complete may be 200, 404 or 403
/// for more details about state codes check http state manager
/// lib\controllers\http_status_manger\http_status_manger.dart
Future<int> register({
required String host,
required User user,
}) async {
if (_loading == true) {
return -2;
}
_loading = true;
notifyListeners();
Response response;
try {
response = await post(Uri.parse(host + URLs.register),
body: await user.toRegisterJson());
} catch (error) {
_loading = false;
notifyListeners();
return -1;
}
_loading = false;
notifyListeners();
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received
_user = User.fromJson(jsonDecode(utf8.decode(response.bodyBytes))[0]);
_user?.hospital = user.hospital;
notifyListeners();
return response.statusCode;
}
return response.statusCode;
}
/// sign up with User object;
/// return -2 if request in progress
/// return -1 if error happen when sending request
/// return state code if request complete may be 200, 404 or 403
/// for more details about state codes check http state manager
/// lib\controllers\http_status_manger\http_status_manger.dart
Future<int> updateProfile({
required String host,
required User user,
}) async {
if (_loading == true) {
return -2;
}
_loading = true;
notifyListeners();
Response response;
Map<String, dynamic> jsonObject = {};
jsonObject["uid"] = user.id;
jsonObject["token"] = user.token;
if (user.department?.id != _user?.department?.id) {
jsonObject["department"] = user.department?.id;
}
if (user.whatsApp != _user?.whatsApp) {
jsonObject["whatsapp"] = user.whatsApp;
}
if (user.phoneNumber != _user?.phoneNumber) {
jsonObject["phone"] = user.phoneNumber;
}
try {
response =
await post(Uri.parse(host + URLs.updateProfile), body: jsonObject);
} catch (error) {
_loading = false;
notifyListeners();
return -1;
}
_loading = false;
notifyListeners();
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received
_user = User.fromJson(jsonDecode(utf8.decode(response.bodyBytes))[0]);
_user?.hospital = user.hospital;
_user?.department = user.department;
notifyListeners();
return response.statusCode;
}
return response.statusCode;
}
}

@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import '../../exceptions/api_exception.dart';
/// ## Change Notifier Class To Handle The State While Waiting The Futures Value
class LoadingNotifier with ChangeNotifier {
bool _loading = false;
/// - Returns [TRUE] if [waitApiRequest] function called
/// - Returns [FALSE] if [waitApiRequest] function completed in both states (failed, succeed)
bool get loading => _loading;
/// - [fun] : Callback function that contains the API request.
/// - [onError] : Optional callback function to handle the request on failure with [APIException] parameter.
/// - [onSuccess] : Optional callback function to handle the request on succeed.
void waitApiRequest(Function fun, {Function(APIException)? onError, Function? onSuccess}) async {
if (_loading == true) {
debugPrint('loading_notifier.dart : another action already started');
return;
}
_loading = true;
debugPrint('loading_notifier.dart : start loading');
notifyListeners();
try {
await fun();
if (onSuccess != null) {
await onSuccess();
}
} on APIException catch (error) {
debugPrint("loading_notifier.dart : [_waitResult] returns this message ${error.message} : ${error.arguments}");
if (onError != null) {
await onError(error);
}
} finally {
stopLoading();
debugPrint('loading_notifier.dart : stop loading');
}
}
/// ## Stop loading and Notify listeners
void stopLoading() {
_loading = false;
notifyListeners();
}
}

@ -0,0 +1,103 @@
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/api/user_api_client.dart';
import '../../models/user.dart';
import '../../views/pages/user/land_page.dart';
import '../http_status_manger/http_status_manger.dart';
import '../localization/localization.dart';
import 'loading_notifier.dart';
import 'settings/setting_provider.dart';
class UserProvider extends LoadingNotifier {
/// - [UserApiClient.user] will be null
/// - loading process will stop
void reset() {
UserApiClient().user = null;
stopLoading();
}
/// ## Login & Fill [UserApiClient.user] data
/// - onSuccess and user is Active : push to [LandPage]
/// - onSuccess and user isn't Active : toast message will appears
/// - onError : SnackBar will appears
Future login(BuildContext context, {required User user}) async {
final subtitle = AppLocalization.of(context)?.subtitle;
waitApiRequest(
() async {
await UserApiClient().login(user: user);
},
onSuccess: () {
if (context.mounted) {
Provider.of<SettingProvider>(context, listen: false).setUser(UserApiClient().user ?? User());
if (UserApiClient().user?.isActive ?? false) {
Navigator.of(context).pushNamed(LandPage.id);
} else {
Fluttertoast.showToast(msg: subtitle?.activationAlert ?? "");
}
}
},
onError: (error) {
String errorMessage = error.error?.errorCode == 400 ? subtitle?.wrongEmailOrPassword ?? "" : HttpStatusManger.getStatusMessage(status: error.error?.errorCode, subtitle: subtitle);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(errorMessage)));
},
);
}
/// ## Register & Fill [UserApiClient.user] data
/// - onSuccess : toast message will appears
/// - onError : SnackBar will appears
Future register(BuildContext context, {required User newUser}) async {
final subtitle = AppLocalization.of(context)?.subtitle;
if (newUser.hospital == null) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(subtitle?.hospitalRequired ?? "")));
return;
}
if (newUser.department == null) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(subtitle?.unitRequired ?? "")));
return;
}
waitApiRequest(
() async {
await UserApiClient().register(newUser: newUser);
},
onSuccess: () {
Fluttertoast.showToast(msg: subtitle?.activationAlert ?? "");
Navigator.of(context).pop();
},
onError: (error) {
String? errorMessage = error.error?.errorCode == 402
? subtitle?.nameExist
: error.error?.errorCode == 401
? subtitle?.emailExist
: HttpStatusManger.getStatusMessage(status: error.error?.errorCode, subtitle: subtitle);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(errorMessage ?? "")));
},
);
}
/// ## Update current user profile
/// - onSuccess : SnackBar will appears
/// - onError : SnackBar will appears
Future updateProfile(BuildContext context, {required User updatedUser}) async {
final subtitle = AppLocalization.of(context)?.subtitle;
if (updatedUser.department?.id == null) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(subtitle?.unitRequired ?? "")));
return;
}
waitApiRequest(
() async {
await UserApiClient().updateProfile(updatedUser: updatedUser);
},
onSuccess: () {
Provider.of<SettingProvider>(context, listen: false).setUser(UserApiClient().user!);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(subtitle?.requestCompleteSuccessfully ?? '')));
},
onError: (error) {
String errorMessage = HttpStatusManger.getStatusMessage(status: error.error?.errorCode, subtitle: subtitle);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(errorMessage)));
},
);
}
}

@ -1,24 +1,22 @@
class Validator{ class Validator {
// private constructor to avoid create class object // private constructor to avoid create class object
Validator._(); Validator._();
// check if string not empty and has value // check if string not empty and has value
static bool hasValue(String string){ static bool hasValue(String string) {
if (string == null || string.isEmpty) if (string == null || string.isEmpty) return false;
return false;
return true; return true;
} }
// Return true if email is valid. Otherwise, return false // Return true if email is valid. Otherwise, return false
static bool isEmail(String email){ static bool isEmail(String email) {
RegExp exp = new RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+"); RegExp exp = new RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+");
if(exp.hasMatch(email)) if (exp.hasMatch(email)) return true;
return true;
return false; return false;
} }
// Return true if phone number is valid. Otherwise, return false // Return true if phone number is valid. Otherwise, return false
static bool isPhoneNumber(String phoneNumber){ static bool isPhoneNumber(String phoneNumber) {
if (phoneNumber == null || phoneNumber.isEmpty) { if (phoneNumber == null || phoneNumber.isEmpty) {
return false; return false;
} }
@ -26,17 +24,14 @@ class Validator{
final pattern = r'^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*$'; final pattern = r'^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*$';
final regExp = RegExp(pattern); final regExp = RegExp(pattern);
if (regExp.hasMatch(phoneNumber)) if (regExp.hasMatch(phoneNumber)) return true;
return true;
return false; return false;
} }
// Return true if password is valid. Otherwise, return false // Return true if password is valid. Otherwise, return false
static bool isValidPassword(String password){ static bool isValidPassword(String password) {
if(password == null) if (password == null) return false;
return false; if (password.length < 6) return false;
if(password.length <6)
return false;
return true; return true;
} }

@ -0,0 +1,29 @@
import 'dart:convert';
import '../api/api_client.dart';
class APIException implements Exception {
static const String BAD_REQUEST = 'api_common_bad_request';
static const String UNAUTHORIZED = 'api_common_unauthorized';
static const String FORBIDDEN = 'api_common_forbidden';
static const String NOT_FOUND = 'api_common_not_found';
static const String INTERNAL_SERVER_ERROR = 'api_common_internal_server_error';
static const String UPGRADE_REQUIRED = 'api_common_upgrade_required';
static const String BAD_RESPONSE_FORMAT = 'api_common_bad_response_format';
static const String OTHER = 'api_common_http_error';
static const String TIMEOUT = 'api_common_http_timeout';
static const String UNKNOWN = 'unexpected_error';
final String message;
final APIError? error;
final arguments;
const APIException(this.message, {this.arguments, this.error});
Map<String, dynamic> toJson() => {'message': message, 'error': error, 'arguments': '$arguments'};
@override
String toString() {
return jsonEncode(this);
}
}

@ -7,8 +7,7 @@ extension IntExtensions on int {
Widget get width => SizedBox(width: toDouble()); Widget get width => SizedBox(width: toDouble());
Widget get divider => Widget get divider => Divider(height: toDouble(), thickness: toDouble(), color: AColors.greyEF);
Divider(height: toDouble(), thickness: toDouble(), color: AColors.greyEF);
Widget get makeItSquare => SizedBox(width: toDouble(), height: toDouble()); Widget get makeItSquare => SizedBox(width: toDouble(), height: toDouble());
} }

@ -47,8 +47,8 @@ import 'controllers/providers/api/status_drop_down/report/service_report_reasons
import 'controllers/providers/api/status_drop_down/report/service_report_status_provider.dart'; import 'controllers/providers/api/status_drop_down/report/service_report_status_provider.dart';
import 'controllers/providers/api/status_drop_down/report/service_report_types_provider.dart'; import 'controllers/providers/api/status_drop_down/report/service_report_types_provider.dart';
import 'controllers/providers/api/status_drop_down/report/service_types_provider.dart'; import 'controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import 'controllers/providers/api/user_provider.dart';
import 'controllers/providers/settings/setting_provider.dart'; import 'controllers/providers/settings/setting_provider.dart';
import 'controllers/providers/user_provider.dart';
import 'views/pages/device_transfer/request_device_transfer.dart'; import 'views/pages/device_transfer/request_device_transfer.dart';
import 'views/pages/device_transfer/track_device_transfer.dart'; import 'views/pages/device_transfer/track_device_transfer.dart';
import 'views/widgets/hospitals/single_hospital_picker.dart'; import 'views/widgets/hospitals/single_hospital_picker.dart';
@ -57,11 +57,8 @@ void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
if (Platform.isIOS) { if (Platform.isIOS) {
await Firebase.initializeApp( await Firebase.initializeApp(
options: const FirebaseOptions( options:
apiKey: "AIzaSyACQkSleNwU1jzEKR5ho1uSfZERokwwAbc", const FirebaseOptions(apiKey: "AIzaSyACQkSleNwU1jzEKR5ho1uSfZERokwwAbc", appId: "1:973582662416:ios:bc4a8061444c6a08fbc395", messagingSenderId: "973582662416", projectId: "atoms-fb912"),
appId: "1:973582662416:ios:bc4a8061444c6a08fbc395",
messagingSenderId: "973582662416",
projectId: "atoms-fb912"),
); );
} else { } else {
await Firebase.initializeApp(); await Firebase.initializeApp();
@ -87,8 +84,7 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => ServiceRequestsProvider()), ChangeNotifierProvider(create: (_) => ServiceRequestsProvider()),
ChangeNotifierProvider(create: (_) => DepartmentsProvider()), ChangeNotifierProvider(create: (_) => DepartmentsProvider()),
ChangeNotifierProvider(create: (_) => NotificationsProvider()), ChangeNotifierProvider(create: (_) => NotificationsProvider()),
ChangeNotifierProvider( ChangeNotifierProvider(create: (_) => PreventiveMaintenanceVisitsProvider()),
create: (_) => PreventiveMaintenanceVisitsProvider()),
ChangeNotifierProvider(create: (_) => RegularVisitsProvider()), ChangeNotifierProvider(create: (_) => RegularVisitsProvider()),
ChangeNotifierProvider(create: (_) => PartsProvider()), ChangeNotifierProvider(create: (_) => PartsProvider()),
ChangeNotifierProvider(create: (_) => ServiceReportReasonsProvider()), ChangeNotifierProvider(create: (_) => ServiceReportReasonsProvider()),
@ -106,8 +102,7 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => PentryVisitStatusProvider()), ChangeNotifierProvider(create: (_) => PentryVisitStatusProvider()),
ChangeNotifierProvider(create: (_) => PentryStatusProvider()), ChangeNotifierProvider(create: (_) => PentryStatusProvider()),
ChangeNotifierProvider(create: (_) => ServiceRequestPriorityProvider()), ChangeNotifierProvider(create: (_) => ServiceRequestPriorityProvider()),
ChangeNotifierProvider( ChangeNotifierProvider(create: (_) => ServiceRequestDefectTypesProvider()),
create: (_) => ServiceRequestDefectTypesProvider()),
], ],
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
@ -125,11 +120,7 @@ class MyApp extends StatelessWidget {
scaffoldBackgroundColor: AColors.scaffoldBackgroundColor, scaffoldBackgroundColor: AColors.scaffoldBackgroundColor,
primaryColor: AColors.primaryColor, primaryColor: AColors.primaryColor,
indicatorColor: AColors.primaryColor, indicatorColor: AColors.primaryColor,
colorScheme: const ColorScheme.light( colorScheme: const ColorScheme.light(primary: AColors.primaryColor, onPrimary: Colors.white, secondary: AColors.secondaryColor, onSecondary: Colors.white)),
primary: AColors.primaryColor,
onPrimary: Colors.white,
secondary: AColors.secondaryColor,
onSecondary: Colors.white)),
localizationsDelegates: const [ localizationsDelegates: const [
// ... app-specific localization delegate[s] here // ... app-specific localization delegate[s] here
AppLocalization.delegate, AppLocalization.delegate,
@ -157,10 +148,8 @@ class MyApp extends StatelessWidget {
SingleDepartmentPicker.id: (_) => SingleDepartmentPicker(), SingleDepartmentPicker.id: (_) => SingleDepartmentPicker(),
ServiceRequestsPage.id: (_) => ServiceRequestsPage(), ServiceRequestsPage.id: (_) => ServiceRequestsPage(),
NotificationsPage.id: (_) => NotificationsPage(), NotificationsPage.id: (_) => NotificationsPage(),
FutureRequestServiceDetails.id: (_) => FutureRequestServiceDetails.id: (_) => const FutureRequestServiceDetails(),
const FutureRequestServiceDetails(), PreventiveMaintenanceVisitsPage.id: (_) => PreventiveMaintenanceVisitsPage(),
PreventiveMaintenanceVisitsPage.id: (_) =>
PreventiveMaintenanceVisitsPage(),
RegularVisitsPage.id: (_) => const RegularVisitsPage(), RegularVisitsPage.id: (_) => const RegularVisitsPage(),
TrackGasRefillPage.id: (_) => const TrackGasRefillPage(), TrackGasRefillPage.id: (_) => const TrackGasRefillPage(),
RequestDeviceTransfer.id: (_) => const RequestDeviceTransfer(), RequestDeviceTransfer.id: (_) => const RequestDeviceTransfer(),

@ -1,7 +1,6 @@
import '../views/pages/user/requests/future_request_service_details.dart'; import '../views/pages/user/requests/future_request_service_details.dart';
class AppNotification{ class AppNotification {
String? requestId; String? requestId;
String? title; String? title;
String? description; String? description;
@ -16,13 +15,12 @@ class AppNotification{
this.path, this.path,
}); });
factory AppNotification.fromJson(Map<String,dynamic> parsedJson){ factory AppNotification.fromJson(Map<String, dynamic> parsedJson) {
return AppNotification( return AppNotification(
requestId: parsedJson["nid"], requestId: parsedJson["nid"],
title: parsedJson["call_client"] ?? parsedJson["title"], title: parsedJson["call_client"] ?? parsedJson["title"],
description: parsedJson["task_description"], description: parsedJson["task_description"],
date: parsedJson["creation_date"], date: parsedJson["creation_date"],
path: FutureRequestServiceDetails.id path: FutureRequestServiceDetails.id);
);
} }
} }

@ -1,4 +1,4 @@
class Department{ class Department {
String? id; String? id;
String? name; String? name;
@ -7,13 +7,13 @@ class Department{
this.name, this.name,
}); });
factory Department.fromJson(Map<String,dynamic> parsedJson){ factory Department.fromJson(Map<String, dynamic> parsedJson) {
return Department( return Department(
id: parsedJson["nid"] ?? parsedJson["id"], id: parsedJson["nid"] ?? parsedJson["id"],
name: parsedJson["dept_name"] ?? parsedJson["value"], name: parsedJson["dept_name"] ?? parsedJson["value"],
); );
} }
factory Department.fromDepartment(Department? department){ factory Department.fromDepartment(Department? department) {
return Department( return Department(
id: department?.id, id: department?.id,
name: department?.name, name: department?.name,

@ -52,8 +52,7 @@ class DeviceTransferInfo {
userId = old?.userId; userId = old?.userId;
name = old?.name; name = old?.name;
client = old?.client != null ? Hospital.fromHospital(old?.client) : null; client = old?.client != null ? Hospital.fromHospital(old?.client) : null;
department = department = department != null ? Department.fromDepartment(old?.department!) : null;
department != null ? Department.fromDepartment(old?.department!) : null;
workingHours = old?.workingHours; workingHours = old?.workingHours;
travelingHours = old?.travelingHours; travelingHours = old?.travelingHours;
comment = old?.comment; comment = old?.comment;
@ -61,8 +60,7 @@ class DeviceTransferInfo {
status = old?.status; status = old?.status;
} }
factory DeviceTransferInfo.fromJson( factory DeviceTransferInfo.fromJson(Map<String, dynamic> parsedJson, String key) {
Map<String, dynamic> parsedJson, String key) {
return DeviceTransferInfo( return DeviceTransferInfo(
workingHours: parsedJson["${key}working_hours"], workingHours: parsedJson["${key}working_hours"],
travelingHours: parsedJson["${key}travel_hours"], travelingHours: parsedJson["${key}travel_hours"],

@ -1,4 +1,4 @@
enum UsersTypes{ enum UsersTypes {
engineer, // 0 engineer, // 0
normal_user, // 1 normal_user, // 1
} }

@ -10,7 +10,8 @@ class GasRefillDetails {
this.type, this.type,
this.cylinderSize, this.cylinderSize,
this.requestedQuantity, this.requestedQuantity,
this.deliveredQuantity, required model, this.deliveredQuantity,
required model,
}); });
bool validate() { bool validate() {
@ -24,23 +25,19 @@ class GasRefillDetails {
return GasRefillDetails( return GasRefillDetails(
type: Lookup.fromJson(parsedJson["type"]), type: Lookup.fromJson(parsedJson["type"]),
cylinderSize: Lookup.fromJson(parsedJson["size"]), cylinderSize: Lookup.fromJson(parsedJson["size"]),
requestedQuantity: parsedJson["requsted_qty"] == null requestedQuantity: parsedJson["requsted_qty"] == null ? 0 : int.tryParse(parsedJson["requsted_qty"].toString()) ?? 0,
? 0 deliveredQuantity: parsedJson["deliverd_qty"] == null ? 0 : int.tryParse(parsedJson["deliverd_qty"].toString()) ?? 0,
: int.tryParse(parsedJson["requsted_qty"].toString()) ?? 0, model: null,
deliveredQuantity: parsedJson["deliverd_qty"] == null
? 0
: int.tryParse(parsedJson["deliverd_qty"].toString()) ?? 0, model: null,
); );
} }
factory GasRefillDetails.fromDetails(GasRefillDetails details) { factory GasRefillDetails.fromDetails(GasRefillDetails details) {
return GasRefillDetails( return GasRefillDetails(
type: details.type != null ? Lookup.fromStatus(details.type!) : null, type: details.type != null ? Lookup.fromStatus(details.type!) : null,
cylinderSize: details.cylinderSize != null cylinderSize: details.cylinderSize != null ? Lookup.fromStatus(details.cylinderSize!) : null,
? Lookup.fromStatus(details.cylinderSize!)
: null,
requestedQuantity: details.requestedQuantity, requestedQuantity: details.requestedQuantity,
deliveredQuantity: details.deliveredQuantity, model: null, deliveredQuantity: details.deliveredQuantity,
model: null,
); );
} }
} }

@ -31,9 +31,7 @@ class GasRefillModel {
clientName = model.clientName; clientName = model.clientName;
title = model.title; title = model.title;
status = model.status != null ? Lookup.fromStatus(model.status!) : null; status = model.status != null ? Lookup.fromStatus(model.status!) : null;
details = model.details details = model.details?.map<GasRefillDetails>((e) => GasRefillDetails.fromDetails(e)).toList();
?.map<GasRefillDetails>((e) => GasRefillDetails.fromDetails(e))
.toList();
} }
factory GasRefillModel.fromJson(Map<String, dynamic> parsedJson) { factory GasRefillModel.fromJson(Map<String, dynamic> parsedJson) {

@ -1,4 +1,4 @@
class Hospital{ class Hospital {
String? id; String? id;
String? name; String? name;
@ -7,14 +7,14 @@ class Hospital{
this.name, this.name,
}); });
factory Hospital.fromJson(Map<String,dynamic> parsedJson){ factory Hospital.fromJson(Map<String, dynamic> parsedJson) {
return Hospital( return Hospital(
id: parsedJson["nid"] ?? parsedJson["id"], id: parsedJson["nid"] ?? parsedJson["id"],
name: parsedJson["client_name"] ?? parsedJson["value"], name: parsedJson["client_name"] ?? parsedJson["value"],
); );
} }
factory Hospital.fromHospital(Hospital? hospital){ factory Hospital.fromHospital(Hospital? hospital) {
return Hospital( return Hospital(
id: hospital?.id, id: hospital?.id,
name: hospital?.name, name: hospital?.name,

@ -1,4 +1,4 @@
class Issue{ class Issue {
String? title; String? title;
String? userId; String? userId;
List<int>? reports; List<int>? reports;
@ -15,13 +15,13 @@ class Issue{
this.serviceRequestId, this.serviceRequestId,
}); });
Map<String,String> toMap(){ Map<String, String> toMap() {
Map<String,String> map ={}; Map<String, String> map = {};
if(title != null) map["title"] = title??""; if (title != null) map["title"] = title ?? "";
if(reports != null) map["issue_report"] = reports.toString(); if (reports != null) map["issue_report"] = reports.toString();
if(userId != null) map["uid"] = userId??""; if (userId != null) map["uid"] = userId ?? "";
if(description != null) map["desc"] = description??""; if (description != null) map["desc"] = description ?? "";
if(serviceRequestId != null) map["call_id"] = serviceRequestId??""; if (serviceRequestId != null) map["call_id"] = serviceRequestId ?? "";
return map; return map;
} }
} }

@ -1,5 +1,4 @@
class Lookup{ class Lookup {
final String? label; final String? label;
final String? key; final String? key;
final int? id; final int? id;
@ -11,16 +10,12 @@ class Lookup{
}); });
@override @override
bool operator == (Object other) => bool operator ==(Object other) => identical(this, other) || other is Lookup && key == other.key && id == other.id;
identical(this, other) || other is Lookup &&
key == other.key &&
id == other.id;
@override @override
int get hashCode => id.hashCode; int get hashCode => id.hashCode;
factory Lookup.fromStatus(Lookup old){ factory Lookup.fromStatus(Lookup old) {
return Lookup( return Lookup(
label: old.label, label: old.label,
id: old.id, id: old.id,
@ -28,16 +23,14 @@ class Lookup{
); );
} }
factory Lookup.fromJson(Map<String,dynamic> parsedJson){ factory Lookup.fromJson(Map<String, dynamic> parsedJson) {
return Lookup( return Lookup(
label: parsedJson["value"], label: parsedJson["value"],
id: parsedJson["id"] is int? id: parsedJson["id"] is int? ? parsedJson["id"] : int.tryParse(parsedJson["id"] ?? parsedJson["uid"]),
? parsedJson["id"]
: int.tryParse(parsedJson["id"] ?? parsedJson["uid"]),
); );
} }
factory Lookup.fromIntIdJson(Map<String,dynamic> parsedJson){ factory Lookup.fromIntIdJson(Map<String, dynamic> parsedJson) {
return Lookup( return Lookup(
label: parsedJson["value"], label: parsedJson["value"],
id: parsedJson["id"], id: parsedJson["id"],

@ -12,9 +12,7 @@ class CalibrationTool {
Map<String, String> toMap() { Map<String, String> toMap() {
return { return {
if (assetsNumber != null) 'assetsSN': (assetsNumber?.id).toString(), if (assetsNumber != null) 'assetsSN': (assetsNumber?.id).toString(),
if (dataOfTesting != null) if (dataOfTesting != null) 'dataOfTesting': ((dataOfTesting?.millisecondsSinceEpoch ?? 0) ~/ 1000).toString(),
'dataOfTesting':
((dataOfTesting?.millisecondsSinceEpoch ?? 0) ~/ 1000).toString(),
}; };
} }

@ -8,13 +8,7 @@ class Contact {
String? telephone; String? telephone;
String? landLine; String? landLine;
Contact( Contact({this.title, this.contactPerson, this.job, this.email, this.telephone, this.landLine});
{this.title,
this.contactPerson,
this.job,
this.email,
this.telephone,
this.landLine});
Map<String, String> toMap() { Map<String, String> toMap() {
return { return {

@ -1,13 +1,9 @@
import '../../lookup.dart'; import '../../lookup.dart';
class ContactTitle extends Lookup { class ContactTitle extends Lookup {
ContactTitle({ ContactTitle({required int id, required String label}) : super(id: id, label: label);
required int id,
required String label
}):super(id: id,label: label);
factory ContactTitle.fromMap(Map<String,dynamic> parsedJson){ factory ContactTitle.fromMap(Map<String, dynamic> parsedJson) {
return ContactTitle( return ContactTitle(
label: parsedJson["value"], label: parsedJson["value"],
id: parsedJson["id"], id: parsedJson["id"],

@ -1,8 +1,7 @@
import '../../lookup.dart'; import '../../lookup.dart';
class ContactTitle extends Lookup { class ContactTitle extends Lookup {
ContactTitle({required int id, required String label}) ContactTitle({required int id, required String label}) : super(id: id, label: label);
: super(id: id, label: label);
factory ContactTitle.fromMap(Map<String, dynamic> parsedJson) { factory ContactTitle.fromMap(Map<String, dynamic> parsedJson) {
return ContactTitle( return ContactTitle(

@ -1,4 +1,4 @@
class Part{ class Part {
String? id; String? id;
String? code; String? code;
String? name; String? name;
@ -11,13 +11,12 @@ class Part{
this.quantity = 1, this.quantity = 1,
}); });
factory Part.fromJson(Map<String,dynamic> parsedJson){ factory Part.fromJson(Map<String, dynamic> parsedJson) {
return Part( return Part(
id: parsedJson["nid"] ?? parsedJson["id"], id: parsedJson["nid"] ?? parsedJson["id"],
code: parsedJson["part_code"] ?? parsedJson["name"], code: parsedJson["part_code"] ?? parsedJson["name"],
name: parsedJson["part_name"], name: parsedJson["part_name"],
quantity: parsedJson["qty"] == null quantity: parsedJson["qty"] == null ? 1 : int.tryParse(parsedJson["qty"].toString()) ?? 1,
? 1 : int.tryParse(parsedJson["qty"].toString()) ?? 1,
); );
} }
} }

@ -50,71 +50,70 @@ class ServiceReport {
this.timer, this.timer,
}); });
Map<String,String> toMap(){ Map<String, String> toMap() {
Map<String,String> _map = {}; Map<String, String> _map = {};
if(id != null) _map["id"] = id??""; if (id != null) _map["id"] = id ?? "";
if(visitDate != null) _map["visit_date"] = ((visitDate?.millisecondsSinceEpoch??0) ~/ 1000).toString(); if (visitDate != null) _map["visit_date"] = ((visitDate?.millisecondsSinceEpoch ?? 0) ~/ 1000).toString();
if(serviceType != null) _map["service_type"] = serviceType?.id.toString()??""; if (serviceType != null) _map["service_type"] = serviceType?.id.toString() ?? "";
if(status != null) _map["status"] = status?.id.toString()??""; if (status != null) _map["status"] = status?.id.toString() ?? "";
if(type != null) _map["service_report_type"] = type?.id.toString()??""; if (type != null) _map["service_report_type"] = type?.id.toString() ?? "";
if(faultDescription != null && (faultDescription?.isNotEmpty??false)) _map["fault_description"] = faultDescription??""; if (faultDescription != null && (faultDescription?.isNotEmpty ?? false)) _map["fault_description"] = faultDescription ?? "";
//if(workHours != null && workHours.isNotEmpty) _map["working_hours"] = workHours; //if(workHours != null && workHours.isNotEmpty) _map["working_hours"] = workHours;
if(timer != null){ if (timer != null) {
_map["start_time"] = ((timer?.startAt?.millisecondsSinceEpoch??0) / 1000).toStringAsFixed(0); _map["start_time"] = ((timer?.startAt?.millisecondsSinceEpoch ?? 0) / 1000).toStringAsFixed(0);
_map["end_time"] = ((timer?.endAt ?? DateTime.now()).millisecondsSinceEpoch / 1000).toStringAsFixed(0); _map["end_time"] = ((timer?.endAt ?? DateTime.now()).millisecondsSinceEpoch / 1000).toStringAsFixed(0);
_map["working_hours"] = ((timer?.durationInSecond??0) / 60 / 60).toStringAsFixed(5); _map["working_hours"] = ((timer?.durationInSecond ?? 0) / 60 / 60).toStringAsFixed(5);
} }
if(travelingHours != null && (travelingHours?.isNotEmpty??false)) _map["traveling_hours"] = travelingHours??""; if (travelingHours != null && (travelingHours?.isNotEmpty ?? false)) _map["traveling_hours"] = travelingHours ?? "";
if(workPreformed != null && (workPreformed?.isNotEmpty??false)) _map["work_performed"] = workPreformed??""; if (workPreformed != null && (workPreformed?.isNotEmpty ?? false)) _map["work_performed"] = workPreformed ?? "";
if(jobSheetNumber != null && (jobSheetNumber?.isNotEmpty??false)) _map["job_sheet_no"] = jobSheetNumber??""; if (jobSheetNumber != null && (jobSheetNumber?.isNotEmpty ?? false)) _map["job_sheet_no"] = jobSheetNumber ?? "";
if(parts != null && (parts?.isNotEmpty??false)){ if (parts != null && (parts?.isNotEmpty ?? false)) {
Map<String,int> _partsMap = {}; Map<String, int> _partsMap = {};
parts?.forEach((part) { parts?.forEach((part) {
if((part.id?.isNotEmpty??false)) { if ((part.id?.isNotEmpty ?? false)) {
_partsMap[part?.id??""] = part.quantity; _partsMap[part?.id ?? ""] = part.quantity;
} }
}); });
_map["parts"] = json.encode(_partsMap); _map["parts"] = json.encode(_partsMap);
} }
if(device?.id != null && device?.id != null) _map["eq_id"] = device?.id??""; if (device?.id != null && device?.id != null) _map["eq_id"] = device?.id ?? "";
if(quantity != null && (quantity?.isNotEmpty??false)) _map["qty"] = quantity??""; if (quantity != null && (quantity?.isNotEmpty ?? false)) _map["qty"] = quantity ?? "";
if(endDate != null) _map["end_date"] = ((endDate?.millisecondsSinceEpoch??0) ~/ 1000).toString(); if (endDate != null) _map["end_date"] = ((endDate?.millisecondsSinceEpoch ?? 0) ~/ 1000).toString();
if(reason != null) _map["reasons"] = reason?.id.toString()??""; if (reason != null) _map["reasons"] = reason?.id.toString() ?? "";
if(operatingHours != null && (operatingHours?.isNotEmpty??false)) _map["operation_hours"] = operatingHours??""; if (operatingHours != null && (operatingHours?.isNotEmpty ?? false)) _map["operation_hours"] = operatingHours ?? "";
if(callLastSituation != null) _map["call_last_situtation"] = callLastSituation?.id.toString()??""; if (callLastSituation != null) _map["call_last_situtation"] = callLastSituation?.id.toString() ?? "";
if(image != null) _map["image"] = image??""; if (image != null) _map["image"] = image ?? "";
if(invoiceCode != null) _map["invoice_no"] = invoiceCode??""; if (invoiceCode != null) _map["invoice_no"] = invoiceCode ?? "";
if(invoiceNumber != null) _map["invoice_code"] = invoiceNumber??""; if (invoiceNumber != null) _map["invoice_code"] = invoiceNumber ?? "";
return _map; return _map;
} }
bool validate(){ bool validate() {
if(visitDate == null) return false; if (visitDate == null) return false;
if(serviceType == null) return false; if (serviceType == null) return false;
if(status == null) return false; if (status == null) return false;
if(type == null) return false; if (type == null) return false;
if(callLastSituation == null) return false; if (callLastSituation == null) return false;
if(callLastSituation?.id == 12){ if (callLastSituation?.id == 12) {
if(invoiceCode != null || invoiceCode?.isEmpty == true) return false; if (invoiceCode != null || invoiceCode?.isEmpty == true) return false;
if(invoiceNumber != null || invoiceNumber?.isEmpty== true ) return false; if (invoiceNumber != null || invoiceNumber?.isEmpty == true) return false;
} }
if(parts == null) return false; if (parts == null) return false;
//if(endDate == null) return false; //if(endDate == null) return false;
//if(reason == null) return false; //if(reason == null) return false;
if((device?.id == null ||(device?.id?.isEmpty??false)) && type?.id != 1) return false; if ((device?.id == null || (device?.id?.isEmpty ?? false)) && type?.id != 1) return false;
//if(quantity == null || quantity.isEmpty) return false; //if(quantity == null || quantity.isEmpty) return false;
//if(image == null) return false; //if(image == null) return false;
return true; return true;
} }
factory ServiceReport.fromJson(Map<String,dynamic> parsedJson,String id){ factory ServiceReport.fromJson(Map<String, dynamic> parsedJson, String id) {
List<Part> _parts = []; List<Part> _parts = [];
if(parsedJson["parts"] != null){ if (parsedJson["parts"] != null) {
if(parsedJson["parts"][0]["id"] != null){ if (parsedJson["parts"][0]["id"] != null) {
List partsList = parsedJson["parts"]; List partsList = parsedJson["parts"];
_parts = partsList.map((e) => Part.fromJson(e)).toList(); _parts = partsList.map((e) => Part.fromJson(e)).toList();
} }
} }
return ServiceReport( return ServiceReport(
id: id, id: id,
@ -124,7 +123,7 @@ class ServiceReport {
status: Lookup.fromJson(parsedJson["service_report_status"]), status: Lookup.fromJson(parsedJson["service_report_status"]),
type: Lookup.fromJson(parsedJson["service_report_type"]), type: Lookup.fromJson(parsedJson["service_report_type"]),
faultDescription: parsedJson["fault_description"], faultDescription: parsedJson["fault_description"],
endDate:getDate(parsedJson["end_date"]), endDate: getDate(parsedJson["end_date"]),
invoiceCode: parsedJson["invoice_code"], invoiceCode: parsedJson["invoice_code"],
invoiceNumber: parsedJson["invoice_no"], invoiceNumber: parsedJson["invoice_no"],
jobSheetNumber: parsedJson["job_sheet_no"], jobSheetNumber: parsedJson["job_sheet_no"],
@ -134,15 +133,12 @@ class ServiceReport {
travelingHours: parsedJson["traveling_hours"], travelingHours: parsedJson["traveling_hours"],
visitDate: getDate(parsedJson["visit_date"]), visitDate: getDate(parsedJson["visit_date"]),
//workHours: parsedJson["working_hours"], //workHours: parsedJson["working_hours"],
timer: TimerModel( timer: TimerModel(durationInSecond: (int.tryParse(parsedJson["working_hours"] ?? "") ?? 0) * 60 * 60),
durationInSecond: (int.tryParse(parsedJson["working_hours"] ?? "") ?? 0) * 60 *60),
workPreformed: parsedJson["work_performed"], workPreformed: parsedJson["work_performed"],
device: parsedJson["eq_nid"] == null ? null : Device(id: parsedJson["eq_nid"],serialNumber: parsedJson["eq_serial"]) device: parsedJson["eq_nid"] == null ? null : Device(id: parsedJson["eq_nid"], serialNumber: parsedJson["eq_serial"]));
);
} }
static getDate(String date){ static getDate(String date) {
return date == null || date.isEmpty return date == null || date.isEmpty ? null : DateTime.fromMillisecondsSinceEpoch((int.tryParse(date) ?? 0) * 1000);
? null : DateTime.fromMillisecondsSinceEpoch((int.tryParse(date)??0) * 1000);
} }
} }

@ -70,12 +70,8 @@ class ServiceRequest {
deviceNumber: parsedJson["device_no"], deviceNumber: parsedJson["device_no"],
deviceId: parsedJson["deviceid"], deviceId: parsedJson["deviceid"],
audio: parsedJson["audio"] ?? "", audio: parsedJson["audio"] ?? "",
deviceArName: parsedJson["equipment_arabic_name"] == false deviceArName: parsedJson["equipment_arabic_name"] == false ? "No Name found" : parsedJson["equipment_arabic_name"],
? "No Name found" deviceEnName: parsedJson["equipment_english_name"] == false ? "No Name found" : parsedJson["equipment_english_name"],
: parsedJson["equipment_arabic_name"],
deviceEnName: parsedJson["equipment_english_name"] == false
? "No Name found"
: parsedJson["equipment_english_name"],
devicePhotos: List<String>.from(parsedJson["image"]), devicePhotos: List<String>.from(parsedJson["image"]),
deviceSerialNumber: parsedJson["call_sn"], deviceSerialNumber: parsedJson["call_sn"],
date: parsedJson["call_data"], date: parsedJson["call_data"],
@ -85,9 +81,7 @@ class ServiceRequest {
departmentName: parsedJson["department_name"], departmentName: parsedJson["department_name"],
engineerName: parsedJson["employee_name"], engineerName: parsedJson["employee_name"],
hospitalId: parsedJson["client"], hospitalId: parsedJson["client"],
reportID: parsedJson["service_report_nid"] is String reportID: parsedJson["service_report_nid"] is String ? parsedJson["service_report_nid"] : null,
? parsedJson["service_report_nid"]
: null,
viewReport: parsedJson["service_report_nid"] is bool ? false : true, viewReport: parsedJson["service_report_nid"] is bool ? false : true,
deviceModel: parsedJson["device_model"], deviceModel: parsedJson["device_model"],
engineerMobile: parsedJson["engineer_mobile"], engineerMobile: parsedJson["engineer_mobile"],

@ -22,8 +22,7 @@ class ServiceRequestSearch {
String toSearchString() { String toSearchString() {
String search = ""; String search = "";
if (deviceSerialNumber != null && if (deviceSerialNumber != null && (deviceSerialNumber?.isNotEmpty ?? false)) {
(deviceSerialNumber?.isNotEmpty ?? false)) {
search += "&sn_id=$deviceSerialNumber"; search += "&sn_id=$deviceSerialNumber";
} }

@ -1,6 +1,4 @@
import 'package:meta/meta.dart'; class Subtitle {
class Subtitle{
// http requests status messages // http requests status messages
String currentlyServiceNotAvailable; String currentlyServiceNotAvailable;
String waitUntilYourRequestComplete; String waitUntilYourRequestComplete;
@ -216,7 +214,7 @@ class Subtitle{
String duplicateAlertMessage; String duplicateAlertMessage;
String alert; String alert;
void setIssues(List<String> issues){ void setIssues(List<String> issues) {
issues.clear(); issues.clear();
issues.add(reason1); issues.add(reason1);
issues.add(reason2); issues.add(reason2);
@ -278,7 +276,6 @@ class Subtitle{
required this.titleValidateMessage, required this.titleValidateMessage,
required this.to, required this.to,
required this.urlNotFound, required this.urlNotFound,
required this.nameExist, required this.nameExist,
required this.unitRequired, required this.unitRequired,
required this.unite, required this.unite,
@ -384,7 +381,6 @@ class Subtitle{
required this.pickImage, required this.pickImage,
required this.requiredImage, required this.requiredImage,
required this.activationAlert, required this.activationAlert,
required this.callId, required this.callId,
required this.requiredWord, required this.requiredWord,
required this.quantity, required this.quantity,
@ -409,7 +405,7 @@ class Subtitle{
required this.duplicateRequest, required this.duplicateRequest,
}); });
factory Subtitle.fromJson(Map<String,dynamic> parsedJson){ factory Subtitle.fromJson(Map<String, dynamic> parsedJson) {
return Subtitle( return Subtitle(
currentlyServiceNotAvailable: parsedJson["server_error_message"], currentlyServiceNotAvailable: parsedJson["server_error_message"],
failedToCompleteRequest: parsedJson["failed_request_message"], failedToCompleteRequest: parsedJson["failed_request_message"],
@ -423,7 +419,6 @@ class Subtitle{
signOut: parsedJson["sign_out"], signOut: parsedJson["sign_out"],
signOutAlert: parsedJson["logout_alert"], signOutAlert: parsedJson["logout_alert"],
language: parsedJson["language"], language: parsedJson["language"],
name: parsedJson["name"], name: parsedJson["name"],
email: parsedJson["email"], email: parsedJson["email"],
phoneNumber: parsedJson["phone_number"], phoneNumber: parsedJson["phone_number"],
@ -437,7 +432,6 @@ class Subtitle{
passwordValidateMessage: parsedJson["password_validate_message"], passwordValidateMessage: parsedJson["password_validate_message"],
confirmPasswordValidateMessage: parsedJson["confirm_password_validate_message"], confirmPasswordValidateMessage: parsedJson["confirm_password_validate_message"],
phoneNumberValidateMessage: parsedJson["phone_number_validate_message"], phoneNumberValidateMessage: parsedJson["phone_number_validate_message"],
forgetPasswordWithMark: parsedJson["forget_password_with_mark"], forgetPasswordWithMark: parsedJson["forget_password_with_mark"],
showPassword: parsedJson["show_password"], showPassword: parsedJson["show_password"],
wrongEmailOrPassword: parsedJson["wrong_email_or_password"], wrongEmailOrPassword: parsedJson["wrong_email_or_password"],
@ -447,7 +441,6 @@ class Subtitle{
back: parsedJson["back"], back: parsedJson["back"],
search: parsedJson["search"], search: parsedJson["search"],
searchByName: parsedJson["search_by_name"], searchByName: parsedJson["search_by_name"],
address: parsedJson["address"], address: parsedJson["address"],
addressNotFound: parsedJson["address_not_found"], addressNotFound: parsedJson["address_not_found"],
addressValidateMessage: parsedJson["address_validate_message"], addressValidateMessage: parsedJson["address_validate_message"],
@ -466,7 +459,6 @@ class Subtitle{
titleNotFound: parsedJson["title_not_found"], titleNotFound: parsedJson["title_not_found"],
titleValidateMessage: parsedJson["title_validate_message"], titleValidateMessage: parsedJson["title_validate_message"],
urlNotFound: parsedJson["url_not_found"], urlNotFound: parsedJson["url_not_found"],
date: parsedJson["date"], date: parsedJson["date"],
status: parsedJson["status"], status: parsedJson["status"],
code: parsedJson["code"], code: parsedJson["code"],
@ -542,7 +534,6 @@ class Subtitle{
visitDate: parsedJson["visitDate"], visitDate: parsedJson["visitDate"],
whatsApp: parsedJson["whatsApp"], whatsApp: parsedJson["whatsApp"],
workPerformed: parsedJson["workPerformed"], workPerformed: parsedJson["workPerformed"],
actualDate: parsedJson["actualDate"], actualDate: parsedJson["actualDate"],
done: parsedJson["done"], done: parsedJson["done"],
expectDate: parsedJson["expectDate"], expectDate: parsedJson["expectDate"],
@ -573,7 +564,6 @@ class Subtitle{
requiredImage: parsedJson["requiredImage"], requiredImage: parsedJson["requiredImage"],
taskStatus: parsedJson["taskStatus"], taskStatus: parsedJson["taskStatus"],
activationAlert: parsedJson["activationAlert"], activationAlert: parsedJson["activationAlert"],
attachImage: parsedJson["attachImage"], attachImage: parsedJson["attachImage"],
callLastSituation: parsedJson["callLastSituation"], callLastSituation: parsedJson["callLastSituation"],
customer: parsedJson["customer"], customer: parsedJson["customer"],
@ -592,12 +582,10 @@ class Subtitle{
requiredWord: parsedJson["requiredWord"], requiredWord: parsedJson["requiredWord"],
serviceType: parsedJson["serviceType"], serviceType: parsedJson["serviceType"],
workPreformed: parsedJson["workPreformed"], workPreformed: parsedJson["workPreformed"],
alert: parsedJson["alert"], alert: parsedJson["alert"],
duplicateAlert: parsedJson["duplicateAlert"], duplicateAlert: parsedJson["duplicateAlert"],
duplicateAlertMessage: parsedJson["duplicateAlertMessage"], duplicateAlertMessage: parsedJson["duplicateAlertMessage"],
duplicateRequest: parsedJson["duplicateRequest"], duplicateRequest: parsedJson["duplicateRequest"],
); );
} }
} }

@ -3,5 +3,5 @@ class TimerModel {
DateTime? endAt; DateTime? endAt;
int? durationInSecond; int? durationInSecond;
TimerModel({this.startAt,this.endAt,this.durationInSecond}); TimerModel({this.startAt, this.endAt, this.durationInSecond});
} }

@ -1,5 +1,3 @@
import '../controllers/notification/firebase_notification_manger.dart'; import '../controllers/notification/firebase_notification_manger.dart';
import 'department.dart'; import 'department.dart';
import 'enums/user_types.dart'; import 'enums/user_types.dart';
@ -19,34 +17,22 @@ class User {
String? token; String? token;
bool isActive; bool isActive;
User( User({this.id, this.userName = "", this.email = "", this.password = "", this.phoneNumber, this.hospital, this.image, this.department, this.type, this.whatsApp, this.token, this.isActive = false});
{this.id,
this.userName = "",
this.email = "",
this.password = "",
this.phoneNumber,
this.hospital,
this.image,
this.department,
this.type,
this.whatsApp,
this.token,
this.isActive = false});
Future<Map<String, dynamic>> toLoginJson() async { Future<Map<String, dynamic>> toLoginJson() async {
if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken(); if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken();
return { return {
"username": userName, "username": userName,
"pass": password, "pass": password,
"firebase_token": FirebaseNotificationManger?.token ?? "", "firebase_token": FirebaseNotificationManger.token ?? "",
}; };
} }
Map<String, dynamic> toUpdateProfileJson() { Map<String, dynamic> toUpdateProfileJson() {
Map<String, dynamic> jsonObject = {}; Map<String, dynamic> jsonObject = {};
if (department?.id != null && (department?.id?.isNotEmpty??false)) jsonObject["department"] = department?.id??""; if (department?.id != null && (department?.id?.isNotEmpty ?? false)) jsonObject["department"] = department?.id ?? "";
if (whatsApp != null && (whatsApp?.isNotEmpty??false)) jsonObject["whatsapp"] = whatsApp; if (whatsApp != null && (whatsApp?.isNotEmpty ?? false)) jsonObject["whatsapp"] = whatsApp;
if (phoneNumber != null && (phoneNumber?.isNotEmpty??false)) jsonObject["phone"] = phoneNumber; if (phoneNumber != null && (phoneNumber?.isNotEmpty ?? false)) jsonObject["phone"] = phoneNumber;
return jsonObject; return jsonObject;
} }
@ -60,7 +46,7 @@ class User {
"department": department?.id, "department": department?.id,
"phone": phoneNumber, "phone": phoneNumber,
"pass": password, "pass": password,
"firebase_token": FirebaseNotificationManger?.token ?? "", "firebase_token": FirebaseNotificationManger.token ?? "",
}; };
} }

@ -1,10 +1,7 @@
import '../lookup.dart'; import '../lookup.dart';
import 'visit.dart'; import 'visit.dart';
class VisitsGroup{ class VisitsGroup {
String? userId; String? userId;
String? workingHours; String? workingHours;
String? travelingHours; String? travelingHours;
@ -27,24 +24,22 @@ class VisitsGroup{
this.taskStatus, this.taskStatus,
}); });
Map<String,String> toJson(){ Map<String, String> toJson() {
Map<String,String> jsonObject = {}; Map<String, String> jsonObject = {};
jsonObject["nids"] = visits!.map((e) => e.id).toList().join(','); jsonObject["nids"] = visits!.map((e) => e.id).toList().join(',');
if(status != null) jsonObject["status"] = status?.id.toString()??""; if (status != null) jsonObject["status"] = status?.id.toString() ?? "";
if(date != null) jsonObject["date"] = date.toString().split(" ").first; if (date != null) jsonObject["date"] = date.toString().split(" ").first;
if(jobSheetNumber != null && (jobSheetNumber?.isNotEmpty??false)) { if (jobSheetNumber != null && (jobSheetNumber?.isNotEmpty ?? false)) {
jsonObject["job_sheet_no"] = jobSheetNumber!; jsonObject["job_sheet_no"] = jobSheetNumber!;
} }
if(travelingHours != null &&(travelingHours?.isNotEmpty??false)) { if (travelingHours != null && (travelingHours?.isNotEmpty ?? false)) {
jsonObject["traveling_hours"] = travelingHours??""; jsonObject["traveling_hours"] = travelingHours ?? "";
} }
if(workingHours != null && (workingHours?.isNotEmpty??false)) { if (workingHours != null && (workingHours?.isNotEmpty ?? false)) {
jsonObject["working_hours"] = workingHours??""; jsonObject["working_hours"] = workingHours ?? "";
} }
if(image != null) jsonObject["image"] = image??""; if (image != null) jsonObject["image"] = image ?? "";
if(taskStatus != null) jsonObject["task_status"] = taskStatus?.id.toString()??""; if (taskStatus != null) jsonObject["task_status"] = taskStatus?.id.toString() ?? "";
return jsonObject; return jsonObject;
} }
} }

@ -1,4 +1,4 @@
class VisitsSearch{ class VisitsSearch {
String? deviceSerialNumber; String? deviceSerialNumber;
String? hospitalName; String? hospitalName;
String? brand; String? brand;
@ -23,7 +23,7 @@ class VisitsSearch{
this.expectedDateTo, this.expectedDateTo,
}); });
fromSearch(VisitsSearch newSearch){ fromSearch(VisitsSearch newSearch) {
deviceSerialNumber = newSearch.deviceSerialNumber; deviceSerialNumber = newSearch.deviceSerialNumber;
brand = newSearch.brand; brand = newSearch.brand;
hospitalName = newSearch.hospitalName; hospitalName = newSearch.hospitalName;
@ -36,48 +36,47 @@ class VisitsSearch{
statusValue = newSearch.statusValue; statusValue = newSearch.statusValue;
} }
String toSearchString(){ String toSearchString() {
String _search = ""; String _search = "";
if(deviceSerialNumber != null && (deviceSerialNumber?.isNotEmpty??false)){ if (deviceSerialNumber != null && (deviceSerialNumber?.isNotEmpty ?? false)) {
_search += "&sn_id=$deviceSerialNumber"; _search += "&sn_id=$deviceSerialNumber";
} }
if(hospitalName != null && (hospitalName?.isNotEmpty??false)){ if (hospitalName != null && (hospitalName?.isNotEmpty ?? false)) {
_search += "&client=$hospitalName"; _search += "&client=$hospitalName";
} }
if(brand != null && (brand?.isNotEmpty??false)){ if (brand != null && (brand?.isNotEmpty ?? false)) {
_search += "&brand=$brand"; _search += "&brand=$brand";
} }
if(model != null && (model?.isNotEmpty??false)){ if (model != null && (model?.isNotEmpty ?? false)) {
_search += "&model=$model"; _search += "&model=$model";
} }
if(expectedDateFrom != null){ if (expectedDateFrom != null) {
_search += "&expected_date_from=${(expectedDateFrom?.millisecondsSinceEpoch??0) ~/ 1000}"; _search += "&expected_date_from=${(expectedDateFrom?.millisecondsSinceEpoch ?? 0) ~/ 1000}";
} }
if(expectedDateTo != null){ if (expectedDateTo != null) {
_search += "&expected_date_to=${(expectedDateTo?.millisecondsSinceEpoch??0) ~/1000}"; _search += "&expected_date_to=${(expectedDateTo?.millisecondsSinceEpoch ?? 0) ~/ 1000}";
} }
if(actualDateFrom != null){ if (actualDateFrom != null) {
_search += "&actual_date_from=${(actualDateFrom?.millisecondsSinceEpoch??0) ~/ 1000}"; _search += "&actual_date_from=${(actualDateFrom?.millisecondsSinceEpoch ?? 0) ~/ 1000}";
} }
if(actualDateTo != null){ if (actualDateTo != null) {
_search += "&actual_date_to=${(actualDateTo?.millisecondsSinceEpoch??0) ~/1000}"; _search += "&actual_date_to=${(actualDateTo?.millisecondsSinceEpoch ?? 0) ~/ 1000}";
} }
if(statusValue != null){ if (statusValue != null) {
_search += "&status=$statusValue"; _search += "&status=$statusValue";
} }
if(contactStatus != null){ if (contactStatus != null) {
_search += "&assigned_to=$contactStatus"; _search += "&assigned_to=$contactStatus";
} }
return _search; return _search;
} }
} }

@ -20,23 +20,31 @@ class AColors {
static Color inputFieldBackgroundColor = Color(0xfff5f5f5); static Color inputFieldBackgroundColor = Color(0xfff5f5f5);
static Color greyEF = Color(0xffEFEFEF); static Color greyEF = Color(0xffEFEFEF);
static Color getRequestStatusColor(int id){ static Color getRequestStatusColor(int id) {
switch(id){ switch (id) {
case 4: return AColors.deepRed; case 4:
case 6: return AColors.green; return AColors.deepRed;
case 5: return AColors.orange; case 6:
case 8: return AColors.green; return AColors.green;
case 9: return AColors.orange; case 5:
default : return AColors.grey; return AColors.orange;
case 8:
return AColors.green;
case 9:
return AColors.orange;
default:
return AColors.grey;
} }
} }
static Color getGasStatusColor(int id){ static Color getGasStatusColor(int id) {
switch(id){ switch (id) {
case 0: return AColors.orange; case 0:
case 1: return AColors.green; return AColors.orange;
default : return AColors.grey; case 1:
return AColors.green;
default:
return AColors.grey;
} }
} }
} }

@ -1,39 +1,31 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class AppStyle { class AppStyle {
AppStyle._(); AppStyle._();
static const double borderRadius = 10; static const double borderRadius = 10;
static const BoxShadow boxShadow = BoxShadow( static const BoxShadow boxShadow = BoxShadow(color: Colors.black26, blurRadius: 3, offset: Offset(0, 2));
color: Colors.black26,
blurRadius: 3,
offset: Offset(0,2)
);
static double getBorderRadius(BuildContext context){ static double getBorderRadius(BuildContext context) {
return borderRadius * getScaleFactor(context); return borderRadius * getScaleFactor(context);
} }
static double getScaleFactor(BuildContext context){ static double getScaleFactor(BuildContext context) {
return MediaQuery.of(context).orientation == Orientation.portrait return MediaQuery.of(context).orientation == Orientation.portrait
? MediaQuery.of(context).size.width/(360) > 1.5 ? MediaQuery.of(context).size.width / (360) > 1.5
? 1.5 : MediaQuery.of(context).size.width/(360) ? 1.5
: MediaQuery.of(context).size.height/(360) > 1.5 : MediaQuery.of(context).size.width / (360)
? 1.5 : MediaQuery.of(context).size.height/(360); : MediaQuery.of(context).size.height / (360) > 1.5
? 1.5
: MediaQuery.of(context).size.height / (360);
} }
static BorderRadius getCardBorder(BuildContext context){ static BorderRadius getCardBorder(BuildContext context) {
return BorderRadius.only( return BorderRadius.only(
topRight: Radius.circular( topRight: Radius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
AppStyle.borderRadius * AppStyle.getScaleFactor(context) topLeft: Radius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
), bottomRight: Radius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
topLeft: Radius.circular(
AppStyle.borderRadius * AppStyle.getScaleFactor(context)
),
bottomRight: Radius.circular(
AppStyle.borderRadius * AppStyle.getScaleFactor(context)
),
); );
} }
} }

@ -1,9 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../api/user_api_client.dart';
import '../../../controllers/localization/localization.dart'; import '../../../controllers/localization/localization.dart';
import '../../../controllers/providers/api/device_transfer_provider.dart'; import '../../../controllers/providers/api/device_transfer_provider.dart';
import '../../../controllers/providers/api/user_provider.dart';
import '../../../controllers/providers/settings/setting_provider.dart'; import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../controllers/providers/user_provider.dart';
import '../../../models/device/device_transfer.dart'; import '../../../models/device/device_transfer.dart';
import '../../../models/device/device_transfer_info.dart'; import '../../../models/device/device_transfer_info.dart';
import '../../../models/subtitle.dart'; import '../../../models/subtitle.dart';
@ -25,7 +27,6 @@ class DeviceTransferDetails extends StatefulWidget {
} }
class _DeviceTransferDetailsState extends State<DeviceTransferDetails> { class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
final DeviceTransferInfo _model = DeviceTransferInfo(); final DeviceTransferInfo _model = DeviceTransferInfo();
bool _isSender = false; bool _isSender = false;
bool _isReceiver = false; bool _isReceiver = false;
@ -48,8 +49,8 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
_userProvider = Provider.of<UserProvider>(context); _userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context); _settingProvider = Provider.of<SettingProvider>(context);
_deviceTransferProvider = Provider.of<DeviceTransferProvider>(context); _deviceTransferProvider = Provider.of<DeviceTransferProvider>(context);
_isSender = _userProvider?.user?.id == widget.model.sender?.userId; _isSender = UserApiClient().user?.id == widget.model.sender?.userId;
_isReceiver = _userProvider?.user?.id == widget.model.receiver?.userId; _isReceiver = UserApiClient().user?.id == widget.model.receiver?.userId;
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
body: SafeArea( body: SafeArea(
@ -64,18 +65,15 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
children: [ children: [
Container( Container(
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
child: Row( child: Row(
children: [ children: [
ABackButton(), ABackButton(),
Expanded( Expanded(
child: Center( child: Center(
child: Text( child: Text(
_subtitle?.details??"", _subtitle?.details ?? "",
style: Theme.of(context).textTheme.headline6?.copyWith( style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
color: AColors.white,
fontStyle: FontStyle.italic
),
), ),
), ),
), ),
@ -85,7 +83,7 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
), ),
Expanded( Expanded(
child: SingleChildScrollView( child: SingleChildScrollView(
padding: EdgeInsets.all(16*AppStyle.getScaleFactor(context)), padding: EdgeInsets.all(16 * AppStyle.getScaleFactor(context)),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -97,59 +95,52 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
title: _subtitle?.device, title: _subtitle?.device,
info: widget.model.device?.serialNumber, info: widget.model.device?.serialNumber,
), ),
const SizedBox(height:8), const SizedBox(height: 8),
Row( Row(
children: [ children: [
Expanded( Expanded(
child: Text( child: Text("Sender", style: Theme.of(context).textTheme.headline6),
"Sender",
style: Theme.of(context).textTheme.headline6
),
), ),
if(_isSender) if (_isSender)
ASmallButton( ASmallButton(
text: _subtitle?.edit??"", text: _subtitle?.edit ?? "",
onPressed: (){ onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(MaterialPageRoute(
MaterialPageRoute( builder: (_) => UpdateDeviceTransfer(
builder: (_)=> UpdateDeviceTransfer(model: widget.model,isSender: _isSender,) model: widget.model,
) isSender: _isSender,
); )));
}, },
), ),
], ],
), ),
const SizedBox(height:12), const SizedBox(height: 12),
DeviceTransferInfoSection( DeviceTransferInfoSection(
info: widget.model.sender!, info: widget.model.sender!,
), ),
const SizedBox(height:8), const SizedBox(height: 8),
Row( Row(
children: [ children: [
Expanded( Expanded(
child: Text( child: Text("Receiver", style: Theme.of(context).textTheme.headline6),
"Receiver",
style: Theme.of(context).textTheme.headline6
),
), ),
if(_isReceiver) if (_isReceiver)
ASmallButton( ASmallButton(
text: _subtitle?.edit??"", text: _subtitle?.edit ?? "",
onPressed: (){ onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(MaterialPageRoute(
MaterialPageRoute( builder: (_) => UpdateDeviceTransfer(
builder: (_)=> UpdateDeviceTransfer(model: widget.model,isSender: _isSender,) model: widget.model,
) isSender: _isSender,
); )));
}, },
), ),
], ],
), ),
const SizedBox(height:12), const SizedBox(height: 12),
DeviceTransferInfoSection( DeviceTransferInfoSection(
info: widget.model.receiver!, info: widget.model.receiver!,
), ),
], ],
), ),
), ),

@ -3,11 +3,12 @@ import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/hospital.dart';
import '../../../api/user_api_client.dart';
import '../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../controllers/localization/localization.dart'; import '../../../controllers/localization/localization.dart';
import '../../../controllers/providers/api/device_transfer_provider.dart'; import '../../../controllers/providers/api/device_transfer_provider.dart';
import '../../../controllers/providers/api/user_provider.dart';
import '../../../controllers/providers/settings/setting_provider.dart'; import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../controllers/providers/user_provider.dart';
import '../../../extensions/int_extensions.dart'; import '../../../extensions/int_extensions.dart';
import '../../../models/device/device_transfer.dart'; import '../../../models/device/device_transfer.dart';
import '../../../models/device/device_transfer_info.dart'; import '../../../models/device/device_transfer_info.dart';
@ -35,10 +36,8 @@ class _RequestDeviceTransferState extends State<RequestDeviceTransfer> {
UserProvider? _userProvider; UserProvider? _userProvider;
SettingProvider? _settingProvider; SettingProvider? _settingProvider;
DeviceTransferProvider? _deviceTransferProvider; DeviceTransferProvider? _deviceTransferProvider;
final TextEditingController _requestedQuantityController = final TextEditingController _requestedQuantityController = TextEditingController();
TextEditingController(); final DeviceTransfer _formModel = DeviceTransfer(receiver: DeviceTransferInfo());
final DeviceTransfer _formModel =
DeviceTransfer(receiver: DeviceTransferInfo());
final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@ -64,7 +63,7 @@ class _RequestDeviceTransferState extends State<RequestDeviceTransfer> {
setState(() {}); setState(() {});
int? status = await _deviceTransferProvider?.createRequest( int? status = await _deviceTransferProvider?.createRequest(
user: _userProvider?.user, user: UserApiClient().user,
host: _settingProvider?.host ?? "", host: _settingProvider?.host ?? "",
model: _formModel, model: _formModel,
); );
@ -76,8 +75,7 @@ class _RequestDeviceTransferState extends State<RequestDeviceTransfer> {
); );
Navigator.of(context).pop(); Navigator.of(context).pop();
} else { } else {
String errorMessage = HttpStatusManger.getStatusMessage( String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle);
status: status, subtitle: _subtitle);
ScaffoldMessenger.of(context).showSnackBar(SnackBar( ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(errorMessage), content: Text(errorMessage),
)); ));
@ -95,8 +93,7 @@ class _RequestDeviceTransferState extends State<RequestDeviceTransfer> {
_subtitle = AppLocalization.of(context)?.subtitle; _subtitle = AppLocalization.of(context)?.subtitle;
_userProvider = Provider.of<UserProvider>(context); _userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context); _settingProvider = Provider.of<SettingProvider>(context);
_deviceTransferProvider = _deviceTransferProvider = Provider.of<DeviceTransferProvider>(context, listen: false);
Provider.of<DeviceTransferProvider>(context, listen: false);
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
body: Form( body: Form(
@ -117,10 +114,7 @@ class _RequestDeviceTransferState extends State<RequestDeviceTransfer> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
"Transfer Device", "Transfer Device",
style: Theme.of(context).textTheme.headline5?.copyWith( style: Theme.of(context).textTheme.headline5?.copyWith(color: Theme.of(context).primaryColor, fontSize: 28, fontWeight: FontWeight.bold),
color: Theme.of(context).primaryColor,
fontSize: 28,
fontWeight: FontWeight.bold),
), ),
), ),
), ),
@ -174,7 +168,7 @@ class _RequestDeviceTransferState extends State<RequestDeviceTransfer> {
), ),
6.height, 6.height,
HospitalButton( HospitalButton(
hospital: _formModel.receiver?.client??Hospital(), hospital: _formModel.receiver?.client ?? Hospital(),
onHospitalPick: (hospital) { onHospitalPick: (hospital) {
_formModel.receiver?.client = hospital; _formModel.receiver?.client = hospital;
setState(() {}); setState(() {});

@ -1,10 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../api/user_api_client.dart';
import '../../../controllers/localization/localization.dart'; import '../../../controllers/localization/localization.dart';
import '../../../controllers/providers/api/device_transfer_provider.dart'; import '../../../controllers/providers/api/device_transfer_provider.dart';
import '../../../controllers/providers/api/user_provider.dart';
import '../../../controllers/providers/settings/setting_provider.dart'; import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../controllers/providers/user_provider.dart';
import '../../../models/subtitle.dart'; import '../../../models/subtitle.dart';
import '../../../models/user.dart'; import '../../../models/user.dart';
import '../../app_style/colors.dart'; import '../../app_style/colors.dart';
@ -21,8 +22,7 @@ class TrackDeviceTransferPage extends StatefulWidget {
State<TrackDeviceTransferPage> createState() => _TrackDeviceTransferPageState(); State<TrackDeviceTransferPage> createState() => _TrackDeviceTransferPageState();
} }
class _TrackDeviceTransferPageState extends State<TrackDeviceTransferPage> class _TrackDeviceTransferPageState extends State<TrackDeviceTransferPage> with TickerProviderStateMixin {
with TickerProviderStateMixin{
late DeviceTransferProvider _deviceTransferProvider; late DeviceTransferProvider _deviceTransferProvider;
UserProvider? _userProvider; UserProvider? _userProvider;
late SettingProvider _settingProvider; late SettingProvider _settingProvider;
@ -43,8 +43,8 @@ class _TrackDeviceTransferPageState extends State<TrackDeviceTransferPage>
onRefresh: () async { onRefresh: () async {
_deviceTransferProvider.reset(); _deviceTransferProvider.reset();
await _deviceTransferProvider.getRequests( await _deviceTransferProvider.getRequests(
user: _userProvider?.user??User(), user: UserApiClient().user ?? User(),
host: _settingProvider.host??"", host: _settingProvider.host ?? "",
); );
}, },
child: Stack( child: Stack(
@ -52,8 +52,8 @@ class _TrackDeviceTransferPageState extends State<TrackDeviceTransferPage>
Column( Column(
children: [ children: [
Container( Container(
color:AColors.primaryColor, color: AColors.primaryColor,
padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
child: Column( child: Column(
children: [ children: [
Row( Row(
@ -63,17 +63,15 @@ class _TrackDeviceTransferPageState extends State<TrackDeviceTransferPage>
child: Center( child: Center(
child: Text( child: Text(
"Device Transfer", "Device Transfer",
style: Theme.of(context).textTheme.headline6?.copyWith( style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
color: AColors.white,
fontStyle: FontStyle.italic
), ),
), ),
), ),
), const SizedBox(
const SizedBox(width: 48,) width: 48,
)
], ],
), ),
], ],
), ),
), ),
@ -82,8 +80,8 @@ class _TrackDeviceTransferPageState extends State<TrackDeviceTransferPage>
nextPage: _deviceTransferProvider.nextPage, nextPage: _deviceTransferProvider.nextPage,
onLazyLoad: () async { onLazyLoad: () async {
await _deviceTransferProvider.getRequests( await _deviceTransferProvider.getRequests(
user: _userProvider?.user??User(), user: UserApiClient().user ?? User(),
host: _settingProvider.host??"", host: _settingProvider.host ?? "",
); );
}, },
items: _deviceTransferProvider.items, items: _deviceTransferProvider.items,

@ -5,11 +5,12 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../api/user_api_client.dart';
import '../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../controllers/localization/localization.dart'; import '../../../controllers/localization/localization.dart';
import '../../../controllers/providers/api/device_transfer_provider.dart'; import '../../../controllers/providers/api/device_transfer_provider.dart';
import '../../../controllers/providers/api/user_provider.dart';
import '../../../controllers/providers/settings/setting_provider.dart'; import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../controllers/providers/user_provider.dart';
import '../../../models/device/device_transfer.dart'; import '../../../models/device/device_transfer.dart';
import '../../../models/device/device_transfer_info.dart'; import '../../../models/device/device_transfer_info.dart';
import '../../../models/subtitle.dart'; import '../../../models/subtitle.dart';
@ -46,54 +47,41 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
_update() async { _update() async {
_validate = true; _validate = true;
if((_formKey.currentState?.validate()??false)){ if ((_formKey.currentState?.validate() ?? false)) {
setState(() {}); setState(() {});
return false; return false;
} }
_formKey.currentState?.save(); _formKey.currentState?.save();
_isLoading =true; _isLoading = true;
setState(() {}); setState(() {});
int? status = await _deviceTransferProvider?.updateRequest( int? status = await _deviceTransferProvider?.updateRequest(
user: _userProvider?.user??User(), user: UserApiClient().user ?? User(), host: _settingProvider?.host ?? "", requestId: widget.model?.id ?? "", isSender: widget.isSender ?? false, newModel: _formModel, oldModel: widget.model);
host: _settingProvider?.host??"", _isLoading = false;
requestId: widget.model?.id??"",
isSender: widget.isSender??false,
newModel: _formModel,
oldModel: widget.model
);
_isLoading =false;
setState(() {}); setState(() {});
if(status!=null && status >= 200 && status < 300){ if (status != null && status >= 200 && status < 300) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: _subtitle?.requestCompleteSuccessfully??"", msg: _subtitle?.requestCompleteSuccessfully ?? "",
); );
_validate = false; _validate = false;
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.of(context).pop(); Navigator.of(context).pop();
}else{ } else {
String errorMessage = HttpStatusManger.getStatusMessage( String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle);
status: status, subtitle: _subtitle); ScaffoldMessenger.of(context).showSnackBar(SnackBar(
ScaffoldMessenger.of(context).showSnackBar( content: Text(errorMessage),
SnackBar( ));
content: Text(
errorMessage
),
)
);
} }
} }
@override @override
void setState(VoidCallback fn){ void setState(VoidCallback fn) {
if(mounted) super.setState(() {}); if (mounted) super.setState(() {});
} }
@override @override
void initState() { void initState() {
_formModel.fromDetails((widget.isSender??false) ? widget.model?.sender : widget.model?.receiver, _formModel.fromDetails((widget.isSender ?? false) ? widget.model?.sender : widget.model?.receiver, withSignature: false);
withSignature: false
);
super.initState(); super.initState();
} }
@ -108,7 +96,7 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
_subtitle = AppLocalization.of(context)?.subtitle; _subtitle = AppLocalization.of(context)?.subtitle;
_userProvider = Provider.of<UserProvider>(context); _userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context); _settingProvider = Provider.of<SettingProvider>(context);
_deviceTransferProvider = Provider.of<DeviceTransferProvider>(context,listen: false); _deviceTransferProvider = Provider.of<DeviceTransferProvider>(context, listen: false);
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
body: Form( body: Form(
@ -129,72 +117,86 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
"Edit Transfer Device", "Edit Transfer Device",
style: Theme.of(context).textTheme.headline5?.copyWith( style: Theme.of(context).textTheme.headline5?.copyWith(color: Theme.of(context).primaryColor, fontSize: 28, fontWeight: FontWeight.bold),
color: Theme.of(context).primaryColor,
fontSize: 28,
fontWeight: FontWeight.bold
), ),
), ),
), ),
const SizedBox(
height: 8,
), ),
const SizedBox(height: 8,),
ASubTitle("Comment"), ASubTitle("Comment"),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _formModel.comment??"", initialValue: _formModel.comment ?? "",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
textInputType: TextInputType.text, textInputType: TextInputType.text,
onSaved: (value){ onSaved: (value) {
_formModel.comment = value; _formModel.comment = value;
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
ASubTitle(_subtitle?.travelingHours??""), height: 8,
const SizedBox(height: 4,), ),
ASubTitle(_subtitle?.travelingHours ?? ""),
const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _formModel.travelingHours??"", initialValue: _formModel.travelingHours ?? "",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
textInputType: TextInputType.number, textInputType: TextInputType.number,
onSaved: (value){ onSaved: (value) {
_formModel.travelingHours = value; _formModel.travelingHours = value;
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
ASubTitle(_subtitle?.workingHours??""), height: 8,
const SizedBox(height: 4,), ),
ASubTitle(_subtitle?.workingHours ?? ""),
const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _formModel.workingHours??"", initialValue: _formModel.workingHours ?? "",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
textInputType: TextInputType.number, textInputType: TextInputType.number,
onSaved: (value){ onSaved: (value) {
_formModel.workingHours = value; _formModel.workingHours = value;
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
ASubTitle(_subtitle?.status??""), height: 8,
const SizedBox(height: 4,), ),
ASubTitle(_subtitle?.status ?? ""),
const SizedBox(
height: 4,
),
GasStatusMenu( GasStatusMenu(
initialValue: _formModel.status, initialValue: _formModel.status,
onSelect: (status){ onSelect: (status) {
_formModel.status = status; _formModel.status = status;
setState(() {}); setState(() {});
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
const ASubTitle("Signature"), const ASubTitle("Signature"),
// if(_validate && _formModel.signature == null) // if(_validate && _formModel.signature == null)
// ASubTitle(_subtitle.requiredWord,color: Colors.red,), // ASubTitle(_subtitle.requiredWord,color: Colors.red,),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ESignature( ESignature(
oldSignature: (widget.isSender??false) oldSignature: (widget.isSender ?? false) ? widget.model?.sender?.signature : widget.model?.receiver?.signature,
? widget.model?.sender?.signature
: widget.model?.receiver?.signature,
newSignature: _signature, newSignature: _signature,
onSaved: (signature){ onSaved: (signature) {
_signature = signature; _signature = signature;
_formModel.signature = base64Encode(signature); _formModel.signature = base64Encode(signature);
}, },
@ -202,11 +204,13 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
Padding( Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: AButton( child: AButton(
text: _subtitle?.update??"", text: _subtitle?.update ?? "",
onPressed: _update, onPressed: _update,
), ),
), ),
const SizedBox(height: 100,) const SizedBox(
height: 100,
)
], ],
), ),
), ),
@ -216,4 +220,3 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
); );
} }
} }

@ -1,11 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../controllers/http_status_manger/http_status_manger.dart';
import '../../controllers/localization/localization.dart'; import '../../controllers/localization/localization.dart';
import '../../controllers/providers/api/user_provider.dart';
import '../../controllers/providers/settings/setting_provider.dart'; import '../../controllers/providers/settings/setting_provider.dart';
import '../../controllers/providers/user_provider.dart';
import '../../controllers/validator/validator.dart'; import '../../controllers/validator/validator.dart';
import '../../models/subtitle.dart'; import '../../models/subtitle.dart';
import '../../models/user.dart'; import '../../models/user.dart';
@ -13,7 +11,6 @@ import '../app_style/sizing.dart';
import '../widgets/app_text_form_field.dart'; import '../widgets/app_text_form_field.dart';
import '../widgets/buttons/app_button.dart'; import '../widgets/buttons/app_button.dart';
import '../widgets/loaders/loading_manager.dart'; import '../widgets/loaders/loading_manager.dart';
import 'user/land_page.dart';
class Login extends StatefulWidget { class Login extends StatefulWidget {
static const String id = "/login"; static const String id = "/login";
@ -21,18 +18,16 @@ class Login extends StatefulWidget {
const Login({super.key}); const Login({super.key});
@override @override
_LoginState createState() => _LoginState(); LoginState createState() => LoginState();
} }
class _LoginState extends State<Login> { class LoginState extends State<Login> {
UserProvider? _userProvider; late UserProvider _userProvider;
SettingProvider? _settingProvider; late SettingProvider _settingProvider;
final User _user = User();
bool _obscurePassword = true; bool _obscurePassword = true;
final bool _firstTime = true;
late double _height; late double _height;
late double _width; final User _user = User();
late String _payload;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@ -41,14 +36,12 @@ class _LoginState extends State<Login> {
_userProvider = Provider.of<UserProvider>(context); _userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context); _settingProvider = Provider.of<SettingProvider>(context);
_height = MediaQuery.of(context).size.height; _height = MediaQuery.of(context).size.height;
_width = MediaQuery.of(context).size.width;
Subtitle? subtitle = AppLocalization.of(context)?.subtitle; Subtitle? subtitle = AppLocalization.of(context)?.subtitle;
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
body: SafeArea( body: SafeArea(
child: LoadingManager( child: LoadingManager(
isLoading: (_userProvider?.isLoading ?? false) || isLoading: (_userProvider.loading) || !(_settingProvider.isLoaded),
!(_settingProvider?.isLoaded ?? false),
isFailedLoading: false, isFailedLoading: false,
stateCode: 200, stateCode: 200,
onRefresh: () async {}, onRefresh: () async {},
@ -71,9 +64,7 @@ class _LoginState extends State<Login> {
), ),
), ),
Padding( Padding(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(horizontal: 24 * AppStyle.getScaleFactor(context), vertical: 24 * AppStyle.getScaleFactor(context)),
horizontal: 24 * AppStyle.getScaleFactor(context),
vertical: 24 * AppStyle.getScaleFactor(context)),
child: Column( child: Column(
children: [ children: [
SizedBox( SizedBox(
@ -85,12 +76,12 @@ class _LoginState extends State<Login> {
textAlign: TextAlign.left, textAlign: TextAlign.left,
style: Theme.of(context).textTheme.bodyLarge, style: Theme.of(context).textTheme.bodyLarge,
prefixIconData: Icons.account_circle, prefixIconData: Icons.account_circle,
validator: (value) => Validator.hasValue(value ?? '') validator: (value) => Validator.hasValue(value ?? '') ? null : subtitle?.nameValidateMessage,
? null
: subtitle?.nameValidateMessage,
textInputType: TextInputType.name, textInputType: TextInputType.name,
onSaved: (value) { onSaved: (value) {
_user.userName = value!; if (value != null) {
_user.userName = value;
}
}, },
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
@ -98,13 +89,10 @@ class _LoginState extends State<Login> {
initialValue: _user.password, initialValue: _user.password,
hintText: subtitle?.password ?? "", hintText: subtitle?.password ?? "",
obscureText: _obscurePassword, obscureText: _obscurePassword,
style: Theme.of(context).textTheme.bodyText1, style: Theme.of(context).textTheme.bodyLarge,
prefixIconData: Icons.vpn_key_sharp, prefixIconData: Icons.vpn_key_sharp,
textAlign: TextAlign.left, textAlign: TextAlign.left,
validator: (value) => validator: (value) => Validator.isValidPassword(value ?? '') ? null : subtitle?.passwordValidateMessage,
Validator.isValidPassword(value ?? '')
? null
: subtitle?.passwordValidateMessage,
showPassword: () { showPassword: () {
_obscurePassword = !_obscurePassword; _obscurePassword = !_obscurePassword;
setState(() {}); setState(() {});
@ -119,35 +107,9 @@ class _LoginState extends State<Login> {
AButton( AButton(
text: subtitle?.signIn ?? "", text: subtitle?.signIn ?? "",
onPressed: () async { onPressed: () async {
if (!(_formKey.currentState?.validate() ?? true)) { if (_formKey.currentState?.validate() ?? false) {
return;
}
_formKey.currentState?.save(); _formKey.currentState?.save();
int? status = await _userProvider?.login( await _userProvider.login(context, user: _user);
user: _user,
host: _settingProvider?.host ?? "",
);
if (status != null &&
status >= 200 &&
status < 300) {
_settingProvider
?.setUser(_userProvider?.user ?? User());
if (_userProvider?.user?.isActive ?? false) {
Navigator.of(context).pushNamed(LandPage.id);
} else {
Fluttertoast.showToast(
msg: subtitle?.activationAlert ?? "",
);
}
} else {
String errorMessage = status == 400
? subtitle?.wrongEmailOrPassword ?? ""
: HttpStatusManger.getStatusMessage(
status: status, subtitle: subtitle);
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
content: Text(errorMessage),
));
} }
}, },
), ),

@ -1,12 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../controllers/http_status_manger/http_status_manger.dart';
import '../../controllers/localization/localization.dart'; import '../../controllers/localization/localization.dart';
import '../../controllers/providers/api/user_provider.dart'; import '../../controllers/providers/user_provider.dart';
import '../../controllers/providers/settings/setting_provider.dart';
import '../../controllers/validator/validator.dart'; import '../../controllers/validator/validator.dart';
import '../../models/hospital.dart'; import '../../models/hospital.dart';
import '../../models/subtitle.dart'; import '../../models/subtitle.dart';
@ -18,20 +15,19 @@ import '../widgets/departments/department_button.dart';
import '../widgets/hospitals/hospital_button.dart'; import '../widgets/hospitals/hospital_button.dart';
import '../widgets/loaders/loading_manager.dart'; import '../widgets/loaders/loading_manager.dart';
class Register extends StatefulWidget { class Register extends StatefulWidget {
static final String id = "/register"; static const String id = "/register";
const Register({super.key});
@override @override
_RegisterState createState() => _RegisterState(); RegisterState createState() => RegisterState();
} }
class _RegisterState extends State<Register> { class RegisterState extends State<Register> {
UserProvider? _userProvider; late UserProvider _userProvider;
SettingProvider? _settingProvider;
late double _width;
late double _height; late double _height;
User _user = User(); final User _user = User();
bool _obscurePassword = true; bool _obscurePassword = true;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@ -39,14 +35,12 @@ class _RegisterState extends State<Register> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context); _userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_width = MediaQuery.of(context).size.width;
_height = MediaQuery.of(context).size.height; _height = MediaQuery.of(context).size.height;
Subtitle? _subtitle = AppLocalization.of(context)?.subtitle; Subtitle? subtitle = AppLocalization.of(context)?.subtitle;
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
body: LoadingManager( body: LoadingManager(
isLoading: _userProvider?.isLoading??false, isLoading: _userProvider.loading,
isFailedLoading: false, isFailedLoading: false,
stateCode: 200, stateCode: 200,
onRefresh: () async {}, onRefresh: () async {},
@ -66,16 +60,16 @@ class _RegisterState extends State<Register> {
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: Image( child: Image(
height: _height / 6, height: _height / 6,
image: AssetImage("assets/images/logo.png"), image: const AssetImage("assets/images/logo.png"),
), ),
), ),
), ),
ATextFormField( ATextFormField(
initialValue: _user.userName, initialValue: _user.userName,
hintText: _subtitle?.name??"", hintText: subtitle?.name ?? "",
prefixIconData: Icons.account_circle, prefixIconData: Icons.account_circle,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.titleLarge,
validator: (value) => Validator.hasValue(value!) ? '' : _subtitle?.nameValidateMessage??"", validator: (value) => Validator.hasValue(value!) ? '' : subtitle?.nameValidateMessage ?? "",
onSaved: (value) { onSaved: (value) {
_user.userName = value!; _user.userName = value!;
}, },
@ -83,11 +77,11 @@ class _RegisterState extends State<Register> {
const SizedBox(height: 12), const SizedBox(height: 12),
ATextFormField( ATextFormField(
initialValue: _user.email, initialValue: _user.email,
hintText: _subtitle?.email??"", hintText: subtitle?.email ?? "",
prefixIconData: Icons.email, prefixIconData: Icons.email,
textInputType: TextInputType.emailAddress, textInputType: TextInputType.emailAddress,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.titleLarge,
validator: (value) => Validator.isEmail(value!) ? '' : _subtitle?.emailValidateMessage??"", validator: (value) => Validator.isEmail(value!) ? '' : subtitle?.emailValidateMessage ?? "",
onSaved: (value) { onSaved: (value) {
_user.email = value!; _user.email = value!;
}, },
@ -95,11 +89,11 @@ class _RegisterState extends State<Register> {
const SizedBox(height: 12), const SizedBox(height: 12),
ATextFormField( ATextFormField(
initialValue: _user.password, initialValue: _user.password,
hintText: _subtitle?.password??"", hintText: subtitle?.password ?? "",
prefixIconData: Icons.vpn_key_sharp, prefixIconData: Icons.vpn_key_sharp,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.titleLarge,
obscureText: _obscurePassword, obscureText: _obscurePassword,
validator: (value) => Validator.isValidPassword(value!) ? '' : _subtitle?.passwordValidateMessage??'', validator: (value) => Validator.isValidPassword(value!) ? '' : subtitle?.passwordValidateMessage ?? '',
showPassword: () { showPassword: () {
_obscurePassword = !_obscurePassword; _obscurePassword = !_obscurePassword;
setState(() {}); setState(() {});
@ -115,10 +109,10 @@ class _RegisterState extends State<Register> {
ATextFormField( ATextFormField(
initialValue: _user.password, initialValue: _user.password,
prefixIconData: Icons.vpn_key_sharp, prefixIconData: Icons.vpn_key_sharp,
hintText: _subtitle?.confirmPassword??"", hintText: subtitle?.confirmPassword ?? "",
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.titleLarge,
obscureText: _obscurePassword, obscureText: _obscurePassword,
validator: (value) => _user.password == value ? '' : _subtitle?.confirmPasswordValidateMessage??"", validator: (value) => _user.password == value ? '' : subtitle?.confirmPasswordValidateMessage ?? "",
showPassword: () { showPassword: () {
_obscurePassword = !_obscurePassword; _obscurePassword = !_obscurePassword;
setState(() {}); setState(() {});
@ -126,7 +120,7 @@ class _RegisterState extends State<Register> {
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
HospitalButton( HospitalButton(
hospital: _user.hospital??Hospital(), hospital: _user.hospital ?? Hospital(),
onHospitalPick: (hospital) { onHospitalPick: (hospital) {
_user.hospital = hospital; _user.hospital = hospital;
setState(() {}); setState(() {});
@ -142,24 +136,24 @@ class _RegisterState extends State<Register> {
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
ATextFormField( ATextFormField(
initialValue: _user.phoneNumber??"", initialValue: _user.phoneNumber ?? "",
hintText: _subtitle?.phoneNumber??"", hintText: subtitle?.phoneNumber ?? "",
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.titleLarge,
prefixIconData: Icons.phone_android, prefixIconData: Icons.phone_android,
validator: (value) => Validator.isPhoneNumber(value!) ? '' : _subtitle?.phoneNumberValidateMessage??"", validator: (value) => Validator.isPhoneNumber(value!) ? '' : subtitle?.phoneNumberValidateMessage ?? "",
textInputType: TextInputType.phone, textInputType: TextInputType.phone,
onSaved: (value) { onSaved: (value) {
_user.phoneNumber = value; _user.phoneNumber = value;
}, },
), ),
SizedBox(height: 8), const SizedBox(height: 8),
ATextFormField( ATextFormField(
initialValue: _user.whatsApp??"", initialValue: _user.whatsApp ?? "",
hintText: _subtitle?.whatsApp??"", hintText: subtitle?.whatsApp ?? "",
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.titleLarge,
prefixIconData: FontAwesomeIcons.whatsapp, prefixIconData: FontAwesomeIcons.whatsapp,
prefixIconSize: 36, prefixIconSize: 36,
validator: (value) => (Validator.isPhoneNumber(value!)) ? "" : _subtitle?.phoneNumberValidateMessage??"", validator: (value) => (Validator.isPhoneNumber(value!)) ? "" : subtitle?.phoneNumberValidateMessage ?? "",
textInputType: TextInputType.phone, textInputType: TextInputType.phone,
onSaved: (value) { onSaved: (value) {
_user.whatsApp = value; _user.whatsApp = value;
@ -167,45 +161,18 @@ class _RegisterState extends State<Register> {
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
AButton( AButton(
text: _subtitle?.signUp??"", text: subtitle?.signUp ?? "",
onPressed: () async { onPressed: () async {
if (!(_formKey.currentState?.validate()??false)) return; if (_formKey.currentState?.validate() ?? false) {
_formKey.currentState?.save(); _formKey.currentState?.save();
if (_user.hospital == null) { await _userProvider.register(context, newUser: _user);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(_subtitle?.hospitalRequired??""),
));
return;
}
if (_user.department == null) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(_subtitle?.unitRequired??""),
));
return;
}
int? status = await _userProvider?.register(
user: _user,
host: _settingProvider?.host??"",
);
if (status != null && status >= 200 && status < 300) {
Fluttertoast.showToast(msg: _subtitle?.activationAlert??"");
Navigator.of(context).pop();
} else {
String? errorMessage = status == 402
? _subtitle?.nameExist
: status == 401
? _subtitle?.emailExist
: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(errorMessage??""),
));
} }
}, },
), ),
], ],
), ),
), ),
ABackButton(), const ABackButton(),
], ],
), ),
), ),

@ -5,9 +5,9 @@ import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flare_flutter/flare_actor.dart'; import 'package:flare_flutter/flare_actor.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/api/user_api_client.dart';
import '../../controllers/notification/notification_manger.dart'; import '../../controllers/notification/notification_manger.dart';
import '../../controllers/providers/api/user_provider.dart';
import '../../controllers/providers/settings/setting_provider.dart'; import '../../controllers/providers/settings/setting_provider.dart';
import '../../models/app_notification.dart'; import '../../models/app_notification.dart';
import '../../models/user.dart'; import '../../models/user.dart';
@ -24,11 +24,10 @@ class SplashScreen extends StatefulWidget {
} }
class _SplashScreenState extends State<SplashScreen> { class _SplashScreenState extends State<SplashScreen> {
SettingProvider? _settingProvider; late SettingProvider _settingProvider;
UserProvider? _userProvider;
_goToUserScreen(User? user) { _goToUserScreen(User? user) {
_userProvider?.user = user; UserApiClient().user = user;
// Navigator.of(context).pushNamed(Login.id); // Navigator.of(context).pushNamed(Login.id);
Navigator.of(context).pushNamed(LandPage.id); Navigator.of(context).pushNamed(LandPage.id);
} }
@ -36,14 +35,12 @@ class _SplashScreenState extends State<SplashScreen> {
@override @override
void initState() { void initState() {
Firebase.initializeApp(); Firebase.initializeApp();
NotificationManger.initialisation((notificationDetails) { NotificationManger.initialisation((notificationDetails) {
AppNotification notification = AppNotification.fromJson( AppNotification notification = AppNotification.fromJson(json.decode(notificationDetails.payload ?? ""));
json.decode(notificationDetails.payload ?? "")); if (notification.path == null || (notification.path?.isEmpty ?? false)) {
if (notification.path == null || (notification.path?.isEmpty ?? false))
return; return;
Navigator.pushNamed(context, notification.path ?? "", }
arguments: notification.requestId); Navigator.pushNamed(context, notification.path ?? "", arguments: notification.requestId);
}, (id, title, body, payload) async {}); }, (id, title, body, payload) async {});
super.initState(); super.initState();
} }
@ -51,7 +48,6 @@ class _SplashScreenState extends State<SplashScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_settingProvider = Provider.of<SettingProvider>(context, listen: false); _settingProvider = Provider.of<SettingProvider>(context, listen: false);
_userProvider = Provider.of<UserProvider>(context, listen: false);
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
body: Center( body: Center(
@ -62,11 +58,12 @@ class _SplashScreenState extends State<SplashScreen> {
fit: BoxFit.contain, fit: BoxFit.contain,
animation: "splash", animation: "splash",
callback: (animation) async { callback: (animation) async {
print(await FirebaseMessaging.instance.getToken()); debugPrint(await FirebaseMessaging.instance.getToken());
if (context.mounted) {
Navigator.of(context).pushNamed(Login.id); Navigator.of(context).pushNamed(Login.id);
if ((_settingProvider?.isLoaded ?? false) && if (_settingProvider.isLoaded && _settingProvider.user != null) {
_settingProvider?.user != null) { _goToUserScreen(_settingProvider.user);
_goToUserScreen(_settingProvider?.user); }
} }
}, },
), ),

@ -2,11 +2,12 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../api/user_api_client.dart';
import '../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/gas_refill_provider.dart'; import '../../../../controllers/providers/api/gas_refill_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../models/enums/user_types.dart'; import '../../../../models/enums/user_types.dart';
import '../../../../models/gas_refill/gas_refill_model.dart'; import '../../../../models/gas_refill/gas_refill_model.dart';
import '../../../../models/subtitle.dart'; import '../../../../models/subtitle.dart';
@ -22,6 +23,7 @@ import '../../../widgets/requests/info_row.dart';
import '../../../widgets/requests/request_status.dart'; import '../../../widgets/requests/request_status.dart';
import '../../../widgets/status/gas_refill/gas_status.dart'; import '../../../widgets/status/gas_refill/gas_status.dart';
import '../../../widgets/titles/app_sub_title.dart'; import '../../../widgets/titles/app_sub_title.dart';
class GasRefillDetails extends StatefulWidget { class GasRefillDetails extends StatefulWidget {
final GasRefillModel? model; final GasRefillModel? model;
const GasRefillDetails({Key? key, this.model}) : super(key: key); const GasRefillDetails({Key? key, this.model}) : super(key: key);
@ -31,7 +33,6 @@ class GasRefillDetails extends StatefulWidget {
} }
class _GasRefillDetailsState extends State<GasRefillDetails> { class _GasRefillDetailsState extends State<GasRefillDetails> {
final GasRefillModel _model = GasRefillModel(); final GasRefillModel _model = GasRefillModel();
bool _enableEdit = false; bool _enableEdit = false;
bool _validate = false; bool _validate = false;
@ -44,45 +45,35 @@ class _GasRefillDetailsState extends State<GasRefillDetails> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
_update() async { _update() async {
_validate = true; _validate = true;
if(!(_formKey.currentState?.validate()??false)){ if (!(_formKey.currentState?.validate() ?? false)) {
setState(() {}); setState(() {});
return false; return false;
} }
_formKey.currentState?.save(); _formKey.currentState?.save();
_isLoading =true; _isLoading = true;
setState(() {}); setState(() {});
int? status = await _gasRefillProvider?.updateModel( int? status = await _gasRefillProvider?.updateModel(user: UserApiClient().user ?? User(), host: _settingProvider?.host ?? "", newModel: _model, oldModel: widget.model);
user: _userProvider?.user??User(), _isLoading = false;
host: _settingProvider?.host??"",
newModel: _model,
oldModel: widget.model
);
_isLoading =false;
setState(() {}); setState(() {});
if(status != null && status >= 200 && status < 300){ if (status != null && status >= 200 && status < 300) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: _subtitle?.requestCompleteSuccessfully??"", msg: _subtitle?.requestCompleteSuccessfully ?? "",
); );
_enableEdit = false; _enableEdit = false;
_validate = false; _validate = false;
//Navigator.of(context).pop(); //Navigator.of(context).pop();
}else{ } else {
String errorMessage = HttpStatusManger.getStatusMessage( String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle);
status: status, subtitle: _subtitle); ScaffoldMessenger.of(context).showSnackBar(SnackBar(
ScaffoldMessenger.of(context).showSnackBar( content: Text(errorMessage),
SnackBar( ));
content: Text(
errorMessage
),
)
);
} }
} }
@override @override
void initState() { void initState() {
_model.fromGasRefillModel(widget.model??GasRefillModel()); _model.fromGasRefillModel(widget.model ?? GasRefillModel());
super.initState(); super.initState();
} }
@ -106,22 +97,19 @@ class _GasRefillDetailsState extends State<GasRefillDetails> {
children: [ children: [
Container( Container(
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
child: Row( child: Row(
children: [ children: [
ABackButton(), ABackButton(),
Expanded( Expanded(
child: Center( child: Center(
child: Text( child: Text(
_subtitle?.details??"", _subtitle?.details ?? "",
style: Theme.of(context).textTheme.headline6?.copyWith( style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
color: AColors.white,
fontStyle: FontStyle.italic
),
), ),
), ),
), ),
if(_userProvider?.user?.type == UsersTypes.engineer) if (UserApiClient().user?.type == UsersTypes.engineer)
AIconButton( AIconButton(
iconData: _enableEdit ? Icons.cancel : Icons.edit, iconData: _enableEdit ? Icons.cancel : Icons.edit,
color: Theme.of(context).colorScheme.onPrimary, color: Theme.of(context).colorScheme.onPrimary,
@ -129,46 +117,55 @@ class _GasRefillDetailsState extends State<GasRefillDetails> {
backgroundColor: AColors.green, backgroundColor: AColors.green,
onPressed: () async { onPressed: () async {
_enableEdit = !_enableEdit; _enableEdit = !_enableEdit;
_model.fromGasRefillModel(widget.model??GasRefillModel()); _model.fromGasRefillModel(widget.model ?? GasRefillModel());
setState(() {}); setState(() {});
}, },
), ),
const SizedBox(width: 16,) const SizedBox(
width: 16,
)
], ],
), ),
), ),
Expanded( Expanded(
child: SingleChildScrollView( child: SingleChildScrollView(
padding: EdgeInsets.all(16*AppStyle.getScaleFactor(context)), padding: EdgeInsets.all(16 * AppStyle.getScaleFactor(context)),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
RequestInfoRow( RequestInfoRow(
title: _subtitle?.title??"", title: _subtitle?.title ?? "",
info: _model.title??"", info: _model.title ?? "",
), ),
RequestInfoRow( RequestInfoRow(
title: _subtitle?.hospital??"", title: _subtitle?.hospital ?? "",
info: _model.clientName??"", info: _model.clientName ?? "",
), ),
_enableEdit ? _enableEdit
Column( ? Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 8,), const SizedBox(
ASubTitle(_subtitle?.status??""), height: 8,
if(_validate && _model.status == null) ),
ASubTitle(_subtitle?.requiredWord??"",color: Colors.red,), ASubTitle(_subtitle?.status ?? ""),
const SizedBox(height: 4,), if (_validate && _model.status == null)
ASubTitle(
_subtitle?.requiredWord ?? "",
color: Colors.red,
),
const SizedBox(
height: 4,
),
GasStatusMenu( GasStatusMenu(
initialValue: _model.status, initialValue: _model.status,
onSelect: (status){ onSelect: (status) {
_model.status = status; _model.status = status;
}, },
) )
], ],
): )
Row( : Row(
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
@ -177,33 +174,36 @@ class _GasRefillDetailsState extends State<GasRefillDetails> {
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),
), ),
StatusLabel(label: _model.status?.label??"", StatusLabel(label: _model.status?.label ?? "", color: AColors.getGasStatusColor(_model.status?.id ?? 0)),
color: AColors.getGasStatusColor(_model.status?.id??0)
),
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
const ASubTitle("Gas Requests"), const ASubTitle("Gas Requests"),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
ListView.builder( ListView.builder(
shrinkWrap: true, shrinkWrap: true,
physics: const ClampingScrollPhysics(), physics: const ClampingScrollPhysics(),
itemCount: _model.details?.length, itemCount: _model.details?.length,
itemBuilder: (context,index){ itemBuilder: (context, index) {
final details = _model.details![index]; final details = _model.details![index];
return GasRefillUpdateDetailsItem( return GasRefillUpdateDetailsItem(
details: details, details: details,
validate: _validate, validate: _validate,
enableEdit: _enableEdit, enableEdit: _enableEdit,
); );
} }),
), if (_enableEdit)
if(_enableEdit)
Column( Column(
children: [ children: [
const SizedBox(height: 16,), const SizedBox(
height: 16,
),
AButton( AButton(
text: _subtitle?.update??"", text: _subtitle?.update ?? "",
onPressed: _update, onPressed: _update,
), ),
], ],

@ -2,11 +2,12 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../api/user_api_client.dart';
import '../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/gas_refill_provider.dart'; import '../../../../controllers/providers/api/gas_refill_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../controllers/validator/validator.dart'; import '../../../../controllers/validator/validator.dart';
import '../../../../models/gas_refill/gas_refill_details.dart'; import '../../../../models/gas_refill/gas_refill_details.dart';
import '../../../../models/gas_refill/gas_refill_model.dart'; import '../../../../models/gas_refill/gas_refill_model.dart';
@ -19,6 +20,7 @@ import '../../../widgets/gas_refill/gas_refill_create_details_item.dart';
import '../../../widgets/loaders/loading_manager.dart'; import '../../../widgets/loaders/loading_manager.dart';
import '../../../widgets/status/gas_refill/gas_type.dart'; import '../../../widgets/status/gas_refill/gas_type.dart';
import '../../../widgets/titles/app_sub_title.dart'; import '../../../widgets/titles/app_sub_title.dart';
class RequestGasRefill extends StatefulWidget { class RequestGasRefill extends StatefulWidget {
static const String id = "/request-gas-refill"; static const String id = "/request-gas-refill";
const RequestGasRefill({Key? key}) : super(key: key); const RequestGasRefill({Key? key}) : super(key: key);
@ -42,57 +44,51 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override @override
void setState(VoidCallback fn){ void setState(VoidCallback fn) {
if(mounted) super.setState(() {}); if (mounted) super.setState(() {});
} }
_onSubmit() async { _onSubmit() async {
if((_formModel.details?.isEmpty??false)){ if ((_formModel.details?.isEmpty ?? false)) {
if(!_addNewModel()) return; if (!_addNewModel()) return;
} }
_isLoading =true; _isLoading = true;
setState(() {}); setState(() {});
int? status = await _gasRefillProvider?.createModel( int? status = await _gasRefillProvider?.createModel(
user: _userProvider?.user??User(), user: UserApiClient().user ?? User(),
host: _settingProvider?.host??"", host: _settingProvider?.host ?? "",
model: _formModel, model: _formModel,
); );
_isLoading =false; _isLoading = false;
setState(() {}); setState(() {});
if(status != null && status >= 200 && status < 300){ if (status != null && status >= 200 && status < 300) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: _subtitle?.requestCompleteSuccessfully??"", msg: _subtitle?.requestCompleteSuccessfully ?? "",
); );
Navigator.of(context).pop(); Navigator.of(context).pop();
}else{ } else {
String errorMessage = HttpStatusManger.getStatusMessage( String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle);
status: status, subtitle: _subtitle); ScaffoldMessenger.of(context).showSnackBar(SnackBar(
ScaffoldMessenger.of(context).showSnackBar( content: Text(errorMessage),
SnackBar( ));
content: Text(
errorMessage
),
)
);
} }
} }
bool _addNewModel(){ bool _addNewModel() {
_validate = true; _validate = true;
if(!(_formKey.currentState?.validate()??false)){ if (!(_formKey.currentState?.validate() ?? false)) {
setState(() {}); setState(() {});
return false; return false;
} }
_formKey.currentState?.save(); _formKey.currentState?.save();
if(!_currentDetails.validate()) { if (!_currentDetails.validate()) {
setState(() { }); setState(() {});
return false; return false;
} }
_formModel.details?.insert(0, _currentDetails);
_formModel.details?.insert(0,_currentDetails);
_validate = false; _validate = false;
Scrollable.ensureVisible(_DetailsKey.currentContext!); Scrollable.ensureVisible(_DetailsKey.currentContext!);
_requestedQuantityController.clear(); _requestedQuantityController.clear();
@ -106,12 +102,13 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
_requestedQuantityController.dispose(); _requestedQuantityController.dispose();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_subtitle = AppLocalization.of(context)?.subtitle; _subtitle = AppLocalization.of(context)?.subtitle;
_userProvider = Provider.of<UserProvider>(context); _userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context); _settingProvider = Provider.of<SettingProvider>(context);
_gasRefillProvider = Provider.of<GasRefillProvider>(context,listen: false); _gasRefillProvider = Provider.of<GasRefillProvider>(context, listen: false);
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
body: Form( body: Form(
@ -132,11 +129,7 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
"Request Gas Refill", "Request Gas Refill",
style: Theme.of(context).textTheme.headline5?.copyWith( style: Theme.of(context).textTheme.headline5?.copyWith(color: Theme.of(context).primaryColor, fontSize: 28, fontWeight: FontWeight.bold),
color: Theme.of(context).primaryColor,
fontSize: 28,
fontWeight: FontWeight.bold
),
), ),
), ),
), ),
@ -167,14 +160,21 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
// ), // ),
// const SizedBox(height: 8,), // const SizedBox(height: 8,),
// Divider(color: Theme.of(context).colorScheme.primary,), // Divider(color: Theme.of(context).colorScheme.primary,),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
const ASubTitle("Type"), const ASubTitle("Type"),
if(_validate && _currentDetails.type == null) if (_validate && _currentDetails.type == null)
ASubTitle(_subtitle?.requiredWord??"",color: Colors.red,), ASubTitle(
const SizedBox(height: 4,), _subtitle?.requiredWord ?? "",
color: Colors.red,
),
const SizedBox(
height: 4,
),
GasTypeMenu( GasTypeMenu(
initialValue: _currentDetails.type, initialValue: _currentDetails.type,
onSelect: (status){ onSelect: (status) {
_currentDetails.type = status; _currentDetails.type = status;
}, },
), ),
@ -190,53 +190,58 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
// _currentDetails.cylinderSize = status; // _currentDetails.cylinderSize = status;
// }, // },
// ), // ),
const SizedBox(height: 8,), const SizedBox(
ASubTitle(_subtitle?.quantity??""), height: 8,
if(_validate && _currentDetails.requestedQuantity == null) ),
ASubTitle(_subtitle?.requiredWord??"",color: Colors.red,), ASubTitle(_subtitle?.quantity ?? ""),
SizedBox(height: 4,), if (_validate && _currentDetails.requestedQuantity == null)
ASubTitle(
_subtitle?.requiredWord ?? "",
color: Colors.red,
),
SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: (_currentDetails?.requestedQuantity ?? "").toString(), initialValue: (_currentDetails?.requestedQuantity ?? "").toString(),
textAlign: TextAlign.center, textAlign: TextAlign.center,
controller: _requestedQuantityController, controller: _requestedQuantityController,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
validator: (value) => validator: (value) => Validator.isNumeric(value!) ? '' : "allow numbers only",
Validator.isNumeric(value!)
? '' : "allow numbers only",
textInputType: TextInputType.number, textInputType: TextInputType.number,
onSaved: (value){ onSaved: (value) {
_currentDetails.requestedQuantity = int.tryParse(value!); _currentDetails.requestedQuantity = int.tryParse(value!);
}, },
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
AButton( AButton(
text: _subtitle?.add??"", text: _subtitle?.add ?? "",
onPressed: _addNewModel, onPressed: _addNewModel,
), ),
if((_formModel.details?.isNotEmpty??false)) if ((_formModel.details?.isNotEmpty ?? false)) const ASubTitle("Gas Requests"),
const ASubTitle("Gas Requests"),
ListView.builder( ListView.builder(
key: _DetailsKey, key: _DetailsKey,
shrinkWrap: true, shrinkWrap: true,
physics: const ClampingScrollPhysics(), physics: const ClampingScrollPhysics(),
itemCount: _formModel.details?.length, itemCount: _formModel.details?.length,
itemBuilder: (context,index){ itemBuilder: (context, index) {
final model = _formModel.details![index]; final model = _formModel.details![index];
return GasRefillCreateDetailsItem( return GasRefillCreateDetailsItem(
model: model, model: model,
onDelete: (){ onDelete: () {
_formModel.details?.remove(model); _formModel.details?.remove(model);
setState(() {}); setState(() {});
}, },
); );
} }),
),
const SizedBox(height: 16), const SizedBox(height: 16),
AButton( AButton(
text: _subtitle?.submit??"", text: _subtitle?.submit ?? "",
onPressed: _onSubmit, onPressed: _onSubmit,
), ),
const SizedBox(height: 100,) const SizedBox(
height: 100,
)
], ],
), ),
), ),
@ -246,4 +251,3 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
); );
} }
} }

@ -1,10 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../api/user_api_client.dart';
import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/gas_refill_provider.dart'; import '../../../../controllers/providers/api/gas_refill_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../models/subtitle.dart'; import '../../../../models/subtitle.dart';
import '../../../../models/user.dart'; import '../../../../models/user.dart';
import '../../../app_style/colors.dart'; import '../../../app_style/colors.dart';
@ -21,8 +22,7 @@ class TrackGasRefillPage extends StatefulWidget {
State<TrackGasRefillPage> createState() => _TrackGasRefillPageState(); State<TrackGasRefillPage> createState() => _TrackGasRefillPageState();
} }
class _TrackGasRefillPageState extends State<TrackGasRefillPage> class _TrackGasRefillPageState extends State<TrackGasRefillPage> with TickerProviderStateMixin {
with TickerProviderStateMixin{
GasRefillProvider? _gasRefillProvider; GasRefillProvider? _gasRefillProvider;
UserProvider? _userProvider; UserProvider? _userProvider;
SettingProvider? _settingProvider; SettingProvider? _settingProvider;
@ -42,8 +42,8 @@ class _TrackGasRefillPageState extends State<TrackGasRefillPage>
onRefresh: () async { onRefresh: () async {
_gasRefillProvider?.reset(); _gasRefillProvider?.reset();
await _gasRefillProvider?.getRequests( await _gasRefillProvider?.getRequests(
user: _userProvider?.user??User(), user: UserApiClient().user ?? User(),
host: _settingProvider?.host??"", host: _settingProvider?.host ?? "",
); );
}, },
child: Stack( child: Stack(
@ -51,8 +51,8 @@ class _TrackGasRefillPageState extends State<TrackGasRefillPage>
Column( Column(
children: [ children: [
Container( Container(
color:AColors.white, color: AColors.white,
padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
child: Column( child: Column(
children: [ children: [
Row( Row(
@ -61,36 +61,33 @@ class _TrackGasRefillPageState extends State<TrackGasRefillPage>
Expanded( Expanded(
child: Center( child: Center(
child: Text( child: Text(
_subtitle?.serviceRequests??"", _subtitle?.serviceRequests ?? "",
style: Theme.of(context).textTheme.headline6?.copyWith( style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.grey3A, fontStyle: FontStyle.italic),
color: AColors.grey3A,
fontStyle: FontStyle.italic
), ),
), ),
), ),
), const SizedBox(
const SizedBox(width: 48,) width: 48,
)
], ],
), ),
], ],
), ),
), ),
Expanded( Expanded(
child: GasRefillList( child: GasRefillList(
nextPage: _gasRefillProvider?.nextPage??false, nextPage: _gasRefillProvider?.nextPage ?? false,
onLazyLoad: () async { onLazyLoad: () async {
await _gasRefillProvider?.getRequests( await _gasRefillProvider?.getRequests(
user: _userProvider?.user??User(), user: UserApiClient().user ?? User(),
host: _settingProvider?.host??"", host: _settingProvider?.host ?? "",
); );
}, },
items: _gasRefillProvider?.items??[], items: _gasRefillProvider?.items ?? [],
), ),
), ),
], ],
), ),
], ],
), ),
), ),

@ -8,6 +8,7 @@ import 'package:provider/provider.dart';
import 'package:share/share.dart'; import 'package:share/share.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import '../../../api/user_api_client.dart';
import '../../../controllers/localization/localization.dart'; import '../../../controllers/localization/localization.dart';
import '../../../controllers/notification/firebase_notification_manger.dart'; import '../../../controllers/notification/firebase_notification_manger.dart';
import '../../../controllers/providers/api/departments_provider.dart'; import '../../../controllers/providers/api/departments_provider.dart';
@ -15,8 +16,8 @@ import '../../../controllers/providers/api/devices_provider.dart';
import '../../../controllers/providers/api/preventive_maintenance_visits_provider.dart'; import '../../../controllers/providers/api/preventive_maintenance_visits_provider.dart';
import '../../../controllers/providers/api/regular_visits_provider.dart'; import '../../../controllers/providers/api/regular_visits_provider.dart';
import '../../../controllers/providers/api/service_requests_provider.dart'; import '../../../controllers/providers/api/service_requests_provider.dart';
import '../../../controllers/providers/api/user_provider.dart';
import '../../../controllers/providers/settings/setting_provider.dart'; import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../controllers/providers/user_provider.dart';
import '../../../extensions/int_extensions.dart'; import '../../../extensions/int_extensions.dart';
import '../../../extensions/widget_extensions.dart'; import '../../../extensions/widget_extensions.dart';
import '../../../models/enums/user_types.dart'; import '../../../models/enums/user_types.dart';
@ -80,14 +81,12 @@ class _LandPageState extends State<LandPage> {
_departmentsProvider = Provider.of<DepartmentsProvider>(context); _departmentsProvider = Provider.of<DepartmentsProvider>(context);
_devicesProvider = Provider.of<DevicesProvider>(context); _devicesProvider = Provider.of<DevicesProvider>(context);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context); _serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
_preventiveMaintenanceVisitsProvider = _preventiveMaintenanceVisitsProvider = Provider.of<PreventiveMaintenanceVisitsProvider>(context);
Provider.of<PreventiveMaintenanceVisitsProvider>(context);
_regularVisitsProvider = Provider.of<RegularVisitsProvider>(context); _regularVisitsProvider = Provider.of<RegularVisitsProvider>(context);
Subtitle _subtitle = AppLocalization.of(context)!.subtitle!; Subtitle _subtitle = AppLocalization.of(context)!.subtitle!;
if (firstTime) { if (firstTime) {
if (path != null) { if (path != null) {
Navigator.of(context).pushNamed("/" + path.split("/").first, Navigator.of(context).pushNamed("/" + path.split("/").first, arguments: path.split("/").last);
arguments: path.split("/").last);
} }
firstTime = false; firstTime = false;
} }
@ -154,21 +153,19 @@ class _LandPageState extends State<LandPage> {
mainAxisSpacing: 12, mainAxisSpacing: 12,
childAspectRatio: 1, childAspectRatio: 1,
children: [ children: [
if (_userProvider.user!.type == UsersTypes.normal_user) if (UserApiClient().user!.type == UsersTypes.normal_user)
LandPageItem( LandPageItem(
text: _subtitle.newServiceRequest, text: _subtitle.newServiceRequest,
icon: FontAwesomeIcons.tools, icon: FontAwesomeIcons.tools,
onPressed: () { onPressed: () {
Navigator.of(context) Navigator.of(context).pushNamed(CreateRequestPage.id);
.pushNamed(CreateRequestPage.id);
}, },
), ),
LandPageItem( LandPageItem(
text: _subtitle.trackServiceRequest, text: _subtitle.trackServiceRequest,
icon: FontAwesomeIcons.tasks, icon: FontAwesomeIcons.tasks,
onPressed: () { onPressed: () {
Navigator.of(context) Navigator.of(context).pushNamed(ServiceRequestsPage.id);
.pushNamed(ServiceRequestsPage.id);
}, },
), ),
//if (_userProvider.user.type == UsersTypes.engineer) //if (_userProvider.user.type == UsersTypes.engineer)
@ -187,37 +184,33 @@ class _LandPageState extends State<LandPage> {
// Navigator.of(context).pushNamed(PreventiveMaintenanceVisitsPage.id); // Navigator.of(context).pushNamed(PreventiveMaintenanceVisitsPage.id);
// }, // },
// ), // ),
if (_userProvider.user?.type != UsersTypes.engineer) if (UserApiClient().user?.type != UsersTypes.engineer)
LandPageItem( LandPageItem(
text: "Request Gas Refill", text: "Request Gas Refill",
icon: FontAwesomeIcons.truckFast, icon: FontAwesomeIcons.truckFast,
onPressed: () { onPressed: () {
Navigator.of(context) Navigator.of(context).pushNamed(RequestGasRefill.id);
.pushNamed(RequestGasRefill.id);
}, },
), ),
LandPageItem( LandPageItem(
text: "Track Gas Refill", text: "Track Gas Refill",
icon: Icons.content_paste_search, icon: Icons.content_paste_search,
onPressed: () { onPressed: () {
Navigator.of(context) Navigator.of(context).pushNamed(TrackGasRefillPage.id);
.pushNamed(TrackGasRefillPage.id);
}, },
), ),
LandPageItem( LandPageItem(
text: "transfer Device", text: "transfer Device",
icon: FontAwesomeIcons.rightLeft, icon: FontAwesomeIcons.rightLeft,
onPressed: () { onPressed: () {
Navigator.of(context) Navigator.of(context).pushNamed(RequestDeviceTransfer.id);
.pushNamed(RequestDeviceTransfer.id);
}, },
), ),
LandPageItem( LandPageItem(
text: "Track Device Transfer", text: "Track Device Transfer",
icon: FontAwesomeIcons.peopleCarryBox, icon: FontAwesomeIcons.peopleCarryBox,
onPressed: () { onPressed: () {
Navigator.of(context) Navigator.of(context).pushNamed(TrackDeviceTransferPage.id);
.pushNamed(TrackDeviceTransferPage.id);
}, },
), ),
], ],
@ -250,8 +243,7 @@ class _LandPageState extends State<LandPage> {
Align( Align(
alignment: Alignment.topRight, alignment: Alignment.topRight,
child: Padding( child: Padding(
padding: padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: AIconButton( child: AIconButton(
iconData: Icons.menu, iconData: Icons.menu,
color: AColors.primaryColor, color: AColors.primaryColor,
@ -283,10 +275,7 @@ class _LandPageState extends State<LandPage> {
height: 50 * AppStyle.getScaleFactor(context), height: 50 * AppStyle.getScaleFactor(context),
width: 50 * AppStyle.getScaleFactor(context), width: 50 * AppStyle.getScaleFactor(context),
padding: EdgeInsets.all(4), padding: EdgeInsets.all(4),
decoration: BoxDecoration( decoration: BoxDecoration(border: Border.all(color: Theme.of(context).primaryColor, width: 2), shape: BoxShape.circle),
border: Border.all(
color: Theme.of(context).primaryColor, width: 2),
shape: BoxShape.circle),
child: ClipOval( child: ClipOval(
child: ClipOval( child: ClipOval(
child: Icon( child: Icon(
@ -299,7 +288,7 @@ class _LandPageState extends State<LandPage> {
), ),
12.width, 12.width,
Text( Text(
_userProvider.user?.userName ?? "", UserApiClient().user?.userName ?? "",
style: Theme.of(context).textTheme.headline6?.copyWith( style: Theme.of(context).textTheme.headline6?.copyWith(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
@ -326,10 +315,7 @@ class _LandPageState extends State<LandPage> {
}), }),
Text( Text(
"English", "English",
style: Theme.of(context) style: Theme.of(context).textTheme.bodyText1?.copyWith(color: AColors.grey3A),
.textTheme
.bodyText1
?.copyWith(color: AColors.grey3A),
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),
Radio( Radio(
@ -342,10 +328,7 @@ class _LandPageState extends State<LandPage> {
}), }),
Text( Text(
"عربي", "عربي",
style: Theme.of(context) style: Theme.of(context).textTheme.bodyText1?.copyWith(color: AColors.grey3A),
.textTheme
.bodyText1
?.copyWith(color: AColors.grey3A),
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),
], ],
@ -389,12 +372,8 @@ class _LandPageState extends State<LandPage> {
icon: Icons.share, icon: Icons.share,
title: _subtitle.shareApp, title: _subtitle.shareApp,
onPressed: () async { onPressed: () async {
PackageInfo packageInfo = PackageInfo packageInfo = await PackageInfo.fromPlatform();
await PackageInfo.fromPlatform(); String shareLink = "\n https://play.google.com/store/apps/details?id=" + packageInfo.packageName + "\n https://apps.apple.com/us/app/";
String shareLink =
"\n https://play.google.com/store/apps/details?id=" +
packageInfo.packageName +
"\n https://apps.apple.com/us/app/";
Share.share(shareLink); Share.share(shareLink);
}, },
), ),
@ -406,15 +385,11 @@ class _LandPageState extends State<LandPage> {
children: [ children: [
Text( Text(
"Powered By NewTrack", "Powered By NewTrack",
style: Theme.of(context).textTheme.headline6?.copyWith( style: Theme.of(context).textTheme.headline6?.copyWith(fontWeight: FontWeight.w500, color: AColors.grey3A, fontSize: 12),
fontWeight: FontWeight.w500,
color: AColors.grey3A,
fontSize: 12),
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),
6.width, 6.width,
Image.asset("assets/images/qr.jpeg", Image.asset("assets/images/qr.jpeg", width: 32, height: 32, color: AColors.grey3A)
width: 32, height: 32, color: AColors.grey3A)
], ],
).paddingOnly(left: 20, right: 20, top: 8, bottom: 8), ).paddingOnly(left: 20, right: 20, top: 8, bottom: 8),
], ],

@ -1,4 +1,3 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/localization/localization.dart';
@ -8,6 +7,7 @@ import '../../../widgets/loaders/lazy_loading.dart';
import '../../../widgets/loaders/no_item_found.dart'; import '../../../widgets/loaders/no_item_found.dart';
import '../../../widgets/notifications/notification_item.dart'; import '../../../widgets/notifications/notification_item.dart';
import '../requests/future_request_service_details.dart'; import '../requests/future_request_service_details.dart';
class NotificationsList extends StatelessWidget { class NotificationsList extends StatelessWidget {
final List<AppNotification>? notifications; final List<AppNotification>? notifications;
final bool? nextPage; final bool? nextPage;
@ -18,29 +18,27 @@ class NotificationsList extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Subtitle? _subtitle = AppLocalization.of(context)?.subtitle; Subtitle? _subtitle = AppLocalization.of(context)?.subtitle;
if((notifications?.isEmpty??false)){ if ((notifications?.isEmpty ?? false)) {
return NoItemFound(message: _subtitle?.notificationsNotFound??"",); return NoItemFound(
message: _subtitle?.notificationsNotFound ?? "",
);
} }
return LazyLoading( return LazyLoading(
nextPage: nextPage??false, nextPage: nextPage ?? false,
onLazyLoad: onLazyLoad??()async{}, onLazyLoad: onLazyLoad ?? () async {},
onLoadingEnd: () { }, onLoadingEnd: () {},
child: ListView.builder( child: ListView.builder(
physics: BouncingScrollPhysics(), physics: BouncingScrollPhysics(),
itemCount: notifications?.length, itemCount: notifications?.length,
padding: EdgeInsets.symmetric(horizontal: 16,vertical: 8), padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
itemBuilder: (context,itemIndex){ itemBuilder: (context, itemIndex) {
return NotificationItem( return NotificationItem(
notification: notifications![itemIndex], notification: notifications![itemIndex],
onPressed: (notification){ onPressed: (notification) {
Navigator.of(context).pushNamed( Navigator.of(context).pushNamed(FutureRequestServiceDetails.id, arguments: notification.requestId);
FutureRequestServiceDetails.id,
arguments: notification.requestId
);
}, },
); );
} }),
),
); );
} }
} }

@ -1,10 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../api/user_api_client.dart';
import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/notifications_provider.dart'; import '../../../../controllers/providers/api/notifications_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../models/subtitle.dart'; import '../../../../models/subtitle.dart';
import '../../../../models/user.dart'; import '../../../../models/user.dart';
import '../../../app_style/colors.dart'; import '../../../app_style/colors.dart';
@ -18,8 +19,7 @@ class NotificationsPage extends StatefulWidget {
_NotificationsPageState createState() => _NotificationsPageState(); _NotificationsPageState createState() => _NotificationsPageState();
} }
class _NotificationsPageState extends State<NotificationsPage> class _NotificationsPageState extends State<NotificationsPage> with TickerProviderStateMixin {
with TickerProviderStateMixin{
NotificationsProvider? _notificationsProvider; NotificationsProvider? _notificationsProvider;
UserProvider? _userProvider; UserProvider? _userProvider;
SettingProvider? _settingProvider; SettingProvider? _settingProvider;
@ -33,15 +33,15 @@ class _NotificationsPageState extends State<NotificationsPage>
return Scaffold( return Scaffold(
body: SafeArea( body: SafeArea(
child: LoadingManager( child: LoadingManager(
isLoading: _notificationsProvider?.isLoading??false, isLoading: _notificationsProvider?.isLoading ?? false,
isFailedLoading: _notificationsProvider?.notifications == null, isFailedLoading: _notificationsProvider?.notifications == null,
stateCode: _notificationsProvider?.stateCode??0, stateCode: _notificationsProvider?.stateCode ?? 0,
onRefresh: () async { onRefresh: () async {
_notificationsProvider?.reset(); _notificationsProvider?.reset();
await _notificationsProvider?.getNotifications( await _notificationsProvider?.getNotifications(
user: _userProvider?.user??User(), user: UserApiClient().user ?? User(),
host: _settingProvider?.host??"", host: _settingProvider?.host ?? "",
hospitalId: _userProvider?.user?.hospital?.id??"", hospitalId: UserApiClient().user?.hospital?.id ?? "",
); );
}, },
child: Stack( child: Stack(
@ -49,8 +49,8 @@ class _NotificationsPageState extends State<NotificationsPage>
Column( Column(
children: [ children: [
Container( Container(
color:AColors.primaryColor, color: AColors.primaryColor,
padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
child: Column( child: Column(
children: [ children: [
Row( Row(
@ -59,18 +59,16 @@ class _NotificationsPageState extends State<NotificationsPage>
Expanded( Expanded(
child: Center( child: Center(
child: Text( child: Text(
_subtitle?.notifications??"", _subtitle?.notifications ?? "",
style: Theme.of(context).textTheme.headline6?.copyWith( style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
color: AColors.white,
fontStyle: FontStyle.italic
), ),
), ),
), ),
), SizedBox(
SizedBox(width: 48,) width: 48,
)
], ],
), ),
], ],
), ),
), ),
@ -79,9 +77,9 @@ class _NotificationsPageState extends State<NotificationsPage>
nextPage: _notificationsProvider?.nextPage, nextPage: _notificationsProvider?.nextPage,
onLazyLoad: () async { onLazyLoad: () async {
await _notificationsProvider?.getNotifications( await _notificationsProvider?.getNotifications(
user: _userProvider?.user??User(), user: UserApiClient().user ?? User(),
host: _settingProvider?.host??"", host: _settingProvider?.host ?? "",
hospitalId: _userProvider?.user?.hospital?.id??"", hospitalId: UserApiClient().user?.hospital?.id ?? "",
); );
}, },
notifications: _notificationsProvider?.notifications, notifications: _notificationsProvider?.notifications,
@ -89,7 +87,6 @@ class _NotificationsPageState extends State<NotificationsPage>
), ),
], ],
), ),
], ],
), ),
), ),

@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../api/user_api_client.dart';
import '../../../controllers/localization/localization.dart'; import '../../../controllers/localization/localization.dart';
import '../../../controllers/providers/api/user_provider.dart';
import '../../../controllers/providers/settings/setting_provider.dart'; import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../controllers/providers/user_provider.dart';
import '../../../controllers/validator/validator.dart'; import '../../../controllers/validator/validator.dart';
import '../../../models/subtitle.dart'; import '../../../models/subtitle.dart';
import '../../../models/user.dart'; import '../../../models/user.dart';
@ -17,13 +17,17 @@ import '../../widgets/buttons/app_button.dart';
import '../../widgets/departments/department_button.dart'; import '../../widgets/departments/department_button.dart';
import '../../widgets/hospitals/hospital_button.dart'; import '../../widgets/hospitals/hospital_button.dart';
import '../../widgets/loaders/loading_manager.dart'; import '../../widgets/loaders/loading_manager.dart';
class ProfilePage extends StatefulWidget { class ProfilePage extends StatefulWidget {
static final String id = "/user/profile"; static const String id = "/user/profile";
const ProfilePage({super.key});
@override @override
_ProfilePageState createState() => _ProfilePageState(); ProfilePageState createState() => ProfilePageState();
} }
class _ProfilePageState extends State<ProfilePage> { class ProfilePageState extends State<ProfilePage> {
late UserProvider _userProvider; late UserProvider _userProvider;
late SettingProvider _settingProvider; late SettingProvider _settingProvider;
late double _width; late double _width;
@ -32,21 +36,22 @@ class _ProfilePageState extends State<ProfilePage> {
bool _firstTime = true; bool _firstTime = true;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context); _userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context); _settingProvider = Provider.of<SettingProvider>(context);
_width = MediaQuery.of(context).size.width; _width = MediaQuery.of(context).size.width;
_height = MediaQuery.of(context).size.height; _height = MediaQuery.of(context).size.height;
Subtitle _subtitle = AppLocalization.of(context)!.subtitle!; Subtitle subtitle = AppLocalization.of(context)!.subtitle!;
if(_firstTime){ if (_firstTime) {
_user = User.fromJson(_userProvider.user!.toJson()); _user = User.fromJson(UserApiClient().user!.toJson());
_firstTime = false; _firstTime = false;
} }
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
body:LoadingManager( body: LoadingManager(
isLoading: _userProvider.isLoading, isLoading: _userProvider.loading,
isFailedLoading: false, isFailedLoading: false,
stateCode: 200, stateCode: 200,
onRefresh: () async {}, onRefresh: () async {},
@ -61,153 +66,111 @@ class _ProfilePageState extends State<ProfilePage> {
Hero( Hero(
tag: "logo", tag: "logo",
child: Image( child: Image(
height: _height/4, height: _height / 4,
image: AssetImage("assets/images/logo.png"), image: const AssetImage("assets/images/logo.png"),
), ),
), ),
Container( Container(
padding: EdgeInsets.symmetric(horizontal: 16,vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
margin: EdgeInsets.symmetric(horizontal: 16), margin: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AColors.primaryColor, color: AColors.primaryColor,
borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)),
boxShadow: [ boxShadow: const [BoxShadow(color: AColors.grey, offset: Offset(0, -1))],
BoxShadow(
color: AColors.grey,
offset: Offset(0,-1),
)
]
), ),
child: Column( child: Column(
children: [ children: [
ATextFormField( ATextFormField(
initialValue: _user.userName, initialValue: _user.userName,
hintText: _subtitle.name, hintText: subtitle.name,
enable: false, enable: false,
prefixIconData: Icons.account_circle, prefixIconData: Icons.account_circle,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.titleLarge,
validator: (value) => Validator.hasValue(value!) validator: (value) => Validator.hasValue(value!) ? '' : subtitle.nameValidateMessage,
? '' : _subtitle.nameValidateMessage, onSaved: (value) {
onSaved: (value){
_user.userName = value!; _user.userName = value!;
}, },
), ),
SizedBox(height: 8,), const SizedBox(height: 8),
ATextFormField( ATextFormField(
initialValue: _user.email, initialValue: _user.email,
hintText: _subtitle.email, hintText: subtitle.email,
enable: false, enable: false,
prefixIconData: Icons.email, prefixIconData: Icons.email,
textInputType: TextInputType.emailAddress, textInputType: TextInputType.emailAddress,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.titleLarge,
validator: (value) => Validator.isEmail(value!) validator: (value) => Validator.isEmail(value!) ? '' : subtitle.emailValidateMessage,
? '' : _subtitle.emailValidateMessage, onSaved: (value) {
onSaved: (value){
_user.email = value!; _user.email = value!;
}, },
), ),
SizedBox(height: 8,), const SizedBox(height: 8),
AbsorbPointer( AbsorbPointer(
child: HospitalButton( child: HospitalButton(
hospital: _user.hospital!, hospital: _user.hospital!,
onHospitalPick: (hospital){ onHospitalPick: (hospital) {
_user.hospital = hospital; _user.hospital = hospital;
setState(() {}); setState(() {});
}, },
), ),
), ),
SizedBox(height: 8,), const SizedBox(height: 8),
DepartmentButton( DepartmentButton(
department: _user.department, department: _user.department,
onDepartmentPick: (department){ onDepartmentPick: (department) {
_user.department = department; _user.department = department;
setState(() {}); setState(() {});
}, },
), ),
SizedBox(height: 8,), const SizedBox(height: 8),
ATextFormField( ATextFormField(
initialValue: _user.phoneNumber, initialValue: _user.phoneNumber,
hintText: _subtitle.phoneNumber, hintText: subtitle.phoneNumber,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.titleLarge,
prefixIconData: Icons.phone_android, prefixIconData: Icons.phone_android,
validator: (value) => validator: (value) => Validator.isPhoneNumber(value!) ? '' : subtitle.phoneNumberValidateMessage,
Validator.isPhoneNumber(value!) ? '' : _subtitle.phoneNumberValidateMessage,
textInputType: TextInputType.phone, textInputType: TextInputType.phone,
onSaved: (value){ onSaved: (value) {
_user.phoneNumber = value; _user.phoneNumber = value;
}, },
), ),
SizedBox(height: 8,), const SizedBox(height: 8),
ATextFormField( ATextFormField(
initialValue: _user.whatsApp, initialValue: _user.whatsApp,
hintText: _subtitle.whatsApp, hintText: subtitle.whatsApp,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.titleLarge,
prefixIconData: FontAwesomeIcons.whatsapp, prefixIconData: FontAwesomeIcons.whatsapp,
prefixIconSize: 36, prefixIconSize: 36,
validator: (value) => validator: (value) => Validator.isPhoneNumber(value!) ? '' : subtitle.phoneNumberValidateMessage,
Validator.isPhoneNumber(value!) ? '' : _subtitle.phoneNumberValidateMessage,
textInputType: TextInputType.phone, textInputType: TextInputType.phone,
onSaved: (value){ onSaved: (value) {
_user.whatsApp = value; _user.whatsApp = value;
}, },
), ),
], ],
), ),
), ),
SizedBox(height: 16,), const SizedBox(height: 16),
Center( Center(
child: SizedBox( child: SizedBox(
height: _width / 8, height: _width / 8,
width: _width/1.2, width: _width / 1.2,
child: AButton( child: AButton(
text: _subtitle.update, text: subtitle.update,
onPressed: () async { onPressed: () async {
if(!(_formKey.currentState?.validate()??false)) if (_formKey.currentState?.validate() ?? false) {
return;
_formKey.currentState?.save(); _formKey.currentState?.save();
if(_user.department?.id == null){ await _userProvider.updateProfile(context, updatedUser: _user);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
_subtitle.unitRequired
),
)
);
return;
}
int status = await _userProvider.updateProfile(
user: _user,
host: _settingProvider.host!,
);
if(status >= 200 && status < 300){
_settingProvider.setUser(_userProvider.user!);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
_subtitle.requestCompleteSuccessfully
),
)
);
}else{
String errorMessage = HttpStatusManger.getStatusMessage(
status: status, subtitle: _subtitle);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
errorMessage
),
)
);
} }
}, },
), ),
), ),
), ),
SizedBox(height: 32,), const SizedBox(height: 32),
], ],
), ),
), ),
ABackButton(), const ABackButton(),
], ],
), ),
), ),

@ -2,10 +2,11 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../api/user_api_client.dart';
import '../../../controllers/localization/localization.dart'; import '../../../controllers/localization/localization.dart';
import '../../../controllers/providers/api/service_requests_provider.dart'; import '../../../controllers/providers/api/service_requests_provider.dart';
import '../../../controllers/providers/api/user_provider.dart';
import '../../../controllers/providers/settings/setting_provider.dart'; import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../controllers/providers/user_provider.dart';
import '../../../controllers/validator/validator.dart'; import '../../../controllers/validator/validator.dart';
import '../../../models/issue.dart'; import '../../../models/issue.dart';
import '../../../models/service_request/service_request.dart'; import '../../../models/service_request/service_request.dart';
@ -67,12 +68,7 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
), ),
child: Text( child: Text(
_subtitle.reportIssue, _subtitle.reportIssue,
style: Theme.of(context) style: Theme.of(context).textTheme.headline5?.copyWith(color: AColors.cyan, fontWeight: FontWeight.bold),
.textTheme
.headline5
?.copyWith(
color: AColors.cyan,
fontWeight: FontWeight.bold),
), ),
), ),
), ),
@ -88,10 +84,8 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: AColors.grey, color: AColors.grey,
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular( topLeft: Radius.circular(AppStyle.getBorderRadius(context)),
AppStyle.getBorderRadius(context)), topRight: Radius.circular(AppStyle.getBorderRadius(context)),
topRight: Radius.circular(
AppStyle.getBorderRadius(context)),
), ),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
@ -107,9 +101,7 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
hintText: _subtitle.title, hintText: _subtitle.title,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.headline6,
validator: (value) => Validator.hasValue(value!) validator: (value) => Validator.hasValue(value!) ? '' : _subtitle.titleValidateMessage,
? ''
: _subtitle.titleValidateMessage,
textInputType: TextInputType.name, textInputType: TextInputType.name,
onSaved: (value) { onSaved: (value) {
_issue.title = value; _issue.title = value;
@ -122,8 +114,7 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
children: List.generate( children: List.generate(
_issues.length, _issues.length,
(index) => ReportIssueItem( (index) => ReportIssueItem(
isSelected: isSelected: _issue.reports?.contains(index),
_issue.reports?.contains(index),
issueInfo: _issues[index], issueInfo: _issues[index],
onChange: (info, value) { onChange: (info, value) {
if (value) { if (value) {
@ -154,16 +145,13 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
child: AButton( child: AButton(
text: _subtitle.submit, text: _subtitle.submit,
onPressed: () async { onPressed: () async {
if (!(_formKey.currentState?.validate() ?? if (!(_formKey.currentState?.validate() ?? false)) return;
false)) return;
_formKey.currentState?.save(); _formKey.currentState?.save();
_issue.serviceRequestId = _issue.serviceRequestId = widget.serviceRequest?.id;
widget.serviceRequest?.id;
_isLoading = true; _isLoading = true;
setState(() {}); setState(() {});
int status = await _serviceRequestsProvider int status = await _serviceRequestsProvider.createIssueReport(
.createIssueReport( user: UserApiClient().user ?? User(),
user: _userProvider.user ?? User(),
host: _settingProvider.host ?? "", host: _settingProvider.host ?? "",
issue: _issue, issue: _issue,
); );
@ -171,8 +159,7 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
setState(() {}); setState(() {});
if (status >= 200 && status < 300) { if (status >= 200 && status < 300) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: msg: _subtitle.requestCompleteSuccessfully,
_subtitle.requestCompleteSuccessfully,
); );
Navigator.of(context).pop(); Navigator.of(context).pop();
} }

@ -6,11 +6,12 @@ import 'package:fluttertoast/fluttertoast.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../api/user_api_client.dart';
import '../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/service_requests_provider.dart'; import '../../../../controllers/providers/api/service_requests_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../controllers/validator/validator.dart'; import '../../../../controllers/validator/validator.dart';
import '../../../../extensions/int_extensions.dart'; import '../../../../extensions/int_extensions.dart';
import '../../../../extensions/widget_extensions.dart'; import '../../../../extensions/widget_extensions.dart';
@ -100,12 +101,7 @@ class _CreateRequestPageState extends State<CreateRequestPage> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
_subtitle.newServiceRequest, _subtitle.newServiceRequest,
style: Theme.of(context) style: Theme.of(context).textTheme.headline5?.copyWith(color: AColors.cyan, fontWeight: FontWeight.w600),
.textTheme
.headline5
?.copyWith(
color: AColors.cyan,
fontWeight: FontWeight.w600),
), ),
), ),
), ),
@ -113,25 +109,21 @@ class _CreateRequestPageState extends State<CreateRequestPage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
12.height, 12.height,
_userProvider.user?.hospital == null UserApiClient().user?.hospital == null
? SizedBox.shrink() ? SizedBox.shrink()
: ATextFormField( : ATextFormField(
enable: false, enable: false,
initialValue: initialValue: UserApiClient().user?.hospital?.name ?? _subtitle.noHospitalFound,
_userProvider.user?.hospital?.name ??
_subtitle.noHospitalFound,
hintText: _subtitle.hospital, hintText: _subtitle.hospital,
prefixIconData: FontAwesomeIcons.hospital, prefixIconData: FontAwesomeIcons.hospital,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
), ),
12.height, 12.height,
_userProvider.user?.department == null UserApiClient().user?.department == null
? SizedBox.shrink() ? SizedBox.shrink()
: ATextFormField( : ATextFormField(
enable: false, enable: false,
initialValue: initialValue: UserApiClient().user?.department?.name ?? _subtitle.noUniteFound,
_userProvider.user?.department?.name ??
_subtitle.noUniteFound,
hintText: _subtitle.unite, hintText: _subtitle.unite,
prefixIconData: FontAwesomeIcons.hospitalUser, prefixIconData: FontAwesomeIcons.hospitalUser,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
@ -185,9 +177,7 @@ class _CreateRequestPageState extends State<CreateRequestPage> {
prefixIconData: FontAwesomeIcons.triangleExclamation, prefixIconData: FontAwesomeIcons.triangleExclamation,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.headline6,
textInputType: TextInputType.multiline, textInputType: TextInputType.multiline,
validator: (value) => Validator.hasValue(value!) validator: (value) => Validator.hasValue(value!) ? '' : _subtitle.maintenanceIssueRequired,
? ''
: _subtitle.maintenanceIssueRequired,
onSaved: (value) { onSaved: (value) {
_serviceRequest.maintenanceIssue = value; _serviceRequest.maintenanceIssue = value;
}, },
@ -204,23 +194,18 @@ class _CreateRequestPageState extends State<CreateRequestPage> {
child: AButton( child: AButton(
text: _subtitle.submit, text: _subtitle.submit,
onPressed: () async { onPressed: () async {
if (!(_formKey.currentState?.validate() ?? false)) if (!(_formKey.currentState?.validate() ?? false)) return;
return;
_formKey.currentState?.save(); _formKey.currentState?.save();
_serviceRequest.deviceId = _device?.id ?? ""; _serviceRequest.deviceId = _device?.id ?? "";
_isLoading = true; _isLoading = true;
setState(() {}); setState(() {});
_serviceRequest.devicePhotos = _deviceImages _serviceRequest.devicePhotos = _deviceImages.map((e) => base64Encode(e.readAsBytesSync())).toList();
.map((e) => base64Encode(e.readAsBytesSync()))
.toList();
if (_serviceRequest.audio != null) { if (_serviceRequest.audio != null) {
final file = File(_serviceRequest.audio!); final file = File(_serviceRequest.audio!);
_serviceRequest.audio = _serviceRequest.audio = base64Encode(file.readAsBytesSync());
base64Encode(file.readAsBytesSync());
} }
int status = int status = await _serviceRequestsProvider.createRequest(
await _serviceRequestsProvider.createRequest( user: UserApiClient().user!,
user: _userProvider.user!,
host: _settingProvider.host ?? "", host: _settingProvider.host ?? "",
serviceRequest: _serviceRequest, serviceRequest: _serviceRequest,
); );
@ -232,9 +217,7 @@ class _CreateRequestPageState extends State<CreateRequestPage> {
); );
Navigator.of(context).pop(); Navigator.of(context).pop();
} else { } else {
String errorMessage = String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle);
HttpStatusManger.getStatusMessage(
status: status, subtitle: _subtitle);
ScaffoldMessenger.of(context).showSnackBar(SnackBar( ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(errorMessage), content: Text(errorMessage),
)); ));

@ -1,10 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../api/user_api_client.dart';
import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/service_requests_provider.dart'; import '../../../../controllers/providers/api/service_requests_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../models/service_request/service_request.dart'; import '../../../../models/service_request/service_request.dart';
import '../../../../models/subtitle.dart'; import '../../../../models/subtitle.dart';
import '../../../widgets/loaders/app_loading.dart'; import '../../../widgets/loaders/app_loading.dart';
@ -17,12 +18,10 @@ class FutureRequestServiceDetails extends StatefulWidget {
const FutureRequestServiceDetails({super.key}); const FutureRequestServiceDetails({super.key});
@override @override
_FutureRequestServiceDetailsState createState() => _FutureRequestServiceDetailsState createState() => _FutureRequestServiceDetailsState();
_FutureRequestServiceDetailsState();
} }
class _FutureRequestServiceDetailsState class _FutureRequestServiceDetailsState extends State<FutureRequestServiceDetails> {
extends State<FutureRequestServiceDetails> {
late UserProvider _userProvider; late UserProvider _userProvider;
late SettingProvider _settingProvider; late SettingProvider _settingProvider;
@override @override
@ -33,13 +32,8 @@ class _FutureRequestServiceDetailsState
Subtitle _subtitle = AppLocalization.of(context)!.subtitle!; Subtitle _subtitle = AppLocalization.of(context)!.subtitle!;
return Scaffold( return Scaffold(
body: FutureBuilder<ServiceRequest>( body: FutureBuilder<ServiceRequest>(
future: ServiceRequestsProvider().getSingleServiceRequest( future: ServiceRequestsProvider().getSingleServiceRequest(requestId: requestId ?? '', user: UserApiClient().user!, host: _settingProvider.host ?? "", subtitle: _subtitle),
requestId: requestId ?? '', builder: (BuildContext context, AsyncSnapshot<ServiceRequest> snapshot) {
user: _userProvider.user!,
host: _settingProvider.host ?? "",
subtitle: _subtitle),
builder:
(BuildContext context, AsyncSnapshot<ServiceRequest> snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
return FailedLoading( return FailedLoading(
message: snapshot.error.toString(), message: snapshot.error.toString(),

@ -2,15 +2,14 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../../api/user_api_client.dart';
import '../../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../../../controllers/localization/localization.dart'; import '../../../../../controllers/localization/localization.dart';
import '../../../../../controllers/providers/api/service_requests_provider.dart'; import '../../../../../controllers/providers/api/service_requests_provider.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../controllers/providers/api/user_provider.dart';
import '../../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../../controllers/validator/validator.dart'; import '../../../../../controllers/validator/validator.dart';
import '../../../../../models/device/device.dart'; import '../../../../../models/device/device.dart';
@ -37,19 +36,18 @@ import '../../../../widgets/status/report/service_report_status.dart';
import '../../../../widgets/status/report/service_status.dart'; import '../../../../widgets/status/report/service_status.dart';
import '../../../../widgets/timer/app_timer.dart'; import '../../../../widgets/timer/app_timer.dart';
import '../../../../widgets/titles/app_sub_title.dart'; import '../../../../widgets/titles/app_sub_title.dart';
class CreateServiceReport extends StatefulWidget { class CreateServiceReport extends StatefulWidget {
static final String id = "/create-service-report"; static const String id = "/create-service-report";
final ServiceRequest? request ; final ServiceRequest? request;
const CreateServiceReport({Key? key, this.request}) : super(key: key); const CreateServiceReport({Key? key, this.request}) : super(key: key);
@override @override
_CreateServiceReportState createState() => _CreateServiceReportState(); CreateServiceReportState createState() => CreateServiceReportState();
} }
class _CreateServiceReportState extends State<CreateServiceReport> with TickerProviderStateMixin{ class CreateServiceReportState extends State<CreateServiceReport> with TickerProviderStateMixin {
UserProvider? _userProvider;
SettingProvider? _settingProvider; SettingProvider? _settingProvider;
ServiceRequestsProvider? _serviceRequestsProvider; ServiceRequestsProvider? _serviceRequestsProvider;
@ -61,8 +59,8 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
File? _image; File? _image;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
TextEditingController _faultController = TextEditingController(); final TextEditingController _faultController = TextEditingController();
TextEditingController _workPreformedController = TextEditingController(); final TextEditingController _workPreformedController = TextEditingController();
@override @override
void initState() { void initState() {
@ -73,8 +71,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
id: widget.request?.deviceId, id: widget.request?.deviceId,
serialNumber: widget.request?.deviceSerialNumber, serialNumber: widget.request?.deviceSerialNumber,
), ),
parts: [] parts: []);
);
super.initState(); super.initState();
} }
@ -84,9 +81,9 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
_workPreformedController.dispose(); _workPreformedController.dispose();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context); _settingProvider = Provider.of<SettingProvider>(context);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context); _serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
_subtitle = AppLocalization.of(context)?.subtitle; _subtitle = AppLocalization.of(context)?.subtitle;
@ -105,43 +102,46 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
ListView( ListView(
children: [ children: [
//AppNameBar(), //AppNameBar(),
const SizedBox(height: 16,), const SizedBox(
height: 16,
),
Center( Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
_subtitle?.newServiceReport??"", _subtitle?.newServiceReport ?? "",
style: Theme.of(context).textTheme.headline5?.copyWith( style: Theme.of(context).textTheme.headline5?.copyWith(color: AColors.cyan, fontSize: 28, fontWeight: FontWeight.bold),
color: AColors.cyan,
fontSize: 28,
fontWeight: FontWeight.bold
),
), ),
), ),
), ),
Container( Container(
padding: const EdgeInsets.symmetric(horizontal: 16), padding: const EdgeInsets.symmetric(horizontal: 16),
margin: const EdgeInsets.symmetric(horizontal: 16,vertical: 16), margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
decoration: BoxDecoration( decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [
color: AColors.grey,
borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)),
boxShadow: [
const BoxShadow( const BoxShadow(
color: AColors.grey, color: AColors.grey,
offset: Offset(0,-1), offset: Offset(0, -1),
) )
] ]),
),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
Wrap( Wrap(
spacing: 10, spacing: 10,
children: [ children: [
ASubTitle("${_subtitle?.callId}: ${widget.request?.requestCode}",font: 14,), ASubTitle(
widget.request?.deviceSerialNumber == null ? const SizedBox(): "${_subtitle?.callId}: ${widget.request?.requestCode}",
ASubTitle("${_subtitle?.deviceSN}: ${widget.request?.deviceSerialNumber}",font: 14,), font: 14,
),
widget.request?.deviceSerialNumber == null
? const SizedBox()
: ASubTitle(
"${_subtitle?.deviceSN}: ${widget.request?.deviceSerialNumber}",
font: 14,
),
Text( Text(
"${_subtitle?.customer}: ${widget.request?.hospitalName}", "${_subtitle?.customer}: ${widget.request?.hospitalName}",
style: Theme.of(context).textTheme.subtitle1?.copyWith( style: Theme.of(context).textTheme.subtitle1?.copyWith(
@ -150,7 +150,6 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
), ),
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
) )
], ],
), ),
const Divider(), const Divider(),
@ -183,18 +182,21 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.visitDate??""), ASubTitle(_subtitle?.visitDate ?? ""),
_validate && _serviceReport?.visitDate == null ? _validate && _serviceReport?.visitDate == null
ASubTitle(_subtitle?.requiredWord??"",color: Colors.red,): ? ASubTitle(
const SizedBox.shrink(), _subtitle?.requiredWord ?? "",
color: Colors.red,
)
: const SizedBox.shrink(),
Row( Row(
children: [ children: [
Expanded( Expanded(
child: ADatePicker( child: ADatePicker(
date: _serviceReport?.visitDate??DateTime.now(), date: _serviceReport?.visitDate ?? DateTime.now(),
from: DateTime.now().subtract(const Duration(days: 365)), from: DateTime.now().subtract(const Duration(days: 365)),
to: DateTime.now().add(const Duration(days: 365)), to: DateTime.now().add(const Duration(days: 365)),
onDatePicker: (date){ onDatePicker: (date) {
_serviceReport?.visitDate = date; _serviceReport?.visitDate = date;
setState(() {}); setState(() {});
}, },
@ -205,44 +207,59 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
], ],
), ),
), ),
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// device sn // device sn
Visibility( Visibility(
visible: widget.request?.deviceSerialNumber == null, visible: widget.request?.deviceSerialNumber == null,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.deviceSN??""), ASubTitle(_subtitle?.deviceSN ?? ""),
_validate && _serviceReport?.device?.id == null ? _validate && _serviceReport?.device?.id == null
ASubTitle(_subtitle?.requiredWord??"",color: Colors.red,): ? ASubTitle(
const SizedBox.shrink(), _subtitle?.requiredWord ?? "",
color: Colors.red,
)
: const SizedBox.shrink(),
AutoCompleteDeviceField( AutoCompleteDeviceField(
hospitalId: widget.request?.hospitalId??"", hospitalId: widget.request?.hospitalId ?? "",
initialValue: _serviceReport!.device!, initialValue: _serviceReport!.device!,
onPick: (id){ onPick: (id) {
_serviceReport?.device?.id = id; _serviceReport?.device?.id = id;
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
], ],
), ),
), ),
const SizedBox(height: 8,), const SizedBox(
ASubTitle(_subtitle?.serviceType??""), height: 8,
_validate && _serviceReport?.serviceType == null ? ),
ASubTitle(_subtitle?.requiredWord??"",color: Colors.red,): ASubTitle(_subtitle?.serviceType ?? ""),
const SizedBox.shrink(), _validate && _serviceReport?.serviceType == null
const SizedBox(height: 4,), ? ASubTitle(
_subtitle?.requiredWord ?? "",
color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
ServiceStatusMenu( ServiceStatusMenu(
initialValue: _serviceReport?.serviceType, initialValue: _serviceReport?.serviceType,
onSelect: (status){ onSelect: (status) {
_serviceReport?.serviceType = status; _serviceReport?.serviceType = status;
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// Report status and Service Type // Report status and Service Type
Row( Row(
children: [ children: [
@ -251,39 +268,50 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.reportStatus??""), ASubTitle(_subtitle?.reportStatus ?? ""),
_validate && _serviceReport?.status == null ? _validate && _serviceReport?.status == null
ASubTitle(_subtitle?.requiredWord??"",color: Colors.red,): ? ASubTitle(
const SizedBox.shrink(), _subtitle?.requiredWord ?? "",
const SizedBox(height: 4,), color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
ServiceReportStatusMenu( ServiceReportStatusMenu(
report: _serviceReport, report: _serviceReport,
onSelect: (status){ onSelect: (status) {
_serviceReport?.status = status; _serviceReport?.status = status;
}, },
), ),
], ],
), ),
), ),
const SizedBox(width: 8,), const SizedBox(
width: 8,
),
Provider.of<ServiceReportLastCallsProvider>(context).isLoading == null Provider.of<ServiceReportLastCallsProvider>(context).isLoading == null
? const SizedBox.shrink(): ? const SizedBox.shrink()
:
// Call's last Situation // Call's last Situation
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.callLastSituation ?? ""),
ASubTitle(_subtitle?.callLastSituation??""), _validate && _serviceReport?.callLastSituation == null
_validate && _serviceReport?.callLastSituation == null ? ? ASubTitle(
ASubTitle(_subtitle?.requiredWord??"",color: Colors.red,): _subtitle?.requiredWord ?? "",
const SizedBox.shrink(), color: Colors.red,
const SizedBox(height: 4,), )
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
ServiceReportLastCallsMenu( ServiceReportLastCallsMenu(
report: _serviceReport, report: _serviceReport,
onSelect: (status){ onSelect: (status) {
if(status?.id == 12 if (status?.id == 12 || _serviceReport?.callLastSituation?.id == 12) {
|| _serviceReport?.callLastSituation?.id == 12){
_serviceReport?.callLastSituation = status; _serviceReport?.callLastSituation = status;
setState(() {}); setState(() {});
} else { } else {
@ -296,48 +324,53 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
), ),
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// invoice number & code // invoice number & code
_serviceReport?.callLastSituation?.id != 12 ? const SizedBox.shrink(): _serviceReport?.callLastSituation?.id != 12
Row( ? const SizedBox.shrink()
: Row(
children: [ children: [
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.invoiceNumber??""), ASubTitle(_subtitle?.invoiceNumber ?? ""),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.invoiceNumber??"", initialValue: _serviceReport?.invoiceNumber ?? "",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
validator: (value) => validator: (value) => Validator.hasValue(value!) ? '' : _subtitle?.requiredWord ?? "",
Validator.hasValue(value!)
? '' : _subtitle?.requiredWord??"",
textInputType: TextInputType.number, textInputType: TextInputType.number,
onSaved: (value){ onSaved: (value) {
_serviceReport?.invoiceNumber = value; _serviceReport?.invoiceNumber = value;
}, },
), ),
], ],
), ),
), ),
const SizedBox(width: 8,), const SizedBox(
width: 8,
),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.invoiceCode??""), ASubTitle(_subtitle?.invoiceCode ?? ""),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.invoiceCode??"", initialValue: _serviceReport?.invoiceCode ?? "",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
validator: (value) => validator: (value) => Validator.hasValue(value!) ? '' : _subtitle?.requiredWord ?? "",
Validator.hasValue(value!)
? '' : _subtitle?.requiredWord??"",
textInputType: TextInputType.text, textInputType: TextInputType.text,
onSaved: (value){ onSaved: (value) {
_serviceReport?.invoiceCode = value; _serviceReport?.invoiceCode = value;
}, },
), ),
@ -347,10 +380,12 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
Row( Row(
children: [ children: [
ASubTitle(_subtitle?.faultDescription??""), ASubTitle(_subtitle?.faultDescription ?? ""),
Expanded( Expanded(
child: SizedBox( child: SizedBox(
height: 32 * AppStyle.getScaleFactor(context), height: 32 * AppStyle.getScaleFactor(context),
@ -362,24 +397,26 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
), ),
], ],
), ),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.faultDescription??"", initialValue: _serviceReport?.faultDescription ?? "",
textAlign: TextAlign.center, textAlign: TextAlign.center,
controller: _faultController, controller: _faultController,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
validator: (value) => validator: (value) => Validator.hasValue(value!) ? '' : _subtitle?.requiredWord ?? "",
Validator.hasValue(value!)
? '' : _subtitle?.requiredWord??"",
textInputType: TextInputType.multiline, textInputType: TextInputType.multiline,
onSaved: (value){ onSaved: (value) {
_serviceReport?.faultDescription = value; _serviceReport?.faultDescription = value;
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
Row( Row(
children: [ children: [
ASubTitle(_subtitle?.workPreformed??""), ASubTitle(_subtitle?.workPreformed ?? ""),
Expanded( Expanded(
child: SizedBox( child: SizedBox(
height: 32 * AppStyle.getScaleFactor(context), height: 32 * AppStyle.getScaleFactor(context),
@ -391,23 +428,27 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
), ),
], ],
), ),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.workPreformed??"", initialValue: _serviceReport?.workPreformed ?? "",
textAlign: TextAlign.center, textAlign: TextAlign.center,
controller: _workPreformedController, controller: _workPreformedController,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
validator: (value) => validator: (value) => Validator.hasValue(value!) ? '' : _subtitle?.requiredWord ?? "",
Validator.hasValue(value!)
? '' : _subtitle?.requiredWord??"",
textInputType: TextInputType.multiline, textInputType: TextInputType.multiline,
onSaved: (value){ onSaved: (value) {
_serviceReport?.workPreformed = value; _serviceReport?.workPreformed = value;
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
Row( Row(
children: [ children: [
// reasons // reasons
@ -415,28 +456,32 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.reasons??""), ASubTitle(_subtitle?.reasons ?? ""),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ServiceReportReasonsMenu( ServiceReportReasonsMenu(
initialValue: _serviceReport?.reason, initialValue: _serviceReport?.reason,
onSelect: (status){ onSelect: (status) {
_serviceReport?.reason = status; _serviceReport?.reason = status;
}, },
), ),
], ],
), ),
), ),
const SizedBox(width: 8,), const SizedBox(
width: 8,
),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.attachImage??""), ASubTitle(_subtitle?.attachImage ?? ""),
AMiniOneImagePicker( AMiniOneImagePicker(
//error: _validate && _serviceReport.image == null, //error: _validate && _serviceReport.image == null,
image: _image, image: _image,
onPick: (image){ onPick: (image) {
_image =image; _image = image;
_serviceReport?.image = base64Encode(image.readAsBytesSync()); _serviceReport?.image = base64Encode(image.readAsBytesSync());
}, },
), ),
@ -445,7 +490,9 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
), ),
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// Traveling Hours & Working Hours // Traveling Hours & Working Hours
Row( Row(
children: [ children: [
@ -453,11 +500,13 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.workingHours??""), ASubTitle(_subtitle?.workingHours ?? ""),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
AppTimer( AppTimer(
timer: _serviceReport?.timer, timer: _serviceReport?.timer,
onChange: (timer) async{ onChange: (timer) async {
_serviceReport?.timer = timer; _serviceReport?.timer = timer;
return true; return true;
}, },
@ -478,13 +527,17 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
], ],
), ),
), ),
const SizedBox(width: 8,), const SizedBox(
width: 8,
),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.travelingHours??""), ASubTitle(_subtitle?.travelingHours ?? ""),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.travelingHours, initialValue: _serviceReport?.travelingHours,
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -494,7 +547,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
// Validator.isNumeric(value) // Validator.isNumeric(value)
// ? null : _subtitle.requiredWord, // ? null : _subtitle.requiredWord,
textInputType: TextInputType.number, textInputType: TextInputType.number,
onSaved: (value){ onSaved: (value) {
_serviceReport?.travelingHours = value; _serviceReport?.travelingHours = value;
}, },
), ),
@ -503,7 +556,9 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
), ),
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// Operating Hours and Job Sheet Number // Operating Hours and Job Sheet Number
Row( Row(
children: [ children: [
@ -534,14 +589,16 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.jobSheetNumber??""), ASubTitle(_subtitle?.jobSheetNumber ?? ""),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.jobSheetNumber, initialValue: _serviceReport?.jobSheetNumber,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
textInputType: TextInputType.name, textInputType: TextInputType.name,
onSaved: (value){ onSaved: (value) {
_serviceReport?.jobSheetNumber = value; _serviceReport?.jobSheetNumber = value;
}, },
), ),
@ -550,7 +607,9 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
), ),
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// Part Number and Quantity // Part Number and Quantity
Row( Row(
children: [ children: [
@ -559,95 +618,92 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle?.partNumber??""), ASubTitle(_subtitle?.partNumber ?? ""),
_validate && _serviceReport?.parts == null ? _validate && _serviceReport?.parts == null
ASubTitle(_subtitle?.requiredWord??"",color: Colors.red,): ? ASubTitle(
const SizedBox.shrink(), _subtitle?.requiredWord ?? "",
const SizedBox(height: 4,), color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
AutoCompletePartsField( AutoCompletePartsField(
onPick: (part){ onPick: (part) {
_serviceReport?.parts?.add(part); _serviceReport?.parts?.add(part);
}, },
), ),
], ],
), ),
), ),
], ],
), ),
SizedBox(height: 8*AppStyle.getScaleFactor(context),), SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
Row( Row(
children: [ children: [
Expanded(flex:3,child: Text(_subtitle?.number??"")), Expanded(flex: 3, child: Text(_subtitle?.number ?? "")),
Expanded(flex: 1,child: Text(_subtitle?.quantity??"")), Expanded(flex: 1, child: Text(_subtitle?.quantity ?? "")),
], ],
), ),
Column( Column(
children: List.generate( children: List.generate(_serviceReport!.parts!.length, (index) {
_serviceReport!.parts!.length,
(index) {
Part _part = _serviceReport!.parts![index]; Part _part = _serviceReport!.parts![index];
return PartItem( return PartItem(
part: _part, part: _part,
onDelete: (part){ onDelete: (part) {
_serviceReport!.parts!.remove(part); _serviceReport!.parts!.remove(part);
setState(() {}); setState(() {});
}, },
); );
} }),
), ),
),
const SizedBox(height: 16,),
const SizedBox(
height: 16,
),
], ],
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: AButton( child: AButton(
text: _subtitle?.submit??"", text: _subtitle?.submit ?? "",
onPressed: () async { onPressed: () async {
_validate = true; _validate = true;
if(!(_formKey.currentState?.validate()??false)){ if (!(_formKey.currentState?.validate() ?? false)) {
setState(() {}); setState(() {});
return; return;
} }
if(!(_serviceReport?.validate()??false)) return; if (!(_serviceReport?.validate() ?? false)) return;
_formKey.currentState?.save(); _formKey.currentState?.save();
_isLoading =true; _isLoading = true;
setState(() {}); setState(() {});
int? status = await _serviceRequestsProvider?.createServiceReport( int? status =
user: _userProvider!.user!, await _serviceRequestsProvider?.createServiceReport(user: UserApiClient().user!, host: _settingProvider?.host ?? "", report: _serviceReport!, request: widget.request!);
host: _settingProvider?.host??"", _isLoading = false;
report: _serviceReport!,
request: widget.request!
);
_isLoading =false;
setState(() {}); setState(() {});
if(status != null && status >= 200 && status < 300){ if (status != null && status >= 200 && status < 300) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: _subtitle?.requestCompleteSuccessfully??"", msg: _subtitle?.requestCompleteSuccessfully ?? "",
); );
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.of(context).pop(); Navigator.of(context).pop();
}else{ } else {
String errorMessage = HttpStatusManger.getStatusMessage( String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle);
status: status, subtitle: _subtitle); ScaffoldMessenger.of(context).showSnackBar(SnackBar(
ScaffoldMessenger.of(context).showSnackBar( content: Text(errorMessage),
SnackBar( ));
content: Text(
errorMessage
),
)
);
} }
}, },
), ),
), ),
const SizedBox(height: 300,) const SizedBox(
height: 300,
)
], ],
), ),
const ABackButton(), const ABackButton(),

@ -2,16 +2,16 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../../api/user_api_client.dart';
import '../../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../../../controllers/localization/localization.dart'; import '../../../../../controllers/localization/localization.dart';
import '../../../../../controllers/providers/api/service_requests_provider.dart'; import '../../../../../controllers/providers/api/service_requests_provider.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../controllers/providers/api/user_provider.dart';
import '../../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../../controllers/providers/user_provider.dart';
import '../../../../../controllers/validator/validator.dart'; import '../../../../../controllers/validator/validator.dart';
import '../../../../../models/part.dart'; import '../../../../../models/part.dart';
import '../../../../../models/service_report.dart'; import '../../../../../models/service_report.dart';
@ -39,7 +39,7 @@ import '../../../../widgets/titles/app_sub_title.dart';
class EditServiceReport extends StatefulWidget { class EditServiceReport extends StatefulWidget {
static final String id = "/edit-service-report"; static final String id = "/edit-service-report";
final ServiceRequest request ; final ServiceRequest request;
final ServiceReport report; final ServiceReport report;
const EditServiceReport({Key? key, required this.request, required this.report}) : super(key: key); const EditServiceReport({Key? key, required this.request, required this.report}) : super(key: key);
@ -47,9 +47,7 @@ class EditServiceReport extends StatefulWidget {
_EditServiceReportState createState() => _EditServiceReportState(); _EditServiceReportState createState() => _EditServiceReportState();
} }
class _EditServiceReportState extends State<EditServiceReport> with TickerProviderStateMixin{ class _EditServiceReportState extends State<EditServiceReport> with TickerProviderStateMixin {
late UserProvider _userProvider; late UserProvider _userProvider;
late SettingProvider _settingProvider; late SettingProvider _settingProvider;
late ServiceRequestsProvider _serviceRequestsProvider; late ServiceRequestsProvider _serviceRequestsProvider;
@ -77,6 +75,7 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
_workPreformedController.dispose(); _workPreformedController.dispose();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context); _userProvider = Provider.of<UserProvider>(context);
@ -98,43 +97,46 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
ListView( ListView(
children: [ children: [
//AppNameBar(), //AppNameBar(),
const SizedBox(height: 16,), const SizedBox(
height: 16,
),
Center( Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
_subtitle.editServiceReport, _subtitle.editServiceReport,
style: Theme.of(context).textTheme.headline5?.copyWith( style: Theme.of(context).textTheme.headline5?.copyWith(color: AColors.cyan, fontSize: 28, fontWeight: FontWeight.bold),
color: AColors.cyan,
fontSize: 28,
fontWeight: FontWeight.bold
),
), ),
), ),
), ),
Container( Container(
padding: const EdgeInsets.symmetric(horizontal: 16), padding: const EdgeInsets.symmetric(horizontal: 16),
margin: const EdgeInsets.symmetric(horizontal: 16,vertical: 16), margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
decoration: BoxDecoration( decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [
color: AColors.grey,
borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)),
boxShadow: [
BoxShadow( BoxShadow(
color: AColors.grey, color: AColors.grey,
offset: Offset(0,-1), offset: Offset(0, -1),
) )
] ]),
),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
Wrap( Wrap(
spacing: 10, spacing: 10,
children: [ children: [
ASubTitle("${_subtitle.callId}: ${widget.request.requestCode}",font: 14,), ASubTitle(
widget.request.deviceSerialNumber == null ? const SizedBox(): "${_subtitle.callId}: ${widget.request.requestCode}",
ASubTitle("${_subtitle.deviceSN}: ${widget.request.deviceSerialNumber}",font: 14,), font: 14,
),
widget.request.deviceSerialNumber == null
? const SizedBox()
: ASubTitle(
"${_subtitle.deviceSN}: ${widget.request.deviceSerialNumber}",
font: 14,
),
Text( Text(
"${_subtitle.customer}: ${widget.request.hospitalName}", "${_subtitle.customer}: ${widget.request.hospitalName}",
style: Theme.of(context).textTheme.subtitle1?.copyWith( style: Theme.of(context).textTheme.subtitle1?.copyWith(
@ -143,7 +145,6 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
), ),
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
) )
], ],
), ),
const Divider(), const Divider(),
@ -157,29 +158,39 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.reportType), ASubTitle(_subtitle.reportType),
_validate && _serviceReport.type == null ? _validate && _serviceReport.type == null
ASubTitle(_subtitle.requiredWord,color: Colors.red,): ? ASubTitle(
const SizedBox.shrink(), _subtitle.requiredWord,
const SizedBox(height: 4,), color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
ServiceReportTypeMenu( ServiceReportTypeMenu(
initialValue: _serviceReport.type, initialValue: _serviceReport.type,
onSelect: (status){ onSelect: (status) {
_serviceReport.type = status; _serviceReport.type = status;
}, },
), ),
], ],
), ),
), ),
const SizedBox(width: 8,), const SizedBox(
width: 8,
),
// visit date // visit date
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.visitDate), ASubTitle(_subtitle.visitDate),
_validate && _serviceReport.visitDate == null ? _validate && _serviceReport.visitDate == null
ASubTitle(_subtitle.requiredWord,color: Colors.red,): ? ASubTitle(
const SizedBox.shrink(), _subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
Row( Row(
children: [ children: [
Expanded( Expanded(
@ -187,7 +198,7 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
date: _serviceReport.visitDate, date: _serviceReport.visitDate,
from: DateTime.now().subtract(const Duration(days: 365)), from: DateTime.now().subtract(const Duration(days: 365)),
to: DateTime.now().add(const Duration(days: 365)), to: DateTime.now().add(const Duration(days: 365)),
onDatePicker: (date){ onDatePicker: (date) {
_serviceReport.visitDate = date; _serviceReport.visitDate = date;
setState(() {}); setState(() {});
}, },
@ -198,44 +209,59 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
], ],
), ),
), ),
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// device sn // device sn
Visibility( Visibility(
visible: true,//widget.report.device == null, visible: true, //widget.report.device == null,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.deviceSN), ASubTitle(_subtitle.deviceSN),
_validate && _serviceReport.device?.id == null ? _validate && _serviceReport.device?.id == null
ASubTitle(_subtitle.requiredWord,color: Colors.red,): ? ASubTitle(
const SizedBox.shrink(), _subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
AutoCompleteDeviceField( AutoCompleteDeviceField(
hospitalId: widget.request.hospitalId, hospitalId: widget.request.hospitalId,
initialValue: _serviceReport.device!, initialValue: _serviceReport.device!,
onPick: (id){ onPick: (id) {
_serviceReport.device?.id = id; _serviceReport.device?.id = id;
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
], ],
), ),
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
ASubTitle(_subtitle.serviceType), ASubTitle(_subtitle.serviceType),
_validate && _serviceReport.serviceType == null ? _validate && _serviceReport.serviceType == null
ASubTitle(_subtitle.requiredWord,color: Colors.red,): ? ASubTitle(
const SizedBox.shrink(), _subtitle.requiredWord,
const SizedBox(height: 4,), color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
ServiceStatusMenu( ServiceStatusMenu(
initialValue: _serviceReport.serviceType, initialValue: _serviceReport.serviceType,
onSelect: (status){ onSelect: (status) {
_serviceReport.serviceType = status; _serviceReport.serviceType = status;
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// Report status and Service Type // Report status and Service Type
Row( Row(
children: [ children: [
@ -245,38 +271,49 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.reportStatus), ASubTitle(_subtitle.reportStatus),
_validate && _serviceReport.status == null ? _validate && _serviceReport.status == null
ASubTitle(_subtitle.requiredWord,color: Colors.red,): ? ASubTitle(
const SizedBox.shrink(), _subtitle.requiredWord,
const SizedBox(height: 4,), color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
ServiceReportStatusMenu( ServiceReportStatusMenu(
report: _serviceReport, report: _serviceReport,
onSelect: (status){ onSelect: (status) {
_serviceReport.status = status; _serviceReport.status = status;
}, },
), ),
], ],
), ),
), ),
const SizedBox(width: 8,), const SizedBox(
width: 8,
),
Provider.of<ServiceReportLastCallsProvider>(context).isLoading == null Provider.of<ServiceReportLastCallsProvider>(context).isLoading == null
? const SizedBox.shrink(): ? const SizedBox.shrink()
:
// Call's last Situation // Call's last Situation
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.callLastSituation), ASubTitle(_subtitle.callLastSituation),
_validate && _serviceReport.callLastSituation == null ? _validate && _serviceReport.callLastSituation == null
ASubTitle(_subtitle.requiredWord,color: Colors.red,): ? ASubTitle(
const SizedBox.shrink(), _subtitle.requiredWord,
const SizedBox(height: 4,), color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
ServiceReportLastCallsMenu( ServiceReportLastCallsMenu(
report: _serviceReport, report: _serviceReport,
onSelect: (status){ onSelect: (status) {
if(status?.id == 12 if (status?.id == 12 || _serviceReport.callLastSituation?.id == 12) {
|| _serviceReport.callLastSituation?.id == 12){
_serviceReport.callLastSituation = status; _serviceReport.callLastSituation = status;
setState(() {}); setState(() {});
} else { } else {
@ -289,48 +326,53 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
), ),
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// invoice number & code // invoice number & code
_serviceReport.callLastSituation?.id != 12 ? const SizedBox.shrink(): _serviceReport.callLastSituation?.id != 12
Row( ? const SizedBox.shrink()
: Row(
children: [ children: [
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.invoiceNumber), ASubTitle(_subtitle.invoiceNumber),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.invoiceNumber, initialValue: _serviceReport?.invoiceNumber,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
validator: (value) => validator: (value) => Validator.hasValue(value!) ? '' : _subtitle.requiredWord,
Validator.hasValue(value!)
? '' : _subtitle.requiredWord,
textInputType: TextInputType.number, textInputType: TextInputType.number,
onSaved: (value){ onSaved: (value) {
_serviceReport.invoiceNumber = value; _serviceReport.invoiceNumber = value;
}, },
), ),
], ],
), ),
), ),
const SizedBox(width: 8,), const SizedBox(
width: 8,
),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.invoiceCode), ASubTitle(_subtitle.invoiceCode),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.invoiceCode, initialValue: _serviceReport?.invoiceCode,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
validator: (value) => validator: (value) => Validator.hasValue(value!) ? '' : _subtitle.requiredWord,
Validator.hasValue(value!)
? '' : _subtitle.requiredWord,
textInputType: TextInputType.text, textInputType: TextInputType.text,
onSaved: (value){ onSaved: (value) {
_serviceReport.invoiceCode = value; _serviceReport.invoiceCode = value;
}, },
), ),
@ -340,7 +382,9 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
Row( Row(
children: [ children: [
ASubTitle(_subtitle.faultDescription), ASubTitle(_subtitle.faultDescription),
@ -355,21 +399,23 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
), ),
], ],
), ),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.faultDescription, initialValue: _serviceReport?.faultDescription,
textAlign: TextAlign.center, textAlign: TextAlign.center,
controller: _faultController, controller: _faultController,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
validator: (value) => validator: (value) => Validator.hasValue(value!) ? '' : _subtitle.requiredWord,
Validator.hasValue(value!)
? '' : _subtitle.requiredWord,
textInputType: TextInputType.multiline, textInputType: TextInputType.multiline,
onSaved: (value){ onSaved: (value) {
_serviceReport.faultDescription = value; _serviceReport.faultDescription = value;
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
Row( Row(
children: [ children: [
ASubTitle(_subtitle.workPreformed), ASubTitle(_subtitle.workPreformed),
@ -384,23 +430,27 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
), ),
], ],
), ),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.workPreformed, initialValue: _serviceReport?.workPreformed,
textAlign: TextAlign.center, textAlign: TextAlign.center,
controller: _workPreformedController, controller: _workPreformedController,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
validator: (value) => validator: (value) => Validator.hasValue(value!) ? '' : _subtitle.requiredWord,
Validator.hasValue(value!)
? '' : _subtitle.requiredWord,
textInputType: TextInputType.multiline, textInputType: TextInputType.multiline,
onSaved: (value){ onSaved: (value) {
_serviceReport.workPreformed = value; _serviceReport.workPreformed = value;
}, },
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
Row( Row(
children: [ children: [
// reasons // reasons
@ -409,17 +459,21 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.reasons), ASubTitle(_subtitle.reasons),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ServiceReportReasonsMenu( ServiceReportReasonsMenu(
initialValue: _serviceReport.reason, initialValue: _serviceReport.reason,
onSelect: (status){ onSelect: (status) {
_serviceReport.reason = status; _serviceReport.reason = status;
}, },
), ),
], ],
), ),
), ),
const SizedBox(width: 8,), const SizedBox(
width: 8,
),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -428,8 +482,8 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
AMiniOneImagePicker( AMiniOneImagePicker(
//error: _validate && _serviceReport.image == null, //error: _validate && _serviceReport.image == null,
image: _image, image: _image,
onPick: (image){ onPick: (image) {
_image =image; _image = image;
_serviceReport.image = base64Encode(image.readAsBytesSync()); _serviceReport.image = base64Encode(image.readAsBytesSync());
}, },
), ),
@ -438,7 +492,9 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
), ),
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// Traveling Hours & Working Hours // Traveling Hours & Working Hours
Row( Row(
children: [ children: [
@ -447,10 +503,12 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.workingHours), ASubTitle(_subtitle.workingHours),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
AppTimer( AppTimer(
timer: _serviceReport.timer, timer: _serviceReport.timer,
onChange: (timer) async{ onChange: (timer) async {
_serviceReport.timer = timer; _serviceReport.timer = timer;
return true; return true;
}, },
@ -471,23 +529,25 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
], ],
), ),
), ),
const SizedBox(width: 8,), const SizedBox(
width: 8,
),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.travelingHours), ASubTitle(_subtitle.travelingHours),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.travelingHours, initialValue: _serviceReport?.travelingHours,
textAlign: TextAlign.center, textAlign: TextAlign.center,
hintText: "i.e 3, 3.5, 4", hintText: "i.e 3, 3.5, 4",
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
validator: (value) => validator: (value) => Validator.isNumeric(value!) ? '' : _subtitle.requiredWord,
Validator.isNumeric(value!)
? '' : _subtitle.requiredWord,
textInputType: TextInputType.number, textInputType: TextInputType.number,
onSaved: (value){ onSaved: (value) {
_serviceReport.travelingHours = value; _serviceReport.travelingHours = value;
}, },
), ),
@ -496,7 +556,9 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
), ),
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// Operating Hours and Job Sheet Number // Operating Hours and Job Sheet Number
Row( Row(
children: [ children: [
@ -505,36 +567,40 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.operatingHours), ASubTitle(_subtitle.operatingHours),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.operatingHours, initialValue: _serviceReport?.operatingHours,
textAlign: TextAlign.center, textAlign: TextAlign.center,
hintText: "i.e 3, 3.5, 4", hintText: "i.e 3, 3.5, 4",
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
validator: (value) => validator: (value) => Validator.isNumeric(value!) ? '' : _subtitle.requiredWord,
Validator.isNumeric(value!)
? '' : _subtitle.requiredWord,
textInputType: TextInputType.number, textInputType: TextInputType.number,
onSaved: (value){ onSaved: (value) {
_serviceReport.operatingHours = value; _serviceReport.operatingHours = value;
}, },
), ),
], ],
), ),
), ),
const SizedBox(width: 8,), const SizedBox(
width: 8,
),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.jobSheetNumber), ASubTitle(_subtitle.jobSheetNumber),
const SizedBox(height: 4,), const SizedBox(
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.jobSheetNumber, initialValue: _serviceReport?.jobSheetNumber,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
textInputType: TextInputType.name, textInputType: TextInputType.name,
onSaved: (value){ onSaved: (value) {
_serviceReport.jobSheetNumber = value; _serviceReport.jobSheetNumber = value;
}, },
), ),
@ -543,7 +609,9 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
), ),
], ],
), ),
const SizedBox(height: 8,), const SizedBox(
height: 8,
),
// Part Number and Quantity // Part Number and Quantity
Row( Row(
children: [ children: [
@ -553,12 +621,17 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.partNumber), ASubTitle(_subtitle.partNumber),
_validate && _serviceReport.parts == null ? _validate && _serviceReport.parts == null
ASubTitle(_subtitle.requiredWord,color: Colors.red,): ? ASubTitle(
const SizedBox.shrink(), _subtitle.requiredWord,
const SizedBox(height: 4,), color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
AutoCompletePartsField( AutoCompletePartsField(
onPick: (part){ onPick: (part) {
_serviceReport.parts?.add(part); _serviceReport.parts?.add(part);
setState(() {}); setState(() {});
}, },
@ -566,34 +639,33 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
], ],
), ),
), ),
], ],
), ),
SizedBox(height: 8*AppStyle.getScaleFactor(context),), SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
Row( Row(
children: [ children: [
Expanded(flex:3,child: Text(_subtitle.number)), Expanded(flex: 3, child: Text(_subtitle.number)),
Expanded(flex: 1,child: Text(_subtitle.quantity)), Expanded(flex: 1, child: Text(_subtitle.quantity)),
], ],
), ),
Column( Column(
children: List.generate( children: List.generate(_serviceReport.parts!.length, (index) {
_serviceReport.parts!.length,
(index) {
Part _part = _serviceReport.parts![index]; Part _part = _serviceReport.parts![index];
return PartItem( return PartItem(
part: _part, part: _part,
onDelete: (part){ onDelete: (part) {
_serviceReport.parts?.remove(part); _serviceReport.parts?.remove(part);
setState(() {}); setState(() {});
}, },
); );
} }),
), ),
),
const SizedBox(height: 16,),
const SizedBox(
height: 16,
),
], ],
), ),
), ),
@ -603,48 +675,41 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
text: _subtitle.update, text: _subtitle.update,
onPressed: () async { onPressed: () async {
_validate = true; _validate = true;
if(!(_formKey.currentState?.validate()??false)){ if (!(_formKey.currentState?.validate() ?? false)) {
setState(() {}); setState(() {});
return; return;
} }
if(!_serviceReport.validate()) { if (!_serviceReport.validate()) {
setState(() {}); setState(() {});
return; return;
} }
_formKey.currentState?.save(); _formKey.currentState?.save();
_isLoading =true; _isLoading = true;
setState(() {}); setState(() {});
int status = await _serviceRequestsProvider.updateServiceReport( int status =
user: _userProvider.user!, await _serviceRequestsProvider.updateServiceReport(user: UserApiClient().user!, host: _settingProvider.host ?? "", report: _serviceReport, request: widget.request);
host: _settingProvider.host??"", _isLoading = false;
report: _serviceReport,
request: widget.request
);
_isLoading =false;
setState(() {}); setState(() {});
if(status >= 200 && status < 300){ if (status >= 200 && status < 300) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: _subtitle.requestCompleteSuccessfully, msg: _subtitle.requestCompleteSuccessfully,
); );
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.of(context).pop(); Navigator.of(context).pop();
}else{ } else {
String errorMessage = HttpStatusManger.getStatusMessage( String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle);
status: status, subtitle: _subtitle); ScaffoldMessenger.of(context).showSnackBar(SnackBar(
ScaffoldMessenger.of(context).showSnackBar( content: Text(errorMessage),
SnackBar( ));
content: Text(
errorMessage
),
)
);
} }
}, },
), ),
), ),
const SizedBox(height: 300,) const SizedBox(
height: 300,
)
], ],
), ),
const ABackButton(), const ABackButton(),

@ -1,16 +1,18 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../../api/user_api_client.dart';
import '../../../../../controllers/localization/localization.dart'; import '../../../../../controllers/localization/localization.dart';
import '../../../../../controllers/providers/api/service_requests_provider.dart'; import '../../../../../controllers/providers/api/service_requests_provider.dart';
import '../../../../../controllers/providers/api/user_provider.dart';
import '../../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../../controllers/providers/user_provider.dart';
import '../../../../../models/service_report.dart'; import '../../../../../models/service_report.dart';
import '../../../../../models/service_request/service_request.dart'; import '../../../../../models/service_request/service_request.dart';
import '../../../../../models/subtitle.dart'; import '../../../../../models/subtitle.dart';
import '../../../../widgets/loaders/app_loading.dart'; import '../../../../widgets/loaders/app_loading.dart';
import '../../../../widgets/loaders/failed_loading.dart'; import '../../../../widgets/loaders/failed_loading.dart';
import 'edit_service_report.dart'; import 'edit_service_report.dart';
class FutureServiceReport extends StatefulWidget { class FutureServiceReport extends StatefulWidget {
final ServiceRequest request; final ServiceRequest request;
@ -21,7 +23,6 @@ class FutureServiceReport extends StatefulWidget {
} }
class _FutureServiceReportState extends State<FutureServiceReport> { class _FutureServiceReportState extends State<FutureServiceReport> {
late UserProvider _userProvider; late UserProvider _userProvider;
late SettingProvider _settingProvider; late SettingProvider _settingProvider;
@override @override
@ -31,19 +32,16 @@ class _FutureServiceReportState extends State<FutureServiceReport> {
Subtitle _subtitle = AppLocalization.of(context)!.subtitle!; Subtitle _subtitle = AppLocalization.of(context)!.subtitle!;
return Scaffold( return Scaffold(
body: FutureBuilder<ServiceReport>( body: FutureBuilder<ServiceReport>(
future: ServiceRequestsProvider().getSingleServiceReport( future: ServiceRequestsProvider().getSingleServiceReport(reportId: widget.request.reportID ?? "", user: UserApiClient().user!, host: _settingProvider.host ?? "", subtitle: _subtitle),
reportId: widget.request.reportID??"", builder: (BuildContext context, AsyncSnapshot<ServiceReport> snapshot) {
user: _userProvider.user!, if (snapshot.hasError)
host: _settingProvider.host??"",
subtitle: _subtitle
),
builder: (BuildContext context, AsyncSnapshot<ServiceReport> snapshot){
if(snapshot.hasError)
return FailedLoading( return FailedLoading(
message: snapshot.error.toString(), message: snapshot.error.toString(),
onReload: (){setState(() {});}, onReload: () {
setState(() {});
},
); );
if(snapshot.hasData){ if (snapshot.hasData) {
return EditServiceReport( return EditServiceReport(
report: snapshot.data!, report: snapshot.data!,
request: widget.request, request: widget.request,

@ -1,14 +1,13 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../api/user_api_client.dart';
import '../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/service_requests_provider.dart'; import '../../../../controllers/providers/api/service_requests_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../models/enums/user_types.dart'; import '../../../../models/enums/user_types.dart';
import '../../../../models/service_request/service_request.dart'; import '../../../../models/service_request/service_request.dart';
import '../../../../models/subtitle.dart'; import '../../../../models/subtitle.dart';
@ -28,6 +27,7 @@ import '../../../widgets/titles/app_sub_title.dart';
import '../report_issues_page.dart'; import '../report_issues_page.dart';
import 'report/create_service_report.dart'; import 'report/create_service_report.dart';
import 'report/future_service_report.dart'; import 'report/future_service_report.dart';
class RequestDetailsPage extends StatelessWidget { class RequestDetailsPage extends StatelessWidget {
static final String id = "/call-details"; static final String id = "/call-details";
final ServiceRequest serviceRequest; final ServiceRequest serviceRequest;
@ -46,8 +46,8 @@ class RequestDetailsPage extends StatelessWidget {
child: Column( child: Column(
children: [ children: [
Container( Container(
color:AColors.primaryColor, color: AColors.primaryColor,
padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
child: Row( child: Row(
children: [ children: [
ABackButton(), ABackButton(),
@ -55,15 +55,12 @@ class RequestDetailsPage extends StatelessWidget {
child: Center( child: Center(
child: Text( child: Text(
_subtitle.details, _subtitle.details,
style: Theme.of(context).textTheme.headline6?.copyWith( style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
color: AColors.white,
fontStyle: FontStyle.italic
),
), ),
), ),
), ),
Visibility( Visibility(
visible: _userProvider.user?.type == UsersTypes.normal_user, visible: UserApiClient().user?.type == UsersTypes.normal_user,
replacement: AIconButton( replacement: AIconButton(
iconData: Icons.edit, iconData: Icons.edit,
color: AColors.white, color: AColors.white,
@ -72,8 +69,10 @@ class RequestDetailsPage extends StatelessWidget {
onPressed: () async { onPressed: () async {
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
builder: (context){ builder: (context) {
return ServiceRequestsUpdateDialog(request: serviceRequest,); return ServiceRequestsUpdateDialog(
request: serviceRequest,
);
}); });
// DateTime picked = await showDatePicker( // DateTime picked = await showDatePicker(
// context: context, // context: context,
@ -109,29 +108,31 @@ class RequestDetailsPage extends StatelessWidget {
color: AColors.white, color: AColors.white,
buttonSize: 42, buttonSize: 42,
backgroundColor: AColors.deepOrange, backgroundColor: AColors.deepOrange,
onPressed: (){ onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(MaterialPageRoute(
MaterialPageRoute( builder: (_) => ReportIssuesPage(
builder: (_) => ReportIssuesPage(serviceRequest: serviceRequest,) serviceRequest: serviceRequest,
) )));
);
}, },
), ),
), ),
SizedBox(width: 16,) SizedBox(
width: 16,
)
], ],
), ),
), ),
(serviceRequest.devicePhotos?.isEmpty ?? false)
(serviceRequest.devicePhotos?.isEmpty??false) ? SizedBox.shrink(): ? SizedBox.shrink()
Column( : Column(
children: [ children: [
SizedBox(height: 8,), SizedBox(
height: 8,
),
MaterialButton( MaterialButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: (){ onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(MaterialPageRoute(
MaterialPageRoute(
builder: (_) => Scaffold( builder: (_) => Scaffold(
body: InteractiveViewer( body: InteractiveViewer(
child: Center( child: Center(
@ -141,9 +142,7 @@ class RequestDetailsPage extends StatelessWidget {
), ),
), ),
), ),
) )));
)
);
}, },
child: SizedBox( child: SizedBox(
height: 140 * AppStyle.getScaleFactor(context), height: 140 * AppStyle.getScaleFactor(context),
@ -154,26 +153,30 @@ class RequestDetailsPage extends StatelessWidget {
), ),
), ),
), ),
SizedBox(height: 8,),
SizedBox( SizedBox(
height: 60* AppStyle.getScaleFactor(context), height: 8,
),
SizedBox(
height: 60 * AppStyle.getScaleFactor(context),
child: ImagesList( child: ImagesList(
images: serviceRequest.devicePhotos!, images: serviceRequest.devicePhotos!,
), ),
), ),
], ],
), ),
TabBar(labelColor: AColors.primaryColor, tabs: [
TabBar( Tab(
labelColor: AColors.primaryColor, text: _subtitle.general,
tabs: [ ),
Tab(text: _subtitle.general,), Tab(
Tab(text: _subtitle.serviceRequestInformation,), text: _subtitle.serviceRequestInformation,
),
]), ]),
SizedBox(height: 8,), SizedBox(
height: 8,
),
Expanded( Expanded(
child: TabBarView( child: TabBarView(
children: [ children: [
ListView( ListView(
padding: EdgeInsets.symmetric(horizontal: 16), padding: EdgeInsets.symmetric(horizontal: 16),
@ -192,7 +195,7 @@ class RequestDetailsPage extends StatelessWidget {
), ),
RequestInfoRow( RequestInfoRow(
title: _subtitle.deviceModel, title: _subtitle.deviceModel,
info : serviceRequest.deviceModel, info: serviceRequest.deviceModel,
), ),
RequestInfoRow( RequestInfoRow(
title: _subtitle.engineerName, title: _subtitle.engineerName,
@ -206,8 +209,9 @@ class RequestDetailsPage extends StatelessWidget {
title: _subtitle.date, title: _subtitle.date,
info: serviceRequest.date, info: serviceRequest.date,
), ),
serviceRequest.nextVisitDate == null ? SizedBox.shrink() : serviceRequest.nextVisitDate == null
RequestInfoRow( ? SizedBox.shrink()
: RequestInfoRow(
title: _subtitle.nextVisitDate, title: _subtitle.nextVisitDate,
info: DateFormat('EE dd/MM/yyyy').format(serviceRequest.nextVisitDate!), info: DateFormat('EE dd/MM/yyyy').format(serviceRequest.nextVisitDate!),
), ),
@ -220,12 +224,12 @@ class RequestDetailsPage extends StatelessWidget {
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),
), ),
StatusLabel(label: serviceRequest.statusLabel, StatusLabel(label: serviceRequest.statusLabel, color: AColors.getRequestStatusColor(serviceRequest.statusValue!)),
color: AColors.getRequestStatusColor(serviceRequest.statusValue!)
),
], ],
), ),
Divider(color: Theme.of(context).primaryColor,), Divider(
color: Theme.of(context).primaryColor,
),
RequestInfoRow( RequestInfoRow(
title: _subtitle.hospital, title: _subtitle.hospital,
info: serviceRequest.hospitalName, info: serviceRequest.hospitalName,
@ -246,7 +250,7 @@ class RequestDetailsPage extends StatelessWidget {
title: _subtitle.maintenanceIssue, title: _subtitle.maintenanceIssue,
content: serviceRequest.maintenanceIssue, content: serviceRequest.maintenanceIssue,
), ),
if(serviceRequest.audio?.isNotEmpty == true) if (serviceRequest.audio?.isNotEmpty == true)
ASoundPlayer( ASoundPlayer(
audio: serviceRequest.audio, audio: serviceRequest.audio,
), ),
@ -261,28 +265,16 @@ class RequestDetailsPage extends StatelessWidget {
builder: (_) => AAlertDialog( builder: (_) => AAlertDialog(
title: _subtitle.duplicateAlert, title: _subtitle.duplicateAlert,
content: _subtitle.duplicateAlertMessage, content: _subtitle.duplicateAlertMessage,
) ));
); if (result == true) {
if(result == true){
showDialog( showDialog(
context: context, context: context,
builder: (context){ builder: (context) {
return Center(child: CircularProgressIndicator()); return Center(child: CircularProgressIndicator());
} });
); int status = await _serviceRequestsProvider.createDuplicatedReport(host: _settingProvider.host ?? "", user: UserApiClient().user!, request: serviceRequest);
int status = await _serviceRequestsProvider.createDuplicatedReport(
host: _settingProvider.host??"",
user: _userProvider.user!,
request: serviceRequest
);
Navigator.of(context).pop(); Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle))));
SnackBar(
content: Text(
HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle)
)
)
);
} }
}, },
), ),
@ -290,8 +282,8 @@ class RequestDetailsPage extends StatelessWidget {
) )
], ],
), ),
serviceRequest.viewReport??false ? serviceRequest.viewReport ?? false
ListView( ? ListView(
padding: EdgeInsets.symmetric(horizontal: 16), padding: EdgeInsets.symmetric(horizontal: 16),
children: [ children: [
RequestInfoRow( RequestInfoRow(
@ -310,44 +302,44 @@ class RequestDetailsPage extends StatelessWidget {
title: _subtitle.jobSheetNumber, title: _subtitle.jobSheetNumber,
info: serviceRequest.jobSheetNumber, info: serviceRequest.jobSheetNumber,
), ),
_userProvider.user?.type == UsersTypes.engineer ? UserApiClient().user?.type == UsersTypes.engineer
Padding( ? Padding(
padding: EdgeInsets.all(32), padding: EdgeInsets.all(32),
child: AButton( child: AButton(
text: _subtitle.editServiceReport, text: _subtitle.editServiceReport,
onPressed: (){ onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (_) => FutureServiceReport( builder: (_) => FutureServiceReport(
request: serviceRequest, request: serviceRequest,
) )),
),
); );
}, },
), ),
): SizedBox.shrink(), )
: SizedBox.shrink(),
], ],
): )
_userProvider.user?.type == UsersTypes.engineer ? : UserApiClient().user?.type == UsersTypes.engineer
Center( ? Center(
child: Padding( child: Padding(
padding: EdgeInsets.all(32), padding: EdgeInsets.all(32),
child: AButton( child: AButton(
text: "Create Report", text: "Create Report",
onPressed: (){ onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (_) => CreateServiceReport( builder: (_) => CreateServiceReport(
request: serviceRequest, request: serviceRequest,
) )),
),
); );
}, },
), ),
), ),
): Center(child: ASubTitle(_subtitle.noDateFound),), )
: Center(
child: ASubTitle(_subtitle.noDateFound),
),
], ],
), ),
), ),

@ -1,10 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../api/user_api_client.dart';
import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/service_requests_provider.dart'; import '../../../../controllers/providers/api/service_requests_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../models/service_request/service_request_search.dart'; import '../../../../models/service_request/service_request_search.dart';
import '../../../../models/subtitle.dart'; import '../../../../models/subtitle.dart';
import '../../../app_style/colors.dart'; import '../../../app_style/colors.dart';
@ -21,8 +22,7 @@ class ServiceRequestsPage extends StatefulWidget {
_ServiceRequestsPageState createState() => _ServiceRequestsPageState(); _ServiceRequestsPageState createState() => _ServiceRequestsPageState();
} }
class _ServiceRequestsPageState extends State<ServiceRequestsPage> class _ServiceRequestsPageState extends State<ServiceRequestsPage> with TickerProviderStateMixin {
with TickerProviderStateMixin {
late ServiceRequestsProvider _serviceRequestsProvider; late ServiceRequestsProvider _serviceRequestsProvider;
late UserProvider _userProvider; late UserProvider _userProvider;
late SettingProvider _settingProvider; late SettingProvider _settingProvider;
@ -49,9 +49,9 @@ class _ServiceRequestsPageState extends State<ServiceRequestsPage>
onRefresh: () async { onRefresh: () async {
_serviceRequestsProvider.reset(); _serviceRequestsProvider.reset();
await _serviceRequestsProvider.getRequests( await _serviceRequestsProvider.getRequests(
user: _userProvider.user!, user: UserApiClient().user!,
host: _settingProvider.host ?? "", host: _settingProvider.host ?? "",
hospitalId: _userProvider.user!.hospital!.id, hospitalId: UserApiClient().user!.hospital!.id,
); );
}, },
child: Stack( child: Stack(
@ -60,8 +60,7 @@ class _ServiceRequestsPageState extends State<ServiceRequestsPage>
children: [ children: [
Container( Container(
color: AColors.primaryColor, color: AColors.primaryColor,
padding: padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
child: Column( child: Column(
children: [ children: [
Row( Row(
@ -71,10 +70,7 @@ class _ServiceRequestsPageState extends State<ServiceRequestsPage>
child: Center( child: Center(
child: Text( child: Text(
subtitle?.serviceRequests ?? '', subtitle?.serviceRequests ?? '',
style: Theme.of(context) style: Theme.of(context).textTheme.titleLarge?.copyWith(
.textTheme
.titleLarge
?.copyWith(
color: AColors.white, color: AColors.white,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
), ),
@ -88,14 +84,12 @@ class _ServiceRequestsPageState extends State<ServiceRequestsPage>
buttonSize: 42, buttonSize: 42,
backgroundColor: AColors.white, backgroundColor: AColors.white,
onPressed: () async { onPressed: () async {
ServiceRequestSearch? temp = ServiceRequestSearch? temp = await showModalBottomSheet(
await showModalBottomSheet(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
builder: (context) { builder: (context) {
return ServiceRequestsSearchDialog( return ServiceRequestsSearchDialog(
initialSearchValue: initialSearchValue: _serviceRequestsProvider.search!,
_serviceRequestsProvider.search!,
); );
}, },
); );
@ -117,9 +111,9 @@ class _ServiceRequestsPageState extends State<ServiceRequestsPage>
nextPage: _serviceRequestsProvider.nextPage!, nextPage: _serviceRequestsProvider.nextPage!,
onLazyLoad: () async { onLazyLoad: () async {
await _serviceRequestsProvider.getRequests( await _serviceRequestsProvider.getRequests(
user: _userProvider.user, user: UserApiClient().user,
host: _settingProvider.host ?? "", host: _settingProvider.host ?? "",
hospitalId: _userProvider.user?.hospital?.id, hospitalId: UserApiClient().user?.hospital?.id,
); );
}, },
requests: _serviceRequestsProvider.serviceRequests ?? [], requests: _serviceRequestsProvider.serviceRequests ?? [],

@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../../api/user_api_client.dart';
import '../../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../../../controllers/localization/localization.dart'; import '../../../../../controllers/localization/localization.dart';
import '../../../../../controllers/providers/api/regular_visits_provider.dart'; import '../../../../../controllers/providers/api/regular_visits_provider.dart';
import '../../../../../controllers/providers/api/user_provider.dart';
import '../../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../../models/pantry/pentry.dart'; import '../../../../../models/pantry/pentry.dart';
import '../../../../../models/subtitle.dart'; import '../../../../../models/subtitle.dart';
@ -31,7 +31,6 @@ class _EditPentryState extends State<EditPentry> with SingleTickerProviderStateM
bool _isLoading = false; bool _isLoading = false;
bool _validate = false; bool _validate = false;
Subtitle? _subtitle; Subtitle? _subtitle;
late UserProvider _userProvider;
late SettingProvider _settingProvider; late SettingProvider _settingProvider;
late RegularVisitsProvider _regularVisitsProvider; late RegularVisitsProvider _regularVisitsProvider;
Pentry? _pentry; Pentry? _pentry;
@ -50,7 +49,7 @@ class _EditPentryState extends State<EditPentry> with SingleTickerProviderStateM
_isLoading = true; _isLoading = true;
setState(() {}); setState(() {});
int status = await _regularVisitsProvider.updatePentry(user: _userProvider.user, host: _settingProvider.host, pentry: _pentry, visit: widget.visit); int status = await _regularVisitsProvider.updatePentry(user: UserApiClient().user, host: _settingProvider.host, pentry: _pentry, visit: widget.visit);
_isLoading = false; _isLoading = false;
setState(() {}); setState(() {});
if (status >= 200 && status < 300) { if (status >= 200 && status < 300) {
@ -84,7 +83,6 @@ class _EditPentryState extends State<EditPentry> with SingleTickerProviderStateM
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_subtitle = AppLocalization.of(context)?.subtitle; _subtitle = AppLocalization.of(context)?.subtitle;
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context); _settingProvider = Provider.of<SettingProvider>(context);
_regularVisitsProvider = Provider.of<RegularVisitsProvider>(context); _regularVisitsProvider = Provider.of<RegularVisitsProvider>(context);
return Scaffold( return Scaffold(

@ -1,9 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../../api/user_api_client.dart';
import '../../../../../controllers/localization/localization.dart'; import '../../../../../controllers/localization/localization.dart';
import '../../../../../controllers/providers/api/regular_visits_provider.dart'; import '../../../../../controllers/providers/api/regular_visits_provider.dart';
import '../../../../../controllers/providers/api/user_provider.dart';
import '../../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../../models/pantry/pentry.dart'; import '../../../../../models/pantry/pentry.dart';
import '../../../../../models/subtitle.dart'; import '../../../../../models/subtitle.dart';
@ -13,7 +13,6 @@ import '../../../../widgets/loaders/failed_loading.dart';
import 'edit_pentry.dart'; import 'edit_pentry.dart';
class FutureEditPentry extends StatefulWidget { class FutureEditPentry extends StatefulWidget {
final Visit visit; final Visit visit;
const FutureEditPentry({Key? key, required this.visit}) : super(key: key); const FutureEditPentry({Key? key, required this.visit}) : super(key: key);
@ -23,31 +22,25 @@ class FutureEditPentry extends StatefulWidget {
} }
class _FutureEditPentryState extends State<FutureEditPentry> { class _FutureEditPentryState extends State<FutureEditPentry> {
late UserProvider _userProvider;
late SettingProvider _settingProvider; late SettingProvider _settingProvider;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context); _settingProvider = Provider.of<SettingProvider>(context);
//String requestId = ModalRoute.of(context).settings.arguments; //String requestId = ModalRoute.of(context).settings.arguments;
Subtitle subtitle = AppLocalization.of(context)!.subtitle!; Subtitle subtitle = AppLocalization.of(context)!.subtitle!;
return Scaffold( return Scaffold(
body: FutureBuilder<Pentry?>( body: FutureBuilder<Pentry?>(
future: RegularVisitsProvider().getPently( future: RegularVisitsProvider().getPently(user: UserApiClient().user!, host: _settingProvider.host ?? "", id: widget.visit.id!),
user: _userProvider.user!, builder: (BuildContext context, AsyncSnapshot<Pentry?> snapshot) {
host: _settingProvider.host??"", if (snapshot.hasError) {
id: widget.visit.id!
),
builder: (BuildContext context, AsyncSnapshot<Pentry?> snapshot){
if(snapshot.hasError) {
return FailedLoading( return FailedLoading(
message: subtitle.failedToCompleteRequest, message: subtitle.failedToCompleteRequest,
onReload: (){setState(() {});}, onReload: () {
setState(() {});
},
); );
} }
if(snapshot.hasData){ if (snapshot.hasData) {
return EditPentry( return EditPentry(
pentry: snapshot.data, pentry: snapshot.data,
visit: widget.visit, visit: widget.visit,

@ -3,11 +3,12 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../api/user_api_client.dart';
import '../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/preventive_maintenance_visits_provider.dart'; import '../../../../controllers/providers/api/preventive_maintenance_visits_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../models/subtitle.dart'; import '../../../../models/subtitle.dart';
import '../../../../models/visits/visits_group.dart'; import '../../../../models/visits/visits_group.dart';
import '../../../../models/visits/visits_search.dart'; import '../../../../models/visits/visits_search.dart';
@ -26,8 +27,7 @@ class PreventiveMaintenanceVisitsPage extends StatefulWidget {
_PreventiveMaintenanceVisitsPageState createState() => _PreventiveMaintenanceVisitsPageState(); _PreventiveMaintenanceVisitsPageState createState() => _PreventiveMaintenanceVisitsPageState();
} }
class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceVisitsPage> class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceVisitsPage> with TickerProviderStateMixin {
with TickerProviderStateMixin{
late PreventiveMaintenanceVisitsProvider _visitsProvider; late PreventiveMaintenanceVisitsProvider _visitsProvider;
late UserProvider _userProvider; late UserProvider _userProvider;
late SettingProvider _settingProvider; late SettingProvider _settingProvider;
@ -49,8 +49,8 @@ class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceV
//_visitsProvider.visitsSearch = VisitsSearch(); //_visitsProvider.visitsSearch = VisitsSearch();
_visitsProvider.reset(); _visitsProvider.reset();
await _visitsProvider.getVisits( await _visitsProvider.getVisits(
user: _userProvider.user!, user: UserApiClient().user!,
host: _settingProvider.host??"", host: _settingProvider.host ?? "",
//visitsSearch: _visitsSearch //visitsSearch: _visitsSearch
); );
}, },
@ -59,8 +59,8 @@ class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceV
Column( Column(
children: [ children: [
Container( Container(
color:AColors.primaryColor, color: AColors.primaryColor,
padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
child: Column( child: Column(
children: [ children: [
Row( Row(
@ -70,10 +70,7 @@ class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceV
child: Center( child: Center(
child: Text( child: Text(
_subtitle.preventiveMaintenance, _subtitle.preventiveMaintenance,
style: Theme.of(context).textTheme.headline6?.copyWith( style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
color: AColors.white,
fontStyle: FontStyle.italic
),
), ),
), ),
), ),
@ -86,37 +83,39 @@ class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceV
VisitsSearch? _temp = await showModalBottomSheet( VisitsSearch? _temp = await showModalBottomSheet(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
builder: (context){ builder: (context) {
return VisitsSearchDialog( return VisitsSearchDialog(
initialSearchValue: _visitsProvider.visitsSearch!, onSearch: (VisitsSearch ) {}, initialSearchValue: _visitsProvider.visitsSearch!,
onSearch: (VisitsSearch) {},
); );
}); });
if(_temp != null){ if (_temp != null) {
_visitsProvider.visitsSearch = _temp; _visitsProvider.visitsSearch = _temp;
_visitsProvider.reset(); _visitsProvider.reset();
setState(() {}); setState(() {});
await _visitsProvider.getVisits( await _visitsProvider.getVisits(
user: _userProvider.user!, user: UserApiClient().user!,
host: _settingProvider.host??"", host: _settingProvider.host ?? "",
//visitsSearch: _visitsSearch //visitsSearch: _visitsSearch
); );
} }
}, },
), ),
SizedBox(width: 16,) SizedBox(
width: 16,
)
], ],
), ),
], ],
), ),
), ),
Visibility( Visibility(
visible:_visitsProvider.visitsSearch?.toSearchString().isNotEmpty??false, visible: _visitsProvider.visitsSearch?.toSearchString().isNotEmpty ?? false,
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: AButton( child: AButton(
text: _subtitle.clearSearch, text: _subtitle.clearSearch,
onPressed: (){ onPressed: () {
_visitsProvider.visitsSearch = VisitsSearch(); _visitsProvider.visitsSearch = VisitsSearch();
_visitsProvider.reset(); _visitsProvider.reset();
setState(() {}); setState(() {});
@ -129,8 +128,8 @@ class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceV
nextPage: _visitsProvider.nextPage!, nextPage: _visitsProvider.nextPage!,
onLazyLoad: () async { onLazyLoad: () async {
await _visitsProvider.getVisits( await _visitsProvider.getVisits(
user: _userProvider.user!, user: UserApiClient().user!,
host: _settingProvider.host??"", host: _settingProvider.host ?? "",
//visitsSearch: _visitsSearch //visitsSearch: _visitsSearch
); );
}, },
@ -139,10 +138,13 @@ class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceV
isScrollControlled: true, isScrollControlled: true,
context: context, context: context,
builder: (context) { builder: (context) {
return UpdateVisitsGroupSheet(visits: visits,title:_subtitle.updatePreventiveMaintenance,); return UpdateVisitsGroupSheet(
visits: visits,
title: _subtitle.updatePreventiveMaintenance,
);
}, },
)as VisitsGroup; ) as VisitsGroup;
if(_group != null){ if (_group != null) {
showDialog<void>( showDialog<void>(
context: context, context: context,
barrierDismissible: false, barrierDismissible: false,
@ -153,24 +155,17 @@ class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceV
); );
}, },
); );
int status = await _visitsProvider.updateGroupOfVisits( int status = await _visitsProvider.updateGroupOfVisits(user: UserApiClient().user!, host: _settingProvider.host ?? "", group: _group);
user: _userProvider.user!,
host: _settingProvider.host??"",
group: _group
);
Navigator.of(context).pop(); Navigator.of(context).pop();
if(status >= 200 && status < 300){ if (status >= 200 && status < 300) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: _subtitle.preventiveMaintenanceUpdatedSuccessfully, msg: _subtitle.preventiveMaintenanceUpdatedSuccessfully,
toastLength: Toast.LENGTH_LONG, toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
}else{ } else {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: HttpStatusManger.getStatusMessage( msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle),
status: status,
subtitle: _subtitle
),
toastLength: Toast.LENGTH_LONG, toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
@ -182,7 +177,6 @@ class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceV
), ),
], ],
), ),
], ],
), ),
), ),

@ -3,11 +3,12 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../api/user_api_client.dart';
import '../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/regular_visits_provider.dart'; import '../../../../controllers/providers/api/regular_visits_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../models/subtitle.dart'; import '../../../../models/subtitle.dart';
import '../../../../models/visits/visits_group.dart'; import '../../../../models/visits/visits_group.dart';
import '../../../../models/visits/visits_search.dart'; import '../../../../models/visits/visits_search.dart';
@ -28,8 +29,7 @@ class RegularVisitsPage extends StatefulWidget {
_RegularVisitsPageState createState() => _RegularVisitsPageState(); _RegularVisitsPageState createState() => _RegularVisitsPageState();
} }
class _RegularVisitsPageState extends State<RegularVisitsPage> class _RegularVisitsPageState extends State<RegularVisitsPage> with TickerProviderStateMixin {
with TickerProviderStateMixin {
late RegularVisitsProvider _visitsProvider; late RegularVisitsProvider _visitsProvider;
late UserProvider _userProvider; late UserProvider _userProvider;
late SettingProvider _settingProvider; late SettingProvider _settingProvider;
@ -50,7 +50,7 @@ class _RegularVisitsPageState extends State<RegularVisitsPage>
_visitsProvider.reset(); _visitsProvider.reset();
//_visitsProvider.visitsSearch = VisitsSearch(); //_visitsProvider.visitsSearch = VisitsSearch();
await _visitsProvider.getVisits( await _visitsProvider.getVisits(
user: _userProvider.user, user: UserApiClient().user,
host: _settingProvider.host, host: _settingProvider.host,
); );
}, },
@ -60,8 +60,7 @@ class _RegularVisitsPageState extends State<RegularVisitsPage>
children: [ children: [
Container( Container(
color: AColors.primaryColor, color: AColors.primaryColor,
padding: padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
child: Column( child: Column(
children: [ children: [
Row( Row(
@ -71,12 +70,7 @@ class _RegularVisitsPageState extends State<RegularVisitsPage>
child: Center( child: Center(
child: Text( child: Text(
_subtitle.preventiveMaintenance, _subtitle.preventiveMaintenance,
style: Theme.of(context) style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
.textTheme
.headline6
?.copyWith(
color: AColors.white,
fontStyle: FontStyle.italic),
), ),
), ),
), ),
@ -84,26 +78,21 @@ class _RegularVisitsPageState extends State<RegularVisitsPage>
duration: Duration(milliseconds: 400), duration: Duration(milliseconds: 400),
child: AIconButton( child: AIconButton(
key: ValueKey(_expandedSearch), key: ValueKey(_expandedSearch),
iconData: _expandedSearch iconData: _expandedSearch ? Icons.keyboard_arrow_up : Icons.search,
? Icons.keyboard_arrow_up
: Icons.search,
color: AColors.secondaryColor, color: AColors.secondaryColor,
buttonSize: 42, buttonSize: 42,
backgroundColor: AColors.white, backgroundColor: AColors.white,
onPressed: () async { onPressed: () async {
VisitsSearch _temp = VisitsSearch _temp = await showModalBottomSheet(
await showModalBottomSheet(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
builder: (context) { builder: (context) {
return VisitsSearchDialog( return VisitsSearchDialog(
initialSearchValue: initialSearchValue: _visitsProvider.visitsSearch!,
_visitsProvider.visitsSearch!,
onSearch: (VisitsSearch) {}, onSearch: (VisitsSearch) {},
); );
}); });
_visitsProvider.visitsSearch _visitsProvider.visitsSearch?.fromSearch(_temp);
?.fromSearch(_temp);
_visitsProvider.reset(); _visitsProvider.reset();
setState(() {}); setState(() {});
}, },
@ -118,10 +107,7 @@ class _RegularVisitsPageState extends State<RegularVisitsPage>
), ),
), ),
Visibility( Visibility(
visible: _visitsProvider.visitsSearch visible: _visitsProvider.visitsSearch?.toSearchString().isNotEmpty ?? false,
?.toSearchString()
.isNotEmpty ??
false,
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: AButton( child: AButton(
@ -139,7 +125,7 @@ class _RegularVisitsPageState extends State<RegularVisitsPage>
nextPage: _visitsProvider.nextPage, nextPage: _visitsProvider.nextPage,
onLazyLoad: () async { onLazyLoad: () async {
await _visitsProvider.getVisits( await _visitsProvider.getVisits(
user: _userProvider.user!, user: UserApiClient().user!,
host: _settingProvider.host ?? "", host: _settingProvider.host ?? "",
); );
}, },
@ -161,16 +147,11 @@ class _RegularVisitsPageState extends State<RegularVisitsPage>
builder: (BuildContext context) { builder: (BuildContext context) {
return CupertinoAlertDialog( return CupertinoAlertDialog(
title: Text(_subtitle.updatingDots), title: Text(_subtitle.updatingDots),
content: content: Center(child: CircularProgressIndicator()),
Center(child: CircularProgressIndicator()),
); );
}, },
); );
int status = int status = await _visitsProvider.updateGroupOfVisits(user: UserApiClient().user!, host: _settingProvider.host ?? "", group: group);
await _visitsProvider.updateGroupOfVisits(
user: _userProvider.user!,
host: _settingProvider.host ?? "",
group: group);
Navigator.of(context).pop(); Navigator.of(context).pop();
if (status >= 200 && status < 300) { if (status >= 200 && status < 300) {
Fluttertoast.showToast( Fluttertoast.showToast(
@ -180,8 +161,7 @@ class _RegularVisitsPageState extends State<RegularVisitsPage>
); );
} else { } else {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: HttpStatusManger.getStatusMessage( msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle),
status: status, subtitle: _subtitle),
toastLength: Toast.LENGTH_LONG, toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );

@ -29,13 +29,22 @@ class UpdateVisitsGroupSheet extends StatefulWidget {
class _UpdateVisitsGroupSheetState extends State<UpdateVisitsGroupSheet> { class _UpdateVisitsGroupSheetState extends State<UpdateVisitsGroupSheet> {
List<Lookup> status = [ List<Lookup> status = [
Lookup(label: "Done", id: 0,), Lookup(
label: "Done",
id: 0,
),
Lookup(label: "Not Yet", id: 1), Lookup(label: "Not Yet", id: 1),
Lookup(label: "On Hold", id: 2,), Lookup(
label: "On Hold",
id: 2,
),
]; ];
List<Lookup> taskStatus = [ List<Lookup> taskStatus = [
Lookup(label: "Passed", id: 0,), Lookup(
label: "Passed",
id: 0,
),
Lookup(label: "Failed", id: 1), Lookup(label: "Failed", id: 1),
]; ];
VisitsGroup _group = VisitsGroup(); VisitsGroup _group = VisitsGroup();
@ -74,7 +83,7 @@ class _UpdateVisitsGroupSheetState extends State<UpdateVisitsGroupSheet> {
), ),
ASmallButton( ASmallButton(
text: _subtitle.cancel, text: _subtitle.cancel,
onPressed: (){ onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
), ),
@ -83,39 +92,47 @@ class _UpdateVisitsGroupSheetState extends State<UpdateVisitsGroupSheet> {
AOneImagePicker( AOneImagePicker(
image: _image, image: _image,
onPick: (image){ onPick: (image) {
_image =image; _image = image;
_group.image = base64Encode(image.readAsBytesSync()); _group.image = base64Encode(image.readAsBytesSync());
}, },
), ),
SizedBox(height: 12 * AppStyle.getScaleFactor(context),), SizedBox(
height: 12 * AppStyle.getScaleFactor(context),
),
ATextFormField( ATextFormField(
initialValue: _group.jobSheetNumber, initialValue: _group.jobSheetNumber,
hintText: _subtitle.jobSheetNumber, hintText: _subtitle.jobSheetNumber,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.headline6,
onSaved: (value){ onSaved: (value) {
_group.jobSheetNumber = value; _group.jobSheetNumber = value;
}, },
), ),
SizedBox(height: 8 * AppStyle.getScaleFactor(context),), SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
ATextFormField( ATextFormField(
initialValue: _group.workingHours, initialValue: _group.workingHours,
hintText: _subtitle.workingHours, hintText: _subtitle.workingHours,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.headline6,
onSaved: (value){ onSaved: (value) {
_group.workingHours = value; _group.workingHours = value;
}, },
), ),
SizedBox(height: 8 * AppStyle.getScaleFactor(context),), SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
ATextFormField( ATextFormField(
initialValue: _group.travelingHours, initialValue: _group.travelingHours,
hintText: _subtitle.travelingHours, hintText: _subtitle.travelingHours,
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.headline6,
onSaved: (value){ onSaved: (value) {
_group.travelingHours = value; _group.travelingHours = value;
}, },
), ),
SizedBox(height: 8 * AppStyle.getScaleFactor(context),), SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
Row( Row(
children: [ children: [
Expanded( Expanded(
@ -127,7 +144,7 @@ class _UpdateVisitsGroupSheetState extends State<UpdateVisitsGroupSheet> {
), ),
ADatePicker( ADatePicker(
date: _group.date ?? DateTime.now(), date: _group.date ?? DateTime.now(),
onDatePicker: (date){ onDatePicker: (date) {
_group.date = date; _group.date = date;
setState(() {}); setState(() {});
}, },
@ -140,19 +157,19 @@ class _UpdateVisitsGroupSheetState extends State<UpdateVisitsGroupSheet> {
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),
SizedBox(height: 8 * AppStyle.getScaleFactor(context),), SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
Center( Center(
child: Wrap( child: Wrap(
spacing: 10, spacing: 10,
runSpacing: 10, runSpacing: 10,
children: List.generate( children: List.generate(status.length, (index) {
status.length,
(index) {
bool isSelected = _group.status == status[index]; bool isSelected = _group.status == status[index];
return FilterItem( return FilterItem(
isSelected: isSelected, isSelected: isSelected,
onSelected: (){ onSelected: () {
if(isSelected) if (isSelected)
_group.status = null; _group.status = null;
else else
_group.status = status[index]; _group.status = status[index];
@ -161,9 +178,7 @@ class _UpdateVisitsGroupSheetState extends State<UpdateVisitsGroupSheet> {
}, },
status: status[index], status: status[index],
); );
} }),
),
), ),
), ),
Text( Text(
@ -171,19 +186,19 @@ class _UpdateVisitsGroupSheetState extends State<UpdateVisitsGroupSheet> {
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),
SizedBox(height: 8 * AppStyle.getScaleFactor(context),), SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
Center( Center(
child: Wrap( child: Wrap(
spacing: 10, spacing: 10,
runSpacing: 10, runSpacing: 10,
children: List.generate( children: List.generate(taskStatus.length, (index) {
taskStatus.length,
(index) {
bool isSelected = _group.taskStatus == taskStatus[index]; bool isSelected = _group.taskStatus == taskStatus[index];
return FilterItem( return FilterItem(
isSelected: isSelected, isSelected: isSelected,
onSelected: (){ onSelected: () {
if(isSelected) if (isSelected)
_group.taskStatus = null; _group.taskStatus = null;
else else
_group.taskStatus = taskStatus[index]; _group.taskStatus = taskStatus[index];
@ -192,42 +207,32 @@ class _UpdateVisitsGroupSheetState extends State<UpdateVisitsGroupSheet> {
}, },
status: taskStatus[index], status: taskStatus[index],
); );
} }),
), ),
), ),
SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
), ),
SizedBox(height: 8 * AppStyle.getScaleFactor(context),),
Expanded( Expanded(
child: ListView.builder( child: ListView.builder(
itemCount: widget.visits?.length, itemCount: widget.visits?.length,
itemBuilder: (context,index){ itemBuilder: (context, index) {
Visit visit = widget.visits![index]; Visit visit = widget.visits![index];
return Container( return Container(
padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
margin: EdgeInsets.symmetric(vertical: 4), margin: EdgeInsets.symmetric(vertical: 4),
decoration: BoxDecoration( decoration: BoxDecoration(color: AColors.primaryColor, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [AppStyle.boxShadow]),
color: AColors.primaryColor,
borderRadius: BorderRadius.circular(
AppStyle.getBorderRadius(context)
),
boxShadow: [
AppStyle.boxShadow
]
),
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
"${_subtitle.sn}: ${visit.deviceSerialNumber?? _subtitle.noSerialNumberFound}" , "${_subtitle.sn}: ${visit.deviceSerialNumber ?? _subtitle.noSerialNumberFound}",
style: Theme.of(context).textTheme.headline6?.copyWith( style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontSize: 16, fontWeight: FontWeight.bold),
color: AColors.white,
fontSize: 16,
fontWeight: FontWeight.bold
), ),
), ),
), VisitStatusLabel(
VisitStatusLabel(visit: visit,) visit: visit,
)
], ],
), ),
); );
@ -236,7 +241,7 @@ class _UpdateVisitsGroupSheetState extends State<UpdateVisitsGroupSheet> {
), ),
AButton( AButton(
text: _subtitle.update, text: _subtitle.update,
onPressed: (){ onPressed: () {
Navigator.of(context).pop(_group); Navigator.of(context).pop(_group);
}, },
), ),
@ -244,7 +249,6 @@ class _UpdateVisitsGroupSheetState extends State<UpdateVisitsGroupSheet> {
), ),
Align( Align(
alignment: Alignment.topRight, alignment: Alignment.topRight,
), ),
], ],
), ),

@ -15,7 +15,6 @@ import '../../../widgets/requests/info_row.dart';
import '../../../widgets/visits/visit_status.dart'; import '../../../widgets/visits/visit_status.dart';
import 'pantry/future_edit_pently.dart'; import 'pantry/future_edit_pently.dart';
class VisitDetailsPage extends StatelessWidget { class VisitDetailsPage extends StatelessWidget {
static final String id = "/visit-details"; static final String id = "/visit-details";
final Visit visit; final Visit visit;
@ -31,8 +30,8 @@ class VisitDetailsPage extends StatelessWidget {
child: Column( child: Column(
children: [ children: [
Container( Container(
color:AColors.primaryColor, color: AColors.primaryColor,
padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
child: Row( child: Row(
children: [ children: [
ABackButton(), ABackButton(),
@ -40,10 +39,7 @@ class VisitDetailsPage extends StatelessWidget {
child: Center( child: Center(
child: Text( child: Text(
_subtitle.visitInformation, _subtitle.visitInformation,
style: Theme.of(context).textTheme.headline6?.copyWith( style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
color: AColors.white,
fontStyle: FontStyle.italic
),
), ),
), ),
), ),
@ -53,12 +49,15 @@ class VisitDetailsPage extends StatelessWidget {
buttonSize: 42, buttonSize: 42,
backgroundColor: AColors.green, backgroundColor: AColors.green,
onPressed: () async { onPressed: () async {
Navigator.of(context).push( Navigator.of(context).push(MaterialPageRoute(
MaterialPageRoute(builder: (_)=> FutureEditPentry(visit: visit,)) builder: (_) => FutureEditPentry(
); visit: visit,
)));
}, },
), ),
SizedBox(width: 16,) SizedBox(
width: 16,
)
], ],
), ),
), ),
@ -66,12 +65,13 @@ class VisitDetailsPage extends StatelessWidget {
child: ListView( child: ListView(
padding: EdgeInsets.symmetric(horizontal: 16), padding: EdgeInsets.symmetric(horizontal: 16),
children: [ children: [
SizedBox(height: 8,), SizedBox(
height: 8,
),
MaterialButton( MaterialButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: (){ onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(MaterialPageRoute(
MaterialPageRoute(
builder: (_) => Scaffold( builder: (_) => Scaffold(
body: InteractiveViewer( body: InteractiveViewer(
child: Center( child: Center(
@ -81,27 +81,29 @@ class VisitDetailsPage extends StatelessWidget {
), ),
), ),
), ),
) )));
)
);
}, },
child: SizedBox( child: SizedBox(
height: 140 * AppStyle.getScaleFactor(context), height: 140 * AppStyle.getScaleFactor(context),
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
child: ImageLoader( child: ImageLoader(
url: (visit.images?.isEmpty??false) ? " ":visit.images?.first, url: (visit.images?.isEmpty ?? false) ? " " : visit.images?.first,
boxFit: BoxFit.cover, boxFit: BoxFit.cover,
), ),
), ),
), ),
SizedBox(height: 8,),
SizedBox( SizedBox(
height: 60* AppStyle.getScaleFactor(context), height: 8,
),
SizedBox(
height: 60 * AppStyle.getScaleFactor(context),
child: ImagesList( child: ImagesList(
images: visit.images!, images: visit.images!,
), ),
), ),
SizedBox(height: 8,), SizedBox(
height: 8,
),
RequestInfoRow( RequestInfoRow(
title: _subtitle.code, title: _subtitle.code,
info: visit.serialNumber, info: visit.serialNumber,
@ -114,7 +116,6 @@ class VisitDetailsPage extends StatelessWidget {
title: _subtitle.deviceSN, title: _subtitle.deviceSN,
info: visit.deviceSerialNumber, info: visit.deviceSerialNumber,
), ),
RequestInfoRow( RequestInfoRow(
title: _subtitle.expectDate, title: _subtitle.expectDate,
info: visit.expectDate, info: visit.expectDate,
@ -128,17 +129,18 @@ class VisitDetailsPage extends StatelessWidget {
Expanded( Expanded(
child: Text( child: Text(
"${_subtitle.status} : ", "${_subtitle.status} : ",
style: Theme.of(context).textTheme.subtitle1?.copyWith( style: Theme.of(context).textTheme.subtitle1?.copyWith(fontWeight: FontWeight.bold),
fontWeight: FontWeight.bold
),
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),
), ),
VisitStatusLabel(visit: visit,), VisitStatusLabel(
visit: visit,
),
], ],
), ),
Divider(
Divider(color: Theme.of(context).primaryColor,), color: Theme.of(context).primaryColor,
),
RequestInfoRow( RequestInfoRow(
title: _subtitle.contactStatus, title: _subtitle.contactStatus,
info: visit.assignTo, info: visit.assignTo,

@ -15,10 +15,7 @@ class AppNameBar extends StatelessWidget {
child: Center( child: Center(
child: Text( child: Text(
"Test SA", "Test SA",
style: Theme.of(context) style: Theme.of(context).textTheme.titleLarge?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
.textTheme
.titleLarge
?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
), ),
), ),
); );

@ -86,11 +86,8 @@ class _ATextFormFieldState extends State<ATextFormField> {
maxLines: widget.textInputType == TextInputType.multiline ? null : 1, maxLines: widget.textInputType == TextInputType.multiline ? null : 1,
obscuringCharacter: "", obscuringCharacter: "",
controller: widget.controller, controller: widget.controller,
textInputAction: widget.textInputType == TextInputType.multiline textInputAction: widget.textInputType == TextInputType.multiline ? null : widget.textInputAction ?? TextInputAction.next,
? null onEditingComplete: widget.onAction ?? () => FocusScope.of(context).nextFocus(),
: widget.textInputAction ?? TextInputAction.next,
onEditingComplete:
widget.onAction ?? () => FocusScope.of(context).nextFocus(),
// style: widget.style, // style: widget.style,
style: Theme.of(context).textTheme.bodyLarge, style: Theme.of(context).textTheme.bodyLarge,
decoration: InputDecoration( decoration: InputDecoration(
@ -108,11 +105,7 @@ class _ATextFormFieldState extends State<ATextFormField> {
suffixIcon: widget.prefixIconData == null suffixIcon: widget.prefixIconData == null
? null ? null
: Icon(widget.prefixIconData, : Icon(widget.prefixIconData,
size: widget.prefixIconSize == null size: widget.prefixIconSize == null ? 20 * AppStyle.getScaleFactor(context) : (widget.prefixIconSize! - 10) * AppStyle.getScaleFactor(context), color: const Color(0xff2e303a))),
? 20 * AppStyle.getScaleFactor(context)
: (widget.prefixIconSize! - 10) *
AppStyle.getScaleFactor(context),
color: const Color(0xff2e303a))),
), ),
); );
} }

@ -28,7 +28,7 @@ class AButton extends StatelessWidget {
onPressed: onPressed, onPressed: onPressed,
child: Text( child: Text(
text ?? "", text ?? "",
style: textStyle ?? Theme.of(context).textTheme.subtitle2?.copyWith(color: AColors.white, fontSize: 14,fontWeight: FontWeight.w600), style: textStyle ?? Theme.of(context).textTheme.subtitle2?.copyWith(color: AColors.white, fontSize: 14, fontWeight: FontWeight.w600),
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),
), ),

@ -9,19 +9,19 @@ class AFlatButton extends StatelessWidget {
final EdgeInsets? padding; final EdgeInsets? padding;
final VoidCallback? onPressed; final VoidCallback? onPressed;
const AFlatButton({Key? key, required this.text, this.textColor,this.style ,this.onPressed, this.padding}) : super(key: key); const AFlatButton({Key? key, required this.text, this.textColor, this.style, this.onPressed, this.padding}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return TextButton( return TextButton(
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: this.textColor ?? Colors.black, padding: padding, foregroundColor: this.textColor ?? Colors.black,
padding: padding,
), ),
onPressed: onPressed, onPressed: onPressed,
child: Text( child: Text(
text??"", text ?? "",
style: style ?? Theme.of(context).textTheme.bodyText1, style: style ?? Theme.of(context).textTheme.bodyText1,
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
) ));
);
} }
} }

@ -5,7 +5,6 @@ import '../../app_style/colors.dart';
import '../../app_style/sizing.dart'; import '../../app_style/sizing.dart';
class AIconButton extends StatelessWidget { class AIconButton extends StatelessWidget {
final IconData iconData; final IconData iconData;
final Color? color; final Color? color;
final Color? backgroundColor; final Color? backgroundColor;
@ -13,16 +12,7 @@ class AIconButton extends StatelessWidget {
final double? iconSize; final double? iconSize;
final double buttonSize; final double buttonSize;
const AIconButton({Key? key, required this.iconData, this.onPressed, this.color, this.iconSize, this.buttonSize = 54, this.backgroundColor}) : super(key: key);
const AIconButton({
Key? key,
required this.iconData,
this.onPressed,
this.color,
this.iconSize,
this.buttonSize = 54,
this.backgroundColor
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -32,11 +22,7 @@ class AIconButton extends StatelessWidget {
child: ElevatedButton( child: ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular((AppStyle.borderRadius - 4) * AppStyle.getScaleFactor(context))),
borderRadius: BorderRadius.circular(
(AppStyle.borderRadius - 4) * AppStyle.getScaleFactor(context)
)
),
backgroundColor: backgroundColor ?? AColors.onPrimaryColor, backgroundColor: backgroundColor ?? AColors.onPrimaryColor,
), ),
onPressed: onPressed, onPressed: onPressed,

@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import '../../app_style/sizing.dart'; import '../../app_style/sizing.dart';
class AIconButton2 extends StatelessWidget {
class AIconButton2 extends StatelessWidget {
final IconData iconData; final IconData iconData;
final Color? color; final Color? color;
final VoidCallback? onPressed; final VoidCallback? onPressed;

@ -17,11 +17,7 @@ class AOutLinedButton extends StatelessWidget {
return OutlinedButton( return OutlinedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
padding: padding ?? EdgeInsets.symmetric(vertical: 12), padding: padding ?? EdgeInsets.symmetric(vertical: 12),
textStyle: textStyle ?? Theme textStyle: textStyle ?? Theme.of(context).textTheme.subtitle2?.copyWith(fontSize: 18),
.of(context)
.textTheme
.subtitle2
?.copyWith(fontSize: 18),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context))), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context))),
), ),
onPressed: onPressed, onPressed: onPressed,
@ -30,11 +26,7 @@ class AOutLinedButton extends StatelessWidget {
Expanded( Expanded(
child: Text( child: Text(
text ?? "", text ?? "",
style: Theme style: Theme.of(context).textTheme.subtitle2?.copyWith(color: AColors.primaryColor, fontSize: 14, fontWeight: FontWeight.w600),
.of(context)
.textTheme
.subtitle2
?.copyWith(color: AColors.primaryColor, fontSize: 14, fontWeight: FontWeight.w600),
textAlign: TextAlign.center, textAlign: TextAlign.center,
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),

@ -9,26 +9,20 @@ class ASmallButton extends StatelessWidget {
final EdgeInsets? padding; final EdgeInsets? padding;
final VoidCallback? onPressed; final VoidCallback? onPressed;
const ASmallButton({Key? key, required this.text, this.style ,this.onPressed,this.padding, this.color}) : super(key: key); const ASmallButton({Key? key, required this.text, this.style, this.onPressed, this.padding, this.color}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ElevatedButton( return ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
padding: padding, padding: padding,
primary: color ?? Theme.of(context).primaryColor, primary: color ?? Theme.of(context).primaryColor,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
borderRadius: BorderRadius.circular(8)
),
), ),
child: Text( child: Text(
text??"", text ?? "",
style: style ?? Theme.of(context).textTheme.bodyText1?.copyWith( style: style ?? Theme.of(context).textTheme.bodyText1?.copyWith(color: color == Colors.white ? Theme.of(context).primaryColor : Colors.white),
color: color == Colors.white
? Theme.of(context).primaryColor : Colors.white
),
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),
onPressed: onPressed onPressed: onPressed);
);
} }
} }

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
class CarveInImage extends CustomClipper<Path> { class CarveInImage extends CustomClipper<Path> {
final double gab; final double gab;
var radius=10.0; var radius = 10.0;
CarveInImage(this.gab); CarveInImage(this.gab);
@ -10,14 +10,14 @@ class CarveInImage extends CustomClipper<Path> {
Path getClip(Size size) { Path getClip(Size size) {
Path path = Path(); Path path = Path();
path.lineTo(0, size.height); path.lineTo(0, size.height);
path.lineTo(size.width/2 - gab / 2, size.height); path.lineTo(size.width / 2 - gab / 2, size.height);
path.arcToPoint(Offset(size.width/2 + gab / 2, size.height), path.arcToPoint(Offset(size.width / 2 + gab / 2, size.height), radius: Radius.circular(gab / 2));
radius: Radius.circular(gab/2));
path.lineTo(size.width, size.height); path.lineTo(size.width, size.height);
path.lineTo(size.width, 0); path.lineTo(size.width, 0);
path.lineTo(0, 0); path.lineTo(0, 0);
return path; return path;
} }
@override @override
bool shouldReclip(CustomClipper<Path> oldClipper) => true; bool shouldReclip(CustomClipper<Path> oldClipper) => true;
} }

@ -17,24 +17,16 @@ class ADatePicker extends StatelessWidget {
foregroundColor: Colors.white, foregroundColor: Colors.white,
textStyle: Theme.of(context).textTheme.subtitle2, textStyle: Theme.of(context).textTheme.subtitle2,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular( borderRadius: BorderRadius.circular(12 * AppStyle.getScaleFactor(context)),
12 * AppStyle.getScaleFactor(context)
),
), ),
), ),
child: Text( child: Text(
date == null ? "Pick Date" : date == null ? "Pick Date" : date.toString().split(" ").first,
date.toString().split(" ").first,
style: Theme.of(context).textTheme.subtitle2, style: Theme.of(context).textTheme.subtitle2,
textScaleFactor: AppStyle.getScaleFactor(context), textScaleFactor: AppStyle.getScaleFactor(context),
), ),
onPressed: () async { onPressed: () async {
DateTime? picked = await showDatePicker( DateTime? picked = await showDatePicker(context: context, initialDate: DateTime.now(), firstDate: from ?? DateTime.now(), lastDate: to ?? DateTime.now().add(Duration(days: 365)));
context: context,
initialDate: DateTime.now(),
firstDate: from ?? DateTime.now(),
lastDate: to ?? DateTime.now().add(Duration(days: 365))
);
onDatePicker!(picked!); onDatePicker!(picked!);
}, },
); );

@ -12,28 +12,23 @@ class DepartmentItem extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Padding(
padding: EdgeInsets.symmetric(horizontal: 16,vertical: 6), padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6),
child: ElevatedButton( child: ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: AColors.primaryColor, backgroundColor: AColors.primaryColor,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular( borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)),
AppStyle.getBorderRadius(context)
), ),
), ),
), onPressed: () {
onPressed: (){
onPressed!(department!); onPressed!(department!);
}, },
child: ListTile( child: ListTile(
title: Text( title: Text(
department?.name ?? "", department?.name ?? "",
style: Theme.of(context).textTheme.subtitle1?.copyWith( style: Theme.of(context).textTheme.subtitle1?.copyWith(color: AColors.white),
color: AColors.white
),
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
), ),
), ),
), ),
); );

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save