diff --git a/.env b/.env index bef4df2..c770b9d 100644 --- a/.env +++ b/.env @@ -2,4 +2,5 @@ CUSTOM_SCHEME=com.cosqnet.telemednet PROFILE_COLLECTION_NAME=telemednetusers PATIENT_PROFILE_COLLECTION_NAME=patientprofiles DOCTOR_PROFILE_COLLECTION_NAME=doctorprofiles -CONSULTATION_CENTER_COLLECTION_NAME=businesscenters \ No newline at end of file +CONSULTATION_CENTER_COLLECTION_NAME=businesscenters +FIREBASE_STORAGE_BUCKET=gs://cosq-telemednet-dev.firebasestorage.app diff --git a/.vscode/launch.json b/.vscode/launch.json index 1b88d3d..aa728cf 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,18 +5,18 @@ "version": "0.2.0", "configurations": [ { - "name": "telemednet", + "name": "Medora", "request": "launch", "type": "dart" }, { - "name": "telemednet (profile mode)", + "name": "Medora (profile mode)", "request": "launch", "type": "dart", "flutterMode": "profile" }, { - "name": "telemednet (release mode)", + "name": "Medora (release mode)", "request": "launch", "type": "dart", "flutterMode": "release" diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 4cfed6f..af1be1a 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ + + 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..9d62deb 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-hdpi/launcher_icon.png b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png new file mode 100644 index 0000000..4903837 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/launcher_icon.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..483eaf3 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..39ee74e 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..855e4b1 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..a66e5f9 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/logo.jpg b/images/logo.jpg new file mode 100644 index 0000000..a10dd73 Binary files /dev/null and b/images/logo.jpg differ diff --git a/images/splash_screen.jpg b/images/splash_screen.jpg new file mode 100644 index 0000000..e6813c6 Binary files /dev/null and b/images/splash_screen.jpg differ diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index d5e6018..eb5bcea 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -427,7 +427,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -484,7 +484,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fa..d0d98aa 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} +{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}} \ No newline at end of file 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..8ffe7d8 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 7353c41..1e23d2b 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 797d452..ac510f4 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 6ed2d93..c7323d5 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 4cd7b00..c1e6cca 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 fe73094..afc5917 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 321773c..26fe87d 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 797d452..ac510f4 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 502f463..369ebad 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 0ec3034..31cff1b 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-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png new file mode 100644 index 0000000..8f72206 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png new file mode 100644 index 0000000..84e54a0 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png new file mode 100644 index 0000000..a360c1f Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png new file mode 100644 index 0000000..dd61c7c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.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 0ec3034..31cff1b 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 e9f5fea..4e9bb37 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-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png new file mode 100644 index 0000000..9d62deb Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png new file mode 100644 index 0000000..855e4b1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.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 84ac32a..439cee0 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 8953cba..1353dc5 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 0467bf1..260e020 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/controllers/doctor_controller.dart b/lib/controllers/doctor_controller.dart index f872e92..1d0dca8 100644 --- a/lib/controllers/doctor_controller.dart +++ b/lib/controllers/doctor_controller.dart @@ -1,4 +1,4 @@ -import 'package:telemednet/data/models/doctor.dart'; +import 'package:medora/data/models/doctor.dart'; class ValidationHelper { // Basic regex patterns @@ -92,16 +92,16 @@ class DoctorController { model.middleName = middleName; } - void updateLastName(String lastName) { - model.lastName = lastName; + void updateLastName(String firstName) { + model.firstName = firstName; } void addQualification(String qualification) { - model.qualifications!.add(qualification); + model.qualifications!.add(qualification.trim()); } void removeQualification(String qualification) { - model.qualifications!.remove(qualification); + model.qualifications!.remove(qualification.trim()); } void updateFloorBuilding(String floorBuilding) { diff --git a/lib/controllers/patient_controller.dart b/lib/controllers/patient_controller.dart index e61595a..e408271 100644 --- a/lib/controllers/patient_controller.dart +++ b/lib/controllers/patient_controller.dart @@ -1,4 +1,4 @@ -import 'package:telemednet/data/models/patient.dart'; +import 'package:medora/data/models/patient.dart'; import '../data/services/patient_registration_service.dart'; class PatientController { @@ -95,7 +95,7 @@ class PatientController { } Future updatePatientData() async { - return await PatientProfileService.updatePatientProfile(this); + return await PatientProfileService.updatePatientProfile(model); } Future deletePatientData() async { diff --git a/lib/data/models/doctor.dart b/lib/data/models/doctor.dart index 84ff6d8..1fc5f23 100644 --- a/lib/data/models/doctor.dart +++ b/lib/data/models/doctor.dart @@ -10,7 +10,7 @@ class Doctor { String? title; String? surName; String? middleName; - String? lastName; + String? firstName; List? qualifications = []; String? floorBuilding; String? street; @@ -32,7 +32,7 @@ class Doctor { this.title, this.surName, this.middleName, - this.lastName, + this.firstName, this.qualifications, this.floorBuilding, this.street, @@ -53,7 +53,7 @@ class Doctor { 'digitalSignature': digitalSignature, 'title': title, 'surname': surName, - 'lastName': lastName, + 'firstName': firstName, 'middleName': middleName, 'qualifications': qualifications, 'floorBuilding': floorBuilding, @@ -76,7 +76,7 @@ class Doctor { title: json['title'], surName: json['surname'], middleName: json['middleName'], - lastName: json['lastName'], + firstName: json['firstName'], qualifications: List.from(json['qualifications'] ?? []), floorBuilding: json['floorBuilding'], street: json['street'], diff --git a/lib/data/models/doctor_model.dart b/lib/data/models/doctor_model.dart deleted file mode 100644 index 8a9fa31..0000000 --- a/lib/data/models/doctor_model.dart +++ /dev/null @@ -1,37 +0,0 @@ -// import 'package:cloud_firestore/cloud_firestore.dart'; - -// class Doctors { -// final String name; -// final String location; -// final String specialization; -// final int experience; -// final String description; -// final List qualification; -// final List> consultation; -// final String profileImage; - -// Doctors({ -// required this.name, -// required this.location, -// required this.specialization, -// required this.experience, -// required this.description, -// required this.qualification, -// required this.consultation, -// required this.profileImage, -// }); - -// factory Doctors.fromFirestore(DocumentSnapshot doc) { -// final data = doc.data() as Map; -// return Doctors( -// name: data['name'] ?? '', -// location: data['location'] ?? '', -// specialization: data['specialization'] ?? '', -// experience: data['experience'] ?? 0, -// description: data['description'] ?? '', -// qualification: List.from(data['qualification'] ?? []), -// consultation: List>.from(data['consultation'] ?? []), -// profileImage: data['profile_image'] ?? '', -// ); -// } -// } diff --git a/lib/data/models/patient.dart b/lib/data/models/patient.dart index 0d93c62..5dcd4e0 100644 --- a/lib/data/models/patient.dart +++ b/lib/data/models/patient.dart @@ -4,6 +4,7 @@ class PatientModel { String? gender; DateTime? dateOfBirth; String? profileImagePath; + String? profileImageUrl; PatientAddress address; List familyMembers = []; @@ -17,6 +18,7 @@ class PatientModel { 'gender': gender, 'dateOfBirth': dateOfBirth?.toIso8601String(), 'profileImagePath': profileImagePath, + 'profileImageUrl': profileImageUrl, 'address': address.toJson(), 'familyMembers': familyMembers.map((member) => member.toJson()).toList(), }; @@ -31,15 +33,11 @@ class PatientModel { ? DateTime.parse(json['dateOfBirth']) : null; profileImagePath = json['profileImagePath']; - address.houseNo = json['houseNo']; - address.line = json['line']; - address.town = json['town']; - address.pincode = json['pincode']; - address.country = json['country']; - address.state = json['state']; - address.city = json['city']; - address.addressType = json['addressType']; - address.otherLabel = json['otherLabel']; + profileImageUrl = json['profileImageUrl']; + if (json['address'] != null) { + address = + PatientAddress.fromJson(json['address'] as Map); + } if (json['familyMembers'] != null) { familyMembers = (json['familyMembers'] as List) .map((memberJson) => FamilyMember.fromJson(memberJson)) @@ -53,15 +51,8 @@ class PatientModel { gender = other.gender; dateOfBirth = other.dateOfBirth; profileImagePath = other.profileImagePath; - address.houseNo = other.address.houseNo; - address.line = other.address.line; - address.town = other.address.town; - address.pincode = other.address.pincode; - address.country = other.address.country; - address.state = other.address.state; - address.city = other.address.city; - address.addressType = other.address.addressType; - address.otherLabel = other.address.otherLabel; + profileImageUrl = other.profileImageUrl; + address = other.address; familyMembers = other.familyMembers; } } diff --git a/lib/data/services/consultation_booking_service.dart b/lib/data/services/consultation_booking_service.dart index b29aff9..723a1cc 100644 --- a/lib/data/services/consultation_booking_service.dart +++ b/lib/data/services/consultation_booking_service.dart @@ -1,5 +1,5 @@ import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:telemednet/data/models/consultation_booking.dart'; +import 'package:medora/data/models/consultation_booking.dart'; class BookingService { final FirebaseFirestore _firestore = FirebaseFirestore.instance; diff --git a/lib/data/services/consultation_center_service.dart b/lib/data/services/consultation_center_service.dart index 4957e27..d019ce8 100644 --- a/lib/data/services/consultation_center_service.dart +++ b/lib/data/services/consultation_center_service.dart @@ -1,7 +1,7 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:telemednet/controllers/consultation_center_controller.dart'; +import 'package:medora/controllers/consultation_center_controller.dart'; import '../models/consultation_center.dart'; class ConsultationCenterService { diff --git a/lib/data/services/data_service.dart b/lib/data/services/data_service.dart index 37fe338..f59dcdd 100644 --- a/lib/data/services/data_service.dart +++ b/lib/data/services/data_service.dart @@ -1,7 +1,7 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:telemednet/data/models/telemed_user.dart'; +import 'package:medora/data/models/telemed_user.dart'; class DataService { static final String profileCollectionName = diff --git a/lib/data/services/doctor_profile_service.dart b/lib/data/services/doctor_profile_service.dart index e7598d8..e193d76 100644 --- a/lib/data/services/doctor_profile_service.dart +++ b/lib/data/services/doctor_profile_service.dart @@ -1,8 +1,8 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:telemednet/controllers/doctor_controller.dart'; -import 'package:telemednet/data/models/doctor.dart'; +import 'package:medora/controllers/doctor_controller.dart'; +import 'package:medora/data/models/doctor.dart'; class DoctorProfileService { static final String doctorProfileCollectionName = diff --git a/lib/data/services/navigation_service.dart b/lib/data/services/navigation_service.dart index 7311fdd..7ca3be5 100644 --- a/lib/data/services/navigation_service.dart +++ b/lib/data/services/navigation_service.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:telemednet/data/models/telemed_user.dart'; -import 'package:telemednet/data/services/data_service.dart'; -import 'package:telemednet/data/services/doctor_profile_service.dart'; -import 'package:telemednet/data/services/patient_registration_service.dart'; -import 'package:telemednet/route_names.dart'; +import 'package:medora/data/models/telemed_user.dart'; +import 'package:medora/data/services/data_service.dart'; +import 'package:medora/data/services/doctor_profile_service.dart'; +import 'package:medora/data/services/patient_registration_service.dart'; +import 'package:medora/route/route_names.dart'; class NavigationService { static Future handleUserNavigation(BuildContext context) async { diff --git a/lib/data/services/patient_registration_service.dart b/lib/data/services/patient_registration_service.dart index 7769436..fd91ded 100644 --- a/lib/data/services/patient_registration_service.dart +++ b/lib/data/services/patient_registration_service.dart @@ -1,13 +1,63 @@ +import 'dart:io'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; +import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:telemednet/controllers/patient_controller.dart'; -import 'package:telemednet/data/models/patient.dart'; +import 'package:medora/controllers/patient_controller.dart'; +import 'package:medora/data/models/patient.dart'; +import 'package:path/path.dart' as path; class PatientProfileService { static final String patientProfileCollectionName = dotenv.env['PATIENT_PROFILE_COLLECTION_NAME']!; static final FirebaseFirestore db = FirebaseFirestore.instance; + static final FirebaseStorage storage = FirebaseStorage.instanceFor( + bucket: dotenv.env['FIREBASE_STORAGE_BUCKET']!); + + static Future uploadProfileImage(File imageFile) async { + try { + final User? user = FirebaseAuth.instance.currentUser; + if (user == null) { + print('No user logged in'); + return null; + } + final String uid = user.uid; + final String fileName = + 'profile_${uid}_${DateTime.now().millisecondsSinceEpoch}${path.extension(imageFile.path)}'; + final Reference storageRef = + storage.ref().child('profile_images/$fileName'); + final UploadTask uploadTask = storageRef.putFile( + imageFile, + SettableMetadata( + contentType: 'image/${path.extension(imageFile.path).substring(1)}', + customMetadata: { + 'userId': uid, + 'uploadedAt': DateTime.now().toIso8601String(), + }, + ), + ); + final TaskSnapshot snapshot = await uploadTask; + final String downloadUrl = await snapshot.ref.getDownloadURL(); + + print('Profile image uploaded successfully'); + return downloadUrl; + } catch (e) { + print('Error uploading profile image: $e'); + return null; + } + } + + static Future deleteProfileImage(String imageUrl) async { + try { + final Reference storageRef = storage.refFromURL(imageUrl); + await storageRef.delete(); + print('Profile image deleted successfully'); + return true; + } catch (e) { + print('Error deleting profile image: $e'); + return false; + } + } static Future savePatientProfile(PatientController controller) async { try { @@ -19,11 +69,21 @@ class PatientProfileService { final String uid = user.uid; final PatientModel patientData = controller.model; + String? imageUrl; + if (patientData.profileImagePath != null) { + final File imageFile = File(patientData.profileImagePath!); + imageUrl = await uploadProfileImage(imageFile); + if (imageUrl == null) { + print('Failed to upload profile image'); + return false; + } + } final Map patientJson = patientData.toJson(); patientJson['createdAt'] = FieldValue.serverTimestamp(); patientJson['updatedAt'] = FieldValue.serverTimestamp(); patientJson['uid'] = uid; + patientJson['profileImageUrl'] = imageUrl; await db .collection(patientProfileCollectionName) @@ -38,32 +98,7 @@ class PatientProfileService { } } - static Future getPatientProfile() async { - try { - final User? user = FirebaseAuth.instance.currentUser; - if (user == null) { - print('No user logged in'); - return null; - } - - final String uid = user.uid; - final DocumentSnapshot doc = - await db.collection(patientProfileCollectionName).doc(uid).get(); - - if (!doc.exists) { - print('No patient profile found for this user'); - return null; - } - - final data = doc.data() as Map; - return PatientModel.fromJson(data); - } catch (e) { - print('Error fetching patient profile: $e'); - return null; - } - } - - static Future updatePatientProfile(PatientController controller) async { + static Future updatePatientProfile(PatientModel patient) async { try { final User? user = FirebaseAuth.instance.currentUser; if (user == null) { @@ -72,10 +107,30 @@ class PatientProfileService { } final String uid = user.uid; - final PatientModel patientData = controller.model; + String? imageUrl; + if (patient.profileImagePath != null) { + final DocumentSnapshot oldDoc = + await db.collection(patientProfileCollectionName).doc(uid).get(); + if (oldDoc.exists) { + final oldData = oldDoc.data() as Map; + final String? oldImageUrl = oldData['profileImageUrl']; + if (oldImageUrl != null) { + await deleteProfileImage(oldImageUrl); + } + } + final File imageFile = File(patient.profileImagePath!); + imageUrl = await uploadProfileImage(imageFile); + if (imageUrl == null) { + print('Failed to upload new profile image'); + return false; + } + } - final Map patientJson = patientData.toJson(); + final Map patientJson = patient.toJson(); patientJson['updatedAt'] = FieldValue.serverTimestamp(); + if (imageUrl != null) { + patientJson['profileImageUrl'] = imageUrl; + } await db .collection(patientProfileCollectionName) @@ -99,6 +154,15 @@ class PatientProfileService { } final String uid = user.uid; + final DocumentSnapshot doc = + await db.collection(patientProfileCollectionName).doc(uid).get(); + if (doc.exists) { + final data = doc.data() as Map; + final String? imageUrl = data['profileImageUrl']; + if (imageUrl != null) { + await deleteProfileImage(imageUrl); + } + } await db.collection(patientProfileCollectionName).doc(uid).delete(); @@ -109,4 +173,26 @@ class PatientProfileService { return false; } } + + static Future getPatientProfile() async { + try { + final User? user = FirebaseAuth.instance.currentUser; + if (user == null) { + print('No user logged in'); + return null; + } + final String uid = user.uid; + final DocumentSnapshot doc = + await db.collection(patientProfileCollectionName).doc(uid).get(); + if (!doc.exists) { + print('No patient profile found for this user'); + return null; + } + final data = doc.data() as Map; + return PatientModel.fromJson(data); + } catch (e) { + print('Error fetching patient profile: $e'); + return null; + } + } } diff --git a/lib/main.dart b/lib/main.dart index 49fc0f3..55c3aa9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,8 @@ +import 'package:medora/telemednet_app.dart'; import 'package:firebase_ui_auth/firebase_ui_auth.dart'; import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:firebase_core/firebase_core.dart'; -import 'package:telemednet/telemednet_app.dart'; import 'firebase_options.dart'; void main() async { @@ -10,10 +10,7 @@ void main() async { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); - FirebaseUIAuth.configureProviders([ - EmailAuthProvider(), - PhoneAuthProvider() - ]); + FirebaseUIAuth.configureProviders([EmailAuthProvider(), PhoneAuthProvider()]); await dotenv.load(); runApp(const TelemednetApp()); } diff --git a/lib/route_names.dart b/lib/route/route_names.dart similarity index 95% rename from lib/route_names.dart rename to lib/route/route_names.dart index 3667102..03ea4c0 100644 --- a/lib/route_names.dart +++ b/lib/route/route_names.dart @@ -40,4 +40,6 @@ class RouteNames { static const String doctorServicesMenuScreen = '/doctor-services-menu'; static const String consultationTimeSlotScreen = '/doctor-timeslot'; static const String consultationDayScreen = '/doctor-consultation-days'; + static const String loadingScreen = '/loading-screen'; + static const String splashScreen = '/splash-screen'; } diff --git a/lib/routes.dart b/lib/route/routes.dart similarity index 63% rename from lib/routes.dart rename to lib/route/routes.dart index 4cf4981..1b1480e 100644 --- a/lib/routes.dart +++ b/lib/route/routes.dart @@ -1,51 +1,53 @@ import 'package:firebase_ui_auth/firebase_ui_auth.dart'; import 'package:flutter/material.dart'; -import 'package:telemednet/controllers/consultation_center_controller.dart'; -import 'package:telemednet/data/models/consultation_center.dart'; -import 'package:telemednet/data/models/doctor.dart'; -import 'package:telemednet/screens/authentication/launch_screen.dart'; -// import 'package:telemednet/data/telemed_user.dart'; -import 'package:telemednet/controllers/patient_controller.dart'; -import 'package:telemednet/route_names.dart'; -import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/business_center_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/center_fee_and_duration_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/consultation_schedule.dart'; -import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_dashboard_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_landing_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_personal_profile_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_services_menu_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/doctor_profile_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/qualifications_screen.dart'; -import 'package:telemednet/screens/patientScreens/appoinmentBooking/consultation_booking_screen.dart'; -import 'package:telemednet/screens/patientScreens/appoinmentBooking/consultation_time_screen.dart'; -import 'package:telemednet/screens/patientScreens/appoinmentBooking/consultations_center_screen.dart'; -import 'package:telemednet/screens/patientScreens/appoinmentBooking/doctor_details_screen.dart'; -import 'package:telemednet/screens/patientScreens/appoinmentBooking/doctors_list_screen.dart'; -import 'package:telemednet/screens/patientScreens/appoinmentBooking/speciality_screen.dart'; +import 'package:medora/controllers/consultation_center_controller.dart'; +import 'package:medora/data/models/consultation_center.dart'; +import 'package:medora/data/models/doctor.dart'; +import 'package:medora/screens/authentication/launch_screen.dart'; +// import 'package:medora/data/telemed_user.dart'; +import 'package:medora/controllers/patient_controller.dart'; +import 'package:medora/route/route_names.dart'; +import 'package:medora/screens/common/loading_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/business_center_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/center_fee_and_duration_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/consultation_schedule.dart'; +import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_dashboard_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_landing_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_personal_profile_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_services_menu_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorProfileScreens/doctor_profile_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorProfileScreens/qualifications_screen.dart'; +import 'package:medora/screens/patientScreens/appoinmentBooking/consultation_booking_screen.dart'; +import 'package:medora/screens/patientScreens/appoinmentBooking/consultation_time_screen.dart'; +import 'package:medora/screens/patientScreens/appoinmentBooking/consultations_center_screen.dart'; +import 'package:medora/screens/patientScreens/appoinmentBooking/doctor_details_screen.dart'; +import 'package:medora/screens/patientScreens/appoinmentBooking/doctors_list_screen.dart'; +import 'package:medora/screens/patientScreens/appoinmentBooking/speciality_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/achivements_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/address_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorProfileScreens/achivements_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorProfileScreens/address_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/digital_signature_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorProfileScreens/digital_signature_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/experience_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/profile_description_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorProfileScreens/experience_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorProfileScreens/profile_description_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/specialities_selection_screen.dart'; -import 'package:telemednet/screens/patientScreens/patientDashboard/patient_dashboard_screen.dart'; -import 'package:telemednet/screens/patientScreens/patientDashboard/patient_home_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorProfileScreens/specialities_selection_screen.dart'; +import 'package:medora/screens/patientScreens/patientDashboard/patient_dashboard_screen.dart'; +import 'package:medora/screens/patientScreens/patientDashboard/patient_home_screen.dart'; -import 'package:telemednet/screens/patientScreens/patientDashboard/patient_profile_screen.dart'; -import 'package:telemednet/screens/patientScreens/registrationScreens/patient_adress_screen.dart'; -import 'package:telemednet/screens/patientScreens/registrationScreens/patient_family_members_screen.dart'; -import 'package:telemednet/screens/patientScreens/registrationScreens/patient_registration_screen.dart'; +import 'package:medora/screens/patientScreens/patientDashboard/patient_profile_screen.dart'; +import 'package:medora/screens/patientScreens/registrationScreens/patient_adress_screen.dart'; +import 'package:medora/screens/patientScreens/registrationScreens/patient_family_members_screen.dart'; +import 'package:medora/screens/patientScreens/registrationScreens/patient_registration_screen.dart'; +import 'package:medora/screens/splash_screen.dart'; -import 'controllers/doctor_controller.dart'; -import 'screens/patientScreens/patient_landing_screen.dart'; -import 'screens/patientScreens/registrationScreens/family_members_edit_screen.dart'; +import '../controllers/doctor_controller.dart'; +import '../screens/patientScreens/patient_landing_screen.dart'; +import '../screens/patientScreens/registrationScreens/family_members_edit_screen.dart'; final Map routes = { RouteNames.launch: (context) => const LaunchScreen(), @@ -208,4 +210,6 @@ final Map routes = { controller: controller ?? ConsultationCenterController(), ); }, + RouteNames.loadingScreen: (context) => const LoadingScreen(), + RouteNames.splashScreen: (context) => const SplashScreen(), }; diff --git a/lib/screens/authentication/launch_screen.dart b/lib/screens/authentication/launch_screen.dart index 894c20f..58675ec 100644 --- a/lib/screens/authentication/launch_screen.dart +++ b/lib/screens/authentication/launch_screen.dart @@ -1,10 +1,9 @@ -import 'dart:async'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; -import 'package:telemednet/data/services/navigation_service.dart'; -import 'package:telemednet/route_names.dart'; -import 'package:telemednet/screens/authentication/sign_up_screen.dart'; -import 'package:telemednet/widgets/primary_button.dart'; +import 'package:medora/data/services/navigation_service.dart'; +import 'package:medora/route/route_names.dart'; +import 'package:medora/screens/authentication/sign_up_screen.dart'; +import 'package:medora/widgets/primary_button.dart'; class LaunchScreen extends StatefulWidget { const LaunchScreen({super.key}); @@ -19,6 +18,17 @@ class _LaunchScreenState extends State { @override void initState() { super.initState(); + _checkAuthenticationState(); + } + + void _checkAuthenticationState() { + FirebaseAuth.instance.authStateChanges().listen((user) { + if (user != null) { + if (mounted) { + _fetchProfileAndNavigate(context); + } + } + }); } @override @@ -41,40 +51,7 @@ class _LaunchScreenState extends State { ), child: Padding( padding: const EdgeInsets.all(24.0), - child: StreamBuilder( - stream: FirebaseAuth.instance.authStateChanges(), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return _buildLoadingWidget(); - } else if (snapshot.hasData) { - _fetchProfileAndNavigate(context); - return _buildLoadingWidget(); - } else { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Text( - 'Register', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 16), - const Text( - 'Who are you?', - style: TextStyle( - color: Colors.grey, - fontSize: 16, - ), - ), - const SizedBox(height: 24), - _buildUserTypeSelection(context), - ], - ); - } - }, - ), + child: _buildUserTypeSelection(context), ), ), ), @@ -83,26 +60,26 @@ class _LaunchScreenState extends State { ); } - Widget _buildLoadingWidget() { - return const SizedBox( - height: 120, - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - CircularProgressIndicator(), - SizedBox(height: 12), - Text('Please wait...'), - ], - ), - ), - ); - } - Widget _buildUserTypeSelection(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, children: [ + const Text( + 'Register', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 16), + const Text( + 'Who are you?', + style: TextStyle( + color: Colors.grey, + fontSize: 16, + ), + ), + const SizedBox(height: 24), _buildSelectionCard( title: 'Doctor', description: 'Can organise and approve appointments', @@ -122,15 +99,7 @@ class _LaunchScreenState extends State { SizedBox( width: double.infinity, child: PrimaryButton( - onPressed: selectedUserType != null - ? () => Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => SignUpScreen( - selectedUserType: selectedUserType!, - ), - ), - ) - : null, + onPressed: selectedUserType != null ? _navigateToSignUp : null, text: 'Next', ), ), @@ -213,9 +182,17 @@ class _LaunchScreenState extends State { ); } + void _navigateToSignUp() { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => SignUpScreen( + selectedUserType: selectedUserType!, + ), + ), + ); + } + Future _fetchProfileAndNavigate(BuildContext context) async { - if (mounted) { - await NavigationService.handleUserNavigation(context); - } + await NavigationService.handleUserNavigation(context); } } diff --git a/lib/screens/authentication/sign_up_screen.dart b/lib/screens/authentication/sign_up_screen.dart index e60a34f..b8cf0d1 100644 --- a/lib/screens/authentication/sign_up_screen.dart +++ b/lib/screens/authentication/sign_up_screen.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:intl_phone_field/intl_phone_field.dart'; -import 'package:telemednet/data/services/data_service.dart'; -import 'package:telemednet/data/services/navigation_service.dart'; -import 'package:telemednet/widgets/primary_button.dart'; +import 'package:medora/data/services/data_service.dart'; +import 'package:medora/data/services/navigation_service.dart'; +import 'package:medora/widgets/primary_button.dart'; class SignUpScreen extends StatefulWidget { final String selectedUserType; diff --git a/lib/screens/common/loading_screen.dart b/lib/screens/common/loading_screen.dart new file mode 100644 index 0000000..6f4aff1 --- /dev/null +++ b/lib/screens/common/loading_screen.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; + +class LoadingScreen extends StatelessWidget { + const LoadingScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 32), + CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.blue.shade700), + strokeWidth: 4, + ), + const SizedBox(height: 24), + Text( + 'Loading...', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.blue.shade700, + ), + ), + const SizedBox(height: 8), + Text( + 'Please wait while we fetch you...', + style: TextStyle( + fontSize: 14, + color: Colors.grey.shade600, + ), + ), + const SizedBox(height: 32), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: LinearProgressIndicator( + value: null, + backgroundColor: Colors.grey.shade200, + valueColor: AlwaysStoppedAnimation(Colors.blue.shade700), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/doctorScreens/doctorConsultationSchedule/business_center_screen.dart b/lib/screens/doctorScreens/doctorConsultationSchedule/business_center_screen.dart index 0a321de..a8d7e11 100644 --- a/lib/screens/doctorScreens/doctorConsultationSchedule/business_center_screen.dart +++ b/lib/screens/doctorScreens/doctorConsultationSchedule/business_center_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:telemednet/controllers/consultation_center_controller.dart'; +import 'package:medora/controllers/consultation_center_controller.dart'; -import '../../../route_names.dart'; +import '../../../route/route_names.dart'; class BusinessCenterScreen extends StatefulWidget { final ConsultationCenterController controller; diff --git a/lib/screens/doctorScreens/doctorConsultationSchedule/center_fee_and_duration_screen.dart b/lib/screens/doctorScreens/doctorConsultationSchedule/center_fee_and_duration_screen.dart index 243ce6c..eb0de20 100644 --- a/lib/screens/doctorScreens/doctorConsultationSchedule/center_fee_and_duration_screen.dart +++ b/lib/screens/doctorScreens/doctorConsultationSchedule/center_fee_and_duration_screen.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:telemednet/controllers/consultation_center_controller.dart'; -import 'package:telemednet/data/services/consultation_center_service.dart'; -import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart'; -import '../../../route_names.dart'; +import 'package:medora/controllers/consultation_center_controller.dart'; +import 'package:medora/data/services/consultation_center_service.dart'; +import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart'; +import '../../../route/route_names.dart'; class CenterFeeAndDurationScreen extends StatefulWidget { final ConsultationCenterController controller; diff --git a/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart b/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart index 2b35467..00c5f11 100644 --- a/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart +++ b/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:telemednet/controllers/consultation_center_controller.dart'; -import 'package:telemednet/data/models/consultation_center.dart'; -import 'package:telemednet/data/services/consultation_center_service.dart'; -import 'package:telemednet/route_names.dart'; -import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart'; +import 'package:medora/controllers/consultation_center_controller.dart'; +import 'package:medora/data/models/consultation_center.dart'; +import 'package:medora/data/services/consultation_center_service.dart'; +import 'package:medora/route/route_names.dart'; +import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart'; class ConsultationDayScreen extends StatefulWidget { final ConsultationCenterController controller; diff --git a/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_schedule.dart b/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_schedule.dart index 84bfb22..1b57e00 100644 --- a/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_schedule.dart +++ b/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_schedule.dart @@ -1,11 +1,11 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:telemednet/data/models/consultation_center.dart'; -import 'package:telemednet/data/services/consultation_center_service.dart'; +import 'package:medora/data/models/consultation_center.dart'; +import 'package:medora/data/services/consultation_center_service.dart'; import '../../../common/custom_style.dart'; -import '../../../route_names.dart'; +import '../../../route/route_names.dart'; class ScheduleConsultationScreen extends StatefulWidget { const ScheduleConsultationScreen({super.key}); diff --git a/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart b/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart index 7889f6f..6feb335 100644 --- a/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart +++ b/lib/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:telemednet/controllers/consultation_center_controller.dart'; -import 'package:telemednet/data/models/consultation_center.dart'; +import 'package:medora/controllers/consultation_center_controller.dart'; +import 'package:medora/data/models/consultation_center.dart'; class ConsultationTimeSlotScreen extends StatefulWidget { final ConsultationCenterController controller; diff --git a/lib/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart b/lib/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart index 3e0f3a7..332a494 100644 --- a/lib/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart +++ b/lib/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:telemednet/screens/patientScreens/appoinmentBooking/speciality_screen.dart'; +import 'package:medora/screens/patientScreens/appoinmentBooking/speciality_screen.dart'; class DoctorDashboardHomeScreen extends StatefulWidget { const DoctorDashboardHomeScreen({super.key}); diff --git a/lib/screens/doctorScreens/doctorDashboard/doctor_dashboard_screen.dart b/lib/screens/doctorScreens/doctorDashboard/doctor_dashboard_screen.dart index e860752..3ca0f9e 100644 --- a/lib/screens/doctorScreens/doctorDashboard/doctor_dashboard_screen.dart +++ b/lib/screens/doctorScreens/doctorDashboard/doctor_dashboard_screen.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:curved_navigation_bar/curved_navigation_bar.dart'; -import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_personal_profile_screen.dart'; -import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_services_menu_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_personal_profile_screen.dart'; +import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_services_menu_screen.dart'; class DoctorDashboardScreen extends StatefulWidget { const DoctorDashboardScreen({super.key}); diff --git a/lib/screens/doctorScreens/doctorDashboard/doctor_landing_screen.dart b/lib/screens/doctorScreens/doctorDashboard/doctor_landing_screen.dart index 6de2418..9df8e8f 100644 --- a/lib/screens/doctorScreens/doctorDashboard/doctor_landing_screen.dart +++ b/lib/screens/doctorScreens/doctorDashboard/doctor_landing_screen.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:telemednet/route_names.dart'; +import 'package:medora/route/route_names.dart'; class DoctorLandingScreen extends StatelessWidget { const DoctorLandingScreen({super.key}); diff --git a/lib/screens/doctorScreens/doctorDashboard/doctor_personal_profile_screen.dart b/lib/screens/doctorScreens/doctorDashboard/doctor_personal_profile_screen.dart index 9b6827c..da32eee 100644 --- a/lib/screens/doctorScreens/doctorDashboard/doctor_personal_profile_screen.dart +++ b/lib/screens/doctorScreens/doctorDashboard/doctor_personal_profile_screen.dart @@ -1,6 +1,6 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; -import 'package:telemednet/route_names.dart'; +import 'package:medora/route/route_names.dart'; class DoctorPersonalProfileScreen extends StatefulWidget { const DoctorPersonalProfileScreen({super.key}); diff --git a/lib/screens/doctorScreens/doctorDashboard/doctor_services_menu_screen.dart b/lib/screens/doctorScreens/doctorDashboard/doctor_services_menu_screen.dart index 2af4b7f..af37272 100644 --- a/lib/screens/doctorScreens/doctorDashboard/doctor_services_menu_screen.dart +++ b/lib/screens/doctorScreens/doctorDashboard/doctor_services_menu_screen.dart @@ -1,6 +1,6 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; -import 'package:telemednet/route_names.dart'; +import 'package:medora/route/route_names.dart'; class DoctorServicesMenuScreen extends StatefulWidget { const DoctorServicesMenuScreen({super.key}); diff --git a/lib/screens/doctorScreens/doctorProfileScreens/achivements_screen.dart b/lib/screens/doctorScreens/doctorProfileScreens/achivements_screen.dart index 1222536..455cccc 100644 --- a/lib/screens/doctorScreens/doctorProfileScreens/achivements_screen.dart +++ b/lib/screens/doctorScreens/doctorProfileScreens/achivements_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:telemednet/controllers/doctor_controller.dart'; +import 'package:medora/controllers/doctor_controller.dart'; -import '../../../route_names.dart'; +import '../../../route/route_names.dart'; class AchievementsScreen extends StatefulWidget { final DoctorController controller; @@ -57,6 +57,10 @@ class _AchievementsScreenState extends State { _showError('Achievement must be at least 3 characters long'); return false; } + if (!RegExp(r'^[a-zA-Z0-9\s.,]+$').hasMatch(value)) { + _showError('Please enter valid achievement text'); + return false; + } return true; } diff --git a/lib/screens/doctorScreens/doctorProfileScreens/address_screen.dart b/lib/screens/doctorScreens/doctorProfileScreens/address_screen.dart index 8c4e0ad..2131156 100644 --- a/lib/screens/doctorScreens/doctorProfileScreens/address_screen.dart +++ b/lib/screens/doctorScreens/doctorProfileScreens/address_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:telemednet/controllers/doctor_controller.dart'; +import 'package:medora/controllers/doctor_controller.dart'; -import '../../../route_names.dart'; +import '../../../route/route_names.dart'; class DoctorAddressScreen extends StatefulWidget { final DoctorController? controller; diff --git a/lib/screens/doctorScreens/doctorProfileScreens/digital_signature_screen.dart b/lib/screens/doctorScreens/doctorProfileScreens/digital_signature_screen.dart index ab52e07..85a0e66 100644 --- a/lib/screens/doctorScreens/doctorProfileScreens/digital_signature_screen.dart +++ b/lib/screens/doctorScreens/doctorProfileScreens/digital_signature_screen.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'dart:io'; import 'package:image_picker/image_picker.dart'; -import 'package:telemednet/controllers/doctor_controller.dart'; +import 'package:medora/controllers/doctor_controller.dart'; import '../../../data/services/doctor_profile_service.dart'; -import '../../../route_names.dart'; +import '../../../route/route_names.dart'; class DigitalSignatureScreen extends StatefulWidget { final DoctorController controller; diff --git a/lib/screens/doctorScreens/doctorProfileScreens/doctor_profile_screen.dart b/lib/screens/doctorScreens/doctorProfileScreens/doctor_profile_screen.dart index 96d4678..d676952 100644 --- a/lib/screens/doctorScreens/doctorProfileScreens/doctor_profile_screen.dart +++ b/lib/screens/doctorScreens/doctorProfileScreens/doctor_profile_screen.dart @@ -1,8 +1,8 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; -import 'package:telemednet/controllers/doctor_controller.dart'; -import 'package:telemednet/route_names.dart'; +import 'package:medora/controllers/doctor_controller.dart'; +import 'package:medora/route/route_names.dart'; class ProfileUploadPage extends StatefulWidget { const ProfileUploadPage({super.key}); @@ -15,7 +15,7 @@ class _ProfileUploadPageState extends State { final DoctorController _controller = DoctorController(); final TextEditingController _titleController = TextEditingController(); final TextEditingController _surnameController = TextEditingController(); - final TextEditingController _lastnameController = TextEditingController(); + final TextEditingController _firstController = TextEditingController(); final TextEditingController _middlenameController = TextEditingController(); File? _image; final ImagePicker _picker = ImagePicker(); @@ -31,7 +31,7 @@ class _ProfileUploadPageState extends State { _titleController.text = _controller.model.title ?? ''; _surnameController.text = _controller.model.surName ?? ''; - _lastnameController.text = _controller.model.lastName ?? ''; + _firstController.text = _controller.model.firstName ?? ''; _middlenameController.text = _controller.model.middleName ?? ''; } @@ -39,7 +39,7 @@ class _ProfileUploadPageState extends State { void dispose() { _titleController.dispose(); _surnameController.dispose(); - _lastnameController.dispose(); + _firstController.dispose(); _middlenameController.dispose(); super.dispose(); } @@ -65,7 +65,7 @@ class _ProfileUploadPageState extends State { if (_formKey.currentState!.validate()) { _controller.updateTitle(_titleController.text); _controller.updateSurName(_surnameController.text); - _controller.updateLastName(_lastnameController.text); + _controller.updateLastName(_firstController.text); _controller.updateMiddleName(_middlenameController.text); return true; } @@ -242,6 +242,7 @@ class _ProfileUploadPageState extends State { children: [ _buildUniformField( label: 'Name', + icon: Icons.person, child: Container(), // The child parameter is not used in this implementation @@ -355,7 +356,7 @@ class _ProfileUploadPageState extends State { ), Expanded( child: TextFormField( - controller: _lastnameController, + controller: _firstController, onChanged: (value) { _controller.updateLastName(value); }, diff --git a/lib/screens/doctorScreens/doctorProfileScreens/experience_screen.dart b/lib/screens/doctorScreens/doctorProfileScreens/experience_screen.dart index 61be2a6..927ad9c 100644 --- a/lib/screens/doctorScreens/doctorProfileScreens/experience_screen.dart +++ b/lib/screens/doctorScreens/doctorProfileScreens/experience_screen.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:telemednet/controllers/doctor_controller.dart'; +import 'package:medora/controllers/doctor_controller.dart'; -import '../../../route_names.dart'; +import '../../../route/route_names.dart'; class ExperienceScreen extends StatefulWidget { final DoctorController controller; @@ -180,7 +180,7 @@ class _ExperienceScreenState extends State { if (value.length < 5) { return 'License number must be at least 5 digits'; } - if (!RegExp(r'^[0-9]+$').hasMatch(value)) { + if (!RegExp(r'^[a-zA-Z0-9]+$').hasMatch(value)) { return 'Please enter numbers only'; } return null; diff --git a/lib/screens/doctorScreens/doctorProfileScreens/profile_description_screen.dart b/lib/screens/doctorScreens/doctorProfileScreens/profile_description_screen.dart index d9628ff..7bc09b5 100644 --- a/lib/screens/doctorScreens/doctorProfileScreens/profile_description_screen.dart +++ b/lib/screens/doctorScreens/doctorProfileScreens/profile_description_screen.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:telemednet/controllers/doctor_controller.dart'; -import '../../../route_names.dart'; +import 'package:medora/controllers/doctor_controller.dart'; +import '../../../route/route_names.dart'; class ProfileDescriptionScreen extends StatefulWidget { final DoctorController? controller; diff --git a/lib/screens/doctorScreens/doctorProfileScreens/qualifications_screen.dart b/lib/screens/doctorScreens/doctorProfileScreens/qualifications_screen.dart index 51d87da..6c847da 100644 --- a/lib/screens/doctorScreens/doctorProfileScreens/qualifications_screen.dart +++ b/lib/screens/doctorScreens/doctorProfileScreens/qualifications_screen.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:telemednet/controllers/doctor_controller.dart'; -import '../../../route_names.dart'; +import 'package:medora/controllers/doctor_controller.dart'; +import '../../../route/route_names.dart'; class QualificationsScreen extends StatefulWidget { final DoctorController? controller; @@ -82,12 +82,26 @@ class _QualificationsScreenState extends State { if (_formKey.currentState!.validate() && _validateQualification(qualification)) { - setState(() { - qualifications.add(qualification); - _isEditing = true; - _qualificationsController.clear(); - }); - _controller.addQualification(qualification); + // Check if qualification already exists (case-insensitive) + bool isDuplicate = qualifications + .any((q) => q.toLowerCase() == qualification.toLowerCase()); + + if (!isDuplicate) { + setState(() { + qualifications.add(qualification); + _isEditing = true; + _qualificationsController.clear(); + }); + _controller.addQualification(qualification); + } else { + // Show error message for duplicate qualification + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('This qualification has already been added'), + backgroundColor: Colors.red, + ), + ); + } } } @@ -102,8 +116,22 @@ class _QualificationsScreenState extends State { qualifications.remove(qualification); _controller.removeQualification(qualification); } else { - qualifications.add(qualification); - _controller.addQualification(qualification); + // Check if qualification already exists (case-insensitive) + bool isDuplicate = qualifications + .any((q) => q.toLowerCase() == qualification.toLowerCase()); + + if (!isDuplicate) { + qualifications.add(qualification); + _controller.addQualification(qualification); + } else { + // Show error message for duplicate qualification + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('This qualification has already been added'), + backgroundColor: Colors.red, + ), + ); + } } }); } diff --git a/lib/screens/doctorScreens/doctorProfileScreens/specialities_selection_screen.dart b/lib/screens/doctorScreens/doctorProfileScreens/specialities_selection_screen.dart index efea9a3..d52606c 100644 --- a/lib/screens/doctorScreens/doctorProfileScreens/specialities_selection_screen.dart +++ b/lib/screens/doctorScreens/doctorProfileScreens/specialities_selection_screen.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:telemednet/controllers/doctor_controller.dart'; -import '../../../route_names.dart'; +import 'package:medora/controllers/doctor_controller.dart'; +import '../../../route/route_names.dart'; class SpecialitiesScreen extends StatefulWidget { final DoctorController controller; diff --git a/lib/screens/patientScreens/appoinmentBooking/consultation_booking_screen.dart b/lib/screens/patientScreens/appoinmentBooking/consultation_booking_screen.dart index e3dd185..de5e7d2 100644 --- a/lib/screens/patientScreens/appoinmentBooking/consultation_booking_screen.dart +++ b/lib/screens/patientScreens/appoinmentBooking/consultation_booking_screen.dart @@ -2,13 +2,15 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; -import 'package:telemednet/data/models/consultation_center.dart'; -import 'package:telemednet/data/models/doctor.dart'; -import 'package:telemednet/data/services/consultation_booking_service.dart'; -import 'package:telemednet/data/services/patient_registration_service.dart'; -import 'package:telemednet/widgets/alert_screen.dart'; +import 'package:medora/data/models/consultation_center.dart'; +import 'package:medora/data/models/doctor.dart'; +import 'package:medora/data/models/patient.dart'; +import 'package:medora/data/services/consultation_booking_service.dart'; +import 'package:medora/data/services/patient_registration_service.dart'; +import 'package:medora/route/route_names.dart'; +import 'package:medora/widgets/alert_screen.dart'; -class ConsultationBookingScreen extends StatelessWidget { +class ConsultationBookingScreen extends StatefulWidget { final Doctor doctor; final ConsultationCenter selectedConsultation; final DateTime selectedDate; @@ -21,13 +23,58 @@ class ConsultationBookingScreen extends StatelessWidget { required this.selectedDate, required this.selectedTime, }); + + @override + State createState() => + _ConsultationBookingScreenState(); +} + +class _ConsultationBookingScreenState extends State { + PatientModel? selectedPatient; + List familyMembers = []; + FamilyMember? selectedFamilyMember; + bool isLoading = true; + final TextEditingController _nameController = TextEditingController(); + final TextEditingController _relationController = TextEditingController(); + DateTime? _selectedDateOfBirth; + String _selectedGender = 'Male'; + + @override + void dispose() { + _nameController.dispose(); + _relationController.dispose(); + super.dispose(); + } + + @override + void initState() { + super.initState(); + _loadPatientProfile(); + } + + Future _loadPatientProfile() async { + setState(() => isLoading = true); + try { + final currentPatient = await PatientProfileService.getPatientProfile(); + if (currentPatient != null) { + setState(() { + selectedPatient = currentPatient; + }); + } + } catch (e) { + print('Error loading patient data: $e'); + } finally { + setState(() => isLoading = false); + } + } + String get formattedAddress { final parts = [ - selectedConsultation.floorBuilding, - selectedConsultation.street, - selectedConsultation.city, - selectedConsultation.state, - selectedConsultation.postalCode + widget.selectedConsultation.floorBuilding, + widget.selectedConsultation.street, + widget.selectedConsultation.city, + widget.selectedConsultation.state, + widget.selectedConsultation.postalCode ].where((part) => part != null && part.isNotEmpty).toList(); return parts.join(', '); } @@ -51,6 +98,8 @@ class ConsultationBookingScreen extends StatelessWidget { const SizedBox(height: 24), _buildPaymentDetails(), const SizedBox(height: 24), + _buildInClinicAppointmentText(), + const SizedBox(height: 24), _buildConfirmButton(context), ], ), @@ -59,6 +108,63 @@ class ConsultationBookingScreen extends StatelessWidget { ); } + Widget _buildInClinicAppointmentText() { + String patientName = + selectedFamilyMember?.name ?? selectedPatient?.name ?? 'Select Patient'; + String relation = selectedFamilyMember?.relation != null + ? ' (${selectedFamilyMember!.relation})' + : ''; + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: RichText( + text: TextSpan( + style: GoogleFonts.poppins( + fontSize: 16, + color: Colors.black87, + ), + children: [ + const TextSpan(text: 'In-clinic appointment for '), + TextSpan( + text: '$patientName$relation', + style: const TextStyle( + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + TextButton( + onPressed: _showPatientSelectionDialog, + child: Text( + 'Change', + style: GoogleFonts.poppins( + color: Colors.blue, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ); + } + PreferredSizeWidget _buildAppBar(BuildContext context) { return AppBar( backgroundColor: Colors.white, @@ -100,7 +206,7 @@ class ConsultationBookingScreen extends StatelessWidget { const Icon(Icons.calendar_today, color: Colors.white), const SizedBox(width: 12), Text( - DateFormat('EEEE, MMMM d').format(selectedDate), + DateFormat('EEEE, MMMM d').format(widget.selectedDate), style: GoogleFonts.poppins( color: Colors.white, fontSize: 16, @@ -115,7 +221,7 @@ class ConsultationBookingScreen extends StatelessWidget { const Icon(Icons.access_time, color: Colors.white), const SizedBox(width: 12), Text( - selectedTime, + widget.selectedTime, style: GoogleFonts.poppins( color: Colors.white, fontSize: 16, @@ -147,8 +253,8 @@ class ConsultationBookingScreen extends StatelessWidget { children: [ ClipRRect( borderRadius: BorderRadius.circular(12), - child: Image.asset( - doctor.profileImage!, + child: Image.network( + widget.doctor.profileImage!, width: 80, height: 80, fit: BoxFit.cover, @@ -168,21 +274,21 @@ class ConsultationBookingScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - doctor.lastName!, + widget.doctor.firstName ?? '', style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.w600, ), ), Text( - doctor.speciality!, + widget.doctor.speciality!, style: GoogleFonts.poppins( fontSize: 14, color: Colors.grey[600], ), ), Text( - '${doctor.yearsOfExperience} years experience', + '${widget.doctor.yearsOfExperience} years experience', style: GoogleFonts.poppins( fontSize: 14, color: Colors.grey[600], @@ -230,7 +336,7 @@ class ConsultationBookingScreen extends StatelessWidget { ), const SizedBox(height: 8), Text( - 'Average consultation time: ${selectedConsultation.averageDurationMinutes} minutes', + 'Average consultation time: ${widget.selectedConsultation.averageDurationMinutes} minutes', style: GoogleFonts.poppins( fontSize: 14, color: Colors.grey[600], @@ -277,7 +383,7 @@ class ConsultationBookingScreen extends StatelessWidget { ), ), Text( - '₹${selectedConsultation.consultationFee ?? "500"}', + '₹${widget.selectedConsultation.consultationFee ?? "500"}', style: GoogleFonts.poppins( fontSize: 14, fontWeight: FontWeight.w500, @@ -318,14 +424,24 @@ class ConsultationBookingScreen extends StatelessWidget { } void _showConfirmationDialog(BuildContext context) async { - final bookingService = BookingService(); - final currentUser = FirebaseAuth.instance.currentUser; - final patientProfile = await PatientProfileService.getPatientProfile(); - - if (patientProfile == null) { + if (selectedPatient == null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Please select a patient for the appointment'), + backgroundColor: Colors.red, + ), + ); return; } + final bookingService = BookingService(); + final currentUser = FirebaseAuth.instance.currentUser; + + // Get the correct patient name based on selection + final patientName = selectedFamilyMember != null + ? selectedFamilyMember!.name + : selectedPatient!.name; + try { if (context.mounted) { showDialog( @@ -338,15 +454,15 @@ class ConsultationBookingScreen extends StatelessWidget { } final bookingId = await bookingService.createBooking( - doctorName: doctor.lastName!, + doctorName: widget.doctor.firstName ?? 'Doctor', patientId: currentUser!.uid, - patientName: patientProfile.name ?? 'Patient', + patientName: patientName ?? 'Patient', location: formattedAddress, - appointmentDate: selectedDate, - appointmentTime: selectedTime, + appointmentDate: widget.selectedDate, + appointmentTime: widget.selectedTime, consultationFee: - int.parse(selectedConsultation.consultationFee ?? "500"), - specialization: doctor.speciality!, + int.parse(widget.selectedConsultation.consultationFee ?? "500"), + specialization: widget.doctor.speciality!, ); if (context.mounted) { @@ -358,11 +474,12 @@ class ConsultationBookingScreen extends StatelessWidget { arguments: AlertArguments( title: 'Booking Confirmed', message: - 'Your appointment has been successfully booked. Booking ID: ${bookingId.substring(0, 8)}\n\nPlease complete the payment to confirm your appointment.', + 'Your in-clinic appointment has been successfully booked for $patientName. Booking ID: ${bookingId.substring(0, 8)}\n\nPlease complete the payment to confirm your appointment.', actionTitle: 'View Appointments', type: AlertType.success, onActionPressed: () { - Navigator.of(context).popUntil((route) => route.isFirst); + Navigator.pushReplacementNamed( + context, RouteNames.patientDashboardScreen); }, ), ), @@ -391,4 +508,333 @@ class ConsultationBookingScreen extends StatelessWidget { } } } + + Future _showAddFamilyMemberDialog() async { + _nameController.clear(); + _relationController.clear(); + setState(() { + _selectedDateOfBirth = null; + _selectedGender = 'Male'; + }); + + return showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext dialogContext) => StatefulBuilder( + builder: (BuildContext context, StateSetter setDialogState) { + return AlertDialog( + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + title: Text( + 'Add Family Member', + style: GoogleFonts.poppins(fontWeight: FontWeight.w600), + ), + content: AnimatedContainer( + duration: const Duration(milliseconds: 300), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( + controller: _nameController, + decoration: InputDecoration( + labelText: 'Full Name', + labelStyle: GoogleFonts.poppins(), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + prefixIcon: const Icon( + Icons.person_outline, + color: Colors.blue, + ), + ), + ), + const SizedBox(height: 16), + TextFormField( + controller: _relationController, + decoration: InputDecoration( + labelText: 'Relation', + labelStyle: GoogleFonts.poppins(), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + prefixIcon: const Icon( + Icons.family_restroom, + color: Colors.blue, + ), + ), + ), + const SizedBox(height: 16), + InkWell( + onTap: () async { + final DateTime? picked = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1900), + lastDate: DateTime.now(), + builder: (context, child) { + return Theme( + data: Theme.of(context).copyWith( + colorScheme: ColorScheme.light( + primary: Colors.blue, + onPrimary: Colors.white, + surface: Colors.grey[100]!, + ), + ), + child: child!, + ); + }, + ); + if (picked != null) { + setDialogState(() { + _selectedDateOfBirth = picked; + }); + } + }, + child: Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey[300]!), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + children: [ + const Icon(Icons.calendar_today, + color: Colors.blue), + const SizedBox(width: 12), + Text( + _selectedDateOfBirth != null + ? DateFormat('dd/MM/yyyy') + .format(_selectedDateOfBirth!) + : 'Select Date of Birth', + style: GoogleFonts.poppins(), + ), + ], + ), + ), + ), + const SizedBox(height: 16), + Container( + padding: const EdgeInsets.symmetric(horizontal: 12), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey[300]!), + borderRadius: BorderRadius.circular(12), + ), + child: DropdownButtonHideUnderline( + child: DropdownButtonFormField( + value: _selectedGender, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.person_outline, + color: Colors.blue), + border: InputBorder.none, + labelStyle: GoogleFonts.poppins(), + ), + items: ['Male', 'Female', 'Other'] + .map((gender) => DropdownMenuItem( + value: gender, + child: Text(gender, + style: GoogleFonts.poppins()), + )) + .toList(), + onChanged: (value) { + if (value != null) { + setDialogState(() => _selectedGender = value); + } + }, + ), + ), + ), + ], + ), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text( + 'Cancel', + style: GoogleFonts.poppins(color: Colors.grey), + ), + ), + ElevatedButton( + onPressed: () => _addFamilyMember(context), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + padding: + const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + child: Text( + 'Add Member', + style: GoogleFonts.poppins(color: Colors.white), + ), + ), + ], + ); + }, + ), + ); + } + + Future _addFamilyMember(BuildContext context) async { + if (_nameController.text.isEmpty || + _relationController.text.isEmpty || + _selectedDateOfBirth == null) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Please fill in all fields', + style: GoogleFonts.poppins(), + ), + backgroundColor: Colors.red, + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + ); + return; + } + + try { + final newFamilyMember = FamilyMember( + name: _nameController.text, + relation: _relationController.text, + gender: _selectedGender, + dateOfBirth: _selectedDateOfBirth, + ); + + if (selectedPatient != null) { + selectedPatient!.familyMembers.add(newFamilyMember); + await PatientProfileService.updatePatientProfile(selectedPatient!); + + setState(() { + selectedFamilyMember = newFamilyMember; + }); + } + + if (context.mounted) { + Navigator.pop(context); + + _showPatientSelectionDialog(); + } + } catch (e) { + if (context.mounted) { + Navigator.pop(context); // Pop add family member dialog + } + } + } + + void _showPatientSelectionDialog() { + showDialog( + context: context, + builder: (context) => AlertDialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + title: Text( + 'Select Patient', + style: GoogleFonts.poppins(fontWeight: FontWeight.w600), + ), + content: SizedBox( + width: double.maxFinite, + child: ListView( + shrinkWrap: true, + children: [ + // Main patient + _buildPatientTile( + name: selectedPatient?.name ?? '', + subtitle: 'Primary Patient', + isSelected: selectedFamilyMember == null, + onTap: () { + setState(() { + selectedFamilyMember = null; + }); + Navigator.pop(context); + }, + ), + const Divider(), + // Family members + ...selectedPatient?.familyMembers.map( + (member) => _buildPatientTile( + name: member.name ?? '', + subtitle: member.relation ?? '', + isSelected: selectedFamilyMember == member, + onTap: () { + setState(() { + selectedFamilyMember = member; + }); + Navigator.pop(context); + }, + ), + ) ?? + [], + const Divider(), + ListTile( + leading: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.blue.withOpacity(0.1), + shape: BoxShape.circle, + ), + child: const Icon(Icons.person_add, color: Colors.blue), + ), + title: Text( + 'Add Family Member', + style: GoogleFonts.poppins( + color: Colors.blue, + fontWeight: FontWeight.w500, + ), + ), + onTap: () { + Navigator.pop(context); + _showAddFamilyMemberDialog(); + }, + ), + ], + ), + ), + ), + ); + } + + Widget _buildPatientTile({ + required String name, + required String subtitle, + required bool isSelected, + required VoidCallback onTap, + }) { + return ListTile( + leading: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: isSelected + ? Colors.blue.withOpacity(0.1) + : Colors.grey.withOpacity(0.1), + shape: BoxShape.circle, + ), + child: Icon( + Icons.person, + color: isSelected ? Colors.blue : Colors.grey, + ), + ), + title: Text( + name, + style: GoogleFonts.poppins( + fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, + color: isSelected ? Colors.blue : Colors.black87, + ), + ), + subtitle: Text( + subtitle, + style: GoogleFonts.poppins( + color: Colors.grey[600], + ), + ), + trailing: isSelected + ? const Icon(Icons.check_circle, color: Colors.blue) + : null, + onTap: onTap, + ); + } } diff --git a/lib/screens/patientScreens/appoinmentBooking/consultation_time_screen.dart b/lib/screens/patientScreens/appoinmentBooking/consultation_time_screen.dart index a59b7eb..4fb0c11 100644 --- a/lib/screens/patientScreens/appoinmentBooking/consultation_time_screen.dart +++ b/lib/screens/patientScreens/appoinmentBooking/consultation_time_screen.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:telemednet/data/models/consultation_center.dart'; -import 'package:telemednet/data/models/doctor.dart'; +import 'package:medora/data/models/consultation_center.dart'; +import 'package:medora/data/models/doctor.dart'; import 'package:intl/intl.dart'; -import 'package:telemednet/route_names.dart'; +import 'package:medora/route/route_names.dart'; class ConsultationTimeScreen extends StatefulWidget { final Doctor doctor; @@ -134,7 +134,7 @@ class _ConsultationTimeScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.doctor.lastName!, + widget.doctor.firstName ?? '', style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.w600, @@ -152,7 +152,7 @@ class _ConsultationTimeScreenState extends State { ), ClipRRect( borderRadius: BorderRadius.circular(12), - child: Image.asset( + child: Image.network( widget.doctor.profileImage!, width: 60, height: 60, @@ -474,7 +474,7 @@ class _ConsultationTimeScreenState extends State { children: [ _buildConfirmationDetail( 'Doctor', - widget.doctor.lastName!, + widget.doctor.firstName!, ), const SizedBox(height: 8), _buildConfirmationDetail( diff --git a/lib/screens/patientScreens/appoinmentBooking/consultations_center_screen.dart b/lib/screens/patientScreens/appoinmentBooking/consultations_center_screen.dart index 5cb3942..f5a21f0 100644 --- a/lib/screens/patientScreens/appoinmentBooking/consultations_center_screen.dart +++ b/lib/screens/patientScreens/appoinmentBooking/consultations_center_screen.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:telemednet/data/models/doctor.dart'; -import 'package:telemednet/data/models/consultation_center.dart'; -import 'package:telemednet/data/services/consultation_center_service.dart'; -import 'package:telemednet/route_names.dart'; +import 'package:medora/data/models/doctor.dart'; +import 'package:medora/data/models/consultation_center.dart'; +import 'package:medora/data/services/consultation_center_service.dart'; +import 'package:medora/route/route_names.dart'; class ConsultationsCenterScreen extends StatefulWidget { final Doctor doctor; @@ -143,7 +143,7 @@ class _ConsultationsCenterScreenState extends State { children: [ ClipRRect( borderRadius: BorderRadius.circular(12), - child: Image.asset( + child: Image.network( widget.doctor.profileImage!, width: 80, height: 80, @@ -164,7 +164,7 @@ class _ConsultationsCenterScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.doctor.lastName!, + widget.doctor.firstName ?? "", style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.w600, diff --git a/lib/screens/patientScreens/appoinmentBooking/doctor_details_screen.dart b/lib/screens/patientScreens/appoinmentBooking/doctor_details_screen.dart index 92c74d2..52d35e6 100644 --- a/lib/screens/patientScreens/appoinmentBooking/doctor_details_screen.dart +++ b/lib/screens/patientScreens/appoinmentBooking/doctor_details_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:telemednet/data/models/doctor.dart'; -import 'package:telemednet/route_names.dart'; +import 'package:medora/data/models/doctor.dart'; +import 'package:medora/route/route_names.dart'; class DoctorDetailsScreen extends StatelessWidget { final Doctor doctor; @@ -115,7 +115,7 @@ class DoctorDetailsScreen extends StatelessWidget { children: [ ClipRRect( borderRadius: BorderRadius.circular(12), - child: Image.asset( + child: Image.network( doctor.profileImage!, width: 100, height: 100, @@ -137,7 +137,7 @@ class DoctorDetailsScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - doctor.lastName!, + doctor.firstName ?? '', style: GoogleFonts.poppins( fontSize: 20, fontWeight: FontWeight.w600, diff --git a/lib/screens/patientScreens/appoinmentBooking/doctors_list_screen.dart b/lib/screens/patientScreens/appoinmentBooking/doctors_list_screen.dart index 9ea69c6..9743cf6 100644 --- a/lib/screens/patientScreens/appoinmentBooking/doctors_list_screen.dart +++ b/lib/screens/patientScreens/appoinmentBooking/doctors_list_screen.dart @@ -2,9 +2,9 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:telemednet/data/models/doctor.dart'; +import 'package:medora/data/models/doctor.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:telemednet/route_names.dart'; +import 'package:medora/route/route_names.dart'; class DoctorsListScreen extends StatefulWidget { final String specialty; @@ -174,7 +174,7 @@ class _DoctorsListScreenState extends State { .where((doctor) { if (_searchController.text.isEmpty) return true; final searchQuery = _searchController.text.toLowerCase(); - return doctor.surName!.toLowerCase().contains(searchQuery) || + return doctor.firstName!.toLowerCase().contains(searchQuery) || doctor.city!.toLowerCase().contains(searchQuery); }).toList(); @@ -244,7 +244,7 @@ class _DoctorsListScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - doctor.surName!, + doctor.firstName ?? '', style: GoogleFonts.poppins( fontSize: 16, fontWeight: FontWeight.w600, diff --git a/lib/screens/patientScreens/appoinmentBooking/speciality_screen.dart b/lib/screens/patientScreens/appoinmentBooking/speciality_screen.dart index 245978c..233b8a8 100644 --- a/lib/screens/patientScreens/appoinmentBooking/speciality_screen.dart +++ b/lib/screens/patientScreens/appoinmentBooking/speciality_screen.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:animate_do/animate_do.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; -import 'package:telemednet/route_names.dart'; +import 'package:medora/route/route_names.dart'; class Specialty { final String name; diff --git a/lib/screens/patientScreens/patientDashboard/patient_dashboard_screen.dart b/lib/screens/patientScreens/patientDashboard/patient_dashboard_screen.dart index 0f9c0d8..39eff1b 100644 --- a/lib/screens/patientScreens/patientDashboard/patient_dashboard_screen.dart +++ b/lib/screens/patientScreens/patientDashboard/patient_dashboard_screen.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:curved_navigation_bar/curved_navigation_bar.dart'; -import 'package:telemednet/screens/patientScreens/patientDashboard/patient_home_screen.dart'; -import 'package:telemednet/screens/patientScreens/patientDashboard/patient_profile_screen.dart'; +import 'package:medora/screens/patientScreens/patientDashboard/patient_home_screen.dart'; +import 'package:medora/screens/patientScreens/patientDashboard/patient_profile_screen.dart'; class PatientDashboardScreen extends StatefulWidget { const PatientDashboardScreen({super.key}); @@ -46,8 +46,8 @@ class _PatientDashboardScreenState extends State { index: _selectedIndex, items: const [ Icon(Icons.home, size: 30, color: Colors.white), - // Icon(Icons.chat_bubble, size: 30, color: Colors.white), - Icon(Icons.list, size: 30, color: Colors.white), + Icon(Icons.chat_bubble, size: 30, color: Colors.white), + Icon(Icons.assignment, size: 30, color: Colors.white), Icon(Icons.person, size: 30, color: Colors.white), ], onTap: (index) { diff --git a/lib/screens/patientScreens/patientDashboard/patient_home_screen.dart b/lib/screens/patientScreens/patientDashboard/patient_home_screen.dart index dacefd9..6c21ef3 100644 --- a/lib/screens/patientScreens/patientDashboard/patient_home_screen.dart +++ b/lib/screens/patientScreens/patientDashboard/patient_home_screen.dart @@ -1,8 +1,13 @@ +import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; +import 'package:medora/data/models/consultation_booking.dart'; +import 'package:medora/data/services/consultation_booking_service.dart'; +import 'package:medora/route/route_names.dart'; -import 'package:telemednet/screens/patientScreens/appoinmentBooking/speciality_screen.dart'; +import 'package:medora/screens/patientScreens/appoinmentBooking/speciality_screen.dart'; class PatientHomeScreen extends StatefulWidget { const PatientHomeScreen({super.key}); @@ -14,6 +19,8 @@ class PatientHomeScreen extends StatefulWidget { class _PatientHomeScreenState extends State with SingleTickerProviderStateMixin { late AnimationController _animationController; + final BookingService _bookingService = BookingService(); + late Stream> _bookingsStream; @override void initState() { @@ -23,6 +30,14 @@ class _PatientHomeScreenState extends State duration: const Duration(milliseconds: 300), ); _animationController.forward(); + + final User? user = FirebaseAuth.instance.currentUser; + if (user != null) { + final String userId = user.uid; + _bookingsStream = _bookingService.getPatientBookings(userId); + } else { + _bookingsStream = const Stream.empty(); + } } @override @@ -50,7 +65,6 @@ class _PatientHomeScreenState extends State ], ), ), - // _buildBottomNavBar(), ], ), ), @@ -61,14 +75,7 @@ class _PatientHomeScreenState extends State return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Colors.blue[400]!, - Colors.blue[300]!, - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), + color: Colors.blue, borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(30.0), bottomRight: Radius.circular(30.0), @@ -179,47 +186,161 @@ class _PatientHomeScreenState extends State return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - 'Upcoming Consultations', - style: GoogleFonts.poppins( - fontSize: 20, - fontWeight: FontWeight.bold, + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Upcoming Consultations', + style: GoogleFonts.poppins( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Colors.grey[800], + ), + ), + ], ), ), - const SizedBox(height: 16), + const SizedBox(height: 20), SizedBox( - height: 160, - child: ListView( - scrollDirection: Axis.horizontal, - children: [ - _consultationCard( - 'Dr. Smith', '23/09/2024\n5:00 PM - 6:00 PM', 'Cardiologist'), - const SizedBox(width: 16), - _consultationCard('Dr. Johnson', '24/09/2024\n3:30 PM - 4:30 PM', - 'Pediatrician'), - ], + height: 201, + child: StreamBuilder>( + stream: _bookingsStream, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 12), + Text( + 'Loading consultations...', + style: GoogleFonts.poppins( + color: Colors.grey[600], + ), + ), + ], + ), + ); + } + + if (snapshot.hasError) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.error_outline, + color: Colors.red[400], size: 48), + const SizedBox(height: 12), + Text( + 'Error loading consultations', + style: GoogleFonts.poppins( + color: Colors.red[400], + fontWeight: FontWeight.w500, + ), + ), + TextButton( + onPressed: () { + // Implement refresh logic + }, + child: Text( + 'Try Again', + style: GoogleFonts.poppins( + color: Colors.blue[700], + ), + ), + ), + ], + ), + ); + } + + final bookings = snapshot.data ?? []; + + if (bookings.isEmpty) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.calendar_today, + color: Colors.grey[400], size: 48), + const SizedBox(height: 12), + Text( + 'No upcoming consultations', + style: GoogleFonts.poppins( + color: Colors.grey[600], + fontSize: 16, + ), + ), + TextButton( + onPressed: () { + // Navigate to book consultation + }, + child: Text( + 'Book a Consultation', + style: GoogleFonts.poppins( + color: Colors.blue[700], + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ); + } + + return ListView.builder( + padding: const EdgeInsets.symmetric(horizontal: 20), + scrollDirection: Axis.horizontal, + itemCount: bookings.length, + itemBuilder: (context, index) { + final booking = bookings[index]; + return Padding( + padding: const EdgeInsets.only(right: 16), + child: Hero( + tag: 'consultation_${booking.id}', + child: Material( + child: _consultationCard( + booking.doctorName, + '${DateFormat('EEE, MMM d, yyyy').format(booking.appointmentDate)}\n${booking.appointmentTime}', + booking.specialization, + booking.paymentStatus, + ), + ), + ), + ); + }, + ); + }, ), ), ], ); } - Widget _consultationCard(String name, String schedule, String speciality) { + Widget _consultationCard( + String name, + String schedule, + String speciality, + PaymentStatus paymentStatus, + ) { return Container( - width: 280, - padding: const EdgeInsets.all(16), + width: 300, + padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.white, Colors.grey[50]!], begin: Alignment.topLeft, end: Alignment.bottomRight, ), - borderRadius: BorderRadius.circular(20), + borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( - color: Colors.grey.withOpacity(0.2), - blurRadius: 10, - offset: const Offset(0, 5), + color: Colors.grey.withOpacity(0.1), + blurRadius: 20, + offset: const Offset(0, 8), ), ], ), @@ -229,19 +350,30 @@ class _PatientHomeScreenState extends State Row( children: [ Container( - width: 60, - height: 60, + width: 64, + height: 64, decoration: BoxDecoration( - color: Colors.blue[100], + gradient: LinearGradient( + colors: [Colors.blue[400]!, Colors.blue[600]!], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: Colors.blue[300]!.withOpacity(0.3), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ], ), child: const Icon( Icons.person, - size: 40, + size: 36, color: Colors.white, ), ), - const SizedBox(width: 12), + const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -249,14 +381,50 @@ class _PatientHomeScreenState extends State Text( name, style: GoogleFonts.poppins( - fontSize: 16, + fontSize: 18, fontWeight: FontWeight.bold, + color: Colors.grey[800], ), ), Text( speciality, style: GoogleFonts.poppins( color: Colors.grey[600], + fontSize: 14, + ), + ), + const SizedBox(height: 8), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 4, + ), + decoration: BoxDecoration( + color: _getStatusColor(paymentStatus).withOpacity(0.1), + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: + _getStatusColor(paymentStatus).withOpacity(0.2), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + _getStatusIcon(paymentStatus), + size: 14, + color: _getStatusColor(paymentStatus), + ), + const SizedBox(width: 4), + Text( + _getStatusText(paymentStatus), + style: GoogleFonts.poppins( + fontSize: 12, + color: _getStatusColor(paymentStatus), + fontWeight: FontWeight.w600, + ), + ), + ], ), ), ], @@ -264,26 +432,79 @@ class _PatientHomeScreenState extends State ), ], ), - const SizedBox(height: 12), + const SizedBox(height: 16), Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: Colors.blue[50], - borderRadius: BorderRadius.circular(10), - ), - child: Text( - schedule, - style: GoogleFonts.poppins( - color: Colors.blue[700], - fontSize: 12, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: Colors.blue[100]!, ), ), + child: Row( + children: [ + Icon( + Icons.calendar_today, + size: 18, + color: Colors.blue[700], + ), + const SizedBox(width: 8), + Text( + schedule, + style: GoogleFonts.poppins( + color: Colors.blue[700], + fontSize: 13, + fontWeight: FontWeight.w500, + ), + ), + ], + ), ), ], ), ); } + IconData _getStatusIcon(PaymentStatus status) { + switch (status) { + case PaymentStatus.completed: + return Icons.check_circle; + case PaymentStatus.pending: + return Icons.access_time; + case PaymentStatus.failed: + return Icons.error; + default: + return Icons.info; + } + } + + Color _getStatusColor(PaymentStatus status) { + switch (status) { + case PaymentStatus.pending: + return Colors.orange; + case PaymentStatus.completed: + return Colors.green; + case PaymentStatus.failed: + return Colors.red; + default: + return Colors.grey; + } + } + + String _getStatusText(PaymentStatus status) { + switch (status) { + case PaymentStatus.pending: + return 'Payment Pending'; + case PaymentStatus.completed: + return 'Confirmed'; + case PaymentStatus.failed: + return 'Payment Failed'; + default: + return 'Unknown'; + } + } + Widget _buildFindDoctorSection() { final specialistData = [ { @@ -396,7 +617,13 @@ class _PatientHomeScreenState extends State }) { return GestureDetector( onTap: () { - // Replace with your desired navigation action + Navigator.pushNamed( + context, + RouteNames.doctorListScreen, + arguments: { + 'specialty': label, + }, + ); }, child: Container( width: 140, diff --git a/lib/screens/patientScreens/patientDashboard/patient_profile_screen.dart b/lib/screens/patientScreens/patientDashboard/patient_profile_screen.dart index d827337..703f866 100644 --- a/lib/screens/patientScreens/patientDashboard/patient_profile_screen.dart +++ b/lib/screens/patientScreens/patientDashboard/patient_profile_screen.dart @@ -1,6 +1,8 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; -import 'package:telemednet/route_names.dart'; +import 'package:medora/data/services/patient_registration_service.dart'; +import 'package:medora/route/route_names.dart'; +import 'package:medora/data/models/patient.dart'; class PatientProfileScreen extends StatefulWidget { const PatientProfileScreen({super.key}); @@ -11,7 +13,23 @@ class PatientProfileScreen extends StatefulWidget { class _PatientProfileScreenState extends State { final FirebaseAuth _auth = FirebaseAuth.instance; - // final GlobalKey _bottomNavigationKey = GlobalKey(); + PatientModel? _patientProfile; + + @override + void initState() { + super.initState(); + _fetchPatientProfile(); + } + + Future _fetchPatientProfile() async { + final patientProfile = await PatientProfileService.getPatientProfile(); + if (mounted) { + setState(() { + _patientProfile = patientProfile; + }); + } + } + @override Widget build(BuildContext context) { return Scaffold( @@ -20,8 +38,6 @@ class _PatientProfileScreenState extends State { children: [ _buildProfileHeader(), _buildProfileOptions(), - const Spacer(), - // _buildBottomNavBar(), ], ), ), @@ -50,41 +66,46 @@ class _PatientProfileScreenState extends State { Container( width: 60, height: 60, - decoration: const BoxDecoration( + decoration: BoxDecoration( color: Colors.white, shape: BoxShape.circle, + image: _patientProfile?.profileImageUrl != null + ? DecorationImage( + image: NetworkImage(_patientProfile!.profileImageUrl!), + fit: BoxFit.cover, + ) + : null, ), - child: const Center( - child: Text( - 'D', - style: TextStyle( - fontSize: 30, - fontWeight: FontWeight.bold, - color: Colors.blue, - ), - ), - ), + child: _patientProfile?.profileImageUrl == null + ? Center( + child: Text( + _patientProfile != null && _patientProfile!.name != null + ? _patientProfile!.name![0].toUpperCase() + : '', + style: const TextStyle( + fontSize: 30, + fontWeight: FontWeight.bold, + color: Colors.blue, + ), + ), + ) + : null, ), const SizedBox(width: 16), - const Expanded( + Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Dhansh A S', - style: TextStyle( + _patientProfile != null && _patientProfile!.name != null + ? _patientProfile!.name! + : 'Create your profile', + style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.white, ), ), - Text( - 'User profile is incomplete', - style: TextStyle( - fontSize: 14, - color: Colors.white70, - ), - ), ], ), ), @@ -117,7 +138,9 @@ class _PatientProfileScreenState extends State { _buildOptionTile( 'Medical Profile', Icons.medical_information_outlined, - onTap: () {}, + onTap: () { + // Add navigation or action + }, ), const Divider(height: 1), _buildOptionTile( diff --git a/lib/screens/patientScreens/patient_landing_screen.dart b/lib/screens/patientScreens/patient_landing_screen.dart index e6f8b7d..f3cda12 100644 --- a/lib/screens/patientScreens/patient_landing_screen.dart +++ b/lib/screens/patientScreens/patient_landing_screen.dart @@ -1,5 +1,5 @@ +import 'package:medora/route/route_names.dart'; import 'package:flutter/material.dart'; -import 'package:telemednet/route_names.dart'; class PatientLandingScreen extends StatelessWidget { const PatientLandingScreen({super.key}); diff --git a/lib/screens/patientScreens/registrationScreens/family_members_edit_screen.dart b/lib/screens/patientScreens/registrationScreens/family_members_edit_screen.dart index abcf6db..1692af9 100644 --- a/lib/screens/patientScreens/registrationScreens/family_members_edit_screen.dart +++ b/lib/screens/patientScreens/registrationScreens/family_members_edit_screen.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:telemednet/controllers/patient_controller.dart'; -import 'package:telemednet/data/models/patient.dart'; +import 'package:medora/controllers/patient_controller.dart'; +import 'package:medora/data/models/patient.dart'; class FamilyMembersEditScreen extends StatefulWidget { final FamilyMember? familyMember; diff --git a/lib/screens/patientScreens/registrationScreens/patient_adress_screen.dart b/lib/screens/patientScreens/registrationScreens/patient_adress_screen.dart index 62e8a01..9b9f877 100644 --- a/lib/screens/patientScreens/registrationScreens/patient_adress_screen.dart +++ b/lib/screens/patientScreens/registrationScreens/patient_adress_screen.dart @@ -1,6 +1,6 @@ +import 'package:medora/controllers/patient_controller.dart'; import 'package:flutter/material.dart'; import 'package:country_state_city_picker/country_state_city_picker.dart'; -import 'package:telemednet/controllers/patient_controller.dart'; class PatientAddressScreen extends StatefulWidget { final PatientController? controller; diff --git a/lib/screens/patientScreens/registrationScreens/patient_family_members_screen.dart b/lib/screens/patientScreens/registrationScreens/patient_family_members_screen.dart index 4d2485f..58f9e45 100644 --- a/lib/screens/patientScreens/registrationScreens/patient_family_members_screen.dart +++ b/lib/screens/patientScreens/registrationScreens/patient_family_members_screen.dart @@ -1,6 +1,6 @@ +import 'package:medora/data/models/patient.dart'; +import 'package:medora/screens/patientScreens/registrationScreens/family_members_edit_screen.dart'; import 'package:flutter/material.dart'; -import 'package:telemednet/screens/patientScreens/registrationScreens/family_members_edit_screen.dart'; -import 'package:telemednet/data/models/patient.dart'; import '../../../controllers/patient_controller.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; diff --git a/lib/screens/patientScreens/registrationScreens/patient_registration_screen.dart b/lib/screens/patientScreens/registrationScreens/patient_registration_screen.dart index 10f7bfc..2b2af16 100644 --- a/lib/screens/patientScreens/registrationScreens/patient_registration_screen.dart +++ b/lib/screens/patientScreens/registrationScreens/patient_registration_screen.dart @@ -1,6 +1,6 @@ +import 'package:medora/route/route_names.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; -import 'package:telemednet/route_names.dart'; import 'package:image_picker/image_picker.dart'; import 'dart:io'; diff --git a/lib/screens/splash_screen.dart b/lib/screens/splash_screen.dart new file mode 100644 index 0000000..b99122e --- /dev/null +++ b/lib/screens/splash_screen.dart @@ -0,0 +1,38 @@ +import 'package:medora/data/services/navigation_service.dart'; +import 'package:flutter/material.dart'; + +class SplashScreen extends StatefulWidget { + const SplashScreen({super.key}); + + @override + State createState() => _SplashScreenState(); +} + +class _SplashScreenState extends State { + @override + void initState() { + super.initState(); + Future.delayed(const Duration(seconds: 3), () { + if (!mounted) return; + _navigateToAppropriateScreen(); + }); + } + + Future _navigateToAppropriateScreen() async { + await NavigationService.handleUserNavigation(context); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('images/splash_screen.jpg'), + fit: BoxFit.cover, + ), + ), + ), + ); + } +} diff --git a/lib/telemednet_app.dart b/lib/telemednet_app.dart index c22d28c..28e81ae 100644 --- a/lib/telemednet_app.dart +++ b/lib/telemednet_app.dart @@ -1,6 +1,7 @@ +import 'package:medora/route/route_names.dart'; +import 'package:medora/route/routes.dart'; +import 'package:medora/screens/splash_screen.dart'; import 'package:flutter/material.dart'; -import 'package:telemednet/route_names.dart'; -import 'package:telemednet/routes.dart'; class TelemednetApp extends StatefulWidget { const TelemednetApp({super.key}); @@ -15,14 +16,15 @@ class _TelemednetAppState extends State { super.initState(); } - Future login() async {} - @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, - initialRoute: RouteNames.launch, - routes: routes, + initialRoute: RouteNames.splashScreen, + routes: { + RouteNames.splashScreen: (context) => const SplashScreen(), + ...routes, + }, ); } } diff --git a/pubspec.lock b/pubspec.lock index beecb71..dd032bd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -9,6 +9,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.44" + animate_do: + dependency: "direct main" + description: + name: animate_do + sha256: "7a3162729f0ea042f9dd84da217c5bde5472ad9cef644079929d4304a5dc4ca0" + url: "https://pub.dev" + source: hosted + version: "3.3.4" + animations: + dependency: "direct main" + description: + name: animations + sha256: d3d6dcfb218225bbe68e87ccf6378bbb2e32a94900722c5f81611dad089911cb + url: "https://pub.dev" + source: hosted + version: "2.0.11" + archive: + dependency: transitive + description: + name: archive + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + url: "https://pub.dev" + source: hosted + version: "3.6.1" args: dependency: transitive description: @@ -33,6 +57,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + carousel_slider: + dependency: "direct main" + description: + name: carousel_slider + sha256: "7b006ec356205054af5beaef62e2221160ea36b90fb70a35e4deacd49d0349ae" + url: "https://pub.dev" + source: hosted + version: "5.0.0" characters: dependency: transitive description: @@ -41,6 +73,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" clock: dependency: transitive description: @@ -121,6 +169,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" + curved_navigation_bar: + dependency: "direct main" + description: + name: curved_navigation_bar + sha256: bb4ab128fcb6f4a9f0f1f72d227db531818b20218984789777f049fcbf919279 + url: "https://pub.dev" + source: hosted + version: "1.0.6" desktop_webview_auth: dependency: transitive description: @@ -145,6 +201,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" + source: hosted + version: "2.1.3" fhir: dependency: "direct main" description: @@ -326,6 +390,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.2.1" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "619817c4b65b322b5104b6bb6dfe6cda62d9729bd7ad4303ecc8b4e690a67a77" + url: "https://pub.dev" + source: hosted + version: "0.14.1" flutter_lints: dependency: "direct dev" description: @@ -355,6 +427,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.1" + flutter_staggered_animations: + dependency: "direct main" + description: + name: flutter_staggered_animations + sha256: "81d3c816c9bb0dca9e8a5d5454610e21ffb068aedb2bde49d2f8d04f75538351" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter_staggered_grid_view: + dependency: "direct main" + description: + name: flutter_staggered_grid_view + sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395" + url: "https://pub.dev" + source: hosted + version: "0.7.0" flutter_svg: dependency: transitive description: @@ -389,6 +477,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82 + url: "https://pub.dev" + source: hosted + version: "6.2.1" http: dependency: transitive description: @@ -405,6 +501,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + image: + dependency: transitive + description: + name: image + sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d + url: "https://pub.dev" + source: hosted + version: "4.3.0" image_picker: dependency: "direct main" description: @@ -558,7 +662,7 @@ packages: source: hosted version: "2.0.0" path: - dependency: transitive + dependency: "direct main" description: name: path sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" @@ -569,10 +673,58 @@ packages: dependency: transitive description: name: path_parsing - sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.0.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 + url: "https://pub.dev" + source: hosted + version: "2.1.4" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a + url: "https://pub.dev" + source: hosted + version: "2.2.12" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + url: "https://pub.dev" + source: hosted + version: "2.4.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" petitparser: dependency: transitive description: @@ -581,6 +733,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.2" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" plugin_platform_interface: dependency: transitive description: @@ -589,6 +749,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + shimmer: + dependency: "direct main" + description: + name: shimmer + sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9" + url: "https://pub.dev" + source: hosted + version: "3.0.0" sky_engine: dependency: transitive description: flutter @@ -714,6 +882,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" xml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2b48ec3..daa0c2f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,4 +1,4 @@ -name: telemednet +name: medora description: "A new Flutter project." # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. @@ -57,6 +57,8 @@ dependencies: flutter_staggered_animations: ^1.1.1 flutter_staggered_grid_view: ^0.7.0 carousel_slider: ^5.0.0 + path: ^1.9.0 + dev_dependencies: flutter_test: @@ -68,13 +70,18 @@ dev_dependencies: # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^4.0.0 + flutter_launcher_icons: ^0.14.1 +flutter_icons: + android: true + ios: true + image_path: "images/logo.jpg" + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec # The following section is specific to Flutter packages. flutter: - # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. @@ -90,6 +97,7 @@ flutter: - images/patient-avathar.png - images/MaleDr.jpg.png - images/FemaleDr.jpg.png + - images/splash_screen.jpg # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/to/resolution-aware-images