UI complete (#2)
UI complete for patient registration Co-authored-by: Benoy Bose <benoybose@gmail.com> Reviewed-on: cosqnet/telemednet#2 Reviewed-by: Benoy Bose <benoybose@cosq.net> Co-authored-by: DhanshCOSQ <dhanshas@cosq.net> Co-committed-by: DhanshCOSQ <dhanshas@cosq.net>
This commit is contained in:
parent
240ab136fc
commit
ec433190c4
BIN
images/patient-avathar.png
Normal file
BIN
images/patient-avathar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
@ -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 =
|
||||
|
||||
1
lib/data/models/patient.dart
Normal file
1
lib/data/models/patient.dart
Normal file
@ -0,0 +1 @@
|
||||
|
||||
@ -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';
|
||||
}
|
||||
|
||||
@ -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<String, Widget Function(BuildContext)> routes = {
|
||||
'/': (context) => const LaunchScreen(),
|
||||
RouteNames.launch: (context) => const LaunchScreen(),
|
||||
RouteNames.signIn: (context) => SignInScreen(
|
||||
providers: [EmailAuthProvider(), PhoneAuthProvider()],
|
||||
),
|
||||
@ -18,4 +25,14 @@ final Map<String, Widget Function(BuildContext)> 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(),
|
||||
};
|
||||
|
||||
@ -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});
|
||||
61
lib/screens/authentication/user_profile_screen.dart
Normal file
61
lib/screens/authentication/user_profile_screen.dart
Normal file
@ -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<UserProfileScreen> createState() => _UserProfileScreenState();
|
||||
}
|
||||
|
||||
class _UserProfileScreenState extends State<UserProfileScreen> {
|
||||
TelemedUser? user;
|
||||
final FirebaseAuth _auth = FirebaseAuth.instance;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
user = widget.user;
|
||||
}
|
||||
|
||||
Future<void> _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'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
207
lib/screens/patientDashboard/patient_dashboard_screen.dart
Normal file
207
lib/screens/patientDashboard/patient_dashboard_screen.dart
Normal file
@ -0,0 +1,207 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PatientDashboardScreen extends StatefulWidget {
|
||||
const PatientDashboardScreen({super.key});
|
||||
|
||||
@override
|
||||
State<PatientDashboardScreen> createState() => _PatientDashboardScreenState();
|
||||
}
|
||||
|
||||
class _PatientDashboardScreenState extends State<PatientDashboardScreen> {
|
||||
@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
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
94
lib/screens/patientDashboard/patient_landing_screen.dart
Normal file
94
lib/screens/patientDashboard/patient_landing_screen.dart
Normal file
@ -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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<FamilyMembersEditScreen> createState() =>
|
||||
_FamilyMembersEditScreenState();
|
||||
}
|
||||
|
||||
class _FamilyMembersEditScreenState extends State<FamilyMembersEditScreen> {
|
||||
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<String>(
|
||||
decoration: InputDecoration(
|
||||
labelText: label,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
value: value.isEmpty ? null : value,
|
||||
onChanged: onChanged,
|
||||
items: <String>['Father', 'Mother', 'Son', 'Daughter']
|
||||
.map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -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<PatientAddressScreen> createState() => _PatientAddressScreenState();
|
||||
}
|
||||
|
||||
class _PatientAddressScreenState extends State<PatientAddressScreen> {
|
||||
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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<PatientFamilyMembersScreen> createState() =>
|
||||
_PatientFamilyMembersScreenState();
|
||||
}
|
||||
|
||||
class _PatientFamilyMembersScreenState
|
||||
extends State<PatientFamilyMembersScreen> {
|
||||
List<FamilyMember> 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<PatientRegistrationScreen> createState() =>
|
||||
_PatientRegistrationScreenState();
|
||||
}
|
||||
|
||||
class _PatientRegistrationScreenState extends State<PatientRegistrationScreen> {
|
||||
final TextEditingController _nameController = TextEditingController();
|
||||
final TextEditingController _phoneController = TextEditingController();
|
||||
String? _gender;
|
||||
DateTime? _dateOfBirth;
|
||||
File? _image;
|
||||
final ImagePicker _picker = ImagePicker();
|
||||
|
||||
Future<void> _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: <Widget>[
|
||||
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<String> items,
|
||||
Function(String?) onChanged) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(label,
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||
DropdownButton<String>(
|
||||
value: value,
|
||||
isExpanded: true,
|
||||
hint: Text('Select $label'),
|
||||
onChanged: onChanged,
|
||||
items: items.map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
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),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<UserProfileScreen> createState() => _UserProfileScreenState();
|
||||
}
|
||||
|
||||
class _UserProfileScreenState extends State<UserProfileScreen> {
|
||||
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'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
120
lib/shared/user_selection.dart
Normal file
120
lib/shared/user_selection.dart
Normal file
@ -0,0 +1,120 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../route_names.dart';
|
||||
|
||||
class UserSelection extends StatefulWidget {
|
||||
const UserSelection({super.key});
|
||||
|
||||
@override
|
||||
State<UserSelection> createState() => _UserSelectionState();
|
||||
}
|
||||
|
||||
class _UserSelectionState extends State<UserSelection> {
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -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<TelemednetApp> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
initialRoute: '/',
|
||||
debugShowCheckedModeBanner: false,
|
||||
initialRoute: RouteNames.launch,
|
||||
routes: routes,
|
||||
);
|
||||
}
|
||||
|
||||
220
pubspec.lock
220
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"
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user