From ec433190c40c491435f357fc6f0acd006e534f92 Mon Sep 17 00:00:00 2001 From: DhanshCOSQ Date: Thu, 31 Oct 2024 06:04:36 +0000 Subject: [PATCH] UI complete (#2) UI complete for patient registration Co-authored-by: Benoy Bose Reviewed-on: https://git.cosqnet.com/cosqnet/telemednet/pulls/2 Reviewed-by: Benoy Bose Co-authored-by: DhanshCOSQ Co-committed-by: DhanshCOSQ --- images/patient-avathar.png | Bin 0 -> 43807 bytes lib/data/data_service.dart | 2 +- lib/data/models/patient.dart | 1 + lib/data/{ => models}/telemed_user.dart | 0 lib/route_names.dart | 9 + lib/routes.dart | 21 +- .../{ => authentication}/launch_screen.dart | 2 +- .../authentication/user_profile_screen.dart | 61 +++++ .../patient_dashboard_screen.dart | 207 ++++++++++++++++ .../patient_landing_screen.dart | 94 ++++++++ .../family_members_edit_screen.dart | 162 +++++++++++++ .../patient_adress_screen.dart | 114 +++++++++ .../patient_family_members_screen.dart | 153 ++++++++++++ .../patient_registration_screen.dart | 226 ++++++++++++++++++ lib/screens/user_profile_screen.dart | 32 --- lib/shared/user_selection.dart | 120 ++++++++++ lib/telemednet_app.dart | 4 +- pubspec.lock | 220 ++++++++++++++++- pubspec.yaml | 6 + 19 files changed, 1395 insertions(+), 39 deletions(-) create mode 100644 images/patient-avathar.png create mode 100644 lib/data/models/patient.dart rename lib/data/{ => models}/telemed_user.dart (100%) rename lib/screens/{ => authentication}/launch_screen.dart (100%) create mode 100644 lib/screens/authentication/user_profile_screen.dart create mode 100644 lib/screens/patientDashboard/patient_dashboard_screen.dart create mode 100644 lib/screens/patientDashboard/patient_landing_screen.dart create mode 100644 lib/screens/patientDashboard/registrationScreens/family_members_edit_screen.dart create mode 100644 lib/screens/patientDashboard/registrationScreens/patient_adress_screen.dart create mode 100644 lib/screens/patientDashboard/registrationScreens/patient_family_members_screen.dart create mode 100644 lib/screens/patientDashboard/registrationScreens/patient_registration_screen.dart delete mode 100644 lib/screens/user_profile_screen.dart create mode 100644 lib/shared/user_selection.dart diff --git a/images/patient-avathar.png b/images/patient-avathar.png new file mode 100644 index 0000000000000000000000000000000000000000..68b21c66759b73cd615570227111103bd46340bd GIT binary patch literal 43807 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 gjTPWUfWF&H@(z?eD*8l(j literal 0 HcmV?d00001 diff --git a/lib/data/data_service.dart b/lib/data/data_service.dart index b1fa1e4..54b6bea 100644 --- a/lib/data/data_service.dart +++ b/lib/data/data_service.dart @@ -1,7 +1,7 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:telemednet/data/telemed_user.dart'; +import 'package:telemednet/data/models/telemed_user.dart'; class DataService { static final String profileCollectionName = diff --git a/lib/data/models/patient.dart b/lib/data/models/patient.dart new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/lib/data/models/patient.dart @@ -0,0 +1 @@ + diff --git a/lib/data/telemed_user.dart b/lib/data/models/telemed_user.dart similarity index 100% rename from lib/data/telemed_user.dart rename to lib/data/models/telemed_user.dart diff --git a/lib/route_names.dart b/lib/route_names.dart index 3d8ef74..9d65d47 100644 --- a/lib/route_names.dart +++ b/lib/route_names.dart @@ -3,4 +3,13 @@ class RouteNames { static const String userProfile = '/user-profile'; static const String userHome = '/user-home'; static const String signUp = '/sign-up'; + static const String launch = '/launch'; + static const String patientLandingScreen = '/patient-landing-screen'; + static const String patientDashboardScreen = '/patient-dahboard-screen'; + static const String patientRegistrationScreen = + '/patient-registration-screen'; + static const String patientAdressScreen = '/patient-adress-screen'; + static const String patientFamilyMembersScreen = + '/patient-family-members-screen'; + static const String familyMembersEditScreen = '/family-members-edit-screen'; } diff --git a/lib/routes.dart b/lib/routes.dart index ff2fa15..336c2e8 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -1,14 +1,21 @@ // routes.dart import 'package:firebase_ui_auth/firebase_ui_auth.dart'; import 'package:flutter/material.dart'; -import 'package:telemednet/data/telemed_user.dart'; +import 'package:telemednet/data/models/telemed_user.dart'; import 'package:telemednet/screens/launch_screen.dart'; import 'package:telemednet/route_names.dart'; +import 'package:telemednet/screens/patientDashboard/patient_dashboard_screen.dart'; +import 'package:telemednet/screens/patientDashboard/registrationScreens/patient_adress_screen.dart'; +import 'package:telemednet/screens/patientDashboard/registrationScreens/patient_family_members_screen.dart'; +import 'package:telemednet/screens/patientDashboard/registrationScreens/patient_registration_screen.dart'; import 'package:telemednet/screens/user_profile_screen.dart'; import 'package:telemednet/screens/user_screen.dart'; +import 'screens/patientDashboard/patient_landing_screen.dart'; +import 'screens/patientDashboard/registrationScreens/family_members_edit_screen.dart'; + final Map routes = { - '/': (context) => const LaunchScreen(), + RouteNames.launch: (context) => const LaunchScreen(), RouteNames.signIn: (context) => SignInScreen( providers: [EmailAuthProvider(), PhoneAuthProvider()], ), @@ -18,4 +25,14 @@ final Map routes = { return UserProfileScreen(user: user); }, RouteNames.userHome: (context) => const UserScreen(), + RouteNames.patientLandingScreen: (context) => const PatientLandingScreen(), + RouteNames.patientDashboardScreen: (context) => + const PatientDashboardScreen(), + RouteNames.patientRegistrationScreen: (context) => + const PatientRegistrationScreen(), + RouteNames.patientAdressScreen: (context) => const PatientAddressScreen(), + RouteNames.patientFamilyMembersScreen: (context) => + const PatientFamilyMembersScreen(), + RouteNames.familyMembersEditScreen: (context) => + const FamilyMembersEditScreen(), }; diff --git a/lib/screens/launch_screen.dart b/lib/screens/authentication/launch_screen.dart similarity index 100% rename from lib/screens/launch_screen.dart rename to lib/screens/authentication/launch_screen.dart index 424680d..75262d2 100644 --- a/lib/screens/launch_screen.dart +++ b/lib/screens/authentication/launch_screen.dart @@ -3,8 +3,8 @@ import 'dart:async'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:telemednet/data/data_service.dart'; -import 'package:telemednet/widgets/primary_button.dart'; import 'package:telemednet/route_names.dart'; +import 'package:telemednet/widgets/primary_button.dart'; class LaunchScreen extends StatefulWidget { const LaunchScreen({super.key}); diff --git a/lib/screens/authentication/user_profile_screen.dart b/lib/screens/authentication/user_profile_screen.dart new file mode 100644 index 0000000..f6a09d3 --- /dev/null +++ b/lib/screens/authentication/user_profile_screen.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:telemednet/data/models/telemed_user.dart'; +import 'package:telemednet/route_names.dart'; +import 'package:telemednet/shared/user_selection.dart'; + +class UserProfileScreen extends StatefulWidget { + final TelemedUser? user; + const UserProfileScreen({super.key, required this.user}); + + @override + State createState() => _UserProfileScreenState(); +} + +class _UserProfileScreenState extends State { + TelemedUser? user; + final FirebaseAuth _auth = FirebaseAuth.instance; + + @override + void initState() { + super.initState(); + user = widget.user; + } + + Future _signOut() async { + try { + await _auth.signOut(); + // Navigate to login screen or home screen after logout + Navigator.of(context).pushReplacementNamed(RouteNames.launch); + } catch (e) { + print("Error signing out: $e"); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Failed to log out. Please try again.')), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('User Profile'), + actions: [ + IconButton( + icon: Icon(Icons.exit_to_app), + onPressed: _signOut, + ), + ], + ), + body: Column( + children: [ + Expanded(child: UserSelection()), + ElevatedButton( + onPressed: _signOut, + child: Text('Log Out'), + ), + ], + ), + ); + } +} diff --git a/lib/screens/patientDashboard/patient_dashboard_screen.dart b/lib/screens/patientDashboard/patient_dashboard_screen.dart new file mode 100644 index 0000000..1995665 --- /dev/null +++ b/lib/screens/patientDashboard/patient_dashboard_screen.dart @@ -0,0 +1,207 @@ +import 'package:flutter/material.dart'; + +class PatientDashboardScreen extends StatefulWidget { + const PatientDashboardScreen({super.key}); + + @override + State createState() => _PatientDashboardScreenState(); +} + +class _PatientDashboardScreenState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: Column( + children: [ + _buildSearchBar(), + Expanded( + child: ListView( + padding: const EdgeInsets.all(16), + children: [ + _buildRealTimeCard(), + const SizedBox(height: 20), + _buildConsultationsSection(), + const SizedBox(height: 20), + _buildFindDoctorSection(), + ], + ), + ), + _buildBottomNavBar(), + ], + ), + ), + ); + } + + Widget _buildSearchBar() { + return Container( + padding: const EdgeInsets.all(16), + decoration: const BoxDecoration( + color: Color.fromRGBO(96, 181, 250, 1), + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(50.0), + bottomRight: Radius.circular(50.0)), + ), + child: TextField( + decoration: InputDecoration( + hintText: 'Search Doctor/Hospital/Symtoms', + prefixIcon: const Icon(Icons.search), + filled: true, + fillColor: Colors.white, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: BorderSide.none, + ), + ), + ), + ); + } + + Widget _buildRealTimeCard() { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.lightBlue[100]!, Colors.lightBlue[50]!], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Real-time care\nat your fingertips.', + style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + ElevatedButton( + onPressed: () {}, + child: const Text('Consultation >'), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + foregroundColor: Colors.black, + ), + ), + ], + ), + ); + } + + Widget _buildConsultationsSection() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Consultations', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), + const SizedBox(height: 10), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + _consultationCard('Dr Pom', '23/09/2024\n5:00AM-7:00AM'), + const SizedBox(width: 10), + _consultationCard('Dr I', '23/09/2024\n5:00AM-7:00AM'), + ], + ), + ), + ], + ); + } + + Widget _consultationCard(String name, String schedule) { + return GestureDetector( + onTap: () { + // Handle the tap event + print('Tapped on consultation card for $name'); + // You can add more functionality here, like navigating to a detail page + }, + child: Card( + shadowColor: Colors.grey, + child: Container( + width: 200, + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow(color: Colors.grey.withOpacity(0.5), blurRadius: 5), + ], + ), + child: Row( + children: [ + CircleAvatar( + radius: 30, + backgroundColor: Colors.blue[100], + child: const Icon(Icons.person, size: 40, color: Colors.white), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(name, + style: const TextStyle(fontWeight: FontWeight.bold)), + Text(schedule, style: const TextStyle(fontSize: 12)), + ], + ), + ), + ], + ), + ), + ), + ); + } + + Widget _buildFindDoctorSection() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Find a Doctor for your\nHealth Problem', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _categoryIcon(Icons.accessibility_new, Colors.blue), + _categoryIcon(Icons.remove_red_eye, Colors.blue), + _categoryIcon(Icons.medical_services, Colors.blue), + _categoryIcon(Icons.health_and_safety, Colors.blue), + _categoryIcon(Icons.child_care, Colors.blue), + ], + ), + ], + ); + } + + Widget _categoryIcon(IconData icon, Color color) { + return Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(10), + ), + child: Icon(icon, color: Colors.white, size: 30), + ); + } + + Widget _buildBottomNavBar() { + return BottomNavigationBar( + type: BottomNavigationBarType.fixed, + items: const [ + BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), + BottomNavigationBarItem(icon: Icon(Icons.chat_bubble), label: 'Chat'), + BottomNavigationBarItem(icon: Icon(Icons.assignment), label: 'Records'), + BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'), + ], + currentIndex: 0, + selectedItemColor: Colors.blue, + unselectedItemColor: Colors.grey, + onTap: (index) { + // Handle navigation + }, + ); + } +} diff --git a/lib/screens/patientDashboard/patient_landing_screen.dart b/lib/screens/patientDashboard/patient_landing_screen.dart new file mode 100644 index 0000000..4fffa26 --- /dev/null +++ b/lib/screens/patientDashboard/patient_landing_screen.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:telemednet/route_names.dart'; + +class PatientLandingScreen extends StatelessWidget { + const PatientLandingScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Colors.teal.shade100, Colors.white], + ), + ), + child: SafeArea( + child: Column( + children: [ + Expanded( + child: Center( + child: Card( + margin: const EdgeInsets.symmetric(horizontal: 32), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Align( + alignment: Alignment.topRight, + child: TextButton( + onPressed: () { + Navigator.of(context).pushNamed( + RouteNames.patientDashboardScreen); + }, + child: Text( + 'Skip', + style: TextStyle( + color: Colors.teal.shade300, + fontSize: 16, + fontWeight: FontWeight.bold), + ), + ), + ), + Image.asset( + 'images/patient-avathar.png', + height: 200, + width: 200, + ), + const SizedBox(height: 24), + const Text( + 'Set your medical profile', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 30, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 24), + ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed( + RouteNames.patientRegistrationScreen); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + minimumSize: const Size(double.infinity, 50), + ), + child: const Text( + 'Continue', + style: + TextStyle(fontSize: 18, color: Colors.white), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/patientDashboard/registrationScreens/family_members_edit_screen.dart b/lib/screens/patientDashboard/registrationScreens/family_members_edit_screen.dart new file mode 100644 index 0000000..a2659eb --- /dev/null +++ b/lib/screens/patientDashboard/registrationScreens/family_members_edit_screen.dart @@ -0,0 +1,162 @@ +import 'package:flutter/material.dart'; +import 'package:telemednet/screens/patientDashboard/registrationScreens/patient_family_members_screen.dart'; + +class FamilyMembersEditScreen extends StatefulWidget { + final FamilyMember? familyMember; + + const FamilyMembersEditScreen({super.key, this.familyMember}); + + @override + State createState() => + _FamilyMembersEditScreenState(); +} + +class _FamilyMembersEditScreenState extends State { + late TextEditingController nameController; + late TextEditingController relationController; + late TextEditingController genderController; + late TextEditingController dobController; + + @override + void initState() { + super.initState(); + nameController = + TextEditingController(text: widget.familyMember?.name ?? ''); + relationController = + TextEditingController(text: widget.familyMember?.relation ?? ''); + genderController = + TextEditingController(text: widget.familyMember?.gender ?? ''); + dobController = + TextEditingController(text: widget.familyMember?.dateOfBirth ?? ''); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Family member'), + actions: [ + TextButton( + onPressed: () { + FamilyMember newMember = FamilyMember( + name: nameController.text, + relation: relationController.text, + gender: genderController.text, + dateOfBirth: dobController.text, + ); + Navigator.pop(context, newMember); + }, + child: const Text('Done', style: TextStyle(color: Colors.blue)), + ), + ], + ), + body: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildTextField(nameController, 'Name'), + _buildDropdownField('Relation', relationController.text, + (String? newValue) { + setState(() { + relationController.text = newValue ?? ''; + }); + }), + _buildDropdownField('Gender', genderController.text, + (String? newValue) { + setState(() { + genderController.text = newValue ?? ''; + }); + }), + _buildDateField(context), + const SizedBox(height: 16), + const Text('Address', style: TextStyle(fontSize: 16)), + const SizedBox(height: 8), + Card( + child: ListTile( + title: const Text('Enter address details'), + trailing: const Icon(Icons.chevron_right), + onTap: () { + // Navigate to address entry screen + }, + ), + ), + ], + ), + ), + ); + } + + Widget _buildTextField(TextEditingController controller, String label) { + return Padding( + padding: const EdgeInsets.only(bottom: 16), + child: TextField( + controller: controller, + decoration: InputDecoration( + labelText: label, + border: const OutlineInputBorder(), + ), + ), + ); + } + + Widget _buildDropdownField( + String label, String value, Function(String?) onChanged) { + return Padding( + padding: const EdgeInsets.only(bottom: 16), + child: DropdownButtonFormField( + decoration: InputDecoration( + labelText: label, + border: const OutlineInputBorder(), + ), + value: value.isEmpty ? null : value, + onChanged: onChanged, + items: ['Father', 'Mother', 'Son', 'Daughter'] + .map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + ), + ); + } + + Widget _buildDateField(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(bottom: 16), + child: TextField( + controller: dobController, + decoration: const InputDecoration( + labelText: 'Date of Birth', + border: OutlineInputBorder(), + suffixIcon: Icon(Icons.calendar_today), + ), + readOnly: true, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1900), + lastDate: DateTime.now(), + ); + if (pickedDate != null) { + setState(() { + dobController.text = + "${pickedDate.day}/${pickedDate.month}/${pickedDate.year}"; + }); + } + }, + ), + ); + } + + @override + void dispose() { + nameController.dispose(); + relationController.dispose(); + genderController.dispose(); + dobController.dispose(); + super.dispose(); + } +} diff --git a/lib/screens/patientDashboard/registrationScreens/patient_adress_screen.dart b/lib/screens/patientDashboard/registrationScreens/patient_adress_screen.dart new file mode 100644 index 0000000..fe8855d --- /dev/null +++ b/lib/screens/patientDashboard/registrationScreens/patient_adress_screen.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; +import 'package:country_state_city_picker/country_state_city_picker.dart'; + +class PatientAddressScreen extends StatefulWidget { + const PatientAddressScreen({super.key}); + + @override + State createState() => _PatientAddressScreenState(); +} + +class _PatientAddressScreenState extends State { + final TextEditingController _houseNoController = TextEditingController(); + final TextEditingController _lineController = TextEditingController(); + final TextEditingController _townController = TextEditingController(); + final TextEditingController _pincodeController = TextEditingController(); + String? country; + String? state; + String? city; + String? addressType; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Address'), + actions: [ + TextButton( + onPressed: () { + // Save address logic here + }, + child: const Text('Done', style: TextStyle(color: Colors.blue)), + ), + ], + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildTextField('House No', _houseNoController), + _buildTextField('Line', _lineController), + _buildTextField('Town', _townController, hintText: '(OPTIONAL)'), + _buildTextField('Pincode', _pincodeController), + const SizedBox(height: 20), + SelectState( + onCountryChanged: (value) { + setState(() { + country = value; + }); + }, + onStateChanged: (value) { + setState(() { + state = value; + }); + }, + onCityChanged: (value) { + setState(() { + city = value; + }); + }, + ), + const SizedBox(height: 20), + const Text('Type of address', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + _buildAddressTypeChips(), + if (addressType == 'Other') + const TextField( + decoration: InputDecoration( + hintText: 'Other Label...', + border: OutlineInputBorder(), + ), + ), + ], + ), + ), + ); + } + + Widget _buildTextField(String label, TextEditingController controller, + {String? hintText}) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + TextField( + controller: controller, + decoration: InputDecoration( + hintText: hintText, + border: const UnderlineInputBorder(), + ), + ), + const SizedBox(height: 20), + ], + ); + } + + Widget _buildAddressTypeChips() { + return Wrap( + spacing: 8.0, + children: ['Home', 'Office', 'Other'].map((String type) { + return ChoiceChip( + label: Text(type), + selected: addressType == type, + onSelected: (bool selected) { + setState(() { + addressType = selected ? type : addressType; + }); + }, + ); + }).toList(), + ); + } +} diff --git a/lib/screens/patientDashboard/registrationScreens/patient_family_members_screen.dart b/lib/screens/patientDashboard/registrationScreens/patient_family_members_screen.dart new file mode 100644 index 0000000..d8117eb --- /dev/null +++ b/lib/screens/patientDashboard/registrationScreens/patient_family_members_screen.dart @@ -0,0 +1,153 @@ +import 'package:flutter/material.dart'; +import 'package:telemednet/screens/patientDashboard/registrationScreens/family_members_edit_screen.dart'; + +class FamilyMember { + final String name; + final String gender; + final String dateOfBirth; + final String relation; + + FamilyMember({ + required this.name, + required this.gender, + required this.dateOfBirth, + required this.relation, + }); +} + +class PatientFamilyMembersScreen extends StatefulWidget { + const PatientFamilyMembersScreen({super.key}); + + @override + State createState() => + _PatientFamilyMembersScreenState(); +} + +class _PatientFamilyMembersScreenState + extends State { + List familyMembers = [ + FamilyMember( + name: "Dhansh A S", + gender: "Male", + dateOfBirth: "18/12/2001", + relation: "Father", + ), + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Family members'), + actions: [ + TextButton( + onPressed: () { + // Handle 'Done' action + }, + child: Text('Done', style: TextStyle(color: Colors.blue)), + ), + ], + ), + body: ListView.builder( + itemCount: familyMembers.length, + itemBuilder: (context, index) { + return FamilyMemberCard( + familyMember: familyMembers[index], + onEdit: () => _editFamilyMember(index), + onDelete: () => _deleteFamilyMember(index), + ); + }, + ), + floatingActionButton: FloatingActionButton( + onPressed: _addFamilyMember, + child: Icon(Icons.add), + backgroundColor: Colors.blue, + ), + ); + } + + void _addFamilyMember() { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => const FamilyMembersEditScreen()), + ).then((newMember) { + if (newMember != null) { + setState(() { + familyMembers.add(newMember); + }); + } + }); + } + + void _editFamilyMember(int index) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + FamilyMembersEditScreen(familyMember: familyMembers[index]), + ), + ).then((editedMember) { + if (editedMember != null) { + setState(() { + familyMembers[index] = editedMember; + }); + } + }); + } + + void _deleteFamilyMember(int index) { + setState(() { + familyMembers.removeAt(index); + }); + } +} + +class FamilyMemberCard extends StatelessWidget { + final FamilyMember familyMember; + final VoidCallback onEdit; + final VoidCallback onDelete; + + const FamilyMemberCard({ + super.key, + required this.familyMember, + required this.onEdit, + required this.onDelete, + }); + + @override + Widget build(BuildContext context) { + return Card( + margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Padding( + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Name: ${familyMember.name}', + style: TextStyle(fontWeight: FontWeight.bold)), + SizedBox(height: 4), + Text('Gender: ${familyMember.gender}'), + SizedBox(height: 4), + Text('Date of Birth: ${familyMember.dateOfBirth}'), + SizedBox(height: 4), + Text('Relation: ${familyMember.relation}'), + SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + IconButton( + icon: Icon(Icons.edit, color: Colors.blue), + onPressed: onEdit, + ), + IconButton( + icon: Icon(Icons.delete, color: Colors.red), + onPressed: onDelete, + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/patientDashboard/registrationScreens/patient_registration_screen.dart b/lib/screens/patientDashboard/registrationScreens/patient_registration_screen.dart new file mode 100644 index 0000000..09a1d3e --- /dev/null +++ b/lib/screens/patientDashboard/registrationScreens/patient_registration_screen.dart @@ -0,0 +1,226 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:telemednet/route_names.dart'; +import 'package:image_picker/image_picker.dart'; +import 'dart:io'; + +class PatientRegistrationScreen extends StatefulWidget { + const PatientRegistrationScreen({super.key}); + + @override + State createState() => + _PatientRegistrationScreenState(); +} + +class _PatientRegistrationScreenState extends State { + final TextEditingController _nameController = TextEditingController(); + final TextEditingController _phoneController = TextEditingController(); + String? _gender; + DateTime? _dateOfBirth; + File? _image; + final ImagePicker _picker = ImagePicker(); + + Future _getImage(ImageSource source) async { + final XFile? pickedFile = await _picker.pickImage(source: source); + + if (pickedFile != null) { + setState(() { + _image = File(pickedFile.path); + }); + } + } + + void _showImageSourceActionSheet(BuildContext context) { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SafeArea( + child: Wrap( + children: [ + ListTile( + leading: const Icon(Icons.photo_library), + title: const Text('Choose from Gallery'), + onTap: () { + _getImage(ImageSource.gallery); + Navigator.pop(context); + }, + ), + ListTile( + leading: const Icon(Icons.photo_camera), + title: const Text('Take a Photo'), + onTap: () { + _getImage(ImageSource.camera); + Navigator.pop(context); + }, + ), + ], + ), + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Profile'), + actions: [ + IconButton( + icon: const Icon(Icons.check, color: Colors.blue), + onPressed: () { + // Save profile logic here + }, + ), + ], + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Column( + children: [ + GestureDetector( + onTap: () => _showImageSourceActionSheet(context), + child: CircleAvatar( + radius: 50, + backgroundImage: + _image != null ? FileImage(_image!) : null, + child: _image == null + ? const Icon(Icons.person, size: 50) + : null, + ), + ), + TextButton( + onPressed: () => _showImageSourceActionSheet(context), + child: const Text('Upload picture', + style: TextStyle(color: Colors.blue)), + ), + ], + ), + ), + const SizedBox(height: 20), + _buildTextField('Name', _nameController), + _buildTextField('Phone number', _phoneController), + _buildDropdownField('Gender', _gender, ['Male', 'Female', 'Other'], + (value) { + setState(() => _gender = value); + }), + _buildDateField('Date of Birth', _dateOfBirth), + _buildNavigationField('Address'), + _buildNavigationField('Family members'), + ], + ), + ), + ); + } + + Widget _buildTextField(String label, TextEditingController controller) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + TextField( + controller: controller, + decoration: const InputDecoration( + border: UnderlineInputBorder(), + ), + ), + const SizedBox(height: 20), + ], + ); + } + + Widget _buildDropdownField(String label, String? value, List items, + Function(String?) onChanged) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + DropdownButton( + value: value, + isExpanded: true, + hint: Text('Select $label'), + onChanged: onChanged, + items: items.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + ), + const SizedBox(height: 20), + ], + ); + } + + Widget _buildDateField(String label, DateTime? date) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(date != null + ? DateFormat('dd/MM/yyyy').format(date) + : 'Select date'), + IconButton( + icon: const Icon(Icons.calendar_today, color: Colors.blue), + onPressed: () async { + final DateTime? picked = await showDatePicker( + context: context, + initialDate: date ?? DateTime.now(), + firstDate: DateTime(1900), + lastDate: DateTime.now(), + ); + if (picked != null && picked != date) { + setState(() { + _dateOfBirth = picked; + }); + } + }, + ), + ], + ), + const Divider(), + const SizedBox(height: 20), + ], + ); + } + + Widget _buildNavigationField(String label) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(label, + style: + const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + IconButton( + icon: const Icon(Icons.chevron_right, color: Colors.blue), + onPressed: () { + if (label == 'Address') { + Navigator.of(context) + .pushNamed(RouteNames.patientAdressScreen); + } else { + Navigator.of(context) + .pushNamed(RouteNames.patientFamilyMembersScreen); + } + }, + ), + ], + ), + const Divider(), + const SizedBox(height: 20), + ], + ); + } +} diff --git a/lib/screens/user_profile_screen.dart b/lib/screens/user_profile_screen.dart deleted file mode 100644 index cec377e..0000000 --- a/lib/screens/user_profile_screen.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:telemednet/data/telemed_user.dart'; - -class UserProfileScreen extends StatefulWidget { - final TelemedUser? user; - const UserProfileScreen({super.key, required this.user}); - - @override - State createState() => _UserProfileScreenState(); -} - -class _UserProfileScreenState extends State { - TelemedUser? user; - - @override - void initState() { - super.initState(); - user = widget.user; - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('User Profile Screen'), - ), - body: const Center( - child: Text('User Profile Screen'), - ), - ); - } -} diff --git a/lib/shared/user_selection.dart b/lib/shared/user_selection.dart new file mode 100644 index 0000000..38cf0d5 --- /dev/null +++ b/lib/shared/user_selection.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; + +import '../route_names.dart'; + +class UserSelection extends StatefulWidget { + const UserSelection({super.key}); + + @override + State createState() => _UserSelectionState(); +} + +class _UserSelectionState extends State { + String _selectedUserType = ''; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Text( + 'Register', + style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + textAlign: TextAlign.center, + ), + const SizedBox(height: 24), + const Text( + 'Select User Type', + style: TextStyle(fontSize: 16), + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + _buildSelectionOption( + icon: Icons.medical_services, + label: 'Doctor', + description: 'Can organise and approve appointments', + onTap: () => _selectUserType('Doctor'), + ), + const SizedBox(height: 12), + _buildSelectionOption( + icon: Icons.person, + label: 'Patient', + description: 'Can book appointments', + onTap: () => _selectUserType('Patient'), + ), + const SizedBox(height: 24), + ElevatedButton( + onPressed: () { + if (_selectedUserType == 'Patient') { + Navigator.of(context) + .pushNamed(RouteNames.patientLandingScreen); + } else {} + }, + child: const Text('Next'), + style: ElevatedButton.styleFrom( + padding: const EdgeInsets.symmetric(vertical: 12), + ), + ), + ], + ), + ), + ), + ); + } + + Widget _buildSelectionOption({ + required IconData icon, + required String label, + required String description, + required VoidCallback onTap, + }) { + final isSelected = _selectedUserType == label; + return GestureDetector( + onTap: onTap, + child: Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + border: Border.all( + color: isSelected ? Colors.blue : Colors.grey[300]!, + width: 2, + ), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + Icon(icon, size: 40, color: Colors.blue), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: const TextStyle( + fontSize: 16, fontWeight: FontWeight.bold), + ), + Text( + description, + style: TextStyle(fontSize: 12, color: Colors.grey[600]), + ), + ], + ), + ), + if (isSelected) const Icon(Icons.check_circle, color: Colors.blue), + ], + ), + ), + ); + } + + void _selectUserType(String userType) { + setState(() { + _selectedUserType = userType; + }); + } +} diff --git a/lib/telemednet_app.dart b/lib/telemednet_app.dart index 573233a..c22d28c 100644 --- a/lib/telemednet_app.dart +++ b/lib/telemednet_app.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:telemednet/route_names.dart'; import 'package:telemednet/routes.dart'; class TelemednetApp extends StatefulWidget { @@ -19,7 +20,8 @@ class _TelemednetAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( - initialRoute: '/', + debugShowCheckedModeBanner: false, + initialRoute: RouteNames.launch, routes: routes, ); } diff --git a/pubspec.lock b/pubspec.lock index b1700f1..85cab23 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -81,6 +81,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" + country_state_city_picker: + dependency: "direct main" + description: + name: country_state_city_picker + sha256: "509c282165df329ee5a29babb28e13dce3bc32166cea21b202a49c44d20cfef3" + url: "https://pub.dev" + source: hosted + version: "1.2.8" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" crypto: dependency: transitive description: @@ -121,6 +137,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + fhir: + dependency: "direct main" + description: + name: fhir + sha256: "5242574636c300849227902717e2b37e4df7791ea75bda6c47c2600de417546a" + url: "https://pub.dev" + source: hosted + version: "0.12.0" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "712ce7fab537ba532c8febdb1a8f167b32441e74acd68c3ccb2e36dcb52c4ab2" + url: "https://pub.dev" + source: hosted + version: "0.9.3" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc" + url: "https://pub.dev" + source: hosted + version: "0.9.4+2" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "8f5d2f6590d51ecd9179ba39c64f722edc15226cc93dcc8698466ad36a4a85a4" + url: "https://pub.dev" + source: hosted + version: "0.9.3+3" firebase_auth: dependency: "direct main" description: @@ -185,6 +241,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.6+44" + firebase_storage: + dependency: "direct main" + description: + name: firebase_storage + sha256: e00e2909e36f5e44f839fd77dff90ff764f7bb303ed548d43617014ce05c77c8 + url: "https://pub.dev" + source: hosted + version: "12.3.3" + firebase_storage_platform_interface: + dependency: transitive + description: + name: firebase_storage_platform_interface + sha256: "462621bbdb5ab496518aa0f4785cb6db87763d5f1063aa228e1f65562937af1d" + url: "https://pub.dev" + source: hosted + version: "5.1.31" + firebase_storage_web: + dependency: transitive + description: + name: firebase_storage_web + sha256: d9221c943c1341ee2cba51857ddb5916686994b16b181e9e9d2e0d5a9056f9b7 + url: "https://pub.dev" + source: hosted + version: "3.10.3" firebase_ui_auth: dependency: "direct main" description: @@ -217,6 +297,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" flutter: dependency: "direct main" description: flutter @@ -243,6 +331,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398" + url: "https://pub.dev" + source: hosted + version: "2.0.23" flutter_svg: dependency: transitive description: @@ -261,6 +357,14 @@ packages: description: flutter source: sdk version: "0.0.0" + freezed_annotation: + dependency: transitive + description: + name: freezed_annotation + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 + url: "https://pub.dev" + source: hosted + version: "2.4.4" http: dependency: transitive description: @@ -277,14 +381,86 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" - intl: + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + image_picker_android: dependency: transitive + description: + name: image_picker_android + sha256: d34e0d9e024e81321b2aeed7b202ec6181cc282e6a1c0c0b4e6ad07ef1065d82 + url: "https://pub.dev" + source: hosted + version: "0.8.12+16" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "65d94623e15372c5c51bebbcb820848d7bcb323836e12dfdba60b5d3a8b39e50" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "4f0568120c6fcc0aaa04511cb9f9f4d29fc3d0139884b1d06be88dcec7641d6b" + url: "https://pub.dev" + source: hosted + version: "0.8.12+1" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80" + url: "https://pub.dev" + source: hosted + version: "2.10.0" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + intl: + dependency: "direct main" description: name: intl sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.dev" source: hosted version: "0.19.0" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" leak_tracker: dependency: transitive description: @@ -341,6 +517,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.15.0" + mime: + dependency: transitive + description: + name: mime + sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" + url: "https://pub.dev" + source: hosted + version: "1.0.6" path: dependency: transitive description: @@ -386,6 +570,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" stack_trace: dependency: transitive description: @@ -434,6 +626,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + url: "https://pub.dev" + source: hosted + version: "4.5.1" vector_graphics: dependency: transitive description: @@ -490,6 +690,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.5.0" + xml2json: + dependency: transitive + description: + name: xml2json + sha256: "9523203b99032ce419672804010cce72ea47fc277b3135f77bbb7ac8fa391664" + url: "https://pub.dev" + source: hosted + version: "6.2.5" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" sdks: dart: ">=3.5.3 <4.0.0" - flutter: ">=3.22.0" + flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index bdb3bfe..3ae3820 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,6 +40,11 @@ dependencies: firebase_auth: ^5.3.1 firebase_ui_auth: ^1.16.0 cloud_firestore: ^5.4.4 + firebase_storage: ^12.3.3 + image_picker: ^1.1.2 + fhir: ^0.12.0 + intl: ^0.19.0 + country_state_city_picker: ^1.2.8 dev_dependencies: flutter_test: @@ -70,6 +75,7 @@ flutter: assets: - .env - images/cover-picture.jpg + - images/patient-avathar.png # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/to/resolution-aware-images