Null Safety - Widgets Folder

merge-requests/2/head
omar alqaseer 3 years ago
parent b906ca60e6
commit 429c8136ee

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

@ -108,7 +108,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
'$host${URLs.getSingleServiceRequest}?call_nid=$requestId$userData',
));
} catch (error) {
throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle));
throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle) ?? '');
}
// If the call to the server was successful, parse the JSON.
@ -121,7 +121,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
return requests[0];
} else {
throw (HttpStatusManger.getStatusMessage(
status: response.statusCode, subtitle: subtitle));
status: response.statusCode, subtitle: subtitle) ?? "");
}
}
@ -191,27 +191,27 @@ class ServiceRequestsProvider extends ChangeNotifier {
}
Future<int> updateDate({
required String host,
required User user,
required String newDate,
required Lookup employee,
required ServiceRequest request,
required String? host,
required User? user,
required String? newDate,
required Lookup? employee,
required ServiceRequest? request,
}) async {
Response response;
Map<String, String> body = {};
body["uid"] = user.id;
body["token"] = user.token;
body["nid"] = request.id ?? '';
body["date"] = newDate;
body["ass_emp"] = employee.id.toString();
body["uid"] = user?.id ?? '';
body["token"] = user?.token ?? '';
body["nid"] = request?.id ?? '';
body["date"] = newDate ?? '';
body["ass_emp"] = employee?.id.toString() ?? '';
try {
response = await post(
Uri.parse(host + URLs.updateRequestDate),
Uri.parse((host ?? '') + URLs.updateRequestDate),
body: body,
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
request.engineerName = employee.label;
request?.engineerName = employee?.label;
notifyListeners();
}
return response.statusCode;
@ -317,12 +317,12 @@ class ServiceRequestsProvider extends ChangeNotifier {
body["uid"] = user.id;
body["token"] = user.token;
body["job_id"] = request.id ?? '';
body["start_time"] =
(timer.startAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0);
body["start_time"] = ((timer.startAt?.millisecondsSinceEpoch ?? 0) / 1000)
.toStringAsFixed(0);
body["end_time"] =
(timer.endAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0);
((timer.endAt?.millisecondsSinceEpoch ?? 0) / 1000).toStringAsFixed(0);
body["working_hours"] =
(timer.durationInSecond / 60 / 60).toStringAsFixed(5);
((timer.durationInSecond ?? 0) / 60 / 60).toStringAsFixed(5);
body["report_id"] = request.reportID ?? '';
try {
response = await post(
@ -357,7 +357,9 @@ class ServiceRequestsProvider extends ChangeNotifier {
'$host${URLs.getServiceReport}?report_id=$reportId$userData',
));
} catch (error) {
throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle));
throw (HttpStatusManger.getStatusMessage(
status: -1, subtitle: subtitle) ??
'');
}
// If the call to the server was successful, parse the JSON.
@ -367,7 +369,10 @@ class ServiceRequestsProvider extends ChangeNotifier {
json.decode(utf8.decode(response.bodyBytes)), reportId);
} else {
throw (HttpStatusManger.getStatusMessage(
status: response.statusCode, subtitle: subtitle));
status: response.statusCode,
subtitle: subtitle,
) ??
'');
}
}
}

@ -45,14 +45,14 @@ class EmployeesProvider extends ChangeNotifier {
/// 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> getData({required String host, required User user}) async {
Future<int> getData({required String? host, required User? user}) async {
if (_loading == true) return -2;
_loading = true;
notifyListeners();
Response response;
try {
response = await get(
Uri.parse(host + URLs.getEmployees),
Uri.parse((host ?? '') + URLs.getEmployees),
);
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {

@ -47,8 +47,8 @@ class GasCylinderSizesProvider extends ChangeNotifier {
/// for more details check http state manager
/// lib\controllers\http_status_manger\http_status_manger.dart
Future<int> getData({
required String host,
required User user,
required String? host,
required User? user,
}) async {
if (_loading == true) {
return -2;
@ -58,7 +58,7 @@ class GasCylinderSizesProvider extends ChangeNotifier {
Response response;
try {
response = await get(
Uri.parse(host + URLs.getGasCylinderSize),
Uri.parse((host ?? '') + URLs.getGasCylinderSize),
);
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {

@ -46,13 +46,13 @@ class GasStatusProvider extends ChangeNotifier {
/// 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> getData({required String host, required User user}) async {
Future<int> getData({required String? host, required User? user}) async {
if (_loading == true) return -2;
_loading = true;
notifyListeners();
Response response;
try {
response = await get(Uri.parse(host + URLs.getGasStatus));
response = await get(Uri.parse((host ?? '') + URLs.getGasStatus));
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received

@ -46,13 +46,13 @@ class GasTypesProvider extends ChangeNotifier {
/// 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> getData({required String host, required User user}) async {
Future<int> getData({required String? host, required User? user}) async {
if (_loading == true) return -2;
_loading = true;
notifyListeners();
Response response;
try {
response = await get(Uri.parse(host + URLs.getGasTypes));
response = await get(Uri.parse((host ?? '') + URLs.getGasTypes));
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received

@ -45,7 +45,7 @@ class PentryStatusProvider extends ChangeNotifier {
/// 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> getData({required String host, required User user}) async {
Future<int> getData({required String? host, required User? user}) async {
if (_loading == true) {
return -2;
}
@ -53,7 +53,7 @@ class PentryStatusProvider extends ChangeNotifier {
notifyListeners();
Response response;
try {
response = await get(Uri.parse(host + URLs.getPentryStatus));
response = await get(Uri.parse((host ?? '') + URLs.getPentryStatus));
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {

@ -45,7 +45,7 @@ class PentryTaskStatusProvider extends ChangeNotifier {
/// 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> getData({required String host, required User user}) async {
Future<int> getData({required String? host, required User? user}) async {
if (_loading == true) {
return -2;
}
@ -53,7 +53,7 @@ class PentryTaskStatusProvider extends ChangeNotifier {
notifyListeners();
Response response;
try {
response = await get(Uri.parse(host + URLs.getPentryTaskStatus));
response = await get(Uri.parse((host ?? '') + URLs.getPentryTaskStatus));
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {

@ -45,7 +45,7 @@ class PentryVisitStatusProvider extends ChangeNotifier {
/// 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> getData({required String host, required User user}) async {
Future<int> getData({required String? host, required User? user}) async {
if (_loading == true) {
return -2;
}
@ -53,7 +53,7 @@ class PentryVisitStatusProvider extends ChangeNotifier {
notifyListeners();
Response response;
try {
response = await get(Uri.parse(host + URLs.getPentryVisitStatus));
response = await get(Uri.parse((host ?? '') + URLs.getPentryVisitStatus));
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {

@ -45,7 +45,7 @@ class ServiceRequestDefectTypesProvider extends ChangeNotifier {
/// 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> getData({required String host, required User user}) async {
Future<int> getData({required String? host, required User? user}) async {
if (_loading == true) {
return -2;
}
@ -53,7 +53,7 @@ class ServiceRequestDefectTypesProvider extends ChangeNotifier {
notifyListeners();
Response response;
try {
response = await get(Uri.parse(host + URLs.getServiceReportDefectTypes));
response = await get(Uri.parse((host ?? '') + URLs.getServiceReportDefectTypes));
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {

@ -47,8 +47,8 @@ class ServiceReportLastCallsProvider extends ChangeNotifier {
/// for more details check http state manager
/// lib\controllers\http_status_manger\http_status_manger.dart
Future<int> getCalls({
required String host,
required User user,
required String? host,
required User? user,
String? serviceStatus,
}) async {
if (_loading == true) return -2;
@ -58,7 +58,7 @@ class ServiceReportLastCallsProvider extends ChangeNotifier {
try {
response = await get(
Uri.parse(
host +
(host ?? '') +
URLs.getServiceReportLastCalls +
(serviceStatus == null ? "" : "?service_status=$serviceStatus"),
),

@ -45,7 +45,7 @@ class ServiceRequestPriorityProvider extends ChangeNotifier {
/// 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> getData({required String host, required User user}) async {
Future<int> getData({required String? host, required User? user}) async {
if (_loading == true) {
return -2;
}
@ -53,7 +53,7 @@ class ServiceRequestPriorityProvider extends ChangeNotifier {
notifyListeners();
Response response;
try {
response = await get(Uri.parse(host + URLs.getServiceReportPriority));
response = await get(Uri.parse((host ?? '') + URLs.getServiceReportPriority));
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {

@ -45,7 +45,7 @@ class ServiceReportReasonsProvider extends ChangeNotifier {
/// 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> getTypes({required String host, required User user}) async {
Future<int> getTypes({required String? host, required User? user}) async {
if (_loading == true) {
return -2;
}
@ -53,7 +53,7 @@ class ServiceReportReasonsProvider extends ChangeNotifier {
notifyListeners();
Response response;
try {
response = await get(Uri.parse(host + URLs.getServiceReportReasons));
response = await get(Uri.parse((host ?? '') + URLs.getServiceReportReasons));
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received

@ -45,7 +45,7 @@ class ServiceReportStatusProvider extends ChangeNotifier {
/// 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> getTypes({required String host, required User user}) async {
Future<int> getTypes({required String? host, required User? user}) async {
if (_loading == true) {
return -2;
}
@ -53,7 +53,7 @@ class ServiceReportStatusProvider extends ChangeNotifier {
notifyListeners();
Response response;
try {
response = await get(Uri.parse(host + URLs.getServiceReportStatus));
response = await get(Uri.parse((host ?? '') + URLs.getServiceReportStatus));
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received

@ -45,7 +45,7 @@ class ServiceReportTypesProvider extends ChangeNotifier {
/// 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> getTypes({required String host, required User user}) async {
Future<int> getTypes({required String? host, required User? user}) async {
if (_loading == true) {
return -2;
}
@ -53,7 +53,7 @@ class ServiceReportTypesProvider extends ChangeNotifier {
notifyListeners();
Response response;
try {
response = await get(Uri.parse(host + URLs.getServiceReportTypes));
response = await get(Uri.parse((host ?? '') + URLs.getServiceReportTypes));
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received

@ -45,7 +45,7 @@ class ServiceStatusProvider extends ChangeNotifier {
/// 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> getTypes({required String host, required User user}) async {
Future<int> getTypes({required String? host, required User? user}) async {
if (_loading == true) {
return -2;
}
@ -53,7 +53,7 @@ class ServiceStatusProvider extends ChangeNotifier {
notifyListeners();
Response response;
try {
response = await get(Uri.parse(host + URLs.getServiceTypes));
response = await get(Uri.parse((host ?? '') + URLs.getServiceTypes));
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received

@ -1,8 +1,8 @@
class Lookup{
final String label;
final String key;
final int id;
final String? label;
final String? key;
final int? id;
const Lookup({
this.label,

@ -179,7 +179,7 @@ class Subtitle{
String requiredStatus;
String visitInformation;
String expectDate;
String actualDate;
String? actualDate;
String noVisitsFound;
String contactStatus;
String workingHours;

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

@ -3,12 +3,12 @@ class VisitsSearch{
String hospitalName;
String brand;
String model;
String contactStatus;
String? contactStatus;
DateTime expectedDateFrom;
DateTime expectedDateTo;
DateTime actualDateFrom;
DateTime actualDateTo;
int statusValue;
int? statusValue;
VisitsSearch({
this.deviceSerialNumber,

@ -1,20 +1,24 @@
import 'package:flutter/material.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../app_style/colors.dart';
import '../app_style/sizing.dart';
class AppNameBar extends StatelessWidget {
const AppNameBar({super.key});
@override
Widget build(BuildContext context) {
return Container(
height: 50 * AppStyle.getScaleFactor(context),
color:AColors.primaryColor,
color: AColors.primaryColor,
padding: const EdgeInsets.all(8.0),
child: Center(
child: Text(
"Test SA",
style: Theme.of(context).textTheme.headline6.copyWith(
color: AColors.white,
fontStyle: FontStyle.italic
),
style: Theme.of(context)
.textTheme
.titleLarge
?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
),
),
);

@ -1,49 +1,50 @@
import 'package:flutter/material.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../app_style/sizing.dart';
class ATextFormField extends StatefulWidget {
final Function(String) onSaved;
final Function(String) validator;
final Function(String) onChange;
final bool obscureText;
final VoidCallback showPassword;
final String hintText;
final String labelText;
final TextInputType textInputType;
final String initialValue;
final TextStyle style;
final bool enable;
final TextAlign textAlign;
final FocusNode node;
final Widget suffixIcon;
final IconData prefixIconData;
final double prefixIconSize;
final TextEditingController controller;
final TextInputAction textInputAction;
final VoidCallback onAction;
final Function(String?)? onSaved;
final String Function(String?)? validator;
final Function(String)? onChange;
final bool? obscureText;
final VoidCallback? showPassword;
final String? hintText;
final String? labelText;
final TextInputType? textInputType;
final String? initialValue;
final TextStyle? style;
final bool? enable;
final TextAlign? textAlign;
final FocusNode? node;
final Widget? suffixIcon;
final IconData? prefixIconData;
final double? prefixIconSize;
final TextEditingController? controller;
final TextInputAction? textInputAction;
final VoidCallback? onAction;
const ATextFormField(
{Key key,
this.onSaved,
this.validator,
this.node,
this.onChange,
this.obscureText,
this.showPassword,
this.hintText,
this.labelText,
this.textInputType = TextInputType.text,
this.initialValue,
this.enable = true,
this.style,
this.textAlign,
this.suffixIcon,
this.prefixIconData,
this.prefixIconSize,
this.controller,
this.textInputAction,
this.onAction})
: super(key: key);
const ATextFormField({
Key? key,
this.initialValue,
this.node,
this.onChange,
this.showPassword,
this.hintText,
this.labelText,
this.style,
this.textAlign,
this.suffixIcon,
this.prefixIconSize,
this.textInputAction,
this.onAction,
this.obscureText,
this.textInputType = TextInputType.text,
this.enable = true,
this.prefixIconData,
this.controller,
this.onSaved,
this.validator,
}) : super(key: key);
@override
State<ATextFormField> createState() => _ATextFormFieldState();
@ -52,7 +53,9 @@ class ATextFormField extends StatefulWidget {
class _ATextFormFieldState extends State<ATextFormField> {
@override
void initState() {
if (widget.controller != null) widget.controller.text = widget.initialValue;
if (widget.controller != null) {
widget.controller!.text = widget.initialValue ?? '';
}
super.initState();
}
@ -60,13 +63,15 @@ class _ATextFormFieldState extends State<ATextFormField> {
Widget build(BuildContext context) {
return Container(
height: widget.textInputType == TextInputType.multiline ? null : 50,
padding: EdgeInsets.only(left: 12, right: 12),
padding: const EdgeInsets.only(left: 12, right: 12),
decoration: BoxDecoration(
color: Color(0xfff5f5f5),
color: const Color(0xfff5f5f5),
border: Border.all(
color: Color(0xffefefef),
color: const Color(0xffefefef),
),
borderRadius: BorderRadius.circular(
AppStyle.borderRadius * AppStyle.getScaleFactor(context),
),
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
),
child: TextFormField(
focusNode: widget.node,
@ -81,18 +86,21 @@ class _ATextFormFieldState extends State<ATextFormField> {
maxLines: widget.textInputType == TextInputType.multiline ? null : 1,
obscuringCharacter: "",
controller: widget.controller,
textInputAction: widget.textInputType == TextInputType.multiline ? null : widget.textInputAction ?? TextInputAction.next,
onEditingComplete: widget.onAction ?? () => FocusScope.of(context).nextFocus(),
textInputAction: widget.textInputType == TextInputType.multiline
? null
: widget.textInputAction ?? TextInputAction.next,
onEditingComplete:
widget.onAction ?? () => FocusScope.of(context).nextFocus(),
// style: widget.style,
style: Theme.of(context).textTheme.bodyText1,
style: Theme.of(context).textTheme.bodyLarge,
decoration: InputDecoration(
border: InputBorder.none,
suffixIconConstraints: BoxConstraints(minWidth: 0),
suffixIconConstraints: const BoxConstraints(minWidth: 0),
disabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
constraints: BoxConstraints(),
errorStyle: TextStyle(height: 0.3),
constraints: const BoxConstraints(),
errorStyle: const TextStyle(height: 0.3),
//contentPadding: EdgeInsets.only(left: 0),
hintText: widget.hintText,
labelText: widget.labelText,
@ -100,7 +108,11 @@ class _ATextFormFieldState extends State<ATextFormField> {
suffixIcon: widget.prefixIconData == null
? null
: Icon(widget.prefixIconData,
size: widget.prefixIconSize == null ? 20 * AppStyle.getScaleFactor(context) : (widget.prefixIconSize - 10) * AppStyle.getScaleFactor(context), color: Color(0xff2e303a))),
size: widget.prefixIconSize == null
? 20 * AppStyle.getScaleFactor(context)
: (widget.prefixIconSize! - 10) *
AppStyle.getScaleFactor(context),
color: const Color(0xff2e303a))),
),
);
}

@ -2,13 +2,13 @@ import 'package:test_sa/views/app_style/sizing.dart';
import 'package:flutter/material.dart';
class ASmallButton extends StatelessWidget {
final String text;
final String? text;
final TextStyle style;
final Color color;
final EdgeInsets padding;
final VoidCallback onPressed;
const ASmallButton({Key key, this.text, this.style ,this.onPressed,this.padding, this.color}) : super(key: key);
const ASmallButton({Key? key, this.text, this.style ,this.onPressed,this.padding, this.color}) : super(key: key);
@override
Widget build(BuildContext context) {
return ElevatedButton(

@ -5,12 +5,12 @@ import 'package:test_sa/views/app_style/sizing.dart';
import 'date_picker.dart';
class FromToDateBar extends StatefulWidget {
final DateTime from;
final DateTime to;
final DateTime? from;
final DateTime? to;
final Function(DateTime) onPickFrom;
final Function(DateTime) onPickTo;
const FromToDateBar({Key key, this.from, this.to, this.onPickFrom, this.onPickTo}) : super(key: key);
const FromToDateBar({Key? key, this.from, this.to, this.onPickFrom, this.onPickTo}) : super(key: key);
@override
_FromToDateBarState createState() => _FromToDateBarState();
}

@ -5,24 +5,25 @@ import 'package:test_sa/models/subtitle.dart';
import 'app_loading.dart';
import 'failed_loading.dart';
class LoadingManager extends StatefulWidget {
final bool isLoading;
final bool? isLoading;
final bool isFailedLoading;
final bool isNotPage;
final int progress;
final int? progress;
final bool askOnBack;
final int stateCode;
final int? stateCode;
final Future<void> Function() onRefresh;
final Widget child;
LoadingManager({
Key key,
@required this.isLoading,
@required this.isFailedLoading,
@required this.stateCode,
@required this.onRefresh,
@required this.child,
const LoadingManager({
Key? key,
required this.isFailedLoading,
required this.onRefresh,
required this.child,
this.progress,
this.stateCode,
this.isLoading,
this.isNotPage = false,
this.askOnBack = false,
}) : super(key: key);
@ -32,10 +33,9 @@ class LoadingManager extends StatefulWidget {
}
class _LoadingManagerState extends State<LoadingManager> {
@override
void initState() {
if(widget.onRefresh != null && widget.stateCode == null){
if (widget.onRefresh != null && widget.stateCode == null) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
widget.onRefresh();
});
@ -48,7 +48,7 @@ class _LoadingManagerState extends State<LoadingManager> {
Subtitle subtitle = AppLocalization.of(context).subtitle;
Widget placeHolder;
// to load data if load not start
if(widget.isLoading == false && widget.stateCode == null){
if (widget.isLoading == false && widget.stateCode == null) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
widget.onRefresh();
});
@ -56,9 +56,9 @@ class _LoadingManagerState extends State<LoadingManager> {
// if loading of still not start in loading (true or null)
// return loading widget
if(widget.isLoading != false || widget.stateCode == null){
if (widget.isLoading != false || widget.stateCode == null) {
placeHolder = ALoading();
}else if(widget.isFailedLoading && !widget.isNotPage){
} else if (widget.isFailedLoading && !widget.isNotPage) {
// if failed return failed widget
placeHolder = FailedLoading(
message: HttpStatusManger.getStatusMessage(
@ -69,7 +69,7 @@ class _LoadingManagerState extends State<LoadingManager> {
// if load end successfully return loaded widget
return RefreshIndicator(
onRefresh: () async{
onRefresh: () async {
await widget.onRefresh();
},
child: AnimatedSwitcher(

@ -1,10 +1,12 @@
import 'package:flutter/material.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../../app_style/sizing.dart';
class NoItemFound extends StatelessWidget {
final String message;
final String? message;
const NoItemFound({
Key key,
Key? key,
this.message,
}) : super(key: key);
@ -14,7 +16,7 @@ class NoItemFound extends StatelessWidget {
children: [
Center(
child: Text(
message ?? "no item found",
message ?? "no item found",
style: Theme.of(context).textTheme.headline6,
textScaleFactor: AppStyle.getScaleFactor(context),
),

@ -5,16 +5,16 @@ import 'package:qr_code_scanner/qr_code_scanner.dart';
import '../buttons/app_icon_button.dart';
class ScanQr extends StatefulWidget {
const ScanQr({Key key}) : super(key: key);
const ScanQr({Key? key}) : super(key: key);
@override
_ScanQrState createState() => _ScanQrState();
ScanQrState createState() => ScanQrState();
}
class _ScanQrState extends State<ScanQr> {
class ScanQrState extends State<ScanQr> {
Barcode result;
QRViewController _controller;
Barcode? result;
QRViewController? _controller;
bool _scanDone = false;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR_scanner');
@ -64,7 +64,7 @@ class _ScanQrState extends State<ScanQr> {
),
SafeArea(
child: Padding(
padding: EdgeInsets.all(12.0),
padding: const EdgeInsets.all(12.0),
child: AIconButton(
iconData:Icons.arrow_back,
onPressed: (){

@ -1,73 +1,82 @@
import 'package:flutter/material.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../../app_style/sizing.dart';
class RequestInfoRow extends StatelessWidget {
final String title;
final String info;
final String content;
final Widget contentWidget;
final Widget infoWidget;
final String? title;
final String? info;
final String? content;
final Widget? contentWidget;
final Widget? infoWidget;
const RequestInfoRow({
Key? key,
this.title,
this.info,
this.content,
this.contentWidget,
this.infoWidget,
}) : super(key: key);
const RequestInfoRow({Key key, this.title, this.info,this.content, this.contentWidget, this.infoWidget}) : super(key: key);
@override
Widget build(BuildContext context) {
if(info != null && info.isEmpty){
return SizedBox.shrink();
if (info != null && info!.isEmpty) {
return const SizedBox.shrink();
}
if(content != null && content.isEmpty){
return SizedBox.shrink();
if (content != null && content!.isEmpty) {
return const SizedBox.shrink();
}
return Column(
children: [
Row(
children: [
Text(
title + " : ",
style: Theme.of(context).textTheme.subtitle2.copyWith(
//fontSize: 12
),
"$title : ",
style: Theme.of(context).textTheme.titleSmall?.copyWith(
//fontSize: 12
),
textScaleFactor: AppStyle.getScaleFactor(context),
),
if(info != null)
Expanded(
child: Text(
info,
style: Theme.of(context).textTheme.bodyText2,
textAlign: TextAlign.right,
textScaleFactor: AppStyle.getScaleFactor(context),
if (info != null)
Expanded(
child: Text(
info ?? '',
style: Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.right,
textScaleFactor: AppStyle.getScaleFactor(context),
),
),
),
if(infoWidget != null)
if (infoWidget != null)
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
infoWidget,
infoWidget ?? const SizedBox(),
],
),
),
],
),
if(content != null)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row(
children: [
Expanded(
child: Text(
content ?? 'No data found',
style: Theme.of(context).textTheme.bodyText2,
textAlign: TextAlign.center,
textScaleFactor: AppStyle.getScaleFactor(context),
if (content != null)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row(
children: [
Expanded(
child: Text(
content ?? 'No data found',
style: Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.center,
textScaleFactor: AppStyle.getScaleFactor(context),
),
),
),
],
],
),
),
if (contentWidget != null) contentWidget!,
Divider(
color: Theme.of(context).primaryColor,
),
if(contentWidget != null)
contentWidget,
Divider(color: Theme.of(context).primaryColor,),
],
);
}

@ -1,35 +1,39 @@
import 'package:flutter/material.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
class StatusLabel extends StatelessWidget {
final String label;
final Color color;
const StatusLabel({Key key, this.label, this.color}) : super(key: key);
import '../../app_style/colors.dart';
import '../../app_style/sizing.dart';
class StatusLabel extends StatelessWidget {
final String? label;
final Color? color;
const StatusLabel({
Key? key,
this.label,
this.color,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 2,horizontal: 8),
return Container(
padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 8),
alignment: Alignment.center,
decoration: BoxDecoration(
color: color ?? Colors.green,
borderRadius: BorderRadius.circular(
AppStyle.getBorderRadius(context)
),
boxShadow: [
AppStyle.boxShadow
]
color: color ?? Colors.green,
borderRadius: BorderRadius.circular(
AppStyle.getBorderRadius(context),
),
boxShadow: const [AppStyle.boxShadow],
),
child: Text(
label ?? "no status",
style: Theme.of(context).textTheme.subtitle2.copyWith(
color: color.computeLuminance() > 0.5
? AColors.black : Colors.white,
),
)
);
style: Theme.of(context).textTheme.titleSmall?.copyWith(
color: color != null
? color!.computeLuminance() > 0.5
? AColors.black
: Colors.white
: null,
),
));
}
}

@ -1,37 +1,37 @@
import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/subtitle.dart';
import 'package:test_sa/models/user.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/pages/user/requests/report/create_service_report.dart';
import 'package:test_sa/views/pages/user/requests/report/future_service_report.dart';
import 'package:test_sa/views/widgets/loaders/image_loader.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/views/widgets/timer/app_timer.dart';
import '../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../controllers/localization/localization.dart';
import '../../../controllers/providers/api/service_requests_provider.dart';
import '../../../controllers/providers/api/user_provider.dart';
import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../models/enums/user_types.dart';
import '../../../models/service_request/service_request.dart';
import '../../../models/subtitle.dart';
import '../../../models/user.dart';
import '../../app_style/colors.dart';
import '../../app_style/sizing.dart';
import '../../pages/user/requests/report/create_service_report.dart';
import '../loaders/image_loader.dart';
import 'request_status.dart';
class ServiceRequestItem extends StatelessWidget {
final int index;
final ServiceRequest request;
final Function(ServiceRequest) onPressed;
const ServiceRequestItem({Key key, this.request, this.onPressed, this.index}) : super(key: key);
const ServiceRequestItem({
Key? key,
required this.request,
required this.onPressed,
required this.index,
}) : super(key: key);
@override
Widget build(BuildContext context) {
Subtitle _subtitle = AppLocalization.of(context).subtitle;
User _user = Provider.of<UserProvider>(context,listen: false).user;
final servicesProvider = Provider.of<ServiceRequestsProvider>(context,listen: false);
final settingProvider = Provider.of<SettingProvider>(context,listen: false);
Subtitle? subtitle = AppLocalization.of(context)?.subtitle;
User? user = Provider.of<UserProvider>(context, listen: false).user;
Color itemColor = index % 2 == 0
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.onPrimary;
@ -42,71 +42,76 @@ class ServiceRequestItem extends StatelessWidget {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8),
primary: itemColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
AppStyle.getBorderRadius(context)
),
),
),
//padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8),
onPressed: (){
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
backgroundColor: itemColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
AppStyle.getBorderRadius(context),
),
),
),
onPressed: () {
onPressed(request);
},
child: Row(
children: [
//Placeholder(color: onItemColor,fallbackWidth: 80,fallbackHeight: 80,),
_user.type == UsersTypes.normal_user && request.devicePhotos.isEmpty ? SizedBox.shrink():
SizedBox(
width: 80,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
request.devicePhotos.isEmpty ? SizedBox.shrink():
Column(
children: [
SizedBox(
height: 80,
width: 80,
child: ImageLoader(
url: request.devicePhotos.first,
boxFit: BoxFit.cover,
),
),
SizedBox(height: 24,),
],
),
user?.type == UsersTypes.normal_user &&
(request.devicePhotos?.isEmpty ?? true)
? const SizedBox.shrink()
: SizedBox(
width: 80,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
request.devicePhotos?.isEmpty ?? true
? const SizedBox.shrink()
: Column(
children: [
SizedBox(
height: 80,
width: 80,
child: ImageLoader(
url: request.devicePhotos?.first ?? '',
boxFit: BoxFit.cover,
),
),
const SizedBox(
height: 24,
),
],
),
_user.type == UsersTypes.engineer ?
Material(
color: onItemColor,
elevation: 6,
shape: CircleBorder(),
child: IconButton(
icon: Icon(
Icons.description,
color: itemColor,
size: 32,
),
onPressed: (){
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => CreateServiceReport(
request: request,
user?.type == UsersTypes.engineer
? Material(
color: onItemColor,
elevation: 6,
shape: const CircleBorder(),
child: IconButton(
icon: Icon(
Icons.description,
color: itemColor,
size: 32,
),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => CreateServiceReport(
request: request,
),
),
);
},
),
)
),
);
},
: const SizedBox.shrink(),
//SizedBox(height: 8,),
],
),
) :SizedBox.shrink(),
//SizedBox(height: 8,),
],
),
),
const SizedBox(
width: 8,
),
SizedBox(width: 8,),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -120,141 +125,182 @@ class ServiceRequestItem extends StatelessWidget {
Row(
children: [
Expanded(
child: request.requestCode == null ? SizedBox.shrink():
Text(
request.requestCode ?? "-----",
style: Theme.of(context).textTheme.headline6.copyWith(
color: onItemColor,
fontSize: 16,
fontWeight: FontWeight.bold
),
),
child: request.requestCode == null
? const SizedBox.shrink()
: Text(
request.requestCode ?? "-----",
style: Theme.of(context)
.textTheme
.titleLarge
?.copyWith(
color: onItemColor,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
request.engineerName == null ? SizedBox.shrink():
Text(
request.engineerName ?? "",
style: Theme.of(context).textTheme.subtitle2.copyWith(
color: onItemColor,
fontSize: 12,
fontWeight: FontWeight.normal
),
),
request.engineerName == null
? const SizedBox.shrink()
: Text(
request.engineerName ?? "",
style: Theme.of(context)
.textTheme
.titleSmall
?.copyWith(
color: onItemColor,
fontSize: 12,
fontWeight: FontWeight.normal,
),
),
],
),
Divider(color: onItemColor,),
Row(
children: [
Expanded(
child: request.deviceModel == null ? SizedBox.shrink():
Text(
request.deviceModel ?? "Model not available",
style: Theme.of(context).textTheme.subtitle2.copyWith(
color: onItemColor,
fontSize: 12,
fontWeight: FontWeight.normal
),
),
),
request.engineerMobile == null ? SizedBox.shrink():
Text(
request.engineerMobile,
style: Theme.of(context).textTheme.subtitle1.copyWith(
color: onItemColor,
fontSize: 12,
fontWeight: FontWeight.normal
),
),
],
Divider(
color: onItemColor,
),
Divider(color: onItemColor,),
Row(
children: [
Expanded(
child: request.deviceSerialNumber == null ? SizedBox.shrink():
Text(
request.deviceSerialNumber,
style: Theme.of(context).textTheme.subtitle2.copyWith(
color: onItemColor,
fontSize: 12,
fontWeight: FontWeight.normal
),
),
child: request.deviceModel == null
? const SizedBox.shrink()
: Text(
request.deviceModel ??
"Model not available",
style: Theme.of(context)
.textTheme
.titleSmall
?.copyWith(
color: onItemColor,
fontSize: 12,
fontWeight: FontWeight.normal,
),
),
),
request.engineerMobile == null
? const SizedBox.shrink()
: Text(
request.engineerMobile ?? '',
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(
color: onItemColor,
fontSize: 12,
fontWeight: FontWeight.normal,
),
),
],
),
request.deviceEnName == null ? SizedBox.shrink():
Divider(
color: onItemColor,
),
Row(
children: [
Expanded(
child: Text(
request.deviceEnName,
style: Theme.of(context).textTheme.subtitle1.copyWith(
color: onItemColor,
fontSize: 12,
fontWeight: FontWeight.normal
),
),
child: request.deviceSerialNumber == null
? const SizedBox.shrink()
: Text(
request.deviceSerialNumber ?? '',
style: Theme.of(context)
.textTheme
.titleSmall
?.copyWith(
color: onItemColor,
fontSize: 12,
fontWeight: FontWeight.normal,
),
),
),
],
),
request.deviceEnName == null
? const SizedBox.shrink()
: Row(
children: [
Expanded(
child: Text(
request.deviceEnName ?? '',
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(
color: onItemColor,
fontSize: 12,
fontWeight: FontWeight.normal,
),
),
),
],
),
],
),
),
],
),
Divider(color: onItemColor,),
Divider(
color: onItemColor,
),
Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(
request.maintenanceIssue ?? "No maintenance issue found",
style: Theme.of(context).textTheme.subtitle1.copyWith(
color: onItemColor
),
request.maintenanceIssue ??
"No maintenance issue found",
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(color: onItemColor),
textAlign: TextAlign.center,
),
),
),
Divider(color: onItemColor,),
Divider(color: onItemColor),
Row(
children: [
Text(
request.date ?? "Date not available",
style: Theme.of(context).textTheme.subtitle2.copyWith(
color: onItemColor
style: Theme.of(context)
.textTheme
.titleSmall
?.copyWith(color: onItemColor),
),
const Spacer(),
StatusLabel(
label: request.statusLabel,
color: AColors.getRequestStatusColor(
request.statusValue ?? 0,
),
),
Spacer(),
StatusLabel(label: request.statusLabel,
color: AColors.getRequestStatusColor(request.statusValue)),
],
),
request.nextVisitDate == null ? SizedBox.shrink() :
Column(
children: [
Divider(color: onItemColor,),
Row(
children: [
Text(
_subtitle.nextVisitDate,
style: Theme.of(context).textTheme.subtitle2.copyWith(
color: onItemColor
request.nextVisitDate == null
? const SizedBox.shrink()
: Column(
children: [
Divider(
color: onItemColor,
),
),
Spacer(),
Text(
DateFormat('EE dd/MM/yyyy').format(request.nextVisitDate),
style: Theme.of(context).textTheme.subtitle2.copyWith(
color: onItemColor
Row(
children: [
Text(
subtitle?.nextVisitDate ?? '',
style: Theme.of(context)
.textTheme
.titleSmall
?.copyWith(color: onItemColor),
),
const Spacer(),
Text(
DateFormat('EE dd/MM/yyyy')
.format(request.nextVisitDate!),
style: Theme.of(context)
.textTheme
.titleSmall
?.copyWith(color: onItemColor),
),
],
),
),
],
),
],
),
],
),
],
),
),

@ -1,24 +1,30 @@
import 'package:flutter/material.dart';
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/subtitle.dart';
import 'package:test_sa/views/pages/user/requests/request_details.dart';
import 'package:test_sa/views/widgets/loaders/lazy_loading.dart';
import 'package:test_sa/views/widgets/loaders/no_item_found.dart';
import 'package:test_sa/views/widgets/requests/service_request_item.dart';
import '../../../controllers/localization/localization.dart';
import '../../../models/service_request/service_request.dart';
import '../../../models/subtitle.dart';
import '../../pages/user/requests/request_details.dart';
import '../loaders/lazy_loading.dart';
import '../loaders/no_item_found.dart';
import 'service_request_item.dart';
class ServiceRequestsList extends StatelessWidget {
final List<ServiceRequest> requests;
final bool nextPage;
final Future<void> Function() onLazyLoad;
const ServiceRequestsList({Key key, this.requests, this.nextPage, this.onLazyLoad}) : super(key: key);
const ServiceRequestsList({
Key? key,
required this.requests,
required this.nextPage,
required this.onLazyLoad,
}) : super(key: key);
@override
Widget build(BuildContext context) {
Subtitle _subtitle = AppLocalization.of(context).subtitle;
if(requests.length == 0){
return NoItemFound(message: _subtitle.noServiceRequestFound,);
Subtitle? subtitle = AppLocalization.of(context)?.subtitle;
if (requests.isEmpty) {
return NoItemFound(message: subtitle?.noServiceRequestFound);
}
return LazyLoading(
nextPage: nextPage,
@ -26,20 +32,22 @@ class ServiceRequestsList extends StatelessWidget {
child: ListView.builder(
//physics: BouncingScrollPhysics(),
itemCount: requests.length,
padding: EdgeInsets.symmetric(horizontal: 16,vertical: 8),
itemBuilder: (context,itemIndex){
return ServiceRequestItem(
index: itemIndex,
request: requests[itemIndex],
onPressed: (request){
Navigator.of(context).push(
MaterialPageRoute(
builder: (_)=> RequestDetailsPage(serviceRequest: request,)
)
);
},
);
}
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
itemBuilder: (context, itemIndex) {
return ServiceRequestItem(
index: itemIndex,
request: requests[itemIndex],
onPressed: (request) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => RequestDetailsPage(
serviceRequest: request,
),
),
);
},
);
},
),
);
}

@ -1,51 +1,48 @@
import 'package:flutter/cupertino.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart';
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/service_request/service_request_search.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/subtitle.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/buttons/app_button.dart';
import 'package:test_sa/views/widgets/buttons/app_small_button.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field.dart';
import 'package:flutter/material.dart';
import 'package:test_sa/views/widgets/status/employee/employee_mune.dart';
import '../app_text_form_field.dart';
import '../../../controllers/http_status_manger/http_status_manger.dart';
import '../../../controllers/localization/localization.dart';
import '../../../controllers/providers/api/service_requests_provider.dart';
import '../../../controllers/providers/api/user_provider.dart';
import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../models/lookup.dart';
import '../../../models/service_request/service_request.dart';
import '../../../models/subtitle.dart';
import '../../app_style/sizing.dart';
import '../buttons/app_small_button.dart';
import '../date_and_time/date_picker.dart';
import '../status/employee/employee_mune.dart';
class ServiceRequestsUpdateDialog extends StatefulWidget {
final ServiceRequest request;
const ServiceRequestsUpdateDialog({
Key key, this.request,
Key? key,
required this.request,
}) : super(key: key);
@override
State<ServiceRequestsUpdateDialog> createState() => _ServiceRequestsUpdateDialogState();
State<ServiceRequestsUpdateDialog> createState() =>
_ServiceRequestsUpdateDialogState();
}
class _ServiceRequestsUpdateDialogState extends State<ServiceRequestsUpdateDialog>
with TickerProviderStateMixin{
DateTime _dateTime;
Lookup _employee;
Subtitle _subtitle;
UserProvider _userProvider;
SettingProvider _settingProvider;
ServiceRequestsProvider _serviceRequestsProvider;
class _ServiceRequestsUpdateDialogState
extends State<ServiceRequestsUpdateDialog> with TickerProviderStateMixin {
DateTime? _dateTime;
Lookup? _employee;
Subtitle? _subtitle;
UserProvider? _userProvider;
SettingProvider? _settingProvider;
ServiceRequestsProvider? _serviceRequestsProvider;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
_update() async {
if(_dateTime == null && _employee == null){
Fluttertoast.showToast(
msg: _subtitle.noDateFound,
);
if (_dateTime == null && _employee == null) {
Fluttertoast.showToast(msg: _subtitle?.noDateFound ?? '');
return;
}
showDialog<void>(
@ -53,22 +50,26 @@ class _ServiceRequestsUpdateDialogState extends State<ServiceRequestsUpdateDialo
barrierDismissible: false,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: Text(_subtitle.updatingDots),
content: Center(child: CircularProgressIndicator()),
title: Text(_subtitle?.updatingDots ?? ''),
content: const Center(child: CircularProgressIndicator()),
);
},
);
int status = await _serviceRequestsProvider.updateDate(
user: _userProvider.user,
host: _settingProvider.host,
request: widget.request,
newDate: _dateTime?.toString()?.split(" ")?.first,
employee: _employee
int? status = await _serviceRequestsProvider?.updateDate(
user: _userProvider?.user,
host: _settingProvider?.host,
request: widget.request,
newDate: _dateTime?.toString().split(" ").first,
employee: _employee,
);
if(status == 200) Navigator.of(context).pop();
if (status == 200) Navigator.of(context).pop();
Navigator.of(context).pop();
Fluttertoast.showToast(
msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle),
msg: HttpStatusManger.getStatusMessage(
status: status,
subtitle: _subtitle,
) ??
'',
);
}
@ -79,15 +80,16 @@ class _ServiceRequestsUpdateDialogState extends State<ServiceRequestsUpdateDialo
@override
Widget build(BuildContext context) {
_subtitle = AppLocalization.of(context).subtitle;
_userProvider = Provider.of<UserProvider>(context,listen: false);
_settingProvider = Provider.of<SettingProvider>(context,listen: false);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context,listen: false);
return Column(
_subtitle = AppLocalization.of(context)?.subtitle;
_userProvider = Provider.of<UserProvider>(context, listen: false);
_settingProvider = Provider.of<SettingProvider>(context, listen: false);
_serviceRequestsProvider =
Provider.of<ServiceRequestsProvider>(context, listen: false);
return Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
// height: MediaQuery.of(context).size.height / 1.2,
// height: MediaQuery.of(context).size.height / 1.2,
child: Form(
key: _formKey,
child: Padding(
@ -98,46 +100,49 @@ class _ServiceRequestsUpdateDialogState extends State<ServiceRequestsUpdateDialo
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ASmallButton(
text: _subtitle.cancel,
onPressed: (){
text: _subtitle?.cancel,
onPressed: () {
Navigator.of(context).pop();
},
),
ASmallButton(
text: _subtitle.update,
text: _subtitle?.update,
onPressed: _update,
)
],
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context)),
Row(
children: [
Expanded(
child: Text(
_subtitle.date,
_subtitle?.date ?? '',
style: Theme.of(context).textTheme.subtitle1,
textScaleFactor: AppStyle.getScaleFactor(context),
),
),
ADatePicker(
date: _dateTime,
date: _dateTime!,
from: DateTime.now(),
onDatePicker: (date){
onDatePicker: (date) {
_dateTime = date;
setState(() {});
},
),
],
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
SizedBox(
height: 8.0 * AppStyle.getScaleFactor(context),
),
EmployeeMenu(
initialValue: _employee,
onSelect: (employee){
onSelect: (employee) {
_employee = employee;
},
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
SizedBox(
height: 8.0 * AppStyle.getScaleFactor(context),
),
],
),
),

@ -1,29 +1,36 @@
import 'package:flutter/material.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../../../models/lookup.dart';
import '../../app_style/colors.dart';
import '../../app_style/sizing.dart';
class FilterItem extends StatelessWidget {
final bool isSelected;
final Lookup status;
final Lookup? status;
final VoidCallback onSelected;
const FilterItem({
Key key,
Key? key,
this.status,
this.isSelected,
this.onSelected
required this.isSelected,
required this.onSelected,
}) : super(key: key);
Color getStatusColor(){
switch(status.id){
case 0: return AColors.green;
case 4: return AColors.deepRed;
case 6: return AColors.green;
case 5: return AColors.orange;
case 8: return AColors.green;
case 9: return AColors.orange;
default : return AColors.grey;
Color getStatusColor() {
switch (status?.id) {
case 0:
return AColors.green;
case 4:
return AColors.deepRed;
case 6:
return AColors.green;
case 5:
return AColors.orange;
case 8:
return AColors.green;
case 9:
return AColors.orange;
default:
return AColors.grey;
}
}
@ -35,23 +42,24 @@ class FilterItem extends StatelessWidget {
height: 30,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(horizontal: 8),
padding: const EdgeInsets.symmetric(horizontal: 8),
backgroundColor: getStatusColor(),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
AppStyle.getBorderRadius(context)
)
borderRadius: BorderRadius.circular(
AppStyle.getBorderRadius(context),
),
),
primary: getStatusColor(),
),
onPressed: onSelected,
child: Text(
status.label??"",
style: Theme.of(context).textTheme.bodyText1.copyWith(
color:getStatusColor().computeLuminance() > 0.5
? AColors.black : Colors.white,
),
status?.label ?? "",
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: getStatusColor().computeLuminance() > 0.5
? AColors.black
: Colors.white,
),
textScaleFactor: AppStyle.getScaleFactor(context),
),
onPressed:onSelected,
),
),
);

@ -1,54 +1,56 @@
import 'package:flutter/material.dart';
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/service_request_search.dart';
import 'package:test_sa/models/subtitle.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/buttons/app_button.dart';
import 'package:test_sa/views/widgets/buttons/app_small_button.dart';
import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field.dart';
import '../../../controllers/localization/localization.dart';
import '../../../models/lookup.dart';
import '../../../models/service_request/service_request_search.dart';
import '../../../models/subtitle.dart';
import '../../app_style/sizing.dart';
import '../app_text_form_field.dart';
import '../buttons/app_button.dart';
import '../buttons/app_small_button.dart';
import '../hospitals/hospital_auto_complete_field.dart';
import 'filter_item.dart';
class ServiceRequestsSearchDialog extends StatefulWidget {
final ServiceRequestSearch initialSearchValue;
final bool expandedSearch;
final Function(ServiceRequestSearch) onSearch;
final bool? expandedSearch;
final Function(ServiceRequestSearch)? onSearch;
const ServiceRequestsSearchDialog({
Key key,
this.initialSearchValue,
Key? key,
required this.initialSearchValue,
this.expandedSearch,
this.onSearch
this.onSearch,
}) : super(key: key);
@override
_ServiceRequestsSearchDialogState createState() => _ServiceRequestsSearchDialogState();
ServiceRequestsSearchDialogState createState() =>
ServiceRequestsSearchDialogState();
}
class _ServiceRequestsSearchDialogState extends State<ServiceRequestsSearchDialog>
with TickerProviderStateMixin{
ServiceRequestSearch _search;
List<Lookup> status = [
Lookup(label: "New", id: 4,),
class ServiceRequestsSearchDialogState
extends State<ServiceRequestsSearchDialog> with TickerProviderStateMixin {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Lookup(label: "Repaired", id: 6,),
late ServiceRequestSearch _search;
late List<Lookup> status = const [
Lookup(label: "New", id: 4),
Lookup(label: "Repaired", id: 6),
Lookup(label: "Repeated", id: 8),
Lookup(label: "Closed", id: 9,),
Lookup(label: "Under Repair", id: 5,),
Lookup(label: "Closed", id: 9),
Lookup(label: "Under Repair", id: 5),
];
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
void initState() {
super.initState();
_search = ServiceRequestSearch();
_search.fromSearch(widget.initialSearchValue);
}
@override
Widget build(BuildContext context) {
Subtitle _subtitle = AppLocalization.of(context).subtitle;
return SizedBox(
Subtitle? subtitle = AppLocalization.of(context)?.subtitle;
return SizedBox(
height: MediaQuery.of(context).size.height / 1.2,
child: Form(
key: _formKey,
@ -60,121 +62,120 @@ class _ServiceRequestsSearchDialogState extends State<ServiceRequestsSearchDialo
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ASmallButton(
text: _subtitle.cancel,
onPressed: (){
text: subtitle?.cancel,
onPressed: () {
Navigator.of(context).pop();
},
),
ASmallButton(
text: _subtitle.search,
onPressed: (){
if(!_formKey.currentState.validate())
return;
_formKey.currentState.save();
text: subtitle?.search,
onPressed: () {
if (!(_formKey.currentState?.validate() ?? true)) return;
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
},
)
],
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context)),
ATextFormField(
initialValue: _search.deviceSerialNumber,
hintText: _subtitle.serialNumber,
style: Theme.of(context).textTheme.headline6,
hintText: subtitle?.serialNumber,
style: Theme.of(context).textTheme.titleLarge,
textInputAction: TextInputAction.search,
onAction: (){
if(!_formKey.currentState.validate())
return;
_formKey.currentState.save();
onAction: () {
if (!(_formKey.currentState?.validate() ?? true)) return;
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
},
onSaved: (value){
onSaved: (value) {
_search.deviceSerialNumber = value;
},
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
SizedBox(
height: 8.0 * AppStyle.getScaleFactor(context),
),
HospitalAutoCompleteField(
initialValue: _search.hospital,
onSave: (value){
initialValue: _search.hospital ?? '',
onSave: (value) {
_search.hospital = value;
},
onSearch: (value){
onSearch: (value) {
_search.hospital = value;
Navigator.of(context).pop(_search);
},
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
SizedBox(
height: 8.0 * AppStyle.getScaleFactor(context),
),
ATextFormField(
initialValue: _search.deviceName,
hintText: _subtitle.deviceName,
style: Theme.of(context).textTheme.headline6,
hintText: subtitle?.deviceName,
style: Theme.of(context).textTheme.titleLarge,
textInputAction: TextInputAction.search,
onAction: (){
if(!_formKey.currentState.validate())
return;
_formKey.currentState.save();
onAction: () {
if (!(_formKey.currentState?.validate() ?? true)) return;
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
},
onSaved: (value){
onSaved: (value) {
_search.deviceName = value;
},
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context)),
ATextFormField(
initialValue: _search.model,
hintText: _subtitle.model,
style: Theme.of(context).textTheme.headline6,
hintText: subtitle?.model,
style: Theme.of(context).textTheme.titleLarge,
textInputAction: TextInputAction.search,
onAction: (){
if(!_formKey.currentState.validate())
return;
_formKey.currentState.save();
onAction: () {
if (!(_formKey.currentState?.validate() ?? true)) return;
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
},
onSaved: (value){
onSaved: (value) {
_search.model = value;
},
),
SizedBox(height: 16 * AppStyle.getScaleFactor(context),),
SizedBox(
height: 16 * AppStyle.getScaleFactor(context),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Wrap(
spacing: 10,
runSpacing: 10,
alignment: WrapAlignment.spaceEvenly,
children: List.generate(
status.length,
(index) {
bool isSelected = _search.statusValue == status[index].id;
return FilterItem(
isSelected: isSelected,
onSelected: (){
if(isSelected)
_search.statusValue = null;
else
_search.statusValue = status[index].id;
setState(() {});
},
status: status[index],
);
}
),
children: List.generate(status.length, (index) {
bool isSelected = _search.statusValue == status[index].id;
return FilterItem(
isSelected: isSelected,
onSelected: () {
if (isSelected) {
_search.statusValue = null;
} else {
_search.statusValue = status[index].id;
}
setState(() {});
},
status: status[index],
);
}),
),
),
Visibility(
visible: widget.initialSearchValue.toSearchString().isNotEmpty,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16),
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 16,
),
child: AButton(
padding: EdgeInsets.zero,
text: _subtitle.clearSearch,
onPressed: (){
text: subtitle?.clearSearch ?? '',
onPressed: () {
_search = ServiceRequestSearch();
Navigator.of(context).pop(_search);
Navigator.of(context).pop(_search);
},
),
),

@ -1,233 +1,263 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/subtitle.dart';
import 'package:test_sa/models/visits/visits_search.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/buttons/app_button.dart';
import 'package:test_sa/views/widgets/buttons/app_small_button.dart';
import 'package:test_sa/views/widgets/date_and_time/from_to_date_bar.dart';
import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field.dart';
import 'package:test_sa/views/widgets/titles/app_sub_title.dart';
import '../../../controllers/localization/localization.dart';
import '../../../models/lookup.dart';
import '../../../models/subtitle.dart';
import '../../../models/visits/visits_search.dart';
import '../../app_style/sizing.dart';
import '../app_text_form_field.dart';
import '../buttons/app_button.dart';
import '../buttons/app_small_button.dart';
import '../date_and_time/from_to_date_bar.dart';
import '../hospitals/hospital_auto_complete_field.dart';
import '../titles/app_sub_title.dart';
import 'filter_item.dart';
class VisitsSearchDialog extends StatefulWidget {
final VisitsSearch initialSearchValue;
final bool expandedSearch;
final Function(VisitsSearch) onSearch;
const VisitsSearchDialog({
Key key,
this.initialSearchValue,
this.expandedSearch,
this.onSearch
Key? key,
required this.initialSearchValue,
required this.expandedSearch,
required this.onSearch,
}) : super(key: key);
@override
_VisitsSearchDialogState createState() => _VisitsSearchDialogState();
VisitsSearchDialogState createState() => VisitsSearchDialogState();
}
class _VisitsSearchDialogState extends State<VisitsSearchDialog>
with TickerProviderStateMixin{
VisitsSearch _search;
List<Lookup> status = [
Lookup(label: "Done", id: 0,),
class VisitsSearchDialogState extends State<VisitsSearchDialog>
with TickerProviderStateMixin {
VisitsSearch? _search;
List<Lookup> status = const [
Lookup(
label: "Done",
id: 0,
),
Lookup(label: "Not Yet", id: 1),
Lookup(label: "On Hold", id: 2,),
Lookup(
label: "On Hold",
id: 2,
),
];
List<Lookup> contactStatus = [
Lookup(label: "Hospital Employee", key: "H",),
List<Lookup> contactStatus = const [
Lookup(
label: "Hospital Employee",
key: "H",
),
Lookup(label: "Under Warranty", key: "CW"),
Lookup(label: "Under Maintenance Contract", key: "CC",),
Lookup(
label: "Under Maintenance Contract",
key: "CC",
),
];
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
void initState() {
super.initState();
_search = VisitsSearch();
_search.fromSearch(widget.initialSearchValue);
_search?.fromSearch(widget.initialSearchValue);
}
@override
Widget build(BuildContext context) {
Subtitle _subtitle = AppLocalization.of(context).subtitle;
Subtitle? subtitle = AppLocalization.of(context)?.subtitle;
DateTime today = DateTime.now();
return SizedBox(
return SizedBox(
height: MediaQuery.of(context).size.height / 1.3,
child: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16),
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ASmallButton(
text: _subtitle.cancel,
onPressed: (){
text: subtitle?.cancel,
onPressed: () {
Navigator.of(context).pop();
},
),
ASmallButton(
text: _subtitle.search,
onPressed: (){
if(!_formKey.currentState.validate())
text: subtitle?.search,
onPressed: () {
if (!(_formKey.currentState?.validate() ?? true)) {
return;
_formKey.currentState.save();
}
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
},
)
],
),
ATextFormField(
initialValue: _search.deviceSerialNumber,
hintText: _subtitle.serialNumber,
style: Theme.of(context).textTheme.headline6,
initialValue: _search?.deviceSerialNumber,
hintText: subtitle?.serialNumber,
style: Theme.of(context).textTheme.titleLarge,
textInputAction: TextInputAction.search,
onAction: (){
if(!_formKey.currentState.validate())
return;
_formKey.currentState.save();
onAction: () {
if (!(_formKey.currentState?.validate() ?? true)) return;
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
},
onSaved: (value){
_search.deviceSerialNumber = value;
onSaved: (value) {
_search?.deviceSerialNumber = value ?? '';
},
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context)),
HospitalAutoCompleteField(
initialValue: _search.hospitalName,
onSave: (value){
_search.hospitalName = value;
initialValue: _search?.hospitalName ?? '',
onSave: (value) {
_search?.hospitalName = value;
},
onSearch: (value){
_search.hospitalName = value;
onSearch: (value) {
_search?.hospitalName = value;
Navigator.of(context).pop(_search);
},
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
SizedBox(
height: 8.0 * AppStyle.getScaleFactor(context),
),
ATextFormField(
initialValue: _search.brand,
hintText: _subtitle.brand,
style: Theme.of(context).textTheme.headline6,
initialValue: _search?.brand,
hintText: subtitle?.brand,
style: Theme.of(context).textTheme.titleLarge,
textInputAction: TextInputAction.search,
onAction: (){
if(!_formKey.currentState.validate())
return;
_formKey.currentState.save();
onAction: () {
if (!(_formKey.currentState?.validate() ?? false)) return;
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
},
onSaved: (value){
_search.brand = value;
onSaved: (value) {
_search?.brand = value ?? '';
},
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
SizedBox(
height: 8.0 * AppStyle.getScaleFactor(context),
),
ATextFormField(
initialValue: _search.model,
hintText: _subtitle.model,
style: Theme.of(context).textTheme.headline6,
initialValue: _search?.model,
hintText: subtitle?.model,
style: Theme.of(context).textTheme.titleLarge,
textInputAction: TextInputAction.search,
onAction: (){
if(!_formKey.currentState.validate())
return;
_formKey.currentState.save();
onAction: () {
if (!(_formKey.currentState?.validate() ?? true)) return;
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
},
onSaved: (value){
_search.model = value;
onSaved: (value) {
_search?.model = value ?? '';
},
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
ASubTitle(_subtitle.status),
SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),),
SizedBox(
height: 8.0 * AppStyle.getScaleFactor(context),
),
ASubTitle(subtitle?.status ?? ''),
SizedBox(
height: 4.0 * AppStyle.getScaleFactor(context),
),
Wrap(
spacing: 10,
runSpacing: 10,
children: List.generate(
status.length,
(index) {
bool isSelected = _search.statusValue == status[index].id;
return FilterItem(
isSelected: isSelected,
onSelected: (){
if(isSelected)
_search.statusValue = null;
else
_search.statusValue = status[index].id;
setState(() {});
},
status: status[index],
);
}
),
children: List.generate(status.length, (index) {
bool isSelected = _search?.statusValue == status[index].id;
return FilterItem(
isSelected: isSelected,
onSelected: () {
if (isSelected) {
_search?.statusValue = null;
} else {
_search?.statusValue = status[index].id;
}
setState(() {});
},
status: status[index],
);
}),
),
SizedBox(
height: 8.0 * AppStyle.getScaleFactor(context),
),
ASubTitle(subtitle?.contactStatus ?? ''),
SizedBox(
height: 4.0 * AppStyle.getScaleFactor(context),
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
ASubTitle(_subtitle.contactStatus),
SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),),
Wrap(
spacing: 10,
runSpacing: 10,
children: List.generate(
contactStatus.length,
(index) {
bool isSelected = _search.contactStatus == contactStatus[index].key;
return FilterItem(
isSelected: isSelected,
onSelected: (){
if(isSelected)
_search.contactStatus = null;
else
_search.contactStatus = contactStatus[index].key;
setState(() {});
},
status: contactStatus[index],
);
}
contactStatus.length,
(index) {
bool isSelected =
_search?.contactStatus == contactStatus[index].key;
return FilterItem(
isSelected: isSelected,
onSelected: () {
if (isSelected) {
_search?.contactStatus = null;
} else {
_search?.contactStatus = contactStatus[index].key;
}
setState(() {});
},
status: contactStatus[index],
);
},
),
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
ASubTitle(_subtitle.actualDate),
SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),),
SizedBox(
height: 8.0 * AppStyle.getScaleFactor(context),
),
ASubTitle(subtitle?.actualDate ?? ''),
SizedBox(
height: 4.0 * AppStyle.getScaleFactor(context),
),
FromToDateBar(
from: _search.actualDateFrom ,
to: _search.actualDateTo,
onPickFrom: (date){
_search.actualDateFrom = date;
from: _search?.actualDateFrom,
to: _search?.actualDateTo,
onPickFrom: (date) {
_search?.actualDateFrom = date;
},
onPickTo: (date){
_search.actualDateTo = date;
onPickTo: (date) {
_search?.actualDateTo = date;
},
),
SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),),
ASubTitle(_subtitle.expectDate),
SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),),
SizedBox(
height: 8.0 * AppStyle.getScaleFactor(context),
),
ASubTitle(subtitle?.expectDate ?? ''),
SizedBox(
height: 4.0 * AppStyle.getScaleFactor(context),
),
FromToDateBar(
from: _search.expectedDateFrom ?? DateTime(today.year, today.month, 1),
to: _search.expectedDateTo ?? DateTime(today.year, (today.month +1).clamp(1, 12) , today.month == 12 ? 31 : 0),
onPickFrom: (date){
_search.expectedDateFrom = date;
from: _search?.expectedDateFrom ??
DateTime(today.year, today.month, 1),
to: _search?.expectedDateTo ??
DateTime(today.year, (today.month + 1).clamp(1, 12),
today.month == 12 ? 31 : 0),
onPickFrom: (date) {
_search?.expectedDateFrom = date;
},
onPickTo: (date){
_search.expectedDateTo = date;
onPickTo: (date) {
_search?.expectedDateTo = date;
},
),
Visibility(
visible: _search.toSearchString().isNotEmpty,
visible: _search?.toSearchString().isNotEmpty ?? false,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16),
padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: AButton(
padding: EdgeInsets.zero,
text: _subtitle.clearSearch,
onPressed: (){
text: subtitle?.clearSearch ?? '',
onPressed: () {
_search = VisitsSearch();
Navigator.of(context).pop(_search);
},

@ -3,28 +3,30 @@ import 'package:flutter/services.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:rive/rive.dart';
import 'package:test_sa/views/widgets/buttons/app_icon_button2.dart';
import 'package:test_sa/views/widgets/buttons/app_small_button.dart';
import 'package:test_sa/views/widgets/sound/sound_player.dart';
import '../../app_style/sizing.dart';
import '../buttons/app_icon_button2.dart';
import '../buttons/app_small_button.dart';
import 'sound_player.dart';
class RecordSound extends StatefulWidget {
final Function(String) onRecord;
final Function(String?) onRecord;
const RecordSound({Key key, @required this.onRecord}) : super(key: key);
const RecordSound({
Key? key,
required this.onRecord,
}) : super(key: key);
@override
State<RecordSound> createState() => _RecordSoundState();
}
class _RecordSoundState extends State<RecordSound> {
FlutterSoundRecorder _myRecorder = FlutterSoundRecorder();
FlutterSoundRecorder? _myRecorder = FlutterSoundRecorder();
bool _recorderIsOpened = false;
bool _recording = false;
bool _fastTab = false;
String _record;
Artboard _rive;
String? _record;
late Artboard _rive;
@override
void setState(VoidCallback fn) {
@ -34,7 +36,7 @@ class _RecordSoundState extends State<RecordSound> {
@override
void initState() {
super.initState();
_myRecorder.openRecorder().then((value) {
_myRecorder?.openRecorder().then((value) {
_recorderIsOpened = true;
setState(() {});
});
@ -61,7 +63,7 @@ class _RecordSoundState extends State<RecordSound> {
@override
void dispose() {
// Be careful : you must `close` the audio session when you have finished with it.
_myRecorder.closeRecorder();
_myRecorder?.closeRecorder();
_myRecorder = null;
super.dispose();
}
@ -75,11 +77,15 @@ class _RecordSoundState extends State<RecordSound> {
}
_rive.addController(SimpleAnimation('recording'));
if (!_recorderIsOpened) {
await _myRecorder.openRecorder();
await _myRecorder?.openRecorder();
_recorderIsOpened = true;
}
await _myRecorder.startRecorder(toFile: "record_${DateTime.now().millisecondsSinceEpoch}.mp4", codec: Codec.aacMP4, sampleRate: 360000, bitRate: 360000);
await _myRecorder?.startRecorder(
toFile: "record_${DateTime.now().millisecondsSinceEpoch}.mp4",
codec: Codec.aacMP4,
sampleRate: 360000,
bitRate: 360000);
_recording = true;
setState(() {});
@ -91,7 +97,7 @@ class _RecordSoundState extends State<RecordSound> {
setState(() {});
return;
}
String path = (await _myRecorder.stopRecorder()).toString();
String path = (await _myRecorder?.stopRecorder()).toString();
_record = path;
widget.onRecord(path);
_recording = false;
@ -100,8 +106,8 @@ class _RecordSoundState extends State<RecordSound> {
_cancelRecording() async {
if (!_recording) return;
String path = await _myRecorder.stopRecorder();
_myRecorder.deleteRecord(fileName: path);
final path = await _myRecorder?.stopRecorder();
_myRecorder?.deleteRecord(fileName: path ?? '');
_rive.addController(SimpleAnimation('delete'));
// rebuild();
@ -114,13 +120,14 @@ class _RecordSoundState extends State<RecordSound> {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(left: 12, right: 0),
padding: const EdgeInsets.only(left: 12, right: 0),
decoration: BoxDecoration(
color: Color(0xfff5f5f5),
color: const Color(0xfff5f5f5),
border: Border.all(
color: Color(0xffefefef),
color: const Color(0xffefefef),
),
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
borderRadius: BorderRadius.circular(
AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
),
child: Column(
children: [
@ -140,13 +147,15 @@ class _RecordSoundState extends State<RecordSound> {
child: Stack(
children: [
SizedBox(
height: 24 * AppStyle.getScaleFactor(context),
height:
24 * AppStyle.getScaleFactor(context),
child: Rive(
artboard: _rive,
)),
InkWell(
child: SizedBox(
height: 32 * AppStyle.getScaleFactor(context),
height:
32 * AppStyle.getScaleFactor(context),
width: MediaQuery.of(context).size.width,
),
onTap: () {

@ -1,115 +1,106 @@
import 'dart:typed_data';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../../app_style/colors.dart';
import '../../app_style/sizing.dart';
class ASoundPlayer extends StatefulWidget {
final String? audio;
final String audio;
const ASoundPlayer({Key key, this.audio}) : super(key: key);
const ASoundPlayer({Key? key, this.audio}) : super(key: key);
@override
_ASoundPlayerState createState() => _ASoundPlayerState();
ASoundPlayerState createState() => ASoundPlayerState();
}
class _ASoundPlayerState extends State<ASoundPlayer> {
class ASoundPlayerState extends State<ASoundPlayer> {
//FlutterSoundPlayer _myPlayer = FlutterSoundPlayer();
bool _sliderMoving = false;
Duration _audioTime;
Duration _audioPosition;
String _audio;
Duration? _audioTime;
Duration? _audioPosition;
String? _audio;
bool _isLocalFile = false;
bool _failedToLoad = false;
AudioPlayer _audioPlayer;
AudioPlayer? _audioPlayer;
Widget _getAudioButton(){
switch(_audioPlayer.state){
Widget _getAudioButton() {
switch (_audioPlayer?.state) {
case PlayerState.playing:
return IconButton(
icon: const Icon(Icons.pause_rounded),
onPressed: () async {
_failedToLoad = false;
await _audioPlayer.pause();
await _audioPlayer?.pause();
rebuild();
}
);
});
case PlayerState.paused:
return IconButton(
return IconButton(
icon: const Icon(Icons.play_arrow_rounded),
onPressed: () async {
_failedToLoad = false;
await _audioPlayer.resume();
await _audioPlayer?.resume();
rebuild();
}
);
});
case PlayerState.completed:
return IconButton(
return IconButton(
icon: const Icon(Icons.replay_rounded),
onPressed: () async {
_failedToLoad = false;
await _audioPlayer.stop();
await _audioPlayer.resume();
await _audioPlayer?.stop();
await _audioPlayer?.resume();
rebuild();
}
);
});
case PlayerState.stopped:
return IconButton(
icon: Icon( _isLocalFile
icon: Icon(_isLocalFile
? Icons.play_circle_fill_outlined
: Icons.download_rounded
),
: Icons.download_rounded),
onPressed: () async {
_failedToLoad = false;
try {
await _audioPlayer.play(
_isLocalFile?
DeviceFileSource(_audio):UrlSource(_audio),
await _audioPlayer?.play(
_isLocalFile
? DeviceFileSource(_audio ?? '')
: UrlSource(_audio ?? ''),
);
rebuild();
} on Exception catch (e) {
_failedToLoad = true;
}
}
);
default: return IconButton(
icon: const Icon( Icons.replay_rounded),
onPressed: () async {
_failedToLoad = false;
try {
_audioPlayer.seek(const Duration(milliseconds: 0));
_audioPlayer.stop();
await _audioPlayer.play(
_isLocalFile?
DeviceFileSource(_audio):UrlSource(_audio),
);
rebuild();
} on Exception catch (e) {
_failedToLoad = true;
}
}
);
});
default:
return IconButton(
icon: const Icon(Icons.replay_rounded),
onPressed: () async {
_failedToLoad = false;
try {
_audioPlayer?.seek(const Duration(milliseconds: 0));
_audioPlayer?.stop();
await _audioPlayer?.play(
_isLocalFile
? DeviceFileSource(_audio ?? '')
: UrlSource(_audio ?? ''),
);
rebuild();
} on Exception catch (e) {
_failedToLoad = true;
}
});
}
}
String format(Duration d) {
if(d == null)
return "00:00";
String format(Duration? d) {
if (d == null) return "00:00";
return d.toString().substring(2, 7);
}
rebuild(){
rebuild() {
if (!mounted) return;
setState(() {});
}
bool _isLocalUrl(String url) {
if(url?.isEmpty != false) return false;
if (url.isEmpty != false) return false;
return url.startsWith("/") ||
url.startsWith("file://") ||
url.substring(1).startsWith(':\\');
@ -119,32 +110,34 @@ class _ASoundPlayerState extends State<ASoundPlayer> {
void initState() {
super.initState();
_audioPlayer = AudioPlayer();
_audioPlayer.release();
_audioPlayer?.release();
_audio = widget.audio;
_isLocalFile = _isLocalUrl(_audio);
_audioPlayer.setReleaseMode(ReleaseMode.stop);
if(_isLocalFile){
_audioPlayer.setSourceDeviceFile(_audio).then((value) {rebuild();});
} else{
_audioPlayer.setReleaseMode(ReleaseMode.stop);
_isLocalFile = _isLocalUrl(_audio ?? '');
_audioPlayer?.setReleaseMode(ReleaseMode.stop);
if (_isLocalFile) {
_audioPlayer?.setSourceDeviceFile(_audio ?? '').then((value) {
rebuild();
});
} else {
_audioPlayer?.setReleaseMode(ReleaseMode.stop);
}
// set up listeners
_audioPlayer.onPositionChanged.listen((Duration duration) {
if(!_sliderMoving){
_audioPlayer?.onPositionChanged.listen((Duration duration) {
if (!_sliderMoving) {
_audioPosition = duration;
rebuild();
}
//setState(() => position = p);
});
_audioPlayer.onPlayerStateChanged.listen((event) {
_audioPlayer?.onPlayerStateChanged.listen((event) {
//_audioPosition = _audioTime;
rebuild();
});
_audioPlayer.onDurationChanged.listen((Duration duration) {
_audioPlayer?.onDurationChanged.listen((Duration duration) {
_audioTime = duration;
rebuild();
});
_audioPlayer.onSeekComplete.listen((event) {
_audioPlayer?.onSeekComplete.listen((event) {
rebuild();
});
}
@ -152,55 +145,49 @@ class _ASoundPlayerState extends State<ASoundPlayer> {
@override
void dispose() {
super.dispose();
// _myPlayer.closeAudioSession();
_audioPlayer.release();
_audioPlayer.dispose();
// _myPlayer.closeAudioSession();
_audioPlayer?.release();
_audioPlayer?.dispose();
}
@override
Widget build(BuildContext context) {
if(_audio != widget.audio){
if (_audio != widget.audio) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
_audio = widget.audio;
if(_isLocalFile){
await _audioPlayer.setSourceDeviceFile(_audio);
}else{
await _audioPlayer.setSourceUrl(_audio);
if (_isLocalFile) {
await _audioPlayer?.setSourceDeviceFile(_audio ?? '');
} else {
await _audioPlayer?.setSourceUrl(_audio ?? '');
}
_audioPlayer.seek(const Duration(milliseconds: 0));
_audioPlayer.stop();
_audioPlayer?.seek(const Duration(milliseconds: 0));
_audioPlayer?.stop();
rebuild();
});
}
return Column(
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
children: [
Material(
color: Colors.transparent,
child: _getAudioButton()
),
Material(color: Colors.transparent, child: _getAudioButton()),
Expanded(
child: Slider(
value: _audioPosition?.inMilliseconds?.toDouble() ?? 0.0,
min: 0,
max: _audioTime?.inMilliseconds?.toDouble() ?? 60.0,
onChangeStart: (value){
_sliderMoving = true;
},
onChanged: (value){
_audioPosition = Duration(milliseconds: value.round());
rebuild();
},
onChangeEnd: (value){
_sliderMoving = false;
_audioPlayer.seek(Duration(milliseconds: value.round()));
rebuild();
}
),
value: _audioPosition?.inMilliseconds.toDouble() ?? 0.0,
min: 0,
max: _audioTime?.inMilliseconds.toDouble() ?? 60.0,
onChangeStart: (value) {
_sliderMoving = true;
},
onChanged: (value) {
_audioPosition = Duration(milliseconds: value.round());
rebuild();
},
onChangeEnd: (value) {
_sliderMoving = false;
_audioPlayer?.seek(Duration(milliseconds: value.round()));
rebuild();
}),
),
],
),
@ -213,21 +200,21 @@ class _ASoundPlayerState extends State<ASoundPlayer> {
children: [
Text(
"Failed to load",
style: Theme.of(context).textTheme.overline.copyWith(
color: AColors.red
),
style: Theme.of(context)
.textTheme
.labelSmall
?.copyWith(color: AColors.red),
textScaleFactor: AppStyle.getScaleFactor(context),
),
],
),
),
),
Visibility(
visible: _audioPlayer.state != PlayerState.stopped,
visible: _audioPlayer?.state != PlayerState.stopped,
child: Text(
"${format(_audioPosition)}/${format(_audioTime)}",
style: Theme.of(context).textTheme.overline,
style: Theme.of(context).textTheme.labelSmall,
textScaleFactor: AppStyle.getScaleFactor(context),
),
),

@ -4,25 +4,27 @@ import 'package:provider/provider.dart';
import 'package:speech_to_text/speech_recognition_error.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/buttons/app_icon_button2.dart';
import 'package:test_sa/views/widgets/titles/app_sub_title.dart';
import '../../../controllers/providers/settings/setting_provider.dart';
import '../../app_style/sizing.dart';
import '../buttons/app_icon_button2.dart';
import '../titles/app_sub_title.dart';
class SpeechToTextButton extends StatefulWidget {
final TextEditingController controller;
final TextEditingController? controller;
final bool mini;
const SpeechToTextButton({Key key, this.controller, this.mini = false}) : super(key: key);
const SpeechToTextButton({Key? key, this.controller, this.mini = false})
: super(key: key);
@override
_SpeechToTextButtonState createState() => _SpeechToTextButtonState();
SpeechToTextButtonState createState() => SpeechToTextButtonState();
}
class _SpeechToTextButtonState extends State<SpeechToTextButton> {
class SpeechToTextButtonState extends State<SpeechToTextButton> {
bool _speechEnabled = false;
SettingProvider _settingProvider;
SpeechToText _speechToText = SpeechToText();
SettingProvider? _settingProvider;
final SpeechToText _speechToText = SpeechToText();
/// This has to happen only once per app
void _initSpeech() async {
@ -44,10 +46,10 @@ class _SpeechToTextButtonState extends State<SpeechToTextButton> {
if (!_speechEnabled) return;
await _speechToText.listen(
onResult: (SpeechRecognitionResult result) {
widget.controller.text = result.recognizedWords;
widget.controller?.text = result.recognizedWords;
setState(() {});
},
localeId: _settingProvider.speechToText);
localeId: _settingProvider?.speechToText);
setState(() {});
}
@ -68,7 +70,7 @@ class _SpeechToTextButtonState extends State<SpeechToTextButton> {
@override
void setState(VoidCallback fn) {
if (!this.mounted) return;
if (!mounted) return;
super.setState(fn);
}
@ -76,41 +78,43 @@ class _SpeechToTextButtonState extends State<SpeechToTextButton> {
Widget build(BuildContext context) {
_settingProvider = Provider.of<SettingProvider>(context);
return Container(
padding: EdgeInsets.only(left: 12, right: 12),
padding: const EdgeInsets.only(left: 12, right: 12),
decoration: BoxDecoration(
color: Color(0xfff5f5f5),
color: const Color(0xfff5f5f5),
border: Border.all(
color: Color(0xffefefef),
color: const Color(0xffefefef),
),
borderRadius: BorderRadius.circular(
AppStyle.borderRadius * AppStyle.getScaleFactor(context),
),
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
),
child: Row(
children: [
widget.mini ? SizedBox.shrink() : ASubTitle("Text To Speech"),
widget.controller.text.isNotEmpty
widget.mini ? const SizedBox.shrink() : ASubTitle("Text To Speech"),
widget.controller?.text.isNotEmpty ?? false
? AIconButton2(
iconData: Icons.delete,
onPressed: () {
widget.controller.clear();
widget.controller?.clear();
setState(() {});
},
)
: SizedBox.shrink(),
Spacer(),
: const SizedBox.shrink(),
const Spacer(),
TextButton(
onPressed: () {
if (_speechToText.isListening) return;
if (_settingProvider.speechToText == "ar") {
_settingProvider.setSpeechToText("en");
if (_settingProvider?.speechToText == "ar") {
_settingProvider?.setSpeechToText("en");
} else {
_settingProvider.setSpeechToText("ar");
_settingProvider?.setSpeechToText("ar");
}
},
child: Text(_settingProvider.speechToText)),
child: Text(_settingProvider?.speechToText ?? '')),
GestureDetector(
child: _speechToText.isListening
? Icon(
? const Icon(
Icons.fiber_manual_record,
color: Colors.red,
)

@ -1,37 +1,44 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/employee/employee_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/employee/employee_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class EmployeeMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final Lookup initialValue;
final Function(Lookup?) onSelect;
final Lookup? initialValue;
const EmployeeMenu({
Key? key,
required this.onSelect,
required this.initialValue,
}) : super(key: key);
const EmployeeMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
final settingProvider = Provider.of<SettingProvider>(context);
final userProvider = Provider.of<UserProvider>(context);
final menuProvider = Provider.of<EmployeesProvider>(context);
return LoadingManager(
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
)
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host,
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
),
);
}
}

@ -1,37 +1,44 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_size_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_size_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class GasCylinderSizeMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final Lookup initialValue;
final Function(Lookup?)? onSelect;
final Lookup? initialValue;
const GasCylinderSizeMenu({
Key? key,
this.onSelect,
this.initialValue,
}) : super(key: key);
const GasCylinderSizeMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
final settingProvider = Provider.of<SettingProvider>(context);
final userProvider = Provider.of<UserProvider>(context);
final menuProvider = Provider.of<GasCylinderSizesProvider>(context);
return LoadingManager(
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
)
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host,
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
),
);
}
}

@ -1,16 +1,20 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/gas_refill/gas_status_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/gas_refill/gas_status_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class GasStatusMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final Lookup initialValue;
final Function(Lookup?)? onSelect;
final Lookup? initialValue;
const GasStatusMenu({Key? key, this.onSelect, this.initialValue})
: super(key: key);
const GasStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
final settingProvider = Provider.of<SettingProvider>(context);
@ -23,15 +27,12 @@ class GasStatusMenu extends StatelessWidget {
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host
);
user: userProvider.user, host: settingProvider.host);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
)
);
));
}
}

@ -1,37 +1,42 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/gas_refill/gas_types_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/gas_refill/gas_types_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class GasTypeMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final Lookup initialValue;
final Function(Lookup?)? onSelect;
final Lookup? initialValue;
const GasTypeMenu({
Key? key,
this.onSelect,
this.initialValue,
}) : super(key: key);
const GasTypeMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
final settingProvider = Provider.of<SettingProvider>(context);
final userProvider = Provider.of<UserProvider>(context);
final menuProvider = Provider.of<GasTypesProvider>(context);
return LoadingManager(
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
)
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user, host: settingProvider.host);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
),
);
}
}

@ -1,23 +1,29 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../../../models/lookup.dart';
import '../../app_style/colors.dart';
import '../../app_style/sizing.dart';
class MultiStatusMenu extends StatefulWidget {
final List<Lookup> statuses;
final List<Lookup> initialSelectedStatus;
final Function(List<Lookup>) onSelect;
const MultiStatusMenu({Key key, this.statuses, this.onSelect, this.initialSelectedStatus}) : super(key: key);
const MultiStatusMenu({
Key? key,
required this.statuses,
required this.onSelect,
required this.initialSelectedStatus,
}) : super(key: key);
@override
_MultiStatusMenuState createState() => _MultiStatusMenuState();
MultiStatusMenuState createState() => MultiStatusMenuState();
}
class _MultiStatusMenuState extends State<MultiStatusMenu> {
List<Lookup> _selectedStatus = [];
TextEditingController _controller;
class MultiStatusMenuState extends State<MultiStatusMenu> {
final List<Lookup> _selectedStatus = [];
late TextEditingController _controller;
@override
void initState() {
@ -31,101 +37,90 @@ class _MultiStatusMenuState extends State<MultiStatusMenu> {
_controller.clear();
super.dispose();
}
@override
Widget build(BuildContext context) {
return
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Wrap(
crossAxisAlignment: WrapCrossAlignment.start,
alignment: WrapAlignment.start,
runAlignment: WrapAlignment.start,
children: List.generate(
_selectedStatus.length,
(index) {
final status = _selectedStatus[index];
return Container(
height: 36 * AppStyle.getScaleFactor(context),
margin: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)),
//padding: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)),
decoration: BoxDecoration(
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Wrap(
crossAxisAlignment: WrapCrossAlignment.start,
alignment: WrapAlignment.start,
runAlignment: WrapAlignment.start,
children: List.generate(_selectedStatus.length, (index) {
final status = _selectedStatus[index];
return Container(
height: (36 * AppStyle.getScaleFactor(context)).toDouble(),
margin: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)),
//padding: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primary,
borderRadius: BorderRadius.circular(8)
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(width: 12,),
Text(
status.label,
style: Theme.of(context).textTheme.bodyText1.copyWith(
color:Theme.of(context).colorScheme.onPrimary,
borderRadius: BorderRadius.circular(8)),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(
width: 12,
),
Text(
status.label ?? '',
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
),
),
IconButton(
color:Theme.of(context).colorScheme.onPrimary,
onPressed: (){
_selectedStatus.remove(status);
widget.onSelect(_selectedStatus);
setState(() {});
},
icon: const Icon(Icons.delete)
)
],
)
);
}
),
),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 16
),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color:AColors.black),
borderRadius: BorderRadius.circular(
AppStyle.borderRadius * AppStyle.getScaleFactor(context)
),
boxShadow: const [
AppStyle.boxShadow
]
),
child: TypeAheadField<Lookup>(
textFieldConfiguration: TextFieldConfiguration(
style: Theme.of(context).textTheme.subtitle1,
controller: _controller,
textAlign: TextAlign.center,
decoration: const InputDecoration(
border: InputBorder.none,
disabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
),
textInputAction: TextInputAction.search,
),
IconButton(
color: Theme.of(context).colorScheme.onPrimary,
onPressed: () {
_selectedStatus.remove(status);
widget.onSelect(_selectedStatus);
setState(() {});
},
icon: const Icon(Icons.delete))
],
));
}),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: AColors.black),
borderRadius: BorderRadius.circular(
AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
boxShadow: const [AppStyle.boxShadow]),
child: TypeAheadField<Lookup>(
textFieldConfiguration: TextFieldConfiguration(
style: Theme.of(context).textTheme.titleMedium,
controller: _controller,
textAlign: TextAlign.center,
decoration: const InputDecoration(
border: InputBorder.none,
disabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
),
suggestionsCallback: (vale) {
return widget.statuses.where((Lookup option) {
return option.label.toLowerCase().contains(_controller.text);
});
},
itemBuilder: (context, part) {
return ListTile(
title: Text(part.label),
);
},
onSuggestionSelected: (status) {
_controller.clear();
if(!_selectedStatus.contains(status)){
_selectedStatus.add(status);
widget.onSelect(_selectedStatus);
setState(() {});
}
},
textInputAction: TextInputAction.search,
),
suggestionsCallback: (vale) {
return widget.statuses.where((Lookup option) {
return option.label?.toLowerCase().contains(_controller.text) ??
false;
});
},
itemBuilder: (context, part) {
return ListTile(title: Text(part.label ?? ''));
},
onSuggestionSelected: (status) {
_controller.clear();
if (!_selectedStatus.contains(status)) {
_selectedStatus.add(status);
widget.onSelect(_selectedStatus);
setState(() {});
}
},
),
],
);
),
],
);
}
}

@ -1,37 +1,40 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/pentry/pentry_status_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/pentry/pentry_status_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class PentryStatusMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final Lookup initialValue;
final Function(Lookup?)? onSelect;
final Lookup? initialValue;
const PentryStatusMenu({Key? key, this.onSelect, this.initialValue})
: super(key: key);
const PentryStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
final settingProvider = Provider.of<SettingProvider>(context);
final userProvider = Provider.of<UserProvider>(context);
final menuProvider = Provider.of<PentryStatusProvider>(context);
return LoadingManager(
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
)
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host,
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
),
);
}
}

@ -1,37 +1,44 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/pentry/pentry_task_status_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/pentry/pentry_task_status_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class PentryTaskStatusMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final Lookup initialValue;
final Function(Lookup?)? onSelect;
final Lookup? initialValue;
const PentryTaskStatusMenu({
Key? key,
this.onSelect,
this.initialValue,
}) : super(key: key);
const PentryTaskStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
final settingProvider = Provider.of<SettingProvider>(context);
final userProvider = Provider.of<UserProvider>(context);
final menuProvider = Provider.of<PentryTaskStatusProvider>(context);
return LoadingManager(
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
)
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host,
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
),
);
}
}

@ -1,37 +1,44 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/pentry/pentry_visit_status_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/pentry/pentry_visit_status_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class PentryVisitsStatusMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final Lookup initialValue;
final Function(Lookup?)? onSelect;
final Lookup? initialValue;
const PentryVisitsStatusMenu({
Key? key,
this.onSelect,
this.initialValue,
}) : super(key: key);
const PentryVisitsStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
final settingProvider = Provider.of<SettingProvider>(context);
final userProvider = Provider.of<UserProvider>(context);
final menuProvider = Provider.of<PentryVisitStatusProvider>(context);
return LoadingManager(
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
)
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host,
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
),
);
}
}

@ -1,29 +1,36 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_report.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../models/lookup.dart';
import '../../../../models/service_report.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class ServiceReportLastCallsMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final ServiceReport report;
final Function(Lookup?)? onSelect;
final ServiceReport? report;
const ServiceReportLastCallsMenu({
Key key,@required this.onSelect,@required this.report}) : super(key: key);
Key? key,
required this.onSelect,
required this.report,
}) : super(key: key);
@override
Widget build(BuildContext context) {
ServiceReportLastCallsProvider _menuProvider = Provider.of<ServiceReportLastCallsProvider>(context);
ServiceReportLastCallsProvider menuProvider =
Provider.of<ServiceReportLastCallsProvider>(context);
return LoadingManager(
isLoading: _menuProvider.isLoading,
isFailedLoading: _menuProvider.calls == null,
stateCode: _menuProvider.stateCode,
onRefresh: () async {},
child: SingleStatusMenu(
initialStatus: report?.callLastSituation,
statuses: _menuProvider.calls,
onSelect: onSelect,
)
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.calls == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {},
child: SingleStatusMenu(
initialStatus: report?.callLastSituation,
statuses: menuProvider.calls,
onSelect: onSelect,
),
);
}
}

@ -1,38 +1,44 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_reasons_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/report/service_report_reasons_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class ServiceReportReasonsMenu extends StatelessWidget {
final Lookup initialValue;
final Function(Lookup) onSelect;
final Lookup? initialValue;
final Function(Lookup?)? onSelect;
const ServiceReportReasonsMenu({
Key? key,
this.onSelect,
this.initialValue,
}) : super(key: key);
const ServiceReportReasonsMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
SettingProvider _settingProvider = Provider.of<SettingProvider>(context);
UserProvider _userProvider = Provider.of<UserProvider>(context);
ServiceReportReasonsProvider _menuProvider = Provider.of<ServiceReportReasonsProvider>(context);
SettingProvider settingProvider = Provider.of<SettingProvider>(context);
UserProvider userProvider = Provider.of<UserProvider>(context);
ServiceReportReasonsProvider menuProvider =
Provider.of<ServiceReportReasonsProvider>(context);
return LoadingManager(
isLoading: _menuProvider.isLoading,
isFailedLoading: _menuProvider.reasons == null,
stateCode: _menuProvider.stateCode,
onRefresh: () async {
_menuProvider.reset();
await _menuProvider.getTypes(
user: _userProvider.user,
host: _settingProvider.host,
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: _menuProvider.reasons,
onSelect: onSelect,
)
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.reasons == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getTypes(
user: userProvider.user,
host: settingProvider.host,
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.reasons,
onSelect: onSelect,
),
);
}
}

@ -2,69 +2,81 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_status_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_report.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.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_status_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../../../models/service_report.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class ServiceReportStatusMenu extends StatefulWidget {
final Function(Lookup) onSelect;
final ServiceReport report;
final Function(Lookup?) onSelect;
final ServiceReport? report;
const ServiceReportStatusMenu({Key key, this.onSelect, this.report}) : super(key: key);
const ServiceReportStatusMenu({
Key? key,
required this.onSelect,
this.report,
}) : super(key: key);
@override
State<ServiceReportStatusMenu> createState() => _ServiceReportStatusMenuState();
State<ServiceReportStatusMenu> createState() =>
_ServiceReportStatusMenuState();
}
class _ServiceReportStatusMenuState extends State<ServiceReportStatusMenu> {
bool firstTime = true;
@override
Widget build(BuildContext context) {
SettingProvider _settingProvider = Provider.of<SettingProvider>(context);
UserProvider _userProvider = Provider.of<UserProvider>(context);
ServiceReportStatusProvider _menuProvider = Provider.of<ServiceReportStatusProvider>(context);
ServiceReportLastCallsProvider _callsLastSituationsProvider = Provider.of<ServiceReportLastCallsProvider>(context,listen: false);
if(firstTime){
_callsLastSituationsProvider.reset();
SettingProvider settingProvider = Provider.of<SettingProvider>(context);
UserProvider userProvider = Provider.of<UserProvider>(context);
ServiceReportStatusProvider menuProvider =
Provider.of<ServiceReportStatusProvider>(context);
ServiceReportLastCallsProvider callsLastSituationsProvider =
Provider.of<ServiceReportLastCallsProvider>(context, listen: false);
if (firstTime) {
callsLastSituationsProvider.reset();
firstTime = false;
}
return LoadingManager(
isLoading: _menuProvider.isLoading == true || _callsLastSituationsProvider.isLoading == true,
isFailedLoading: _menuProvider.statuses == null || _callsLastSituationsProvider.calls == null,
stateCode: _menuProvider.stateCode == null || _callsLastSituationsProvider.stateCode == null ? null:
max(_menuProvider.stateCode ?? 0,_callsLastSituationsProvider.stateCode ?? 0),
isLoading: menuProvider.isLoading == true ||
callsLastSituationsProvider.isLoading == true,
isFailedLoading: menuProvider.statuses == null ||
callsLastSituationsProvider.calls == null,
stateCode: menuProvider.stateCode == null ||
callsLastSituationsProvider.stateCode == null
? null
: max(menuProvider.stateCode ?? 0,
callsLastSituationsProvider.stateCode ?? 0),
onRefresh: () async {
if(_menuProvider.stateCode == null){
_menuProvider.reset();
await _menuProvider.getTypes(
user: _userProvider.user,
host: _settingProvider.host
if (menuProvider.stateCode == null) {
menuProvider.reset();
await menuProvider.getTypes(
user: userProvider.user,
host: settingProvider.host,
);
}
await _callsLastSituationsProvider.getCalls(
user: _userProvider.user,
host: _settingProvider.host,
serviceStatus: widget.report.status?.id.toString()
);
await callsLastSituationsProvider.getCalls(
user: userProvider.user,
host: settingProvider.host,
serviceStatus: widget.report?.status?.id.toString());
},
child: SingleStatusMenu(
statuses: _menuProvider.statuses,
initialStatus: widget.report.status,
onSelect: (status){
_callsLastSituationsProvider.getCalls(
user: _userProvider.user,
host: _settingProvider.host,
serviceStatus: status.id.toString()
);
widget.report.callLastSituation = null;
statuses: menuProvider.statuses,
initialStatus: widget.report?.status,
onSelect: (status) {
callsLastSituationsProvider.getCalls(
user: userProvider.user,
host: settingProvider.host,
serviceStatus: status?.id.toString());
widget.report?.callLastSituation = null;
widget.onSelect(status);
},
)
);
));
}
}

@ -1,21 +1,29 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_types_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/report/service_report_types_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class ServiceReportTypeMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final Lookup initialValue;
final Function(Lookup?) onSelect;
final Lookup? initialValue;
const ServiceReportTypeMenu({
Key? key,
required this.onSelect,
this.initialValue,
}) : super(key: key);
const ServiceReportTypeMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
SettingProvider settingProvider = Provider.of<SettingProvider>(context);
UserProvider userProvider = Provider.of<UserProvider>(context);
ServiceReportTypesProvider menuProvider = Provider.of<ServiceReportTypesProvider>(context);
ServiceReportTypesProvider menuProvider =
Provider.of<ServiceReportTypesProvider>(context);
return LoadingManager(
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.types == null,
@ -24,7 +32,7 @@ class ServiceReportTypeMenu extends StatelessWidget {
menuProvider.reset();
await menuProvider.getTypes(
user: userProvider.user,
host: settingProvider.host
host: settingProvider.host,
);
onSelect(initialValue ?? menuProvider.types?.last);
},
@ -32,7 +40,6 @@ class ServiceReportTypeMenu extends StatelessWidget {
initialStatus: initialValue ?? menuProvider.types?.last,
statuses: menuProvider.types,
onSelect: onSelect,
)
);
));
}
}

@ -1,37 +1,44 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.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 '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class ServiceStatusMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final Lookup initialValue;
final Function(Lookup?)? onSelect;
final Lookup? initialValue;
const ServiceStatusMenu({
Key? key,
this.onSelect,
this.initialValue,
}) : super(key: key);
const ServiceStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
SettingProvider _settingProvider = Provider.of<SettingProvider>(context);
UserProvider _userProvider = Provider.of<UserProvider>(context);
ServiceStatusProvider _menuProvider = Provider.of<ServiceStatusProvider>(context);
SettingProvider settingProvider = Provider.of<SettingProvider>(context);
UserProvider userProvider = Provider.of<UserProvider>(context);
ServiceStatusProvider menuProvider =
Provider.of<ServiceStatusProvider>(context);
return LoadingManager(
isLoading: _menuProvider.isLoading,
isFailedLoading: _menuProvider.statuses == null,
stateCode: _menuProvider.stateCode,
onRefresh: () async {
_menuProvider.reset();
await _menuProvider.getTypes(
user: _userProvider.user,
host: _settingProvider.host
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: _menuProvider.statuses,
onSelect: onSelect,
)
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.statuses == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getTypes(
user: userProvider.user,
host: settingProvider.host,
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.statuses,
onSelect: onSelect,
),
);
}
}

@ -1,37 +1,44 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_defect_types_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/report/service_report_defect_types_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class ServiceRequestDefectTypesMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final Lookup initialValue;
final Function(Lookup?)? onSelect;
final Lookup? initialValue;
const ServiceRequestDefectTypesMenu({
Key? key,
this.onSelect,
this.initialValue,
}) : super(key: key);
const ServiceRequestDefectTypesMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
final settingProvider = Provider.of<SettingProvider>(context);
final userProvider = Provider.of<UserProvider>(context);
final menuProvider = Provider.of<ServiceRequestDefectTypesProvider>(context);
final menuProvider =
Provider.of<ServiceRequestDefectTypesProvider>(context);
return LoadingManager(
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
)
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host,
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
),
);
}
}

@ -1,37 +1,43 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/single_status_menu.dart';
import '../../../../controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart';
import '../../../../controllers/providers/api/user_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/lookup.dart';
import '../../loaders/loading_manager.dart';
import '../single_status_menu.dart';
class ServiceRequestPriorityMenu extends StatelessWidget {
final Function(Lookup) onSelect;
final Lookup initialValue;
final Function(Lookup?)? onSelect;
final Lookup? initialValue;
const ServiceRequestPriorityMenu({
Key? key,
this.onSelect,
this.initialValue,
}) : super(key: key);
const ServiceRequestPriorityMenu({Key key, this.onSelect, this.initialValue}) : super(key: key);
@override
Widget build(BuildContext context) {
final settingProvider = Provider.of<SettingProvider>(context);
final userProvider = Provider.of<UserProvider>(context);
final menuProvider = Provider.of<ServiceRequestPriorityProvider>(context);
return LoadingManager(
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
)
isLoading: menuProvider.isLoading,
isFailedLoading: menuProvider.items == null,
stateCode: menuProvider.stateCode,
onRefresh: () async {
menuProvider.reset();
await menuProvider.getData(
user: userProvider.user,
host: settingProvider.host,
);
},
child: SingleStatusMenu(
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
),
);
}
}

@ -1,27 +1,33 @@
import 'package:flutter/material.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../../../models/lookup.dart';
import '../../app_style/colors.dart';
import '../../app_style/sizing.dart';
class SingleStatusMenu extends StatefulWidget {
final List<Lookup> statuses;
final Lookup initialStatus;
final Function(Lookup) onSelect;
final List<Lookup>? statuses;
final Lookup? initialStatus;
final Function(Lookup?)? onSelect;
const SingleStatusMenu({Key key, this.statuses, this.onSelect, this.initialStatus}) : super(key: key);
const SingleStatusMenu({
Key? key,
this.onSelect,
this.statuses,
this.initialStatus,
}) : super(key: key);
@override
_SingleStatusMenuState createState() => _SingleStatusMenuState();
SingleStatusMenuState createState() => SingleStatusMenuState();
}
class _SingleStatusMenuState extends State<SingleStatusMenu> {
Lookup _selectedStatus;
class SingleStatusMenuState extends State<SingleStatusMenu> {
Lookup? _selectedStatus;
@override
void didUpdateWidget(covariant SingleStatusMenu oldWidget) {
if (widget.initialStatus != null) {
_selectedStatus = widget.statuses?.firstWhere((element) {
return element?.id == widget.initialStatus.id;
return element.id == widget.initialStatus?.id;
});
} else {
_selectedStatus = null;
@ -33,7 +39,7 @@ class _SingleStatusMenuState extends State<SingleStatusMenu> {
void initState() {
if (widget.initialStatus != null) {
_selectedStatus = widget.statuses?.firstWhere((element) {
return element?.id == widget.initialStatus.id;
return element.id == widget.initialStatus?.id;
});
}
@ -47,9 +53,11 @@ class _SingleStatusMenuState extends State<SingleStatusMenu> {
decoration: BoxDecoration(
color: AColors.inputFieldBackgroundColor,
border: Border.all(
color: Color(0xffefefef),
color: const Color(0xffefefef),
),
borderRadius: BorderRadius.circular(
AppStyle.borderRadius * AppStyle.getScaleFactor(context),
),
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
// boxShadow: const [
// AppStyle.boxShadow
// ]
@ -57,7 +65,7 @@ class _SingleStatusMenuState extends State<SingleStatusMenu> {
child: DropdownButton<Lookup>(
value: _selectedStatus,
iconSize: 24,
icon: Icon(Icons.keyboard_arrow_down_rounded),
icon: const Icon(Icons.keyboard_arrow_down_rounded),
elevation: 0,
isExpanded: true,
hint: Text(
@ -65,19 +73,23 @@ class _SingleStatusMenuState extends State<SingleStatusMenu> {
style: Theme.of(context).textTheme.subtitle1,
),
style: TextStyle(color: Theme.of(context).primaryColor),
underline: SizedBox.shrink(),
onChanged: (Lookup newValue) {
underline: const SizedBox.shrink(),
onChanged: (Lookup? newValue) {
setState(() {
_selectedStatus = newValue;
});
widget.onSelect(newValue);
if (widget.onSelect != null) {
widget.onSelect!(newValue);
}
},
items: widget.statuses.map<DropdownMenuItem<Lookup>>((Lookup value) {
items: widget.statuses?.map<DropdownMenuItem<Lookup>>((Lookup value) {
return DropdownMenuItem<Lookup>(
value: value,
child: Text(
value.label,
style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).primaryColor, fontWeight: FontWeight.w600),
value.label ?? '',
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.w600),
),
);
}).toList(),

@ -1,19 +1,21 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/loaders/app_loading.dart';
import '../../../models/timer_model.dart';
import '../../app_style/colors.dart';
import '../../app_style/sizing.dart';
class AppTimer extends StatefulWidget {
final TimerModel timer;
final TimerModel? timer;
final Future<bool> Function(TimerModel) onChange;
final TextStyle style;
final TextStyle? style;
const AppTimer({
Key key,
Key? key,
this.timer,
this.onChange,
this.style,
required this.onChange,
}) : super(key: key);
@override
@ -21,43 +23,46 @@ class AppTimer extends StatefulWidget {
}
class _AppTimerState extends State<AppTimer> {
Timer _timer;
DateTime _startAt;
DateTime _endAt;
Timer? _timer;
DateTime? _startAt;
DateTime? _endAt;
int _delay = 0;
bool _running = false;
bool _loading = false;
final ValueNotifier<String> _period = ValueNotifier("0:00:00");
final ValueNotifier<String> _period = ValueNotifier("0:00:00");
_startTimer() async {
if (!_running) {
final time = DateTime.now();
bool result = await widget.onChange(
TimerModel(startAt: time,endAt: null,durationInSecond: _delay));
if(!result) return;
TimerModel(startAt: time, endAt: null, durationInSecond: _delay),
);
if (!result) return;
_running = true;
if(_endAt != null){
_delay += _endAt.difference(_startAt).inSeconds;
if (_endAt != null && _startAt != null) {
_delay += _endAt!.difference(_startAt!).inSeconds;
}
_startAt = time.subtract(Duration(seconds: _delay));
_endAt = null;
}
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if(_loading == true) return;
_period.value = (_endAt ?? DateTime.now()).difference(
_startAt
).toString().split(".").first;
if (_loading == true) return;
_period.value = (_endAt ?? DateTime.now())
.difference(_startAt!)
.toString()
.split(".")
.first;
});
}
_stopTimer() async {
final time = DateTime.now();
final tempStartAt = _startAt.add(Duration(seconds: _delay));
bool result = await widget.onChange(
TimerModel(startAt: tempStartAt,endAt: time,durationInSecond: _delay));
if(!result) return;
final tempStartAt = _startAt?.add(Duration(seconds: _delay));
bool result = await widget.onChange(TimerModel(
startAt: tempStartAt, endAt: time, durationInSecond: _delay));
if (!result) return;
_running = false;
_endAt = time;
_startAt = tempStartAt;
@ -67,9 +72,9 @@ class _AppTimerState extends State<AppTimer> {
_onPressed() async {
_loading = true;
setState(() {});
if(!_running){
if (!_running) {
await _startTimer();
}else{
} else {
await _stopTimer();
}
_loading = false;
@ -82,17 +87,25 @@ class _AppTimerState extends State<AppTimer> {
_endAt = widget.timer?.endAt;
_running = _startAt != null && _endAt == null;
_delay = (widget.timer?.durationInSecond ?? 0);
final difference = _startAt == null ? 0:
(_endAt ?? DateTime.now())?.difference(_startAt)?.inSeconds ?? 0;
_period.value = Duration(seconds: _running ? difference : _delay + difference).toString().split(".").first;
final difference = _startAt == null
? 0
: (_endAt ?? DateTime.now()).difference(_startAt!).inSeconds;
_period.value =
Duration(seconds: _running ? difference : _delay + difference)
.toString()
.split(".")
.first;
super.initState();
if(_running){_startTimer();}
if (_running) {
_startTimer();
}
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return SizedBox(
@ -100,31 +113,34 @@ class _AppTimerState extends State<AppTimer> {
height: 28 * AppStyle.getScaleFactor(context),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(1, 1),
padding: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)),
backgroundColor: _running ? AColors.green[300] : AColors.grey,
foregroundColor: Colors.black
),
minimumSize: const Size(1, 1),
padding: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)),
backgroundColor: _running ? AColors.green[300] : AColors.grey,
foregroundColor: Colors.black),
onPressed: _loading ? null : _onPressed,
child: _loading ? const SizedBox.square(
dimension: 18,child: CircularProgressIndicator(color: Colors.white,)):
Row(
children: [
Icon(_running ? Icons.pause : Icons.play_arrow),
Expanded(
child: Center(
child: ValueListenableBuilder<String>(
valueListenable: _period,
builder: (context,value,_){
return Text(value,
style: widget.style,
);
}
),
child: _loading
? const SizedBox.square(
dimension: 18,
child: CircularProgressIndicator(
color: Colors.white,
))
: Row(
children: [
Icon(_running ? Icons.pause : Icons.play_arrow),
Expanded(
child: Center(
child: ValueListenableBuilder<String>(
valueListenable: _period,
builder: (context, value, _) {
return Text(
value,
style: widget.style,
);
}),
),
),
],
),
),
],
),
),
);
}

@ -1,22 +1,26 @@
import 'package:flutter/material.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../../app_style/sizing.dart';
class ASubTitle extends StatelessWidget {
final String text;
final EdgeInsets padding;
final Color color;
final double font;
const ASubTitle(this.text, {Key key,this.padding, this.color, this.font}) : super(key: key);
final EdgeInsets? padding;
final Color? color;
final double? font;
const ASubTitle(this.text, {Key? key, this.padding, this.color, this.font})
: super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: padding ?? EdgeInsets.zero,
child: Text(
text,
style: Theme.of(context).textTheme.bodyText1.copyWith(
// fontWeight: FontWeight.bold,
fontSize: font,
color: color
),
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
// fontWeight: FontWeight.bold,
fontSize: font,
color: color),
textScaleFactor: AppStyle.getScaleFactor(context),
),
);

@ -1,22 +1,30 @@
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:flutter/material.dart';
import '../../app_style/sizing.dart';
class ATitle extends StatelessWidget {
final String text;
final EdgeInsets padding;
final EdgeInsets? padding;
final bool center;
const ATitle(this.text, {Key key,this.padding,this.center= false}) : super(key: key);
const ATitle(this.text, {Key? key, this.padding, this.center = false})
: super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: padding ?? EdgeInsets.symmetric(horizontal: 16,vertical: 8),
padding: padding ??
const EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
child: Row(
mainAxisAlignment: center
? MainAxisAlignment.center
: MainAxisAlignment.start,
mainAxisAlignment:
center ? MainAxisAlignment.center : MainAxisAlignment.start,
children: [
Text(
text,
style: Theme.of(context).textTheme.headline6,
style: Theme.of(context).textTheme.titleLarge,
textScaleFactor: AppStyle.getScaleFactor(context),
),
],

@ -1,24 +1,32 @@
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../../app_style/sizing.dart';
class ExpandableInfoRow extends StatefulWidget {
final IconData iconData;
final IconData? iconData;
final String title;
final Widget child;
const ExpandableInfoRow({Key key, this.iconData, this.title, this.child}) : super(key: key);
const ExpandableInfoRow({
Key? key,
this.iconData,
required this.title,
required this.child,
}) : super(key: key);
@override
_ExpandableInfoRowState createState() => _ExpandableInfoRowState();
ExpandableInfoRowState createState() => ExpandableInfoRowState();
}
class _ExpandableInfoRowState extends State<ExpandableInfoRow>
with TickerProviderStateMixin{
class ExpandableInfoRowState extends State<ExpandableInfoRow>
with TickerProviderStateMixin {
bool _isExpanded = false;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: (){
onTap: () {
_isExpanded = !_isExpanded;
setState(() {});
},
@ -26,39 +34,37 @@ class _ExpandableInfoRowState extends State<ExpandableInfoRow>
children: [
Row(
children: <Widget>[
widget.iconData != null ?
Padding(
padding: EdgeInsets.symmetric(
horizontal: 8 * AppStyle.getScaleFactor(context),
vertical: 2 * AppStyle.getScaleFactor(context),
),
child: FaIcon(
widget.iconData,
color: Theme.of(context).primaryColor,
size: 20 * AppStyle.getScaleFactor(context),
),
):SizedBox.shrink(),
widget.iconData != null
? Padding(
padding: EdgeInsets.symmetric(
horizontal: 8 * AppStyle.getScaleFactor(context),
vertical: 2 * AppStyle.getScaleFactor(context),
),
child: FaIcon(
widget.iconData,
color: Theme.of(context).primaryColor,
size: 20 * AppStyle.getScaleFactor(context),
),
)
: const SizedBox.shrink(),
Expanded(
flex: 2,
child: Text(
widget.title,
style: TextStyle(
style: const TextStyle(
//color: Theme.of(context).dividerColor,
fontSize: 14,
fontWeight: FontWeight.bold,
),
textScaleFactor: AppStyle.getScaleFactor(context),
textScaleFactor: AppStyle.getScaleFactor(context),
),
),
AnimatedSwitcher(
duration: Duration(milliseconds: 400),
duration: const Duration(milliseconds: 400),
transitionBuilder: (Widget child, Animation<double> animation) {
return FadeTransition(
child: ScaleTransition(
child: child,
scale: animation
),
opacity: animation,
child: ScaleTransition(scale: animation, child: child),
);
},
child: Icon(
@ -75,17 +81,21 @@ class _ExpandableInfoRowState extends State<ExpandableInfoRow>
],
),
AnimatedSize(
duration: Duration(milliseconds: 300),
duration: const Duration(milliseconds: 300),
child: Visibility(
visible: _isExpanded,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8 * AppStyle.getScaleFactor(context)),
child: widget.child,
)
),
visible: _isExpanded,
child: Padding(
padding: EdgeInsets.symmetric(
vertical: 8 * AppStyle.getScaleFactor(context)),
child: widget.child,
)),
),
Divider(
height: 2 * AppStyle.getScaleFactor(context),
),
SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
Divider(height: 2 * AppStyle.getScaleFactor(context),),
SizedBox(height: 8 * AppStyle.getScaleFactor(context),),
],
),
);

@ -1,13 +1,12 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/subtitle.dart';
import 'package:test_sa/models/visits/visit.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/visits/visit_status.dart';
import '../../../controllers/localization/localization.dart';
import '../../../controllers/providers/api/user_provider.dart';
import '../../../models/enums/user_types.dart';
import '../../../models/visits/visit.dart';
import '../../app_style/sizing.dart';
import 'visit_status.dart';
class VisitItem extends StatelessWidget {
final Visit visit;
@ -18,31 +17,47 @@ class VisitItem extends StatelessWidget {
final Function(Visit) onLongPress;
final Function(Visit) onSelect;
const VisitItem({Key key, this.visit, this.onPressed, this.isSelected = false, this.activeSelectMod = false, this.onLongPress, this.onSelect, this.index}) : super(key: key);
const VisitItem({
Key? key,
this.isSelected = false,
this.activeSelectMod = false,
required this.visit,
required this.onPressed,
required this.onLongPress,
required this.onSelect,
required this.index,
}) : super(key: key);
@override
Widget build(BuildContext context) {
UserProvider _userProvider = Provider.of<UserProvider>(context);
Color itemColor = index % 2 == 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary;
Color onItemColor = index % 2 != 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary;
Subtitle _subtitle = AppLocalization.of(context).subtitle;
UserProvider userProvider = Provider.of<UserProvider>(context);
Color itemColor = index % 2 == 0
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.onPrimary;
Color onItemColor = index % 2 != 0
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.onPrimary;
final subtitle = AppLocalization.of(context)?.subtitle;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
primary: itemColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)),
borderRadius:
BorderRadius.circular(AppStyle.getBorderRadius(context)),
),
),
onPressed: () {
if (activeSelectMod && _userProvider.user.type == UsersTypes.engineer)
if (activeSelectMod &&
userProvider.user?.type == UsersTypes.engineer) {
onSelect(visit);
else
} else {
onPressed(visit);
}
},
onLongPress: _userProvider.user.type == UsersTypes.engineer
onLongPress: userProvider.user?.type == UsersTypes.engineer
? () {
onLongPress(visit);
}
@ -55,11 +70,14 @@ class VisitItem extends StatelessWidget {
Expanded(
child: Text(
"S.N: " + visit.deviceSerialNumber ?? "No serial number",
style: Theme.of(context).textTheme.headline6.copyWith(color: onItemColor, fontSize: 16, fontWeight: FontWeight.bold),
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: onItemColor,
fontSize: 16,
fontWeight: FontWeight.bold),
),
),
AnimatedSwitcher(
duration: Duration(milliseconds: 400),
duration: const Duration(milliseconds: 400),
child: Visibility(
key: ValueKey(activeSelectMod),
visible: activeSelectMod,
@ -87,7 +105,7 @@ class VisitItem extends StatelessWidget {
Expanded(
child: Text(
visit.hospitalName ?? "No client found",
style: Theme.of(context).textTheme.subtitle1.copyWith(
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: onItemColor,
fontSize: 14,
),
@ -97,7 +115,7 @@ class VisitItem extends StatelessWidget {
),
Text(
visit.modelAndBrand ?? "",
style: Theme.of(context).textTheme.subtitle1.copyWith(
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: onItemColor,
fontSize: 14,
),
@ -110,12 +128,15 @@ class VisitItem extends StatelessWidget {
Expanded(
child: Text(
visit.employName ?? "No employ found",
style: Theme.of(context).textTheme.headline6.copyWith(color: onItemColor, fontSize: 14, fontWeight: FontWeight.bold),
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: onItemColor,
fontSize: 14,
fontWeight: FontWeight.bold),
),
),
Text(
visit.contactStatus ?? "",
style: Theme.of(context).textTheme.subtitle1.copyWith(
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: onItemColor,
fontSize: 14,
),
@ -132,15 +153,15 @@ class VisitItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_subtitle.expectDate,
style: Theme.of(context).textTheme.headline6.copyWith(
subtitle?.expectDate ?? '',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: onItemColor,
fontSize: 14,
),
),
Text(
visit.expectDate ?? _subtitle.noDateFound,
style: Theme.of(context).textTheme.headline6.copyWith(
visit.expectDate ?? subtitle?.noDateFound ?? '',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: onItemColor,
fontSize: 14,
),
@ -152,15 +173,15 @@ class VisitItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_subtitle.actualDate,
style: Theme.of(context).textTheme.headline6.copyWith(
subtitle?.actualDate ?? '',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: onItemColor,
fontSize: 14,
),
),
Text(
visit.actualDate ?? _subtitle.noDateFound,
style: Theme.of(context).textTheme.headline6.copyWith(
visit.actualDate ?? subtitle?.noDateFound ?? '',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: onItemColor,
fontSize: 14,
),

@ -1,44 +1,47 @@
import 'package:flutter/material.dart';
import 'package:test_sa/models/visits/visit.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../../../models/visits/visit.dart';
import '../../app_style/colors.dart';
import '../../app_style/sizing.dart';
class VisitStatusLabel extends StatelessWidget {
final Visit visit;
const VisitStatusLabel({Key key, this.visit}) : super(key: key);
const VisitStatusLabel({Key? key, required this.visit}) : super(key: key);
Color getStatusColor(){
switch(visit.status.id){
case 0: return AColors.green;
case 1: return AColors.grey;
case 2: return AColors.grey;
default : return AColors.grey;
Color getStatusColor() {
switch (visit.status.id) {
case 0:
return AColors.green;
case 1:
return AColors.grey;
case 2:
return AColors.grey;
default:
return AColors.grey;
}
}
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 2,horizontal: 8),
alignment: Alignment.center,
decoration: BoxDecoration(
color: getStatusColor(),
borderRadius: BorderRadius.circular(
AppStyle.getBorderRadius(context)
return Container(
padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 8),
alignment: Alignment.center,
decoration: BoxDecoration(
color: getStatusColor(),
borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)),
boxShadow: const [AppStyle.boxShadow],
),
child: Text(
visit.status.label == null || visit.status.label.isEmpty
? "no status"
: visit.status.label,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
color: getStatusColor().computeLuminance() > 0.5
? AColors.black
: Colors.white,
),
boxShadow: [
AppStyle.boxShadow
]
),
child: Text(
visit.status.label == null
|| visit.status.label.isEmpty
? "no status" :visit.status.label,
style: Theme.of(context).textTheme.subtitle2.copyWith(
color: getStatusColor().computeLuminance() > 0.5
? AColors.black : Colors.white,
),
)
),
);
}
}

@ -1,12 +1,14 @@
import 'package:test_sa/controllers/localization/localization.dart';
import 'package:test_sa/models/subtitle.dart';
import 'package:test_sa/models/visits/visit.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/pages/user/visits/visit_details.dart';
import 'package:test_sa/views/widgets/loaders/lazy_loading.dart';
import 'package:test_sa/views/widgets/loaders/no_item_found.dart';
import 'package:test_sa/views/widgets/visits/visit_item.dart';
import 'package:flutter/material.dart';
import '../../../controllers/localization/localization.dart';
import '../../../models/subtitle.dart';
import '../../../models/visits/visit.dart';
import '../../app_style/sizing.dart';
import '../../pages/user/visits/visit_details.dart';
import '../loaders/lazy_loading.dart';
import '../loaders/no_item_found.dart';
import 'visit_item.dart';
class VisitsList extends StatefulWidget {
final List<Visit> visits;
final bool nextPage;
@ -14,29 +16,31 @@ class VisitsList extends StatefulWidget {
final Function(List<Visit>) onEditGroup;
const VisitsList({
Key key,
this.visits,
this.nextPage,
this.onLazyLoad,
this.onEditGroup
Key? key,
required this.visits,
required this.nextPage,
required this.onLazyLoad,
required this.onEditGroup,
}) : super(key: key);
@override
_VisitsListState createState() => _VisitsListState();
VisitsListState createState() => VisitsListState();
}
class _VisitsListState extends State<VisitsList> {
List<Visit> _selectedVisits = [];
class VisitsListState extends State<VisitsList> {
final List<Visit> _selectedVisits = [];
@override
void initState() {
_selectedVisits.clear();
super.initState();
}
@override
Widget build(BuildContext context) {
Subtitle _subtitle = AppLocalization.of(context).subtitle;
if(widget.visits.length == 0){
return NoItemFound(message: _subtitle.noVisitsFound,);
Subtitle? subtitle = AppLocalization.of(context)?.subtitle;
if (widget.visits.isEmpty) {
return NoItemFound(message: subtitle?.noVisitsFound);
}
return Stack(
children: [
@ -44,34 +48,33 @@ class _VisitsListState extends State<VisitsList> {
nextPage: widget.nextPage,
onLazyLoad: widget.onLazyLoad,
child: ListView.builder(
//physics: BouncingScrollPhysics(),
itemCount: widget.visits.length,
padding: EdgeInsets.symmetric(horizontal: 16,vertical: 8),
itemBuilder: (context,itemIndex){
Visit _visit = widget.visits[itemIndex];
bool _isSelected = _selectedVisits.contains(_visit);
//physics: BouncingScrollPhysics(),
itemCount: widget.visits.length,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
itemBuilder: (context, itemIndex) {
Visit visit = widget.visits[itemIndex];
bool isSelected = _selectedVisits.contains(visit);
return VisitItem(
visit: _visit,
isSelected: _isSelected,
visit: visit,
isSelected: isSelected,
index: itemIndex,
activeSelectMod: _selectedVisits.isNotEmpty,
onPressed: (visit){
Navigator.of(context).push(
MaterialPageRoute(
builder: (_)=> VisitDetailsPage(visit: visit,)
)
);
onPressed: (visit) {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => VisitDetailsPage(
visit: visit,
)));
},
onSelect: (visit){
if(_isSelected){
onSelect: (visit) {
if (isSelected) {
_selectedVisits.remove(visit);
} else {
_selectedVisits.add(visit);
}
setState(() {});
},
onLongPress: (visit){
if(_isSelected){
onLongPress: (visit) {
if (isSelected) {
_selectedVisits.remove(visit);
} else {
_selectedVisits.add(visit);
@ -79,15 +82,14 @@ class _VisitsListState extends State<VisitsList> {
setState(() {});
},
);
}
),
}),
),
Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding: EdgeInsets.all(8.0 * AppStyle.getScaleFactor(context)),
child: AnimatedSwitcher(
duration: Duration(milliseconds: 400),
duration: const Duration(milliseconds: 400),
child: Visibility(
key: ValueKey(_selectedVisits.isNotEmpty),
visible: _selectedVisits.isNotEmpty,
@ -96,17 +98,17 @@ class _VisitsListState extends State<VisitsList> {
children: [
FloatingActionButton(
heroTag: "cancel",
child: Icon(Icons.cancel),
onPressed: (){
child: const Icon(Icons.cancel),
onPressed: () {
_selectedVisits.clear();
setState(() {});
},
),
FloatingActionButton(
heroTag: "edit",
child: Icon(Icons.edit),
onPressed: (){
if(!widget.visits.contains(_selectedVisits.first)){
child: const Icon(Icons.edit),
onPressed: () {
if (!widget.visits.contains(_selectedVisits.first)) {
_selectedVisits.clear();
setState(() {});
return;

Loading…
Cancel
Save