remote localization files added

haroon_dev
haroon amjad 4 hours ago
parent f929bd9017
commit 0eb9ec11d3

@ -0,0 +1,6 @@
<svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="56" height="56" rx="28" fill="white"/>
<rect width="56" height="56" rx="28" fill="white"/>
<rect x="0.5" y="0.5" width="55" height="55" rx="27.5" stroke="#2E3039" stroke-opacity="0.13" stroke-dasharray="2 2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M28 18.25C28.4142 18.25 28.75 18.5858 28.75 19V26.25H36C36.4142 26.25 36.75 26.5858 36.75 27C36.75 27.4142 36.4142 27.75 36 27.75H28.75V35C28.75 35.4142 28.4142 35.75 28 35.75C27.5858 35.75 27.25 35.4142 27.25 35V27.75H20C19.5858 27.75 19.25 27.4142 19.25 27C19.25 26.5858 19.5858 26.25 20 26.25H27.25V19C27.25 18.5858 27.5858 18.25 28 18.25Z" fill="#161616" stroke="#2E3039" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 835 B

@ -1654,5 +1654,8 @@
"twoWaySubtitle": "نقل من الموقع إلى المستشفى والعودة مرة أخرى",
"toHospitalSubtitle": "نقل من موقعك الحالي إلى المستشفى",
"fromHospitalSubtitle": "نقل من المستشفى إلى منزلك",
"clinicSchedule": "جدول العيادة"
"clinicSchedule": "جدول العيادة",
"doctorAddedToFavourite": "تمت إضافة الطبيب إلى قائمة المفضلة",
"doctorRemovedFromFavourite": "تمت إزالة الطبيب من قائمة الأطباء المفضلين",
"addNewFavorite": "إضافة مفضلة جديدة"
}

@ -1646,5 +1646,8 @@
"twoWaySubtitle": "Round trip from location to hospital and back",
"toHospitalSubtitle": "Transfer from your current location to the hospital",
"fromHospitalSubtitle": "Transfer from the hospital back to your home",
"clinicSchedule": "Clinic Schedule"
"clinicSchedule": "Clinic Schedule",
"doctorAddedToFavourite": "Doctor added to favorites list",
"doctorRemovedFromFavourite": "Doctor removed from favorites list",
"addNewFavorite": "Add new favourite"
}

@ -199,8 +199,8 @@ class ApiClientImp implements ApiClient {
body['TokenID'] = "@dm!n";
}
body['TokenID'] = "@dm!n";
body['PatientID'] = 1018977;
// body['TokenID'] = "@dm!n";
// body['PatientID'] = 1018977;
// body['PatientTypeID'] = 1;
// body['PatientOutSA'] = 0;
// body['SessionID'] = "45786230487560q";

@ -233,6 +233,11 @@ class ApiConsts {
static String getAiOverViewLabOrders = "Services/Patients.svc/REST/HMGAI_Lab_Analyze_Orders_API";
static String getAiOverViewLabOrder = "Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API";
static String googleCloudStorageARTranslationFileURL = "https://storage.googleapis.com/hmg-patientapp-translations/ar-SA.json";
static String googleCloudStorageENTranslationFileURL = "https://storage.googleapis.com/hmg-patientapp-translations/en-US.json";
static String googleCloudStorageENTranslationFileBaseURL = "https://storage.googleapis.com/hmg-patientapp-translations";
// ************ static values for Api ****************
static final double appVersionID = 20.9;

@ -220,6 +220,7 @@ class AppAssets {
static const String ibw = '$svgBasePath/ibw.svg';
static const String general_health = '$svgBasePath/general_health.svg';
static const String women_health = '$svgBasePath/women_health.svg';
static const String add_new_family_icon = '$svgBasePath/add_new_family_icon.svg';
static const String height = '$svgBasePath/height.svg';
static const String weight = '$svgBasePath/weight.svg';

@ -630,7 +630,7 @@ class AuthenticationViewModel extends ChangeNotifier {
_appState.setUserBloodGroup = activation.patientBlodType ?? "N/A";
// Fetch patient blood type from new API
await getPatientBloodTypeNew();
// await getPatientBloodTypeNew();
}
// _appState.setUserBloodGroup = (activation.patientBlodType ?? "");
_appState.setAppAuthToken = activation.authenticationTokenId;
@ -722,6 +722,7 @@ class AuthenticationViewModel extends ChangeNotifier {
}
Future<void> navigateToHomeScreen() async {
getPatientBloodTypeNew();
Navigator.pushAndRemoveUntil(
_navigationService.navigatorKey.currentContext!,
CustomPageRoute(
@ -1018,7 +1019,9 @@ class AuthenticationViewModel extends ChangeNotifier {
nationalId: _appState.getAuthenticatedUser()!.patientIdentificationNo,
gender: _appState.getAuthenticatedUser()!.gender)
.toJson());
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
resultEither.fold((failure) async {
// await _errorHandlerService.handleError(failure: failure);
}, (apiResponse) async {
if (apiResponse.messageStatus == 2) {}
if (apiResponse.messageStatus == 1) {
log("Insert Device Data Success");

@ -857,8 +857,8 @@ class BookAppointmentsViewModel extends ChangeNotifier {
}
initialSlotDuration = apiResponse.data["InitialSlotDuration"];
freeSlotsResponse = apiResponse.data['FreeTimeSlots'];
isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"];
// isWaitingAppointmentAvailable = true;
// isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"];
isWaitingAppointmentAvailable = true;
freeSlotsResponse.forEach((element) {
// date = (isLiveCareSchedule != null && isLiveCareSchedule)

@ -0,0 +1,27 @@
import 'dart:convert';
import 'dart:io';
import 'dart:ui';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
class RemoteFileLoader extends AssetLoader {
@override
Future<Map<String, dynamic>?> load(String path, Locale locale) async {
final directory = await getApplicationDocumentsDirectory();
// easy_localization uses toLanguageTag() which gives 'en-US' or 'ar-SA'
final fileName = "${locale.toLanguageTag()}.json";
final file = File("${directory.path}/$fileName");
if (await file.exists()) {
final String jsonString = await file.readAsString();
return jsonDecode(jsonString);
} else {
// If the download failed or hasn't happened yet, load from local assets
// path is the 'path' property from the EasyLocalization widget
final localData = await rootBundle.loadString('$path/$fileName');
return jsonDecode(localData);
}
}
}

@ -0,0 +1,35 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
class TranslationService {
// Replace with your actual hosting URL
static final String baseUrl = ApiConsts.googleCloudStorageENTranslationFileBaseURL;
static Future<void> downloadTranslations() async {
final directory = await getApplicationDocumentsDirectory();
// Ensure these match your locale codes exactly (en-US, ar-SA)
List<String> files = ["en-US.json", "ar-SA.json"];
for (String fileName in files) {
try {
String url = "$baseUrl/$fileName";
debugPrint(url);
// final response = await http.get(Uri.parse("$baseUrl/$fileName"));
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final file = File("${directory.path}/$fileName");
await file.writeAsBytes(response.bodyBytes);
} else {
print("Failed to download $fileName: Status ${response.statusCode}");
}
} catch (e) {
print("Network error while downloading $fileName: $e");
}
}
}
}

@ -1647,5 +1647,8 @@ abstract class LocaleKeys {
static const toHospitalSubtitle = 'toHospitalSubtitle';
static const fromHospitalSubtitle = 'fromHospitalSubtitle';
static const clinicSchedule = 'clinicSchedule';
static const doctorAddedToFavourite = 'doctorAddedToFavourite';
static const doctorRemovedFromFavourite = 'doctorRemovedFromFavourite';
static const addNewFavorite = 'addNewFavorite';
}

@ -41,6 +41,8 @@ import 'package:hmg_patient_app_new/features/services_price_list/services_price_
import 'package:hmg_patient_app_new/features/smartwatch_health_data/health_provider.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/features/todo_section/todo_section_view_model.dart';
import 'package:hmg_patient_app_new/features/translations/custom_asset_loader.dart';
import 'package:hmg_patient_app_new/features/translations/translation_service.dart';
import 'package:hmg_patient_app_new/features/water_monitor/water_monitor_view_model.dart';
import 'package:hmg_patient_app_new/presentation/health_calculators_and_converts/health_calculator_view_model.dart';
import 'package:hmg_patient_app_new/features/health_trackers/health_trackers_view_model.dart';
@ -95,6 +97,9 @@ Future<void> callInitializations() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
// Download the latest JSONs from your server
await TranslationService.downloadTranslations();
// await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
try {
@ -125,6 +130,7 @@ void main() async {
Locale('ar', 'SA'),
],
path: 'assets/langs',
assetLoader: RemoteFileLoader(),
fallbackLocale: Locale('en', 'US'),
child: MultiProvider(providers: <SingleChildWidget>[
ChangeNotifierProvider<LabViewModel>(

@ -255,7 +255,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
height: 110.h,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: 3, // Show 3 shimmer items
itemCount: 3,
// Show 3 shimmer items
shrinkWrap: true,
padding: EdgeInsets.only(left: 24.w, right: 24.w),
itemBuilder: (context, index) {
@ -341,6 +342,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
SizedBox(height: 24.h),
LocaleKeys.favouriteDoctors.tr(context: context).toText18(isBold: true).paddingSymmetrical(24.w, 0.h),
SizedBox(height: 16.h),
Row(
children: [
SizedBox(
height: 110.h,
child: ListView.separated(
@ -407,8 +410,19 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 8.h),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.add_new_family_icon, height: 64.h, width: 64.h),
SizedBox(width: 80.w, child: LocaleKeys.addNewFavorite.tr(context: context).toText12(color: AppColors.textColor, fontWeight: FontWeight.w500, isCenter: true).paddingOnly(top: 4.h)),
],
).onPress(() {
Navigator.of(context).push(CustomPageRoute(page: SearchDoctorByName()));
}),
],
);
),
],
);
}),
],
],

@ -54,11 +54,9 @@ class DoctorProfilePage extends StatelessWidget {
doctorID: viewModel.doctorsProfileResponseModel.doctorID ?? 0,
isActive: viewModel.isFavouriteDoctor,
onSuccess: (response) {
Utils.showToast(viewModel.isFavouriteDoctor ? LocaleKeys.doctorAddedToFavourite.tr(context: context) : LocaleKeys.doctorRemovedFromFavourite.tr(context: context));
// Successfully added/removed favorite - refresh the favorites list
getIt.get<MyAppointmentsViewModel>().refreshFavouriteDoctors();
print(
viewModel.isFavouriteDoctor ? "Doctor added to favorites" : "Doctor removed from favorites",
);
},
onError: (error) {
// Revert the state on error

@ -63,20 +63,20 @@ class WaitingAppointmentOnlineCheckinSheet extends StatelessWidget {
});
}),
SizedBox(height: 16.h),
checkInOptionCard(
AppAssets.checkin_nfc_icon,
LocaleKeys.nfcNearFieldCommunication.tr(),
LocaleKeys.scanPhoneViaNFC.tr(),
).onPress(() {
Future.delayed(const Duration(milliseconds: 500), () {
showNfcReader(context, onNcfScan: (String nfcId) {
Future.delayed(const Duration(milliseconds: 100), () {
checkScannedNFCAndQRCode(nfcId, context);
});
}, onCancel: () {});
});
}),
SizedBox(height: 16.h),
// checkInOptionCard(
// AppAssets.checkin_nfc_icon,
// LocaleKeys.nfcNearFieldCommunication.tr(),
// LocaleKeys.scanPhoneViaNFC.tr(),
// ).onPress(() {
// Future.delayed(const Duration(milliseconds: 500), () {
// showNfcReader(context, onNcfScan: (String nfcId) {
// Future.delayed(const Duration(milliseconds: 100), () {
// checkScannedNFCAndQRCode(nfcId, context);
// });
// }, onCancel: () {});
// });
// }),
// SizedBox(height: 16.h),
checkInOptionCard(
AppAssets.checkin_qr_icon,
LocaleKeys.qrCode.tr(),

@ -65,7 +65,7 @@ class _PrescriptionDetailPageState extends State<PrescriptionDetailPage> {
Expanded(
child: CollapsingListView(
title: LocaleKeys.prescriptions.tr(context: context),
instructions: widget.prescriptionsResponseModel.isInOutPatient!
instructions: widget.prescriptionsResponseModel.isInOutPatient ?? false
? () async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPrescriptionPDFPleaseWait.tr(context: context));
await prescriptionsViewModel.getPrescriptionInstructionsPDF(widget.prescriptionsResponseModel, onSuccess: (val) {
@ -112,8 +112,9 @@ class _PrescriptionDetailPageState extends State<PrescriptionDetailPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppCustomChipWidget(
labelText:
"${getIt.get<AppState>().isArabic() ? widget.prescriptionsResponseModel.isInOutPatientDescriptionN : widget.prescriptionsResponseModel.isInOutPatientDescription}",
labelText: getIt.get<AppState>().isArabic()
? (widget.prescriptionsResponseModel.isInOutPatientDescriptionN ?? "مراجع للعيادات الخارجية")
: (widget.prescriptionsResponseModel.isInOutPatientDescription ?? "OutPatient"),
backgroundColor: AppColors.warningColorYellow.withOpacity(0.1),
textColor: AppColors.warningColorYellow,
),

Loading…
Cancel
Save