commit 0f1620ae21ed9ae1d279fa7527b1824e01b4ea08
Author: Benoy Bose <benoybose@gmail.com>
Date: Mon Nov 4 14:45:08 2024 +0530
Squashed commit of the following:
commit f9f34ff304
Author: Benoy Bose <benoybose@gmail.com>
Date: Mon Nov 4 14:30:56 2024 +0530
Updated pub lock
commit 214cf48f9b63bc59425d59a2add17c13bb5ce186
Author: Benoy Bose <benoybose@gmail.com>
Date: Mon Nov 4 14:39:32 2024 +0530
Update pubspec.lock
commit faebb4b341d01933bbe6112c982dda36ae744288
Author: Benoy Bose <benoybose@gmail.com>
Date: Mon Nov 4 14:32:49 2024 +0530
Squashed commit of the following:
commit f9f34ff304
Author: Benoy Bose <benoybose@gmail.com>
Date: Mon Nov 4 14:30:56 2024 +0530
Updated pub lock
commit 4a529e7ef6a237a7551a73e72de2638d2ebc246f
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Nov 4 13:09:05 2024 +0530
Update doctor_personal_profile_screen.dart
commit 190e3a4058583d27418a9d10fb495da185b2a703
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Nov 4 13:07:40 2024 +0530
completed doctor consultation center
commit 1b8196d50976975fd41a32201b9d024f5986cba2
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Sun Nov 3 21:04:53 2024 +0530
completed doctors schedule creation
commit 033e1b74a811a3eaebf430dbe5cf2ea5a8f30fe4
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Sun Nov 3 14:41:25 2024 +0530
commit
commit aa92bebd0b897ab96c04dd9ae4a2ec101b95d1c0
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Sun Nov 3 14:19:56 2024 +0530
commit
commit e0a60c600872281d3915175f5dc5c311e7193be9
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Sun Nov 3 01:58:21 2024 +0530
doctor dashboard
commit 94009dd6e3791a7082a885af300ae04c38fe0207
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Sat Nov 2 20:58:04 2024 +0530
Update doctor_dashboard.dart
commit bdb14d29584cc993391322f762f6bd0b8956d40a
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Nov 1 23:56:38 2024 +0530
appoinment booking complete
commit dc61667a1ccee87b06b9accc6d6f2364126ea6a6
Merge: e08b4b3 17d6c60
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Nov 1 22:15:16 2024 +0530
Merge branch 'feature/medora-108' into feature/medora-55
commit 17d6c6036cd97e5290369f2b14f49cf5b52d3c2b
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Nov 1 22:01:16 2024 +0530
Completed service profile creation
commit 691e34bd721c6137699676c12f0c0b59bcdac953
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Fri Nov 1 18:52:28 2024 +0530
created doctor business center
commit 68bef5ab271f3ce8dc26b79a4cedb64debf6c410
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Fri Nov 1 15:38:45 2024 +0530
dev changes
commit e08b4b3bddad1ef74e05870c55e9371db67fe687
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Nov 1 12:02:47 2024 +0530
deleted booking controller
commit c8901aa51f9d3b78f10b85d24bb76190631ded56
Merge: abdf59e 01e27a1
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Fri Nov 1 11:40:20 2024 +0530
Merge branch 'dev' into feature/medora-108
commit 9d25eca33b1be0093a5e41551315b0cb3b4c100c
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Thu Oct 31 23:07:14 2024 +0530
route changed and deleted unwanted files
commit b07982a56048c12609daabc166cadc6353674d2d
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Thu Oct 31 22:04:04 2024 +0530
deleted duplicated files
commit 6a94bccec91037ade1f47d6d107df010ce6bd8a2
Merge: e5e7b55 01e27a1
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Thu Oct 31 22:03:37 2024 +0530
Merge branch 'dev' into feature/medora-55
commit e5e7b5597ec2a4be9849b5d52efb6baf21d3aa01
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Thu Oct 31 16:34:52 2024 +0530
consultation booking
commit abdf59e4d5221a00c04a5bec10ec15a934c66956
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Wed Oct 30 18:48:11 2024 +0530
commit
commit 42e7bb160530c65ef4ebaff2f9cc4b403dbb4109
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Wed Oct 30 11:17:58 2024 +0530
booking appoinments
commit a117b98fa21ae6bd42b2a2b99d97cbcc11ec1ccb
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Wed Oct 30 11:08:01 2024 +0530
Update pubspec.yaml
commit 64e7201a1e6b1d3fefd4952e3e4afa4031daccc8
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Tue Oct 29 18:02:38 2024 +0530
Update navigation_service.dart
commit 677bb639fa1d71545bd1a8d3c81582965ead3e64
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Tue Oct 29 15:09:06 2024 +0530
Revert "Merge branch 'feature/medora-71' into feature/medora-79"
This reverts commit eaa30a50553f3b0d9c1d73426dace8c5c384d05c, reversing
changes made to 176a6797be31c5bd16f77a1fb595a12451e8000c.
commit 3283d1b30bb0c69270b10d06cf9d00f61377e7dc
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Tue Oct 29 14:16:45 2024 +0530
commit
commit eaa30a50553f3b0d9c1d73426dace8c5c384d05c
Merge: 176a679 2404999
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Tue Oct 29 12:00:14 2024 +0530
Merge branch 'feature/medora-71' into feature/medora-79
commit 176a6797be31c5bd16f77a1fb595a12451e8000c
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Tue Oct 29 11:53:27 2024 +0530
commit doctor profile
commit 23bf668914c000c6d98108c50d60e2e12d827b36
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Tue Oct 29 11:14:16 2024 +0530
Doctor profile
commit 110753ddcfab9f16657ff71ad30a07054e5b1f09
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 28 18:19:42 2024 +0530
commit
commit 67613bf3d9d0e0171a152de093e6b01ccf95820f
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 28 15:10:56 2024 +0530
commit
commit 036aabbeae4ec637f601dc07d13eaf15b93ba2ec
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 28 14:00:17 2024 +0530
commit
commit 240499983bb6864a602efad335c494d5424c2da6
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Mon Oct 28 12:39:02 2024 +0530
common elements added and some error fixed
commit 08f3be051569cfcb6b35db78f416efb862ed5de9
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 28 11:19:21 2024 +0530
commit
commit 62d4d739b84fbd8e6d0d9f0c4a18fc87989bb198
Merge: 6947ba5 66e54bc
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Fri Oct 25 18:45:42 2024 +0530
Merge branch 'feature/medora-71' into feature/medora-79
commit 6947ba519fef2ac77a6dc778a397b9eb30a384b8
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Fri Oct 25 18:40:12 2024 +0530
commit
commit 66e54bcb94d3a68b6421fbc5c9205eee2a21b64b
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Oct 25 17:58:46 2024 +0530
color update
commit 74f216b6d39b1108e8beb43d9fd153468237d8cf
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Oct 25 17:58:23 2024 +0530
fixed some bugs and added common files
commit 180976cceafee37eb64786939315febd6c41d1a7
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Fri Oct 25 15:12:20 2024 +0530
commit
commit a717f95af85022158bd5130b52a0894fd4d04b5d
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Oct 25 14:25:04 2024 +0530
date and ui changes in family list screen
commit d463c805e271438a4324959543fd2f688e908a7f
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Oct 25 13:07:29 2024 +0530
sign up issue solved
commit 2a3fb82c2d7fa25f8bb6707966cdcbbb7b7f6711
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Fri Oct 25 01:19:32 2024 +0530
commit
commit 1000963818dfc4050bdd81a756ebb5207410d876
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Oct 25 01:06:07 2024 +0530
validation added flow corrected and patient registration complete
commit fd5b472830b6c3cffd40262109ee370d58b138a3
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Thu Oct 24 19:25:08 2024 +0530
commit
commit 59387828aec1042eab06d1fc1855c7a8ba1e441d
Merge: f1bd18e ee9163b
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Thu Oct 24 16:28:12 2024 +0530
Merge remote-tracking branch 'origin/feature/medora-79' into feature/medora-71
commit f1bd18e5c1f17926ed6aaf3f14b2875bce0d64d8
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Thu Oct 24 16:27:48 2024 +0530
added roles while creating user
commit a4de95274cbcf3249b325e0ae73d9a4f52fe9272
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Thu Oct 24 16:26:49 2024 +0530
commit
commit ee9163b67061fbd9d2510cee02e4d0aead7c73ef
Merge: cd87cd7 2c6d7b7
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Thu Oct 24 14:18:52 2024 +0530
Merge branch 'feature/medora-71' into feature/medora-79
commit cd87cd748729dc9b95f91a07eeec5104c5b33f5e
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Thu Oct 24 14:15:13 2024 +0530
commit
commit 2c6d7b75abe5541a8a06dbdabcdc98cfc1bd70ff
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Thu Oct 24 12:15:51 2024 +0530
Validation added
commit 95fedc1b7979a5d6a039c5be5819252e6f988b1d
Merge: bc759fa ca23730
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Thu Oct 24 11:12:36 2024 +0530
Merge branch 'feature/medora-71' into feature/medora-79
commit ca237309b4455202a61cd21a07ab8fb97d1487b3
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Thu Oct 24 00:28:42 2024 +0530
Controller added
commit bc759fa390e623cd9a0a7c805e81cc1f8c60bd28
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Wed Oct 23 19:07:35 2024 +0530
Update doctor_profile_service.dart
commit b93514e0f94b0532e0e518a785de946baa1a413c
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Wed Oct 23 19:06:33 2024 +0530
commit
commit b99611c83072a28aa966328072d1c7f4b74890cd
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Wed Oct 23 15:42:48 2024 +0530
Update Doctor_profile_screen.dart
commit 9f2ddf623b7a0dc07c620a2073f93e3a2aae4c86
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Wed Oct 23 12:21:02 2024 +0530
commit
commit fa2cdbacf31716dfdf52881f544ccbd740df5102
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Tue Oct 22 11:19:15 2024 +0530
commit
commit 7adbf395869c2c2e8912509c802aa3dba467ac0c
Merge: 1dec3a4 561174f
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Tue Oct 22 11:19:07 2024 +0530
Merge remote-tracking branch 'origin/feature/medora-71' into feature/medora-79
commit 561174f58b5240746d451a068e45e8abd99a31c9
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Tue Oct 22 11:17:01 2024 +0530
Firebase service and model with controller has been added
commit 1dec3a44bd1fe6383eb79e5049dd40e2daaf5930
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 21 18:20:20 2024 +0530
Update profile_description_screen.dart
commit 2f093115e17c3a53cbe1e5659cbcc0d2f4e173aa
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 21 18:16:34 2024 +0530
commit
commit e40f9afc88dfd0144ee8023b71736f95ef09ff4b
Merge: 14ebc23 8dcff6c
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 21 17:06:43 2024 +0530
Merge remote-tracking branch 'origin/feature/medora-70' into feature/medora-79
commit 14ebc23a5772e92c74b2a0c1ebc2d301f5b7ba0f
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 21 17:06:23 2024 +0530
commit
commit 8dcff6cbff5be921a99c0a3315dfe309f28bfb4a
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Mon Oct 21 17:06:05 2024 +0530
UI complete patient registration
commit 091029b056351afb410f542fb5db81253f59d07a
Merge: 9cbf16f 9f988ce
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 21 16:05:47 2024 +0530
Merge remote-tracking branch 'origin/feature/medora-70' into feature/medora-79
commit 9f988cebc7659b65626b0706f09bda59246710d2
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Mon Oct 21 16:01:29 2024 +0530
UI for patient registartion
commit 9cbf16f14700cf2d7a36720ca796f46614cb5bec
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 21 16:01:17 2024 +0530
commit
commit bd5561bf21b612d07730f6c4330f1aee6a63f652
Merge: 2fb3f01 5a12155
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 21 11:35:59 2024 +0530
Merge remote-tracking branch 'origin/feature/medora-70' into feature/medora-79
commit 2fb3f010fe0ead574de0d25da7f03e0e4f4abd5c
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Mon Oct 21 11:34:41 2024 +0530
doctor profile
commit 5a12155ababfb41606986e9a1e9481a7738a7e8c
Merge: 2090099 6530b5a
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Oct 18 18:17:35 2024 +0530
Merge branch 'feature/medora-78' into feature/medora-70
commit 2090099d7496c1f6c8490462addce2226f4c9397
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Oct 18 18:17:05 2024 +0530
added user selection screen
commit 6530b5ad45c6d6a46577af90c2e82981ce1baa68
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Fri Oct 18 16:47:35 2024 +0530
App deployed
commit b742de48b851369a59e83819762d706607176c70
Author: Jipson George <152465898+Jipson-cosq@users.noreply.github.com>
Date: Fri Oct 18 15:41:19 2024 +0530
commit
commit 33190bb1a324e0a48831087c77336138171a49d9
Merge: 8e3d05d 4809c9a
Author: DhanshCOSQ <dhanshas@cosq.net>
Date: Thu Oct 17 17:17:27 2024 +0530
Merge branch 'dev' into feature/medora-70
commit 8e3d05de97
Author: Benoy Bose <benoybose@gmail.com>
Date: Tue Oct 15 20:00:08 2024 +0530
Reconfigured Firebase
commit 1f12d4cb5d
Author: Benoy Bose <benoybose@gmail.com>
Date: Tue Oct 15 19:50:40 2024 +0530
Updated launch screen
commit 810548880a
Author: Benoy Bose <benoybose@gmail.com>
Date: Mon Oct 14 18:29:27 2024 +0530
Added user screen
681 lines
24 KiB
Dart
681 lines
24 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:telemednet/route_names.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
|
|
import 'dart:io';
|
|
import '../../../controllers/patient_controller.dart';
|
|
import '../../../widgets/alert_screen.dart';
|
|
|
|
class PatientRegistrationScreen extends StatefulWidget {
|
|
const PatientRegistrationScreen({super.key});
|
|
|
|
@override
|
|
State<PatientRegistrationScreen> createState() =>
|
|
_PatientRegistrationScreenState();
|
|
}
|
|
|
|
class _PatientRegistrationScreenState extends State<PatientRegistrationScreen> {
|
|
final PatientController _controller = PatientController();
|
|
final TextEditingController _nameController = TextEditingController();
|
|
final TextEditingController _phoneController = TextEditingController();
|
|
bool _hasErrors = false;
|
|
final Map<String, String> _errors = {};
|
|
|
|
String? _gender;
|
|
DateTime? _dateOfBirth;
|
|
File? _image;
|
|
final ImagePicker _picker = ImagePicker();
|
|
String _selectedCountryCode = '+1';
|
|
|
|
final List<String> _countryCodes = ['+1', '+91', '+44', '+61', '+81'];
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_nameController.text = _controller.model.name ?? '';
|
|
if (_controller.model.phoneNumber != null) {
|
|
String phoneNumber = _controller.model.phoneNumber!;
|
|
if (phoneNumber.startsWith('+')) {
|
|
for (String code in _countryCodes) {
|
|
if (phoneNumber.startsWith(code)) {
|
|
_selectedCountryCode = code;
|
|
_phoneController.text = phoneNumber.substring(code.length);
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
_phoneController.text = phoneNumber;
|
|
}
|
|
}
|
|
|
|
_gender = _controller.model.gender;
|
|
_dateOfBirth = _controller.model.dateOfBirth;
|
|
if (_controller.model.profileImagePath != null) {
|
|
_image = File(_controller.model.profileImagePath!);
|
|
}
|
|
_updateCombinedPhoneNumber(_phoneController.text);
|
|
}
|
|
|
|
Future<void> _getImage(ImageSource source) async {
|
|
final XFile? pickedFile = await _picker.pickImage(source: source);
|
|
|
|
if (pickedFile != null) {
|
|
setState(() {
|
|
_image = File(pickedFile.path);
|
|
});
|
|
_controller.updateProfileImage(pickedFile.path);
|
|
}
|
|
}
|
|
|
|
void _updateCombinedPhoneNumber(String phoneNumber) {
|
|
String cleanPhoneNumber = phoneNumber.replaceAll(RegExp(r'^\+\d{1,3}'), '');
|
|
String fullPhoneNumber = '$_selectedCountryCode$cleanPhoneNumber';
|
|
_controller.updatePhoneNumber(fullPhoneNumber);
|
|
}
|
|
|
|
void _showImageSourceActionSheet(BuildContext context) {
|
|
showModalBottomSheet(
|
|
context: context,
|
|
backgroundColor: Colors.transparent,
|
|
builder: (BuildContext context) {
|
|
return Container(
|
|
decoration: const BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
|
),
|
|
child: SafeArea(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
const Padding(
|
|
padding: EdgeInsets.symmetric(vertical: 16),
|
|
child: Text(
|
|
'Select Image Source',
|
|
style: TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
ListTile(
|
|
leading: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
color: Colors.blue.withOpacity(0.1),
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: const Icon(Icons.photo_library, color: Colors.blue),
|
|
),
|
|
title: const Text('Choose from Gallery'),
|
|
onTap: () {
|
|
_getImage(ImageSource.gallery);
|
|
Navigator.pop(context);
|
|
},
|
|
),
|
|
ListTile(
|
|
leading: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
color: Colors.blue.withOpacity(0.1),
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: const Icon(Icons.photo_camera, color: Colors.blue),
|
|
),
|
|
title: const Text('Take a Photo'),
|
|
onTap: () {
|
|
_getImage(ImageSource.camera);
|
|
Navigator.pop(context);
|
|
},
|
|
),
|
|
const SizedBox(height: 16),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
void _showResultDialog(bool isSuccess) {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => AlertScreen(
|
|
arguments: AlertArguments(
|
|
title: isSuccess ? 'Thank You' : 'Oops!',
|
|
message: isSuccess
|
|
? 'Profile created successfully!'
|
|
: 'Failed to create profile. Please try again.',
|
|
actionTitle: isSuccess ? 'Go to Dashboard' : 'Try Again',
|
|
type: isSuccess ? AlertType.success : AlertType.error,
|
|
onActionPressed: () {
|
|
Navigator.pop(context);
|
|
if (isSuccess) {
|
|
Navigator.pushReplacementNamed(
|
|
context,
|
|
RouteNames.patientDashboardScreen,
|
|
);
|
|
}
|
|
},
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Colors.grey[50],
|
|
appBar: AppBar(
|
|
elevation: 0,
|
|
backgroundColor: Colors.white,
|
|
title: const Text(
|
|
'Create Profile',
|
|
style: TextStyle(color: Colors.black),
|
|
),
|
|
actions: [
|
|
Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: IconButton(
|
|
onPressed: () {
|
|
if (_validateAllFields()) {
|
|
_controller.savePatientData();
|
|
_showResultDialog(true);
|
|
} else {
|
|
_showValidationErrors();
|
|
}
|
|
},
|
|
icon: const Icon(Icons.check, color: Colors.blue, weight: 50),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
body: SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
Container(
|
|
color: Colors.white,
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Column(
|
|
children: [
|
|
GestureDetector(
|
|
onTap: () => _showImageSourceActionSheet(context),
|
|
child: Stack(
|
|
alignment: Alignment.bottomRight,
|
|
children: [
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.blueGrey.withOpacity(0.5),
|
|
blurRadius: 5,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
shape: BoxShape.circle,
|
|
border: Border.all(color: Colors.blue, width: 2),
|
|
),
|
|
child: CircleAvatar(
|
|
radius: 75,
|
|
backgroundImage:
|
|
_image != null ? FileImage(_image!) : null,
|
|
child: _image == null
|
|
? const Icon(Icons.person,
|
|
size: 50, color: Colors.blue)
|
|
: null,
|
|
),
|
|
),
|
|
Container(
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.blueGrey.withOpacity(0.5),
|
|
blurRadius: 5,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
color: Colors.blue,
|
|
shape: BoxShape.circle,
|
|
border: Border.all(color: Colors.white, width: 2),
|
|
),
|
|
child: const Icon(Icons.camera_alt,
|
|
size: 20, color: Colors.white),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(12),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.blueGrey.withOpacity(0.5),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Column(
|
|
children: [
|
|
_buildUniformField(
|
|
label: 'Name',
|
|
icon: Icons.person_outline,
|
|
child: TextField(
|
|
controller: _nameController,
|
|
onChanged: (value) => _controller.updateName(value),
|
|
decoration: const InputDecoration(
|
|
border: InputBorder.none,
|
|
hintText: 'Enter your name',
|
|
),
|
|
),
|
|
),
|
|
_buildUniformField(
|
|
label: 'Phone Number',
|
|
icon: Icons.phone_outlined,
|
|
child: Row(
|
|
children: [
|
|
DropdownButtonHideUnderline(
|
|
child: DropdownButton<String>(
|
|
value: _selectedCountryCode,
|
|
onChanged: (String? newValue) {
|
|
if (newValue != null) {
|
|
setState(() {
|
|
_selectedCountryCode = newValue;
|
|
});
|
|
|
|
_updateCombinedPhoneNumber(
|
|
_phoneController.text);
|
|
}
|
|
},
|
|
items:
|
|
_countryCodes.map<DropdownMenuItem<String>>(
|
|
(String code) {
|
|
return DropdownMenuItem<String>(
|
|
value: code,
|
|
child: Text(code),
|
|
);
|
|
},
|
|
).toList(),
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: TextField(
|
|
controller: _phoneController,
|
|
onChanged: (value) {
|
|
_updateCombinedPhoneNumber(value);
|
|
},
|
|
keyboardType: TextInputType.phone,
|
|
decoration: const InputDecoration(
|
|
border: InputBorder.none,
|
|
hintText: 'Enter your phone number',
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
_buildUniformField(
|
|
label: 'Gender',
|
|
icon: Icons.people_outline,
|
|
child: DropdownButtonHideUnderline(
|
|
child: DropdownButton<String>(
|
|
value: _gender,
|
|
isExpanded: true,
|
|
hint: const Text('Select gender'),
|
|
onChanged: (value) {
|
|
setState(() => _gender = value);
|
|
_controller.updateGender(value!);
|
|
},
|
|
items: ['Male', 'Female', 'Other']
|
|
.map<DropdownMenuItem<String>>((String value) {
|
|
return DropdownMenuItem<String>(
|
|
value: value,
|
|
child: Text(value),
|
|
);
|
|
}).toList(),
|
|
),
|
|
),
|
|
),
|
|
_buildUniformField(
|
|
label: 'Date of Birth',
|
|
icon: Icons.calendar_today_outlined,
|
|
child: InkWell(
|
|
onTap: () async {
|
|
final DateTime? picked = await showDatePicker(
|
|
context: context,
|
|
initialDate: _dateOfBirth ??
|
|
DateTime.now()
|
|
.subtract(const Duration(days: 365 * 18)),
|
|
firstDate: DateTime(1900),
|
|
lastDate: DateTime.now()
|
|
.subtract(const Duration(days: 365 * 18)),
|
|
builder: (context, child) {
|
|
return Theme(
|
|
data: Theme.of(context).copyWith(
|
|
colorScheme: const ColorScheme.light(
|
|
primary: Colors.blue),
|
|
),
|
|
child: child!,
|
|
);
|
|
},
|
|
);
|
|
if (picked != null && picked != _dateOfBirth) {
|
|
setState(() => _dateOfBirth = picked);
|
|
_controller.updateDateOfBirth(picked);
|
|
}
|
|
},
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
|
child: Text(
|
|
_dateOfBirth != null
|
|
? DateFormat('dd/MM/yyyy').format(_dateOfBirth!)
|
|
: 'Select date of birth',
|
|
style: TextStyle(
|
|
color: _dateOfBirth != null
|
|
? Colors.black87
|
|
: Colors.grey,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(12),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.blueGrey.withOpacity(0.5),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
children: [
|
|
_buildNavigationField(
|
|
'Address',
|
|
Icons.location_on,
|
|
() async {
|
|
final result = await Navigator.pushNamed(
|
|
context,
|
|
RouteNames.patientAdressScreen,
|
|
arguments: _controller,
|
|
);
|
|
if (result == true) {
|
|
setState(() {});
|
|
}
|
|
},
|
|
),
|
|
const Divider(height: 1),
|
|
_buildNavigationField(
|
|
'Family Members',
|
|
Icons.family_restroom_outlined,
|
|
() => Navigator.pushNamed(
|
|
context,
|
|
RouteNames.patientFamilyMembersScreen,
|
|
arguments: _controller,
|
|
),
|
|
),
|
|
],
|
|
)),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildUniformField({
|
|
required String label,
|
|
required IconData icon,
|
|
required Widget child,
|
|
String? errorKey,
|
|
}) {
|
|
return Container(
|
|
margin: const EdgeInsets.only(bottom: 16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey[50],
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(
|
|
color: _errors.containsKey(errorKey ?? '')
|
|
? Colors.red
|
|
: Colors.grey.shade200,
|
|
),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 16, top: 8),
|
|
child: Text(
|
|
label,
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w500,
|
|
color: _errors.containsKey(errorKey ?? '')
|
|
? Colors.red
|
|
: Colors.grey[600],
|
|
),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 8),
|
|
child: Row(
|
|
children: [
|
|
Icon(
|
|
icon,
|
|
size: 20,
|
|
color: _errors.containsKey(errorKey ?? '')
|
|
? Colors.red
|
|
: Colors.blue,
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(child: child),
|
|
],
|
|
),
|
|
),
|
|
if (_errors.containsKey(errorKey ?? ''))
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 8),
|
|
child: Text(
|
|
_errors[errorKey]!,
|
|
style: const TextStyle(
|
|
color: Colors.red,
|
|
fontSize: 12,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
bool _validateAllFields() {
|
|
setState(() {
|
|
_errors.clear();
|
|
_hasErrors = false;
|
|
|
|
final name = _nameController.text.trim();
|
|
if (name.isEmpty) {
|
|
_errors['name'] = 'Name is required';
|
|
_hasErrors = true;
|
|
} else if (name.length < 2 &&
|
|
RegExp(r'^[A-Za-z]+([.\s]?[A-Za-z]+)*$').hasMatch(name)) {
|
|
_errors['name'] = 'Name must be at least 2 characters';
|
|
_hasErrors = true;
|
|
}
|
|
|
|
final phoneNumber = _phoneController.text.trim();
|
|
if (phoneNumber.isEmpty) {
|
|
_errors['phone'] = 'Phone number is required';
|
|
_hasErrors = true;
|
|
} else if (!RegExp(r'^\d{10}$').hasMatch(phoneNumber)) {
|
|
_errors['phone'] = 'Enter a valid 10-digit phone number';
|
|
_hasErrors = true;
|
|
}
|
|
|
|
if (_gender == null) {
|
|
_errors['gender'] = 'Please select a gender';
|
|
_hasErrors = true;
|
|
}
|
|
|
|
if (_dateOfBirth == null) {
|
|
_errors['dob'] = 'Date of Birth is required';
|
|
_hasErrors = true;
|
|
} else {
|
|
final age = DateTime.now().difference(_dateOfBirth!).inDays ~/ 365;
|
|
if (age < 18) {
|
|
_errors['dob'] = 'User must be at least 18 years old';
|
|
_hasErrors = true;
|
|
}
|
|
}
|
|
|
|
if (_image == null) {
|
|
_errors['image'] = 'Profile picture is required';
|
|
_hasErrors = true;
|
|
}
|
|
|
|
final address = _controller.model.address;
|
|
if (address.houseNo?.isEmpty ?? true) {
|
|
_errors['address'] = 'Please complete all required address fields';
|
|
_hasErrors = true;
|
|
}
|
|
|
|
if (address.addressType == 'Other' &&
|
|
(address.otherLabel?.isEmpty ?? true)) {
|
|
_errors['address'] = 'Please specify other address label';
|
|
_hasErrors = true;
|
|
}
|
|
});
|
|
|
|
return !_hasErrors;
|
|
}
|
|
|
|
void _showValidationErrors() {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: const Row(
|
|
children: [
|
|
Icon(Icons.error_outline, color: Colors.red),
|
|
SizedBox(width: 8),
|
|
Text('Validation Errors'),
|
|
],
|
|
),
|
|
content: SingleChildScrollView(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: _errors.entries
|
|
.map((error) => Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 4),
|
|
child: Text(
|
|
'• ${error.value}',
|
|
style: const TextStyle(color: Colors.red),
|
|
),
|
|
))
|
|
.toList(),
|
|
),
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: const Text('OK'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildNavigationField(
|
|
String label, IconData icon, VoidCallback onTap) {
|
|
bool isAddressField = label == 'Address';
|
|
bool hasAddressError = _errors.containsKey('address');
|
|
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
ListTile(
|
|
leading: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
color: (isAddressField && hasAddressError)
|
|
? Colors.red.withOpacity(0.1)
|
|
: Colors.blue.withOpacity(0.1),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: Icon(icon,
|
|
color: (isAddressField && hasAddressError)
|
|
? Colors.red
|
|
: Colors.blue,
|
|
size: 24),
|
|
),
|
|
title: Text(
|
|
label,
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w500,
|
|
color: (isAddressField && hasAddressError)
|
|
? Colors.red
|
|
: Colors.black,
|
|
),
|
|
),
|
|
subtitle: isAddressField ? _buildAddressSubtitle() : null,
|
|
trailing: Icon(
|
|
Icons.chevron_right,
|
|
color:
|
|
(isAddressField && hasAddressError) ? Colors.red : Colors.blue,
|
|
),
|
|
onTap: onTap,
|
|
),
|
|
if (isAddressField && hasAddressError)
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 8),
|
|
child: Text(
|
|
_errors['address']!,
|
|
style: const TextStyle(
|
|
color: Colors.red,
|
|
fontSize: 12,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildAddressSubtitle() {
|
|
final address = _controller.model.address;
|
|
if (address.houseNo == null ||
|
|
address.line == null ||
|
|
address.city == null) {
|
|
return const Text(
|
|
'No address added',
|
|
style: TextStyle(color: Colors.grey),
|
|
);
|
|
}
|
|
|
|
return Text(
|
|
'${address.houseNo}, ${address.line}\n'
|
|
'${address.city}, ${address.state} ${address.pincode}\n'
|
|
'${address.addressType}${address.addressType == "Other" ? ": ${address.otherLabel}" : ""}',
|
|
style: const TextStyle(color: Colors.black87),
|
|
);
|
|
}
|
|
}
|