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 { ...@@ -82,6 +82,8 @@ class TechDetails {
class AllServiceList { class AllServiceList {
String? id; String? id;
String? lat;
String? lng;
String? empName; String? empName;
String? date; String? date;
String? techRoleName; String? techRoleName;
...@@ -92,12 +94,14 @@ class AllServiceList { ...@@ -92,12 +94,14 @@ class AllServiceList {
String? customerServiceRating; String? customerServiceRating;
String? inOrOutTime; String? inOrOutTime;
String? runningHrs; String? runningHrs;
String? fsrExt;
String? filePath; String? filePath;
String? fsrExt;
String? fsrNo; String? fsrNo;
AllServiceList( AllServiceList(
{this.id, {this.id,
this.lat,
this.lng,
this.empName, this.empName,
this.date, this.date,
this.techRoleName, this.techRoleName,
...@@ -108,12 +112,14 @@ class AllServiceList { ...@@ -108,12 +112,14 @@ class AllServiceList {
this.customerServiceRating, this.customerServiceRating,
this.inOrOutTime, this.inOrOutTime,
this.runningHrs, this.runningHrs,
this.fsrExt,
this.filePath, this.filePath,
this.fsrExt,
this.fsrNo}); this.fsrNo});
AllServiceList.fromJson(Map<String, dynamic> json) { AllServiceList.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
lat = json['lat'];
lng = json['lng'];
empName = json['emp_name']; empName = json['emp_name'];
date = json['date']; date = json['date'];
techRoleName = json['tech_role_name']; techRoleName = json['tech_role_name'];
...@@ -124,14 +130,16 @@ class AllServiceList { ...@@ -124,14 +130,16 @@ class AllServiceList {
customerServiceRating = json['customer_service_rating']; customerServiceRating = json['customer_service_rating'];
inOrOutTime = json['in_or_out_time']; inOrOutTime = json['in_or_out_time'];
runningHrs = json['running_hrs']; runningHrs = json['running_hrs'];
fsrExt = json['fsr_ext'];
filePath = json['file_path']; filePath = json['file_path'];
fsrExt = json['fsr_ext'];
fsrNo = json['fsr_no']; fsrNo = json['fsr_no'];
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>(); final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id; data['id'] = this.id;
data['lat'] = this.lat;
data['lng'] = this.lng;
data['emp_name'] = this.empName; data['emp_name'] = this.empName;
data['date'] = this.date; data['date'] = this.date;
data['tech_role_name'] = this.techRoleName; data['tech_role_name'] = this.techRoleName;
...@@ -142,8 +150,8 @@ class AllServiceList { ...@@ -142,8 +150,8 @@ class AllServiceList {
data['customer_service_rating'] = this.customerServiceRating; data['customer_service_rating'] = this.customerServiceRating;
data['in_or_out_time'] = this.inOrOutTime; data['in_or_out_time'] = this.inOrOutTime;
data['running_hrs'] = this.runningHrs; data['running_hrs'] = this.runningHrs;
data['fsr_ext'] = this.fsrExt;
data['file_path'] = this.filePath; data['file_path'] = this.filePath;
data['fsr_ext'] = this.fsrExt;
data['fsr_no'] = this.fsrNo; data['fsr_no'] = this.fsrNo;
return data; 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'; ...@@ -2,14 +2,21 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.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:flutter_svg/svg.dart';
import 'package:gen_service/Notifiers/HelpAndComplaintProvider.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/FileViewer.dart';
import 'package:gen_service/Screens/HelpAndComplaintScreens/TechnicianTrackingScreen.dart';
import 'package:gen_service/Screens/HelpAndComplaintScreens/jobcardListScreen.dart'; import 'package:gen_service/Screens/HelpAndComplaintScreens/jobcardListScreen.dart';
import 'package:gen_service/Screens/HelpAndComplaintScreens/serviceListScreen.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:provider/provider.dart';
import 'package:razorpay_flutter/razorpay_flutter.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 '../../Notifiers/PayAmountProvider.dart';
import '../../Utility/AppColors.dart'; import '../../Utility/AppColors.dart';
import '../../Utility/CustomSnackbar.dart'; import '../../Utility/CustomSnackbar.dart';
...@@ -55,6 +62,15 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -55,6 +62,15 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
widget.sessionId, widget.sessionId,
widget.complaintId, 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> { ...@@ -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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<HelpAndComplaintProvider>( return Consumer<HelpAndComplaintProvider>(
...@@ -400,9 +468,9 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -400,9 +468,9 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
child: SizedBox( child: SizedBox(
child: Row( child: Row(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.start, MainAxisAlignment.start,
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.center, CrossAxisAlignment.center,
children: [ children: [
InkResponse( InkResponse(
onTap: () { onTap: () {
...@@ -447,7 +515,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -447,7 +515,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
flex: 5, flex: 5,
child: Column( child: Column(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: [ children: [
RichText( RichText(
text: TextSpan( text: TextSpan(
...@@ -459,15 +527,15 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -459,15 +527,15 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
children: [ children: [
TextSpan( TextSpan(
text: text:
"#${complaintData?.id!}", "#${complaintData?.id!}",
), ),
TextSpan( TextSpan(
text: text:
(complaintData?.complaintName ?? (complaintData?.complaintName ??
"") "")
.isNotEmpty .isNotEmpty
? " | ${complaintData?.complaintName!}" ? " | ${complaintData?.complaintName!}"
: "", : "",
), ),
], ],
), ),
...@@ -492,10 +560,10 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -492,10 +560,10 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: color:
complaintData?.openStatus == complaintData?.openStatus ==
"Open" "Open"
? AppColors.successBG ? AppColors.successBG
: AppColors.yellowBG, : AppColors.yellowBG,
borderRadius: BorderRadius.circular( borderRadius: BorderRadius.circular(
10, 10,
), ),
...@@ -508,10 +576,10 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -508,10 +576,10 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: color:
complaintData?.openStatus == complaintData?.openStatus ==
"Open" "Open"
? AppColors.success ? AppColors.success
: AppColors.normalText, : AppColors.normalText,
), ),
), ),
), ),
...@@ -565,7 +633,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -565,7 +633,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
flex: 5, flex: 5,
child: Column( child: Column(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"${jobCardsData?.date}", "${jobCardsData?.date}",
...@@ -578,53 +646,53 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -578,53 +646,53 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
SizedBox(height: 4), SizedBox(height: 4),
Row( Row(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.start, MainAxisAlignment.start,
children: [ children: [
Text( Text(
"Job Card", "Job Card",
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: color:
AppColors AppColors
.nearDarkText, .nearDarkText,
), ),
), ),
InkResponse( InkResponse(
onTap: onTap:
bottomSheetButtonClicked bottomSheetButtonClicked
? null ? null
: () { : () {
HapticFeedback.mediumImpact(); HapticFeedback.mediumImpact();
setState(() { setState(() {
bottomSheetButtonClicked = bottomSheetButtonClicked =
true; true;
}); });
provider.fetchJobCardProductDetails( provider.fetchJobCardProductDetails(
widget.accId, widget.accId,
widget widget
.sessionId, .sessionId,
jobCardsData! jobCardsData!
.id, .id,
); );
Future.delayed( Future.delayed(
Duration( Duration(
milliseconds: milliseconds:
600, 600,
), ),
() { () {
_showJobCardProductSheet( _showJobCardProductSheet(
context, context,
); );
}, },
); );
}, },
child: Text( child: Text(
" ⓘ View Details", " ⓘ View Details",
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: color:
AppColors AppColors
.buttonColor, .buttonColor,
), ),
), ),
), ),
...@@ -655,9 +723,9 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -655,9 +723,9 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
InkResponse( InkResponse(
onTap: onTap:
() => _openPaymentSheet( () => _openPaymentSheet(
context, context,
jobCardsData!.totalPrice.toString(), jobCardsData!.totalPrice.toString(),
), ),
child: Container( child: Container(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
vertical: 16, vertical: 16,
...@@ -703,7 +771,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -703,7 +771,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
), ),
child: Row( child: Row(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
...@@ -747,235 +815,623 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -747,235 +815,623 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
), ),
child: Column( child: Column(
children: [ children: [
...List.generate(serviceHeadings.length, ( if (serviceData?.openStatus ==
i, "Open") ...[
) { Container(
return Padding( height: 220,
padding: const EdgeInsets.symmetric( margin: const EdgeInsets.symmetric(
vertical: 3, horizontal: 5,
vertical: 10,
), ),
child: Row( decoration: BoxDecoration(
crossAxisAlignment: borderRadius: BorderRadius.circular(
CrossAxisAlignment.start, 18,
children: [ ),
Expanded( ),
child: Text( child: ClipRRect(
serviceHeadings[i] ?? "-", borderRadius: BorderRadius.circular(
style: const TextStyle( 18,
fontSize: 14, ),
color: AppColors.subtitleText, child: Consumer<
), Techniciantrackingprovider
), >(
), builder: (
Expanded( context,
child: InkResponse( mapProvider,
onTap: child,
serviceHeadings[i] == "FSR File" && (serviceData?.fsrFilePath != null) ) {
? () async { return Stack(
await Navigator.push( clipBehavior: Clip.none,
context, children: [
MaterialPageRoute( GoogleMap(
builder: (context,) => Fileviewer( initialCameraPosition: CameraPosition(
fileName: serviceData?.fsrExt ?? "-", target:
fileUrl: serviceData?.fsrFilePath ?? "-", 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;
} if (techLat != null &&
: 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( child: Text(
serviceSubHeadings[i].isEmpty serviceHeadings[i] ?? "-",
? "-" style: const TextStyle(
: serviceSubHeadings[i] ??
"-",
maxLines: 2,
overflow:
TextOverflow.ellipsis,
textAlign: TextAlign.end,
style: TextStyle(
fontSize: 14, fontSize: 14,
color: color:
(serviceHeadings[i] == AppColors.subtitleText,
"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(
], child: InkResponse(
), onTap:
); serviceHeadings[i] ==
}), "FSR File" &&
SizedBox(height: 5), (serviceData
Container( ?.fsrFilePath !=
padding: EdgeInsets.symmetric( null)
horizontal: 0, ? () async {
vertical: 15, await Navigator.push(
), context,
decoration: BoxDecoration( MaterialPageRoute(
color: Color(0xFFE8F6FF), builder:
borderRadius: BorderRadius.circular(16), (
), context,
child: Row( ) => Fileviewer(
mainAxisAlignment: fileName:
MainAxisAlignment.spaceBetween, serviceData
children: [ ?.fsrExt ??
Expanded( "-",
flex: 1, fileUrl:
child: CircleAvatar( serviceData
backgroundImage: ?.fsrFilePath ??
serviceData?.profileImg == "-",
"https://erp.gengroup.in/" ),
? AssetImage( ),
"assets/images/user_img.png", );
) }
: NetworkImage( : null,
"${serviceData?.profileImg}", child: Text(
), serviceSubHeadings[i]
), .isEmpty
), ? "-"
Expanded( : serviceSubHeadings[i] ??
flex: 3, "-",
child: SizedBox(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"${serviceData?.empName}",
maxLines: 2, maxLines: 2,
overflow: overflow:
TextOverflow.ellipsis, TextOverflow.ellipsis,
textAlign: TextAlign.end,
style: TextStyle( style: TextStyle(
color:
AppColors
.nearDarkText,
fontSize: 14, fontSize: 14,
),
),
Text(
"${serviceData?.techRoleName}",
maxLines: 1,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color: color:
AppColors (serviceHeadings[i] ==
.subtitleText, "FSR File")
fontSize: 12, ? 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: if (serviceData?.openStatus ==
CrossAxisAlignment.center, "Closed") ...[
mainAxisAlignment: SizedBox(height: 5),
MainAxisAlignment.center, Container(
children: [ padding: EdgeInsets.symmetric(
Row( horizontal: 0,
mainAxisAlignment: vertical: 10,
MainAxisAlignment ),
.center, decoration: BoxDecoration(
children: List.generate( color: Color(0xFFE8F6FF),
provider borderRadius: BorderRadius.circular(
.starStates 18,
.length, ),
(index) => InkWell( ),
onTap: child: Row(
serviceData?.rating != mainAxisAlignment:
"0" MainAxisAlignment.spaceBetween,
? null children: [
: () { Expanded(
provider.rating = flex: 1,
index + 1; child: CircleAvatar(
for ( radius: 25,
int i = 0; backgroundImage:
i < serviceData?.profileImg ==
provider "https://erp.gengroup.in/"
.starStates ? AssetImage(
.length; "assets/images/user_img.png",
i++ )
) { : NetworkImage(
provider.starStates[i] = "${serviceData?.profileImg}",
i <= ),
index; ),
),
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( child: Image.asset(
children: [ "assets/images/call_technicain_ic.png",
Icon( fit: BoxFit.cover,
Icons height: 40,
.star_rate_rounded, width: 40,
color: ),
provider.starStates[index] ),
? Color( ] else ...[
0xffFFB703, Row(
) mainAxisAlignment:
: Color( MainAxisAlignment
0xffCECECE, .center,
), children: List.generate(
size: 25, 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",
Text( maxLines: 1,
"Your Rating", overflow:
maxLines: 1, TextOverflow
overflow: .ellipsis,
TextOverflow.ellipsis, style: TextStyle(
style: TextStyle( color:
color: AppColors
AppColors .subtitleText,
.subtitleText, fontSize: 12,
fontSize: 12, ),
), ),
), ],
], ],
),
), ),
), ),
), ],
], ),
), ),
), ],
], ],
), ),
), ),
...@@ -994,57 +1450,6 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -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) { Future<void> _showJobCardProductSheet(context) {
return showModalBottomSheet( return showModalBottomSheet(
useSafeArea: true, useSafeArea: true,
...@@ -1139,8 +1544,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -1139,8 +1544,7 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
return Padding( return Padding(
padding: EdgeInsets.symmetric(vertical: 5), padding: EdgeInsets.symmetric(vertical: 5),
child: Row( child: Row(
mainAxisAlignment: mainAxisAlignment: MainAxisAlignment.start,
MainAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
flex: 3, flex: 3,
...@@ -1372,9 +1776,9 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> { ...@@ -1372,9 +1776,9 @@ class _ComplaintDetailsScreenState extends State<ComplaintDetailsScreen> {
child: ElevatedButton( child: ElevatedButton(
onPressed: () { onPressed: () {
double enteredAmount = double enteredAmount =
isPartPayment isPartPayment
? double.tryParse(amountController.text) ?? 0 ? double.tryParse(amountController.text) ?? 0
: totalAmount; : totalAmount;
if (enteredAmount <= 0) { if (enteredAmount <= 0) {
ScaffoldMessenger.of(context).showSnackBar( 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/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:flutter_svg/svg.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:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../Notifiers/serviceAndJobCardListProvier.dart'; import '../../Notifiers/serviceAndJobCardListProvier.dart';
import '../../Utility/AppColors.dart'; import '../../Utility/AppColors.dart';
import '../FileViewer.dart'; import '../FileViewer.dart';
import 'TechnicianTrackingScreen.dart';
class serviceListScreen extends StatefulWidget { class serviceListScreen extends StatefulWidget {
final accId; final accId;
final sessionId; final sessionId;
final complaintId; final complaintId;
final complaintData;
const serviceListScreen({ const serviceListScreen({
super.key, super.key,
required this.accId, required this.accId,
required this.sessionId, required this.sessionId,
required this.complaintId, required this.complaintId, this.complaintData,
}); });
@override @override
...@@ -38,6 +44,14 @@ class _serviceListScreenState extends State<serviceListScreen> { ...@@ -38,6 +44,14 @@ class _serviceListScreenState extends State<serviceListScreen> {
widget.sessionId, widget.sessionId,
widget.complaintId, 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> { ...@@ -205,84 +219,434 @@ class _serviceListScreenState extends State<serviceListScreen> {
), ),
child: Column( child: Column(
children: [ children: [
...List.generate(serviceHeadings.length, ( if (data[j]?.openStatus == "Open") ...[
i, Container(
) { height: 220,
return Padding( margin: const EdgeInsets.symmetric(
padding: const EdgeInsets.symmetric( horizontal: 5,
vertical: 3, vertical: 10,
), ),
child: Row( decoration: BoxDecoration(
crossAxisAlignment: borderRadius: BorderRadius.circular(
CrossAxisAlignment.start, 18,
children: [ ),
Expanded( ),
child: Text( child: ClipRRect(
serviceHeadings[i] ?? "-", borderRadius: BorderRadius.circular(
style: const TextStyle( 18,
fontSize: 14, ),
color: AppColors.subtitleText, child: Consumer<
), Techniciantrackingprovider
), >(
), builder: (
Expanded( context,
child: InkResponse( mapProvider,
onTap: child,
serviceHeadings[i] == ) {
"FSR File" return Stack(
? () async { clipBehavior: Clip.none,
await Navigator.push( children: [
context, GoogleMap(
MaterialPageRoute( initialCameraPosition: CameraPosition(
builder: target:
(context,) => Fileviewer( mapProvider.currentLocation !=
fileName: data[j]?.fsrExt ?? "-", null
fileUrl: data[j]?.filePath ?? "-", ? 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,
),
),
),
),
), ),
); Align(
} alignment:
: null, 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( child: Text(
serviceSubHeadings[i].isEmpty serviceHeadings[i] ?? "-",
? "-" style: const TextStyle(
: serviceSubHeadings[i] ??
"-",
maxLines: 2,
overflow:
TextOverflow.ellipsis,
textAlign: TextAlign.end,
style: TextStyle(
fontSize: 14, fontSize: 14,
color: color:
(serviceHeadings[i] == AppColors.subtitleText,
"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(
], 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), SizedBox(height: 5),
Container( Container(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
...@@ -372,41 +736,42 @@ class _serviceListScreenState extends State<serviceListScreen> { ...@@ -372,41 +736,42 @@ class _serviceListScreenState extends State<serviceListScreen> {
serviceId, serviceId,
); );
return InkWell( return InkWell(
onTap: data[j]?.customerServiceRating != onTap:
"0" data[j]?.customerServiceRating !=
? null "0"
: () async { ? null
final newRating = : () async {
index + 1; final newRating =
index + 1;
provider.setRating( provider.setRating(
serviceId, serviceId,
newRating, newRating,
); );
ScaffoldMessenger.of( ScaffoldMessenger.of(
context, context,
).showSnackBar( ).showSnackBar(
SnackBar( SnackBar(
content: Text( content: Text(
"Submitting rating...", "Submitting rating...",
), ),
duration: duration: Duration(
Duration( seconds:
seconds: 1, 1,
), ),
), ),
); );
await provider await provider.updateRatingForTechnician(
.updateRatingForTechnician( widget
widget.accId, .accId,
widget widget
.sessionId, .sessionId,
serviceId, serviceId,
newRating, newRating,
); );
}, },
child: Padding( child: Padding(
padding: padding:
const EdgeInsets.symmetric( const EdgeInsets.symmetric(
......
...@@ -11,7 +11,7 @@ import 'package:gen_service/Screens/HelpAndComplaintScreens/SelectOrderHelpScree ...@@ -11,7 +11,7 @@ import 'package:gen_service/Screens/HelpAndComplaintScreens/SelectOrderHelpScree
import 'package:gen_service/Screens/HelpAndComplaintScreens/ComplaintListScreen.dart'; import 'package:gen_service/Screens/HelpAndComplaintScreens/ComplaintListScreen.dart';
import 'package:gen_service/Screens/ProfileScreen.dart'; import 'package:gen_service/Screens/ProfileScreen.dart';
import 'package:gen_service/Screens/TransactionScreens/TransactionListScreen.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:provider/provider.dart';
import 'package:razorpay_flutter/razorpay_flutter.dart'; import 'package:razorpay_flutter/razorpay_flutter.dart';
......
...@@ -156,4 +156,15 @@ class AppColors { ...@@ -156,4 +156,15 @@ class AppColors {
Color(0xFF4076FF), 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'; ...@@ -3,6 +3,7 @@ import 'package:gen_service/Notifiers/AuthProvider.dart';
import 'package:gen_service/Notifiers/TransactionsProvider.dart'; import 'package:gen_service/Notifiers/TransactionsProvider.dart';
import 'package:gen_service/Notifiers/mapProvider.dart'; import 'package:gen_service/Notifiers/mapProvider.dart';
import 'package:gen_service/Notifiers/serviceAndJobCardListProvier.dart'; import 'package:gen_service/Notifiers/serviceAndJobCardListProvier.dart';
import 'package:gen_service/Notifiers/technicianTrackingProvider.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'Notifiers/ContactUsProvider.dart'; import 'Notifiers/ContactUsProvider.dart';
...@@ -35,8 +36,8 @@ class MyApp extends StatelessWidget { ...@@ -35,8 +36,8 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => ContactUsProvider()), ChangeNotifierProvider(create: (_) => ContactUsProvider()),
ChangeNotifierProvider(create: (_) => ServiceAndJobCardListProvider()), ChangeNotifierProvider(create: (_) => ServiceAndJobCardListProvider()),
ChangeNotifierProvider(create: (_) => MapProvider()), ChangeNotifierProvider(create: (_) => MapProvider()),
ChangeNotifierProvider(create: (_) => PayAmountProvider()), ChangeNotifierProvider(create: (_) => PayAmountProvider()),
ChangeNotifierProvider(create: (_) => Techniciantrackingprovider()),
], ],
child: Consumer<ThemeProvider>( child: Consumer<ThemeProvider>(
builder: (context, themeProvider, child) { builder: (context, themeProvider, child) {
......
...@@ -358,6 +358,14 @@ packages: ...@@ -358,6 +358,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.31" 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: flutter_svg:
dependency: "direct main" dependency: "direct main"
description: description:
......
...@@ -61,6 +61,7 @@ dependencies: ...@@ -61,6 +61,7 @@ dependencies:
flutter_local_notifications: ^19.5.0 flutter_local_notifications: ^19.5.0
flutter_download_manager: ^0.5.5 flutter_download_manager: ^0.5.5
intl: ^0.20.2 intl: ^0.20.2
flutter_polyline_points: ^3.1.0
dev_dependencies: dev_dependencies:
flutter_test: 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