diff --git a/android/app/build.gradle b/android/app/build.gradle index a8d9421..67bde52 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -60,4 +60,6 @@ flutter { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation(platform("com.google.firebase:firebase-bom:32.7.0")) + } diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..96e3c39 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,48 @@ +{ + "project_info": { + "project_number": "60196905754", + "project_id": "health-pharma-67443", + "storage_bucket": "health-pharma-67443.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:60196905754:android:05ea9ecef5280e578a42a3", + "android_client_info": { + "package_name": "com.arminta.healthcare_pharmacy" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC89L-Xg53Bd_mdCPvKOu7BcC9Ya6UZeds" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:60196905754:android:a35c084e291315488a42a3", + "android_client_info": { + "package_name": "com.arminta.healthparma" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC89L-Xg53Bd_mdCPvKOu7BcC9Ya6UZeds" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index bc93226..2914fc7 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -11,6 +11,14 @@ + + + + + + + + _initFCMToken() async { + // Get the stored FCM token + AppSettings.fcmId = await _getStoredFCMToken(); + + // If FCM token is not available, request a new one + if (AppSettings.fcmId.isEmpty) { + await _fcm.getToken().then((token) { + print('FCM Token: $token'); + // Store the FCM token directly in AppSettings + AppSettings.fcmId = token!; + _storeFCMToken(token); + }); + } + } + + Future _storeFCMToken(String token) async { + // Store the FCM token using SharedPreferences + SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setString('fcmToken', token); + } + + Future _getStoredFCMToken() async { + // Retrieve the stored FCM token from SharedPreferences + SharedPreferences prefs = await SharedPreferences.getInstance(); + return prefs.getString('fcmToken') ?? ''; + } + Future initialize() async { + // Request permission for user notifications + await _fcm.requestPermission(); + + // Get the FCM token and handle incoming messages while the app is in the foreground + _fcm.getToken().then((token) { + print('FCM Token: $token'); + // Do something with the token (e.g., send it to your server) + }); + + + + // Listen to incoming messages while the app is in the foreground + FirebaseMessaging.onMessage.listen((RemoteMessage message) { + print("data::::$message"); + // var payload = message.data.toString(); + // // Handle the incoming message + // Map notificationPayload = jsonDecode(payload); + // Access the extra data using the keys + var payload=message.data; + var extramessage; + if(payload.isNotEmpty){ + extramessage = message.data['extraKey1']; + String? extraValue2 = message.data['extraKey2']; + + } + + // Show a local notification with the received message + _showNotification(message.notification?.title, message.notification?.body,extramessage); + }); + + // Handle messages when the app is in the background or terminated + FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { + var payload = message.data.toString(); + if (payload != null) { + // Parse the JSON payload + Map notificationPayload = jsonDecode(payload); + // Access the extra data using the keys + String? extraValue1 = notificationPayload['extraKey1']; + String? extraValue2 = notificationPayload['extraKey2']; + // Do something with the extra data, e.g., display it in a dialog or use it in your app logic. + } + + // Show a local notification with the received message + // _showNotification(message.notification?.title, message.notification?.body); + }); + } + + // Method to show a local notification using flutter_local_notifications + Future _showNotification(String? title, String? body,String extramessage) async { + const AndroidNotificationDetails androidPlatformChannelSpecifics = + AndroidNotificationDetails( + 'healthpharma', // Replace with your channel ID + 'healthpharmanotifications', // Replace with your channel name + importance: Importance.high, + priority: Priority.high, + showWhen: false, + icon: "logo" + + ); + + const NotificationDetails platformChannelSpecifics = + NotificationDetails(android: androidPlatformChannelSpecifics); + Map notificationPayload = { + "body": body, + "title": title, + "extraKey1": extramessage, + "extraKey2": "Extra Value 2", + // Add more key-value pairs as needed + }; + await _flutterLocalNotificationsPlugin.show( + 0, // notification ID (can be any unique ID) + title, // notification title + body, // notification body + platformChannelSpecifics, + payload: jsonEncode(notificationPayload), // optional, you can pass data or identifier related to the notification + ); + } +} diff --git a/lib/biddingrequests.dart b/lib/biddingrequests.dart index 76a6437..9619956 100644 --- a/lib/biddingrequests.dart +++ b/lib/biddingrequests.dart @@ -5,7 +5,10 @@ import 'package:flutter/services.dart'; import 'package:geolocator/geolocator.dart'; import 'package:healthcare_pharmacy/getmedicines.dart'; import 'package:healthcare_pharmacy/models/biddingrequest_model.dart'; +import 'package:healthcare_pharmacy/models/getdeliveryboy_model.dart'; import 'package:healthcare_pharmacy/settings.dart'; +import 'package:flutter_cupertino_datetime_picker/flutter_cupertino_datetime_picker.dart'; +import 'package:intl/intl.dart'; import 'package:image_picker/image_picker.dart'; import 'package:photo_view/photo_view.dart'; @@ -20,6 +23,12 @@ class BiddingRequests extends StatefulWidget { class _BiddingRequestsState extends State { String Url = ''; List prescriptionsList = []; + List modeldeliveryboyList = []; + var dropdownAllDeliveryBoys; + TextEditingController dateController = TextEditingController(); + var selIOS; + + bool isPrescriptionsDataLoading = false; bool isSereverIssue = false; bool isLoading=false; @@ -51,6 +60,7 @@ class _BiddingRequestsState extends State { ((jsonDecode(response)['data']) as List).map((dynamic model) { return BiddingRequestsModel.fromJson(model); }).toList(); + //String customerId=prescriptionsList[0].customerId.toString(); isPrescriptionsDataLoading = false; }); @@ -62,59 +72,86 @@ class _BiddingRequestsState extends State { } } - + Future getAllDeliveryBoys() async { + var response1= await AppSettings.getAllDeliverboy(); + print(response1); + setState(() { + modeldeliveryboyList = + ((jsonDecode(response1)['deliveryBoys']) as List).map((dynamic model) { + return GetDeliveryboyDetailsModel.fromJson(model); + }).toList(); + dropdownAllDeliveryBoys=modeldeliveryboyList[0]; + }); + } @override void initState() { getAllPrescriptions(); + getAllDeliveryBoys(); //getAllPharmaciesData(dropdownArea); super.initState(); } - showPicDialog(var imageUrl){ - return showDialog( + showPicDialog(List prescriptionPictures) { + int currentIndex = 0; + + showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return StatefulBuilder( - builder: (BuildContext context, StateSetter setState) { - return AlertDialog( - title: const Text(''), - content: SingleChildScrollView( - child: ListBody( - children: [ - Container( - width: MediaQuery.of(context).size.width * .10, - height: MediaQuery.of(context).size.height * .50, - child: PhotoView( - imageProvider: NetworkImage(imageUrl) as ImageProvider, - maxScale: PhotoViewComputedScale.contained * 4.0, - minScale: PhotoViewComputedScale.contained, - initialScale: PhotoViewComputedScale.contained, - basePosition: Alignment.center, - - ) - ) - ], - ), + builder: (BuildContext context, StateSetter setState) { + return Dialog( + // Your custom dialog design here + child: Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * 0.6, + child: Column( + children: [ + Expanded( + child: PageView.builder( + itemCount: prescriptionPictures.length, + controller: PageController(initialPage: currentIndex), + onPageChanged: (index) { + setState(() { + currentIndex = index; + }); + }, + itemBuilder: (BuildContext context, int index) { + return Container( + width: double.infinity, + height: double.infinity, + child: PhotoView( + imageProvider: NetworkImage(prescriptionPictures[index].url), + maxScale: PhotoViewComputedScale.contained * 4.0, + minScale: PhotoViewComputedScale.contained, + initialScale: PhotoViewComputedScale.contained, + basePosition: Alignment.center, + ), + ); + }, + ), + ), + TextButton( + child: Text('Close'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], ), - actions: [ - TextButton( - child: Text('Close', style: textButtonStyle()), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ], - ); - }); + ), + ); + }, + ); }, ); } + Widget _allPrescriptions(){ if (prescriptionsList.length != 0) { return Column( @@ -124,13 +161,212 @@ class _BiddingRequestsState extends State { padding: EdgeInsets.all(0), itemCount: prescriptionsList.length, itemBuilder: (BuildContext context, int index) { + return GestureDetector( - onTap: (){ + onTap: () { + // Your regular tap action logic goes here Navigator.push( context, new MaterialPageRoute( - builder: (__) => new GetMedicines(medicinebookingid:prescriptionsList[index].bidding_bookingid))); + builder: (__) => new GetMedicines(medicinebookingid:prescriptionsList[index].bookingId))); + }, + onLongPress: () { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return AlertDialog( + title: const Text('Assign'), + content: SingleChildScrollView( + child: ListBody( + children: [ + Container( + padding: const EdgeInsets.fromLTRB(10, 10, 10, 0), + child: DropdownButtonFormField( + // Initial Value + value: dropdownAllDeliveryBoys, + isExpanded: true, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.water, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Select delivery boy', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + + hint: Text('Select delivery boy'), + // Down Arrow Icon + icon: const Icon(Icons.keyboard_arrow_down), + items: modeldeliveryboyList + .map>( + (value) => new DropdownMenuItem( + value: value, + child: new Text(value.deliveryboy_name), + )) + .toList(), + onChanged: (GetDeliveryboyDetailsModel? newValue) { + setState(() { + dropdownAllDeliveryBoys = newValue; + }); + + }, + ), + ), + + SizedBox( + height: 05, + ), + Container( + padding: const EdgeInsets.all(10), + child: TextFormField( + cursorColor: greyColor, + enabled: false, + controller: dateController, + textCapitalization: TextCapitalization.characters, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.date_range, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Select date & time', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ), + + SizedBox( + height: 05, + ), + + ], + ), + ), + actions: [ + TextButton( + child: Text('cancel', style: textButtonStyle()), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: Text('Assign ', style: textButtonStyle()), + onPressed: () async{ + var payload = new Map(); + payload["pharmacyname"] = + AppSettings.pharmacyName; + payload["pharmacyId"] = + AppSettings.pharmacyId; + payload["customerId"] = + prescriptionsList[index].customerId; + payload["address"] = + prescriptionsList[index] + .address; + payload["dateOfOrder"] = + prescriptionsList[index].bookingId; + payload["action"] = "accept"; + payload["price"] = + prescriptionsList[index].amount; + payload["delivery_agent"] = dropdownAllDeliveryBoys.deliveryboy_name; + payload["agent_mobile"] = dropdownAllDeliveryBoys.deliveryboy_phone; + payload["agent_alternative_mobile"] = dropdownAllDeliveryBoys.deliveryboy_alternativeContactNumber; + payload["expectedDateOfDelivery"] =dateController.text.toString(); + + bool requestStatus = + await AppSettings.assignDeliveryboyBookingRequests( + prescriptionsList[index].bookingId, + payload); + if (requestStatus) { + Navigator.of(context).pop(); + AppSettings.longSuccessToast( + "Delivery Boy Assigned Successfully"); + await getAllPrescriptions(); + } else {} + }, + ), + + + IconButton( + onPressed: () async { + DatePicker.showDatePicker( + context, + dateFormat: 'dd MMMM yyyy HH:mm', + initialDateTime: DateTime.now(), + minDateTime:DateTime.now(), + maxDateTime: DateTime.now().add(Duration(days: 15)), + onMonthChangeStartWithFirstDate: true, + pickerMode: DateTimePickerMode.datetime, + pickerTheme: DateTimePickerTheme( + // backgroundColor: Colors.white, + cancelTextStyle: labelTextStyle(), + confirmTextStyle: labelTextStyle(), + // showTitle: true, + //title: Text('Pick date and time'), + itemTextStyle: valuesTextStyle(), + ), + onConfirm: (dateTime, List index)async { + DateTime selectdate = dateTime; + setState(() { + selIOS = DateFormat('dd-MMM-yyyy - HH:mm').format(selectdate); + }); + + if(selIOS!=''){ + setState(() { + dateController.text=selIOS.toString(); + }); + } + else { + AppSettings.longFailedToast('please select date'); + } + }, + ); + }, + icon: Icon( + Icons.calendar_month, + color: primaryColor, + )) + + + + ], + ); + }); + }, + ); + + + + + + + + }, + + + child: Card( //color: prescriptionsList[index].cardColor, @@ -145,25 +381,22 @@ class _BiddingRequestsState extends State { children: [ GestureDetector( child: Container( - width: MediaQuery.of(context).size.width * .18, - height: - MediaQuery.of(context).size.height * .10, + width: MediaQuery.of(context).size.width * 0.18, + height: MediaQuery.of(context).size.height * 0.10, decoration: BoxDecoration( - shape: BoxShape.circle, - image: DecorationImage( - image: (AppSettings.updatedImage != null) ? FileImage(AppSettings.updatedImage!) as ImageProvider : AssetImage("images/mobilebg.png"), // picked file - fit: BoxFit.cover)), - /* decoration: BoxDecoration( - shape: BoxShape.rectangle, + shape: BoxShape.circle, image: DecorationImage( - image: NetworkImage(prescriptionsList[index].prescription_url) as ImageProvider, // picked file - fit: BoxFit.contain)),*/ + image: NetworkImage(prescriptionsList[index].PrescriptionPictures[0].url ?? "images/logo.png"), + fit: BoxFit.cover, + ), + ), ), - onTap: (){ - // showPicDialog(prescriptionsList[index].prescription_url); - + onTap: () { + // Handle onTap event if needed + showPicDialog(prescriptionsList[index].PrescriptionPictures); }, ), + SizedBox(width:MediaQuery.of(context).size.width * .02,), Container( width: MediaQuery.of(context).size.width * .55, @@ -171,12 +404,11 @@ class _BiddingRequestsState extends State { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(prescriptionsList[index].bidding_firstName.toString().toUpperCase(),style: valuesTextStyle()), - Text(prescriptionsList[index].bidding_contactNumber.toString().toUpperCase(),style: valuesTextStyle()), - Text(prescriptionsList[index].bidding_bookingid.toString().toUpperCase(),style: valuesTextStyle()), - Text(prescriptionsList[index].bidding_address.toString().toUpperCase(),style: valuesTextStyle()), - Text(prescriptionsList[index].custumerid_bidding.toString().toUpperCase(),style: valuesTextStyle()), - Text(prescriptionsList[index].pharmacyid_bidding.toString().toUpperCase(),style: valuesTextStyle()), + Text(prescriptionsList[index].firstName.toString().toUpperCase(),style: valuesTextStyle()), + Text(prescriptionsList[index].bookingId.toString().toUpperCase(),style: valuesTextStyle()), + Text(prescriptionsList[index].address.toString().toUpperCase(),style: valuesTextStyle()), + Text(prescriptionsList[index].customerId.toString().toUpperCase(),style: valuesTextStyle()), + Text(prescriptionsList[index].pharmacyId.toString().toUpperCase(),style: valuesTextStyle()), ], ), @@ -185,7 +417,6 @@ class _BiddingRequestsState extends State { Visibility( visible:true , - child: prescriptionsList[index].status.toString().toLowerCase()=='pending'?Column( children: [ TextButton( @@ -202,9 +433,8 @@ class _BiddingRequestsState extends State { payload["action"] = "accept"; bool requestStatus = await AppSettings.getRequestBiddingDetails( - prescriptionsList[index].bidding_bookingid, + prescriptionsList[index].bookingId, payload); - if (requestStatus) { // Navigator.of(context).pop(); AppSettings.longSuccessToast( @@ -229,7 +459,7 @@ class _BiddingRequestsState extends State { payload["action"] = "reject"; bool requestStatus = await AppSettings.getRequestBiddingDetails( - prescriptionsList[index].bidding_bookingid, + prescriptionsList[index].bookingId, payload); if (requestStatus) { diff --git a/lib/chat/chat_controller.dart b/lib/chat/chat_controller.dart new file mode 100644 index 0000000..f20b789 --- /dev/null +++ b/lib/chat/chat_controller.dart @@ -0,0 +1,88 @@ +import 'dart:io'; + +import 'package:firebase_storage/firebase_storage.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'chatmessage.dart'; + + +class ChatController extends GetxController { + final CollectionReference _messagesCollection = + FirebaseFirestore.instance.collection('messages'); + + // Observable list of messages + RxList messages = [].obs; + + void sendMessage(String messageContent, String messageType, bool isText) async { + try { + await _messagesCollection.add({ + 'messageContent': messageContent, + 'messageType': messageType, + 'isText': isText, + 'timestamp': Timestamp.now(), + }); + print("Message sent successfully"); + } catch (e) { + print('Error sending message: $e'); + } + } + + Future uploadImage(File image, String id) async { + try { + String fileName = DateTime.now().millisecondsSinceEpoch.toString(); + Reference storageReference = + FirebaseStorage.instance.ref().child('products/$fileName'); + SettableMetadata metadata = SettableMetadata(contentType: 'image/jpeg'); + UploadTask uploadTask = storageReference.putFile(image, metadata); + + String temporaryMessageId = UniqueKey().toString(); + messages.add(ChatMessage( + messageContent: 'Uploading...', + messageType: id, + isText: true, + temporaryMessageId: temporaryMessageId, + )); + + TaskSnapshot taskSnapshot = await uploadTask; + String downloadURL = await storageReference.getDownloadURL(); + + // Replace the temporary message with the uploaded image + int index = messages.indexWhere((message) => message.temporaryMessageId == temporaryMessageId); + if (index != -1) { + messages[index] = ChatMessage( + messageContent: downloadURL, + messageType: id, + isText: false, + temporaryMessageId: '', + ); + } + + print('Image uploaded successfully. Download URL: $downloadURL'); + return downloadURL; + } catch (e) { + print('Error uploading image: $e'); + throw e; + } + } + + Stream getMessagesStream() { + return _messagesCollection.orderBy('timestamp').snapshots(); + } + + @override + void onInit() { + super.onInit(); + // Listen for changes in the messages collection and update the local list + getMessagesStream().listen((QuerySnapshot snapshot) { + messages.assignAll(snapshot.docs.map((doc) => ChatMessage( + messageContent: doc['messageContent'], + messageType: doc['messageType'], + isText: doc['isText'], + temporaryMessageId: '', + ))); + }); + + + } +} diff --git a/lib/chat/chatmessage.dart b/lib/chat/chatmessage.dart new file mode 100644 index 0000000..03695f0 --- /dev/null +++ b/lib/chat/chatmessage.dart @@ -0,0 +1,15 @@ +import 'package:flutter/cupertino.dart'; + +class ChatMessage { + String messageContent; + String messageType; + bool isText; + String temporaryMessageId; // New property for temporary message identifier + + ChatMessage({ + required this.messageContent, + required this.messageType, + required this.isText, + required this.temporaryMessageId, // Include in the constructor + }); +} diff --git a/lib/chat/chatpage.dart b/lib/chat/chatpage.dart new file mode 100644 index 0000000..beca6d9 --- /dev/null +++ b/lib/chat/chatpage.dart @@ -0,0 +1,241 @@ +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:healthcare_pharmacy/chat/chatzoomable_image.dart'; +import 'package:healthcare_pharmacy/pages/index.dart'; +import 'package:healthcare_pharmacy/settings.dart'; +import 'package:image_picker/image_picker.dart'; +import 'chat_controller.dart'; +import 'chatmessage.dart'; +import 'package:photo_view/photo_view.dart'; + +class ChatPage extends StatefulWidget { + var pharmacyName; + var profilePictureUrl; + + + ChatPage({ + this.pharmacyName,this.profilePictureUrl + }); + + @override + State createState() => _ChatPageState(); +} + +class _ChatPageState extends State { + final ChatController chatController = Get.put(ChatController()); + final TextEditingController content = TextEditingController(); + final ImagePicker _picker = ImagePicker(); + XFile? _image; + var id="2"; + bool _sending = false; + final ScrollController _scrollController = ScrollController(); + + @override + void initState() { + super.initState(); + _scrollToBottom(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor:Colors.green, + elevation: 0, + automaticallyImplyLeading: false, + flexibleSpace: SafeArea( + child: Container( + padding: EdgeInsets.only(right: 16), + child: Row( + children: [ + IconButton( + onPressed: (){ + Navigator.pop(context); + }, + icon: Icon(Icons.arrow_back,color: Colors.black,), + ), + SizedBox(width: 2,), + CircleAvatar( + backgroundImage: NetworkImage(AppSettings.profilePictureUrl), + maxRadius: 20, + ), + SizedBox(width: 12,), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(widget.pharmacyName,style: TextStyle( fontSize: 16 ,fontWeight: FontWeight.w600),), + // SizedBox(height: 6,), + // Text("Online",style: TextStyle(color: Colors.grey.shade600, fontSize: 13),), + ], + ), + ), + /*IconButton( + onPressed: () { + UrlLauncher.launch("tel://8328206298"); + }, + icon: Icon(Icons.call, color: Colors.black), + ),*/ + IconButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => IndexPage()), + ); + }, + icon: Icon(Icons.videocam, color: Colors.black), + ), + ], + ), + ), + ), + ), + body: Stack( + children: [ + Obx(() => ListView.builder( + itemCount: chatController.messages.length, + shrinkWrap: true, + padding: EdgeInsets.only(top: 10, bottom: 80), // Adjust bottom padding to accommodate the input field + physics: ScrollPhysics(), + controller: _scrollController, + itemBuilder: (context, index) { + final data = chatController.messages[index]; + return Container( + padding: EdgeInsets.only( + left: 14, right: 14, top: 10, bottom: 10), + child: Align( + alignment: (data.messageType != id ? Alignment.topLeft : Alignment.topRight), + child: GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ChatZoomableImage(data.messageContent), + ), + ); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: (data.messageType != id + ? Colors.grey.shade200 + : Colors.blue[200]), + ), + padding: EdgeInsets.all(16), + child: data.isText + ? Text(data.messageContent, style: TextStyle(fontSize: 15)) + : Image.network( + data.messageContent, + scale: 3, + width: 100, + height: 100, + fit: BoxFit.cover, + ), + ), + ), + + ), + ); + }, + )), + Align(alignment: Alignment.bottomCenter,child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Container( + height: 60, + width: double.infinity, + color: Colors.white, + child: Row( + children: [ + GestureDetector( + onTap: getImage, + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + color: Colors.lightBlue, + borderRadius: BorderRadius.circular(30), + ), + child: Icon(Icons.add, color: Colors.white, size: 20), + ), + ), + SizedBox(width: 15), + Expanded( + child: TextField( + controller: content, + decoration: InputDecoration( + hintText: "Write message...", + hintStyle: TextStyle(color: Colors.black54), + border: InputBorder.none, + ), + ), + ), + SizedBox(width: 15), + FloatingActionButton( + onPressed: () { + sendMessage(); + }, + child: Icon(Icons.send, color: Colors.white, size: 18), + backgroundColor: Colors.blue, + elevation: 0, + ), + ], + ), + ), + ),) + ], + ), + ); + } + + void _scrollToBottom() { + Future.delayed(Duration(milliseconds: 300), () { + if (_scrollController.hasClients) { + _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + } + }); + } + + Future getImage() async { + final XFile? image = + await _picker.pickImage(source: ImageSource.gallery); + if (image != null) { + setState(() { + _image = image; + }); + sendMessage(); // Call sendMessage function to send the selected image immediately + } + } + + void sendMessage() async { + String messageContent = content.text.trim(); + if (messageContent.isNotEmpty || _image != null) { + setState(() { + _sending = true; + }); + try { + if (_image != null) { + String imageUrl = + await chatController.uploadImage(File(_image!.path),'$id'); + chatController.sendMessage(imageUrl, '$id', false); + _image = null; // Clear the selected image after sending + } + if (messageContent.isNotEmpty) { + chatController.sendMessage(messageContent, '$id', true); + content.clear(); + } + } finally { + setState(() { + _sending = false; + }); + } + _scrollToBottom(); // Scroll to the bottom after sending message + } + } +} diff --git a/lib/chat/chatzoomable_image.dart b/lib/chat/chatzoomable_image.dart new file mode 100644 index 0000000..7696d77 --- /dev/null +++ b/lib/chat/chatzoomable_image.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:healthcare_pharmacy/settings.dart'; +import 'package:photo_view/photo_view.dart'; + +class ChatZoomableImage extends StatelessWidget { + final String imageUrl; + + ChatZoomableImage(this.imageUrl); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: primaryColor, // Set the background color + title: Text('Preview Image'), // Set the title text + actions: [ + IconButton( + icon: Icon(Icons.close), + onPressed: () { + Navigator.pop(context); + }, + ), + ], + ), + body: Center( + child: imageUrl.isNotEmpty + ? PhotoView( + imageProvider: NetworkImage(imageUrl), + minScale: PhotoViewComputedScale.contained, + maxScale: PhotoViewComputedScale.contained * 3.0, + ) + : Image.asset( + 'images/mobilebg.png', // Path to your default image + fit: BoxFit.cover, + ), + ), + ); + } +} + diff --git a/lib/chatview.dart b/lib/chatview.dart new file mode 100644 index 0000000..e932dd8 --- /dev/null +++ b/lib/chatview.dart @@ -0,0 +1,201 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:healthcare_pharmacy/models/chatconversation_model.dart'; +import 'package:healthcare_pharmacy/settings.dart'; +import 'ChatMessage.dart'; + +class ChatUIconvoid extends StatefulWidget { + const ChatUIconvoid({super.key}); + + @override + State createState() => _ChatUIconvoidState(); +} + +class _ChatUIconvoidState extends State { + + TextEditingController _messageController = TextEditingController(); + bool isLoading=false; + List chatCoversatitonIdList = []; + List messages = [ + ChatMessage(message: "Hello", type: "receiver"), + ChatMessage(message: "How have you?", type: "receiver"), + ChatMessage( + message: "I am doing fine.How have you?", + type: "sender"), + + ]; + + @override + void initState() { + // TODO: implement initState + isLoading=true; + getConversasionId(); + super.initState(); + } + Future getConversasionId() async { + isLoading = true; + try { + var response = await AppSettings.getChatId(); + setState(() { + chatCoversatitonIdList = + ((jsonDecode(response)['newConversation']) as List).map((dynamic model) { + return GetCoversatitonIdModel.fromJson(model); + }).toList(); + + // Extracting the conversation_id from the response + String conversationId = + jsonDecode(response)['newConversation']['conversation_id']; + + // Use the conversationId as needed in your code + print('Conversation ID: $conversationId'); + + isLoading = false; + isLoading = false; + }); + + + } catch (e) { + setState(() { + isLoading = false; + }); + } + } + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + elevation: 0, + automaticallyImplyLeading: false, + backgroundColor: Colors.white, + flexibleSpace: SafeArea( + child: Container( + padding: EdgeInsets.only(right: 16), + child: Row( + children: [ + IconButton( + onPressed: (){ + Navigator.pop(context); + }, + icon: Icon(Icons.arrow_back,color: Colors.black,), + ), + SizedBox(width: 2,), + CircleAvatar( + backgroundImage: NetworkImage("https://www.shutterstock.com/image-photo/pharmacist-holding-medicine-box-capsule-260nw-717437125.jpg"), + maxRadius: 20, + ), + SizedBox(width: 12,), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Arminta pharma",style: TextStyle( fontSize: 16 ,fontWeight: FontWeight.w600),), + // SizedBox(height: 6,), + // Text("Online",style: TextStyle(color: Colors.grey.shade600, fontSize: 13),), + ], + ), + ), + Icon(Icons.settings,color: Colors.black54,), + ], + ), + ), + ), + ), + body: Stack( + children: [ + ListView.builder( + itemCount: messages.length, + shrinkWrap: true, + padding: EdgeInsets.only(top: 10,bottom: 60), + itemBuilder: (context, index){ + return Container( + padding: EdgeInsets.only(left: 14,right: 14,top: 10,bottom: 10), + child: Align( + alignment: (messages[index].type == "receiver"?Alignment.topLeft:Alignment.topRight), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: (messages[index].type == "receiver"?Colors.grey.shade200:Colors.blue[200]), + ), + padding: EdgeInsets.symmetric(horizontal: 16,vertical: 10), + child: Text(messages[index].message, style: TextStyle(fontSize: 15),), + ), + ), + ); + }, + ), + Align( + alignment: Alignment.bottomLeft, + child: Container( + padding: EdgeInsets.only(left: 10, bottom: 10, top: 10), + height: 60, + width: double.infinity, + color: Colors.white, + child: Row( + children: [ + GestureDetector( + onTap: () {}, + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + color: Colors.lightBlue, + borderRadius: BorderRadius.circular(30), + ), + child: Icon( + Icons.add, + color: Colors.white, + size: 20, + ), + ), + ), + SizedBox( + width: 15, + ), + Expanded( + child: TextField( + controller: _messageController, + decoration: InputDecoration( + hintText: "Write message...", + hintStyle: TextStyle(color: Colors.black54), + border: InputBorder.none), + ), + ), + SizedBox( + width: 15, + ), + FloatingActionButton( + onPressed: () { + String newMessage = _messageController.text; + if (newMessage.isNotEmpty) { + // Add the new message to the list + setState(() { + messages.add( + ChatMessage( + message: newMessage, + type: "sender", + ), + ); + }); + + // Clear the text field + _messageController.clear(); + } + }, + child: Icon( + Icons.send, + color: Colors.white, + size: 18, + ), + backgroundColor: Colors.blue, + elevation: 0, + ), + ], + ), + ), + ), + ], + )); + } +} diff --git a/lib/conver.dart b/lib/conver.dart new file mode 100644 index 0000000..de7cf75 --- /dev/null +++ b/lib/conver.dart @@ -0,0 +1,395 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:healthcare_pharmacy/pages/index.dart'; +import 'package:healthcare_pharmacy/settings.dart'; +import 'package:url_launcher/url_launcher.dart' as UrlLauncher; +import 'package:web_socket_channel/io.dart'; +import 'package:web_socket_channel/web_socket_channel.dart'; +import 'models/ChatMessage.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:flutter_callkeep/flutter_callkeep.dart'; + + +class ChatUI extends StatefulWidget { + + const ChatUI({Key? key}) : super(key: key); + + @override + State createState() => _ChatUIState(); +} + +class _ChatUIState extends State { + WebSocketChannel channel=IOWebSocketChannel.connect( + "wss://socketsbay.com/wss/v2/1/demo/", + ); + // WebSocket channel for call signaling + late WebSocketChannel callChannel; + + WebSocketConnectionState _connectionState = WebSocketConnectionState.connecting; + late ScrollController _scrollController; + final TextEditingController _controller = TextEditingController(); + // Store messages + final List _messages = []; + String myUserId = 'user456'; + String otherUserId = 'user123'; + final ImagePicker _picker = ImagePicker(); + + Future pickImageFromGallery() async { + try { + final image = await _picker.pickImage(source: ImageSource.gallery); + if (image == null) return; + final imageTemp = File(image.path); + setState(() { + AppSettings.updatedImage = imageTemp; + }); + // uploadProfileApi(AppSettings.updatedImage); + AppSettings.saveProfile(image.path); + + + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future takeImageFromCamera() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + setState(() { + AppSettings.updatedImage = imageTemp; + }); + + //uploadProfileApi(AppSettings.updatedImage); + AppSettings.saveProfile(image.path); + + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: _connectionState == WebSocketConnectionState.error ? Colors.red : _connectionState == WebSocketConnectionState.closed ? Colors.red : Colors.green, + elevation: 0, + automaticallyImplyLeading: false, + flexibleSpace: SafeArea( + child: Container( + padding: EdgeInsets.only(right: 16), + child: Row( + children: [ + IconButton( + onPressed: (){ + Navigator.pop(context); + }, + icon: Icon(Icons.arrow_back,color: Colors.black,), + ), + SizedBox(width: 2,), + CircleAvatar( + backgroundImage: NetworkImage("https://ehealth.eletsonline.com/wp-content/uploads/2020/12/pharma-industry-in-2021.jpg"), + maxRadius: 20, + ), + SizedBox(width: 12,), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Suresh",style: TextStyle( fontSize: 16 ,fontWeight: FontWeight.w600),), + // SizedBox(height: 6,), + // Text("Online",style: TextStyle(color: Colors.grey.shade600, fontSize: 13),), + ], + ), + ), + IconButton( + onPressed: () { + UrlLauncher.launch("tel://8328206298"); + }, + icon: Icon(Icons.call, color: Colors.black), + ), + IconButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => IndexPage()), + ); + }, + icon: Icon(Icons.videocam, color: Colors.black), + ), + ], + ), + ), + ), + ), + body: Stack( + children: [ + ListView.builder( + controller: _scrollController, + itemCount: _messages.length, + shrinkWrap: true, + padding: EdgeInsets.only(top: 10,bottom: 60), + itemBuilder: (context, index){ + bool isSentByMe = _messages[index].senderId == myUserId; + return Container( + padding: EdgeInsets.only(left: 14,right: 14,top: 10,bottom: 10), + child: Align( + alignment: (isSentByMe?Alignment.topRight:Alignment.topLeft), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: (isSentByMe?Colors.blue[200]:Colors.grey[200]), + ), + padding: EdgeInsets.symmetric(horizontal: 16,vertical: 10), + child: Text(_messages[index].messageContent, style: TextStyle(fontSize: 15),), + ), + ), + ); + }, + ), + Align( + alignment: Alignment.bottomLeft, + child: Container( + padding: EdgeInsets.only(left: 10, bottom: 10, top: 10), + height: 60, + width: double.infinity, + color: Colors.white, + child: Row( + children: [ + GestureDetector( + onTap: () { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: greyColor, + ), + onTap: () async { + await takeImageFromCamera(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: greyColor, + ), + onTap: () async { + await pickImageFromGallery(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + color: Colors.lightBlue, + borderRadius: BorderRadius.circular(30), + ), + child: Icon( + Icons.add, + color: Colors.white, + size: 20, + ), + ), + ), + SizedBox( + width: 15, + ), + Expanded( + child: TextField( + controller: _controller, + decoration: InputDecoration( + hintText: "Write message...", + hintStyle: TextStyle(color: Colors.black54), + border: InputBorder.none), + ), + ), + SizedBox( + width: 15, + ), + FloatingActionButton( + onPressed: () { + String newMessage = _controller.text; + if (newMessage.isNotEmpty) { + // Add the new message to the list + setState(() { + _sendMessage(); + }); + + // Clear the text field + _controller.clear(); + } + }, + child: Icon( + Icons.send, + color: Colors.white, + size: 18, + ), + backgroundColor: Colors.blue, + elevation: 0, + ), + ], + ), + ), + ), + ], + )); + + } + + + + void _sendMessage() { + if (_controller.text.isNotEmpty) { + var message = ChatMessage( + senderId: myUserId, + receiverId: otherUserId, + messageType: 'text', + messageContent: _controller.text, + ); + channel.sink.add(chatMessageToJson(message)); + _messages.add(message); + _controller.clear(); + } + } + + + @override + void initState() { + super.initState(); + // Initialize the WebSocket channel for call signaling + callChannel = IOWebSocketChannel.connect( + "wss://socketsbay.com/wss/v2/1/demo/call", // adjust the URL accordingly + ); + _scrollController = ScrollController(); + channel.stream.listen((message) { + if (message is String) { + var receivedMessage = chatMessageFromJson(message); + setState(() { + _messages.add(receivedMessage); + }); + _scrollToBottom(); + } + }, onError: (error) { + setState(() { + _connectionState = WebSocketConnectionState.error; + }); + },onDone: (){ + setState(() { + _connectionState = WebSocketConnectionState.closed; + }); + },); + } + + + // ... existing code ... + + void startCall(String callId) { + // Send a call initiation message to the other user + var callMessage = { + 'type': 'call', + 'callId': callId, + 'senderId': myUserId, + 'receiverId': otherUserId, + }; + callChannel.sink.add(jsonEncode(callMessage)); + + // Update UI or perform other actions as needed + // ... + + // For simplicity, let's assume the call is accepted after a short delay + Future.delayed(Duration(seconds: 2), () { + // Handle call accepted + onCallAccepted(callId); + }); + } + + void onCallAccepted(String callId) { + // Update UI or perform other actions as needed + // ... + + // Send a call accepted message to the other user + var acceptedMessage = { + 'type': 'call_accepted', + 'callId': callId, + 'senderId': myUserId, + 'receiverId': otherUserId, + }; + callChannel.sink.add(jsonEncode(acceptedMessage)); + + // Start the actual call + // ... + } + + void endCall(String callId) { + // Send a call end message to the other user + var endMessage = { + 'type': 'call_end', + 'callId': callId, + 'senderId': myUserId, + 'receiverId': otherUserId, + }; + callChannel.sink.add(jsonEncode(endMessage)); + + // Update UI or perform other actions as needed + // ... + + // For simplicity, let's assume the call is ended immediately + onCallEnded(callId); + } + + void onCallEnded(String callId) { + // Update UI or perform other actions as needed + // ... + + // Close the call WebSocket channel + callChannel.sink.close(); + + // For simplicity, let's assume the call ended immediately + // ... + } + + + + void _scrollToBottom() { + // Scroll to the bottom of the list + _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: Duration(milliseconds: 200), + curve: Curves.easeOut, + ); + } + + + @override + void dispose() { + channel.sink.close(); + super.dispose(); + } +} + +enum WebSocketConnectionState { connecting, open, closing, closed, error } \ No newline at end of file diff --git a/lib/createoffers.dart b/lib/createoffers.dart index f58d486..e8ce80b 100644 --- a/lib/createoffers.dart +++ b/lib/createoffers.dart @@ -10,7 +10,7 @@ import 'package:intl/intl.dart'; import 'package:flutter_cupertino_datetime_picker/flutter_cupertino_datetime_picker.dart'; import 'package:image_picker/image_picker.dart'; import 'package:image/image.dart' as Img; - +import 'package:gallery_saver/gallery_saver.dart'; class offers extends StatefulWidget { @@ -74,8 +74,7 @@ class _offersState extends State { } } - - Future takeImageFromCamera() async { + /* Future takeImageFromCamera() async { try { final image = await _picker.pickImage(source: ImageSource.camera); if (image == null) return; @@ -89,6 +88,11 @@ class _offersState extends State { // Compress the image List compressedImage = Img.encodeJpg(decodedImage!, quality: 45); + // Save the original and compressed images to the gallery + await GallerySaver.saveImage(image.path, albumName: 'MedicinesAlbum'); + //await GallerySaver.saveImage(image.path, albumName: null); + //await GallerySaver.saveImage(imageFile.path, albumName: 'YourAlbumName'); + // Save the compressed image back to file await imageFile.writeAsBytes(compressedImage); @@ -106,6 +110,32 @@ class _offersState extends State { print('Failed to pick image: $e'); } } +*/ + Future takeImageFromCamera() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + + final File imageFile = File(image.path); + + // Read the image from file + List imageBytes = await imageFile.readAsBytes(); + Img.Image? decodedImage = Img.decodeImage(imageBytes); + // Compress the image + List compressedImage = Img.encodeJpg(decodedImage!, quality: 45); + await imageFile.writeAsBytes(compressedImage); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.offeruploadImageHTTPNew(imageFile); + print(jsonDecode(res)); + setState(() { + offerUrl = jsonDecode(res)['picture'][0]['url']; + print(offerUrl); + }); + Navigator.of(context, rootNavigator: true).pop(); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } @override Widget build(BuildContext context) { diff --git a/lib/dashboard.dart b/lib/dashboard.dart index 74dd953..f96f245 100644 --- a/lib/dashboard.dart +++ b/lib/dashboard.dart @@ -4,7 +4,10 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:healthcare_pharmacy/adddeliveryboy.dart'; +import 'package:healthcare_pharmacy/chat/chatpage.dart'; +import 'package:healthcare_pharmacy/chatview.dart'; import 'package:healthcare_pharmacy/companyoffrers.dart'; +import 'package:healthcare_pharmacy/conver.dart'; import 'package:healthcare_pharmacy/getallpharmacies.dart'; import 'package:healthcare_pharmacy/getdeliveryboydata.dart'; import 'package:healthcare_pharmacy/getmedicines.dart'; @@ -421,7 +424,7 @@ class _DashboardState extends State { width: 10, ), - Container( + /*Container( child: AppSettings.qrCode==''?TextButton( child: Text( @@ -473,7 +476,7 @@ class _DashboardState extends State { child: Image.memory(Uint8List.fromList(base64.decode(AppSettings.qrCode))), ), ), - ) + )*/ ], ),), SizedBox( @@ -820,6 +823,31 @@ class _DashboardState extends State { ); }, ), + Divider( + color: Colors.grey, + ), + ListTile( + title: Row( + children: const [ + Image( + image: const AssetImage('images/inactive.png'), + height: 25, + width: 25, + fit: BoxFit.fill), + const SizedBox( + width: 10, + ), + Text('Chat', style: TextStyle(color: Colors.black)), + ], + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ChatPage(pharmacyName: AppSettings.pharmacyName,profilePictureUrl: AppSettings.profilePictureUrl)), + ); + }, + ), Divider( color: Colors.grey, diff --git a/lib/getdeliveryboydata.dart b/lib/getdeliveryboydata.dart index 369f407..be547ce 100644 --- a/lib/getdeliveryboydata.dart +++ b/lib/getdeliveryboydata.dart @@ -183,8 +183,8 @@ class _GetDeliveryboyDataState extends State { } else { Navigator.of(context, rootNavigator: true).pop(); - AppSettings.longFailedStyledToast( - "Deliveryboy upadtion failed", context); + AppSettings.longFailedToast( + "Deliveryboy upadtion failed"); Navigator.of(context).pop(); } } catch (exception) { @@ -192,7 +192,7 @@ class _GetDeliveryboyDataState extends State { print(exception); } } else { - AppSettings.longFailedStyledToast("enter details", context); + AppSettings.longFailedToast("enter details"); } }, ), diff --git a/lib/getmedicines.dart b/lib/getmedicines.dart index fd40517..3cda81f 100644 --- a/lib/getmedicines.dart +++ b/lib/getmedicines.dart @@ -127,74 +127,84 @@ class _GetMedicinesState extends State with TickerProviderStateMix ); } - Widget _bindMedicines() { - if (medicine_name!='') { - return Padding(padding: EdgeInsets.all(10), - child: Container( - width: double.infinity, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - GestureDetector( - child: Container( - width: MediaQuery.of(context).size.width * .18, - height: - MediaQuery.of(context).size.height * .10, - decoration: BoxDecoration( + Widget _bindMedicines() { + if (medicine_name != '') { + return Padding( + padding: EdgeInsets.all(10), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, // Set background color to white + borderRadius: BorderRadius.circular(5.0), // Set border radius to 5 + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 2, + blurRadius: 5, + offset: Offset(0, 3), // changes position of shadow + ), + ], + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + child: Container( + width: MediaQuery.of(context).size.width * .18, + height: MediaQuery.of(context).size.height * .10, + decoration: BoxDecoration( shape: BoxShape.rectangle, image: DecorationImage( - image: NetworkImage(medImages[0]) as ImageProvider, // picked file - fit: BoxFit.contain)), - ), - onTap: () async { - showPicDialog(medImages[0]); - }, - ), - GestureDetector( - child: Column( - children: [ - Text(("Name :"+ medicine_name), - style: TextStyle(fontWeight: FontWeight.bold), - ), - Text(("Manufacturers :"+ medicine_manufacturers), - style: TextStyle(fontWeight: FontWeight.bold), - ), - Text( - medicine_salt_composition, - style: TextStyle(fontWeight: FontWeight.bold), - ), - Text(("Estimate Price :"+ medicine_mrp), - style: TextStyle(fontWeight: FontWeight.bold), + image: NetworkImage(medImages[0]) as ImageProvider, + fit: BoxFit.contain, + ), + borderRadius: BorderRadius.circular(5.0), // Set border radius to 5 ), - Text(("Medicine_Use :"+ medicine_primary_use), - style: TextStyle(fontWeight: FontWeight.bold), + ), + onTap: () async { + showPicDialog(medImages[0]); + }, + ), + SizedBox(width: 10), + Expanded( + child: GestureDetector( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 30), + Text( + "Name: " + medicine_name, + style: TextStyle(fontWeight: FontWeight.bold), + ), + Text( + "Estimate Price: " + medicine_mrp, + style: TextStyle(fontWeight: FontWeight.bold), + ), + Text( + "Medicine Use: " + medicine_primary_use, + style: TextStyle(fontWeight: FontWeight.bold), + ), + ], ), - ], + onTap: () { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new MedicineDetails( + name: medicine_name, + price: medicine_mrp, + bookid: medbookingid, + ), + ), + ); + }, + ), ), - onTap: () { - /* Navigator.push( - context, - new MaterialPageRoute( - builder: (__) => new MedicineDetailsCount()));*/ - Navigator.push( - context, - new MaterialPageRoute( - builder: (__) => new MedicineDetails(name: medicine_name,price: medicine_mrp,bookid:medbookingid))); - }, - - - - ), - - - ], + ], + ), ), - - - ), - ); - } + ); + } else { return Center( child: Padding( diff --git a/lib/main.dart b/lib/main.dart index 1c665c5..189e54a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,10 @@ +import 'dart:io'; + +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; +import 'package:healthcare_pharmacy/PushNotificationService.dart'; +import 'package:healthcare_pharmacy/chat/chatpage.dart'; import 'package:sizer/sizer.dart'; import 'package:flutter/services.dart'; import 'splash_screen.dart'; @@ -7,6 +13,16 @@ void main () async { // Set default home. Widget _defaultHome = Splash(); WidgetsFlutterBinding.ensureInitialized(); + FirebaseOptions firebaseOptions = FirebaseOptions( + apiKey: 'AIzaSyC89L-Xg53Bd_mdCPvKOu7BcC9Ya6UZeds', + appId: '1:60196905754:android:05ea9ecef5280e578a42a3', + messagingSenderId: '60196905754 ', + projectId: 'health-pharma-67443', + storageBucket: "health-pharma-67443.appspot.com"// Firebase Realtime Database URL + ); + Platform.isAndroid? await Firebase.initializeApp(options: firebaseOptions):await Firebase.initializeApp(); + PushNotificationService().initialize(); + FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(alert: true,badge: true,sound: true); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) .then((_) { runApp(Sizer( diff --git a/lib/medicinecart.dart b/lib/medicinecart.dart index 3dba8f1..ebcd7a7 100644 --- a/lib/medicinecart.dart +++ b/lib/medicinecart.dart @@ -37,7 +37,10 @@ class _MedicineCartListState extends State with TickerProvider String bookingidstring=''; bool isLoading=false; - + double finalGrandTotal=0.0; + double gstPercentage=0.0; + double discountedTotalAmount=0.0; + double additionalDiscount=0.0; @@ -244,31 +247,116 @@ class _MedicineCartListState extends State with TickerProvider onPrimary: Colors.white, // foreground ), onPressed: () async{ - // Calculate final amount - double gst = 0.00; // Replace with your actual GST value - double additionalDiscount = 10.00; // Replace with your actual additional discount value - double finalAmount = double.parse(totalPrice) + gst - additionalDiscount; showDialog( barrierDismissible: false, context: context, builder: (BuildContext context) { - // Update controllers with values - medicine_priceController.text = totalPrice.toString(); - medicine_gstPriceController.text = gst.toString(); + + double totalAmount = double.parse(totalPrice); + double additionalDiscountPercentage = 5; + double specialDiscountPercentage = 5; + gstPercentage = 18; + + // Calculate additional discount + additionalDiscount = (totalAmount * additionalDiscountPercentage) / 100; + discountedTotalAmount = totalAmount - additionalDiscount; + + // Calculate special discount + double specialDiscount = (discountedTotalAmount * specialDiscountPercentage) / 100; + double grandTotal = discountedTotalAmount - specialDiscount; + + + // Calculate GST on the grand total + double gstOnGrandTotal = (grandTotal * gstPercentage) / 100; + finalGrandTotal = grandTotal + gstOnGrandTotal; + medicine_priceController.text = finalGrandTotal.toString(); + medicine_gstPriceController.text = gstPercentage.toString(); medicine_additionalPriceController.text = additionalDiscount.toString(); return AlertDialog( - title: Text('Payment Receipt'), + title: Text( + 'Payment Receipt', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.red, + fontSize: 20 + ), + ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Total Price: $totalPrice'), - Text('GST: $gst'), - Text('Additional Discount: $additionalDiscount'), - Divider(), // Add a divider line - Text('Final Amount: $finalAmount'), // Show final amount + Text( + 'Medicines Total Amount: ${totalAmount.toStringAsFixed(2)}', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 16 + ), + ), + + Text( + 'Additional Discount (-5%): ${additionalDiscount.toStringAsFixed(2)} ', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 16 + ), + ), + Divider( + thickness: 2, // Adjust the thickness as needed + color: Colors.grey, // Adjust the color as needed + ), + Text( + 'Discounted Total Ammount: ${discountedTotalAmount.toStringAsFixed(2)}', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 16 + ), + ), + Text( + 'Special Discount (-5%): ${specialDiscount.toStringAsFixed(2)}', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 16 + ), + ), + Divider( + thickness: 2, // Adjust the thickness as needed + color: Colors.grey, // Adjust the color as needed + ), + Text( + 'Special Discounted Total Ammount: ${grandTotal.toStringAsFixed(2)}', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 16 + ), + ), + Text( + 'GST (+18%): ${gstOnGrandTotal.toStringAsFixed(2)}', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 16 + ), + ), + Divider( + thickness: 2, // Adjust the thickness as needed + color: Colors.black, // Adjust the color as needed + ), + + Text( + 'Grand Total: ${finalGrandTotal.toStringAsFixed(2)}', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.redAccent, + fontSize: 20 + ), + ), ], ), actions: [ @@ -298,7 +386,7 @@ class _MedicineCartListState extends State with TickerProvider AppSettings.longSuccessToast( "Medicines Final Price Sent Successfully"); - await Navigator.push( + await Navigator.push( context, MaterialPageRoute( builder: (context) => Dashboard()), @@ -324,8 +412,53 @@ class _MedicineCartListState extends State with TickerProvider child: Text('Submit'), ), ), + SizedBox(height: 10), // Add some spacing between buttons + /* Center( + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // fores + ), + onPressed: () async{ + var payload = new Map(); + payload["pharmacyname"] = + "Arminta Pharma PVT LTD"; + payload["pharmacyId"] = + "AWSSSUR1"; + payload["customerId"] = + "AWSSSUR1"; + payload["address"] = + "kphb"; + payload["dateOfOrder"] = + "15/02/2024"; + payload["action"] = "accept"; + payload["price"] = + "1000"; + payload["delivery_agent"] = "Arminta"; + payload["agent_mobile"] = "8328206299"; + payload["expectedDateOfDelivery"] ="20/02/2024"; + + bool requestStatus = + await AppSettings.assignDeliveryboyBookingRequests( + widget.bookidID, + payload); + + if (requestStatus) { + Navigator.of(context).pop(); + AppSettings.longSuccessToast( + "Booking Accepted"); + // await getBookingRequestsData(); + + + } else {} + }, + child: Text('Assign Deliver Boy'), + ), + ),*/ ], + ); + }, ); @@ -336,6 +469,7 @@ class _MedicineCartListState extends State with TickerProvider + ]); } else { return Center( diff --git a/lib/models/ChatMessage.dart b/lib/models/ChatMessage.dart new file mode 100644 index 0000000..f11c129 --- /dev/null +++ b/lib/models/ChatMessage.dart @@ -0,0 +1,37 @@ +import 'package:meta/meta.dart'; +import 'dart:convert'; + +// Define chatMessageFromJson and chatMessageToJson at the top level +ChatMessage chatMessageFromJson(String str) => ChatMessage.fromJson(json.decode(str)); + +String chatMessageToJson(ChatMessage data) => json.encode(data.toJson()); + +class ChatMessage { + String senderId; + String receiverId; + String messageType; + String messageContent; + + ChatMessage({ + required this.senderId, + required this.receiverId, + required this.messageType, + required this.messageContent, + }); + + factory ChatMessage.fromJson(Map json) => ChatMessage( + senderId: json["senderId"], + receiverId: json["receiverId"], + messageType: json["messageType"], + messageContent: json["messageContent"], + ); + + Map toJson() => { + "senderId": senderId, + "receiverId": receiverId, + "messageType": messageType, + "messageContent": messageContent, + }; +} + + diff --git a/lib/models/biddingrequest_model.dart b/lib/models/biddingrequest_model.dart index e0aa5e6..368495a 100644 --- a/lib/models/biddingrequest_model.dart +++ b/lib/models/biddingrequest_model.dart @@ -1,56 +1,67 @@ import 'package:flutter/material.dart'; import 'package:healthcare_pharmacy/settings.dart'; -class BiddingRequestsModel { - String? custumerid_bidding = ''; - String? pharmacyid_bidding=''; - String? amount_bidding=''; - String? bidding_bookingid=''; - String? bidding_firstName=''; - String? bidding_contactNumber=''; - String? bidding_address=''; - String orderStatus=''; - String status=''; - - - Color cardColor=Colors.white; - Color textColor=Colors.black; - +class PrescriptionPicture { + late String id; + late String url; + PrescriptionPicture({ + required this.id, + required this.url, + }); - BiddingRequestsModel(); - - factory BiddingRequestsModel.fromJson(Map json){ - BiddingRequestsModel rtvm = new BiddingRequestsModel(); + factory PrescriptionPicture.fromJson(Map json) { + return PrescriptionPicture( + id: json['_id'], + url: json['url'], + ); + } +} - rtvm.custumerid_bidding = json['customerId'].toString() ??''; - rtvm.pharmacyid_bidding = json['pharmacyId'].toString() ?? ''; - rtvm.amount_bidding = json['biddingAmount'].toString() ?? ''; - rtvm.bidding_bookingid = json['bookingId'].toString() ?? ''; - rtvm.bidding_firstName = json['customerDetails']["firstName"].toString() ?? ''; - rtvm.bidding_firstName = json['customerDetails']["address1"].toString() ?? ''; - rtvm.bidding_firstName = json['customerDetails']["firstName"].toString() ?? ''; +class BiddingRequestsModel { + String? customerId = ''; + String? pharmacyId = ''; + String? amount = ''; + String? bookingId = ''; + String? profilePicture = ''; + String? firstName = ''; + String? address = ''; + String orderStatus = ''; + String status = ''; - rtvm.status = json['status'] ; + List PrescriptionPictures = []; + Color cardColor = Colors.white; + Color textColor = Colors.black; - // rtvm.bidding_contactNumber = json['customerDetails']['profile']["contactNumber"].toString() ?? ''; + BiddingRequestsModel(); - // rtvm.bidding_contactNumber = json['contactNumber'].toString() ?? ''; - // rtvm.bidding_address1 = json['address1'].toString() ?? ''; + factory BiddingRequestsModel.fromJson(Map json) { + BiddingRequestsModel rtvm = BiddingRequestsModel(); + rtvm.customerId = json['customerId'].toString() ?? ''; + rtvm.pharmacyId = json['pharmacyId'].toString() ?? ''; + rtvm.amount = json['biddingAmount'].toString() ?? ''; + rtvm.bookingId = json['bookingId'].toString() ?? ''; + rtvm.profilePicture = json['profilePicture'] ?? ''; + rtvm.firstName = json['customerDetails']["firstName"].toString() ?? ''; + rtvm.address = json['customerDetails']["address1"].toString() ?? ''; + rtvm.status = json['status']; - // rtvm.prescription_url = json['pictureUrl'][0] ?? ''; - if(rtvm.status.toString().toLowerCase()=='accepted'){ - rtvm.textColor=Colors.green; - } - else if(rtvm.status.toString().toLowerCase()=='rejected'){ - rtvm.textColor=Colors.red; + if (json['PrescriptionPictures'] != null) { + var pictures = json['PrescriptionPictures'] as List; + rtvm.PrescriptionPictures = + pictures.map((picture) => PrescriptionPicture.fromJson(picture)).toList(); } - else{ - rtvm.textColor=primaryColor; + + if (rtvm.status.toString().toLowerCase() == 'accepted') { + rtvm.textColor = Colors.green; + } else if (rtvm.status.toString().toLowerCase() == 'rejected') { + rtvm.textColor = Colors.red; + } else { + rtvm.textColor = primaryColor; } + return rtvm; } - -} \ No newline at end of file +} diff --git a/lib/models/chatconversation_model.dart b/lib/models/chatconversation_model.dart new file mode 100644 index 0000000..11cc606 --- /dev/null +++ b/lib/models/chatconversation_model.dart @@ -0,0 +1,22 @@ +import 'dart:convert'; + +List listdadFromJson(String str) => List.from(json.decode(str).map((x) => GetCoversatitonIdModel .fromJson(x))); + +String listdadToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); + +class GetCoversatitonIdModel { + String ? conversation_id; + + GetCoversatitonIdModel ({ + required this.conversation_id, + + }); + + factory GetCoversatitonIdModel .fromJson(Map json) => GetCoversatitonIdModel ( + conversation_id: json["conversation_id"], + ); + + Map toJson() => { + "conversation_id": conversation_id, + }; +} \ No newline at end of file diff --git a/lib/offerstabdata.dart b/lib/offerstabdata.dart index 025c3fc..6363f64 100644 --- a/lib/offerstabdata.dart +++ b/lib/offerstabdata.dart @@ -607,8 +607,8 @@ class _OffersDataState extends State with TickerProviderStateMixin, ); } else { Navigator.of(context, rootNavigator: true).pop(); - AppSettings.longFailedStyledToast( - "Offer upadtion failed", context); + AppSettings.longFailedToast( + "Offer upadtion failed"); Navigator.of(context).pop(); } } catch (exception) { @@ -616,7 +616,7 @@ class _OffersDataState extends State with TickerProviderStateMixin, print(exception); } } else { - AppSettings.longFailedStyledToast("enter details", context); + AppSettings.longFailedToast("enter details"); } }, ), diff --git a/lib/offersview.dart b/lib/offersview.dart index 4dffce8..e696d04 100644 --- a/lib/offersview.dart +++ b/lib/offersview.dart @@ -384,8 +384,8 @@ class _OffersViewState extends State with TickerProviderStateMixin { await getOffersViewData(); } else { Navigator.of(context, rootNavigator: true).pop(); - AppSettings.longFailedStyledToast( - "Offer upadtion failed", context); + AppSettings.longFailedToast( + "Offer upadtion failed"); Navigator.of(context).pop(); } } catch (exception) { @@ -393,7 +393,7 @@ class _OffersViewState extends State with TickerProviderStateMixin { print(exception); } } else { - AppSettings.longFailedStyledToast("enter details", context); + AppSettings.longFailedToast("enter details"); } }, ), diff --git a/lib/pages/call.dart b/lib/pages/call.dart new file mode 100644 index 0000000..59eaaa1 --- /dev/null +++ b/lib/pages/call.dart @@ -0,0 +1,271 @@ + +import 'package:flutter/material.dart'; +import 'package:healthcare_pharmacy/settings.dart'; +import 'dart:async'; +import 'package:permission_handler/permission_handler.dart'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine/rtc_engine.dart' as rtc_engine; +import 'package:agora_rtc_engine/rtc_local_view.dart' as rtc_local_view; +import 'package:agora_rtc_engine/rtc_remote_view.dart' as rtc_remote_view; + +class CallPage extends StatefulWidget { + final String? channelName; + final ClientRole? role; + const CallPage({Key? key, this.channelName, this.role}) : super(key: key); + + @override + State createState() => _CallPageState(); +} + +class _CallPageState extends State { + final _users = []; + final _infoString = []; + late RtcEngine _engine; + bool muted = false; // Define the muted variable + bool viewPanel = true; + @override + void initState() { + super.initState(); + initialize(); + } + + @override + void dispose() { + _users.clear(); + _engine.leaveChannel(); + _engine.destroy(); + super.dispose(); + } + + Future initialize() async { + if (appId.isEmpty) { + setState(() { + _infoString.add('AppId is missing please provide AppId'); + _infoString.add('Agora Engine is not starting'); + }); + return; + } + _engine = await rtc_engine.RtcEngine.create(appId); + await _engine.enableVideo(); + await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); + await _engine.setClientRole(widget.role!); + _addAgoraEventHandler(); + VideoEncoderConfiguration configuration = VideoEncoderConfiguration( + dimensions: VideoDimensions(width: 1920, height: 1080), + ); + await _engine.setVideoEncoderConfiguration(configuration); + await _engine.joinChannel(token, widget.channelName!, null, 0); + } + + void _addAgoraEventHandler() { + _engine.setEventHandler( + rtc_engine.RtcEngineEventHandler( + error: (code) { + setState(() { + final info = 'Error: $code'; + _infoString.add(info); + }); + }, + joinChannelSuccess: (channel, uid, elapsed) { + setState(() { + final info = 'Join Channel: $channel, uid:$uid'; + _infoString.add(info); + }); + }, + leaveChannel: (stats) { + setState(() { + _infoString.add('Leave Channel'); + _users.clear(); + }); + }, + userJoined: (uid, elapsed) { + setState(() { + final info = 'User joined: $uid'; + _infoString.add(info); + _users.add(uid); + }); + }, + userOffline: (uid, elapsed) { + setState(() { + final info = 'User Offline: $uid'; + _infoString.add(info); + _users.remove(uid); + }); + }, + firstRemoteVideoFrame: (uid, width, height, elapsed) { + setState(() { + final info = 'First Remote Video: $uid $width*$height'; + _infoString.add(info); + _users.remove(uid); + }); + }, + ), + ); + } + + + + + + Widget _viewRows() { + final List list = []; + if (widget.role == ClientRole.Broadcaster) { + list.add(const rtc_local_view.SurfaceView()); + } + for (var uid in _users) { + list.add(rtc_remote_view.SurfaceView( + uid: uid, + channelId: widget.channelName!, + )); + } + final views=list; + return Column( + children: List.generate( + views.length, + (index) => Expanded( + child: views[index], + ), + ), + ); + } + + + Widget _toolbar() { + if (widget.role == ClientRole.Audience) return SizedBox(); + + return Container( + alignment: Alignment.bottomCenter, + padding: const EdgeInsets.symmetric(vertical: 48), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + RawMaterialButton( + onPressed: () { + setState(() { + muted = !muted; + }); + _engine.muteLocalAudioStream(muted); + }, + child: Icon( + muted ? Icons.mic_off : Icons.mic, + color: muted ? Colors.white : Colors.blueAccent, + size: 20.0, + ), + shape: CircleBorder(), + elevation: 2.0, + fillColor: muted ? Colors.blueAccent : Colors.white, + padding: EdgeInsets.all(12.0), + ), + RawMaterialButton( + onPressed: () => Navigator.pop(context), + child: Icon( + Icons.call_end, + color: Colors.white, + size: 35.0, + ), + shape: CircleBorder(), + elevation: 2.0, + fillColor: Colors.redAccent, + padding: EdgeInsets.all(15.0), + ), + RawMaterialButton( + onPressed: () { + _engine.switchCamera(); + }, + child: Icon( + Icons.switch_camera, + color: Colors.blueAccent, + size: 20.0, + ), + shape: CircleBorder(), + elevation: 2.0, + fillColor: Colors.white, + padding: EdgeInsets.all(12.0), + ), + ], + ), + ); + } + + + Widget _panel() + { + return Visibility( + visible: viewPanel, + child: Container( + padding: const EdgeInsets.symmetric(vertical: 48), + alignment: Alignment.bottomCenter, + child: FractionallySizedBox( + heightFactor: 0.5, + child: Container( + padding: EdgeInsets.symmetric(vertical: 48), + child: ListView.builder( + reverse: true, + itemCount: _infoString.length, + itemBuilder:(BuildContext context,int index) + { + if(_infoString.isEmpty) + { + return const Text("null"); + } + return Padding( + padding: const EdgeInsets.symmetric(vertical: 3,horizontal: 10), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Container( + padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 5), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5) + ), + child: Text( + _infoString[index], + style: const TextStyle(color:Colors.blueGrey), + ), + ), + + ) + ], + ), + ); + }, + ), + ), + ), + ), + ); + } + + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text("VideoCall"), + centerTitle: true, + actions: [ + IconButton(onPressed:() + { + setState(() { + viewPanel=!viewPanel; + }); + }, icon: const Icon(Icons.ice_skating)) + ], + ), + backgroundColor: Colors.black, + body: Center( + child: Stack( + children: [ + _viewRows(), + _panel(), + _toolbar(), + ] + ), + ), + ); + } +} diff --git a/lib/pages/index.dart b/lib/pages/index.dart new file mode 100644 index 0000000..de048ea --- /dev/null +++ b/lib/pages/index.dart @@ -0,0 +1,120 @@ +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter/material.dart'; +import 'package:async/async.dart'; +import 'dart:developer'; +import 'package:permission_handler/permission_handler.dart'; +import './call.dart'; +import 'package:flutter/material.dart' hide Size; +import 'dart:ui' as ui; + +class IndexPage extends StatefulWidget { + const IndexPage({Key? key}) : super(key: key); + + @override + State createState() => _IndexPageState(); +} + +class _IndexPageState extends State { + + TextEditingController _channelController = TextEditingController(text: 'call'); + + bool _validateError=false; + ClientRole? _role= ClientRole.Broadcaster; + + + @override + void dispose() { + _channelController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text("VideoCall"), + centerTitle: true, + ), + body: SingleChildScrollView( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + children: [ + const SizedBox(height: 20), + const SizedBox(height: 20), + TextField( + controller: _channelController, + decoration: InputDecoration( + errorText: _validateError ? 'Chanel Name is Mondatory' : null, + border: UnderlineInputBorder(borderSide: BorderSide(width: 1),), + hintText: 'channel name', + ), + ), + RadioListTile( + title: const Text('Broadcaster'), + onChanged: (ClientRole? value) + { + setState(() { + _role=value; + }); + }, + value: ClientRole.Broadcaster, + groupValue: _role, + ), + RadioListTile( + title: const Text('Audience'), + onChanged: (ClientRole? value) + { + setState(() { + _role=value; + }); + }, + value: ClientRole.Audience, + groupValue: _role, + ), + ElevatedButton( + onPressed: onjoin, + child: const Text('Join'), + style: ElevatedButton.styleFrom( + minimumSize: const ui.Size(double.infinity, 40), + ), + ) + ], + ), + ), + ), + ); + } + + Future onjoin() async { + setState(() { + _channelController.text.isEmpty + ? _validateError=true: + _validateError=false; // This line doesn't actually update any state + }); + + if(_channelController.text.isNotEmpty) + { + await _handlecameraAndMic(Permission.camera); + await _handlecameraAndMic(Permission.microphone); + await Navigator.push( + context, + MaterialPageRoute( + builder: (__) => CallPage( + channelName: _channelController.text, // Passes the text from _channelController as channelName + role: _role, // Passes the value of _role as role + ), + ), + ); + + + + } + } + + Future _handlecameraAndMic(Permission permission) async + { + final status=await permission.request(); + log(status.toString()); + } +} diff --git a/lib/settings.dart b/lib/settings.dart index e7aaba6..2f63e65 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -9,7 +9,6 @@ import 'package:healthcare_pharmacy/preloader.dart'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; import 'package:intl/intl.dart'; -import 'package:flutter_styled_toast/flutter_styled_toast.dart'; import 'dart:async'; import 'package:geolocator/geolocator.dart'; import 'package:dio/dio.dart'; @@ -29,6 +28,9 @@ const Color dashboardbackground = Color(0XFFF5F5F5); Color AppBarGradient_1 = Color(0XFF1258F6); +const appId="e5b593d506884e32856b5d6b1d72860f"; +const token="007eJxTYDibv+bcAy2rY7+OVHIEfQj1+/0y//Sai9e3BXUrfzsU+G65AkOqaZKppXGKqYGZhYVJqrGRhalZkmmKWZJhirmRhZlBmt9i4bSGQEaG63HbWBkZIBDEZ2FITszJYWAAAHfyIs8="; + TextStyle PreloaderText() { return TextStyle(color: Colors.blueAccent); } @@ -147,6 +149,8 @@ class AppSettings { static double userLatitude = 0; static double userLongitude = 0; static String healthpharmaIdsign = ''; + static String customerId = 'AHSUSNE1'; + static String healthpharmastaticid = '123456789'; static String profileImage = ''; static List storedPreferenceValidKeys = ['pharmacyname', 'access_token']; @@ -183,6 +187,7 @@ class AppSettings { static String createOffersUrl = host + 'addoffer'; static String createCompanyOffersUrl = host + 'addcompanyoffer'; static String getOffersActiveDataUrl = host + 'getActivePharmacyOfferdata'; + static String getApprovedOffersDataUrl = host + 'getapprovedPharmacyOfferdata'; static String getOffersinActiveDataUrl = host + 'getInActivePharmacyOfferdata'; static String updateOffersDataUrl = host + 'updateOffer'; @@ -205,6 +210,10 @@ class AppSettings { static String deleteDeliveryboyUrl = host + 'deletedeliveryboy'; static String getPharmacyAccountsUrl = host + 'pharmacyAccounts'; static String generateQRCodeUrl = host + 'generate-qrcode-pharmacy'; + static String getIdDataUrl = host + 'startConversation'; + static String acceptBookingRequestsUrl = host + 'assignDeliveryBoy'; + + static File? updatedImage; @@ -370,7 +379,36 @@ class AppSettings { } } + static Future assignDeliveryboyBookingRequests(var bookingId,payload) async { + var response = await http.post(Uri.parse(acceptBookingRequestsUrl + '/' + bookingId), + body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + try { + var _response = json.decode(response.body); + print(_response); + return true; + } catch (e) { + // display error toast + return false; + } + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.post(Uri.parse(acceptBookingRequestsUrl + '/' + bookingId), + body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } static Future generateQRCode() async { var uri = Uri.parse(generateQRCodeUrl + '/' + healthpharmaIdsign); @@ -590,6 +628,33 @@ class AppSettings { return ''; } } + + static Future getChatId() async { + //path parameter + var uri = Uri.parse(getIdDataUrl + '/' +healthpharmaIdsign ); + uri = uri.replace(query: 'customerId=$customerId'); + var response = await http.get(uri, headers: await buildRequestHeaders()); + var responcedatatemp=jsonDecode(response.body); + print("responcedata$responcedatatemp"); + print("responcedata$customerId"); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } static Future getApprovedOffers() async { //path parameter var uri = Uri.parse(getApprovedOffersDataUrl + '/' + healthpharmaIdsign); @@ -615,8 +680,8 @@ class AppSettings { static Future getCartDetails(bookingId) async { //path parameter - var uri = Uri.parse(getCartDataUrl + '/' + bookingId); - // uri = uri.replace(query: 'pharmacyId=$healthpharmaIdsign'); + var uri = Uri.parse(getCartDataUrl + '/' +healthpharmaIdsign ); + uri = uri.replace(query: 'bookingId=$bookingId'); var response = await http.get(uri, headers: await buildRequestHeaders()); var responcedatatemp=jsonDecode(response.body); print("responcedata$responcedatatemp"); @@ -659,8 +724,8 @@ class AppSettings { ] }); print("Timintgs"+body.toString()); - var uri = Uri.parse(addToCartDataUrl); - uri = uri.replace(query: 'pharmacyId=$healthpharmaIdsign'); + var uri = Uri.parse(addToCartDataUrl+ '/' + healthpharmaIdsign); + // uri = uri.replace(query: 'pharmacyId=$healthpharmaIdsign'); var response = await http.post( uri, headers: headers, @@ -680,7 +745,8 @@ class AppSettings { "additional_discount": additionalDiscont }); print("cartResponce"+body.toString()); - var uri = Uri.parse(getCartFinalAmmountUrl+ '/' + bookingId); + var uri = Uri.parse(getCartFinalAmmountUrl + '/' +healthpharmaIdsign ); + uri = uri.replace(query: 'bookingId=$bookingId'); var response = await http.post( uri, headers: headers, @@ -690,10 +756,6 @@ class AppSettings { return response; } - - - - static Future getPharmacyData() async { var uri = Uri.parse(getPharmacyDataUrl); var response = await http.get(uri, headers: await buildRequestHeaders()); @@ -1263,20 +1325,7 @@ class AppSettings { fontSize: 16.0); }*/ - static void longFailedStyledToast(String message, context) { - showToast( - message, - context: context, - animation: StyledToastAnimation.scale, - reverseAnimation: StyledToastAnimation.fade, - position: StyledToastPosition.bottom, - animDuration: Duration(seconds: 1), - duration: Duration(seconds: 6), - curve: Curves.elasticOut, - reverseCurve: Curves.linear, - backgroundColor: Colors.red, - ); - } + static void longFailedToast(String message) { Fluttertoast.showToast( msg: message, diff --git a/lib/viewpager.dart b/lib/viewpager.dart index 42fb436..c031e8d 100644 --- a/lib/viewpager.dart +++ b/lib/viewpager.dart @@ -549,8 +549,8 @@ class _ViewpagerState extends State { ); } else { Navigator.of(context, rootNavigator: true).pop(); - AppSettings.longFailedStyledToast( - "Offer upadtion failed", context); + AppSettings.longFailedToast( + "Offer upadtion failed"); Navigator.of(context).pop(); } } catch (exception) { @@ -558,7 +558,7 @@ class _ViewpagerState extends State { print(exception); } } else { - AppSettings.longFailedStyledToast("enter details", context); + AppSettings.longFailedToast("enter details"); } }, ), diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index f6f23bf..7299b5c 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,9 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index f16b4c3..786ff5c 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux url_launcher_linux ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index a6de6bf..ca8b907 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,10 +5,13 @@ import FlutterMacOS import Foundation +import agora_rtc_engine import cloud_firestore import device_info_plus_macos +import file_selector_macos import firebase_core import firebase_messaging +import firebase_storage import flutter_local_notifications import geolocator_apple import location @@ -18,10 +21,13 @@ import shared_preferences_foundation import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AgoraRtcEnginePlugin.register(with: registry.registrar(forPlugin: "AgoraRtcEnginePlugin")) FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) + FLTFirebaseStoragePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseStoragePlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin")) diff --git a/pubspec.lock b/pubspec.lock index f41f934..6004046 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,14 +7,21 @@ packages: name: _flutterfire_internals url: "https://pub.dartlang.org" source: hosted - version: "1.3.2" + version: "1.3.16" + agora_rtc_engine: + dependency: "direct main" + description: + name: agora_rtc_engine + url: "https://pub.dartlang.org" + source: hosted + version: "5.3.1" archive: dependency: transitive description: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.3.7" + version: "3.4.2" args: dependency: transitive description: @@ -79,26 +86,26 @@ packages: source: hosted version: "1.1.1" cloud_firestore: - dependency: "direct dev" + dependency: "direct main" description: name: cloud_firestore url: "https://pub.dartlang.org" source: hosted - version: "4.8.0" + version: "4.14.0" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "5.15.0" + version: "6.1.0" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web url: "https://pub.dartlang.org" source: hosted - version: "3.6.0" + version: "3.9.0" cloudinary_public: dependency: "direct dev" description: @@ -161,7 +168,7 @@ packages: name: dbus url: "https://pub.dartlang.org" source: hosted - version: "0.7.3" + version: "0.7.4" device_info_plus: dependency: "direct dev" description: @@ -217,7 +224,7 @@ packages: name: dio url: "https://pub.dartlang.org" source: hosted - version: "5.2.0+1" + version: "5.4.0" fake_async: dependency: transitive description: @@ -239,48 +246,97 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.1.4" - firebase_core: + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.2" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.3+1" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.6.0" + file_selector_windows: dependency: transitive + description: + name: file_selector_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.3" + firebase_core: + dependency: "direct main" description: name: firebase_core url: "https://pub.dartlang.org" source: hosted - version: "2.13.1" + version: "2.24.2" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.8.0" + version: "5.0.0" firebase_core_web: dependency: transitive description: name: firebase_core_web url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.10.0" firebase_messaging: - dependency: "direct dev" + dependency: "direct main" description: name: firebase_messaging url: "https://pub.dartlang.org" source: hosted - version: "14.6.2" + version: "14.7.10" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.5.2" + version: "4.5.18" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web url: "https://pub.dartlang.org" source: hosted - version: "3.5.2" + version: "3.5.18" + firebase_storage: + dependency: "direct main" + description: + name: firebase_storage + url: "https://pub.dartlang.org" + source: hosted + version: "11.6.0" + firebase_storage_platform_interface: + dependency: transitive + description: + name: firebase_storage_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.3" + firebase_storage_web: + dependency: transitive + description: + name: firebase_storage_web + url: "https://pub.dartlang.org" + source: hosted + version: "3.6.17" flutter: dependency: "direct main" description: flutter @@ -293,6 +349,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + flutter_callkeep: + dependency: "direct main" + description: + name: flutter_callkeep + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.2" flutter_cupertino_datetime_picker: dependency: "direct dev" description: @@ -327,9 +390,9 @@ packages: name: flutter_lints url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" flutter_local_notifications: - dependency: "direct dev" + dependency: "direct main" description: name: flutter_local_notifications url: "https://pub.dartlang.org" @@ -349,18 +412,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.0.0" - flutter_localizations: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" flutter_native_contact_picker: dependency: "direct dev" description: name: flutter_native_contact_picker url: "https://pub.dartlang.org" source: hosted - version: "0.0.4" + version: "0.0.6" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -382,20 +440,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" - flutter_styled_toast: - dependency: "direct dev" - description: - name: flutter_styled_toast - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" flutter_svg: dependency: "direct main" description: name: flutter_svg url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.1.6" flutter_svg_provider: dependency: "direct main" description: @@ -419,28 +470,35 @@ packages: name: fluttertoast url: "https://pub.dartlang.org" source: hosted - version: "8.2.2" + version: "8.2.4" + gallery_saver: + dependency: "direct dev" + description: + name: gallery_saver + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.2" geocoding: dependency: "direct dev" description: name: geocoding url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" geocoding_android: dependency: transitive description: name: geocoding_android url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.2" geocoding_ios: dependency: transitive description: name: geocoding_ios url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" geocoding_platform_interface: dependency: transitive description: @@ -461,35 +519,35 @@ packages: name: geolocator_android url: "https://pub.dartlang.org" source: hosted - version: "4.1.8" + version: "4.3.1" geolocator_apple: dependency: transitive description: name: geolocator_apple url: "https://pub.dartlang.org" source: hosted - version: "2.2.6" + version: "2.3.5" geolocator_platform_interface: dependency: transitive description: name: geolocator_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.0.7" + version: "4.1.0" geolocator_web: dependency: transitive description: name: geolocator_web url: "https://pub.dartlang.org" source: hosted - version: "2.1.6" + version: "2.2.1" geolocator_windows: dependency: transitive description: name: geolocator_windows url: "https://pub.dartlang.org" source: hosted - version: "0.1.1" + version: "0.1.3" get: dependency: "direct dev" description: @@ -524,7 +582,7 @@ packages: name: google_maps_flutter_android url: "https://pub.dartlang.org" source: hosted - version: "2.4.15" + version: "2.4.16" google_maps_flutter_ios: dependency: transitive description: @@ -538,14 +596,14 @@ packages: name: google_maps_flutter_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.2.7" + version: "2.4.0" google_maps_flutter_web: dependency: transitive description: name: google_maps_flutter_web url: "https://pub.dartlang.org" source: hosted - version: "0.5.0+1" + version: "0.5.3" google_maps_place_picker_mb: dependency: "direct dev" description: @@ -587,49 +645,63 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "3.1.3" + version: "3.3.0" image_picker: dependency: "direct dev" description: name: image_picker url: "https://pub.dartlang.org" source: hosted - version: "0.8.7+5" + version: "0.8.9" image_picker_android: dependency: transitive description: name: image_picker_android url: "https://pub.dartlang.org" source: hosted - version: "0.8.6+19" + version: "0.8.7+4" image_picker_for_web: dependency: transitive description: name: image_picker_for_web url: "https://pub.dartlang.org" source: hosted - version: "2.1.12" + version: "2.2.0" image_picker_ios: dependency: transitive description: name: image_picker_ios url: "https://pub.dartlang.org" source: hosted - version: "0.8.7+4" + version: "0.8.8" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.1" image_picker_platform_interface: dependency: transitive description: name: image_picker_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.6.4" - imei_plugin: - dependency: "direct dev" + version: "2.9.0" + image_picker_windows: + dependency: transitive description: - name: imei_plugin + name: image_picker_windows url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "0.2.1" intl: dependency: "direct dev" description: @@ -804,28 +876,28 @@ packages: name: path_provider_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.27" + version: "2.1.0" path_provider_foundation: dependency: transitive description: name: path_provider_foundation url: "https://pub.dartlang.org" source: hosted - version: "2.2.4" + version: "2.3.0" path_provider_linux: dependency: transitive description: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.11" + version: "2.2.0" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.6" + version: "2.1.0" path_provider_windows: dependency: transitive description: @@ -834,40 +906,40 @@ packages: source: hosted version: "2.0.7" permission_handler: - dependency: "direct dev" + dependency: "direct main" description: name: permission_handler url: "https://pub.dartlang.org" source: hosted - version: "10.3.0" + version: "10.4.5" permission_handler_android: dependency: transitive description: name: permission_handler_android url: "https://pub.dartlang.org" source: hosted - version: "10.2.3" + version: "10.3.6" permission_handler_apple: dependency: transitive description: name: permission_handler_apple url: "https://pub.dartlang.org" source: hosted - version: "9.1.0" + version: "9.1.4" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.10.0" + version: "3.12.0" permission_handler_windows: dependency: transitive description: name: permission_handler_windows url: "https://pub.dartlang.org" source: hosted - version: "0.1.2" + version: "0.1.3" petitparser: dependency: transitive description: @@ -888,14 +960,14 @@ packages: name: platform url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "3.1.1" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.5" pointycastle: dependency: transitive description: @@ -916,7 +988,7 @@ packages: name: provider url: "https://pub.dartlang.org" source: hosted - version: "6.0.5" + version: "6.1.1" pull_to_refresh: dependency: "direct dev" description: @@ -958,7 +1030,7 @@ packages: name: sanitize_html url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0" share: dependency: "direct dev" description: @@ -972,49 +1044,49 @@ packages: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.2.0" shared_preferences_android: dependency: transitive description: name: shared_preferences_android url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.2.0" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation url: "https://pub.dartlang.org" source: hosted - version: "2.2.2" + version: "2.3.3" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "2.3.0" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "2.3.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.2.0" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "2.3.0" sizer: dependency: "direct dev" description: @@ -1089,7 +1161,7 @@ packages: name: tuple url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" typed_data: dependency: transitive description: @@ -1105,7 +1177,7 @@ packages: source: hosted version: "2.2.0" url_launcher: - dependency: "direct dev" + dependency: "direct main" description: name: url_launcher url: "https://pub.dartlang.org" @@ -1117,7 +1189,7 @@ packages: name: url_launcher_android url: "https://pub.dartlang.org" source: hosted - version: "6.0.35" + version: "6.0.38" url_launcher_ios: dependency: transitive description: @@ -1138,28 +1210,28 @@ packages: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "3.0.5" + version: "3.0.6" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.3" url_launcher_web: dependency: transitive description: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.17" + version: "2.0.18" url_launcher_windows: dependency: transitive description: name: url_launcher_windows url: "https://pub.dartlang.org" source: hosted - version: "3.0.6" + version: "3.0.7" uuid: dependency: "direct main" description: @@ -1181,6 +1253,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.0+2" + web_socket_channel: + dependency: "direct main" + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" win32: dependency: transitive description: @@ -1201,7 +1280,7 @@ packages: name: xml url: "https://pub.dartlang.org" source: hosted - version: "5.4.1" + version: "6.1.0" yaml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index efa1442..2a09e0e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,7 +10,12 @@ dependencies: flutter: sdk: flutter - + firebase_core: ^2.24.2 + web_socket_channel: + flutter_callkeep: + url_launcher: ^6.0.10 + firebase_messaging: ^14.4.1 + flutter_local_notifications: ^9.0.2 cupertino_icons: ^1.0.2 location: ^4.4.0 geolocator: ^9.0.2 @@ -24,22 +29,28 @@ dependencies: uuid: ^3.0.7 flutter_svg_provider: ^1.0.3 flutter_svg: ^1.0.1 + agora_rtc_engine: ^5.3.1 + permission_handler: + cloud_firestore: + firebase_storage: + dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 http: ^0.13.5 + quantity_input: ^1.0.2 shared_preferences: ^2.0.15 sizer: ^2.0.11 geolocator: ^9.0.2 geocoding: ^2.0.4 image_picker: ^0.8.6+1 + gallery_saver: ^2.0.3 flutter_launcher_icons: ^0.11.0 url_launcher: ^6.1.9 intl: ^0.17.0 flutter_svg: ^1.0.1 - flutter_styled_toast: ^2.1.3 google_maps_place_picker_mb: ^2.0.0-mb.22 flutter_datetime_picker: ^1.5.1 date_time_picker: ^2.1.0 @@ -49,7 +60,6 @@ dev_dependencies: flutter_local_notifications: ^9.0.2 cloud_firestore: ^4.5.2 flutter_device_type: ^0.4.0 - imei_plugin: ^1.2.0 device_information: ^0.0.4 device_info_plus: ^3.2.4 overlay_support: ^2.1.0 @@ -63,7 +73,6 @@ dev_dependencies: cloudinary_public: ^0.21.0 carousel_slider: ^4.2.1 photo_view: ^0.14.0 - quantity_input: ^1.0.2 flutter_native_contact_picker: ^0.0.4 path: ^1.8.0 path_provider: ^2.0.11 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 2cd4f25..9e818bf 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,14 +6,26 @@ #include "generated_plugin_registrant.h" +#include +#include +#include #include +#include #include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + AgoraRtcEnginePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("AgoraRtcEnginePlugin")); + CloudFirestorePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("CloudFirestorePluginCApi")); + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); + FirebaseStoragePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseStoragePluginCApi")); GeolocatorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("GeolocatorWindows")); PermissionHandlerWindowsPluginRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 8ae151b..6f1c63a 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,7 +3,11 @@ # list(APPEND FLUTTER_PLUGIN_LIST + agora_rtc_engine + cloud_firestore + file_selector_windows firebase_core + firebase_storage geolocator_windows permission_handler_windows url_launcher_windows