Commit afecc427 authored by Sai Srinivas's avatar Sai Srinivas
Browse files

20-11-2025 Poly Lines and technician tracking screen, and technician tracking...

20-11-2025 Poly Lines and technician tracking screen, and technician tracking in complaint details and service List screen and changes in Modal for serviceList Response
parent ec8a1705
......@@ -82,6 +82,8 @@ class TechDetails {
class AllServiceList {
String? id;
String? lat;
String? lng;
String? empName;
String? date;
String? techRoleName;
......@@ -92,12 +94,14 @@ class AllServiceList {
String? customerServiceRating;
String? inOrOutTime;
String? runningHrs;
String? fsrExt;
String? filePath;
String? fsrExt;
String? fsrNo;
AllServiceList(
{this.id,
this.lat,
this.lng,
this.empName,
this.date,
this.techRoleName,
......@@ -108,12 +112,14 @@ class AllServiceList {
this.customerServiceRating,
this.inOrOutTime,
this.runningHrs,
this.fsrExt,
this.filePath,
this.fsrExt,
this.fsrNo});
AllServiceList.fromJson(Map<String, dynamic> json) {
id = json['id'];
lat = json['lat'];
lng = json['lng'];
empName = json['emp_name'];
date = json['date'];
techRoleName = json['tech_role_name'];
......@@ -124,14 +130,16 @@ class AllServiceList {
customerServiceRating = json['customer_service_rating'];
inOrOutTime = json['in_or_out_time'];
runningHrs = json['running_hrs'];
fsrExt = json['fsr_ext'];
filePath = json['file_path'];
fsrExt = json['fsr_ext'];
fsrNo = json['fsr_no'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['lat'] = this.lat;
data['lng'] = this.lng;
data['emp_name'] = this.empName;
data['date'] = this.date;
data['tech_role_name'] = this.techRoleName;
......@@ -142,8 +150,8 @@ class AllServiceList {
data['customer_service_rating'] = this.customerServiceRating;
data['in_or_out_time'] = this.inOrOutTime;
data['running_hrs'] = this.runningHrs;
data['fsr_ext'] = this.fsrExt;
data['file_path'] = this.filePath;
data['fsr_ext'] = this.fsrExt;
data['fsr_no'] = this.fsrNo;
return data;
}
......
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:location/location.dart' as LocationPlugin;
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
class Techniciantrackingprovider extends ChangeNotifier {
final String _googleApikey = "AIzaSyBGzvgMMKwPBAANTwaoRsAnrCpiWCj8wVs";
GoogleMapController? _mapController;
LocationPlugin.LocationData? _currentLocation;
bool _isLoading = true;
bool _hasPermission = false;
final Set<Marker> _markers = {};
final Set<Polyline> _polylines = {};
final List<LatLng> _polylineCoordinates = [];
late PolylinePoints polylinePoints;
BitmapDescriptor? customerIcon;
BitmapDescriptor? technicianIcon;
LatLng get startLocation => const LatLng(17.439112226708446, 78.43292499146135);
GoogleMapController? get mapController => _mapController;
Set<Marker> get markers => _markers;
Set<Polyline> get polylines => _polylines;
LocationPlugin.LocationData? get currentLocation => _currentLocation;
bool get isLoading => _isLoading;
set mapController(GoogleMapController? controller) {
_mapController = controller;
notifyListeners();
}
Future<void> loadCustomIcons() async {
customerIcon ??= await BitmapDescriptor.fromAssetImage(
const ImageConfiguration(size: Size(80, 80)),
'assets/images/maps_ic.png',
);
technicianIcon ??= await BitmapDescriptor.fromAssetImage(
const ImageConfiguration(size: Size(80, 80)),
'assets/images/technician_marker.png',
);
notifyListeners();
}
Future<void> getLocationPermission(BuildContext context) async {
_isLoading = true;
notifyListeners();
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
_isLoading = false;
notifyListeners();
return;
}
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
_isLoading = false;
notifyListeners();
return;
}
}
if (permission == LocationPermission.deniedForever) {
_isLoading = false;
notifyListeners();
return;
}
_hasPermission = true;
await loadCustomIcons();
final LocationPlugin.Location location = LocationPlugin.Location();
_currentLocation = await location.getLocation();
// Add customer marker
if (_currentLocation != null) {
_markers.add(Marker(
markerId: const MarkerId('customer'),
position: LatLng(_currentLocation!.latitude!, _currentLocation!.longitude!),
infoWindow: const InfoWindow(title: "You are here"),
icon: customerIcon ?? BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen),
));
}
_isLoading = false;
notifyListeners();
}
void updateTechnicianLocation(double? lat, double? lng) {
if (lat == null || lng == null || lat == 0 || lng == 0) return;
final technicianLatLng = LatLng(lat, lng);
// Remove old technician marker
_markers.removeWhere((m) => m.markerId.value == 'technician');
_polylines.clear();
_polylineCoordinates.clear();
// Add new technician marker
_markers.add(Marker(
markerId: const MarkerId('technician'),
position: technicianLatLng,
infoWindow: const InfoWindow(title: "Technician"),
icon: technicianIcon ?? BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue),
));
// Draw route if customer location exists
if (_currentLocation != null) {
_drawRoute(
LatLng(_currentLocation!.latitude!, _currentLocation!.longitude!),
technicianLatLng,
);
}
// Adjust camera
_fitBothMarkers();
setPolylines(lat,lng);
notifyListeners();
}
void setPolylines(double? lat, double? lng) async {
_polylineCoordinates.clear();
_polylines.clear();
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
// googleApiKey: "AIzaSyAA2ukvrb1kWQZ2dttsNIMynLJqVCYYrhw",
request: PolylineRequest(
origin: await PointLatLng(
lat!,
lng!),
destination: await PointLatLng(
_currentLocation!.latitude!,
_currentLocation!.longitude!),
mode: TravelMode.driving),
// Example LatLng// Example LatLng
// Example LatLng
);
if (result.points.isNotEmpty) {
result.points.forEach((PointLatLng point) {
_polylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
_polylines.add(Polyline(
width: 1,
polylineId: PolylineId("poly"),
color: Color(0xFF008CDE),
points: _polylineCoordinates,
));
notifyListeners();
}
}
Future<void> _drawRoute(LatLng origin, LatLng destination) async {
final polylinePoints = PolylinePoints(apiKey: _googleApikey);
try {
final result = await polylinePoints.getRouteBetweenCoordinates(
request: PolylineRequest(
origin: PointLatLng(origin.latitude, origin.longitude),
destination: PointLatLng(destination.latitude, destination.longitude),
mode: TravelMode.driving,
),
);
if (result.points.isNotEmpty) {
_polylineCoordinates.clear();
for (var point in result.points) {
_polylineCoordinates.add(LatLng(point.latitude, point.longitude));
}
_polylines.add(Polyline(
polylineId: const PolylineId('route'),
color: Colors.blue,
width: 5,
points: _polylineCoordinates,
patterns: [PatternItem.dash(20), PatternItem.gap(10)],
));
}
} catch (e) {
debugPrint("Polyline Error: $e");
}
notifyListeners();
}
void _fitBothMarkers() {
if (_markers.length < 2 || _mapController == null) return;
final positions = _markers.map((m) => m.position).toList();
double minLat = positions[0].latitude;
double maxLat = positions[0].latitude;
double minLng = positions[0].longitude;
double maxLng = positions[0].longitude;
for (var pos in positions) {
if (pos.latitude < minLat) minLat = pos.latitude;
if (pos.latitude > maxLat) maxLat = pos.latitude;
if (pos.longitude < minLng) minLng = pos.longitude;
if (pos.longitude > maxLng) maxLng = pos.longitude;
}
_mapController!.animateCamera(
CameraUpdate.newLatLngBounds(
LatLngBounds(
southwest: LatLng(minLat, minLng),
northeast: LatLng(maxLat, maxLng),
),
100,
),
);
}
Future<void> setMapStyle(GoogleMapController controller) async {
String mapStyle = '''
[
{
"featureType": "road",
"elementType": "geometry",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "road.arterial",
"elementType": "geometry",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "road.highway",
"elementType": "geometry",
"stylers": [
{
"visibility": "off"
}
]
},
{
"featureType": "road.local",
"elementType": "geometry",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "poi",
"elementType": "labels",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "poi.business",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "transit",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "road.local",
"elementType": "labels",
"stylers": [
{
"visibility": "on"
}
]
}
]
''';
await controller.setMapStyle(mapStyle);
}
void clearMap() {
_markers.clear();
_polylines.clear();
_polylineCoordinates.clear();
notifyListeners();
}
}
\ No newline at end of file
......@@ -2,14 +2,21 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart'
show PolylinePoints;
import 'package:flutter_svg/svg.dart';
import 'package:gen_service/Notifiers/HelpAndComplaintProvider.dart';
import 'package:gen_service/Notifiers/technicianTrackingProvider.dart';
import 'package:gen_service/Screens/FileViewer.dart';
import 'package:gen_service/Screens/HelpAndComplaintScreens/TechnicianTrackingScreen.dart';
import 'package:gen_service/Screens/HelpAndComplaintScreens/jobcardListScreen.dart';
import 'package:gen_service/Screens/HelpAndComplaintScreens/serviceListScreen.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:provider/provider.dart';
import 'package:razorpay_flutter/razorpay_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../Models/HelpAndComplaintModels/complaintDetailsResponse.dart';
import '../../Notifiers/PayAmountProvider.dart';
import '../../Utility/AppColors.dart';
import '../../Utility/CustomSnackbar.dart';
......@@ -55,6 +62,15 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
widget.sessionId,
widget.complaintId,
);
final mapProvider = Provider.of<Techniciantrackingprovider>(
context,
listen: false,
);
mapProvider.getLocationPermission(context);
mapProvider.polylinePoints = PolylinePoints(
apiKey: "AIzaSyAA2ukvrb1kWQZ2dttsNIMynLJqVCYYrhw",
);
});
}
......@@ -181,6 +197,58 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
// });
// }
Widget sectionHeading(text,[ComplaintDetails? complaintData]) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
text,
style: TextStyle(color: AppColors.nearDarkText, fontSize: 14),
),
if (text != "Complaint Details") ...[
InkResponse(
onTap: () async {
var redirectScreen;
switch (text) {
case "Job Cards":
redirectScreen = Jobcardlistscreen(
accId: widget.accId,
sessionId: widget.sessionId,
complaintId: widget.complaintId,
);
break;
case "Service Details":
redirectScreen = serviceListScreen(
accId: widget.accId,
sessionId: widget.sessionId,
complaintId: widget.complaintId,
complaintData:complaintData
);
break;
default:
break;
}
await Navigator.push(
context,
MaterialPageRoute(builder: (context) => redirectScreen),
);
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
"See All",
style: TextStyle(color: AppColors.buttonColor, fontSize: 14),
),
),
),
],
],
),
);
}
@override
Widget build(BuildContext context) {
return Consumer<HelpAndComplaintProvider>(
......@@ -400,9 +468,9 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
child: SizedBox(
child: Row(
mainAxisAlignment:
MainAxisAlignment.start,
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.center,
CrossAxisAlignment.center,
children: [
InkResponse(
onTap: () {
......@@ -447,7 +515,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
flex: 5,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
......@@ -459,15 +527,15 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
children: [
TextSpan(
text:
"#${complaintData?.id!}",
"#${complaintData?.id!}",
),
TextSpan(
text:
(complaintData?.complaintName ??
"")
.isNotEmpty
? " | ${complaintData?.complaintName!}"
: "",
(complaintData?.complaintName ??
"")
.isNotEmpty
? " | ${complaintData?.complaintName!}"
: "",
),
],
),
......@@ -492,10 +560,10 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
),
decoration: BoxDecoration(
color:
complaintData?.openStatus ==
"Open"
? AppColors.successBG
: AppColors.yellowBG,
complaintData?.openStatus ==
"Open"
? AppColors.successBG
: AppColors.yellowBG,
borderRadius: BorderRadius.circular(
10,
),
......@@ -508,10 +576,10 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
fontSize: 14,
fontWeight: FontWeight.w400,
color:
complaintData?.openStatus ==
"Open"
? AppColors.success
: AppColors.normalText,
complaintData?.openStatus ==
"Open"
? AppColors.success
: AppColors.normalText,
),
),
),
......@@ -565,7 +633,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
flex: 5,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
CrossAxisAlignment.start,
children: [
Text(
"${jobCardsData?.date}",
......@@ -578,53 +646,53 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
SizedBox(height: 4),
Row(
mainAxisAlignment:
MainAxisAlignment.start,
MainAxisAlignment.start,
children: [
Text(
"Job Card",
style: TextStyle(
fontSize: 14,
color:
AppColors
.nearDarkText,
AppColors
.nearDarkText,
),
),
InkResponse(
onTap:
bottomSheetButtonClicked
? null
: () {
HapticFeedback.mediumImpact();
setState(() {
bottomSheetButtonClicked =
true;
});
provider.fetchJobCardProductDetails(
widget.accId,
widget
.sessionId,
jobCardsData!
.id,
);
Future.delayed(
Duration(
milliseconds:
600,
),
() {
_showJobCardProductSheet(
context,
);
},
);
},
bottomSheetButtonClicked
? null
: () {
HapticFeedback.mediumImpact();
setState(() {
bottomSheetButtonClicked =
true;
});
provider.fetchJobCardProductDetails(
widget.accId,
widget
.sessionId,
jobCardsData!
.id,
);
Future.delayed(
Duration(
milliseconds:
600,
),
() {
_showJobCardProductSheet(
context,
);
},
);
},
child: Text(
" ⓘ View Details",
style: TextStyle(
fontSize: 14,
color:
AppColors
.buttonColor,
AppColors
.buttonColor,
),
),
),
......@@ -655,9 +723,9 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
InkResponse(
onTap:
() => _openPaymentSheet(
context,
jobCardsData!.totalPrice.toString(),
),
context,
jobCardsData!.totalPrice.toString(),
),
child: Container(
padding: EdgeInsets.symmetric(
vertical: 16,
......@@ -703,7 +771,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
......@@ -747,235 +815,623 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
),
child: Column(
children: [
...List.generate(serviceHeadings.length, (
i,
) {
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 3,
if (serviceData?.openStatus ==
"Open") ...[
Container(
height: 220,
margin: const EdgeInsets.symmetric(
horizontal: 5,
vertical: 10,
),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
serviceHeadings[i] ?? "-",
style: const TextStyle(
fontSize: 14,
color: AppColors.subtitleText,
),
),
),
Expanded(
child: InkResponse(
onTap:
serviceHeadings[i] == "FSR File" && (serviceData?.fsrFilePath != null)
? () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context,) => Fileviewer(
fileName: serviceData?.fsrExt ?? "-",
fileUrl: serviceData?.fsrFilePath ?? "-",
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
18,
),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(
18,
),
child: Consumer<
Techniciantrackingprovider
>(
builder: (
context,
mapProvider,
child,
) {
return Stack(
clipBehavior: Clip.none,
children: [
GoogleMap(
initialCameraPosition: CameraPosition(
target:
mapProvider.currentLocation !=
null
? LatLng(
mapProvider
.currentLocation!
.latitude!,
mapProvider
.currentLocation!
.longitude!,
)
: mapProvider
.startLocation,
zoom: 15,
),
);
myLocationEnabled: true,
myLocationButtonEnabled:
false,
zoomControlsEnabled: false,
mapType: MapType.normal,
markers:
mapProvider.markers,
polylines:
mapProvider.polylines,
onMapCreated: (
GoogleMapController
controller,
) {
mapProvider
.mapController =
controller;
mapProvider.setMapStyle(
controller,
);
final double? techLat1 = 17.4484769;
final double? techLng1 = 78.3710461;
final double? techLat = double.tryParse(
serviceData?.lat?.trim() ?? '${techLat1}',
)??techLat1;
final double? techLng = double.tryParse(
serviceData?.lng?.trim() ?? '${techLng1}',
)??techLng1;
}
: null,
if (techLat != null &&
techLng != null &&
techLat != 0 &&
techLng != 0) {
mapProvider
.updateTechnicianLocation(
techLat,
techLng,
);
}
},
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Align(
alignment:
Alignment
.bottomCenter,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(
0xFFFFFFFF,
).withOpacity(
0.01,
),
Color(0xFFFFFFFF),
Color(0xFFFFFFFF),
Color(
0xFFFFFFFF,
).withOpacity(
0.01,
),
],
begin:
Alignment
.bottomCenter,
end:
Alignment
.topCenter,
),
),
child: Column(
children: [
InkResponse(
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder:
(
context,
) => TechnicianTrackingScreen(
details:
serviceData!,
from: "Single",
complaintData:complaintData
),
),
);
},
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(
0xFFFFFFFF,
),
Color(
0xFFFFFFFF,
),
Color(
0xFFFFFFFF,
),
Color(
0xFFFFFFFF,
).withOpacity(
0.8,
),
Color(
0xFFFFFFFF,
).withOpacity(
0.5,
),
Color(
0xFFFFFFFF,
).withOpacity(
0.1,
),
Color(
0xFFFFFFFF,
).withOpacity(
0.01,
),
],
begin:
Alignment
.bottomCenter,
end:
Alignment
.topCenter,
),
),
padding:
EdgeInsets.symmetric(
vertical:
10,
),
child: Center(
child: Text(
"Tap to Track Engineer",
textAlign:
TextAlign
.center,
style: TextStyle(
fontSize:
14,
color:
AppColors
.buttonColor,
),
),
),
),
),
Align(
alignment:
Alignment
.bottomCenter,
child: Container(
height: 60,
padding:
EdgeInsets.symmetric(
horizontal:
0,
vertical:
10,
),
decoration: BoxDecoration(
color: Color(
0xFFE8F6FF,
),
borderRadius:
BorderRadius.circular(
18,
),
),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Expanded(
flex: 1,
child: CircleAvatar(
radius:
25,
backgroundImage:
serviceData?.profileImg ==
"https://erp.gengroup.in/"
? AssetImage(
"assets/images/user_img.png",
)
: NetworkImage(
"${serviceData?.profileImg}",
),
),
),
Expanded(
flex: 3,
child: SizedBox(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"${serviceData?.empName}",
maxLines:
2,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color:
AppColors.nearDarkText,
fontSize:
14,
),
),
Text(
"${serviceData?.techRoleName}",
maxLines:
1,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color:
AppColors.subtitleText,
fontSize:
12,
),
),
],
),
),
),
Expanded(
flex: 1,
child: SizedBox(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
InkResponse(
onTap: () async {
var url =
"tel:${serviceData?.mobNum}";
if (await canLaunch(
url,
)) {
await launch(
url,
);
} else {
throw 'Could not launch $url';
}
},
child: Image.asset(
"assets/images/call_technicain_ic.png",
fit:
BoxFit.cover,
height:
40,
width:
40,
),
),
],
),
),
),
],
),
),
),
],
),
),
),
),
],
);
},
),
),
),
] else ...[
...List.generate(serviceHeadings.length, (
i,
) {
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 3,
),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
serviceSubHeadings[i].isEmpty
? "-"
: serviceSubHeadings[i] ??
"-",
maxLines: 2,
overflow:
TextOverflow.ellipsis,
textAlign: TextAlign.end,
style: TextStyle(
serviceHeadings[i] ?? "-",
style: const TextStyle(
fontSize: 14,
color:
(serviceHeadings[i] ==
"FSR File")
? AppColors
.buttonColor
: AppColors
.nearDarkText,
decoration:
(serviceHeadings[i] ==
"FSR File")
? TextDecoration
.underline
: TextDecoration
.none,
decorationColor:
(serviceHeadings[i] ==
"FSR File")
? AppColors
.buttonColor
: AppColors
.nearDarkText,
AppColors.subtitleText,
),
),
),
),
],
),
);
}),
SizedBox(height: 5),
Container(
padding: EdgeInsets.symmetric(
horizontal: 0,
vertical: 15,
),
decoration: BoxDecoration(
color: Color(0xFFE8F6FF),
borderRadius: BorderRadius.circular(16),
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 1,
child: CircleAvatar(
backgroundImage:
serviceData?.profileImg ==
"https://erp.gengroup.in/"
? AssetImage(
"assets/images/user_img.png",
)
: NetworkImage(
"${serviceData?.profileImg}",
),
),
),
Expanded(
flex: 3,
child: SizedBox(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"${serviceData?.empName}",
Expanded(
child: InkResponse(
onTap:
serviceHeadings[i] ==
"FSR File" &&
(serviceData
?.fsrFilePath !=
null)
? () async {
await Navigator.push(
context,
MaterialPageRoute(
builder:
(
context,
) => Fileviewer(
fileName:
serviceData
?.fsrExt ??
"-",
fileUrl:
serviceData
?.fsrFilePath ??
"-",
),
),
);
}
: null,
child: Text(
serviceSubHeadings[i]
.isEmpty
? "-"
: serviceSubHeadings[i] ??
"-",
maxLines: 2,
overflow:
TextOverflow.ellipsis,
TextOverflow.ellipsis,
textAlign: TextAlign.end,
style: TextStyle(
color:
AppColors
.nearDarkText,
fontSize: 14,
),
),
Text(
"${serviceData?.techRoleName}",
maxLines: 1,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color:
AppColors
.subtitleText,
fontSize: 12,
(serviceHeadings[i] ==
"FSR File")
? AppColors
.buttonColor
: AppColors
.nearDarkText,
decoration:
(serviceHeadings[i] ==
"FSR File")
? TextDecoration
.underline
: TextDecoration
.none,
decorationColor:
(serviceHeadings[i] ==
"FSR File")
? AppColors
.buttonColor
: AppColors
.nearDarkText,
),
),
],
),
),
),
],
),
Expanded(
flex: 3,
child: SizedBox(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment
.center,
children: List.generate(
provider
.starStates
.length,
(index) => InkWell(
onTap:
serviceData?.rating !=
"0"
? null
: () {
provider.rating =
index + 1;
for (
int i = 0;
i <
provider
.starStates
.length;
i++
) {
provider.starStates[i] =
i <=
index;
);
}),
],
if (serviceData?.openStatus ==
"Closed") ...[
SizedBox(height: 5),
Container(
padding: EdgeInsets.symmetric(
horizontal: 0,
vertical: 10,
),
decoration: BoxDecoration(
color: Color(0xFFE8F6FF),
borderRadius: BorderRadius.circular(
18,
),
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 1,
child: CircleAvatar(
radius: 25,
backgroundImage:
serviceData?.profileImg ==
"https://erp.gengroup.in/"
? AssetImage(
"assets/images/user_img.png",
)
: NetworkImage(
"${serviceData?.profileImg}",
),
),
),
Expanded(
flex: 3,
child: SizedBox(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"${serviceData?.empName}",
maxLines: 2,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color:
AppColors
.nearDarkText,
fontSize: 14,
),
),
Text(
"${serviceData?.techRoleName}",
maxLines: 1,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color:
AppColors
.subtitleText,
fontSize: 12,
),
),
],
),
),
),
Expanded(
flex:
serviceData?.openStatus ==
"Open"
? 1
: 3,
child: SizedBox(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
if (serviceData
?.openStatus ==
"Open") ...[
InkResponse(
onTap: () async {
var url =
"tel:${serviceData?.mobNum}";
if (await canLaunch(
url,
)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
provider
.notifyListeners();
provider.updateRatingForTechnician(
widget
.accId,
widget
.sessionId,
widget
.complaintId,
provider
.rating,
);
},
child: Row(
children: [
Icon(
Icons
.star_rate_rounded,
color:
provider.starStates[index]
? Color(
0xffFFB703,
)
: Color(
0xffCECECE,
),
size: 25,
child: Image.asset(
"assets/images/call_technicain_ic.png",
fit: BoxFit.cover,
height: 40,
width: 40,
),
),
] else ...[
Row(
mainAxisAlignment:
MainAxisAlignment
.center,
children: List.generate(
provider
.starStates
.length,
(index) => InkWell(
onTap:
serviceData?.rating !=
"0"
? null
: () {
provider.rating =
index +
1;
for (
int i =
0;
i <
provider.starStates.length;
i++
) {
provider.starStates[i] =
i <=
index;
}
provider
.notifyListeners();
provider.updateRatingForTechnician(
widget
.accId,
widget
.sessionId,
widget
.complaintId,
provider
.rating,
);
},
child: Row(
children: [
Icon(
Icons
.star_rate_rounded,
color:
provider.starStates[index]
? Color(
0xffFFB703,
)
: Color(
0xffCECECE,
),
size: 25,
),
],
),
],
),
),
),
),
),
Text(
"Your Rating",
maxLines: 1,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color:
AppColors
.subtitleText,
fontSize: 12,
),
),
],
Text(
"Your Rating",
maxLines: 1,
overflow:
TextOverflow
.ellipsis,
style: TextStyle(
color:
AppColors
.subtitleText,
fontSize: 12,
),
),
],
],
),
),
),
),
],
],
),
),
),
],
],
),
),
......@@ -994,57 +1450,6 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
);
}
Widget sectionHeading(text) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
text,
style: TextStyle(color: AppColors.nearDarkText, fontSize: 14),
),
if (text != "Complaint Details") ...[
InkResponse(
onTap: () async {
var redirectScreen;
switch (text) {
case "Job Cards":
redirectScreen = Jobcardlistscreen(
accId: widget.accId,
sessionId: widget.sessionId,
complaintId: widget.complaintId,
);
break;
case "Service Details":
redirectScreen = serviceListScreen(
accId: widget.accId,
sessionId: widget.sessionId,
complaintId: widget.complaintId,
);
break;
default:
break;
}
await Navigator.push(
context,
MaterialPageRoute(builder: (context) => redirectScreen),
);
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
"See All",
style: TextStyle(color: AppColors.buttonColor, fontSize: 14),
),
),
),
],
],
),
);
}
Future<void> _showJobCardProductSheet(context) {
return showModalBottomSheet(
useSafeArea: true,
......@@ -1139,8 +1544,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
return Padding(
padding: EdgeInsets.symmetric(vertical: 5),
child: Row(
mainAxisAlignment:
MainAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
flex: 3,
......@@ -1372,9 +1776,9 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
child: ElevatedButton(
onPressed: () {
double enteredAmount =
isPartPayment
? double.tryParse(amountController.text) ?? 0
: totalAmount;
isPartPayment
? double.tryParse(amountController.text) ?? 0
: totalAmount;
if (enteredAmount <= 0) {
ScaffoldMessenger.of(context).showSnackBar(
......
import 'dart:io';
import 'dart:ui';
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:flutter/material.dart';
import 'package:gen_service/Models/HelpAndComplaintModels/allServiceListResponse.dart';
import 'package:gen_service/Notifiers/technicianTrackingProvider.dart';
import 'package:gen_service/Services/api_calling.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import '../../Models/HelpAndComplaintModels/complaintDetailsResponse.dart';
import '../../Utility/AppColors.dart';
class TechnicianTrackingScreen extends StatefulWidget {
final ServiceDetails? details;
final AllServiceList? allDet;
final String from;
final ComplaintDetails? complaintData;
const TechnicianTrackingScreen({
super.key,
this.details,
this.allDet,
required this.from,
required this.complaintData,
});
@override
_TechnicianTrackingScreenState createState() =>
_TechnicianTrackingScreenState();
}
class _TechnicianTrackingScreenState extends State<TechnicianTrackingScreen> {
var serviceData;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
final mapProvider = Provider.of<Techniciantrackingprovider>(
context,
listen: false,
);
mapProvider.getLocationPermission(context);
mapProvider.polylinePoints = PolylinePoints(
apiKey: "AIzaSyAA2ukvrb1kWQZ2dttsNIMynLJqVCYYrhw",
);
if (widget.from == "All") {
serviceData = widget.allDet;
} else {
serviceData = widget.details;
}
});
// InitialPorterFunction();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
return SafeArea(
top: false,
bottom: Platform.isIOS ? false : true,
maintainBottomViewPadding: true,
child: Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: Color(0xFF4076FF),
body: Consumer<Techniciantrackingprovider>(
builder: (context, mapProvider, child) {
return CustomScrollView(
slivers: [
SliverAppBar(
automaticallyImplyLeading: false,
stretch: true,
onStretchTrigger: () async {},
stretchTriggerOffset: 300.0,
backgroundColor: Color(0xFF4076FF),
expandedHeight: screenHeight * 0.15,
flexibleSpace: FlexibleSpaceBar(
stretchModes: const [
StretchMode.zoomBackground,
StretchMode.blurBackground,
],
background: Container(
decoration: const BoxDecoration(
gradient: AppColors.commonAppBarGradient,
),
child: SafeArea(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(width: 8),
InkResponse(
onTap: () {
HapticFeedback.selectionClick();
Navigator.pop(context, true);
},
child: SvgPicture.asset(
"assets/svg/appbar_back.svg",
height: 25,
),
),
SizedBox(width: 10),
Expanded(
flex: 4,
child: InkResponse(
onTap: () {
HapticFeedback.selectionClick();
Navigator.pop(context, true);
},
child: Text(
"Track Technician",
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
fontSize: 16,
color: Colors.white,
height: 1.1,
),
),
),
),
],
),
SizedBox(height: 10),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 5,
),
child: Column(
children: [
// Product Info Row
Padding(
padding: const EdgeInsets.symmetric(
vertical: 4.0,
),
child: Row(
children: [
Expanded(
flex: 5,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
style: const TextStyle(
fontFamily: 'Poppins',
color: Color(0xFF48F3FF),
fontSize: 12,
),
children: [
TextSpan(
text:
"#${widget.complaintData?.id!}",
),
TextSpan(
text:
(widget.complaintData?.complaintName ??
"")
.isNotEmpty
? " | ${widget.complaintData?.complaintName!}"
: "",
),
],
),
),
Text(
"${widget.complaintData?.registredDate ?? ""}",
maxLines: 2,
style: const TextStyle(
color: Colors.white,
fontSize: 14,
),
),
],
),
),
Expanded(
flex: 2,
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 15,
vertical: 7,
),
decoration: BoxDecoration(
color:
widget
.complaintData
?.openStatus ==
"Open"
? AppColors.successBG
: AppColors.yellowBG,
borderRadius:
BorderRadius.circular(10),
),
child: Center(
child: Text(
"${widget.complaintData?.openStatus}",
style: TextStyle(
fontFamily: "Poppins",
fontSize: 14,
fontWeight: FontWeight.w400,
color:
widget
.complaintData
?.openStatus ==
"Open"
? AppColors.success
: AppColors
.normalText,
),
),
),
),
),
],
),
),
],
),
),
],
),
),
),
),
),
SliverFillRemaining(
hasScrollBody: false,
child: Container(
decoration: const BoxDecoration(
color: AppColors.backgroundRegular,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
padding: const EdgeInsets.symmetric(
horizontal: 5,
vertical: 0,
),
child: Column(
children: [
Container(
margin: const EdgeInsets.symmetric(
horizontal: 0,
vertical: 5,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18),
),
height: screenHeight * 0.8,
child: ClipRRect(
borderRadius: BorderRadius.circular(18),
child: GoogleMap(
myLocationEnabled: true,
zoomGesturesEnabled: true,
zoomControlsEnabled: true,
scrollGesturesEnabled: false,
gestureRecognizers: {
Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(),
),
Factory<PanGestureRecognizer>(
() => PanGestureRecognizer(),
),
Factory<ScaleGestureRecognizer>(
() => ScaleGestureRecognizer(),
),
},
initialCameraPosition: CameraPosition(
target:
mapProvider.currentLocation != null
? LatLng(
mapProvider
.currentLocation!
.latitude!,
mapProvider
.currentLocation!
.longitude!,
)
: mapProvider.startLocation,
zoom: 15,
),
myLocationButtonEnabled: false,
mapType: MapType.normal,
markers: mapProvider.markers,
polylines: mapProvider.polylines,
onMapCreated: (GoogleMapController controller) {
mapProvider.mapController = controller;
mapProvider.setMapStyle(controller);
final double? techLat1 = 17.4484769;
final double? techLng1 = 78.3710461;
final double? techLat = double.tryParse(
serviceData?.lat?.trim() ?? '${techLat1}',
)??techLat1;
final double? techLng = double.tryParse(
serviceData?.lng?.trim() ?? '${techLng1}',
)??techLng1;
if (techLat != null &&
techLng != null &&
techLat != 0 &&
techLng != 0) {
mapProvider.updateTechnicianLocation(
techLat,
techLng,
);
}
},
),
),
),
],
),
),
),
],
);
},
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: Container(
alignment: Alignment.center,
height: 80,
width: screenWidth,
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 10),
margin: EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Color(0xFF008CDE),
borderRadius: BorderRadius.circular(50),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: CircleAvatar(
radius: 25,
backgroundImage:
serviceData?.profileImg == "https://erp.gengroup.in/"
? AssetImage("assets/images/user_img.png")
: NetworkImage("${serviceData?.profileImg}"),
),
),
Expanded(
flex: 3,
child: SizedBox(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${serviceData?.empName}",
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.white,
fontSize: 14,
),
),
Text(
"${serviceData?.techRoleName}",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.white,
fontSize: 12,
),
),
],
),
),
),
Expanded(
flex: 1,
child: SizedBox(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkResponse(
onTap: () async {
var url = "tel:${serviceData?.mobNum}";
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
},
child: Image.asset(
"assets/images/call_technicain_ic.png",
fit: BoxFit.cover,
height: 40,
width: 40,
),
),
],
),
),
),
],
),
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:flutter_svg/svg.dart';
import 'package:gen_service/Notifiers/technicianTrackingProvider.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../Notifiers/serviceAndJobCardListProvier.dart';
import '../../Utility/AppColors.dart';
import '../FileViewer.dart';
import 'TechnicianTrackingScreen.dart';
class serviceListScreen extends StatefulWidget {
final accId;
final sessionId;
final complaintId;
final complaintData;
const serviceListScreen({
super.key,
required this.accId,
required this.sessionId,
required this.complaintId,
required this.complaintId, this.complaintData,
});
@override
......@@ -38,6 +44,14 @@ class _serviceListScreenState extends State<serviceListScreen> {
widget.sessionId,
widget.complaintId,
);
final mapProvider = Provider.of<Techniciantrackingprovider>(
context,
listen: false,
);
mapProvider.getLocationPermission(context);
mapProvider.polylinePoints = PolylinePoints(
apiKey: "AIzaSyAA2ukvrb1kWQZ2dttsNIMynLJqVCYYrhw",
);
});
}
......@@ -205,84 +219,434 @@ class _serviceListScreenState extends State<serviceListScreen> {
),
child: Column(
children: [
...List.generate(serviceHeadings.length, (
i,
) {
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 3,
if (data[j]?.openStatus == "Open") ...[
Container(
height: 220,
margin: const EdgeInsets.symmetric(
horizontal: 5,
vertical: 10,
),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
serviceHeadings[i] ?? "-",
style: const TextStyle(
fontSize: 14,
color: AppColors.subtitleText,
),
),
),
Expanded(
child: InkResponse(
onTap:
serviceHeadings[i] ==
"FSR File"
? () async {
await Navigator.push(
context,
MaterialPageRoute(
builder:
(context,) => Fileviewer(
fileName: data[j]?.fsrExt ?? "-",
fileUrl: data[j]?.filePath ?? "-",
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
18,
),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(
18,
),
child: Consumer<
Techniciantrackingprovider
>(
builder: (
context,
mapProvider,
child,
) {
return Stack(
clipBehavior: Clip.none,
children: [
GoogleMap(
initialCameraPosition: CameraPosition(
target:
mapProvider.currentLocation !=
null
? LatLng(
mapProvider
.currentLocation!
.latitude!,
mapProvider
.currentLocation!
.longitude!,
)
: mapProvider
.startLocation,
zoom: 15,
),
myLocationEnabled: true,
myLocationButtonEnabled:
false,
zoomControlsEnabled: false,
mapType: MapType.normal,
markers:
mapProvider.markers,
polylines:
mapProvider.polylines,
onMapCreated: (
GoogleMapController
controller,
) {
mapProvider
.mapController =
controller;
mapProvider.setMapStyle(
controller,
);
final double? techLat1 = 17.4484769;
final double? techLng1 = 78.3710461;
final double? techLat = double.tryParse(
data[j]?.lat?.trim() ?? '${techLat1}',
)??techLat1;
final double? techLng = double.tryParse(
data[j]?.lng?.trim() ?? '${techLng1}',
)??techLng1;
if (techLat != null &&
techLng != null &&
techLat != 0 &&
techLng != 0) {
mapProvider
.updateTechnicianLocation(
techLat,
techLng,
);
}
},
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Align(
alignment:
Alignment
.bottomCenter,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(
0xFFFFFFFF,
).withOpacity(
0.01,
),
Color(0xFFFFFFFF),
Color(0xFFFFFFFF),
Color(
0xFFFFFFFF,
).withOpacity(
0.01,
),
],
begin:
Alignment
.bottomCenter,
end:
Alignment
.topCenter,
),
),
child: Column(
children: [
InkResponse(
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder:
(
context,
) => TechnicianTrackingScreen(
allDet:
data[j],
from: "All",
complaintData: widget.complaintData,
),
),
);
},
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(
0xFFFFFFFF,
),
Color(
0xFFFFFFFF,
),
Color(
0xFFFFFFFF,
),
Color(
0xFFFFFFFF,
).withOpacity(
0.8,
),
Color(
0xFFFFFFFF,
).withOpacity(
0.5,
),
Color(
0xFFFFFFFF,
).withOpacity(
0.1,
),
Color(
0xFFFFFFFF,
).withOpacity(
0.01,
),
],
begin:
Alignment
.bottomCenter,
end:
Alignment
.topCenter,
),
),
padding:
EdgeInsets.symmetric(
vertical:
10,
),
child: Center(
child: Text(
"Tap to Track Engineer",
textAlign:
TextAlign
.center,
style: TextStyle(
fontSize:
14,
color:
AppColors
.buttonColor,
),
),
),
),
),
);
}
: null,
Align(
alignment:
Alignment
.bottomCenter,
child: Container(
height: 60,
padding:
EdgeInsets.symmetric(
horizontal:
0,
vertical:
10,
),
decoration: BoxDecoration(
color: Color(
0xFFE8F6FF,
),
borderRadius:
BorderRadius.circular(
18,
),
),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Expanded(
flex: 1,
child: CircleAvatar(
radius:
25,
backgroundImage:
data[j]?.profileImg ==
"https://erp.gengroup.in/"
? AssetImage(
"assets/images/user_img.png",
)
: NetworkImage(
"${data[j]?.profileImg}",
),
),
),
Expanded(
flex: 3,
child: SizedBox(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"${data[j]?.empName}",
maxLines:
2,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color:
AppColors.nearDarkText,
fontSize:
14,
),
),
Text(
"${data[j]?.techRoleName}",
maxLines:
1,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color:
AppColors.subtitleText,
fontSize:
12,
),
),
],
),
),
),
Expanded(
flex: 1,
child: SizedBox(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
InkResponse(
onTap: () async {
var url =
"tel:${data[j]?.mobNum}";
if (await canLaunch(
url,
)) {
await launch(
url,
);
} else {
throw 'Could not launch $url';
}
},
child: Image.asset(
"assets/images/call_technicain_ic.png",
fit:
BoxFit.cover,
height:
40,
width:
40,
),
),
],
),
),
),
],
),
),
),
],
),
),
),
),
],
);
},
),
),
),
] else ...[
...List.generate(serviceHeadings.length, (
i,
) {
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 3,
),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
serviceSubHeadings[i].isEmpty
? "-"
: serviceSubHeadings[i] ??
"-",
maxLines: 2,
overflow:
TextOverflow.ellipsis,
textAlign: TextAlign.end,
style: TextStyle(
serviceHeadings[i] ?? "-",
style: const TextStyle(
fontSize: 14,
color:
(serviceHeadings[i] ==
"FSR File")
? AppColors
.buttonColor
: AppColors
.nearDarkText,
decoration:
(serviceHeadings[i] ==
"FSR File")
? TextDecoration
.underline
: TextDecoration
.none,
decorationColor:
(serviceHeadings[i] ==
"FSR File")
? AppColors
.buttonColor
: AppColors
.nearDarkText,
AppColors.subtitleText,
),
),
),
),
],
),
);
}),
Expanded(
child: InkResponse(
onTap:
serviceHeadings[i] ==
"FSR File"
? () async {
await Navigator.push(
context,
MaterialPageRoute(
builder:
(
context,
) => Fileviewer(
fileName:
data[j]
?.fsrExt ??
"-",
fileUrl:
data[j]
?.filePath ??
"-",
),
),
);
}
: null,
child: Text(
serviceSubHeadings[i]
.isEmpty
? "-"
: serviceSubHeadings[i] ??
"-",
maxLines: 2,
overflow:
TextOverflow.ellipsis,
textAlign: TextAlign.end,
style: TextStyle(
fontSize: 14,
color:
(serviceHeadings[i] ==
"FSR File")
? AppColors
.buttonColor
: AppColors
.nearDarkText,
decoration:
(serviceHeadings[i] ==
"FSR File")
? TextDecoration
.underline
: TextDecoration
.none,
decorationColor:
(serviceHeadings[i] ==
"FSR File")
? AppColors
.buttonColor
: AppColors
.nearDarkText,
),
),
),
),
],
),
);
}),
],
SizedBox(height: 5),
Container(
padding: EdgeInsets.symmetric(
......@@ -372,41 +736,42 @@ class _serviceListScreenState extends State<serviceListScreen> {
serviceId,
);
return InkWell(
onTap: data[j]?.customerServiceRating !=
"0"
? null
: () async {
final newRating =
index + 1;
onTap:
data[j]?.customerServiceRating !=
"0"
? null
: () async {
final newRating =
index + 1;
provider.setRating(
serviceId,
newRating,
);
provider.setRating(
serviceId,
newRating,
);
ScaffoldMessenger.of(
context,
).showSnackBar(
SnackBar(
content: Text(
"Submitting rating...",
),
duration:
Duration(
seconds: 1,
),
),
);
ScaffoldMessenger.of(
context,
).showSnackBar(
SnackBar(
content: Text(
"Submitting rating...",
),
duration: Duration(
seconds:
1,
),
),
);
await provider
.updateRatingForTechnician(
widget.accId,
widget
.sessionId,
serviceId,
newRating,
);
},
await provider.updateRatingForTechnician(
widget
.accId,
widget
.sessionId,
serviceId,
newRating,
);
},
child: Padding(
padding:
const EdgeInsets.symmetric(
......
......@@ -11,7 +11,7 @@ import 'package:gen_service/Screens/HelpAndComplaintScreens/SelectOrderHelpScree
import 'package:gen_service/Screens/HelpAndComplaintScreens/ComplaintListScreen.dart';
import 'package:gen_service/Screens/ProfileScreen.dart';
import 'package:gen_service/Screens/TransactionScreens/TransactionListScreen.dart';
import 'package:gen_service/Screens/TransactionScreens/contactMap.dart';
import 'package:gen_service/Screens/HelpAndComplaintScreens/contactMap.dart';
import 'package:provider/provider.dart';
import 'package:razorpay_flutter/razorpay_flutter.dart';
......
......@@ -156,4 +156,15 @@ class AppColors {
Color(0xFF4076FF),
],
);
static LinearGradient whiteGradient = LinearGradient(
colors: [
Color(0xFFFFFFFF).withOpacity(0.0),
Color(0xFFFFFFFF),
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
);
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ import 'package:gen_service/Notifiers/AuthProvider.dart';
import 'package:gen_service/Notifiers/TransactionsProvider.dart';
import 'package:gen_service/Notifiers/mapProvider.dart';
import 'package:gen_service/Notifiers/serviceAndJobCardListProvier.dart';
import 'package:gen_service/Notifiers/technicianTrackingProvider.dart';
import 'package:provider/provider.dart';
import 'Notifiers/ContactUsProvider.dart';
......@@ -35,8 +36,8 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => ContactUsProvider()),
ChangeNotifierProvider(create: (_) => ServiceAndJobCardListProvider()),
ChangeNotifierProvider(create: (_) => MapProvider()),
ChangeNotifierProvider(create: (_) => PayAmountProvider()),
ChangeNotifierProvider(create: (_) => Techniciantrackingprovider()),
],
child: Consumer<ThemeProvider>(
builder: (context, themeProvider, child) {
......
......@@ -358,6 +358,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.31"
flutter_polyline_points:
dependency: "direct main"
description:
name: flutter_polyline_points
sha256: c775fe59fbcf1f925d611c039555c7f58ed6d9411747b7a2915bbd9c5e730a51
url: "https://pub.dev"
source: hosted
version: "3.1.0"
flutter_svg:
dependency: "direct main"
description:
......
......@@ -61,6 +61,7 @@ dependencies:
flutter_local_notifications: ^19.5.0
flutter_download_manager: ^0.5.5
intl: ^0.20.2
flutter_polyline_points: ^3.1.0
dev_dependencies:
flutter_test:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment