diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index e9f7430..11eda48 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4..7508d4a 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b7..b641102 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 09d4391..2c094cd 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d..8b3a345 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372e..3793c60 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/images/appicon.png b/images/appicon.png index 6ee10c4..2339073 100644 Binary files a/images/appicon.png and b/images/appicon.png differ diff --git a/images/logo.png b/images/logo.png index 3982b86..2339073 100644 Binary files a/images/logo.png and b/images/logo.png differ diff --git a/images/mobilebg.png b/images/mobilebg.png index 5d42afb..11114b8 100644 Binary files a/images/mobilebg.png and b/images/mobilebg.png differ diff --git a/images/mobilebg2.png b/images/mobilebg2.png index 5ce3749..9984e87 100644 Binary files a/images/mobilebg2.png and b/images/mobilebg2.png differ diff --git a/images/mobilebg3.png b/images/mobilebg3.png index 8673834..691db75 100644 Binary files a/images/mobilebg3.png and b/images/mobilebg3.png differ diff --git a/images/myconnections.png b/images/myconnections.png index 00d4f80..b22e6af 100644 Binary files a/images/myconnections.png and b/images/myconnections.png differ diff --git a/images/splashscreen.png b/images/splashscreen.png index e1ce188..c15473b 100644 Binary files a/images/splashscreen.png and b/images/splashscreen.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index dc9ada4..34724f3 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 28c6bf0..7602b51 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 2ccbfd9..7f41342 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index f091b6b..41b38d4 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 4cde121..27348ad 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index d0ef06e..d3109f0 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index dcdc230..3f83127 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 2ccbfd9..7f41342 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index c8f9ed8..8429d37 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index a6d6b86..bed72f0 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index a6d6b86..bed72f0 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 75b2d16..696ff6e 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index c4df70d..e93cb24 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 6a84f41..31bc042 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index d0e1f58..2c5219c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/lib/common/dashboard.dart b/lib/common/dashboard.dart index 8974232..e0708e5 100644 --- a/lib/common/dashboard.dart +++ b/lib/common/dashboard.dart @@ -1,4 +1,7 @@ import 'dart:convert'; +import 'package:doctor/common/qrcode_display.dart'; +import 'package:doctor/common/updateprofile.dart'; +import 'package:doctor/connected_patients/connected_patients.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:image_picker/image_picker.dart'; @@ -129,24 +132,24 @@ class _DashboardState extends State { shape: BoxShape.circle, image: DecorationImage( image: AssetImage( - "images/seekopinion.png"), // picked file + "images/myconnections.png"), // picked file fit: BoxFit.fitWidth)), ), onTap: () { - /* Navigator.push( + Navigator.push( context, MaterialPageRoute( - builder: (context) => const SeekOpinion()), - );*/ + builder: (context) => const ConnectedPatients()), + ); }, ), Text( - 'Seek Opinion', + 'My Connections', style: dashboardTextStyle(), ), ], ), - Column( + /*Column( children: [ GestureDetector( child: Container( @@ -161,11 +164,11 @@ class _DashboardState extends State { fit: BoxFit.fitWidth)), ), onTap: () { - /*Navigator.push( + *//*Navigator.push( context, MaterialPageRoute( builder: (context) => const AllReports()), - );*/ + );*//* }, ), Text( @@ -173,11 +176,11 @@ class _DashboardState extends State { style: dashboardTextStyle(), ), ], - ), + ),*/ ], ), ), - Padding( + /*Padding( padding: EdgeInsets.all(10), child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -288,7 +291,7 @@ class _DashboardState extends State { ), ], ), - ) + )*/ ])); } @@ -298,16 +301,9 @@ class _DashboardState extends State { devicedetection(); } - /*Future uploadProfileApi(image) async { - var payload = new Map(); - payload["formData"] = image.toString(); - var response1 = await AppSettings.updateProfilePicture(payload); - - print(response1); - }*/ Future pickImageFromGallery() async { - /* try { + try { final image = await _picker.pickImage(source: ImageSource.gallery); if (image == null) return; final imageTemp = File(image.path); @@ -322,11 +318,11 @@ class _DashboardState extends State { AppSettings.saveData('profile', jsonDecode(res)['picture'], 'STRING'); } on PlatformException catch (e) { print('Failed to pick image: $e'); - }*/ + } } Future takeImageFromCamera() async { - /*try { + try { final image = await _picker.pickImage(source: ImageSource.camera); if (image == null) return; final imageTemp = File(image.path); @@ -340,7 +336,7 @@ class _DashboardState extends State { AppSettings.saveData('profile', jsonDecode(res)['picture'], 'STRING'); } on PlatformException catch (e) { print('Failed to pick image: $e'); - }*/ + } } showLogoutAlertDialog(context) { @@ -427,82 +423,143 @@ class _DashboardState extends State { children: [ DrawerHeader( decoration: const BoxDecoration( - color: buttonColors, + color: secondaryColor, ), child: Row( + children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: GestureDetector( - child: Container( - width: MediaQuery.of(context).size.width * .20, - height: + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + GestureDetector( + child: Container( + width: MediaQuery.of(context).size.width * .20, + height: MediaQuery.of(context).size.height * .15, - decoration: BoxDecoration( - shape: BoxShape.circle, - image: DecorationImage( - image: (AppSettings.profilePictureUrl != - '' && + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + image: (AppSettings.profilePictureUrl != + '' && AppSettings.profilePictureUrl != 'null') - ? NetworkImage(AppSettings - .profilePictureUrl) - as ImageProvider - : AssetImage( + ? NetworkImage(AppSettings + .profilePictureUrl) + as ImageProvider + : AssetImage( "images/profile_pic.png"), // picked file - fit: BoxFit.fitWidth)), - ), - onTap: () { - showModalBottomSheet( - context: context, - builder: (BuildContext context) { - return SizedBox( - height: 200, - child: Center( - child: Row( - mainAxisAlignment: + fit: BoxFit.fitWidth)), + ), + 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: primaryColor, - ), - onTap: () async { - await takeImageFromCamera(); - Navigator.pop(context); - }, - ), - SizedBox( - width: MediaQuery.of(context) + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCamera(); + Navigator.pop(context); + }, + ), + SizedBox( + width: MediaQuery.of(context) .size .width * - .20, - ), - GestureDetector( - child: Icon( - Icons.photo, - size: 100, - color: primaryColor, - ), - onTap: () async { - await pickImageFromGallery(); - Navigator.pop(context); - }, + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGallery(); + Navigator.pop(context); + }, + ), + ], ), - ], - ), - ), + ), + ); + }); + }, + ), + Container( + + child: AppSettings.qrCode==''?TextButton( + child: Text( + 'GetQR', + style: TextStyle( + fontSize: 15, + color: Colors.white, + decoration: TextDecoration.underline, + ), + ), + onPressed: () async{ + AppSettings.preLoaderDialog(context); + + try{ + var value = await AppSettings.generateQRCode(); + var valueResponse = jsonDecode(value); + String dataUri = jsonDecode(value)['qrCodeData']; + + List parts = dataUri.split(","); + String? base64String = parts.length == 2 ? parts[1] : null; + + if (base64String != null) { + + print(base64String); + AppSettings.qrCode=base64String; + } else { + print("Invalid data URI"); + } + Navigator.of(context, rootNavigator: true).pop(); + } + catch(e){ + Navigator.of(context, rootNavigator: true).pop(); + } + + + + }, + ):GestureDetector( + onTap: (){ + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const DisplayQrCode()), ); - }); - }, + }, + child: Container( + height:MediaQuery.of(context).size.height * .20, + width:MediaQuery.of(context).size.width * .1, + child: Image.memory(Uint8List.fromList(base64.decode(AppSettings.qrCode))), + ), + ), + + ) + ], ), ), Text( - AppSettings.userName, + AppSettings.doctorName, style: drawerHeaderTextStyleNew(), ), Text( @@ -536,7 +593,8 @@ class _DashboardState extends State { ) ], ), - Container() + + ], )), ListTile( @@ -557,14 +615,14 @@ class _DashboardState extends State { ], ), onTap: () { - /*Navigator.push( + Navigator.push( context, MaterialPageRoute( builder: (context) => const UpdateProfile()), - );*/ + ); }, ), - Divider( + /*Divider( color: Colors.grey, ), ListTile( @@ -757,6 +815,7 @@ class _DashboardState extends State { }, ), + */ Divider( color: Colors.grey, ), diff --git a/lib/common/login.dart b/lib/common/login.dart index 1353d46..370980e 100644 --- a/lib/common/login.dart +++ b/lib/common/login.dart @@ -104,6 +104,7 @@ class _LoginState extends State { child: TextFormField( cursorColor: greyColor, controller: mobileNumberController, + style: textFormFieldFilledTextStyle(), keyboardType: TextInputType.number, decoration: textFormFieldDecoration(Icons.phone,'Enter MobileNumber'), @@ -112,29 +113,30 @@ class _LoginState extends State { SizedBox(height:MediaQuery.of(context).size.height * .02,), Container( child: TextFormField( - cursorColor: greyColor, + cursorColor: secondaryColor, obscureText: isObscureText, controller: passwordController, + style: textFormFieldFilledTextStyle(), decoration: InputDecoration( - fillColor: Colors.white, + fillColor: primaryColor, filled: true, labelText: 'Password', - prefixIcon: const Icon(Icons.password, color: greyColor,), + prefixIcon: const Icon(Icons.lock, color: secondaryColor,), labelStyle: const TextStyle( - color: Colors.black, //<-- SEE HERE + color: secondaryColor,fontWeight: FontWeight.bold //<-- SEE HERE ), border: const OutlineInputBorder( - borderSide: BorderSide(color: primaryColor)), + borderSide: BorderSide(color: secondaryColor)), focusedBorder: const OutlineInputBorder( - borderSide: BorderSide(color: primaryColor), + borderSide: BorderSide(color: secondaryColor), ), enabledBorder: const OutlineInputBorder( - borderSide: BorderSide(color: primaryColor), + borderSide: BorderSide(color: secondaryColor), ), suffixIcon: IconButton( icon: Icon( Icons.visibility_off_outlined, - color: isObscureText==true?greyColor:primaryColor, + color: isObscureText==true?greyColor:secondaryColor, ), onPressed: () { @@ -181,7 +183,7 @@ class _LoginState extends State { ), onPressed: () async{ - /* if (mobileNumberController.text != '' && + if (mobileNumberController.text != '' && passwordController.text != '') { AppSettings.preLoaderDialog(context); @@ -227,7 +229,7 @@ class _LoginState extends State { else{ AppSettings.longFailedToast("Please enter valid details"); - }*/ + } }, child: const Text('Login'), diff --git a/lib/common/otpscreen.dart b/lib/common/otpscreen.dart index e86df62..638e273 100644 --- a/lib/common/otpscreen.dart +++ b/lib/common/otpscreen.dart @@ -162,7 +162,7 @@ class _OtpScreenState extends State { _fieldSix.text; }); - /*if (_otp!.length == 6) { + if (_otp!.length == 6) { AppSettings.preLoaderDialog(context); bool isOnline = await AppSettings.internetConnectivity(); @@ -200,7 +200,7 @@ class _OtpScreenState extends State { } else{ - }*/ + } }, child: const Text('Submit')), ) diff --git a/lib/common/qrcode_display.dart b/lib/common/qrcode_display.dart new file mode 100644 index 0000000..06a9429 --- /dev/null +++ b/lib/common/qrcode_display.dart @@ -0,0 +1,123 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:ui'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:flutter_share/flutter_share.dart'; +import 'package:share/share.dart'; +import 'dart:typed_data'; +import 'package:path_provider/path_provider.dart'; +import 'package:http/http.dart' as http; + + + +class DisplayQrCode extends StatefulWidget { + const DisplayQrCode({Key? key}) : super(key: key); + + @override + State createState() => _DisplayQrCodeState(); +} + +class _DisplayQrCodeState extends State { + + + + Future share(var qr) async { + await FlutterShare.share( + title: 'Example share', + text: 'Example share text', + linkUrl: qr, + chooserTitle: 'Example Chooser Title'); + } + + Future shareQRCodeImage1(qrData) async { + + final tempDir = await getTemporaryDirectory(); + final file = File('${tempDir.path}/qr_code.png'); + await file.writeAsBytes(Uint8List.fromList(base64.decode(qrData))); + + // Share the image using the share package + Share.shareFiles([file.path], text: 'Check out this QR code'); + + } + + String imagePath = ''; + + Future downloadQRImage() async { + final response = await http.get(Uri.parse(AppSettings.qrCode)); + + if (response.statusCode == 200) { + final directory = await getApplicationDocumentsDirectory(); + final filePath = '${directory.path}/qr_image.png'; + + final File file = File(filePath); + await file.writeAsBytes(response.bodyBytes); + + setState(() { + imagePath = filePath; + }); + } + } + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Qr Code'), + body: Container( + child: Padding(padding: EdgeInsets.all(10), + child: Column( + children: [ + Center( + child: Container( + padding: EdgeInsets.fromLTRB(0, 20, 0, 0), + width: MediaQuery.of(context).size.width * .60, // Set the desired width + height: MediaQuery.of(context).size.height * .35, // Set the desired height + child: + Image.memory(Uint8List.fromList(base64.decode(AppSettings.qrCode),), + fit: BoxFit.fill), + ), + ), + SizedBox( + height:MediaQuery.of(context).size.height * .05, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + IconButton( + onPressed: () { + //share(AppSettings.qrCode); + shareQRCodeImage1(AppSettings.qrCode); + }, + icon: Icon( + Icons.share, + color: primaryColor, + size: 40, + ), + ), + /*IconButton( + onPressed: () { + downloadQRImage(); + }, + icon: Icon( + Icons.download, + color: primaryColor, + size: 40, + ), + ),*/ + ], + ) + /*Container( + padding: EdgeInsets.fromLTRB(0, 20, 0, 0), + child: Center(child: Image.memory(Uint8List.fromList(base64.decode(AppSettings.qrCode),),),), + )*/ + + ], + ),), + ), + ); + + } +} diff --git a/lib/common/settings.dart b/lib/common/settings.dart index 159b5ea..31dea47 100644 --- a/lib/common/settings.dart +++ b/lib/common/settings.dart @@ -1,20 +1,19 @@ import 'dart:io'; -import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'dart:convert'; import 'package:flutter/services.dart'; import 'package:doctor/common/preloader.dart'; -import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; import 'package:intl/intl.dart'; import 'dart:async'; import 'package:geolocator/geolocator.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:http/http.dart' as http; //const Color primaryColor = Color(0XFF1786A3); const Color primaryColor = Color(0XFF99405B); -const Color secondaryColor = Color(0XFFA0C899); -const Color buttonColors = Color(0XFFFFAC1C); +const Color secondaryColor = Color(0XFFD9D9D9); +const Color buttonColors = Color(0XFF1786A3); const Color greyColor = Color(0XFF8F8E8E); const Color textFieldStartColor = Colors.grey; const Color screenBackgroundColor = Color(0XFFEAF6FF); @@ -22,10 +21,10 @@ const Color screenBackgroundColord = Colors.black12; const Color dashboardbackground = Color(0XFFF5F5F5); //Color AppBarGradient_1 = Color(0XFF1258F6); -Color AppBarGradient_1 = Color(0XFF68A85D); +Color AppBarGradient_1 = Color(0XFF99405B); TextStyle PreloaderText() { - return TextStyle(color: Color(0XFF68A85D)); + return TextStyle(color: Color(0XFF99405B)); } TextStyle labelTextStyle() { @@ -170,24 +169,32 @@ TextStyle drawerHeaderTextStyleNew() { return TextStyle(color: Colors.black, fontSize: 15); } +TextStyle textFormFieldFilledTextStyle() { + return TextStyle(color: secondaryColor); +} + + InputDecoration textFormFieldDecoration(IconData icon, var text) { return InputDecoration( filled: true, - fillColor: Colors.white, + fillColor: primaryColor, prefixIcon: Icon( icon, - color: greyColor, + color: secondaryColor, ), - border: OutlineInputBorder(borderSide: BorderSide(color: primaryColor)), + border: OutlineInputBorder(borderSide: BorderSide(color: secondaryColor)), focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: primaryColor), + borderSide: BorderSide(color: secondaryColor), ), enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: primaryColor), + borderSide: BorderSide(color: secondaryColor), ), labelText: text, + /*labelStyle: TextStyle( + color: myFocusNode.hasFocus ? Colors.blue : Colors.black + )*/ labelStyle: TextStyle( - color: Colors.black, //<-- SEE HERE + color: secondaryColor,fontWeight: FontWeight.bold //<-- SEE HERE ), ); } @@ -224,19 +231,28 @@ Future preloaderWindow(BuildContext context) async { class AppSettings { static SharedPreferences sharedPreferences = SharedPreferences.getInstance() as SharedPreferences; - static String userName = ''; - static String userAddress = ''; + static String doctorName = ''; + static String specialization = ''; + static String qualification = ''; + static List placeOfPractices = []; + static String placeOfPractice1 = ''; + static String placeOfPractice2 = ''; + static String placeOfPractice3 = ''; + static String placeOfPracticeAddress1 = ''; + static String placeOfPracticeAddress2 = ''; + static String placeOfPracticeAddress3 = ''; + static String doctorAddress = ''; static String email = ''; static String age = ''; static String gender = ''; static String phoneNumber = ''; static String accessToken = ''; - static String customerId = ''; - static double userLatitude = 0; - static double userLongitude = 0; + static String doctorId = ''; + static double doctorLatitude = 0; + static double doctorLongitude = 0; static String customerIdsign = ''; static String profileImage = ''; - static List storedPreferenceValidKeys = ['username', 'access_token']; + static List storedPreferenceValidKeys = ['doctorname', 'access_token']; static String preloadText = 'Please wait'; static String latitude = ''; static String longitude = ''; @@ -250,75 +266,31 @@ class AppSettings { static String serverToken = 'AAAAA66BLaA:APA91bHcmbyiNN8hCL-t-M9oH-u7ZMOl74fcImMM2DQZLgdyY98Wu9XxME-CTPcjpjU6Yy48ouxISrOMb9lpa3PJofh8qciUKMNxV2al-bDvGvPP_VVaH0mrTHzR56hdkGy1Zl-0frDO'; + static String qrCode = ''; + static String originalQrCode = ''; + + //api urls - static String host = 'http://35.200.129.165:4000/api/'; - static String loginUrl = host + 'login'; - static String signUpUrl = host + 'users'; + //static String host = 'http://35.200.129.165:4000/api/'; + static String host = 'http://cloudh.in:4000/api/'; + static String loginUrl = host + 'doctorlogin'; + static String signUpUrl = host + 'addDoctor'; static String sendSmsUrl = host + 'sendSms'; - static String phoneVerificationUrl = host + 'phone'; - static String verifyPhnUrl = host + 'phone'; + static String phoneVerificationUrl = host + 'doctorphone'; + static String uploadPicUrl = host + 'uploadsDoctorProfilePicture'; + static String updateProfileUrl = host + 'updateDoctor'; static String resetTokenUrl = host + 'reset_token'; - static String bmiCaluculateUrl = host + 'insertBMI'; - static String bpCaluculateUrl = host + 'insertBP'; - static String sugarCaluculateUrl = host + 'insertSugar'; - static String profilePicUrl = host + 'users/profile-picture'; - static String inviteFriendUrl = host + 'sendInviteLink'; - static String updateProfileUrl = host + 'update/currentUser'; - static String updateLocationUrl = host + 'updateLocation'; - static String uploadPicUrl = host + 'uploads'; - static String getBmiHistoryUrl = host + 'usersbmi'; - static String getBpHistoryUrl = host + 'usersbp'; - static String getSugarHistoryUrl = host + 'userssugar'; - static String addMedicineTimingsUrl = host + 'medicine-timing'; - static String updateMedicineTimingsUrl = host + 'update-medicine-timing'; - static String getMedicineTimingsUrl = host + 'getmedicineztiming'; - static String findingsUploadPicUrl = host + 'uploads-findings-prescription'; - static String addFindingsUrl = host + 'update-uploads-findingsPictureId-prescription'; - static String addReportsUrl = host + 'update-uploads-reportsPictureId-prescription'; - static String addPrescriptionsUrl = host + 'update-uploads-prescriptionPictureId-prescription'; - static String updateFindingsUploadPicUrl = host + 'update-uploads-findings-prescription'; - static String updateReportsUploadPicUrl = host + 'update-uploads-reports-prescription'; - static String reportsUploadPicUrl = host + 'uploads-reports-prescription'; - static String prescriptionUploadPicUrl = host + 'uploads-prescription-prescription'; - static String updatePrescriptionPicUrl = host + 'update-uploads-prescription-prescription'; - static String recordPrescriptionsUploadPicUrl = host + 'uploads-prescription-prescription'; - static String getAllpharmaciesDataUrl = host + 'getAllPharmacylist'; - static String getAllQuotationRequestsUrl = host + 'userprecription'; - static String getQuotationUrl = host + 'submitPicture'; - static String addPrescriptionUrl = host + 'add-prescription-details'; - static String addRecordsUrl = host + 'add-record'; - static String updateRecordsUrl = host + 'records'; - static String reportMySelfVideoUploadUrl = host + 'reportProblemVideo'; - static String uploadReportMyselfPictureUrl = host + 'reportProblemPicture'; - - //static String getAllPrescriptionsDataUrl = host + 'usersinglerprecription'; - static String getAllPrescriptionsDataUrl = host + 'getAllPrescriptionDetails'; + static String generateQRCodeUrl = host + 'generate-qrcode-doctor'; + static String getAllConectedPatientsDataUrl = host + 'customerDetails'; static String getRecordsDataUrl = host + 'getAllRecords'; - static String deleteRecordUrl = host + 'deleteRecord'; - static String deleteFindingsUrl = host + 'delete-uploads-findings'; - static String deletePrescriptionsUrl = host + 'delete-prescription'; - static String deleteReportsUrl = host + 'delete-report'; - static String deleteRecordsUrl = host + 'delete-url'; - static String deleteBMIDetailsUrl = host + 'deleteBMI'; - static String deleteBPDetailsUrl = host + 'deleteBP'; - static String deleteSugarDetailsUrl = host + 'deleteSugar'; - static String addReportMySelfProblemUrl = host + 'insertReport'; - static String getAllReportProblemDetalisUrl = host + 'userreport'; - static String deleteReportMySelfProblemUrl = host + 'deleteReportProblem'; - - - - - + static String getDynamicCodeUrl = host + 'records'; + static String dynamicCodeVerificationUrl = host + 'verifyDynamicCode'; static File? updatedImage; static String image = ''; static String profilePictureUrl = ''; - static var api = { - 'signIn': host + '/login', - }; /*Formatter*/ static String formNum(String s) { @@ -337,6 +309,7 @@ class AppSettings { /* Preloader */ static GlobalKey preLoaderKey = new GlobalKey(); + static Future preLoaderDialog(BuildContext context) async { try { preLoaderKey = new GlobalKey(); @@ -359,8 +332,7 @@ class AppSettings { return _headers; } - static Future> - buildPutRequestHeadersForResetToken() async { + static Future> buildPutRequestHeadersForResetToken() async { Map _headers = new Map(); return _headers; } @@ -378,6 +350,9 @@ class AppSettings { } else if (type == 'DOUBLE') { await sharedPreferences.setDouble(_key, _value); } + else if (type == 'LIST') { + await sharedPreferences.setStringList(_key, _value); + } } static getData(String _key, type) async { @@ -391,6 +366,9 @@ class AppSettings { } else if (type == 'DOUBLE') { return sharedPreferences.getDouble(_key) ?? -1; } + else if (type == 'LIST') { + return sharedPreferences.getStringList(_key) ?? -1; + } } static clearSharedPrefeences() async { @@ -423,19 +401,279 @@ class AppSettings { /*Apis Starts here*/ + static Future signUp(payload) async { + var response = await http.post(Uri.parse(signUpUrl), + body: json.encode(payload), + headers: {'Content-type': 'application/json'}); + + if (response.statusCode == 200) { + try { + var _response = json.decode(response.body); + print(_response); + return true; + } catch (e) { + // display error toast + return false; + } + } else { + return false; + } + } + + static Future sendSms(payload) async { + var response = await http.post(Uri.parse(sendSmsUrl), + body: json.encode(payload), + headers: {'Content-type': 'application/json'}); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } + + static Future phoneVerification(payload) async { + var response = await http.post(Uri.parse(phoneVerificationUrl), + body: json.encode(payload), + headers: {'Content-type': 'application/json'}); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } + + static Future login(payload) async { + var response = await http.post(Uri.parse(loginUrl), + body: json.encode(payload), + headers: {'Content-type': 'application/json'}); + + if (response.statusCode == 200) { + try { + var _response = json.decode(response.body); + + if (_response['simplydata']['error'] == false) { + await saveAvailableReportAndLocationsInMemory(_response); + //await saveProfilePic(_response); + return true; + } else { + return false; + } + } catch (e) { + // display error toast + return false; + } + } else { + return false; + } + } + + static Future resetToken() async { + var uri = Uri.parse(resetTokenUrl + '/' + doctorId); + + try { + // var response = await http.get(uri, headers: await buildPutRequestHeaders()); + var response = await http.get(uri, + headers: await buildPutRequestHeadersForResetToken()); + if (response.statusCode == 200) { + print(response.body); + var res = jsonDecode(response.body); + print(res); + + accessToken = res['access_token']; + return true; + } else { + return false; + } + } catch (e) { + print(e); + return false; + } + } + + static Future uploadImageHTTPNew(file) async { + var request = http.MultipartRequest( + 'POST', Uri.parse(uploadPicUrl + '/' + doctorId)); + request.files.add(await http.MultipartFile.fromPath('picture', file.path)); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future updateProfile(payload) async { + var uri = Uri.parse(updateProfileUrl + '/' + doctorId); + try { + var response = await http.put(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + var _response = json.decode(response.body); + + doctorName = _response['armintahealthdata']['doctorName']; + phoneNumber = _response['armintahealthdata']['phone']; + email = _response['armintahealthdata']['emails'][0]['email']; + age = _response['armintahealthdata']['age'].toString(); + gender=_response['armintahealthdata']['gender'].toString(); + specialization=_response['armintahealthdata']['specialization'].toString(); + qualification=_response['armintahealthdata']['qualification'].toString(); + if(_response['armintahealthdata']['placeOfPractice'].length>0){ + placeOfPractice1=_response['armintahealthdata']['placeOfPractice'][0]['hospitalName']??''; + placeOfPracticeAddress1=_response['armintahealthdata']['placeOfPractice'][0]['address']??''; + } + + + await saveData('phone', _response['armintahealthdata']['phone'], 'STRING'); + await saveData('email', _response['armintahealthdata']['emails'][0]['email'], 'STRING'); + await saveData('doctorname', _response['armintahealthdata']['doctorName'], 'STRING'); + await saveData('age', _response['armintahealthdata']['age'].toString(), 'STRING'); + await saveData('specialization', _response['armintahealthdata']['specialization'], 'STRING'); + await saveData('qualification', _response['armintahealthdata']['qualification'], 'STRING'); + await saveData('gender', _response['armintahealthdata']['gender'], 'STRING'); + if(_response['armintahealthdata']['placeOfPractice'].length>0){ + await saveData('placeOfPractice1',_response['armintahealthdata']['placeOfPractice'][0]['hospitalName']??'', 'STRING'); + await saveData('placeOfPracticeAddress1', _response['armintahealthdata']['placeOfPractice'][0]['address']??'', 'STRING'); + } + + await loadDataFromMemory(); + return true; + } else { + return false; + } + } catch (e) { + print(e); + return false; + } + } + + static Future generateQRCode() async { + var uri = Uri.parse(generateQRCodeUrl + '/' + doctorId); + + var response = await http.post(uri, headers: await buildPutRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.post(uri, headers: await buildPutRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } + + static Future getAllConectedPatients() async { + var uri = Uri.parse(getAllConectedPatientsDataUrl + '/' + doctorId); + //uri = uri.replace(query: 'customerId=$customerId'); + + var response = await http.get(uri, headers: await buildRequestHeaders()); + 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 getAllRecords(customerId) async { + var uri = Uri.parse(getRecordsDataUrl + '/' + customerId); + //uri = uri.replace(query: 'customerId=$customerId'); + + var response = await http.get(uri, headers: await buildRequestHeaders()); + 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 getDynamicCode(payload) async { + var uri = Uri.parse(getDynamicCodeUrl ); + //uri = uri.replace(query: 'customerId=$customerId'); + + var response = await http.post(uri,body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.post(uri,body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } + + static Future dynamicCodeVerification(payload) async { + var uri = Uri.parse(dynamicCodeVerificationUrl + '/'+doctorId); + var response = await http.post(uri, body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } + else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.post(uri, body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } else { + return false; + } + }else { + return false; + } + } + + /*Apis ends here*/ //save data local - static Future saveAvailableReportAndLocationsInMemory( - dynamic input) async { + static Future saveAvailableReportAndLocationsInMemory(dynamic input) async { // save login name information - await saveData('username', input['simplydata']['username'], 'STRING'); - await saveData( - 'access_token', input['simplydata']['access_token'], 'STRING'); + await saveData('doctorname', input['simplydata']['doctorName'], 'STRING'); + await saveData('access_token', input['simplydata']['access_token'], 'STRING'); await saveData('phone', input['simplydata']['phone'], 'STRING'); await saveData('email', input['simplydata']['email'][0]['email'], 'STRING'); - await saveData('customerId', input['simplydata']['customerId'], 'STRING'); + await saveData('doctorId', input['simplydata']['doctorId'], 'STRING'); await saveData('profile', input['simplydata']['picture'], 'STRING'); await saveData('user_address', input['simplydata']['address1'], 'STRING'); await saveData('latitude', input['simplydata']['latitude'], 'DOUBLE'); @@ -443,24 +681,56 @@ class AppSettings { await saveData('fcmId', input['simplydata']['fcmId'], 'STRING'); await saveData('age', input['simplydata']['age'], 'STRING'); await saveData('gender', input['simplydata']['gender'], 'STRING'); + await saveData('qrCode', input['simplydata']['qrCode'], 'STRING'); + await saveData('specialization', input['simplydata']['specialization'], 'STRING'); + await saveData('qualification', input['simplydata']['qualification'], 'STRING'); + if(input['simplydata']['placeOfPractice'].length>0){ + await saveData('placeOfPractice1', input['simplydata']['placeOfPractice'][0]['hospitalName']??'', 'STRING'); + await saveData('placeOfPractice2', input['simplydata']['placeOfPractice'][1]['hospitalName']??'', 'STRING'); + await saveData('placeOfPractice3', input['simplydata']['placeOfPractice'][2]['hospitalName']??'', 'STRING'); + await saveData('placeOfPracticeAddress1', input['simplydata']['placeOfPractice'][0]['address']??'', 'STRING'); + await saveData('placeOfPracticeAddress2', input['simplydata']['placeOfPractice'][1]['address']??'', 'STRING'); + await saveData('placeOfPracticeAddress3', input['simplydata']['placeOfPractice'][2]['address']??'', 'STRING'); + } + //await saveData('age', input['simplydata']['age'], 'STRING'); //latitude,longitude await loadDataFromMemory(); } static Future loadDataFromMemory() async { - userName = await getData('username', 'STRING'); + doctorName = await getData('doctorname', 'STRING'); accessToken = await getData('access_token', 'STRING'); email = await getData('email', 'STRING'); - userAddress = await getData('user_address', 'STRING'); + doctorAddress = await getData('user_address', 'STRING'); phoneNumber = await getData('phone', 'STRING'); - customerId = await getData('customerId', 'STRING'); - userLatitude = await getData('latitude', 'DOUBLE'); - userLongitude = await getData('longitude', 'DOUBLE'); + doctorId = await getData('doctorId', 'STRING'); + doctorLatitude = await getData('latitude', 'DOUBLE'); + doctorLongitude = await getData('longitude', 'DOUBLE'); profilePictureUrl = await getData('profile', 'STRING'); + specialization= await getData('specialization', 'STRING'); + qualification= await getData('qualification', 'STRING'); fcmId = await getData('fcmId', 'STRING'); age = await getData('age', 'STRING'); gender = await getData('gender', 'STRING'); + originalQrCode = await getData('qrCode', 'STRING'); + String dataUri = originalQrCode; + +// Split the data URI at the comma to extract the Base64 part + List parts = dataUri.split(","); + String? base64String = parts.length == 2 ? parts[1] : null; + + if (base64String != null) { + qrCode=base64String; + } else { + print("Invalid data URI"); + } + placeOfPractice1= await getData('placeOfPractice1', 'STRING'); + placeOfPractice2= await getData('placeOfPractice2', 'STRING'); + placeOfPractice3= await getData('placeOfPractice3', 'STRING'); + placeOfPracticeAddress1= await getData('placeOfPracticeAddress1', 'STRING'); + placeOfPracticeAddress2= await getData('placeOfPracticeAddress2', 'STRING'); + placeOfPracticeAddress3= await getData('placeOfPracticeAddress3', 'STRING'); } diff --git a/lib/common/signup.dart b/lib/common/signup.dart index 2c76a4e..cc59239 100644 --- a/lib/common/signup.dart +++ b/lib/common/signup.dart @@ -36,6 +36,10 @@ class _SignUpState extends State { TextEditingController userAddressCapturingController = TextEditingController(); TextEditingController passwordController = TextEditingController(); TextEditingController confirmPasswordController = TextEditingController(); + FocusNode myFocusNode = new FocusNode(); + String? gender; + + var genderUnitItems = [ 'Male', 'Female', @@ -65,11 +69,6 @@ class _SignUpState extends State { isConfirmPwdObscureText = true; super.initState(); } - - - - - PickResult? selectedPlace; bool _mapsInitialized = false; @@ -163,6 +162,7 @@ class _SignUpState extends State { child: Padding( padding: EdgeInsets.all(10), child: Column( + children: [ SizedBox( @@ -180,15 +180,15 @@ class _SignUpState extends State { ), Container( child: TextFormField( - cursorColor: greyColor, - controller: nameController, - textCapitalization: TextCapitalization.words, - decoration: textFormFieldDecoration(Icons.person,'Enter Name'), - - ), + cursorColor: secondaryColor, + controller: nameController, + style: textFormFieldFilledTextStyle(), + textCapitalization: TextCapitalization.words, + decoration: textFormFieldDecoration(Icons.person,'Enter Name'), + ), ), //name - SizedBox(height:MediaQuery.of(context).size.height * .02,), - Container( + + /*Container( child: DropdownButtonFormField( // Initial Value value: genderUnit, @@ -235,13 +235,14 @@ class _SignUpState extends State { genderUnit = newValue!; }); }, - ),), + ),),*/ SizedBox(height:MediaQuery.of(context).size.height * .02,), Container( child: TextFormField( - cursorColor: greyColor, + cursorColor: secondaryColor, controller: mobileNumberController, keyboardType: TextInputType.phone, + style: textFormFieldFilledTextStyle(), maxLength: 10, decoration: textFormFieldDecoration(Icons.phone_android,'Enter Mobile Number'), ), @@ -250,8 +251,9 @@ class _SignUpState extends State { GestureDetector( child: Container( child: TextFormField( - cursorColor: greyColor, + cursorColor: secondaryColor, controller: userAddressCapturingController, + style: textFormFieldFilledTextStyle(), onTap:() { @@ -356,6 +358,7 @@ class _SignUpState extends State { }, keyboardType: TextInputType.streetAddress, readOnly: true, + decoration:textFormFieldDecoration(Icons.location_on_rounded,'Click to select address(map)'), ), @@ -367,42 +370,85 @@ class _SignUpState extends State { SizedBox(height:MediaQuery.of(context).size.height * .02,), Container( child: TextFormField( - cursorColor: greyColor, + cursorColor: secondaryColor, controller: userAddressDescriptionController, - keyboardType: TextInputType.emailAddress, + style: textFormFieldFilledTextStyle(), decoration: textFormFieldDecoration(Icons.plagiarism_outlined,'Address Description (Ex: Flat No)'), ), ),//address description SizedBox(height:MediaQuery.of(context).size.height * .02,), + Text('Select Gender',style: textFormFieldFilledTextStyle(),), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + Expanded(child: RadioListTile( + title: Text("Male",style: TextStyle(color: secondaryColor,fontSize: 11)), + value: "male", + groupValue: gender, + activeColor: secondaryColor, + onChanged: (value){ + setState(() { + gender = value.toString(); + }); + }, + ),), + Expanded(child: RadioListTile( + title: Text("Female",style:TextStyle(color: secondaryColor,fontSize: 11)), + value: "female", + groupValue: gender, + activeColor: secondaryColor, + onChanged: (value){ + setState(() { + gender = value.toString(); + }); + }, + ),), + Expanded(child: RadioListTile( + title: Text("Others",style: TextStyle(color: secondaryColor,fontSize: 11)), + value: "other", + groupValue: gender, + activeColor: secondaryColor, + + onChanged: (value){ + setState(() { + gender = value.toString(); + }); + }, + ),), + ], + ), Container( child: TextFormField( - cursorColor: greyColor, + cursorColor: secondaryColor, obscureText: isPwdObscureText, controller: passwordController, + style: textFormFieldFilledTextStyle(), decoration: InputDecoration( - fillColor: Colors.white, + fillColor: primaryColor, filled: true, labelText: 'Create Password', prefixIcon: const Icon( Icons.lock, - color: greyColor, + color: secondaryColor, ), labelStyle: const TextStyle( - color: Colors.black, //<-- SEE HERE + color: secondaryColor,fontWeight: FontWeight.bold //<-- SEE HERE ), border: const OutlineInputBorder( - borderSide: BorderSide(color: primaryColor)), + borderSide: BorderSide(color: secondaryColor)), focusedBorder: const OutlineInputBorder( - borderSide: BorderSide(color: primaryColor), + borderSide: BorderSide(color: secondaryColor), ), enabledBorder: const OutlineInputBorder( - borderSide: BorderSide(color: primaryColor), + borderSide: BorderSide(color: secondaryColor), ), suffixIcon: IconButton( icon: Icon( Icons.visibility_off_outlined, - color: isPwdObscureText?greyColor:primaryColor, + color: isPwdObscureText?greyColor:secondaryColor, ), onPressed: () { setState(() { @@ -423,73 +469,75 @@ class _SignUpState extends State { onPrimary: Colors.black, // foreground ), onPressed: () async { - /* if (nameController.text != '' && + + + if (nameController.text != '' && passwordController.text != '' && - mobileNumberController.text != '') { - AppSettings.preLoaderDialog(context); - - var payload = new Map(); - payload["username"] = nameController.text.toString(); - payload["password"] = - passwordController.text.toString(); - payload["phone"] = - mobileNumberController.text.toString(); - - payload["firstName"] = nameController.text.toString(); - payload["emails"] = [ - {"email": emailController.text.toString()} - ]; - payload["lastName"] = ''; - payload["address1"] = userAddressCapturingController.text; - payload["address2"] = ''; - payload["city"] = ''; - payload["state"] = ''; - payload["zip"] = ''; - payload["country"] = ''; - payload["notes"] = ''; - payload["latitude"] = lat; - payload["longitude"] = lng; - payload["fcmId"] = AppSettings.fcmId; - payload["age"] = 0; - payload["gender"] = genderUnit.toString(); - - bool signUpStatus = await AppSettings.signUp(payload); - - try { - if (signUpStatus) { - var smsPayload = new Map(); - smsPayload["mobileNumbers"] = mobileNumberController.text.toString(); - bool sendSms = await AppSettings.sendSms(smsPayload); - - if(sendSms){ - Navigator.of(context, rootNavigator: true).pop(); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => OtpScreen(myObject: mobileNumberController.text.toString(),)), - ); - } - else{ - Navigator.of(context, rootNavigator: true).pop(); - } + mobileNumberController.text != ''&&gender!='') { + bool isOnline = await AppSettings.internetConnectivity(); + + if(isOnline){ + AppSettings.preLoaderDialog(context); + + var payload = new Map(); + + + payload["doctorName"] = nameController.text.toString(); + payload["password"] = + passwordController.text.toString(); + payload["phone"] = + mobileNumberController.text.toString(); + payload["emails"] = [ + {"email": emailController.text.toString()} + ]; + payload["address1"] = userAddressCapturingController.text; + payload["address2"] = ''; + payload["latitude"] = lat; + payload["longitude"] = lng; + payload["gender"] = gender.toString(); + + bool signUpStatus = await AppSettings.signUp(payload); + + try { + if (signUpStatus) { + var smsPayload = new Map(); + smsPayload["mobileNumbers"] = mobileNumberController.text.toString(); + bool sendSms = await AppSettings.sendSms(smsPayload); + + if(sendSms){ + Navigator.of(context, rootNavigator: true).pop(); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => OtpScreen(myObject: mobileNumberController.text.toString(),)), + ); + } + else{ + Navigator.of(context, rootNavigator: true).pop(); + } - } - else { + } + else { + Navigator.of(context, rootNavigator: true).pop(); + AppSettings.longFailedToast( + "Mobile number already exists"); + } + } catch (exception) { + print(exception); Navigator.of(context, rootNavigator: true).pop(); - AppSettings.longFailedToast( - "Mobile number already exists"); + AppSettings.longFailedToast("Please enter valid details"); } - } catch (exception) { - print(exception); - Navigator.of(context, rootNavigator: true).pop(); - AppSettings.longFailedToast("Please enter valid details"); + } + else{ + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text('Please check your internet connection'),)); } } else { AppSettings.longFailedToast("details should not be empty"); - }*/ + } }, child: Text('Sign Up'), )),//login button diff --git a/lib/common/updateprofile.dart b/lib/common/updateprofile.dart index 5dd8579..06c3f6b 100644 --- a/lib/common/updateprofile.dart +++ b/lib/common/updateprofile.dart @@ -1,6 +1,7 @@ import 'dart:convert'; +import 'package:doctor/common/zoom_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -19,11 +20,25 @@ class UpdateProfile extends StatefulWidget { class _UpdateprofileState extends State { bool isPwdObscureText=true; + bool isFirstAddButtonShow=false; + bool isSecondAddButtonShow=false; + bool is2ndPlaceOfPracticeControllerVisible=false; + bool is3rdPlaceOfPracticeControllerVisible=false; bool isConfirmPwdObscureText=true; TextEditingController nameController = TextEditingController(); TextEditingController mobileNumberController = TextEditingController(); TextEditingController emailController = TextEditingController(); TextEditingController ageController = TextEditingController(); + TextEditingController specializationController = TextEditingController(); + TextEditingController qualificationController = TextEditingController(); + TextEditingController hospitalNameController1 = TextEditingController(); + TextEditingController hospitalNameController2 = TextEditingController(); + TextEditingController hospitalNameController3 = TextEditingController(); + TextEditingController practiceAddressController1 = TextEditingController(); + TextEditingController practiceAddressController2 = TextEditingController(); + TextEditingController practiceAddressController3 = TextEditingController(); + String? gender; + List placeOfPractices=[]; @@ -32,10 +47,19 @@ class _UpdateprofileState extends State { void initState() { isPwdObscureText=true; isConfirmPwdObscureText=true; - nameController.text=AppSettings.userName; + nameController.text=AppSettings.doctorName; mobileNumberController.text=AppSettings.phoneNumber; emailController.text=AppSettings.email; + specializationController.text=AppSettings.specialization; + qualificationController.text=AppSettings.qualification; ageController.text=AppSettings.age; + gender=AppSettings.gender; + hospitalNameController1.text=AppSettings.placeOfPractice1; + hospitalNameController2.text=AppSettings.placeOfPractice2; + hospitalNameController3.text=AppSettings.placeOfPractice3; + practiceAddressController1.text=AppSettings.placeOfPracticeAddress1; + practiceAddressController2.text=AppSettings.placeOfPracticeAddress2; + practiceAddressController3.text=AppSettings.placeOfPracticeAddress3; super.initState(); @@ -45,7 +69,7 @@ class _UpdateprofileState extends State { final ImagePicker _picker = ImagePicker(); Future pickImageFromGallery() async { - /* try { + try { final image = await _picker.pickImage(source: ImageSource.gallery); if (image == null) return; final imageTemp = File(image.path); @@ -59,11 +83,11 @@ class _UpdateprofileState extends State { AppSettings.saveData('profile', jsonDecode(res)['picture'], 'STRING'); } on PlatformException catch (e) { print('Failed to pick image: $e'); - }*/ + } } Future takeImageFromCamera() async { - /*try { + try { final image = await _picker.pickImage(source: ImageSource.camera); if (image == null) return; final imageTemp = File(image.path); @@ -77,7 +101,7 @@ class _UpdateprofileState extends State { AppSettings.saveData('profile', jsonDecode(res)['picture'], 'STRING'); } on PlatformException catch (e) { print('Failed to pick image: $e'); - }*/ + } } @@ -101,207 +125,552 @@ class _UpdateprofileState extends State { }, child: SafeArea( child: SingleChildScrollView( - child: Column( - children: [ - SizedBox( - height: 40, - ), - /*Container( - child: Image( - image: AssetImage('images/logo.png'), - height: MediaQuery.of(context).size.height * .10, - )),*/ - Container(child: GestureDetector( - child: Container( - width: MediaQuery.of(context).size.width * .30, - height: MediaQuery.of(context).size.height * .20, - decoration: BoxDecoration( - shape: BoxShape.circle, - image: DecorationImage( - image: (AppSettings.profilePictureUrl != ''&& AppSettings.profilePictureUrl != 'null') ? - NetworkImage(AppSettings.profilePictureUrl) as ImageProvider : AssetImage("images/profile_pic.png"), // picked file - fit: BoxFit.fitWidth)), + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + children: [ + SizedBox( + height:MediaQuery.of(context).size.height * .02, ), - 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: primaryColor, + Container(child: GestureDetector( + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .20, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + image: (AppSettings.profilePictureUrl != ''&& AppSettings.profilePictureUrl != 'null') ? + NetworkImage(AppSettings.profilePictureUrl) as ImageProvider : AssetImage("images/profile_pic.png"), // picked file + fit: BoxFit.fitWidth)), + ), + onTap: () { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Profile',imageDetails:AppSettings.profilePictureUrl))); + + }, + ),), + TextButton( + child: const Text( + 'Change', + style: TextStyle(decoration: TextDecoration.underline,color: primaryColor,fontSize: 12), + ), + onPressed: () { + 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: primaryColor, + ), + onTap: () async { + await takeImageFromCamera(); + Navigator.pop(context); + }, ), - onTap: () async { - await takeImageFromCamera(); - Navigator.pop(context); - }, - ), - SizedBox( - width: - MediaQuery.of(context).size.width * .20, - ), - GestureDetector( - child: Icon( - Icons.photo, - size: 100, - color: primaryColor, + SizedBox( + width: + MediaQuery.of(context).size.width * .20, ), - onTap: () async { - await pickImageFromGallery(); - Navigator.pop(context); - }, - ), - ], + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGallery(); + Navigator.pop(context); + }, + ), + ], + ), ), - ), - ); - }); - }, - ),), - SizedBox( - height: 10, - ), - Container( - padding: const EdgeInsets.all(10), - child: TextFormField( - cursorColor: greyColor, - controller: nameController, - decoration: const InputDecoration( - prefixIcon: Icon( - Icons.person, - color: greyColor, + ); + }); + //signup screen + }, + ), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: nameController, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.person, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'DoctorName', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), ), - border: OutlineInputBorder( - borderSide: BorderSide(color: greyColor)), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: greyColor), + ), + ),//name + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: emailController, + keyboardType: TextInputType.emailAddress, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.email, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Enter email ID', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: greyColor), + ), + ), //email + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: mobileNumberController, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.phone_android, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Enter Mobile Number', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), ), - labelText: 'Username', - labelStyle: TextStyle( - color: greyColor, //<-- SEE HERE + ), + ), //mobile + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: ageController, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.person, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Enter age', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), ), ), ), - ),//name - const SizedBox( - height: 15, - ), - Container( - padding: const EdgeInsets.all(10), - child: TextFormField( - cursorColor: greyColor, - controller: emailController, - decoration: const InputDecoration( - prefixIcon: Icon( - Icons.email, - color: greyColor, - ), - border: OutlineInputBorder( - borderSide: BorderSide(color: greyColor)), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: greyColor), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: greyColor), - ), - labelText: 'Enter email ID', - labelStyle: TextStyle( - color: greyColor, //<-- SEE HERE + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Text('Select Gender',style: TextStyle(color: primaryColor,fontSize: 14,fontWeight: FontWeight.bold),), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + Expanded(child: RadioListTile( + title: Text("Male",style: TextStyle(color: primaryColor,fontSize: 11)), + value: "male", + groupValue: gender, + activeColor: primaryColor, + onChanged: (value){ + setState(() { + gender = value.toString(); + }); + }, + ),), + Expanded(child: RadioListTile( + title: Text("Female",style:TextStyle(color: primaryColor,fontSize: 11)), + value: "female", + groupValue: gender, + activeColor: primaryColor, + onChanged: (value){ + setState(() { + gender = value.toString(); + }); + }, + ),), + Expanded(child: RadioListTile( + title: Text("Others",style: TextStyle(color: primaryColor,fontSize: 11)), + value: "other", + groupValue: gender, + activeColor: primaryColor, + + onChanged: (value){ + setState(() { + gender = value.toString(); + }); + }, + ),), + ], + ), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: qualificationController, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.quickreply, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Enter qualification', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), ), ), ), - ), //email - SizedBox( - height: 10, - ), - Container( - padding: const EdgeInsets.all(10), - child: TextFormField( - cursorColor: greyColor, - controller: mobileNumberController, - decoration: const InputDecoration( - prefixIcon: Icon( - Icons.phone_android, - color: greyColor, - ), - border: OutlineInputBorder( - borderSide: BorderSide(color: greyColor)), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: greyColor), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: greyColor), - ), - labelText: 'Enter Mobile Number', - labelStyle: TextStyle( - color: greyColor, //<-- SEE HERE + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: specializationController, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.folder_special, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Enter specialization', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), ), ), ), - ), //mobile - SizedBox( - height: 10, - ), - - SizedBox( - height: 10, - ), - Container( - padding: const EdgeInsets.all(10), - child: TextFormField( - cursorColor: greyColor, - controller: ageController, - decoration: const InputDecoration( - prefixIcon: Icon( - Icons.person, - color: greyColor, - ), - border: OutlineInputBorder( - borderSide: BorderSide(color: greyColor)), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: greyColor), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: greyColor), - ), - labelText: 'Enter age', - labelStyle: TextStyle( - color: greyColor, //<-- SEE HERE + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Text('Place of practice',style: TextStyle(color: primaryColor,fontSize: 14,fontWeight: FontWeight.bold),), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + width: double.infinity, + decoration: BoxDecoration( + color: secondaryColor, + border: Border.all( + //width: 10, + color: Colors.white, + ), + borderRadius: BorderRadius.circular( + 20, + )), + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + TextFormField( + cursorColor: greyColor, + controller: hospitalNameController1, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.location_city, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Enter hospital name', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + TextFormField( + cursorColor: greyColor, + controller: practiceAddressController1, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.location_on, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Enter practice address', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + Visibility( + visible: hospitalNameController1.text!='', + child: IconButton( + onPressed: (){ + + setState(() { + is2ndPlaceOfPracticeControllerVisible=true; + }); + }, + icon: Icon(Icons.add_box, color: primaryColor,))) + ], ), ), ), - ), - Container( - padding: const EdgeInsets.fromLTRB(10, 0, 10, 0), - child: ElevatedButton( - style: ElevatedButton.styleFrom( - primary: primaryColor, // background - onPrimary: Colors.white, // foreground + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Visibility( + visible:hospitalNameController2.text!=''&&hospitalNameController2.text!='null'||is2ndPlaceOfPracticeControllerVisible, + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: secondaryColor, + border: Border.all( + //width: 10, + color: Colors.white, + ), + borderRadius: BorderRadius.circular( + 20, + )), + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + TextFormField( + cursorColor: greyColor, + controller: hospitalNameController2, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.location_city, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Enter hospital name', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + TextFormField( + cursorColor: greyColor, + controller: practiceAddressController2, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.location_on, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Enter practice place', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + Visibility( + visible: hospitalNameController2.text!='', + child: IconButton( + onPressed: (){ + + setState(() { + is3rdPlaceOfPracticeControllerVisible=true; + }); + }, + icon: Icon(Icons.add_box, color: primaryColor,))) + ], + ), + ), + ),), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Visibility( + visible: hospitalNameController3.text!=''&&hospitalNameController3.text!='null'||is3rdPlaceOfPracticeControllerVisible, + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: secondaryColor, + border: Border.all( + //width: 10, + color: Colors.white, + ), + borderRadius: BorderRadius.circular( + 20, + )), + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + TextFormField( + cursorColor: greyColor, + controller: hospitalNameController3, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.location_city, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Enter hospital name', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + TextFormField( + cursorColor: greyColor, + controller: practiceAddressController3, + onChanged:(val) { + + }, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.location_on, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Enter practice place', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ], + ), ), - onPressed: () async{ + ),), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + width:double.infinity, + height: MediaQuery.of(context).size.height * .06, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async{ + if(hospitalNameController1!=''){ + placeOfPractices.add({ + 'hospitalName': hospitalNameController1.text, + 'address': practiceAddressController1.text + }); + } + if(hospitalNameController2!=''){ + placeOfPractices.add({ + 'hospitalName': hospitalNameController2.text, + 'address': practiceAddressController2.text + }); + } + if(hospitalNameController3!=''){ + placeOfPractices.add({ + 'hospitalName': hospitalNameController3.text, + 'address': practiceAddressController3.text + }); + } + - /*int age=0; - if(ageController.text.toString()!=''){ + + + + int age=0; + if(ageController.text.toString()!=''||ageController.text.toString()!='null'){ age=int.parse(ageController.text.toString()); } else{ age=0; } - var payload = new Map(); - payload["username"] = nameController.text.toString(); + payload["doctorName"] = nameController.text.toString(); payload["phone"] = mobileNumberController.text.toString(); payload["age"] = age; + payload["gender"] = gender; + payload["specialization"] = specializationController.text; + payload["qualification"] =qualificationController.text ; + payload["placeOfPractice"] =placeOfPractices ; payload["emails"] = [{"email":emailController.text.toString()}]; bool signUpStatus = await AppSettings.updateProfile(payload); try{ @@ -320,15 +689,17 @@ class _UpdateprofileState extends State { catch(exception){ print(exception); AppSettings.longFailedToast("Please enter valid details"); - }*/ + } + + }, + child: Text('Update'), + ) + ), - }, - child: Text('Update'), - ) - ), - ], - ), + ], + ), + ) )), ), ])); diff --git a/lib/common/zoom_image.dart b/lib/common/zoom_image.dart index 6cbf76f..f55b20d 100644 --- a/lib/common/zoom_image.dart +++ b/lib/common/zoom_image.dart @@ -15,17 +15,43 @@ class _ImageZoomPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppSettings.appBar(widget.imageName), + appBar:AppBar( + backgroundColor: primaryColor, + title: Text(widget.imageName), + actions: [ + IconButton( + onPressed: () { + + Navigator.pop(context); + }, + icon: Icon( + Icons.cancel, + color: buttonColors, + size: 30, + ), + ), + ], + ), body: Container( - //width: MediaQuery.of(context).size.width * .10, - //height: MediaQuery.of(context).size.height * .50, - child: PhotoView( - imageProvider: NetworkImage(widget.imageDetails) as ImageProvider, - maxScale: PhotoViewComputedScale.contained * 4.0, - minScale: PhotoViewComputedScale.contained, - initialScale: PhotoViewComputedScale.contained, - basePosition: Alignment.center, + //width: MediaQuery.of(context).size.width * .10, + //height: MediaQuery.of(context).size.height * .50, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding(padding:EdgeInsets.fromLTRB(10,10,10,0), + child: Text('Use two fingers to zoom/double tap',style: TextStyle(color: Colors.black,fontSize: 12),),), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Expanded( + child: PhotoView( + imageProvider: NetworkImage(widget.imageDetails) as ImageProvider, + maxScale: PhotoViewComputedScale.contained * 4.0, + minScale: PhotoViewComputedScale.contained, + initialScale: PhotoViewComputedScale.contained, + basePosition: Alignment.center, + ), + ) + ], ) ), diff --git a/lib/connected_patients/connected_patients.dart b/lib/connected_patients/connected_patients.dart new file mode 100644 index 0000000..df7c466 --- /dev/null +++ b/lib/connected_patients/connected_patients.dart @@ -0,0 +1,230 @@ +import 'dart:convert'; + +import 'package:doctor/common/settings.dart'; +import 'package:doctor/connected_patients/patient_records.dart'; +import 'package:doctor/models/connected_patients_model.dart'; +import 'package:flutter/material.dart'; + +class ConnectedPatients extends StatefulWidget { + const ConnectedPatients({Key? key}) : super(key: key); + + @override + State createState() => _ConnectedPatientsState(); +} + +class _ConnectedPatientsState extends State { + + + bool isConnectedPatientsDataLoading=false; + bool isSereverIssue=false; + List connectedPatientsList = []; + + Future getAllConnectedPatients() async { + isConnectedPatientsDataLoading=true; + try { + var response = await AppSettings.getAllConectedPatients(); + + setState(() { + connectedPatientsList = ((jsonDecode(response)) as List) + .map((dynamic model) { + return GetConnectedPatientsModel.fromJson(model); + }).toList(); + connectedPatientsList=connectedPatientsList.reversed.toList(); + isConnectedPatientsDataLoading = false; + }); + } catch (e) { + setState(() { + isConnectedPatientsDataLoading = false; + isSereverIssue = true; + }); + } + } + + @override + void initState() { + getAllConnectedPatients(); + super.initState(); + } + + Widget _patients(){ + if(connectedPatientsList.length!=0){ + return ListView.builder( + padding: EdgeInsets.all(0), + itemCount: connectedPatientsList.length, + itemBuilder: (BuildContext context, int index) { + return GestureDetector( + onTap: (){ + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new PatientRecords(patientDetails: connectedPatientsList[index],))); + + + }, + child: Card( + + //color: prescriptionsList[index].cardColor, + child: Padding( + padding:EdgeInsets.all(8) , + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + Container( + + + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Patient Name', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + 'Phone Number', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + 'Age', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + 'Gender', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + + ], + ), + SizedBox(width:MediaQuery.of(context).size.width * .01,), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + ':', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + ':', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + ':', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + ':', + style: labelTextStyle(), + ), + + ], + ), + SizedBox(width:MediaQuery.of(context).size.width * .01,), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(connectedPatientsList[index].user_name.toString().toUpperCase(),style: valuesTextStyle()), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + connectedPatientsList[index].phone_number, + style: valuesTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + connectedPatientsList[index].age+' Yrs', + style: valuesTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + connectedPatientsList[index].gender, + style: valuesTextStyle(), + ), + ], + ), + ], + ), + + + + + ), + + ], + + ), + ], + ), + ), + ), + ); + }); + } + else{ + return Center( + child: Padding( + padding: EdgeInsets.fromLTRB(0, 40, 0, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(height: MediaQuery.of(context).size.height * .25,), + Text('No Connected patients available'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: IconButton( + iconSize: 40, + icon: const Icon( + Icons.info, + color: Colors.white, + ), + onPressed: () async { + /*Navigator.push(context, MaterialPageRoute(builder: (context) => AddReports())).then((value) { + getAllRecords(); + });*/ + }, + ), + ) + ], + ), + ) + ); + } + + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Connected Patients'), + body: Container( + child: isConnectedPatientsDataLoading?Center( + child: CircularProgressIndicator( + color: primaryColor, + strokeWidth: 5.0, + ), + ): _patients(), + ), + ); + } +} diff --git a/lib/connected_patients/patient_records.dart b/lib/connected_patients/patient_records.dart new file mode 100644 index 0000000..dbfe564 --- /dev/null +++ b/lib/connected_patients/patient_records.dart @@ -0,0 +1,1118 @@ +import 'dart:convert'; +import 'package:doctor/connected_patients/records_on_click.dart'; +import 'package:doctor/models/patient_records_model.dart'; +import 'package:flutter/material.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:intl/intl.dart'; + +class PatientRecords extends StatefulWidget { + var patientDetails; + PatientRecords({this.patientDetails}); + + @override + State createState() => _PatientRecordsState(); +} + +class _PatientRecordsState extends State { + + List recordsList = []; + List recordsListOriginal = []; + bool isReportsDataLoading = false; + bool isDynamicDigitsVisible = false; + bool isSereverIssue = false; + TextEditingController searchController = TextEditingController(); + TextEditingController dateInput = TextEditingController(); + TextEditingController fromdateController = TextEditingController(); + TextEditingController todateController = TextEditingController(); + final TextEditingController _fieldOne = TextEditingController(); + final TextEditingController _fieldTwo = TextEditingController(); + final TextEditingController _fieldThree = TextEditingController(); + final TextEditingController _fieldFour = TextEditingController(); + final TextEditingController _fieldFive = TextEditingController(); + final TextEditingController _fieldSix = TextEditingController(); + DateTime fromDate=DateTime.now(); + String dropdownSearchType = 'Problem'; + String? searchBy; + var typeOfSearchItems = [ + 'Problem', + 'Doctor', + 'Date', + ]; + String? _otp; + + Future getAllRecords() async { + isReportsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.patientDetails.customer_id); + + setState(() { + recordsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return PatientRecordsModel.fromJson(model); + }).toList(); + recordsList=recordsListOriginal.reversed.toList(); + isReportsDataLoading = false; + }); + } catch (e) { + setState(() { + isReportsDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getRecordsByProblemName(var problem) async { + + isReportsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.patientDetails.customer_id); + + setState(() { + recordsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return PatientRecordsModel.fromJson(model); + }).toList(); + recordsList=recordsListOriginal.reversed.toList(); + recordsList= recordsListOriginal.where( + (x) => x.problem.toString().toLowerCase().contains(problem.toString().toLowerCase()) + ).toList(); + isReportsDataLoading = false; + }); + } catch (e) { + setState(() { + isReportsDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getRecordsByDoctorName(var doctor) async { + + isReportsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.patientDetails.customer_id); + + setState(() { + recordsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return PatientRecordsModel.fromJson(model); + }).toList(); + recordsList=recordsListOriginal.reversed.toList(); + recordsList= recordsListOriginal.where( + (x) => x.doctorName.toString().toLowerCase().contains(doctor.toString().toLowerCase()) + ).toList(); + isReportsDataLoading = false; + }); + } catch (e) { + setState(() { + isReportsDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getRecordsByDate(var date) async { + + isReportsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.patientDetails.customer_id); + + setState(() { + recordsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return PatientRecordsModel.fromJson(model); + }).toList(); + recordsList=recordsListOriginal.reversed.toList(); + recordsList= recordsListOriginal.where( + (x) => x.date.toString().toLowerCase().contains(date.toString().toLowerCase()) + ).toList(); + isReportsDataLoading = false; + }); + } catch (e) { + setState(() { + isReportsDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getRecordsByDateRange(var fromDate,var toDate) async { + isReportsDataLoading = true; + + try { + var response = await AppSettings.getAllRecords(widget.patientDetails.customer_id); + + setState(() { + recordsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return PatientRecordsModel.fromJson(model); + }).toList(); + recordsList=recordsListOriginal.reversed.toList(); + var dateToCheck = DateTime.now().add(Duration(days: -1)); + + recordsList = recordsListOriginal.reversed.where((product) { + final date = product.dateForFilter; + final startDate =DateFormat('dd-MM-yyyy').parse(fromDate); + final endDate = DateFormat('dd-MM-yyyy').parse(toDate); + return date.isAfter(startDate) && date.isBefore(endDate); + + //reportsList=reportsListOriginal.reversed.toList(); + }).toList(); + + /*if( dateToCheck.isAfter(startDate) && dateToCheck.isBefore(endDate)) + { + print("dateToCheck is between now and lastYear"); + } + else + { + print("dateToCheck is not between now and lastYear"); + }*/ + + + isReportsDataLoading = false; + }); + } catch (e) { + setState(() { + isReportsDataLoading = false; + isSereverIssue = true; + }); + } + } + + @override + void initState() { + getAllRecords(); + var now = new DateTime.now(); + String formattedDate = DateFormat('dd-MM-yyyy').format(now); + fromdateController.text=formattedDate; + todateController.text=formattedDate; + super.initState(); + } + + Widget _filtereddata(){ + if(recordsList.length!=0){ + recordsList.sort((a, b) => b.date.compareTo(a.date)); + return ListView.builder( + padding: EdgeInsets.all(0), + itemCount: recordsList.length, + itemBuilder: (BuildContext context, int index) { + if(recordsList[index].patient_type.toLowerCase().toString()=='self'){ + recordsList[index].age=widget.patientDetails.age; + recordsList[index].patient_name=widget.patientDetails.user_name; + recordsList[index].gender=widget.patientDetails.gender; + + } + + return GestureDetector( + onTap: (){ + + /* Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new AllRecordsOnClick(recordDetails:recordsList[index],initialIndex: 0,))).then((value) { + getAllRecords(); + });*/ + }, + child: Card( + + //color: prescriptionsList[index].cardColor, + child: Padding( + padding:EdgeInsets.all(8) , + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Problem:',style: problemTextStyle()), + Text(recordsList[index].problem.toString().toUpperCase(),style: valuesTextStyle()), + Text('Doctor details: ',style: problemTextStyle()), + Text(recordsList[index].doctorName.toString().toUpperCase(),style: valuesTextStyle()), + Text(recordsList[index].hospitalName.toString().toUpperCase(),style: valuesTextStyle()), + Text('Date: ',style: problemTextStyle()), + Text(recordsList[index].date.toString().toUpperCase(),style: valuesTextStyle()), + Text('Patient details: ',style: problemTextStyle()), + Text(recordsList[index].patient_name.toString().toUpperCase(),style: valuesTextStyle()), + Row( + children: [ + Text(recordsList[index].gender.toString().toUpperCase(),style: valuesTextStyle()), + SizedBox(width:MediaQuery.of(context).size.width * .05,), + Text(recordsList[index].age.toString().toUpperCase()+" Yrs",style: valuesTextStyle()), + ], + ), + + + ], + ), + + + ), + + Visibility( + visible:true, + child: recordsList[index].isReportVisible?Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new AllRecordsOnClick(recordDetails:recordsList[index],initialIndex: 0,))).then((value) { + getAllRecords(); + }); + }, + child: Text('Findings: '+recordsList[index].findingsImages.length.toString(),style:textButtonStyleReports(),), + ), + SizedBox( + width:MediaQuery.of(context).size.width * .05, + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new AllRecordsOnClick(recordDetails:recordsList[index],initialIndex: 0,))).then((value) { + getAllRecords(); + }); + + }, + child: Text('Reports: '+recordsList[index].reportImages.length.toString(),style:textButtonStyleReports()), + ), + SizedBox( + width:MediaQuery.of(context).size.width * .05, + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new AllRecordsOnClick(recordDetails:recordsList[index],initialIndex: 0,))).then((value) { + getAllRecords(); + }); + + + }, + child: Text('Prescriptions: '+recordsList[index].prescriptionImages.length.toString(),style:textButtonStyleReports()), + ), + ], + ):Container( + child: TextButton( + onPressed: () async{ + var payload = new Map(); + payload["customerId"] = recordsList[index].customerId; + payload["doctorId"] =AppSettings.doctorId; + payload["recordId"] = recordsList[index].recordId; + + try{ + var response = await AppSettings.getDynamicCode(payload); + print(jsonDecode(response)); + setState(() { + recordsList[index].isDynamicDigitsVisible=true; + }); + + } + catch(e){ + print(e); + } + + + + + }, + child: Column( + children: [ + Visibility( + visible: !recordsList[index].isDynamicDigitsVisible, + child: Text('Click here to request to see patient records', + style: TextStyle( + color: primaryColor, + fontSize: 14, + decoration: TextDecoration.underline, + )),), + SizedBox( + height:MediaQuery.of(context).size.height * .02, + ), + Visibility( + visible:recordsList[index].isDynamicDigitsVisible, + child: Column( + children: [ + Text('Please enter 6 digit code provided by the patient', + style: TextStyle( + color: primaryColor, + fontSize: 14, + )), + SizedBox( + height:MediaQuery.of(context).size.height * .02, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + OtpInput(_fieldOne, true), // auto focus + OtpInput(_fieldTwo, false), + OtpInput(_fieldThree, false), + OtpInput(_fieldFour, false), + OtpInput(_fieldFive, false), + OtpInput(_fieldSix, false), + ], + ), + SizedBox( + height:MediaQuery.of(context).size.height * .02, + ), + Container( + width:double.infinity, + height: MediaQuery.of(context).size.height * .06, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + + setState(() { + _otp = _fieldOne.text + + _fieldTwo.text + + _fieldThree.text + + _fieldFour.text+ + _fieldFive.text + + _fieldSix.text; + }); + if (_otp!.length == 6) { + AppSettings.preLoaderDialog(context); + + bool isOnline = await AppSettings.internetConnectivity(); + + if(isOnline){ + var payload = new Map(); + payload["dynamicCode"] = _otp.toString(); + payload["recordId"] = recordsList[index].recordId; + payload["customerId"] = recordsList[index].customerId; + bool codeVerified = await AppSettings.dynamicCodeVerification(payload); + if(codeVerified){ + Navigator.of(context,rootNavigator: true).pop(); + AppSettings.longSuccessToast("Code verified successfully"); + setState(() { + recordsList[index].isReportVisible=true; + recordsList[index].isDynamicDigitsVisible=false; + _fieldOne.clear(); + _fieldTwo.clear(); + _fieldThree.clear(); + _fieldFour.clear(); + _fieldFive.clear(); + _fieldSix.clear(); + }); + //getAllRecords(); + } + else{ + Navigator.of(context,rootNavigator: true).pop(); + AppSettings.longFailedToast( + "please enter valid pin"); + recordsList[index].isReportVisible=false; + //getAllRecords(); + } + + + } + else{ + Navigator.of(context,rootNavigator: true).pop(); + AppSettings.longFailedToast( + "Please check your internet"); + } + + + } + else{ + + } + + }, + child: Text('Verify'), + )), + ], + )), + ], + ) + ), + ),) + + ], + ), + ), + ), + ); + }); + } + else{ + return Padding(padding: EdgeInsets.fromLTRB(60,10,60,10), + child: Column( + children: [ + Text('No records found related to your search'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: Colors.red, + radius: 30, + child: const Icon( + Icons.info, + color: Colors.white, + ), + ) + ], + ),); + + } + } + + Widget _allreports(){ + + if(recordsListOriginal.length!=0){ + + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + /*Container( + padding: const EdgeInsets.fromLTRB(10, 10, 10, 0), + child: DropdownButtonFormField( + // Initial Value + value: dropdownSearchType, + isExpanded: true, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.search, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Search By', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + + hint: Text('Select Search Type'), + // Down Arrow Icon + icon: const Icon(Icons.keyboard_arrow_down), + + // Array list of items + items: typeOfSearchItems.map((String items) { + return DropdownMenuItem( + value: items, + child: Text(items), + ); + }).toList(), + // After selecting the desired option,it will + // change button value to selected value + onChanged: (String? newValue) { + setState(() { + dropdownSearchType = newValue!; + }); + }, + ), + ),*/ + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding(padding: EdgeInsets.fromLTRB(10,10,0,0), + child: Text('Please select search option',style: TextStyle(color: Colors.red,fontWeight: FontWeight.bold,fontSize: 16),),), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: RadioListTile( + title: Text("Problem", style: TextStyle(fontSize: 10)), + value: "problem", + groupValue: searchBy, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + searchBy = value.toString(); + }); + }, + ), + ), + Expanded( + child: RadioListTile( + title: Text( + "Doctor", + style: TextStyle(fontSize: 10), + ), + value: "doctor", + groupValue: searchBy, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + searchBy = value.toString(); + }); + }, + ), + ), + Expanded( + child: RadioListTile( + title: + Text("Date", style: TextStyle(fontSize: 10)), + value: "date", + groupValue: searchBy, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + searchBy = value.toString(); + }); + }, + ), + ), + ], + ), + ], + ) + + ), + Visibility( + visible:searchBy.toString().toLowerCase()=='problem' , + child: Container( + height: MediaQuery.of(context).size.height * .07, + padding: EdgeInsets.all(5), + child: Center(child: TextField( + + cursorColor: primaryColor, + controller: searchController, + onChanged: (string) { + if(string.length>=1){ + getRecordsByProblemName(string); + } + else{ + getAllRecords(); + } + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: primaryColor, + ), + /*suffixIcon: Icon( + Icons.clear, + color: greyColor, + ),*/ + suffixIcon: searchController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + searchController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'Search by problem', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ),) + ),), + Visibility( + visible:searchBy.toString().toLowerCase()=='doctor' , + child: Container( + height: MediaQuery.of(context).size.height * .07, + padding: EdgeInsets.all(5), + child: Center(child: TextField( + + cursorColor: primaryColor, + controller: searchController, + onChanged: (string) { + if(string.length>=1){ + getRecordsByDoctorName(string); + } + else{ + getAllRecords(); + } + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: primaryColor, + ), + /*suffixIcon: Icon( + Icons.clear, + color: greyColor, + ),*/ + suffixIcon: searchController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + searchController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'Search by doctor', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ),) + ),), + Visibility( + visible:searchBy.toString().toLowerCase()=='date', + child: Container( + //height: 60, + padding: EdgeInsets.all(5), + child: Row( + children: [ + Expanded( + child: TextField( + + cursorColor: primaryColor, + controller: fromdateController, + onChanged: (string) { + if(string.length>=1){ + //getRecordsByDate(string); + } + else{ + getAllRecords(); + } + }, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print(pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = DateFormat('dd-MM-yyyy').format(pickedDate); + print(formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + fromDate=pickedDate; + fromdateController.text = formattedDate; //set output date to TextField value. + }); + getRecordsByDateRange(fromdateController.text,todateController.text); + } else {} + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.calendar_month, + color: primaryColor, + ), + suffixIcon: fromdateController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + fromdateController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'From date', + + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ), + SizedBox(width: 5), + Expanded( + child: TextField( + + cursorColor: primaryColor, + controller: todateController, + onChanged: (string) { + if(string.length>=1){ + //getRecordsByDate(string); + } + else{ + getAllRecords(); + } + }, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: fromDate, + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + todateController.text = formattedDate; //set output date to TextField value. + }); + getRecordsByDateRange(fromdateController.text,todateController.text); + } else {} + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.calendar_month, + color: primaryColor, + ), + suffixIcon: todateController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + todateController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'To date', + + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ), + SizedBox(width: 5), + + ], + ), + ),), + /*Visibility( + visible:searchBy.toString().toLowerCase()=='date' , + child: Container( + height: MediaQuery.of(context).size.height * .07, + padding: EdgeInsets.all(5), + child: Center(child: TextField( + + cursorColor: primaryColor, + controller: searchController, + onChanged: (string) { + if(string.length>=1){ + getRecordsByDate(string); + } + else{ + getAllRecords(); + } + }, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + searchController.text = formattedDate; //set output date to TextField value. + }); + getRecordsByDate(searchController.text); + } else {} + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: primaryColor, + ), + suffixIcon: searchController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + searchController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'Search by date', + + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ),) + ), + + + ),*/ + Expanded(child: _filtereddata()), + + ]); + + + } + else{ + return Center( + child: Padding( + padding: EdgeInsets.fromLTRB(0, 40, 0, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(height: MediaQuery.of(context).size.height * .25,), + Text('No Records found related to selected patient'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: IconButton( + iconSize: 40, + icon: const Icon( + Icons.info, + color: Colors.white, + ), + onPressed: () async { + /*Navigator.push(context, MaterialPageRoute(builder: (context) => AddReports())).then((value) { + getAllRecords(); + });*/ + }, + ), + ) + ], + ), + ) + ); + } + + + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Records'), + body: isReportsDataLoading?Center( + child: CircularProgressIndicator( + color: primaryColor, + strokeWidth: 5.0, + ), + ): _allreports(), + ); + } + +} + +class OtpInput extends StatelessWidget { + final TextEditingController controller; + final bool autoFocus; + const OtpInput(this.controller, this.autoFocus, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 60, + width: 50, + child: TextField( + autofocus: autoFocus, + textAlign: TextAlign.center, + keyboardType: TextInputType.number, + controller: controller, + maxLength: 1, + cursorColor: Theme.of(context).primaryColor, + decoration: const InputDecoration( + filled: true, + fillColor: Colors.white, + border: OutlineInputBorder(borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + counterText: '', + hintStyle: TextStyle(color: Colors.black, fontSize: 20.0)), + onChanged: (value) { + if (value.length == 1) { + FocusScope.of(context).nextFocus(); + } + }, + ), + ); + } +} diff --git a/lib/connected_patients/records_on_click.dart b/lib/connected_patients/records_on_click.dart new file mode 100644 index 0000000..0d17ece --- /dev/null +++ b/lib/connected_patients/records_on_click.dart @@ -0,0 +1,281 @@ +import 'package:flutter/services.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:doctor/common/zoom_image.dart'; + +class AllRecordsOnClick extends StatefulWidget { + var recordDetails; + var initialIndex; + + AllRecordsOnClick({this.recordDetails,this.initialIndex}); + + @override + State createState() => _AllRecordsOnClickState(); +} + +class _AllRecordsOnClickState extends State + with TickerProviderStateMixin { + + final ImagePicker imagePicker = ImagePicker(); + List imageFileList = []; + final ImagePicker _picker = ImagePicker(); + + @override + void initState() { + super.initState(); + } + + + + Widget findings(var obj){ + if(obj.findingsImages.length!=0){ + return Container( + //color: secondaryColor, + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: Row( + children: [ + Expanded(child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.findingsImages.length, + itemBuilder: (context, index) { + return Row( + children: [ + Card( + child: GestureDetector( + onTap: (){ + //showPicDialog(obj.prescriptionImages[index]['url']); + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Findings',imageDetails:obj.findingsImages[index]['url'])));}, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.findingsImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + ), + ), + ) + + ], + ); + }),), + ], + ) + ); + } + else{ + return GestureDetector( + child: Row( + children: [ + Icon( + Icons.info, + color: Colors.green, + size: 40, + ), + Text('No Findings found',style: textButtonStyle(),) + ], + ), + ); + } + + + + } + + Widget reports(var obj){ + if(obj.reportImages.length!=0){ + return Container( + //color: secondaryColor, + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: Row( + children: [ + Expanded(child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.reportImages.length, + itemBuilder: (context, index) { + return Row( + children: [ + Card( + child: GestureDetector( + onTap: (){ + //showPicDialog(obj.prescriptionImages[index]['url']); + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Findings',imageDetails:obj.reportImages[index]['url'])));}, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.reportImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + ), + ), + ) + + ], + ); + }),), + ], + ) + ); + } + else{ + return GestureDetector( + child: Row( + children: [ + Icon( + Icons.info, + color: Colors.green, + size: 40, + ), + Text('No Reports found',style: textButtonStyle(),) + ], + ), + ); + } + + + + } + + Widget prescriptions(var obj){ + if(obj.prescriptionImages.length!=0){ + return Container( + //color: secondaryColor, + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: Row( + children: [ + Expanded(child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.prescriptionImages.length, + itemBuilder: (context, index) { + return Row( + children: [ + Card( + child: GestureDetector( + onTap: (){ + //showPicDialog(obj.prescriptionImages[index]['url']); + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Prescriptions',imageDetails:obj.prescriptionImages[index]['url'])));}, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.prescriptionImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + ), + ), + ) + + ], + ); + }),), + ], + ) + ); + } + else{ + return GestureDetector( + child: Row( + children: [ + Icon( + Icons.info, + color: Colors.green, + size: 40, + ), + Text('No Prescriptions found',style: textButtonStyle(),) + ], + ), + ); + } + + + + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Records'), + body: Padding( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: MediaQuery.of(context).size.height * .15, + width: double.infinity, + child: Padding( + padding: EdgeInsets.all(0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Problem: ' + + widget.recordDetails.problem.toString().toUpperCase(), + style: problemTextStyle()), + Text(widget.recordDetails.doctorName.toString().toUpperCase(), + style: valuesTextStyle()), + Text( + widget.recordDetails.hospitalName + .toString() + .toUpperCase(), + style: valuesTextStyle()), + Text(widget.recordDetails.date.toString().toUpperCase(), + style: valuesTextStyle()), + Text('Patient details: ', style: problemTextStyle()), + Text( + widget.recordDetails.patient_name + .toString() + .toUpperCase(), + style: valuesTextStyle()), + Row( + children: [ + Text(widget.recordDetails.gender.toString().toUpperCase(), + style: valuesTextStyle()), + SizedBox( + width: MediaQuery.of(context).size.width * .05, + ), + Text( + widget.recordDetails.age.toString().toUpperCase() + + " Yrs", + style: valuesTextStyle()), + ], + ), + ], + ), + ), + ), + Text('Findings',style: TextStyle(color: Colors.red,fontSize: 16,fontWeight: FontWeight.bold),), + findings(widget.recordDetails), + Text('Reports',style: TextStyle(color: Colors.red,fontSize: 16,fontWeight: FontWeight.bold),), + reports(widget.recordDetails), + Text('Prescriptions',style: TextStyle(color: Colors.red,fontSize: 16,fontWeight: FontWeight.bold),), + prescriptions(widget.recordDetails) + ], + ), + ), + ); + } +} diff --git a/lib/google_maps_place_picker_mb/src/models/circle_area.dart b/lib/google_maps_place_picker_mb/src/models/circle_area.dart index 738780e..f16b510 100644 --- a/lib/google_maps_place_picker_mb/src/models/circle_area.dart +++ b/lib/google_maps_place_picker_mb/src/models/circle_area.dart @@ -1,4 +1,5 @@ import 'dart:ui'; + import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:uuid/uuid.dart'; diff --git a/lib/maps/app_colors.dart b/lib/maps/app_colors.dart new file mode 100644 index 0000000..a470502 --- /dev/null +++ b/lib/maps/app_colors.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'helper.dart'; + +class AppColors { + AppColors._(); + + static const Color primaryColor = Color(0xffed1846); + static const Color secondaryColor = Color(0xff5bcb84); + static const Color tColor = Color(0xfff087ca); + static const Color rColor = Color(0xfff08c87); + static const Color statusColorPending = Color(0xfff8c942); + static const Color statusColorInProgress = Color(0xff587add); + static const Color statusColorConfirm = Color(0xff30d300); + static const Color pageBgColor = Color(0xFFF6F6F6); + static const Color grey100Color = Color(0xFFEEEEEE); + static const Color grey200Color = Color(0xFFEEEEEE); + static const Color grey300Color = Color(0xFFE0E0E0); + static const Color grey400Color = Color(0xFFBDBDBD); + static const Color grey500Color = Color(0xFF9E9E9E); + static const Color grey600Color = Color(0xFF757575); + static const Color grey700Color = Color(0xFF616161); + static const Color grey800Color = Color(0xFF424242); + static const Color grey900Color = Color(0xFF212121); + static const Color errorColor = Color(0xFFD50000); + static const Color error100Color = Color(0xffFF5252); + static const Color mainBgColor = Color(0xfff7f7f7); + static const Color logoColor = Color(0xfff1ea0c); + + static MaterialColor primaryMaterialColor = getSwatch(primaryColor); + static MaterialColor errorMaterialColor = getSwatch(errorColor); + static MaterialColor tableRowMaterialColor = getSwatch(grey500Color); +} diff --git a/lib/maps/app_images.dart b/lib/maps/app_images.dart new file mode 100644 index 0000000..a1d2af5 --- /dev/null +++ b/lib/maps/app_images.dart @@ -0,0 +1,4 @@ +class AppImages { + static const String pickupMarker = "assets/images/pickup_marker.png"; + static const String dropMarker = "assets/images/drop_marker.png"; +} diff --git a/lib/maps/app_sizes.dart b/lib/maps/app_sizes.dart new file mode 100644 index 0000000..734f176 --- /dev/null +++ b/lib/maps/app_sizes.dart @@ -0,0 +1,25 @@ +import 'dart:ui'; + +import 'package:get/get.dart'; + + + +class AppSizes { + // get height and width from getX + static final double deviceHeight = Get.height; + static final double deviceWidth = Get.width; + + static const int height1060 = 1060; + static const int height880 = 880; + static const int height740 = 740; + static const int height490 = 490; + + static const int width1060 = 1060; + static const int width880 = 880; + static const int width740 = 740; + static const int width490 = 490; + + static const int screen720x1280 = 490; + + static final double mapPinSize = (deviceWidth * window.devicePixelRatio); +} diff --git a/lib/maps/helper.dart b/lib/maps/helper.dart new file mode 100644 index 0000000..635611e --- /dev/null +++ b/lib/maps/helper.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +MaterialColor getSwatch(Color color) { + final hslColor = HSLColor.fromColor(color); + final lightness = hslColor.lightness; + + /// if [500] is the default color, there are at LEAST five + /// steps below [500]. (i.e. 400, 300, 200, 100, 50.) A + /// divisor of 5 would mean [50] is a lightness of 1.0 or + /// a color of #ffffff. A value of six would be near white + /// but not quite. + const lowDivisor = 6; + + /// if [500] is the default color, there are at LEAST four + /// steps above [500]. A divisor of 4 would mean [900] is + /// a lightness of 0.0 or color of #000000 + const highDivisor = 5; + + final lowStep = (1.0 - lightness) / lowDivisor; + final highStep = lightness / highDivisor; + + return MaterialColor(color.value, { + 50: (hslColor.withLightness(lightness + (lowStep * 5))).toColor(), + 100: (hslColor.withLightness(lightness + (lowStep * 4))).toColor(), + 200: (hslColor.withLightness(lightness + (lowStep * 3))).toColor(), + 300: (hslColor.withLightness(lightness + (lowStep * 2))).toColor(), + 400: (hslColor.withLightness(lightness + lowStep)).toColor(), + 500: (hslColor.withLightness(lightness)).toColor(), + 600: (hslColor.withLightness(lightness - highStep)).toColor(), + 700: (hslColor.withLightness(lightness - (highStep * 2))).toColor(), + 800: (hslColor.withLightness(lightness - (highStep * 3))).toColor(), + 900: (hslColor.withLightness(lightness - (highStep * 4))).toColor(), + }); +} diff --git a/lib/maps/location_controller.dart b/lib/maps/location_controller.dart new file mode 100644 index 0000000..e3ccd5a --- /dev/null +++ b/lib/maps/location_controller.dart @@ -0,0 +1,120 @@ +import 'dart:developer'; +import 'dart:ui' as ui; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:location/location.dart'; + +import 'app_images.dart'; +import 'app_sizes.dart'; +import 'permission_alert.dart'; + +class LocationController extends GetxController { + Location location = Location(); + + // final Rx locationPosition = const LatLng(0.0, 0.0).obs; + /*final Rx locationPosition = + const LatLng(12.90618717, 77.5844983).obs;*/ + final Rx locationPosition = + const LatLng(0, 0).obs; + + bool locationServiceActive = true; + + BitmapDescriptor? pickupMarker; + BitmapDescriptor? dropMarker; + + @override + void onInit() async { + + await _getBytesFromAsset(AppImages.pickupMarker, AppSizes.mapPinSize * 0.1); + await _getBytesFromAsset(AppImages.dropMarker, AppSizes.mapPinSize * 0.05); + + super.onInit(); + refreshToLiveLocation(); + } + + Future _getBytesFromAsset(String path, double size) async { + ByteData data = await rootBundle.load(path); + ui.Codec codec = await ui.instantiateImageCodec( + data.buffer.asUint8List(), + targetWidth: size.toInt(), + allowUpscaling: true, + ); + ui.FrameInfo fi = await codec.getNextFrame(); + if (path == AppImages.pickupMarker) { + pickupMarker = BitmapDescriptor.fromBytes( + (await fi.image.toByteData(format: ui.ImageByteFormat.png))! + .buffer + .asUint8List()); + } else if (path == AppImages.dropMarker) { + dropMarker = BitmapDescriptor.fromBytes( + (await fi.image.toByteData(format: ui.ImageByteFormat.png))! + .buffer + .asUint8List()); + } else {} + } + + refreshToLiveLocation() async { + log("initiating"); + bool serviceEnabled; + + PermissionStatus permissionGranted; + + serviceEnabled = await location.serviceEnabled(); + + if (!serviceEnabled) { + serviceEnabled = await location.requestService(); + locationPosition.value = null; + return; + } + log("permission check"); + permissionGranted = await location.hasPermission(); + + if (permissionGranted == PermissionStatus.denied) { + permissionGranted = await location.requestPermission(); + if (permissionGranted != PermissionStatus.granted) { + showPermissionAlertDialog( + requestMsg: + "Location access needed. Go to Android settings, tap App permissions and tap Allow.", + barrierDismissible: false, + ); + } else { + await location.changeSettings( + accuracy: LocationAccuracy.high, + interval: 2000, + distanceFilter: 2); + + location.onLocationChanged.listen((LocationData currentLocation) async { + var lat = currentLocation.latitude; + var long = currentLocation.longitude; + if (lat != null && long != null) { + locationPosition.value = LatLng( + lat, + long, + ); + log("live location ${locationPosition.value}"); + } + }); + } + } else { + await location.changeSettings( + accuracy: LocationAccuracy.high, + interval: 2000, + distanceFilter: 2); + + location.onLocationChanged.listen((LocationData currentLocation) async { + var lat = currentLocation.latitude; + var long = currentLocation.longitude; + if (lat != null && long != null) { + locationPosition.value = LatLng( + lat, + long, + ); + log("live location ${locationPosition.value}"); + } + }); + } + } +} diff --git a/lib/maps/order_tracking_page.dart b/lib/maps/order_tracking_page.dart new file mode 100644 index 0000000..7de249a --- /dev/null +++ b/lib/maps/order_tracking_page.dart @@ -0,0 +1,252 @@ +import 'dart:async'; +import 'dart:developer'; +import 'dart:math'; +import 'package:flutter/material.dart'; +import 'package:flutter_polyline_points/flutter_polyline_points.dart'; +import 'package:get/get.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:location/location.dart'; +import 'location_controller.dart'; + + +class OrderTrackingPage extends StatefulWidget { + var lat; + var lng; + var d_lat; + var d_lng; + var u_address; + + OrderTrackingPage({ + this.lat, + this.lng, + this.d_lat, + this.d_lng, + this.u_address + + }); + + @override + OrderTrackingPageState createState() => OrderTrackingPageState(); +} + +class OrderTrackingPageState extends State { + final Completer mapController = Completer(); + PolylinePoints polylinePoints = PolylinePoints(); + double latitude=0; + double longitude=0; + double d_latitude=0; + double d_longitude=0; + String u_address = ''; + LocationData? currentLocation; + + + String googleAPiKey ="AIzaSyDJpK9RVhlBejtJu9xSGfneuTN6HOfJgSM"; + + Set markers = {}; + Map polylines = {}; + + late LatLng startLocation ; + late LatLng user_location; + LocationController locationController = Get.put(LocationController()); + double distance = 0.0; + + + @override + void initState() { + super.initState(); + latitude=widget.lat; + longitude=widget.lng; + d_latitude=widget.d_lat; + d_longitude=widget.d_lng; + u_address=widget.u_address; + + + user_location = LatLng(widget.lat,widget.lng); + startLocation = LatLng(widget.d_lat,widget.d_lng); + + LatLng delivery_Location = LatLng(widget.d_lat,widget.d_lng); + + //LatLng endLocation = LatLng(17.4968,78.3614); + + ever(locationController.locationPosition, (value) { + if (value != null) { + // log("${value.latitude} ${value.longitude}"); + var latitude = value.latitude; + var longitude = value.longitude; + startLocation = LatLng(widget.d_lat, widget.d_lng); + getDirections(user_location); + } + }); + getDirections(user_location); //fetch direction polylines from Google API + } + + getDirections(user_location) async { + markers.clear(); + + markers.add(Marker( + markerId: MarkerId(startLocation.toString()), + position: startLocation, + infoWindow: const InfoWindow( + title: 'Starting Point', + snippet: 'Start Marker', + ), + icon: locationController.pickupMarker ?? BitmapDescriptor.defaultMarker, + )); + + markers.add(Marker( + markerId: MarkerId(user_location.toString()), + position: user_location, //position of marker + infoWindow: const InfoWindow( + title: 'Destination Point ', + snippet: 'Destination Marker', + ), + icon: locationController.dropMarker ?? BitmapDescriptor.defaultMarker, + )); + + List polylineCoordinates = []; + + PolylineResult result = await polylinePoints.getRouteBetweenCoordinates( + googleAPiKey, + PointLatLng(startLocation.latitude, startLocation.longitude), + PointLatLng(user_location.latitude, user_location.longitude), + travelMode: TravelMode.driving, + ); + + if (result.points.isNotEmpty) { + for (var point in result.points) { + polylineCoordinates.add(LatLng(point.latitude, point.longitude)); + } + } else { + // log(result.errorMessage ?? "Something went wrong"); + } + +//polulineCoordinates is the List of longitute and latidtude. + double totalDistance = 0; + for(var i = 0; i < polylineCoordinates.length-1; i++){ + totalDistance += calculateDistance( + polylineCoordinates[i].latitude, + polylineCoordinates[i].longitude, + polylineCoordinates[i+1].latitude, + polylineCoordinates[i+1].longitude); + } + print(totalDistance); + + setState(() { + distance = totalDistance; + }); + + addPolyLine(polylineCoordinates); + } + + addPolyLine(List polylineCoordinates) async { + PolylineId id = const PolylineId("poly"); + Polyline polyline = Polyline( + polylineId: id, + color: Colors.deepPurpleAccent, + points: polylineCoordinates, + width:8, + ); + polylines[id] =polyline; + + var position = CameraPosition( + target: LatLng(latitude,longitude), + zoom: 16); + + final GoogleMapController controller = await mapController.future; + controller.animateCamera(CameraUpdate.newCameraPosition(position)); + + setState(() {}); + } + + + double calculateDistance(lat1, lon1, lat2, lon2){ + var p = 0.017453292519943295; + var a = 0.5 - cos((lat2 - lat1) * p)/2 + + cos(lat1 * p) * cos(lat2 * p) * + (1 - cos((lon2 - lon1) * p))/2; + return 12742 * asin(sqrt(a)); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Stack( + children: [ + GoogleMap( + //Map widget from google_maps_flutter package + zoomGesturesEnabled: true, + //enable Zoom in, out on map + initialCameraPosition: CameraPosition( + //innital position in map + target: startLocation, //initial position + zoom: 8.0, //initial zoom level + ), + + markers: markers, + //markers to show on map + polylines: Set.of(polylines.values), + //polylines + mapType: MapType.normal, + //map type + onMapCreated: (controller) { + //method called when map is created + if (!mapController.isCompleted) { + mapController.complete(controller); + } + }, + ), + + const SizedBox( + height: 95, + ), + + Positioned( + bottom: 100, + left: 50, + child: Container( + child: Card( + child: Container( + padding: EdgeInsets.all(20), + child: Text("Total Distance: " + distance.toStringAsFixed(2) + " KM", + style: TextStyle(fontSize: 20, fontWeight:FontWeight.bold)) + ), + ) + )), + /* const SizedBox( + height: 30, + ), + Positioned( + bottom: 80, + left: 0, + child: Container( + child: Card( + child: Container( + padding: EdgeInsets.all(20), + + child: Text("User Address: " + u_address.toString() , + style: TextStyle(fontSize: 15, fontWeight:FontWeight.bold,overflow: TextOverflow.ellipsis)) + ), + ) + )), + const SizedBox( + height: 30, + ), + Positioned( + bottom: 10, + left: 50, + child: Container( + child: Card( + child: Container( + padding: EdgeInsets.all(20), + child: Text("Total DistanceD: " + distance.toStringAsFixed(2) + " KM", + style: TextStyle(fontSize: 20, fontWeight:FontWeight.bold)) + ), + ) + )),*/ + ], + ) + + ); + + } +} diff --git a/lib/maps/padding_type_enum.dart b/lib/maps/padding_type_enum.dart new file mode 100644 index 0000000..dd8ab72 --- /dev/null +++ b/lib/maps/padding_type_enum.dart @@ -0,0 +1 @@ +enum PaddingType { symmetric, only } diff --git a/lib/maps/permission_alert.dart b/lib/maps/permission_alert.dart new file mode 100644 index 0000000..7a1fb34 --- /dev/null +++ b/lib/maps/permission_alert.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:get/get_core/src/get_main.dart'; +import 'package:get/get_navigation/get_navigation.dart'; +import 'package:permission_handler/permission_handler.dart'; + +import 'app_colors.dart'; +import 'primary_button.dart'; +import 'primary_text.dart'; + +void showPermissionAlertDialog({ + String title = "Need Permission", + required String requestMsg, + bool barrierDismissible = true, +}) { + Get.defaultDialog( + title: title, + middleText: "", + backgroundColor: Colors.white, + contentPadding: const EdgeInsets.only(top: 30, bottom: 30.0), + radius: 10, + barrierDismissible: barrierDismissible, + titlePadding: const EdgeInsets.only(top: 15), + titleStyle: const TextStyle( + color: AppColors.grey900Color, + fontSize: 18, + fontWeight: FontWeight.w600, + ), + /*cancel: PrimaryButton( + title: "DISMISS", + onPressed: () {}, + textSize: AppSizes.font_13, + bgColor: AppColors.grey500Color, + ),*/ + confirm: PrimaryButton( + title: "GO TO SETTINGS", + onPressed: () { + openAppSettings(); + Get.back(); + }, + textSize: 13, + ), + content: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: PrimaryText( + requestMsg, + textAlign: TextAlign.center, + fontColor: AppColors.grey800Color, + fontSize: 15, + fontWeight: FontWeight.w500, + ), + ), + ); +} diff --git a/lib/maps/primary_button.dart b/lib/maps/primary_button.dart new file mode 100644 index 0000000..cfe2beb --- /dev/null +++ b/lib/maps/primary_button.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; + +import 'app_colors.dart'; +import 'primary_text.dart'; + + +class PrimaryButton extends StatelessWidget { + final String title; + final VoidCallback onPressed; + final double verticalPadding; + final bool textAllCaps; + final double textSize; + final FontWeight textWeight; + final Color textColor; + final TextDecoration textDecoration; + final int letterSpacing; + final bool isResponsive; + final Color bgColor; + final double horizontalPadding; + + const PrimaryButton({ + Key? key, + required this.title, + required this.onPressed, + this.verticalPadding = 10.0, + this.textAllCaps = true, + this.textSize = 14, + this.textWeight = FontWeight.w500, + this.textColor = Colors.white, + this.textDecoration = TextDecoration.none, + this.letterSpacing = 1, + this.isResponsive = true, + this.bgColor = AppColors.primaryColor, + this.horizontalPadding = 25.0, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(40), + ), + color: bgColor, + child: InkWell( + onTap: onPressed, + child: Padding( + padding: EdgeInsets.symmetric( + vertical: verticalPadding, + horizontal: horizontalPadding, + ), + child: PrimaryText( + textAllCaps ? title.toUpperCase() : title, + // title.toUpperCase(), + textAlign: TextAlign.center, + fontSize: textSize, + fontWeight: textWeight, + fontColor: textColor, + textDecoration: textDecoration, + isResponsive: isResponsive, + ), + ), + ), + ); + } +} diff --git a/lib/maps/primary_text.dart b/lib/maps/primary_text.dart new file mode 100644 index 0000000..ec70048 --- /dev/null +++ b/lib/maps/primary_text.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; + +import 'app_sizes.dart'; +import 'padding_type_enum.dart'; + + +class PrimaryText extends StatelessWidget { + final String text; + final Color? fontColor; + final double fontSize; + final FontWeight fontWeight; + final double horizontalPadding; + final double verticalPadding; + final TextAlign textAlign; + final bool isResponsive; + final TextDecoration? textDecoration; + final PaddingType paddingType; + final double leftPadding; + final double rightPadding; + final double lineHeight; + final FontStyle fontStyle; + final TextOverflow textOverflow; + final bool textAllCaps; + final double letterSpacing; + + const PrimaryText( + this.text, { + Key? key, + this.fontColor = Colors.black, + this.fontSize = 16, + this.fontWeight = FontWeight.w600, + this.horizontalPadding = 0.0, + this.verticalPadding = 0.0, + this.textAlign = TextAlign.start, + this.isResponsive = true, + this.textDecoration, + this.paddingType = PaddingType.symmetric, + this.leftPadding = 0.0, + this.rightPadding = 0.0, + this.lineHeight = 1.5, + this.fontStyle = FontStyle.normal, + this.textOverflow = TextOverflow.visible, + this.textAllCaps = false, + this.letterSpacing = 0, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: paddingType == PaddingType.symmetric + ? EdgeInsets.symmetric( + horizontal: horizontalPadding, + vertical: verticalPadding, + ) + : EdgeInsets.only( + left: leftPadding, + right: rightPadding, + ), + child: Text( + textAllCaps ? text.toUpperCase() : text, + style: TextStyle( + fontSize: responsiveTextSize(), + fontWeight: fontWeight, + color: fontColor, + decoration: textDecoration, + height: lineHeight, + fontStyle: fontStyle, + letterSpacing: letterSpacing, + ), + textScaleFactor: 1, + textAlign: textAlign, + ), + ); + } + + double responsiveTextSize() { + if (isResponsive) { + if (AppSizes.deviceHeight < AppSizes.height490) { + return fontSize - 3; + } else if (AppSizes.deviceHeight < AppSizes.height740) { + return fontSize - 2; + } else if (AppSizes.deviceHeight < AppSizes.height880) { + return fontSize - 1; + } + } + return fontSize; + } +} diff --git a/lib/models/connected_patients_model.dart b/lib/models/connected_patients_model.dart new file mode 100644 index 0000000..7e85e91 --- /dev/null +++ b/lib/models/connected_patients_model.dart @@ -0,0 +1,27 @@ + + +class GetConnectedPatientsModel { + String user_name=''; + String customer_id=''; + String phone_number=''; + String age=''; + String gender=''; + + + + + GetConnectedPatientsModel(); + + factory GetConnectedPatientsModel.fromJson(Map json){ + GetConnectedPatientsModel rtvm = new GetConnectedPatientsModel(); + rtvm.user_name = json['username'] ?? ''; + rtvm.customer_id = json['customerId'] ?? ''; + rtvm.phone_number = json['phone'] ?? ''; + rtvm.age = json['age'].toString() ?? ''; + rtvm.gender = json['gender'] ?? ''; + + + return rtvm; + } + +} \ No newline at end of file diff --git a/lib/models/patient_records_model.dart b/lib/models/patient_records_model.dart new file mode 100644 index 0000000..00f1486 --- /dev/null +++ b/lib/models/patient_records_model.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:intl/intl.dart'; + +class PatientRecordsModel { + String patient_name=''; + String age=''; + String gender=''; + String patient_type=''; + String problem=''; + String doctorName=''; + String hospitalName=''; + String date=''; + String recordId=''; + String customerId=''; + String problem_category=''; + String doctorId=''; + bool isDoctorVerify=false; + bool isDynamicDigitsVisible=false; + bool isDoctorPinVerify=false; + bool isReportVisible=false; + List findingsImages = []; + List reportImages = []; + List prescriptionImages = []; + DateTime dateForFilter=new DateTime.now(); + + PatientRecordsModel(); + + factory PatientRecordsModel.fromJson(Map json){ + PatientRecordsModel rtvm = new PatientRecordsModel(); + + rtvm.patient_type = json['patientType'] ?? ''; + rtvm.doctorName = json['doctorName'] ?? ''; + rtvm.hospitalName = json['hospitalName'] ?? ''; + rtvm.problem = json['problem'] ?? ''; + rtvm.date = json['date'] ?? ''; + rtvm.recordId = json['recordId'] ?? ''; + rtvm.doctorId = json['doctorId'] ?? ''; + rtvm.customerId = json['customerId'] ?? ''; + rtvm.problem_category = json['problemCategory'] ?? ''; + rtvm.findingsImages = json['findings'] ?? []; + rtvm.reportImages = json['reports'] ?? []; + rtvm.prescriptionImages = json['prescription'] ?? []; + rtvm.isDoctorVerify = json['isDoctorVerify'] ?? false; + + + rtvm.dateForFilter = DateFormat('dd-MM-yyyy').parse(rtvm.date); + + if(rtvm.patient_type.toString().toLowerCase()=='self'){ + + } + else{ + rtvm.age=json['others']['age'].toString(); + rtvm.gender=json['others']['gender']; + rtvm.patient_name=json['others']['name']; + } + + if(rtvm.doctorId==AppSettings.doctorId || rtvm.problem_category.toString().toLowerCase()=='general'){ + rtvm.isReportVisible=true; + rtvm.isDoctorPinVerify=true; + } + + return rtvm; + } + +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index bc0e8cf..56010e5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -392,7 +392,7 @@ packages: source: hosted version: "0.4.0" flutter_launcher_icons: - dependency: "direct dev" + dependency: "direct main" description: name: flutter_launcher_icons url: "https://pub.dartlang.org" @@ -447,6 +447,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" + flutter_share: + dependency: "direct main" + description: + name: flutter_share + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" flutter_slidable: dependency: "direct main" description: @@ -1059,6 +1066,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + share: + dependency: "direct main" + description: + name: share + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" shared_preferences: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index f7fd900..09f4875 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,6 +58,9 @@ dependencies: assets_audio_player: ^3.0.3+3 path: ^1.8.0 visibility_detector: ^0.4.0+2 + flutter_launcher_icons: ^0.11.0 + share: ^2.0.4 + flutter_share: ^2.0.0 dev_dependencies: flutter_test: @@ -65,7 +68,11 @@ dev_dependencies: flutter_lints: ^2.0.0 - flutter_launcher_icons: ^0.11.0 + +flutter_icons: + image_path: "images/appicon.png" # Update this path as necessary + android: true + ios: true flutter: