Compare commits

..

No commits in common. '467b73ef7f4ece4facad7e2f37508ff80346f95b' and 'a67fafad8ff169bb34d85462b602b3f1ecfe34e8' have entirely different histories.

@ -1839,6 +1839,5 @@
"generateAiAnalysisPrescription": "تحليل الذكاء الاصطناعي", "generateAiAnalysisPrescription": "تحليل الذكاء الاصطناعي",
"loadingAIAnalysisPrescription": "ٍتحليل الوصفات الطبية بواسطة الذكاء الاصطناعي، يرجى الانتظار...", "loadingAIAnalysisPrescription": "ٍتحليل الوصفات الطبية بواسطة الذكاء الاصطناعي، يرجى الانتظار...",
"thisAboveInfoPrescription": "تم تحليل الوصفة الطبية هذه بواسطة الذكاء الاصطناعي، وهي لا تُعدّ نصيحة طبية. استشر طبيبك المختص للتشخيص والعلاج.", "thisAboveInfoPrescription": "تم تحليل الوصفة الطبية هذه بواسطة الذكاء الاصطناعي، وهي لا تُعدّ نصيحة طبية. استشر طبيبك المختص للتشخيص والعلاج.",
"liveCareNotificationPermissionsMessage": "يتطلب لايف كير أذونات الإشعارات، يرجى السماح بهذه الأذونات للمتابعة.", "liveCareNotificationPermissionsMessage": "يتطلب لايف كير أذونات الإشعارات، يرجى السماح بهذه الأذونات للمتابعة."
"weatherIndicators": "طقس"
} }

@ -1829,8 +1829,7 @@
"generateAiAnalysisPrescription": "Generate AI analysis", "generateAiAnalysisPrescription": "Generate AI analysis",
"loadingAIAnalysisPrescription": "Analysing your prescription, let the AI do the magic, This might take some time.", "loadingAIAnalysisPrescription": "Analysing your prescription, let the AI do the magic, This might take some time.",
"thisAboveInfoPrescription": "This prescription was analyzed by AI, and it is not medical advice. Consult your healthcare provider for diagnosis and treatment.", "thisAboveInfoPrescription": "This prescription was analyzed by AI, and it is not medical advice. Consult your healthcare provider for diagnosis and treatment.",
"liveCareNotificationPermissionsMessage": "LiveCare requires Notifications permission, Please allow to proceed.", "liveCareNotificationPermissionsMessage": "LiveCare requires Notifications permission, Please allow to proceed."
"weatherIndicators": "Weather"
} }

@ -234,8 +234,6 @@ class AppAssets {
static const String add_new_family_icon = '$svgBasePath/add_new_family_icon.svg'; static const String add_new_family_icon = '$svgBasePath/add_new_family_icon.svg';
static const String h_calc = '$svgBasePath/h_calc.svg'; static const String h_calc = '$svgBasePath/h_calc.svg';
static const String h_calc_selected = '$svgBasePath/h_calc_selected.svg'; static const String h_calc_selected = '$svgBasePath/h_calc_selected.svg';
static const String weatherBottom = '$svgBasePath/weather_bottom.svg';
static const String weatherBottomFill = '$svgBasePath/weather_bottom_fill.svg';
static const String height = '$svgBasePath/height.svg'; static const String height = '$svgBasePath/height.svg';
static const String weight = '$svgBasePath/weight.svg'; static const String weight = '$svgBasePath/weight.svg';

@ -30,97 +30,60 @@ class WeatherMonitorViewModel extends ChangeNotifier {
isLoading = true; isLoading = true;
notifyListeners(); notifyListeners();
_cityInfoList.clear(); _cityInfoList.clear();
locationUtils.isShowConfirmDialog = true;
// Check if location permission is already granted locationUtils.getLocation(
final isLocationEnabled = await locationUtils.isLocationPermissionEnabled(); isShowConfirmDialog: true,
onFailure: (){
if (isLocationEnabled) {
// Permission already granted, fetch data directly
isLocationAvailable = true;
final result = await weatherRepo.getCityInfo();
result.fold(
(failure) async {
isLoading = false; isLoading = false;
notifyListeners(); notifyListeners();
await errorHandlerService.handleError(failure: failure); showCommonBottomSheetWithoutHeight(
if (onError != null) { title: LocaleKeys.notice.tr(),
onError(failure.toString()); getIt.get<NavigationService>().navigatorKey.currentContext!,
} child: Utils.getWarningWidget(
}, loadingText: LocaleKeys.grantLocationPermission.tr(),
(apiResponse) { isShowActionButtons: true,
isLoading = false; onCancelTap: () {
if (apiResponse.messageStatus == 2) { getIt.get<NavigationService>().pop();
notifyListeners(); },
if (onError != null) { onConfirmTap: () async {
onError(apiResponse.errorMessage ?? "Unknown error"); getIt.get<NavigationService>().pop();
} openAppSettings();
} else if (apiResponse.messageStatus == 1) { }),
final cities = apiResponse.data ?? []; callBackFunc: () {},
_cityInfoList.addAll(cities); isFullScreen: false,
notifyListeners(); isCloseButtonVisible: true,
if (onSuccess != null) { );
onSuccess(apiResponse);
}
}
}, },
); onSuccess: (position) async {
} else { isLocationAvailable = true;
// Permission not granted, request it final result = await weatherRepo.getCityInfo();
locationUtils.isShowConfirmDialog = true; result.fold(
locationUtils.getLocation( (failure) async {
isShowConfirmDialog: true, isLoading = false;
onFailure: (){ notifyListeners();
isLoading = false; await errorHandlerService.handleError(failure: failure);
notifyListeners(); if (onError != null) {
showCommonBottomSheetWithoutHeight( onError(failure.toString());
title: LocaleKeys.notice.tr(), }
getIt.get<NavigationService>().navigatorKey.currentContext!, },
child: Utils.getWarningWidget( (apiResponse) {
loadingText: LocaleKeys.grantLocationPermission.tr(), isLoading = false;
isShowActionButtons: true, if (apiResponse.messageStatus == 2) {
onCancelTap: () {
getIt.get<NavigationService>().pop();
},
onConfirmTap: () async {
getIt.get<NavigationService>().pop();
openAppSettings();
}),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
},
onSuccess: (position) async {
isLocationAvailable = true;
final result = await weatherRepo.getCityInfo();
result.fold(
(failure) async {
isLoading = false;
notifyListeners(); notifyListeners();
await errorHandlerService.handleError(failure: failure);
if (onError != null) { if (onError != null) {
onError(failure.toString()); onError(apiResponse.errorMessage ?? "Unknown error");
} }
}, } else if (apiResponse.messageStatus == 1) {
(apiResponse) { final cities = apiResponse.data ?? [];
isLoading = false; _cityInfoList.addAll(cities);
if (apiResponse.messageStatus == 2) { notifyListeners();
notifyListeners(); if (onSuccess != null) {
if (onError != null) { onSuccess(apiResponse);
onError(apiResponse.errorMessage ?? "Unknown error");
}
} else if (apiResponse.messageStatus == 1) {
final cities = apiResponse.data ?? [];
_cityInfoList.addAll(cities);
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
} }
}, }
); },
}); );
} });
} }
Future<bool> checkIfTheLocationIsEnabledOrNot() async { Future<bool> checkIfTheLocationIsEnabledOrNot() async {

@ -1831,7 +1831,6 @@ abstract class LocaleKeys {
static const generateAiAnalysisPrescription = 'generateAiAnalysisPrescription'; static const generateAiAnalysisPrescription = 'generateAiAnalysisPrescription';
static const loadingAIAnalysisPrescription = 'loadingAIAnalysisPrescription'; static const loadingAIAnalysisPrescription = 'loadingAIAnalysisPrescription';
static const thisAboveInfoPrescription = 'thisAboveInfoPrescription'; static const thisAboveInfoPrescription = 'thisAboveInfoPrescription';
static const weatherIndicators = 'weatherIndicators';
static const liveCareNotificationPermissionsMessage = 'liveCareNotificationPermissionsMessage'; static const liveCareNotificationPermissionsMessage = 'liveCareNotificationPermissionsMessage';
} }

@ -1,23 +1,19 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.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/dependencies.dart';
import 'package:hmg_patient_app_new/core/location_util.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/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/route_extensions.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.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/hmg_services/services_page.dart';
import 'package:hmg_patient_app_new/presentation/home/landing_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/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/presentation/weather/weather_details_page.dart';
import 'package:hmg_patient_app_new/routes/app_routes.dart'; import 'package:hmg_patient_app_new/routes/app_routes.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/bottom_navigation/bottom_navigation.dart'; import 'package:hmg_patient_app_new/widgets/bottom_navigation/bottom_navigation.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:permission_handler/permission_handler.dart' show openAppSettings;
import '../health_calculators_and_converts/health_calculators_page.dart';
class LandingNavigation extends StatefulWidget { class LandingNavigation extends StatefulWidget {
const LandingNavigation({super.key}); const LandingNavigation({super.key});
@ -39,7 +35,7 @@ class _LandingNavigationState extends State<LandingNavigation> {
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
children: [ children: [
const LandingPage(), const LandingPage(),
appState.isAuthenticated ? MedicalFilePage(showBackIcon: false) : const WeatherDetailsPage(showBackIcon: false,), appState.isAuthenticated ? MedicalFilePage(showBackIcon: false) : /* need add feedback page */ HealthCalculatorsPage(type: HealthCalConEnum.calculator),
SizedBox(), SizedBox(),
// const ToDoPage(), // const ToDoPage(),
// appState.isAuthenticated ? UserInfoSelectionScreen() : /* need add news page */ SizedBox(), // appState.isAuthenticated ? UserInfoSelectionScreen() : /* need add news page */ SizedBox(),
@ -49,47 +45,8 @@ class _LandingNavigationState extends State<LandingNavigation> {
), ),
bottomNavigationBar: BottomNavigation( bottomNavigationBar: BottomNavigation(
currentIndex: _currentIndex, currentIndex: _currentIndex,
onTap: (index) async { onTap: (index) {
setState(() => _currentIndex = index); setState(() => _currentIndex = index);
if (_currentIndex == 1 && !appState.isAuthenticated) {
final locationUtils = getIt.get<LocationUtils>();
final isLocationEnabled = await locationUtils.isLocationPermissionEnabled();
if (isLocationEnabled) {
_pageController.animateToPage(index, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut);
} else {
locationUtils.getLocation(
isShowConfirmDialog: true,
onSuccess: (position) {
_pageController.animateToPage(index, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut);
},
onFailure: () {
showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(),
context,
child: Utils.getWarningWidget(
loadingText: LocaleKeys.grantLocationPermission.tr(),
isShowActionButtons: true,
onCancelTap: () {
getIt.get<NavigationService>().pop();
setState(() => _currentIndex = 0);
},
onConfirmTap: () async {
getIt.get<NavigationService>().pop();
openAppSettings();
setState(() => _currentIndex = 0);
},
),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
},
);
}
return;
}
if (_currentIndex == 2) { if (_currentIndex == 2) {
getIt.get<BookAppointmentsViewModel>().onTabChanged(0); getIt.get<BookAppointmentsViewModel>().onTabChanged(0);
getIt.get<MyAppointmentsViewModel>().getPatientFavouriteDoctors(); getIt.get<MyAppointmentsViewModel>().getPatientFavouriteDoctors();

@ -10,29 +10,9 @@ import 'package:hmg_patient_app_new/presentation/hmg_services/widgets/weather_wi
import 'package:hmg_patient_app_new/theme/colors.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/appbar/collapsing_list_view.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shimmer/shimmer.dart';
class WeatherDetailsPage extends StatefulWidget { class WeatherDetailsPage extends StatelessWidget {
final bool showBackIcon; const WeatherDetailsPage({super.key});
const WeatherDetailsPage({super.key, this.showBackIcon = true});
@override
State<WeatherDetailsPage> createState() => _WeatherDetailsPageState();
}
class _WeatherDetailsPageState extends State<WeatherDetailsPage> {
@override
void initState() {
super.initState();
// Fetch weather data when page loads only if data is not already available
WidgetsBinding.instance.addPostFrameCallback((_) {
final weatherVM = Provider.of<WeatherMonitorViewModel>(context, listen: false);
// Only fetch if cityInfoList is empty
if (weatherVM.cityInfoList.isEmpty && !weatherVM.isLoading) {
weatherVM.initiateFetchWeather();
}
});
}
Color _getColorFromColorName(ColorName? colorName) { Color _getColorFromColorName(ColorName? colorName) {
if (colorName == null) return AppColors.successColor; if (colorName == null) return AppColors.successColor;
@ -152,9 +132,13 @@ class _WeatherDetailsPageState extends State<WeatherDetailsPage> {
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView( body: CollapsingListView(
title: LocaleKeys.healthWeatherIndicators.tr(), title: LocaleKeys.healthWeatherIndicators.tr(),
isLeading: widget.showBackIcon, isLeading: true,
child: weatherVM.isLoading child: weatherVM.isLoading
? _buildShimmerLoading() ? Center(
child: CircularProgressIndicator(
color: AppColors.primaryRedColor,
),
)
: Column( : Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -267,164 +251,5 @@ class _WeatherDetailsPageState extends State<WeatherDetailsPage> {
), ),
).paddingSymmetrical(24.w, 0.w); ).paddingSymmetrical(24.w, 0.w);
} }
Widget _buildShimmerLoading() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Weather Widget Shimmer
Shimmer.fromColors(
baseColor: AppColors.shimmerBaseColor,
highlightColor: AppColors.shimmerHighlightColor,
child: Container(
margin: EdgeInsets.symmetric(horizontal: 24.w),
padding: EdgeInsets.all(16.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: false,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 64.w,
height: 64.w,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(12.r),
),
),
SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: double.infinity,
height: 12.h,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(4.r),
),
),
SizedBox(height: 8.h),
Container(
width: 120.w,
height: 16.h,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(4.r),
),
),
SizedBox(height: 8.h),
Container(
width: 160.w,
height: 12.h,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(4.r),
),
),
],
),
),
],
),
SizedBox(height: 16.h),
Container(
width: double.infinity,
height: 40.h,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(10.r),
),
),
],
),
),
),
SizedBox(height: 16.h),
// Shimmer for category cards
...List.generate(3, (index) {
return Shimmer.fromColors(
baseColor: AppColors.shimmerBaseColor,
highlightColor: AppColors.shimmerHighlightColor,
child: Container(
margin: EdgeInsets.only(bottom: 16.h, left: 24.w, right: 24.w),
padding: EdgeInsets.all(16.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 16.r,
hasShadow: false,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 40.w,
height: 40.w,
decoration: BoxDecoration(
color: AppColors.whiteColor,
shape: BoxShape.circle,
),
),
SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: double.infinity,
height: 14.h,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(4.r),
),
),
SizedBox(height: 8.h),
Container(
width: 100.w,
height: 12.h,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(4.r),
),
),
],
),
),
Container(
width: 60.w,
height: 24.h,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(8.r),
),
),
],
),
SizedBox(height: 12.h),
Container(
width: double.infinity,
height: 8.h,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(4.r),
),
),
],
),
),
);
}),
],
);
}
} }

@ -33,7 +33,6 @@ import 'package:hmg_patient_app_new/presentation/tele_consultation/zoom/call_scr
import 'package:hmg_patient_app_new/presentation/vital_sign/vital_sign_page.dart'; import 'package:hmg_patient_app_new/presentation/vital_sign/vital_sign_page.dart';
import 'package:hmg_patient_app_new/presentation/water_monitor/water_consumption_page.dart'; import 'package:hmg_patient_app_new/presentation/water_monitor/water_consumption_page.dart';
import 'package:hmg_patient_app_new/presentation/water_monitor/water_monitor_settings_page.dart'; import 'package:hmg_patient_app_new/presentation/water_monitor/water_monitor_settings_page.dart';
import 'package:hmg_patient_app_new/presentation/weather/weather_details_page.dart';
import 'package:hmg_patient_app_new/splashPage.dart'; import 'package:hmg_patient_app_new/splashPage.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -96,9 +95,6 @@ class AppRoutes {
// Services Price List // Services Price List
static const String servicesPriceListPage = '/servicesPriceListPage'; static const String servicesPriceListPage = '/servicesPriceListPage';
// Weather
static const String weatherDetailsPage = '/weatherDetailsPage';
static Map<String, WidgetBuilder> get routes => { static Map<String, WidgetBuilder> get routes => {
initialRoute: (context) => SplashPage(), initialRoute: (context) => SplashPage(),
loginScreen: (context) => LoginScreen(), loginScreen: (context) => LoginScreen(),
@ -135,7 +131,6 @@ class AppRoutes {
), ),
emergencyServicesPage: (context) => EmergencyServicesPage(), emergencyServicesPage: (context) => EmergencyServicesPage(),
servicesPriceListPage: (context) => ServicesPriceListPage(), servicesPriceListPage: (context) => ServicesPriceListPage(),
weatherDetailsPage: (context) => WeatherDetailsPage(),
addHealthTrackerEntryPage: (context) { addHealthTrackerEntryPage: (context) {
final args = ModalRoute.of(context)?.settings.arguments as HealthTrackerTypeEnum?; final args = ModalRoute.of(context)?.settings.arguments as HealthTrackerTypeEnum?;
return AddHealthTrackerEntryPage( return AddHealthTrackerEntryPage(

@ -23,7 +23,7 @@ class BottomNavigation extends StatelessWidget {
BottomNavItem(icon: AppAssets.homeBottom, fillIcon: AppAssets.homeBottomFill, label: LocaleKeys.home.tr(context: context)), BottomNavItem(icon: AppAssets.homeBottom, fillIcon: AppAssets.homeBottomFill, label: LocaleKeys.home.tr(context: context)),
appState.isAuthenticated appState.isAuthenticated
? BottomNavItem(icon: AppAssets.myFilesBottom, fillIcon: AppAssets.myFilesBottomFill, label: LocaleKeys.medicalFile.tr(context: context)) ? BottomNavItem(icon: AppAssets.myFilesBottom, fillIcon: AppAssets.myFilesBottomFill, label: LocaleKeys.medicalFile.tr(context: context))
: BottomNavItem(icon: AppAssets.weatherBottom, fillIcon: AppAssets.weatherBottomFill, label: LocaleKeys.weatherIndicators.tr(context: context)), : BottomNavItem(icon: AppAssets.h_calc, fillIcon: AppAssets.h_calc_selected, label: LocaleKeys.healthTools.tr()),
BottomNavItem( BottomNavItem(
icon: AppAssets.bookAppoBottom, icon: AppAssets.bookAppoBottom,
fillIcon: AppAssets.bookAppoBottom, fillIcon: AppAssets.bookAppoBottom,

Loading…
Cancel
Save