Added user_info module IAP

pull/113/head
faizatflutter 2 months ago
parent 34f4cd4f91
commit c7c0a0ac09

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@ -0,0 +1,8 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 11.75C7.30964 11.75 6.75 12.3096 6.75 13C6.75 13.6904 7.30964 14.25 8 14.25H8.00897C8.69933 14.25 9.25897 13.6904 9.25897 13C9.25897 12.3096 8.69933 11.75 8.00897 11.75H8Z" fill="#8F9AA3"/>
<path d="M11.9955 11.75C11.3052 11.75 10.7455 12.3096 10.7455 13C10.7455 13.6904 11.3052 14.25 11.9955 14.25H12.0045C12.6948 14.25 13.2545 13.6904 13.2545 13C13.2545 12.3096 12.6948 11.75 12.0045 11.75H11.9955Z" fill="#8F9AA3"/>
<path d="M15.991 11.75C15.3007 11.75 14.741 12.3096 14.741 13C14.741 13.6904 15.3007 14.25 15.991 14.25H16C16.6904 14.25 17.25 13.6904 17.25 13C17.25 12.3096 16.6904 11.75 16 11.75H15.991Z" fill="#8F9AA3"/>
<path d="M8 15.75C7.30964 15.75 6.75 16.3096 6.75 17C6.75 17.6904 7.30964 18.25 8 18.25H8.00897C8.69933 18.25 9.25897 17.6904 9.25897 17C9.25897 16.3096 8.69933 15.75 8.00897 15.75H8Z" fill="#8F9AA3"/>
<path d="M11.9955 15.75C11.3052 15.75 10.7455 16.3096 10.7455 17C10.7455 17.6904 11.3052 18.25 11.9955 18.25H12.0045C12.6948 18.25 13.2545 17.6904 13.2545 17C13.2545 16.3096 12.6948 15.75 12.0045 15.75H11.9955Z" fill="#8F9AA3"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 2C7 1.44772 6.55229 1 6 1C5.44772 1 5 1.44772 5 2V2.44885C4.23882 2.6903 3.57734 3.06994 3.01802 3.6746C2.18949 4.57031 1.83279 5.69272 1.66416 7.04866C1.49997 8.36894 1.49998 10.0541 1.5 12.1739L1.5 12.8261C1.49998 14.9459 1.49997 16.6311 1.66416 17.9513C1.83279 19.3073 2.18949 20.4297 3.01802 21.3254C3.8568 22.2322 4.92535 22.6329 6.21533 22.8204C7.45141 23.0001 9.02291 23 10.9712 23H13.0288C14.977 23 16.5486 23.0001 17.7847 22.8204C19.0747 22.6329 20.1432 22.2322 20.982 21.3254C21.8105 20.4297 22.1672 19.3073 22.3358 17.9513C22.5 16.6311 22.5 14.9459 22.5 12.8261V12.1739C22.5 10.0541 22.5 8.36895 22.3358 7.04866C22.1672 5.69272 21.8105 4.57031 20.982 3.6746C20.4227 3.06993 19.7612 2.6903 19 2.44885V2C19 1.44772 18.5523 1 18 1C17.4477 1 17 1.44772 17 2V2.09173C15.903 1.99995 14.5863 1.99998 13.0288 2L10.9712 2C9.41376 1.99998 8.09704 1.99995 7 2.09173V2ZM4.49783 9C4.03921 9 3.8099 9 3.66385 9.14417C3.51781 9.28833 3.51487 9.51472 3.509 9.96751C3.50027 10.6407 3.5 11.3942 3.5 12.2432V12.7568C3.5 14.9616 3.50182 16.5221 3.64887 17.7045C3.79327 18.8656 4.06263 19.5094 4.48622 19.9673C4.89956 20.4142 5.4647 20.6903 6.503 20.8412C7.57858 20.9975 9.00425 21 11.05 21H12.95C14.9957 21 16.4214 20.9975 17.497 20.8412C18.5353 20.6903 19.1004 20.4142 19.5138 19.9673C19.9374 19.5094 20.2067 18.8656 20.3511 17.7045C20.4982 16.5221 20.5 14.9616 20.5 12.7568V12.2432C20.5 11.3942 20.4997 10.6407 20.491 9.96751C20.4851 9.51472 20.4822 9.28833 20.3362 9.14417C20.1901 9 19.9608 9 19.5022 9L4.49783 9Z" fill="#8F9AA3"/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.9998 1.25C9.92869 1.25 8.24976 2.92893 8.24976 5C8.24976 6.07361 8.80491 7.11878 9.47398 7.87011C9.81596 8.25412 10.2117 8.58958 10.6283 8.8334C11.0379 9.07316 11.5124 9.25 11.9998 9.25C12.4871 9.25 12.9616 9.07316 13.3712 8.8334C13.7878 8.58958 14.1836 8.25412 14.5255 7.87011C15.1946 7.11878 15.7498 6.07361 15.7498 5C15.7498 2.92893 14.0708 1.25 11.9998 1.25Z" fill="#8F9AA3"/>
<path d="M7.91515 8.34597C7.94794 8.37041 7.98252 8.41503 8.05168 8.50427C8.15094 8.63235 8.25213 8.75374 8.35378 8.86789C8.7849 9.35201 9.29974 9.79407 9.87058 10.1282C10.4203 10.4499 11.1584 10.7502 11.9998 10.7502C12.8411 10.7502 13.5792 10.4499 14.1289 10.1282C14.6998 9.79407 15.2146 9.35201 15.6457 8.86789C15.7474 8.75376 15.8485 8.63238 15.9478 8.50432C16.0171 8.41483 16.0518 8.37008 16.0847 8.34559C16.1822 8.27306 16.3055 8.26531 16.4114 8.32507C16.4471 8.34525 16.483 8.38124 16.5549 8.45323C18.2219 9.92647 19.404 12.5039 18.3564 14.9962C18.0511 15.7227 17.3445 16.2043 16.5513 16.2043L16.2745 16.2021C16.0468 16.2002 15.933 16.1993 15.8506 16.2633C15.7683 16.3274 15.7412 16.438 15.6869 16.6592L14.7228 20.5913C14.4139 21.851 13.2977 22.7504 11.9999 22.7504C10.7021 22.7504 9.58598 21.851 9.2771 20.5913L8.31293 16.6592C8.25869 16.438 8.23157 16.3274 8.14925 16.2633C8.06692 16.1993 7.95305 16.2002 7.72532 16.2021L7.44856 16.2043C6.6554 16.2043 5.94881 15.7227 5.64342 14.9962C4.59582 12.5039 5.77798 9.92648 7.44498 8.45325C7.51667 8.38147 7.55251 8.34558 7.58811 8.32543C7.69403 8.26548 7.81756 8.27324 7.91515 8.34597Z" fill="#8F9AA3"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.8011 1.62239C15.6024 1.12587 14.2555 1.12587 13.0568 1.62239C12.5696 1.8242 12.1382 2.13201 11.673 2.53776C11.2173 2.93519 10.6906 3.46195 10.0247 4.12781L10.0247 4.12784L10.0246 4.12791L4.12791 10.0246L4.1279 10.0246L4.1278 10.0247C3.46194 10.6906 2.93519 11.2174 2.53776 11.673C2.13201 12.1382 1.8242 12.5696 1.62239 13.0568C1.12587 14.2555 1.12587 15.6024 1.62239 16.8011C1.8242 17.2883 2.13201 17.7197 2.53776 18.1849C2.9352 18.6405 3.46199 19.1673 4.12788 19.8332L4.16671 19.872C4.83264 20.538 5.35945 21.0648 5.81512 21.4622C6.28029 21.868 6.71171 22.1758 7.19893 22.3776C8.39764 22.8741 9.7445 22.8741 10.9432 22.3776C11.4304 22.1758 11.8618 21.868 12.327 21.4622C12.4628 21.3438 12.5307 21.2846 12.5566 21.2077C12.575 21.1533 12.5771 21.091 12.5625 21.0355C12.5419 20.9571 12.4759 20.8911 12.3441 20.7593L10.913 19.3282C10.5225 18.9377 10.5225 18.3045 10.913 17.914C11.3035 17.5235 11.9367 17.5235 12.3272 17.914L13.7061 19.2928C13.9061 19.4928 14.0061 19.5928 14.1304 19.5928C14.2546 19.5928 14.3546 19.4928 14.5546 19.2928L15.7919 18.0556C15.9919 17.8556 16.0919 17.7556 16.0919 17.6313C16.0919 17.5071 15.9919 17.4071 15.7919 17.2071L14.413 15.8282C14.0225 15.4377 14.0225 14.8045 14.413 14.414C14.8035 14.0235 15.4367 14.0235 15.8272 14.414L17.2061 15.7928C17.4061 15.9928 17.5061 16.0928 17.6304 16.0928C17.7546 16.0928 17.8546 15.9928 18.0546 15.7928L19.2919 14.5556C19.4919 14.3556 19.5919 14.2556 19.5919 14.1313C19.5919 14.0071 19.4919 13.9071 19.2919 13.7071L17.913 12.3282C17.5225 11.9377 17.5225 11.3045 17.913 10.914C18.3035 10.5235 18.9367 10.5235 19.3272 10.914L20.7574 12.3441C20.8902 12.4769 20.9566 12.5433 21.0357 12.5638C21.0905 12.578 21.152 12.5759 21.2057 12.558C21.2833 12.5322 21.3429 12.4638 21.4622 12.327C21.868 11.8618 22.1758 11.4304 22.3776 10.9432C22.8741 9.7445 22.8741 8.39764 22.3776 7.19893C22.1758 6.71171 21.868 6.28029 21.4622 5.81512C21.0648 5.35945 20.538 4.83264 19.872 4.16671L19.8332 4.12788L19.8331 4.12777C19.1673 3.46193 18.6405 2.93518 18.1849 2.53776C17.7197 2.13201 17.2883 1.8242 16.8011 1.62239Z" fill="#8F9AA3"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.6905 5.77665C20.09 6.15799 20.1047 6.79098 19.7234 7.19048L9.22336 18.1905C9.03745 18.3852 8.78086 18.4968 8.51163 18.4999C8.2424 18.5031 7.98328 18.3975 7.79289 18.2071L4.29289 14.7071C3.90237 14.3166 3.90237 13.6834 4.29289 13.2929C4.68342 12.9024 5.31658 12.9024 5.70711 13.2929L8.48336 16.0692L18.2766 5.80953C18.658 5.41003 19.291 5.39531 19.6905 5.77665Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 533 B

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.6439 1.25L13.3561 1.25C14.259 1.24997 15.0211 1.24994 15.6249 1.32042C16.255 1.39396 16.8707 1.55847 17.3706 2.00915C17.5958 2.21222 17.7873 2.44899 17.9376 2.71113C18.2326 3.22573 18.2812 3.77334 18.2347 4.31609C19.2103 4.4287 20.0196 4.68604 20.6521 5.31966C21.2538 5.92238 21.5125 6.68113 21.6335 7.58241C21.75 8.4507 21.75 9.55477 21.75 10.9249V16.043C21.75 17.4131 21.75 18.5172 21.6335 19.3855C21.5125 20.2867 21.2538 21.0455 20.6521 21.6482C20.0502 22.2511 19.2923 22.5105 18.3919 22.6318C17.5249 22.7486 16.4225 22.7486 15.055 22.7485L8.94504 22.7485C7.57752 22.7486 6.47513 22.7486 5.60808 22.6318C4.70774 22.5105 3.94976 22.2511 3.3479 21.6482C2.74621 21.0455 2.48747 20.2867 2.3665 19.3855C2.24997 18.5172 2.24998 17.4131 2.25 16.0431L2.25 10.9248C2.24998 9.55478 2.24997 8.45069 2.3665 7.58241C2.48747 6.68113 2.74621 5.92238 3.3479 5.31966C3.98043 4.68604 4.78975 4.4287 5.76534 4.31608C5.71879 3.77334 5.76736 3.22573 6.06239 2.71113C6.21268 2.44899 6.40422 2.21222 6.62944 2.00915C7.1293 1.55847 7.74503 1.39396 8.37506 1.32042C8.97893 1.24994 9.74097 1.24997 10.6439 1.25ZM8.60067 3.2073C8.13641 3.26149 7.99252 3.35241 7.92575 3.4126C7.8493 3.48154 7.78534 3.56095 7.73568 3.64756C7.69637 3.71613 7.64027 3.8608 7.69746 4.30137C7.75673 4.75797 7.91092 5.36081 8.14823 6.27796C8.33725 7.00848 8.46246 7.48783 8.59555 7.84684C8.72171 8.18716 8.82647 8.33584 8.9287 8.43308C9.00978 8.51021 9.10016 8.57847 9.1982 8.63631C9.32461 8.71091 9.5056 8.77465 9.88389 8.81094C10.1378 8.83531 10.4406 8.84448 10.8301 8.84793L11.5514 6.68404C11.726 6.1601 12.2924 5.87694 12.8163 6.05159C13.3402 6.22624 13.6234 6.79256 13.4488 7.3165L12.9378 8.84935C13.4424 8.84743 13.8138 8.83994 14.1161 8.81094C14.4944 8.77465 14.6754 8.71091 14.8018 8.63631C14.8998 8.57847 14.9902 8.51021 15.0713 8.43308C15.1735 8.33584 15.2783 8.18716 15.4045 7.84684C15.5375 7.48783 15.6628 7.00848 15.8518 6.27796C16.0891 5.36081 16.2433 4.75797 16.3025 4.30137C16.3597 3.8608 16.3036 3.71613 16.2643 3.64756C16.2147 3.56095 16.1507 3.48153 16.0742 3.4126C16.0075 3.35241 15.8636 3.26149 15.3993 3.2073C14.9218 3.15157 14.2747 3.15 13.2979 3.15L10.7021 3.15C9.72532 3.15 9.07816 3.15157 8.60067 3.2073ZM10 17C9.44772 17 9 17.4477 9 18C9 18.5523 9.44772 19 10 19H14C14.5523 19 15 18.5523 15 18C15 17.4477 14.5523 17 14 17L10 17Z" fill="#8F9AA3"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@ -195,8 +195,13 @@ class AppAssets {
static const String heart = '$svgBasePath/heart.svg';
static const String alertSquare = '$svgBasePath/alert-square.svg';
static const String arrowRight = '$svgBasePath/arrow-right.svg';
static const String tickIcon = '$svgBasePath/tick.svg';
// Symptoms Checker
static const String calendarGrey = '$svgBasePath/calendar-grey.svg';
static const String weightScale = '$svgBasePath/weight-scale.svg';
static const String rulerIcon = '$svgBasePath/ruler.svg';
static const String genderIcon = '$svgBasePath/gender.svg';
static const String bodyIcon = '$svgBasePath/body_icon.svg';
static const String rotateIcon = '$svgBasePath/rotate_icon.svg';
static const String refreshIcon = '$svgBasePath/refresh.svg';
@ -218,6 +223,8 @@ class AppAssets {
static const String dummyUser = '$pngBasePath/dummy_user.png';
static const String comprehensiveCheckupEn = '$pngBasePath/cc_en.png';
static const String comprehensiveCheckupAr = '$pngBasePath/cc_er.png';
static const String maleIcon = '$pngBasePath/male_icon.png';
static const String femaleIcon = '$pngBasePath/female_icon.png';
static const String fullBodyFront = '$pngBasePath/full_body_front.png';
static const String fullBodyBack = '$pngBasePath/full_body_back.png';
@ -236,9 +243,9 @@ class AppAnimations {
static const String splashLaunching = '$lottieBasePath/splash_launching.json';
static const String noData = '$lottieBasePath/Nodata.json';
static const String ripple = '$lottieBasePath/Ripple.json';
static const String pending_loading_animation = '$lottieBasePath/pending_loading_animation.json';
static const String pendingLoadingAnimation = '$lottieBasePath/pending_loading_animation.json';
static const String ambulance = '$lottieBasePath/ambulance.json';
static const String ambulance_alert = '$lottieBasePath/ambulance_alert.json';
static const String rrt_ambulance = '$lottieBasePath/rrt_ambulance.json';
static const String ambulanceAlert = '$lottieBasePath/ambulance_alert.json';
static const String rrtAmbulance = '$lottieBasePath/rrt_ambulance.json';
}

@ -36,10 +36,28 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
// Selected symptoms tracking (organId -> Set of symptom IDs)
final Map<String, Set<String>> _selectedSymptomsByOrgan = {};
// User Info Flow State
int _userInfoCurrentPage = 0;
String? _selectedGender;
int? _selectedAge;
double? _selectedHeight;
bool _isHeightCm = true;
double? _selectedWeight;
bool _isWeightKg = true;
// Getters
bool isPossibleConditionsLoading = false;
// User Info Getters
int get userInfoCurrentPage => _userInfoCurrentPage;
String? get selectedGender => _selectedGender;
int? get selectedAge => _selectedAge;
double? get selectedHeight => _selectedHeight;
bool get isHeightCm => _isHeightCm;
double? get selectedWeight => _selectedWeight;
bool get isWeightKg => _isWeightKg;
BodyView get currentView => _currentView;
Set<String> get selectedOrganIds => _selectedOrganIds;
@ -247,6 +265,91 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
_isBottomSheetExpanded = false;
_tooltipTimer?.cancel();
_tooltipOrganId = null;
// Reset user info flow
_userInfoCurrentPage = 0;
_selectedGender = null;
_selectedAge = null;
_selectedHeight = null;
_isHeightCm = true;
_selectedWeight = null;
_isWeightKg = true;
notifyListeners();
}
// User Info Flow Methods
/// Set current page in user info flow
void setUserInfoPage(int page) {
_userInfoCurrentPage = page;
notifyListeners();
}
/// Navigate to next page in user info flow
void nextUserInfoPage() {
if (_userInfoCurrentPage < 3) {
_userInfoCurrentPage++;
notifyListeners();
}
}
/// Navigate to previous page in user info flow
void previousUserInfoPage() {
if (_userInfoCurrentPage > 0) {
_userInfoCurrentPage--;
notifyListeners();
}
}
/// Set selected gender
void setGender(String gender) {
_selectedGender = gender;
notifyListeners();
}
/// Set selected age
void setAge(int age) {
_selectedAge = age;
notifyListeners();
}
/// Set selected height
void setHeight(double height, bool isCm) {
_selectedHeight = height;
_isHeightCm = isCm;
notifyListeners();
}
/// Set selected weight
void setWeight(double weight, bool isKg) {
_selectedWeight = weight;
_isWeightKg = isKg;
notifyListeners();
}
/// Check if user info page is last
bool get isUserInfoLastPage => _userInfoCurrentPage == 3;
/// Validate and submit user info
Map<String, dynamic> getUserInfoData() {
return {
'gender': _selectedGender,
'age': _selectedAge,
'height': _selectedHeight,
'heightUnit': _isHeightCm ? 'cm' : 'ft',
'weight': _selectedWeight,
'weightUnit': _isWeightKg ? 'kg' : 'lbs',
};
}
/// Reset user info flow
void resetUserInfo() {
_userInfoCurrentPage = 0;
_selectedGender = null;
_selectedAge = null;
_selectedHeight = null;
_isHeightCm = true;
_selectedWeight = null;
_isWeightKg = true;
notifyListeners();
}

@ -1,7 +1,6 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';

@ -4,11 +4,11 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_config.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
@ -25,7 +25,6 @@ import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/immed
import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/select_immediate_livecare_clinic_page.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/search_doctor_by_name.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/select_clinic_page.dart';
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@ -71,145 +70,137 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
regionalViewModel = Provider.of<AppointmentViaRegionViewmodel>(context, listen: true);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView(
title: LocaleKeys.bookAppo.tr(context: context),
isLeading: true,
leadingCallback: () {
Navigator.pushAndRemoveUntil(
context,
CustomPageRoute(
page: LandingNavigation(),
),
(r) => false);
},
child: SingleChildScrollView(
child: Consumer<BookAppointmentsViewModel>(builder: (context, bookAppointmentsVM, child) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 16.h),
CustomTabBar(
activeTextColor: Color(0xffED1C2B),
activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
tabs: [
CustomTabBarModel(null, "General".needTranslation),
CustomTabBarModel(null, "LiveCare".needTranslation),
],
onTabChange: (index) {
bookAppointmentsVM.onTabChanged(index);
},
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 24.h),
getSelectedTabData(bookAppointmentsVM.selectedTabIndex),
SizedBox(height: 24.h),
"Recent Visits".needTranslation.toText18(isBold: true).paddingSymmetrical(24.w, 0.h),
SizedBox(height: 16.h),
Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
return myAppointmentsVM.isPatientMyDoctorsLoading
? Column(
crossAxisAlignment: CrossAxisAlignment.center,
body: Column(
children: [
Expanded(
child: CollapsingListView(
title: LocaleKeys.bookAppo.tr(context: context),
isLeading: true,
child: SingleChildScrollView(
child: Consumer<BookAppointmentsViewModel>(builder: (context, bookAppointmentsVM, child) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.network(
"https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
width: 64.w,
height: 64.h,
fit: BoxFit.cover,
).circle(100).toShimmer2(isShow: true, radius: 50.r),
SizedBox(height: 8.h),
("Dr. John Smith Smith Smith")
.toString()
.toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2)
.toShimmer2(isShow: true),
],
)
: myAppointmentsVM.patientMyDoctorsList.isEmpty
? Container(
width: SizeConfig.screenWidth,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 12.r,
hasShadow: false,
),
child: Utils.getNoDataWidget(
context,
noDataText: "You don't have any completed visits yet".needTranslation,
isSmallWidget: true,
width: 62.w,
height: 62.h,
),
).paddingSymmetrical(24.w, 0.h)
: SizedBox(
height: 110.h,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: myAppointmentsVM.patientMyDoctorsList.length,
shrinkWrap: true,
padding: EdgeInsets.only(left: 24.w, right: 24.w),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: SizedBox(
// width: 80.w,
child: Column(
SizedBox(height: 16.h),
CustomTabBar(
activeTextColor: Color(0xffED1C2B),
activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
tabs: [
CustomTabBarModel(null, "General".needTranslation),
CustomTabBarModel(null, "LiveCare".needTranslation),
],
onTabChange: (index) {
bookAppointmentsVM.onTabChanged(index);
},
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 24.h),
getSelectedTabData(bookAppointmentsVM.selectedTabIndex),
SizedBox(height: 24.h),
if (appState.isAuthenticated) ...[
Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
return myAppointmentsVM.isPatientMyDoctorsLoading
? Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.network(
myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!,
"https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
width: 64.w,
height: 64.h,
fit: BoxFit.cover,
).circle(100).toShimmer2(isShow: false, radius: 50.r),
).circle(100).toShimmer2(isShow: true, radius: 50.r),
SizedBox(height: 8.h),
SizedBox(
width: 80.w,
child: (myAppointmentsVM.patientMyDoctorsList[index].doctorName)
.toString()
.toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2)
.toShimmer2(isShow: false),
),
("Dr. John Smith Smith Smith")
.toString()
.toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2)
.toShimmer2(isShow: true),
],
),
).onPress(() async {
bookAppointmentsViewModel.setSelectedDoctor(DoctorsListResponseModel(
clinicID: myAppointmentsVM.patientMyDoctorsList[index].clinicID,
projectID: myAppointmentsVM.patientMyDoctorsList[index].projectID,
doctorID: myAppointmentsVM.patientMyDoctorsList[index].doctorID,
));
LoaderBottomSheet.showLoader();
await bookAppointmentsViewModel.getDoctorProfile(onSuccess: (dynamic respData) {
LoaderBottomSheet.hideLoader();
Navigator.of(context).push(
CustomPageRoute(
page: DoctorProfilePage(),
),
);
}, onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
}),
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 8.h),
),
)
: myAppointmentsVM.patientMyDoctorsList.isEmpty
? SizedBox()
: Column(
children: [
if (appState.isAuthenticated) ...[],
"Recent Visits".needTranslation.toText18(isBold: true).paddingSymmetrical(24.w, 0.h),
SizedBox(height: 16.h),
SizedBox(
height: 110.h,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: myAppointmentsVM.patientMyDoctorsList.length,
shrinkWrap: true,
padding: EdgeInsets.only(left: 24.w, right: 24.w),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: SizedBox(
// width: 80.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.network(
myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!,
width: 64.w,
height: 64.h,
fit: BoxFit.cover,
).circle(100).toShimmer2(isShow: false, radius: 50.r),
SizedBox(height: 8.h),
SizedBox(
width: 80.w,
child: (myAppointmentsVM.patientMyDoctorsList[index].doctorName)
.toString()
.toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2)
.toShimmer2(isShow: false),
),
],
),
).onPress(() async {
bookAppointmentsViewModel.setSelectedDoctor(DoctorsListResponseModel(
clinicID: myAppointmentsVM.patientMyDoctorsList[index].clinicID,
projectID: myAppointmentsVM.patientMyDoctorsList[index].projectID,
doctorID: myAppointmentsVM.patientMyDoctorsList[index].doctorID,
));
LoaderBottomSheet.showLoader();
await bookAppointmentsViewModel.getDoctorProfile(onSuccess: (dynamic respData) {
LoaderBottomSheet.hideLoader();
Navigator.of(context).push(
CustomPageRoute(
page: DoctorProfilePage(),
),
);
}, onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
}),
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 8.h),
),
),
],
);
}),
],
],
);
}),
],
);
}),
),
),
),
),
_buildSymptomsBottomCard(),
],
),
);
}
@ -460,6 +451,37 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
return Container();
}
Widget _buildSymptomsBottomCard() {
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
child: Row(
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Not sure? help me choose a clinic!".needTranslation.toText16(weight: FontWeight.w600, color: AppColors.textColor),
SizedBox(height: 4.h),
"Mention your symptoms and find the list of doctors accordingly".needTranslation.toText12(
fontWeight: FontWeight.w500,
color: AppColors.greyTextColor,
),
],
),
),
SizedBox(width: 16.w),
CustomButton(
height: 40.h,
text: "",
onPressed: () => context.navigateWithName(AppRoutes.userInfoSelection),
icon: AppAssets.arrow_forward,
)
],
).paddingAll(24.w),
);
}
void openRegionListBottomSheet(BuildContext context, RegionBottomSheetType type) {
regionalViewModel.flush();
regionalViewModel.setBottomSheetType(type);

@ -97,7 +97,7 @@ class EmergencyServicesPage extends StatelessWidget {
}),
],
),
Lottie.asset(AppAnimations.ambulance_alert,
Lottie.asset(AppAnimations.ambulanceAlert,
repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain),
SizedBox(height: 8.h),
"Confirmation".needTranslation.toText28(color: AppColors.whiteColor, isBold: true),
@ -200,7 +200,7 @@ class EmergencyServicesPage extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Lottie.asset(AppAnimations.ambulance_alert, repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain),
Lottie.asset(AppAnimations.ambulanceAlert, repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain),
SizedBox(height: 8.h),
LocaleKeys.confirm.tr().toText28(color: AppColors.whiteColor, isBold: true),
SizedBox(height: 8.h),
@ -313,7 +313,7 @@ class EmergencyServicesPage extends StatelessWidget {
}),
],
),
Lottie.asset(AppAnimations.ambulance_alert,
Lottie.asset(AppAnimations.ambulanceAlert,
repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain),
SizedBox(height: 8.h),
LocaleKeys.confirm.tr().toText28(color: AppColors.whiteColor, isBold: true),

@ -12,7 +12,6 @@ import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/int_extensions.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
@ -40,7 +39,6 @@ import 'package:hmg_patient_app_new/presentation/home/widgets/small_service_card
import 'package:hmg_patient_app_new/presentation/home/widgets/welcome_widget.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/presentation/profile_settings/profile_settings.dart';
import 'package:hmg_patient_app_new/routes/app_routes.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@ -494,8 +492,7 @@ class _LandingPageState extends State<LandingPage> {
mainAxisSize: MainAxisSize.min,
spacing: 12.h,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 18.h, width: 18.h)
.onPress(() => context.navigateWithName(AppRoutes.organSelectorPage)),
Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 18.h, width: 18.h),
Utils.buildSvgWithAssets(icon: AppAssets.search_icon, height: 18.h, width: 18.h).onPress(() {}),
Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 18.h, width: 18.h).onPress(() {
showCommonBottomSheetWithoutHeight(
@ -581,7 +578,6 @@ class _LandingPageState extends State<LandingPage> {
);
},
),
// height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3,
isFullScreen: false,
callBackFunc: () {
isDone = true;

@ -1,12 +1,13 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/presentation/contact_us/feedback_page.dart';
import 'package:hmg_patient_app_new/presentation/hmg_services/services_page.dart';
import 'package:hmg_patient_app_new/presentation/home/landing_page.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/presentation/todo_section/todo_page.dart';
import 'package:hmg_patient_app_new/routes/app_routes.dart';
import 'package:hmg_patient_app_new/widgets/bottom_navigation/bottom_navigation.dart';
class LandingNavigation extends StatefulWidget {
@ -18,12 +19,11 @@ class LandingNavigation extends StatefulWidget {
class _LandingNavigationState extends State<LandingNavigation> {
int _currentIndex = 0;
late AppState appState;
final PageController _pageController = PageController();
@override
Widget build(BuildContext context) {
appState = getIt.get<AppState>();
AppState appState = getIt.get<AppState>();
return Scaffold(
body: PageView(
controller: _pageController,
@ -31,7 +31,7 @@ class _LandingNavigationState extends State<LandingNavigation> {
children: [
const LandingPage(),
appState.isAuthenticated ? MedicalFilePage() : /* need add feedback page */ FeedbackPage(),
BookAppointmentPage(),
SizedBox(),
const ToDoPage(),
ServicesPage(),
],
@ -40,6 +40,10 @@ class _LandingNavigationState extends State<LandingNavigation> {
currentIndex: _currentIndex,
onTap: (index) {
setState(() => _currentIndex = index);
if (_currentIndex == 2) {
context.navigateWithName(AppRoutes.bookAppointmentPage);
return;
}
_pageController.animateToPage(index, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut);
},
),

@ -42,7 +42,7 @@ class _OrganSelectorPageState extends State<OrganSelectorPage> {
return;
}
context.navigateWithName(AppRoutes.symptomsCheckerScreen);
context.navigateWithName(AppRoutes.symptomsSelectorScreen);
}
@override

@ -148,7 +148,7 @@ class _RiskFactorsScreenState extends State<RiskFactorsScreen> {
Expanded(
child: CollapsingListView(
title: "Risks".needTranslation,
onLeadingTapped: () => _buildConfirmationBottomSheet(
leadingCallback: () => _buildConfirmationBottomSheet(
context: context,
onConfirm: () => {
context.pop(),

@ -148,7 +148,7 @@ class _SuggestionsScreenState extends State<SuggestionsScreen> {
Expanded(
child: CollapsingListView(
title: "Suggestions".needTranslation,
onLeadingTapped: () => _buildConfirmationBottomSheet(
leadingCallback: () => _buildConfirmationBottomSheet(
context: context,
onConfirm: () => {
context.pop(),

@ -78,7 +78,7 @@ class _SymptomsSelectorScreenState extends State<SymptomsSelectorScreen> {
Expanded(
child: CollapsingListView(
title: "Symptoms Selector".needTranslation,
onLeadingTapped: () => _buildConfirmationBottomSheet(
leadingCallback: () => _buildConfirmationBottomSheet(
context: context,
onConfirm: () => {
context.pop(),

@ -103,7 +103,7 @@ class _TriageScreenState extends State<TriageScreen> {
// context.pop(),
// }),
onLeadingTapped: () => context.pop(),
leadingCallback: () => context.pop(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

@ -0,0 +1,187 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
class UserInfoSelectionScreen extends StatelessWidget {
const UserInfoSelectionScreen({super.key});
_buildEditInfoTile({
required String leadingIcon,
required String title,
required String subTitle,
required VoidCallback onTap,
required String trailingIcon,
required BuildContext context,
Color? iconColor,
}) {
return InkWell(
onTap: onTap,
child: Row(
children: [
Expanded(
child: Row(
children: [
Container(
height: 40.h,
width: 40.h,
margin: EdgeInsets.only(right: 10.h),
padding: EdgeInsets.all(8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 12.r, color: AppColors.greyColor),
child: Utils.buildSvgWithAssets(icon: leadingIcon, iconColor: iconColor)),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
title.toText16(weight: FontWeight.w500),
subTitle.toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500),
],
),
],
),
),
Utils.buildSvgWithAssets(icon: trailingIcon, height: 24.h, width: 24.h),
],
),
);
}
Widget _getDivider() {
return Divider(
color: AppColors.dividerColor,
).paddingSymmetrical(0, 16.h);
}
@override
Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
String name = "";
if (appState.isAuthenticated) {
name = "${appState.getAuthenticatedUser()!.firstName!} ${appState.getAuthenticatedUser()!.lastName!} ";
} else {
name = "Guest";
}
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(
children: [
Expanded(
child: CollapsingListView(
title: "Symptoms Checker".needTranslation,
isLeading: true,
child: SingleChildScrollView(
child: Column(
children: [
Container(
width: double.infinity,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
padding: EdgeInsets.symmetric(vertical: 24.h, horizontal: 16.w),
child: Column(
children: [
"Hi $name, Is your information up to date?".needTranslation.toText18(
weight: FontWeight.w600,
color: AppColors.textColor,
),
SizedBox(height: 24.h),
_buildEditInfoTile(
context: context,
leadingIcon: AppAssets.genderIcon,
title: "Gender".needTranslation,
subTitle: "Male".needTranslation,
onTap: () {},
trailingIcon: AppAssets.edit_icon,
),
_getDivider(),
_buildEditInfoTile(
context: context,
leadingIcon: AppAssets.calendar,
title: "Age".needTranslation,
subTitle: "32 Years",
iconColor: AppColors.greyTextColor,
onTap: () {},
trailingIcon: AppAssets.edit_icon,
),
_getDivider(),
_buildEditInfoTile(
context: context,
leadingIcon: AppAssets.rulerIcon,
title: "Height".needTranslation,
subTitle: "17 8cm",
onTap: () {},
trailingIcon: AppAssets.edit_icon,
),
_getDivider(),
_buildEditInfoTile(
context: context,
leadingIcon: AppAssets.weightScale,
title: "Weight".needTranslation,
subTitle: "88 kg",
onTap: () {},
trailingIcon: AppAssets.edit_icon,
),
],
),
),
],
).paddingAll(24.w),
),
),
),
_buildBottomCard(context),
],
),
);
}
Widget _buildBottomCard(BuildContext context) {
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
child: SafeArea(
top: false,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 24.h),
Row(
children: [
Expanded(
child: CustomButton(
text: "No, Edit all".needTranslation,
icon: AppAssets.edit_icon,
iconColor: AppColors.primaryRedColor,
onPressed: () => context.navigateWithName(AppRoutes.userInfoFlowManager),
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.11),
borderColor: Colors.transparent,
textColor: AppColors.primaryRedColor,
fontSize: 16.f,
),
),
SizedBox(width: 12.w),
Expanded(
child: CustomButton(
text: "Yes, It is".needTranslation,
icon: AppAssets.tickIcon,
iconColor: AppColors.whiteColor,
onPressed: () => () {},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
),
),
],
),
],
).paddingSymmetrical(24.w, 0),
),
);
}
}

@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:provider/provider.dart';
/// Age selection page content
class AgeSelectionPage extends StatelessWidget {
final int? selectedAge;
final Function(int) onAgeSelected;
const AgeSelectionPage({
super.key,
required this.selectedAge,
required this.onAgeSelected,
});
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: EdgeInsets.all(24.w),
child: Consumer<SymptomsCheckerViewModel>(
builder: (BuildContext context, symptomsViewModel, Widget? child) {
return Column(
children: [
"What is your gender?".needTranslation.toText18(weight: FontWeight.w600, color: AppColors.textColor),
SizedBox(height: 70.h),
"< Age Widget Here >".needTranslation.toText18(weight: FontWeight.w600, color: AppColors.greyTextColor),
],
);
},
),
);
}
}

@ -0,0 +1,75 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:provider/provider.dart';
/// Gender selection page content
class GenderSelectionPage extends StatelessWidget {
final String? selectedGender;
final Function(String) onGenderSelected;
GenderSelectionPage({
super.key,
required this.selectedGender,
required this.onGenderSelected,
});
_buildGenderOption(String iconPng, String label, bool isSelected) {
return Container(
height: 160.h,
width: 160.w,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, borderRadius: 24.r, side: isSelected ? BorderSide(color: AppColors.primaryRedColor, width: 2.5) : null),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Utils.buildImgWithAssets(icon: iconPng, height: 80.h, width: 80.h, fit: BoxFit.contain),
SizedBox(height: 8.h),
label.toText16(
weight: FontWeight.w500,
)
],
),
);
}
final genders = ["Male", "Female"];
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: EdgeInsets.all(24.w),
child: Consumer<SymptomsCheckerViewModel>(
builder: (BuildContext context, symptomsViewModel, Widget? child) {
return Column(
children: [
"What is your gender?".needTranslation.toText18(weight: FontWeight.w600, color: AppColors.textColor),
SizedBox(height: 70.h),
Row(
children: [
Expanded(
child: InkWell(
onTap: () => onGenderSelected(genders[0]),
child: _buildGenderOption(AppAssets.maleIcon, "Male".needTranslation, symptomsViewModel.selectedGender == genders[0]),
),
),
SizedBox(width: 16.w),
Expanded(
child: InkWell(
onTap: () => onGenderSelected(genders[1]),
child: _buildGenderOption(AppAssets.femaleIcon, "Female".needTranslation, symptomsViewModel.selectedGender == genders[1]),
))
],
),
],
);
},
),
);
}
}

@ -0,0 +1,175 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
/// Height selection page content
class HeightSelectionPage extends StatefulWidget {
final double height;
final bool isCm;
final Function(double, bool) onHeightChanged;
const HeightSelectionPage({
super.key,
required this.height,
required this.isCm,
required this.onHeightChanged,
});
@override
State<HeightSelectionPage> createState() => _HeightSelectionPageState();
}
class _HeightSelectionPageState extends State<HeightSelectionPage> {
late double heightValue;
@override
void initState() {
super.initState();
heightValue = widget.height;
}
Widget _unitSelector() {
return Container(
height: 54.h,
padding: EdgeInsets.all(4.h),
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(10.r),
),
child: LayoutBuilder(
builder: (context, constraints) {
final tabWidth = (constraints.maxWidth - 8.w) / 2;
return Stack(
children: [
// Animated sliding indicator
AnimatedContainer(
duration: const Duration(milliseconds: 250),
curve: Curves.easeInOut,
width: tabWidth,
height: constraints.maxHeight,
margin: EdgeInsets.only(left: widget.isCm ? 0 : tabWidth + 8.w),
decoration: BoxDecoration(
color: AppColors.bottomNAVBorder,
borderRadius: BorderRadius.circular(7.r),
),
),
// Tab buttons
Row(
children: [
Expanded(
child: GestureDetector(
onTap: () {
if (!widget.isCm) {
// Convert from FT to CM (1 ft = 30.48 cm)
final convertedHeight = heightValue * 30.48;
widget.onHeightChanged(convertedHeight, true);
}
},
child: Container(
alignment: Alignment.center,
color: Colors.transparent,
child: Text(
'CM',
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 14.f,
color: widget.isCm ? AppColors.textColor : AppColors.textColor.withValues(alpha: 0.6),
),
),
),
),
),
Expanded(
child: GestureDetector(
onTap: () {
if (widget.isCm) {
// Convert from CM to FT (1 cm = 0.0328084 ft)
final convertedHeight = heightValue / 30.48;
widget.onHeightChanged(convertedHeight, false);
}
},
child: Container(
alignment: Alignment.center,
color: Colors.transparent,
child: Text(
'FT',
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 14.f,
color: !widget.isCm ? AppColors.textColor : AppColors.textColor.withValues(alpha: 0.6),
),
),
),
),
),
],
),
],
);
},
),
);
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.h),
Center(
child: Text(
'How tall are you?'.needTranslation,
style: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, color: AppColors.textColor),
),
),
SizedBox(height: 24.h),
Padding(
padding: EdgeInsets.symmetric(horizontal: 24.w),
child: _unitSelector(),
),
SizedBox(height: 90.h),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
heightValue.round().toString(),
style: TextStyle(fontSize: 100.f, color: AppColors.textColor, height: 1),
),
SizedBox(width: 8.w),
Text(widget.isCm ? 'cm' : 'ft', style: TextStyle(fontWeight: FontWeight.w700, fontSize: 24.f)).paddingOnly(bottom: 10.h, left: 8.w),
],
),
],
);
}
}
class _RulerPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paintTick = Paint()..color = const Color(0xFF222222);
final paintSmall = Paint()..color = const Color(0xFF222222).withValues(alpha: 0.6);
final width = size.width;
final start = 120;
final end = 210;
final steps = end - start;
for (int i = 0; i <= steps; i++) {
final x = (i / steps) * width;
if (i % 10 == 0) {
canvas.drawLine(Offset(x, size.height * 0.1), Offset(x, size.height * 0.6), paintTick);
} else if (i % 5 == 0) {
canvas.drawLine(Offset(x, size.height * 0.2), Offset(x, size.height * 0.5), paintSmall);
} else {
canvas.drawLine(Offset(x, size.height * 0.35), Offset(x, size.height * 0.5), paintSmall);
}
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

@ -0,0 +1,236 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
/// Weight selection page content
class WeightSelectionPage extends StatefulWidget {
final double weight;
final bool isKg;
final Function(double, bool) onWeightChanged;
const WeightSelectionPage({
super.key,
required this.weight,
required this.isKg,
required this.onWeightChanged,
});
@override
State<WeightSelectionPage> createState() => _WeightSelectionPageState();
}
class _WeightSelectionPageState extends State<WeightSelectionPage> {
late double weightValue;
@override
void initState() {
super.initState();
weightValue = widget.weight;
}
Widget _unitSelector() {
return Container(
height: 54.h,
padding: EdgeInsets.all(4.h),
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(10.r),
),
child: LayoutBuilder(
builder: (context, constraints) {
final tabWidth = (constraints.maxWidth - 8.w) / 2;
return Stack(
children: [
// Animated sliding indicator
AnimatedContainer(
duration: const Duration(milliseconds: 250),
curve: Curves.easeInOut,
width: tabWidth,
height: constraints.maxHeight,
margin: EdgeInsets.only(left: widget.isKg ? 0 : tabWidth + 8.w),
decoration: BoxDecoration(
color: AppColors.bottomNAVBorder,
borderRadius: BorderRadius.circular(7.r),
),
),
// Tab buttons
Row(
children: [
Expanded(
child: GestureDetector(
onTap: () {
if (!widget.isKg) {
// Convert from LBS to KG (1 lb = 0.453592 kg)
final convertedWeight = weightValue / 2.20462;
widget.onWeightChanged(convertedWeight, true);
}
},
child: Container(
alignment: Alignment.center,
color: Colors.transparent,
child: Text(
'KG',
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 14.f,
color: widget.isKg ? AppColors.textColor : AppColors.textColor.withValues(alpha: 0.6),
),
),
),
),
),
Expanded(
child: GestureDetector(
onTap: () {
if (widget.isKg) {
// Convert from KG to LBS (1 kg = 2.20462 lbs)
final convertedWeight = weightValue * 2.20462;
widget.onWeightChanged(convertedWeight, false);
}
},
child: Container(
alignment: Alignment.center,
color: Colors.transparent,
child: Text(
'LBS',
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 14.f,
color: !widget.isKg ? AppColors.textColor : AppColors.textColor.withValues(alpha: 0.6),
),
),
),
),
),
],
),
],
);
},
),
);
}
Widget _weightSlider() {
return Column(
children: [
SizedBox(height: 18.h),
SizedBox(height: 12.h),
SizedBox(
height: 80.h,
child: Row(
children: [
Expanded(child: Container()),
Expanded(
flex: 6,
child: Stack(
alignment: Alignment.center,
children: [
Positioned.fill(
child: CustomPaint(
painter: _WeightRulerPainter(),
),
),
SliderTheme(
data: SliderTheme.of(context).copyWith(
trackHeight: 6.h,
thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 0),
overlayShape: const RoundSliderOverlayShape(overlayRadius: 0),
activeTrackColor: AppColors.primaryRedColor,
inactiveTrackColor: AppColors.lightRedButtonColor,
),
child: Slider(
min: 30,
max: 150,
value: weightValue,
onChanged: (v) {
setState(() => weightValue = v);
widget.onWeightChanged(v, widget.isKg);
},
),
),
Positioned(
right: 0,
child: Container(
width: 18.w,
height: 18.h,
decoration: BoxDecoration(
color: AppColors.primaryRedColor,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(4.r),
),
),
),
],
),
),
Expanded(child: Container()),
],
),
),
],
);
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.h),
Center(
child: Text(
'What is your weight?'.needTranslation,
style: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, color: AppColors.textColor),
),
),
SizedBox(height: 20.h),
Padding(
padding: EdgeInsets.symmetric(horizontal: 24.w),
child: _unitSelector(),
),
SizedBox(height: 90.h),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
weightValue.round().toString(),
style: TextStyle(fontSize: 100.f, color: AppColors.textColor, height: 1),
),
SizedBox(width: 8.w),
Text(widget.isKg ? 'kg' : 'lbs', style: TextStyle(fontWeight: FontWeight.w700, fontSize: 24.f)).paddingOnly(bottom: 10.h, left: 8.w),
],
),
],
);
}
}
class _WeightRulerPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paintTick = Paint()..color = const Color(0xFF222222);
final paintSmall = Paint()..color = const Color(0xFF222222).withValues(alpha: 0.6);
final width = size.width;
final start = 30;
final end = 150;
final steps = end - start;
for (int i = 0; i <= steps; i++) {
final x = (i / steps) * width;
if (i % 10 == 0) {
canvas.drawLine(Offset(x, size.height * 0.1), Offset(x, size.height * 0.6), paintTick);
} else if (i % 5 == 0) {
canvas.drawLine(Offset(x, size.height * 0.2), Offset(x, size.height * 0.5), paintSmall);
} else {
canvas.drawLine(Offset(x, size.height * 0.35), Offset(x, size.height * 0.5), paintSmall);
}
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

@ -0,0 +1,209 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection/pages/age_selection_page.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection/pages/gender_selection_page.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection/pages/height_selection_page.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection/pages/weight_selection_page.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:provider/provider.dart';
/// Manages the user info selection flow with PageView
/// Only the page content changes, header and footer remain fixed
class UserInfoFlowManager extends StatefulWidget {
const UserInfoFlowManager({super.key});
@override
State<UserInfoFlowManager> createState() => _UserInfoFlowManagerState();
}
class _UserInfoFlowManagerState extends State<UserInfoFlowManager> {
final PageController _pageController = PageController();
late SymptomsCheckerViewModel _viewModel;
// Page titles
final List<String> _pageTitles = [
"Your Gender",
"Your Birth Date",
"Your Height",
"Your Weight",
];
@override
void initState() {
super.initState();
_viewModel = context.read<SymptomsCheckerViewModel>();
// _viewModel.resetUserInfo();
}
@override
void dispose() {
_pageController.dispose();
super.dispose();
}
void _onNext() {
if (_viewModel.userInfoCurrentPage < 3) {
_viewModel.nextUserInfoPage();
_pageController.animateToPage(
_viewModel.userInfoCurrentPage,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
} else {
// Submit and navigate to next screen
_submitUserInfo();
}
}
void _onPrevious() {
if (_viewModel.userInfoCurrentPage > 0) {
_viewModel.previousUserInfoPage();
_pageController.animateToPage(
_viewModel.userInfoCurrentPage,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
} else {
context.pop();
}
}
void _submitUserInfo() {
final userInfo = _viewModel.getUserInfoData();
// Log user info
log('User Info Submitted:');
log('Gender: ${userInfo['gender']}');
log('Age: ${userInfo['age']}');
log('Height: ${userInfo['height']} ${userInfo['heightUnit']}');
log('Weight: ${userInfo['weight']} ${userInfo['weightUnit']}');
// TODO: Save user info to backend/storage
// Navigate to symptoms checker or next screen
context.pop();
}
Widget _buildProgressBar(int currentPage) {
return Row(
children: List.generate(4, (index) {
final isActive = index <= currentPage;
return Expanded(
child: Container(
height: 4.h,
margin: EdgeInsets.symmetric(horizontal: 6.w),
decoration: BoxDecoration(
color: isActive ? AppColors.primaryRedColor : AppColors.greyLightColor,
borderRadius: BorderRadius.circular(8.r),
),
),
);
}),
);
}
Widget _buildStickyBottomCard(bool isLastPage) {
return Container(
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.vertical(top: Radius.circular(24.r)),
),
padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 16.h),
child: SafeArea(
top: false,
child: Row(
children: [
Expanded(
child: CustomButton(
text: "Previous".needTranslation,
onPressed: _onPrevious,
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.11),
borderColor: Colors.transparent,
textColor: AppColors.primaryRedColor,
fontSize: 16.f,
),
),
SizedBox(width: 12.w),
Expanded(
child: CustomButton(
text: isLastPage ? "Submit".needTranslation : "Next".needTranslation,
onPressed: _onNext,
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
),
),
],
),
),
);
}
@override
Widget build(BuildContext context) {
return Consumer<SymptomsCheckerViewModel>(
builder: (context, viewModel, child) {
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(
children: [
Expanded(
child: CollapsingListView(
title: _pageTitles[viewModel.userInfoCurrentPage].needTranslation,
isLeading: true,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.h),
_buildProgressBar(viewModel.userInfoCurrentPage),
SizedBox(height: 24.h),
SizedBox(
height: 600.h,
child: PageView(
controller: _pageController,
physics: const NeverScrollableScrollPhysics(), // Disable swipe
onPageChanged: (index) {
viewModel.setUserInfoPage(index);
},
children: [
GenderSelectionPage(
selectedGender: viewModel.selectedGender,
onGenderSelected: viewModel.setGender,
),
AgeSelectionPage(
selectedAge: viewModel.selectedAge,
onAgeSelected: viewModel.setAge,
),
HeightSelectionPage(
height: viewModel.selectedHeight ?? 178,
isCm: viewModel.isHeightCm,
onHeightChanged: viewModel.setHeight,
),
WeightSelectionPage(
weight: viewModel.selectedWeight ?? 70,
isKg: viewModel.isWeightKg,
onWeightChanged: viewModel.setWeight,
),
],
),
),
],
),
),
),
_buildStickyBottomCard(viewModel.isUserInfoLastPage),
],
),
);
},
);
}
}

@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
/// Progress bar widget showing the current step in user info selection flow
/// Total steps: 4 (Gender -> Age -> Height -> Weight)
class UserInfoProgressBar extends StatelessWidget {
final int currentStep;
final int totalSteps;
const UserInfoProgressBar({
super.key,
required this.currentStep,
this.totalSteps = 4,
});
@override
Widget build(BuildContext context) {
return Row(
children: List.generate(totalSteps, (index) {
final isActive = index < currentStep;
return Expanded(
child: Container(
height: 4.h,
margin: EdgeInsets.symmetric(horizontal: 6.w),
decoration: BoxDecoration(
color: isActive ? AppColors.primaryRedColor : AppColors.greyLightColor,
borderRadius: BorderRadius.circular(8.r),
),
),
);
}),
);
}
}

@ -0,0 +1,67 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection/widgets/user_info_progress_bar.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection/widgets/user_info_sticky_bottom_card.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
/// Base scaffold for user info selection flow pages
/// Provides consistent layout with progress bar and sticky bottom card
class UserInfoSelectionScaffold extends StatelessWidget {
final String title;
final int currentStep;
final Widget child;
final VoidCallback? onPrevious;
final VoidCallback? onNext;
final bool showPrevious;
final String? nextButtonText;
final bool isScrollable;
const UserInfoSelectionScaffold({
super.key,
required this.title,
required this.currentStep,
required this.child,
this.onPrevious,
this.onNext,
this.showPrevious = true,
this.nextButtonText,
this.isScrollable = true,
});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(
children: [
Expanded(
child: CollapsingListView(
title: title,
isLeading: true,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.h),
UserInfoProgressBar(currentStep: currentStep),
SizedBox(height: 24.h),
isScrollable
? SingleChildScrollView(
child: child,
)
: child,
],
),
),
),
UserInfoStickyBottomCard(
onPrevious: onPrevious,
onNext: onNext,
showPrevious: showPrevious,
nextButtonText: nextButtonText,
),
],
),
);
}
}

@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
/// Sticky bottom card with Previous/Next navigation buttons
class UserInfoStickyBottomCard extends StatelessWidget {
final VoidCallback? onPrevious;
final VoidCallback? onNext;
final bool showPrevious;
final String? nextButtonText;
const UserInfoStickyBottomCard({
super.key,
this.onPrevious,
this.onNext,
this.showPrevious = true,
this.nextButtonText,
});
@override
Widget build(BuildContext context) {
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 16.h),
Row(
children: [
if (showPrevious) ...[
Expanded(
child: CustomButton(
text: "Previous".needTranslation,
onPressed: onPrevious ?? () => context.pop(),
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.11),
borderColor: Colors.transparent,
textColor: AppColors.primaryRedColor,
fontSize: 16.f,
),
),
SizedBox(width: 12.w),
],
Expanded(
child: CustomButton(
text: nextButtonText ?? "Next".needTranslation,
onPressed: onNext ?? () {},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
),
),
],
),
SizedBox(height: 24.h),
],
).paddingSymmetrical(24.w, 0),
);
}
}

@ -3,6 +3,7 @@ import 'package:hmg_patient_app_new/presentation/authentication/login.dart';
import 'package:hmg_patient_app_new/presentation/authentication/register.dart';
import 'package:hmg_patient_app_new/presentation/authentication/register_step2.dart';
import 'package:hmg_patient_app_new/presentation/blood_donation/blood_donation_page.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart';
import 'package:hmg_patient_app_new/presentation/comprehensive_checkup/comprehensive_checkup_page.dart';
import 'package:hmg_patient_app_new/presentation/e_referral/new_e_referral.dart';
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
@ -14,6 +15,8 @@ import 'package:hmg_patient_app_new/presentation/symptoms_checker/risk_factors_s
import 'package:hmg_patient_app_new/presentation/symptoms_checker/suggestions_screen.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/symptoms_selector_screen.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/triage_screen.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection/user_info_flow_manager.dart';
import 'package:hmg_patient_app_new/presentation/tele_consultation/zoom/call_screen.dart';
import 'package:hmg_patient_app_new/splashPage.dart';
@ -30,14 +33,21 @@ class AppRoutes {
static const String zoomCallPage = '/zoomCallPage';
static const String bloodDonationPage = '/bloodDonationPage';
//appointments
static const String bookAppointmentPage = '/bookAppointmentPage';
// Symptoms Checker
static const String organSelectorPage = '/organSelectorPage';
static const String symptomsCheckerScreen = '/symptomsCheckerScreen';
static const String symptomsSelectorScreen = '/symptomsCheckerScreen';
static const String suggestionsScreen = '/suggestionsScreen';
static const String riskFactorsScreen = '/riskFactorsScreen';
static const String possibleConditionsScreen = '/possibleConditionsScreen';
static const String triageScreen = '/triageProgressScreen';
//UserInfoSelection
static const String userInfoSelection = '/userInfoSelection';
static const String userInfoFlowManager = '/userInfoFlowManager';
static Map<String, WidgetBuilder> get routes => {
initialRoute: (context) => SplashPage(),
loginScreen: (context) => LoginScreen(),
@ -50,12 +60,16 @@ class AppRoutes {
comprehensiveCheckupPage: (context) => ComprehensiveCheckupPage(),
homeHealthCarePage: (context) => HhcProceduresPage(),
organSelectorPage: (context) => OrganSelectorPage(),
symptomsCheckerScreen: (context) => SymptomsSelectorScreen(),
symptomsSelectorScreen: (context) => SymptomsSelectorScreen(),
riskFactorsScreen: (context) => RiskFactorsScreen(),
suggestionsScreen: (context) => SuggestionsScreen(),
possibleConditionsScreen: (context) => PossibleConditionsScreen(),
triageScreen: (context) => TriageScreen()
zoomCallPage: (context) => CallScreen(),
bloodDonationPage: (context) => BloodDonationPage()
triageScreen: (context) => TriageScreen(),
bloodDonationPage: (context) => BloodDonationPage(),
bookAppointmentPage: (context) => BookAppointmentPage(),
userInfoSelection: (context) => UserInfoSelectionScreen(),
userInfoFlowManager: (context) => UserInfoFlowManager(),
//
};
}

@ -26,7 +26,7 @@ class CollapsingListView extends StatelessWidget {
Widget? trailing;
bool isClose;
bool isLeading;
VoidCallback? onLeadingTapped;
VoidCallback? leadingCallback;
CollapsingListView({
super.key,
@ -42,7 +42,7 @@ class CollapsingListView extends StatelessWidget {
this.requests,
this.isLeading = true,
this.trailing,
this.onLeadingTapped,
this.leadingCallback,
});
@override
@ -69,8 +69,8 @@ class CollapsingListView extends StatelessWidget {
icon: Utils.buildSvgWithAssets(icon: isClose ? AppAssets.closeBottomNav : AppAssets.arrow_back, width: 32.h, height: 32.h),
padding: EdgeInsets.only(left: 12),
onPressed: () {
if (onLeadingTapped != null) {
onLeadingTapped!();
if (leadingCallback != null) {
leadingCallback!();
} else {
context.pop();
}

@ -215,8 +215,11 @@ class TextInputWidget extends StatelessWidget {
language: appState.getLanguageCode()!,
initialDate: DateTime.now(),
fontFamily: appState.getLanguageCode() == "ar" ? "GESSTwo" : "Poppins",
okWidget: Padding(padding: EdgeInsets.only(right: 8.h), child: Utils.buildSvgWithAssets(icon: AppAssets.confirm, width: 24.h, height: 24.h)),
cancelWidget: Padding(padding: EdgeInsets.only(right: 8.h), child: Utils.buildSvgWithAssets(icon: AppAssets.cancel, iconColor: Colors.white, width: 24.h, height: 24.h)),
okWidget:
Padding(padding: EdgeInsets.only(right: 8.h), child: Utils.buildSvgWithAssets(icon: AppAssets.confirm, width: 24.h, height: 24.h)),
cancelWidget: Padding(
padding: EdgeInsets.only(right: 8.h),
child: Utils.buildSvgWithAssets(icon: AppAssets.cancel, iconColor: Colors.white, width: 24.h, height: 24.h)),
onCalendarTypeChanged: (bool value) {
isGregorian = value;
});
@ -276,7 +279,12 @@ class TextInputWidget extends StatelessWidget {
decoration: InputDecoration(
isDense: true,
hintText: hintText,
hintStyle: TextStyle(fontSize: 14.f, height: 21 / 16, fontWeight: FontWeight.w500, color: hintColor != null ? AppColors.textColor : Color(0xff898A8D), letterSpacing: -0.75),
hintStyle: TextStyle(
fontSize: 14.f,
height: 21 / 16,
fontWeight: FontWeight.w500,
color: hintColor != null ? AppColors.textColor : Color(0xff898A8D),
letterSpacing: -0.75),
prefixIconConstraints: BoxConstraints(minWidth: 30.h),
prefixIcon: prefix == null ? null : "+${prefix!}".toText14(letterSpacing: -1, color: AppColors.textColor, weight: FontWeight.w500),
contentPadding: EdgeInsets.zero,

Loading…
Cancel
Save