feature/medora-55 (#6)
Booking physical consultation , bugs fixed and Profile picture adding using firebase storage is complete. Co-authored-by: Jipson George <152465898+Jipson-cosq@users.noreply.github.com> Reviewed-on: cosqnet/telemednet#6 Co-authored-by: DhanshCOSQ <dhanshas@cosq.net> Co-committed-by: DhanshCOSQ <dhanshas@cosq.net>
3
.env
@ -2,4 +2,5 @@ CUSTOM_SCHEME=com.cosqnet.telemednet
|
|||||||
PROFILE_COLLECTION_NAME=telemednetusers
|
PROFILE_COLLECTION_NAME=telemednetusers
|
||||||
PATIENT_PROFILE_COLLECTION_NAME=patientprofiles
|
PATIENT_PROFILE_COLLECTION_NAME=patientprofiles
|
||||||
DOCTOR_PROFILE_COLLECTION_NAME=doctorprofiles
|
DOCTOR_PROFILE_COLLECTION_NAME=doctorprofiles
|
||||||
CONSULTATION_CENTER_COLLECTION_NAME=businesscenters
|
CONSULTATION_CENTER_COLLECTION_NAME=businesscenters
|
||||||
|
FIREBASE_STORAGE_BUCKET=gs://cosq-telemednet-dev.firebasestorage.app
|
||||||
|
|||||||
6
.vscode/launch.json
vendored
@ -5,18 +5,18 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "telemednet",
|
"name": "Medora",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "dart"
|
"type": "dart"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "telemednet (profile mode)",
|
"name": "Medora (profile mode)",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
"flutterMode": "profile"
|
"flutterMode": "profile"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "telemednet (release mode)",
|
"name": "Medora (release mode)",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
"flutterMode": "release"
|
"flutterMode": "release"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<application
|
<application
|
||||||
android:label="telemednet"
|
android:label="Medora"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
</adaptive-icon>
|
||||||
|
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 6.5 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/launcher_icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 31 KiB |
BIN
images/logo.jpg
Normal file
|
After Width: | Height: | Size: 274 KiB |
BIN
images/splash_screen.jpg
Normal file
|
After Width: | Height: | Size: 227 KiB |
@ -427,7 +427,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
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_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
@ -484,7 +484,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
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_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
|||||||
@ -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":"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"}}
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 501 KiB |
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 901 B |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 25 KiB |
@ -1,4 +1,4 @@
|
|||||||
import 'package:telemednet/data/models/doctor.dart';
|
import 'package:medora/data/models/doctor.dart';
|
||||||
|
|
||||||
class ValidationHelper {
|
class ValidationHelper {
|
||||||
// Basic regex patterns
|
// Basic regex patterns
|
||||||
@ -92,16 +92,16 @@ class DoctorController {
|
|||||||
model.middleName = middleName;
|
model.middleName = middleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateLastName(String lastName) {
|
void updateLastName(String firstName) {
|
||||||
model.lastName = lastName;
|
model.firstName = firstName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addQualification(String qualification) {
|
void addQualification(String qualification) {
|
||||||
model.qualifications!.add(qualification);
|
model.qualifications!.add(qualification.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeQualification(String qualification) {
|
void removeQualification(String qualification) {
|
||||||
model.qualifications!.remove(qualification);
|
model.qualifications!.remove(qualification.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateFloorBuilding(String floorBuilding) {
|
void updateFloorBuilding(String floorBuilding) {
|
||||||
|
|||||||
@ -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';
|
import '../data/services/patient_registration_service.dart';
|
||||||
|
|
||||||
class PatientController {
|
class PatientController {
|
||||||
@ -95,7 +95,7 @@ class PatientController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> updatePatientData() async {
|
Future<bool> updatePatientData() async {
|
||||||
return await PatientProfileService.updatePatientProfile(this);
|
return await PatientProfileService.updatePatientProfile(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> deletePatientData() async {
|
Future<bool> deletePatientData() async {
|
||||||
|
|||||||
@ -10,7 +10,7 @@ class Doctor {
|
|||||||
String? title;
|
String? title;
|
||||||
String? surName;
|
String? surName;
|
||||||
String? middleName;
|
String? middleName;
|
||||||
String? lastName;
|
String? firstName;
|
||||||
List<String>? qualifications = [];
|
List<String>? qualifications = [];
|
||||||
String? floorBuilding;
|
String? floorBuilding;
|
||||||
String? street;
|
String? street;
|
||||||
@ -32,7 +32,7 @@ class Doctor {
|
|||||||
this.title,
|
this.title,
|
||||||
this.surName,
|
this.surName,
|
||||||
this.middleName,
|
this.middleName,
|
||||||
this.lastName,
|
this.firstName,
|
||||||
this.qualifications,
|
this.qualifications,
|
||||||
this.floorBuilding,
|
this.floorBuilding,
|
||||||
this.street,
|
this.street,
|
||||||
@ -53,7 +53,7 @@ class Doctor {
|
|||||||
'digitalSignature': digitalSignature,
|
'digitalSignature': digitalSignature,
|
||||||
'title': title,
|
'title': title,
|
||||||
'surname': surName,
|
'surname': surName,
|
||||||
'lastName': lastName,
|
'firstName': firstName,
|
||||||
'middleName': middleName,
|
'middleName': middleName,
|
||||||
'qualifications': qualifications,
|
'qualifications': qualifications,
|
||||||
'floorBuilding': floorBuilding,
|
'floorBuilding': floorBuilding,
|
||||||
@ -76,7 +76,7 @@ class Doctor {
|
|||||||
title: json['title'],
|
title: json['title'],
|
||||||
surName: json['surname'],
|
surName: json['surname'],
|
||||||
middleName: json['middleName'],
|
middleName: json['middleName'],
|
||||||
lastName: json['lastName'],
|
firstName: json['firstName'],
|
||||||
qualifications: List<String>.from(json['qualifications'] ?? []),
|
qualifications: List<String>.from(json['qualifications'] ?? []),
|
||||||
floorBuilding: json['floorBuilding'],
|
floorBuilding: json['floorBuilding'],
|
||||||
street: json['street'],
|
street: json['street'],
|
||||||
|
|||||||
@ -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<String> qualification;
|
|
||||||
// final List<Map<String, dynamic>> 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<String, dynamic>;
|
|
||||||
// return Doctors(
|
|
||||||
// name: data['name'] ?? '',
|
|
||||||
// location: data['location'] ?? '',
|
|
||||||
// specialization: data['specialization'] ?? '',
|
|
||||||
// experience: data['experience'] ?? 0,
|
|
||||||
// description: data['description'] ?? '',
|
|
||||||
// qualification: List<String>.from(data['qualification'] ?? []),
|
|
||||||
// consultation: List<Map<String, dynamic>>.from(data['consultation'] ?? []),
|
|
||||||
// profileImage: data['profile_image'] ?? '',
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@ -4,6 +4,7 @@ class PatientModel {
|
|||||||
String? gender;
|
String? gender;
|
||||||
DateTime? dateOfBirth;
|
DateTime? dateOfBirth;
|
||||||
String? profileImagePath;
|
String? profileImagePath;
|
||||||
|
String? profileImageUrl;
|
||||||
PatientAddress address;
|
PatientAddress address;
|
||||||
|
|
||||||
List<FamilyMember> familyMembers = [];
|
List<FamilyMember> familyMembers = [];
|
||||||
@ -17,6 +18,7 @@ class PatientModel {
|
|||||||
'gender': gender,
|
'gender': gender,
|
||||||
'dateOfBirth': dateOfBirth?.toIso8601String(),
|
'dateOfBirth': dateOfBirth?.toIso8601String(),
|
||||||
'profileImagePath': profileImagePath,
|
'profileImagePath': profileImagePath,
|
||||||
|
'profileImageUrl': profileImageUrl,
|
||||||
'address': address.toJson(),
|
'address': address.toJson(),
|
||||||
'familyMembers': familyMembers.map((member) => member.toJson()).toList(),
|
'familyMembers': familyMembers.map((member) => member.toJson()).toList(),
|
||||||
};
|
};
|
||||||
@ -31,15 +33,11 @@ class PatientModel {
|
|||||||
? DateTime.parse(json['dateOfBirth'])
|
? DateTime.parse(json['dateOfBirth'])
|
||||||
: null;
|
: null;
|
||||||
profileImagePath = json['profileImagePath'];
|
profileImagePath = json['profileImagePath'];
|
||||||
address.houseNo = json['houseNo'];
|
profileImageUrl = json['profileImageUrl'];
|
||||||
address.line = json['line'];
|
if (json['address'] != null) {
|
||||||
address.town = json['town'];
|
address =
|
||||||
address.pincode = json['pincode'];
|
PatientAddress.fromJson(json['address'] as Map<String, dynamic>);
|
||||||
address.country = json['country'];
|
}
|
||||||
address.state = json['state'];
|
|
||||||
address.city = json['city'];
|
|
||||||
address.addressType = json['addressType'];
|
|
||||||
address.otherLabel = json['otherLabel'];
|
|
||||||
if (json['familyMembers'] != null) {
|
if (json['familyMembers'] != null) {
|
||||||
familyMembers = (json['familyMembers'] as List)
|
familyMembers = (json['familyMembers'] as List)
|
||||||
.map((memberJson) => FamilyMember.fromJson(memberJson))
|
.map((memberJson) => FamilyMember.fromJson(memberJson))
|
||||||
@ -53,15 +51,8 @@ class PatientModel {
|
|||||||
gender = other.gender;
|
gender = other.gender;
|
||||||
dateOfBirth = other.dateOfBirth;
|
dateOfBirth = other.dateOfBirth;
|
||||||
profileImagePath = other.profileImagePath;
|
profileImagePath = other.profileImagePath;
|
||||||
address.houseNo = other.address.houseNo;
|
profileImageUrl = other.profileImageUrl;
|
||||||
address.line = other.address.line;
|
address = other.address;
|
||||||
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;
|
|
||||||
familyMembers = other.familyMembers;
|
familyMembers = other.familyMembers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
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 {
|
class BookingService {
|
||||||
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter_dotenv/flutter_dotenv.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';
|
import '../models/consultation_center.dart';
|
||||||
|
|
||||||
class ConsultationCenterService {
|
class ConsultationCenterService {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter_dotenv/flutter_dotenv.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 {
|
class DataService {
|
||||||
static final String profileCollectionName =
|
static final String profileCollectionName =
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
import 'package:telemednet/controllers/doctor_controller.dart';
|
import 'package:medora/controllers/doctor_controller.dart';
|
||||||
import 'package:telemednet/data/models/doctor.dart';
|
import 'package:medora/data/models/doctor.dart';
|
||||||
|
|
||||||
class DoctorProfileService {
|
class DoctorProfileService {
|
||||||
static final String doctorProfileCollectionName =
|
static final String doctorProfileCollectionName =
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:telemednet/data/models/telemed_user.dart';
|
import 'package:medora/data/models/telemed_user.dart';
|
||||||
import 'package:telemednet/data/services/data_service.dart';
|
import 'package:medora/data/services/data_service.dart';
|
||||||
import 'package:telemednet/data/services/doctor_profile_service.dart';
|
import 'package:medora/data/services/doctor_profile_service.dart';
|
||||||
import 'package:telemednet/data/services/patient_registration_service.dart';
|
import 'package:medora/data/services/patient_registration_service.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
|
|
||||||
class NavigationService {
|
class NavigationService {
|
||||||
static Future<void> handleUserNavigation(BuildContext context) async {
|
static Future<void> handleUserNavigation(BuildContext context) async {
|
||||||
|
|||||||
@ -1,13 +1,63 @@
|
|||||||
|
import 'dart:io';
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
|
import 'package:firebase_storage/firebase_storage.dart';
|
||||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
import 'package:telemednet/controllers/patient_controller.dart';
|
import 'package:medora/controllers/patient_controller.dart';
|
||||||
import 'package:telemednet/data/models/patient.dart';
|
import 'package:medora/data/models/patient.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
class PatientProfileService {
|
class PatientProfileService {
|
||||||
static final String patientProfileCollectionName =
|
static final String patientProfileCollectionName =
|
||||||
dotenv.env['PATIENT_PROFILE_COLLECTION_NAME']!;
|
dotenv.env['PATIENT_PROFILE_COLLECTION_NAME']!;
|
||||||
static final FirebaseFirestore db = FirebaseFirestore.instance;
|
static final FirebaseFirestore db = FirebaseFirestore.instance;
|
||||||
|
static final FirebaseStorage storage = FirebaseStorage.instanceFor(
|
||||||
|
bucket: dotenv.env['FIREBASE_STORAGE_BUCKET']!);
|
||||||
|
|
||||||
|
static Future<String?> 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<bool> 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<bool> savePatientProfile(PatientController controller) async {
|
static Future<bool> savePatientProfile(PatientController controller) async {
|
||||||
try {
|
try {
|
||||||
@ -19,11 +69,21 @@ class PatientProfileService {
|
|||||||
|
|
||||||
final String uid = user.uid;
|
final String uid = user.uid;
|
||||||
final PatientModel patientData = controller.model;
|
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<String, dynamic> patientJson = patientData.toJson();
|
final Map<String, dynamic> patientJson = patientData.toJson();
|
||||||
patientJson['createdAt'] = FieldValue.serverTimestamp();
|
patientJson['createdAt'] = FieldValue.serverTimestamp();
|
||||||
patientJson['updatedAt'] = FieldValue.serverTimestamp();
|
patientJson['updatedAt'] = FieldValue.serverTimestamp();
|
||||||
patientJson['uid'] = uid;
|
patientJson['uid'] = uid;
|
||||||
|
patientJson['profileImageUrl'] = imageUrl;
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.collection(patientProfileCollectionName)
|
.collection(patientProfileCollectionName)
|
||||||
@ -38,32 +98,7 @@ class PatientProfileService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<PatientModel?> getPatientProfile() async {
|
static Future<bool> updatePatientProfile(PatientModel patient) 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<String, dynamic>;
|
|
||||||
return PatientModel.fromJson(data);
|
|
||||||
} catch (e) {
|
|
||||||
print('Error fetching patient profile: $e');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<bool> updatePatientProfile(PatientController controller) async {
|
|
||||||
try {
|
try {
|
||||||
final User? user = FirebaseAuth.instance.currentUser;
|
final User? user = FirebaseAuth.instance.currentUser;
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
@ -72,10 +107,30 @@ class PatientProfileService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String uid = user.uid;
|
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<String, dynamic>;
|
||||||
|
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<String, dynamic> patientJson = patientData.toJson();
|
final Map<String, dynamic> patientJson = patient.toJson();
|
||||||
patientJson['updatedAt'] = FieldValue.serverTimestamp();
|
patientJson['updatedAt'] = FieldValue.serverTimestamp();
|
||||||
|
if (imageUrl != null) {
|
||||||
|
patientJson['profileImageUrl'] = imageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.collection(patientProfileCollectionName)
|
.collection(patientProfileCollectionName)
|
||||||
@ -99,6 +154,15 @@ class PatientProfileService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String uid = user.uid;
|
final String uid = user.uid;
|
||||||
|
final DocumentSnapshot doc =
|
||||||
|
await db.collection(patientProfileCollectionName).doc(uid).get();
|
||||||
|
if (doc.exists) {
|
||||||
|
final data = doc.data() as Map<String, dynamic>;
|
||||||
|
final String? imageUrl = data['profileImageUrl'];
|
||||||
|
if (imageUrl != null) {
|
||||||
|
await deleteProfileImage(imageUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await db.collection(patientProfileCollectionName).doc(uid).delete();
|
await db.collection(patientProfileCollectionName).doc(uid).delete();
|
||||||
|
|
||||||
@ -109,4 +173,26 @@ class PatientProfileService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<PatientModel?> 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<String, dynamic>;
|
||||||
|
return PatientModel.fromJson(data);
|
||||||
|
} catch (e) {
|
||||||
|
print('Error fetching patient profile: $e');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
|
import 'package:medora/telemednet_app.dart';
|
||||||
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
|
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:telemednet/telemednet_app.dart';
|
|
||||||
import 'firebase_options.dart';
|
import 'firebase_options.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
@ -10,10 +10,7 @@ void main() async {
|
|||||||
await Firebase.initializeApp(
|
await Firebase.initializeApp(
|
||||||
options: DefaultFirebaseOptions.currentPlatform,
|
options: DefaultFirebaseOptions.currentPlatform,
|
||||||
);
|
);
|
||||||
FirebaseUIAuth.configureProviders([
|
FirebaseUIAuth.configureProviders([EmailAuthProvider(), PhoneAuthProvider()]);
|
||||||
EmailAuthProvider(),
|
|
||||||
PhoneAuthProvider()
|
|
||||||
]);
|
|
||||||
await dotenv.load();
|
await dotenv.load();
|
||||||
runApp(const TelemednetApp());
|
runApp(const TelemednetApp());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,4 +40,6 @@ class RouteNames {
|
|||||||
static const String doctorServicesMenuScreen = '/doctor-services-menu';
|
static const String doctorServicesMenuScreen = '/doctor-services-menu';
|
||||||
static const String consultationTimeSlotScreen = '/doctor-timeslot';
|
static const String consultationTimeSlotScreen = '/doctor-timeslot';
|
||||||
static const String consultationDayScreen = '/doctor-consultation-days';
|
static const String consultationDayScreen = '/doctor-consultation-days';
|
||||||
|
static const String loadingScreen = '/loading-screen';
|
||||||
|
static const String splashScreen = '/splash-screen';
|
||||||
}
|
}
|
||||||
@ -1,51 +1,53 @@
|
|||||||
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
|
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:telemednet/controllers/consultation_center_controller.dart';
|
import 'package:medora/controllers/consultation_center_controller.dart';
|
||||||
import 'package:telemednet/data/models/consultation_center.dart';
|
import 'package:medora/data/models/consultation_center.dart';
|
||||||
import 'package:telemednet/data/models/doctor.dart';
|
import 'package:medora/data/models/doctor.dart';
|
||||||
import 'package:telemednet/screens/authentication/launch_screen.dart';
|
import 'package:medora/screens/authentication/launch_screen.dart';
|
||||||
// import 'package:telemednet/data/telemed_user.dart';
|
// import 'package:medora/data/telemed_user.dart';
|
||||||
import 'package:telemednet/controllers/patient_controller.dart';
|
import 'package:medora/controllers/patient_controller.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/business_center_screen.dart';
|
import 'package:medora/screens/common/loading_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/center_fee_and_duration_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/business_center_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/center_fee_and_duration_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/consultation_schedule.dart';
|
import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/consultation_schedule.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_dashboard_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_landing_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_dashboard_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_personal_profile_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_landing_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_services_menu_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_personal_profile_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/doctor_profile_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_services_menu_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/qualifications_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorProfileScreens/doctor_profile_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/appoinmentBooking/consultation_booking_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorProfileScreens/qualifications_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/appoinmentBooking/consultation_time_screen.dart';
|
import 'package:medora/screens/patientScreens/appoinmentBooking/consultation_booking_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/appoinmentBooking/consultations_center_screen.dart';
|
import 'package:medora/screens/patientScreens/appoinmentBooking/consultation_time_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/appoinmentBooking/doctor_details_screen.dart';
|
import 'package:medora/screens/patientScreens/appoinmentBooking/consultations_center_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/appoinmentBooking/doctors_list_screen.dart';
|
import 'package:medora/screens/patientScreens/appoinmentBooking/doctor_details_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/appoinmentBooking/speciality_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:medora/screens/doctorScreens/doctorProfileScreens/achivements_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/address_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:medora/screens/doctorScreens/doctorProfileScreens/experience_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/profile_description_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorProfileScreens/profile_description_screen.dart';
|
||||||
|
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorProfileScreens/specialities_selection_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorProfileScreens/specialities_selection_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/patientDashboard/patient_dashboard_screen.dart';
|
import 'package:medora/screens/patientScreens/patientDashboard/patient_dashboard_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/patientDashboard/patient_home_screen.dart';
|
import 'package:medora/screens/patientScreens/patientDashboard/patient_home_screen.dart';
|
||||||
|
|
||||||
import 'package:telemednet/screens/patientScreens/patientDashboard/patient_profile_screen.dart';
|
import 'package:medora/screens/patientScreens/patientDashboard/patient_profile_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/registrationScreens/patient_adress_screen.dart';
|
import 'package:medora/screens/patientScreens/registrationScreens/patient_adress_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/registrationScreens/patient_family_members_screen.dart';
|
import 'package:medora/screens/patientScreens/registrationScreens/patient_family_members_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/registrationScreens/patient_registration_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 '../controllers/doctor_controller.dart';
|
||||||
import 'screens/patientScreens/patient_landing_screen.dart';
|
import '../screens/patientScreens/patient_landing_screen.dart';
|
||||||
import 'screens/patientScreens/registrationScreens/family_members_edit_screen.dart';
|
import '../screens/patientScreens/registrationScreens/family_members_edit_screen.dart';
|
||||||
|
|
||||||
final Map<String, Widget Function(BuildContext)> routes = {
|
final Map<String, Widget Function(BuildContext)> routes = {
|
||||||
RouteNames.launch: (context) => const LaunchScreen(),
|
RouteNames.launch: (context) => const LaunchScreen(),
|
||||||
@ -208,4 +210,6 @@ final Map<String, Widget Function(BuildContext)> routes = {
|
|||||||
controller: controller ?? ConsultationCenterController(),
|
controller: controller ?? ConsultationCenterController(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
RouteNames.loadingScreen: (context) => const LoadingScreen(),
|
||||||
|
RouteNames.splashScreen: (context) => const SplashScreen(),
|
||||||
};
|
};
|
||||||
@ -1,10 +1,9 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:telemednet/data/services/navigation_service.dart';
|
import 'package:medora/data/services/navigation_service.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
import 'package:telemednet/screens/authentication/sign_up_screen.dart';
|
import 'package:medora/screens/authentication/sign_up_screen.dart';
|
||||||
import 'package:telemednet/widgets/primary_button.dart';
|
import 'package:medora/widgets/primary_button.dart';
|
||||||
|
|
||||||
class LaunchScreen extends StatefulWidget {
|
class LaunchScreen extends StatefulWidget {
|
||||||
const LaunchScreen({super.key});
|
const LaunchScreen({super.key});
|
||||||
@ -19,6 +18,17 @@ class _LaunchScreenState extends State<LaunchScreen> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthenticationState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthenticationState() {
|
||||||
|
FirebaseAuth.instance.authStateChanges().listen((user) {
|
||||||
|
if (user != null) {
|
||||||
|
if (mounted) {
|
||||||
|
_fetchProfileAndNavigate(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -41,40 +51,7 @@ class _LaunchScreenState extends State<LaunchScreen> {
|
|||||||
),
|
),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(24.0),
|
padding: const EdgeInsets.all(24.0),
|
||||||
child: StreamBuilder(
|
child: _buildUserTypeSelection(context),
|
||||||
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),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -83,26 +60,26 @@ class _LaunchScreenState extends State<LaunchScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
Widget _buildUserTypeSelection(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
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(
|
_buildSelectionCard(
|
||||||
title: 'Doctor',
|
title: 'Doctor',
|
||||||
description: 'Can organise and approve appointments',
|
description: 'Can organise and approve appointments',
|
||||||
@ -122,15 +99,7 @@ class _LaunchScreenState extends State<LaunchScreen> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: PrimaryButton(
|
child: PrimaryButton(
|
||||||
onPressed: selectedUserType != null
|
onPressed: selectedUserType != null ? _navigateToSignUp : null,
|
||||||
? () => Navigator.of(context).push(
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => SignUpScreen(
|
|
||||||
selectedUserType: selectedUserType!,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
text: 'Next',
|
text: 'Next',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -213,9 +182,17 @@ class _LaunchScreenState extends State<LaunchScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _navigateToSignUp() {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => SignUpScreen(
|
||||||
|
selectedUserType: selectedUserType!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _fetchProfileAndNavigate(BuildContext context) async {
|
Future<void> _fetchProfileAndNavigate(BuildContext context) async {
|
||||||
if (mounted) {
|
await NavigationService.handleUserNavigation(context);
|
||||||
await NavigationService.handleUserNavigation(context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl_phone_field/intl_phone_field.dart';
|
import 'package:intl_phone_field/intl_phone_field.dart';
|
||||||
import 'package:telemednet/data/services/data_service.dart';
|
import 'package:medora/data/services/data_service.dart';
|
||||||
import 'package:telemednet/data/services/navigation_service.dart';
|
import 'package:medora/data/services/navigation_service.dart';
|
||||||
import 'package:telemednet/widgets/primary_button.dart';
|
import 'package:medora/widgets/primary_button.dart';
|
||||||
|
|
||||||
class SignUpScreen extends StatefulWidget {
|
class SignUpScreen extends StatefulWidget {
|
||||||
final String selectedUserType;
|
final String selectedUserType;
|
||||||
|
|||||||
50
lib/screens/common/loading_screen.dart
Normal file
@ -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<Color>(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<Color>(Colors.blue.shade700),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
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 {
|
class BusinessCenterScreen extends StatefulWidget {
|
||||||
final ConsultationCenterController controller;
|
final ConsultationCenterController controller;
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:telemednet/controllers/consultation_center_controller.dart';
|
import 'package:medora/controllers/consultation_center_controller.dart';
|
||||||
import 'package:telemednet/data/services/consultation_center_service.dart';
|
import 'package:medora/data/services/consultation_center_service.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/consultation_day_screen.dart';
|
||||||
import '../../../route_names.dart';
|
import '../../../route/route_names.dart';
|
||||||
|
|
||||||
class CenterFeeAndDurationScreen extends StatefulWidget {
|
class CenterFeeAndDurationScreen extends StatefulWidget {
|
||||||
final ConsultationCenterController controller;
|
final ConsultationCenterController controller;
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:telemednet/controllers/consultation_center_controller.dart';
|
import 'package:medora/controllers/consultation_center_controller.dart';
|
||||||
import 'package:telemednet/data/models/consultation_center.dart';
|
import 'package:medora/data/models/consultation_center.dart';
|
||||||
import 'package:telemednet/data/services/consultation_center_service.dart';
|
import 'package:medora/data/services/consultation_center_service.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorConsultationSchedule/consultation_time_slot_screen.dart';
|
||||||
|
|
||||||
class ConsultationDayScreen extends StatefulWidget {
|
class ConsultationDayScreen extends StatefulWidget {
|
||||||
final ConsultationCenterController controller;
|
final ConsultationCenterController controller;
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:telemednet/data/models/consultation_center.dart';
|
import 'package:medora/data/models/consultation_center.dart';
|
||||||
import 'package:telemednet/data/services/consultation_center_service.dart';
|
import 'package:medora/data/services/consultation_center_service.dart';
|
||||||
|
|
||||||
import '../../../common/custom_style.dart';
|
import '../../../common/custom_style.dart';
|
||||||
import '../../../route_names.dart';
|
import '../../../route/route_names.dart';
|
||||||
|
|
||||||
class ScheduleConsultationScreen extends StatefulWidget {
|
class ScheduleConsultationScreen extends StatefulWidget {
|
||||||
const ScheduleConsultationScreen({super.key});
|
const ScheduleConsultationScreen({super.key});
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:telemednet/controllers/consultation_center_controller.dart';
|
import 'package:medora/controllers/consultation_center_controller.dart';
|
||||||
import 'package:telemednet/data/models/consultation_center.dart';
|
import 'package:medora/data/models/consultation_center.dart';
|
||||||
|
|
||||||
class ConsultationTimeSlotScreen extends StatefulWidget {
|
class ConsultationTimeSlotScreen extends StatefulWidget {
|
||||||
final ConsultationCenterController controller;
|
final ConsultationCenterController controller;
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
import 'package:google_fonts/google_fonts.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 {
|
class DoctorDashboardHomeScreen extends StatefulWidget {
|
||||||
const DoctorDashboardHomeScreen({super.key});
|
const DoctorDashboardHomeScreen({super.key});
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:animations/animations.dart';
|
import 'package:animations/animations.dart';
|
||||||
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
|
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart';
|
import 'package:medora/screens/doctorScreens/doctorDashboard/doctor_dashboard_home_screen.dart';
|
||||||
import 'package:telemednet/screens/doctorScreens/doctorDashboard/doctor_personal_profile_screen.dart';
|
import 'package:medora/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_services_menu_screen.dart';
|
||||||
|
|
||||||
class DoctorDashboardScreen extends StatefulWidget {
|
class DoctorDashboardScreen extends StatefulWidget {
|
||||||
const DoctorDashboardScreen({super.key});
|
const DoctorDashboardScreen({super.key});
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
|
|
||||||
class DoctorLandingScreen extends StatelessWidget {
|
class DoctorLandingScreen extends StatelessWidget {
|
||||||
const DoctorLandingScreen({super.key});
|
const DoctorLandingScreen({super.key});
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
|
|
||||||
class DoctorPersonalProfileScreen extends StatefulWidget {
|
class DoctorPersonalProfileScreen extends StatefulWidget {
|
||||||
const DoctorPersonalProfileScreen({super.key});
|
const DoctorPersonalProfileScreen({super.key});
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
|
|
||||||
class DoctorServicesMenuScreen extends StatefulWidget {
|
class DoctorServicesMenuScreen extends StatefulWidget {
|
||||||
const DoctorServicesMenuScreen({super.key});
|
const DoctorServicesMenuScreen({super.key});
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
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 {
|
class AchievementsScreen extends StatefulWidget {
|
||||||
final DoctorController controller;
|
final DoctorController controller;
|
||||||
@ -57,6 +57,10 @@ class _AchievementsScreenState extends State<AchievementsScreen> {
|
|||||||
_showError('Achievement must be at least 3 characters long');
|
_showError('Achievement must be at least 3 characters long');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!RegExp(r'^[a-zA-Z0-9\s.,]+$').hasMatch(value)) {
|
||||||
|
_showError('Please enter valid achievement text');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
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 {
|
class DoctorAddressScreen extends StatefulWidget {
|
||||||
final DoctorController? controller;
|
final DoctorController? controller;
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:image_picker/image_picker.dart';
|
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 '../../../data/services/doctor_profile_service.dart';
|
||||||
import '../../../route_names.dart';
|
import '../../../route/route_names.dart';
|
||||||
|
|
||||||
class DigitalSignatureScreen extends StatefulWidget {
|
class DigitalSignatureScreen extends StatefulWidget {
|
||||||
final DoctorController controller;
|
final DoctorController controller;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:telemednet/controllers/doctor_controller.dart';
|
import 'package:medora/controllers/doctor_controller.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
|
|
||||||
class ProfileUploadPage extends StatefulWidget {
|
class ProfileUploadPage extends StatefulWidget {
|
||||||
const ProfileUploadPage({super.key});
|
const ProfileUploadPage({super.key});
|
||||||
@ -15,7 +15,7 @@ class _ProfileUploadPageState extends State<ProfileUploadPage> {
|
|||||||
final DoctorController _controller = DoctorController();
|
final DoctorController _controller = DoctorController();
|
||||||
final TextEditingController _titleController = TextEditingController();
|
final TextEditingController _titleController = TextEditingController();
|
||||||
final TextEditingController _surnameController = TextEditingController();
|
final TextEditingController _surnameController = TextEditingController();
|
||||||
final TextEditingController _lastnameController = TextEditingController();
|
final TextEditingController _firstController = TextEditingController();
|
||||||
final TextEditingController _middlenameController = TextEditingController();
|
final TextEditingController _middlenameController = TextEditingController();
|
||||||
File? _image;
|
File? _image;
|
||||||
final ImagePicker _picker = ImagePicker();
|
final ImagePicker _picker = ImagePicker();
|
||||||
@ -31,7 +31,7 @@ class _ProfileUploadPageState extends State<ProfileUploadPage> {
|
|||||||
|
|
||||||
_titleController.text = _controller.model.title ?? '';
|
_titleController.text = _controller.model.title ?? '';
|
||||||
_surnameController.text = _controller.model.surName ?? '';
|
_surnameController.text = _controller.model.surName ?? '';
|
||||||
_lastnameController.text = _controller.model.lastName ?? '';
|
_firstController.text = _controller.model.firstName ?? '';
|
||||||
_middlenameController.text = _controller.model.middleName ?? '';
|
_middlenameController.text = _controller.model.middleName ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ class _ProfileUploadPageState extends State<ProfileUploadPage> {
|
|||||||
void dispose() {
|
void dispose() {
|
||||||
_titleController.dispose();
|
_titleController.dispose();
|
||||||
_surnameController.dispose();
|
_surnameController.dispose();
|
||||||
_lastnameController.dispose();
|
_firstController.dispose();
|
||||||
_middlenameController.dispose();
|
_middlenameController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ class _ProfileUploadPageState extends State<ProfileUploadPage> {
|
|||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState!.validate()) {
|
||||||
_controller.updateTitle(_titleController.text);
|
_controller.updateTitle(_titleController.text);
|
||||||
_controller.updateSurName(_surnameController.text);
|
_controller.updateSurName(_surnameController.text);
|
||||||
_controller.updateLastName(_lastnameController.text);
|
_controller.updateLastName(_firstController.text);
|
||||||
_controller.updateMiddleName(_middlenameController.text);
|
_controller.updateMiddleName(_middlenameController.text);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -242,6 +242,7 @@ class _ProfileUploadPageState extends State<ProfileUploadPage> {
|
|||||||
children: [
|
children: [
|
||||||
_buildUniformField(
|
_buildUniformField(
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
|
|
||||||
icon: Icons.person,
|
icon: Icons.person,
|
||||||
child:
|
child:
|
||||||
Container(), // The child parameter is not used in this implementation
|
Container(), // The child parameter is not used in this implementation
|
||||||
@ -355,7 +356,7 @@ class _ProfileUploadPageState extends State<ProfileUploadPage> {
|
|||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: _lastnameController,
|
controller: _firstController,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_controller.updateLastName(value);
|
_controller.updateLastName(value);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.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 {
|
class ExperienceScreen extends StatefulWidget {
|
||||||
final DoctorController controller;
|
final DoctorController controller;
|
||||||
@ -180,7 +180,7 @@ class _ExperienceScreenState extends State<ExperienceScreen> {
|
|||||||
if (value.length < 5) {
|
if (value.length < 5) {
|
||||||
return 'License number must be at least 5 digits';
|
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 'Please enter numbers only';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
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 ProfileDescriptionScreen extends StatefulWidget {
|
class ProfileDescriptionScreen extends StatefulWidget {
|
||||||
final DoctorController? controller;
|
final DoctorController? controller;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
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 QualificationsScreen extends StatefulWidget {
|
class QualificationsScreen extends StatefulWidget {
|
||||||
final DoctorController? controller;
|
final DoctorController? controller;
|
||||||
@ -82,12 +82,26 @@ class _QualificationsScreenState extends State<QualificationsScreen> {
|
|||||||
|
|
||||||
if (_formKey.currentState!.validate() &&
|
if (_formKey.currentState!.validate() &&
|
||||||
_validateQualification(qualification)) {
|
_validateQualification(qualification)) {
|
||||||
setState(() {
|
// Check if qualification already exists (case-insensitive)
|
||||||
qualifications.add(qualification);
|
bool isDuplicate = qualifications
|
||||||
_isEditing = true;
|
.any((q) => q.toLowerCase() == qualification.toLowerCase());
|
||||||
_qualificationsController.clear();
|
|
||||||
});
|
if (!isDuplicate) {
|
||||||
_controller.addQualification(qualification);
|
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<QualificationsScreen> {
|
|||||||
qualifications.remove(qualification);
|
qualifications.remove(qualification);
|
||||||
_controller.removeQualification(qualification);
|
_controller.removeQualification(qualification);
|
||||||
} else {
|
} else {
|
||||||
qualifications.add(qualification);
|
// Check if qualification already exists (case-insensitive)
|
||||||
_controller.addQualification(qualification);
|
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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
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 SpecialitiesScreen extends StatefulWidget {
|
class SpecialitiesScreen extends StatefulWidget {
|
||||||
final DoctorController controller;
|
final DoctorController controller;
|
||||||
|
|||||||
@ -2,13 +2,15 @@ import 'package:firebase_auth/firebase_auth.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:telemednet/data/models/consultation_center.dart';
|
import 'package:medora/data/models/consultation_center.dart';
|
||||||
import 'package:telemednet/data/models/doctor.dart';
|
import 'package:medora/data/models/doctor.dart';
|
||||||
import 'package:telemednet/data/services/consultation_booking_service.dart';
|
import 'package:medora/data/models/patient.dart';
|
||||||
import 'package:telemednet/data/services/patient_registration_service.dart';
|
import 'package:medora/data/services/consultation_booking_service.dart';
|
||||||
import 'package:telemednet/widgets/alert_screen.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 Doctor doctor;
|
||||||
final ConsultationCenter selectedConsultation;
|
final ConsultationCenter selectedConsultation;
|
||||||
final DateTime selectedDate;
|
final DateTime selectedDate;
|
||||||
@ -21,13 +23,58 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
required this.selectedDate,
|
required this.selectedDate,
|
||||||
required this.selectedTime,
|
required this.selectedTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ConsultationBookingScreen> createState() =>
|
||||||
|
_ConsultationBookingScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ConsultationBookingScreenState extends State<ConsultationBookingScreen> {
|
||||||
|
PatientModel? selectedPatient;
|
||||||
|
List<PatientModel> 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<void> _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 {
|
String get formattedAddress {
|
||||||
final parts = [
|
final parts = [
|
||||||
selectedConsultation.floorBuilding,
|
widget.selectedConsultation.floorBuilding,
|
||||||
selectedConsultation.street,
|
widget.selectedConsultation.street,
|
||||||
selectedConsultation.city,
|
widget.selectedConsultation.city,
|
||||||
selectedConsultation.state,
|
widget.selectedConsultation.state,
|
||||||
selectedConsultation.postalCode
|
widget.selectedConsultation.postalCode
|
||||||
].where((part) => part != null && part.isNotEmpty).toList();
|
].where((part) => part != null && part.isNotEmpty).toList();
|
||||||
return parts.join(', ');
|
return parts.join(', ');
|
||||||
}
|
}
|
||||||
@ -51,6 +98,8 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
_buildPaymentDetails(),
|
_buildPaymentDetails(),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
|
_buildInClinicAppointmentText(),
|
||||||
|
const SizedBox(height: 24),
|
||||||
_buildConfirmButton(context),
|
_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) {
|
PreferredSizeWidget _buildAppBar(BuildContext context) {
|
||||||
return AppBar(
|
return AppBar(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
@ -100,7 +206,7 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
const Icon(Icons.calendar_today, color: Colors.white),
|
const Icon(Icons.calendar_today, color: Colors.white),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Text(
|
Text(
|
||||||
DateFormat('EEEE, MMMM d').format(selectedDate),
|
DateFormat('EEEE, MMMM d').format(widget.selectedDate),
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
@ -115,7 +221,7 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
const Icon(Icons.access_time, color: Colors.white),
|
const Icon(Icons.access_time, color: Colors.white),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Text(
|
Text(
|
||||||
selectedTime,
|
widget.selectedTime,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
@ -147,8 +253,8 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
child: Image.asset(
|
child: Image.network(
|
||||||
doctor.profileImage!,
|
widget.doctor.profileImage!,
|
||||||
width: 80,
|
width: 80,
|
||||||
height: 80,
|
height: 80,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
@ -168,21 +274,21 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
doctor.lastName!,
|
widget.doctor.firstName ?? '',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
doctor.speciality!,
|
widget.doctor.speciality!,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey[600],
|
color: Colors.grey[600],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'${doctor.yearsOfExperience} years experience',
|
'${widget.doctor.yearsOfExperience} years experience',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey[600],
|
color: Colors.grey[600],
|
||||||
@ -230,7 +336,7 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
'Average consultation time: ${selectedConsultation.averageDurationMinutes} minutes',
|
'Average consultation time: ${widget.selectedConsultation.averageDurationMinutes} minutes',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey[600],
|
color: Colors.grey[600],
|
||||||
@ -277,7 +383,7 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'₹${selectedConsultation.consultationFee ?? "500"}',
|
'₹${widget.selectedConsultation.consultationFee ?? "500"}',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -318,14 +424,24 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _showConfirmationDialog(BuildContext context) async {
|
void _showConfirmationDialog(BuildContext context) async {
|
||||||
final bookingService = BookingService();
|
if (selectedPatient == null) {
|
||||||
final currentUser = FirebaseAuth.instance.currentUser;
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
final patientProfile = await PatientProfileService.getPatientProfile();
|
const SnackBar(
|
||||||
|
content: Text('Please select a patient for the appointment'),
|
||||||
if (patientProfile == null) {
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
return;
|
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 {
|
try {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
showDialog(
|
showDialog(
|
||||||
@ -338,15 +454,15 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final bookingId = await bookingService.createBooking(
|
final bookingId = await bookingService.createBooking(
|
||||||
doctorName: doctor.lastName!,
|
doctorName: widget.doctor.firstName ?? 'Doctor',
|
||||||
patientId: currentUser!.uid,
|
patientId: currentUser!.uid,
|
||||||
patientName: patientProfile.name ?? 'Patient',
|
patientName: patientName ?? 'Patient',
|
||||||
location: formattedAddress,
|
location: formattedAddress,
|
||||||
appointmentDate: selectedDate,
|
appointmentDate: widget.selectedDate,
|
||||||
appointmentTime: selectedTime,
|
appointmentTime: widget.selectedTime,
|
||||||
consultationFee:
|
consultationFee:
|
||||||
int.parse(selectedConsultation.consultationFee ?? "500"),
|
int.parse(widget.selectedConsultation.consultationFee ?? "500"),
|
||||||
specialization: doctor.speciality!,
|
specialization: widget.doctor.speciality!,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
@ -358,11 +474,12 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
arguments: AlertArguments(
|
arguments: AlertArguments(
|
||||||
title: 'Booking Confirmed',
|
title: 'Booking Confirmed',
|
||||||
message:
|
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',
|
actionTitle: 'View Appointments',
|
||||||
type: AlertType.success,
|
type: AlertType.success,
|
||||||
onActionPressed: () {
|
onActionPressed: () {
|
||||||
Navigator.of(context).popUntil((route) => route.isFirst);
|
Navigator.pushReplacementNamed(
|
||||||
|
context, RouteNames.patientDashboardScreen);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -391,4 +508,333 @@ class ConsultationBookingScreen extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _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<String>(
|
||||||
|
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<void> _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,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:telemednet/data/models/consultation_center.dart';
|
import 'package:medora/data/models/consultation_center.dart';
|
||||||
import 'package:telemednet/data/models/doctor.dart';
|
import 'package:medora/data/models/doctor.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
|
|
||||||
class ConsultationTimeScreen extends StatefulWidget {
|
class ConsultationTimeScreen extends StatefulWidget {
|
||||||
final Doctor doctor;
|
final Doctor doctor;
|
||||||
@ -134,7 +134,7 @@ class _ConsultationTimeScreenState extends State<ConsultationTimeScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
widget.doctor.lastName!,
|
widget.doctor.firstName ?? '',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -152,7 +152,7 @@ class _ConsultationTimeScreenState extends State<ConsultationTimeScreen> {
|
|||||||
),
|
),
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
child: Image.asset(
|
child: Image.network(
|
||||||
widget.doctor.profileImage!,
|
widget.doctor.profileImage!,
|
||||||
width: 60,
|
width: 60,
|
||||||
height: 60,
|
height: 60,
|
||||||
@ -474,7 +474,7 @@ class _ConsultationTimeScreenState extends State<ConsultationTimeScreen> {
|
|||||||
children: [
|
children: [
|
||||||
_buildConfirmationDetail(
|
_buildConfirmationDetail(
|
||||||
'Doctor',
|
'Doctor',
|
||||||
widget.doctor.lastName!,
|
widget.doctor.firstName!,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
_buildConfirmationDetail(
|
_buildConfirmationDetail(
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:telemednet/data/models/doctor.dart';
|
import 'package:medora/data/models/doctor.dart';
|
||||||
import 'package:telemednet/data/models/consultation_center.dart';
|
import 'package:medora/data/models/consultation_center.dart';
|
||||||
import 'package:telemednet/data/services/consultation_center_service.dart';
|
import 'package:medora/data/services/consultation_center_service.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
|
|
||||||
class ConsultationsCenterScreen extends StatefulWidget {
|
class ConsultationsCenterScreen extends StatefulWidget {
|
||||||
final Doctor doctor;
|
final Doctor doctor;
|
||||||
@ -143,7 +143,7 @@ class _ConsultationsCenterScreenState extends State<ConsultationsCenterScreen> {
|
|||||||
children: [
|
children: [
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
child: Image.asset(
|
child: Image.network(
|
||||||
widget.doctor.profileImage!,
|
widget.doctor.profileImage!,
|
||||||
width: 80,
|
width: 80,
|
||||||
height: 80,
|
height: 80,
|
||||||
@ -164,7 +164,7 @@ class _ConsultationsCenterScreenState extends State<ConsultationsCenterScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
widget.doctor.lastName!,
|
widget.doctor.firstName ?? "",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:telemednet/data/models/doctor.dart';
|
import 'package:medora/data/models/doctor.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
|
|
||||||
class DoctorDetailsScreen extends StatelessWidget {
|
class DoctorDetailsScreen extends StatelessWidget {
|
||||||
final Doctor doctor;
|
final Doctor doctor;
|
||||||
@ -115,7 +115,7 @@ class DoctorDetailsScreen extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
child: Image.asset(
|
child: Image.network(
|
||||||
doctor.profileImage!,
|
doctor.profileImage!,
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
@ -137,7 +137,7 @@ class DoctorDetailsScreen extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
doctor.lastName!,
|
doctor.firstName ?? '',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cloud_firestore/cloud_firestore.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:google_fonts/google_fonts.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
import 'package:medora/route/route_names.dart';
|
||||||
|
|
||||||
class DoctorsListScreen extends StatefulWidget {
|
class DoctorsListScreen extends StatefulWidget {
|
||||||
final String specialty;
|
final String specialty;
|
||||||
@ -174,7 +174,7 @@ class _DoctorsListScreenState extends State<DoctorsListScreen> {
|
|||||||
.where((doctor) {
|
.where((doctor) {
|
||||||
if (_searchController.text.isEmpty) return true;
|
if (_searchController.text.isEmpty) return true;
|
||||||
final searchQuery = _searchController.text.toLowerCase();
|
final searchQuery = _searchController.text.toLowerCase();
|
||||||
return doctor.surName!.toLowerCase().contains(searchQuery) ||
|
return doctor.firstName!.toLowerCase().contains(searchQuery) ||
|
||||||
doctor.city!.toLowerCase().contains(searchQuery);
|
doctor.city!.toLowerCase().contains(searchQuery);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ class _DoctorsListScreenState extends State<DoctorsListScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
doctor.surName!,
|
doctor.firstName ?? '',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:animate_do/animate_do.dart';
|
import 'package:animate_do/animate_do.dart';
|
||||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.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 {
|
class Specialty {
|
||||||
final String name;
|
final String name;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:animations/animations.dart';
|
import 'package:animations/animations.dart';
|
||||||
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
|
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/patientDashboard/patient_home_screen.dart';
|
import 'package:medora/screens/patientScreens/patientDashboard/patient_home_screen.dart';
|
||||||
import 'package:telemednet/screens/patientScreens/patientDashboard/patient_profile_screen.dart';
|
import 'package:medora/screens/patientScreens/patientDashboard/patient_profile_screen.dart';
|
||||||
|
|
||||||
class PatientDashboardScreen extends StatefulWidget {
|
class PatientDashboardScreen extends StatefulWidget {
|
||||||
const PatientDashboardScreen({super.key});
|
const PatientDashboardScreen({super.key});
|
||||||
@ -46,8 +46,8 @@ class _PatientDashboardScreenState extends State<PatientDashboardScreen> {
|
|||||||
index: _selectedIndex,
|
index: _selectedIndex,
|
||||||
items: const [
|
items: const [
|
||||||
Icon(Icons.home, size: 30, color: Colors.white),
|
Icon(Icons.home, size: 30, color: Colors.white),
|
||||||
// Icon(Icons.chat_bubble, size: 30, color: Colors.white),
|
Icon(Icons.chat_bubble, size: 30, color: Colors.white),
|
||||||
Icon(Icons.list, size: 30, color: Colors.white),
|
Icon(Icons.assignment, size: 30, color: Colors.white),
|
||||||
Icon(Icons.person, size: 30, color: Colors.white),
|
Icon(Icons.person, size: 30, color: Colors.white),
|
||||||
],
|
],
|
||||||
onTap: (index) {
|
onTap: (index) {
|
||||||
|
|||||||
@ -1,8 +1,13 @@
|
|||||||
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:google_fonts/google_fonts.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 {
|
class PatientHomeScreen extends StatefulWidget {
|
||||||
const PatientHomeScreen({super.key});
|
const PatientHomeScreen({super.key});
|
||||||
@ -14,6 +19,8 @@ class PatientHomeScreen extends StatefulWidget {
|
|||||||
class _PatientHomeScreenState extends State<PatientHomeScreen>
|
class _PatientHomeScreenState extends State<PatientHomeScreen>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
late AnimationController _animationController;
|
late AnimationController _animationController;
|
||||||
|
final BookingService _bookingService = BookingService();
|
||||||
|
late Stream<List<Booking>> _bookingsStream;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -23,6 +30,14 @@ class _PatientHomeScreenState extends State<PatientHomeScreen>
|
|||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
);
|
);
|
||||||
_animationController.forward();
|
_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
|
@override
|
||||||
@ -50,7 +65,6 @@ class _PatientHomeScreenState extends State<PatientHomeScreen>
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// _buildBottomNavBar(),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -61,14 +75,7 @@ class _PatientHomeScreenState extends State<PatientHomeScreen>
|
|||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
color: Colors.blue,
|
||||||
colors: [
|
|
||||||
Colors.blue[400]!,
|
|
||||||
Colors.blue[300]!,
|
|
||||||
],
|
|
||||||
begin: Alignment.topLeft,
|
|
||||||
end: Alignment.bottomRight,
|
|
||||||
),
|
|
||||||
borderRadius: const BorderRadius.only(
|
borderRadius: const BorderRadius.only(
|
||||||
bottomLeft: Radius.circular(30.0),
|
bottomLeft: Radius.circular(30.0),
|
||||||
bottomRight: Radius.circular(30.0),
|
bottomRight: Radius.circular(30.0),
|
||||||
@ -179,47 +186,161 @@ class _PatientHomeScreenState extends State<PatientHomeScreen>
|
|||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Padding(
|
||||||
'Upcoming Consultations',
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
style: GoogleFonts.poppins(
|
child: Row(
|
||||||
fontSize: 20,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
fontWeight: FontWeight.bold,
|
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(
|
SizedBox(
|
||||||
height: 160,
|
height: 201,
|
||||||
child: ListView(
|
child: StreamBuilder<List<Booking>>(
|
||||||
scrollDirection: Axis.horizontal,
|
stream: _bookingsStream,
|
||||||
children: [
|
builder: (context, snapshot) {
|
||||||
_consultationCard(
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
'Dr. Smith', '23/09/2024\n5:00 PM - 6:00 PM', 'Cardiologist'),
|
return Center(
|
||||||
const SizedBox(width: 16),
|
child: Column(
|
||||||
_consultationCard('Dr. Johnson', '24/09/2024\n3:30 PM - 4:30 PM',
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
'Pediatrician'),
|
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(
|
return Container(
|
||||||
width: 280,
|
width: 300,
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
colors: [Colors.white, Colors.grey[50]!],
|
colors: [Colors.white, Colors.grey[50]!],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(24),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: Colors.grey.withOpacity(0.2),
|
color: Colors.grey.withOpacity(0.1),
|
||||||
blurRadius: 10,
|
blurRadius: 20,
|
||||||
offset: const Offset(0, 5),
|
offset: const Offset(0, 8),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -229,19 +350,30 @@ class _PatientHomeScreenState extends State<PatientHomeScreen>
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
width: 60,
|
width: 64,
|
||||||
height: 60,
|
height: 64,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blue[100],
|
gradient: LinearGradient(
|
||||||
|
colors: [Colors.blue[400]!, Colors.blue[600]!],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
),
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.blue[300]!.withOpacity(0.3),
|
||||||
|
blurRadius: 12,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.person,
|
Icons.person,
|
||||||
size: 40,
|
size: 36,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 16),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -249,14 +381,50 @@ class _PatientHomeScreenState extends State<PatientHomeScreen>
|
|||||||
Text(
|
Text(
|
||||||
name,
|
name,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.grey[800],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
speciality,
|
speciality,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
color: Colors.grey[600],
|
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<PatientHomeScreen>
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 16),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blue[50],
|
color: Colors.blue[50],
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(16),
|
||||||
),
|
border: Border.all(
|
||||||
child: Text(
|
color: Colors.blue[100]!,
|
||||||
schedule,
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
color: Colors.blue[700],
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
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() {
|
Widget _buildFindDoctorSection() {
|
||||||
final specialistData = [
|
final specialistData = [
|
||||||
{
|
{
|
||||||
@ -396,7 +617,13 @@ class _PatientHomeScreenState extends State<PatientHomeScreen>
|
|||||||
}) {
|
}) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// Replace with your desired navigation action
|
Navigator.pushNamed(
|
||||||
|
context,
|
||||||
|
RouteNames.doctorListScreen,
|
||||||
|
arguments: {
|
||||||
|
'specialty': label,
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 140,
|
width: 140,
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter/material.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 {
|
class PatientProfileScreen extends StatefulWidget {
|
||||||
const PatientProfileScreen({super.key});
|
const PatientProfileScreen({super.key});
|
||||||
@ -11,7 +13,23 @@ class PatientProfileScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _PatientProfileScreenState extends State<PatientProfileScreen> {
|
class _PatientProfileScreenState extends State<PatientProfileScreen> {
|
||||||
final FirebaseAuth _auth = FirebaseAuth.instance;
|
final FirebaseAuth _auth = FirebaseAuth.instance;
|
||||||
// final GlobalKey<CurvedNavigationBarState> _bottomNavigationKey = GlobalKey();
|
PatientModel? _patientProfile;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_fetchPatientProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchPatientProfile() async {
|
||||||
|
final patientProfile = await PatientProfileService.getPatientProfile();
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_patientProfile = patientProfile;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -20,8 +38,6 @@ class _PatientProfileScreenState extends State<PatientProfileScreen> {
|
|||||||
children: [
|
children: [
|
||||||
_buildProfileHeader(),
|
_buildProfileHeader(),
|
||||||
_buildProfileOptions(),
|
_buildProfileOptions(),
|
||||||
const Spacer(),
|
|
||||||
// _buildBottomNavBar(),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -50,41 +66,46 @@ class _PatientProfileScreenState extends State<PatientProfileScreen> {
|
|||||||
Container(
|
Container(
|
||||||
width: 60,
|
width: 60,
|
||||||
height: 60,
|
height: 60,
|
||||||
decoration: const BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
|
image: _patientProfile?.profileImageUrl != null
|
||||||
|
? DecorationImage(
|
||||||
|
image: NetworkImage(_patientProfile!.profileImageUrl!),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
child: const Center(
|
child: _patientProfile?.profileImageUrl == null
|
||||||
child: Text(
|
? Center(
|
||||||
'D',
|
child: Text(
|
||||||
style: TextStyle(
|
_patientProfile != null && _patientProfile!.name != null
|
||||||
fontSize: 30,
|
? _patientProfile!.name![0].toUpperCase()
|
||||||
fontWeight: FontWeight.bold,
|
: '',
|
||||||
color: Colors.blue,
|
style: const TextStyle(
|
||||||
),
|
fontSize: 30,
|
||||||
),
|
fontWeight: FontWeight.bold,
|
||||||
),
|
color: Colors.blue,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
const Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Dhansh A S',
|
_patientProfile != null && _patientProfile!.name != null
|
||||||
style: TextStyle(
|
? _patientProfile!.name!
|
||||||
|
: 'Create your profile',
|
||||||
|
style: const TextStyle(
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
|
||||||
'User profile is incomplete',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: Colors.white70,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -117,7 +138,9 @@ class _PatientProfileScreenState extends State<PatientProfileScreen> {
|
|||||||
_buildOptionTile(
|
_buildOptionTile(
|
||||||
'Medical Profile',
|
'Medical Profile',
|
||||||
Icons.medical_information_outlined,
|
Icons.medical_information_outlined,
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
// Add navigation or action
|
||||||
|
},
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
_buildOptionTile(
|
_buildOptionTile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
import 'package:medora/route/route_names.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
|
||||||
|
|
||||||
class PatientLandingScreen extends StatelessWidget {
|
class PatientLandingScreen extends StatelessWidget {
|
||||||
const PatientLandingScreen({super.key});
|
const PatientLandingScreen({super.key});
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:telemednet/controllers/patient_controller.dart';
|
import 'package:medora/controllers/patient_controller.dart';
|
||||||
import 'package:telemednet/data/models/patient.dart';
|
import 'package:medora/data/models/patient.dart';
|
||||||
|
|
||||||
class FamilyMembersEditScreen extends StatefulWidget {
|
class FamilyMembersEditScreen extends StatefulWidget {
|
||||||
final FamilyMember? familyMember;
|
final FamilyMember? familyMember;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
import 'package:medora/controllers/patient_controller.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:country_state_city_picker/country_state_city_picker.dart';
|
import 'package:country_state_city_picker/country_state_city_picker.dart';
|
||||||
import 'package:telemednet/controllers/patient_controller.dart';
|
|
||||||
|
|
||||||
class PatientAddressScreen extends StatefulWidget {
|
class PatientAddressScreen extends StatefulWidget {
|
||||||
final PatientController? controller;
|
final PatientController? controller;
|
||||||
|
|||||||
@ -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: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 '../../../controllers/patient_controller.dart';
|
||||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
import 'package:medora/route/route_names.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|||||||
38
lib/screens/splash_screen.dart
Normal file
@ -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<SplashScreen> createState() => _SplashScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SplashScreenState extends State<SplashScreen> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
Future.delayed(const Duration(seconds: 3), () {
|
||||||
|
if (!mounted) return;
|
||||||
|
_navigateToAppropriateScreen();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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:flutter/material.dart';
|
||||||
import 'package:telemednet/route_names.dart';
|
|
||||||
import 'package:telemednet/routes.dart';
|
|
||||||
|
|
||||||
class TelemednetApp extends StatefulWidget {
|
class TelemednetApp extends StatefulWidget {
|
||||||
const TelemednetApp({super.key});
|
const TelemednetApp({super.key});
|
||||||
@ -15,14 +16,15 @@ class _TelemednetAppState extends State<TelemednetApp> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> login() async {}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
initialRoute: RouteNames.launch,
|
initialRoute: RouteNames.splashScreen,
|
||||||
routes: routes,
|
routes: {
|
||||||
|
RouteNames.splashScreen: (context) => const SplashScreen(),
|
||||||
|
...routes,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
182
pubspec.lock
@ -9,6 +9,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.44"
|
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:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -33,6 +57,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
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:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -41,6 +73,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
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:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -121,6 +169,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.8"
|
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:
|
desktop_webview_auth:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -145,6 +201,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
version: "1.3.1"
|
||||||
|
ffi:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ffi
|
||||||
|
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.3"
|
||||||
fhir:
|
fhir:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -326,6 +390,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.2.1"
|
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:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -355,6 +427,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.1"
|
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:
|
flutter_svg:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -389,6 +477,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
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:
|
http:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -405,6 +501,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.2"
|
version: "4.0.2"
|
||||||
|
image:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image
|
||||||
|
sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.3.0"
|
||||||
image_picker:
|
image_picker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -558,7 +662,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||||
@ -569,10 +673,58 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_parsing
|
name: path_parsing
|
||||||
sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca"
|
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
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:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -581,6 +733,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.2"
|
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:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -589,6 +749,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.8"
|
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:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -714,6 +882,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
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:
|
xml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
12
pubspec.yaml
@ -1,4 +1,4 @@
|
|||||||
name: telemednet
|
name: medora
|
||||||
description: "A new Flutter project."
|
description: "A new Flutter project."
|
||||||
# The following line prevents the package from being accidentally published to
|
# The following line prevents the package from being accidentally published to
|
||||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
# 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_animations: ^1.1.1
|
||||||
flutter_staggered_grid_view: ^0.7.0
|
flutter_staggered_grid_view: ^0.7.0
|
||||||
carousel_slider: ^5.0.0
|
carousel_slider: ^5.0.0
|
||||||
|
path: ^1.9.0
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@ -68,13 +70,18 @@ dev_dependencies:
|
|||||||
# package. See that file for information about deactivating specific lint
|
# package. See that file for information about deactivating specific lint
|
||||||
# rules and activating additional ones.
|
# rules and activating additional ones.
|
||||||
flutter_lints: ^4.0.0
|
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
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
||||||
# The following section is specific to Flutter packages.
|
# The following section is specific to Flutter packages.
|
||||||
flutter:
|
flutter:
|
||||||
|
|
||||||
# The following line ensures that the Material Icons font is
|
# The following line ensures that the Material Icons font is
|
||||||
# included with your application, so that you can use the icons in
|
# included with your application, so that you can use the icons in
|
||||||
# the material Icons class.
|
# the material Icons class.
|
||||||
@ -90,6 +97,7 @@ flutter:
|
|||||||
- images/patient-avathar.png
|
- images/patient-avathar.png
|
||||||
- images/MaleDr.jpg.png
|
- images/MaleDr.jpg.png
|
||||||
- images/FemaleDr.jpg.png
|
- images/FemaleDr.jpg.png
|
||||||
|
- images/splash_screen.jpg
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
# https://flutter.dev/to/resolution-aware-images
|
# https://flutter.dev/to/resolution-aware-images
|
||||||
|
|||||||