Compare commits

..

No commits in common. "89551b9fd7213da1872a0b5846a0026197385500" and "f7027c7ad5cb672f691d1aa7d7a8dbea4de1556c" have entirely different histories.

10 changed files with 15 additions and 434 deletions

View File

@ -14,7 +14,7 @@ keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
} }
android { android {
namespace = "com.cosqnet.medoraprovider" namespace = "com.cosqnet.telemednet"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = "25.1.8937393" ndkVersion = "25.1.8937393"

View File

@ -1,4 +1,4 @@
package com.cosqnet.medoraprovider; package com.cosqnet.telemednet;
import io.flutter.embedding.android.FlutterActivity; import io.flutter.embedding.android.FlutterActivity;

View File

@ -368,7 +368,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.medoraprovider; PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.telemednet;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -384,7 +384,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.medoraprovider.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.telemednet.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -401,7 +401,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.medoraprovider.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.telemednet.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@ -416,7 +416,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.medoraprovider.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.telemednet.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@ -547,7 +547,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.medoraprovider; PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.telemednet;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -569,7 +569,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.medoraprovider; PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.telemednet;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;

View File

@ -1,96 +0,0 @@
import 'package:medora/data/models/patient.dart';
import '../data/services/patient_registration_service.dart';
class PatientController {
final PatientModel model = PatientModel();
Map<String, String> validationErrors = {};
void clearValidationErrors() {
validationErrors.clear();
}
void updateName(String name) {
model.name = name;
}
void updatePhoneNumber(String phoneNumber) {
model.phoneNumber = phoneNumber;
}
void updateGender(String gender) {
model.gender = gender;
}
void updateDateOfBirth(DateTime dateOfBirth) {
model.dateOfBirth = dateOfBirth;
}
void updateProfileImage(String imagePath) {
model.profileImagePath = imagePath;
}
void updateHouseNo(String houseNo) {
model.address.houseNo = houseNo;
}
void updateLine(String line) {
model.address.line = line;
}
void updateTown(String town) {
model.address.town = town;
}
void updatePincode(String pincode) {
model.address.pincode = pincode;
}
void updateCountry(String country) {
model.address.country = country;
}
void updateState(String state) {
model.address.state = state;
}
void updateCity(String city) {
model.address.city = city;
}
void addFamilyMember(FamilyMember member) {
model.familyMembers.add(member);
}
void updateFamilyMember(int index, FamilyMember member) {
if (index >= 0 && index < model.familyMembers.length) {
model.familyMembers[index] = member;
}
}
void deleteFamilyMember(int index) {
if (index >= 0 && index < model.familyMembers.length) {
model.familyMembers.removeAt(index);
}
}
Future<bool> savePatientData() async {
return await PatientProfileService.savePatientProfile(this);
}
Future<bool> loadPatientData() async {
PatientModel? loadedModel = await PatientProfileService.getPatientProfile();
if (loadedModel != null) {
model.updateFrom(loadedModel);
return true;
}
return false;
}
Future<bool> updatePatientData() async {
return await PatientProfileService.updatePatientProfile(model);
}
Future<bool> deletePatientData() async {
return await PatientProfileService.deletePatientProfile();
}
}

View File

@ -1,126 +0,0 @@
class PatientModel {
String? name;
String? phoneNumber;
String? gender;
DateTime? dateOfBirth;
String? profileImagePath;
String? profileImageUrl;
PatientAddress address;
List<FamilyMember> familyMembers = [];
PatientModel() : address = PatientAddress();
Map<String, dynamic> toJson() {
return {
'name': name,
'phoneNumber': phoneNumber,
'gender': gender,
'dateOfBirth': dateOfBirth?.toIso8601String(),
'profileImagePath': profileImagePath,
'profileImageUrl': profileImageUrl,
'address': address.toJson(),
'familyMembers': familyMembers.map((member) => member.toJson()).toList(),
};
}
PatientModel.fromJson(Map<String, dynamic> json)
: address = PatientAddress() {
name = json['name'];
phoneNumber = json['phoneNumber'];
gender = json['gender'];
dateOfBirth = json['dateOfBirth'] != null
? DateTime.parse(json['dateOfBirth'])
: null;
profileImagePath = json['profileImagePath'];
profileImageUrl = json['profileImageUrl'];
if (json['address'] != null) {
address =
PatientAddress.fromJson(json['address'] as Map<String, dynamic>);
}
if (json['familyMembers'] != null) {
familyMembers = (json['familyMembers'] as List)
.map((memberJson) => FamilyMember.fromJson(memberJson))
.toList();
}
}
void updateFrom(PatientModel other) {
name = other.name;
phoneNumber = other.phoneNumber;
gender = other.gender;
dateOfBirth = other.dateOfBirth;
profileImagePath = other.profileImagePath;
profileImageUrl = other.profileImageUrl;
address = other.address;
familyMembers = other.familyMembers;
}
}
class FamilyMember {
String? name;
String? relation;
String? gender;
DateTime? dateOfBirth;
FamilyMember({this.name, this.relation, this.gender, this.dateOfBirth});
Map<String, dynamic> toJson() {
return {
'name': name,
'relation': relation,
'gender': gender,
'dateOfBirth': dateOfBirth?.toIso8601String(),
};
}
FamilyMember.fromJson(Map<String, dynamic> json) {
name = json['name'];
relation = json['relation'];
gender = json['gender'];
dateOfBirth = json['dateOfBirth'] != null
? DateTime.parse(json['dateOfBirth'])
: null;
}
}
class PatientAddress {
String? houseNo;
String? line;
String? town;
String? pincode;
String? country;
String? state;
String? city;
PatientAddress(
{this.houseNo,
this.line,
this.town,
this.pincode,
this.country,
this.state,
this.city});
Map<String, dynamic> toJson() {
return {
'houseNo': houseNo,
'line': line,
'town': town,
'pincode': pincode,
'country': country,
'state': state,
'city': city,
};
}
PatientAddress.fromJson(Map<String, dynamic> json) {
houseNo = json['houseNo'];
line = json['line'];
town = json['town'];
pincode = json['pincode'];
country = json['country'];
state = json['state'];
city = json['city'];
}
}

View File

@ -1,198 +0,0 @@
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:medora/controllers/patient_controller.dart';
import 'package:medora/data/models/patient.dart';
import 'package:path/path.dart' as path;
class PatientProfileService {
static final String patientProfileCollectionName =
dotenv.env['PATIENT_PROFILE_COLLECTION_NAME']!;
static final FirebaseFirestore db = FirebaseFirestore.instance;
static final FirebaseStorage storage = FirebaseStorage.instanceFor(
bucket: dotenv.env['FIREBASE_STORAGE_BUCKET']!);
static Future<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 {
try {
final User? user = FirebaseAuth.instance.currentUser;
if (user == null) {
print('No user logged in');
return false;
}
final String uid = user.uid;
final PatientModel patientData = controller.model;
String? imageUrl;
if (patientData.profileImagePath != null) {
final File imageFile = File(patientData.profileImagePath!);
imageUrl = await uploadProfileImage(imageFile);
if (imageUrl == null) {
print('Failed to upload profile image');
return false;
}
}
final Map<String, dynamic> patientJson = patientData.toJson();
patientJson['createdAt'] = FieldValue.serverTimestamp();
patientJson['updatedAt'] = FieldValue.serverTimestamp();
patientJson['uid'] = uid;
patientJson['profileImageUrl'] = imageUrl;
await db
.collection(patientProfileCollectionName)
.doc(uid)
.set(patientJson);
print('Patient profile saved successfully');
return true;
} catch (e) {
print('Error saving patient profile: $e');
return false;
}
}
static Future<bool> updatePatientProfile(PatientModel patient) async {
try {
final User? user = FirebaseAuth.instance.currentUser;
if (user == null) {
print('No user logged in');
return false;
}
final String uid = user.uid;
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 = patient.toJson();
patientJson['updatedAt'] = FieldValue.serverTimestamp();
if (imageUrl != null) {
patientJson['profileImageUrl'] = imageUrl;
}
await db
.collection(patientProfileCollectionName)
.doc(uid)
.update(patientJson);
print('Patient profile updated successfully');
return true;
} catch (e) {
print('Error updating patient profile: $e');
return false;
}
}
static Future<bool> deletePatientProfile() async {
try {
final User? user = FirebaseAuth.instance.currentUser;
if (user == null) {
print('No user logged in');
return false;
}
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();
print('Patient profile deleted successfully');
return true;
} catch (e) {
print('Error deleting patient profile: $e');
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;
}
}
}

View File

@ -85,4 +85,5 @@ class DefaultFirebaseOptions {
storageBucket: 'cosq-telemednet-dev.appspot.com', storageBucket: 'cosq-telemednet-dev.appspot.com',
measurementId: 'G-BBV9TFGNN5', measurementId: 'G-BBV9TFGNN5',
); );
}
}

View File

@ -7,7 +7,7 @@ project(runner LANGUAGES CXX)
set(BINARY_NAME "telemednet") set(BINARY_NAME "telemednet")
# The unique GTK application identifier for this application. See: # The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID # https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "com.cosqnet.medoraprovider") set(APPLICATION_ID "com.cosqnet.telemednet")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake. # versions of CMake.

View File

@ -385,7 +385,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.medoraprovider.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.telemednet.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/telemednet.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/telemednet"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/telemednet.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/telemednet";
@ -399,7 +399,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.medoraprovider.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.telemednet.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/telemednet.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/telemednet"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/telemednet.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/telemednet";
@ -413,7 +413,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.medoraprovider.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.telemednet.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/telemednet.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/telemednet"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/telemednet.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/telemednet";

View File

@ -8,7 +8,7 @@
PRODUCT_NAME = telemednet PRODUCT_NAME = telemednet
// The application's bundle identifier // The application's bundle identifier
PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.medoraprovider PRODUCT_BUNDLE_IDENTIFIER = com.cosqnet.telemednet
// The copyright displayed in application information // The copyright displayed in application information
PRODUCT_COPYRIGHT = Copyright © 2024 com.cosqnet. All rights reserved. PRODUCT_COPYRIGHT = Copyright © 2024 com.cosqnet. All rights reserved.