diff --git a/lib/models/course/education_journey_insert_model.dart b/lib/models/course/education_journey_insert_model.dart new file mode 100644 index 00000000..bda62d45 --- /dev/null +++ b/lib/models/course/education_journey_insert_model.dart @@ -0,0 +1,85 @@ +import 'dart:convert'; + +class PatientEducationJourneyInsert { + String? tokenId; + int? patientId; + int? languageId; + List? data; + + PatientEducationJourneyInsert({ + this.tokenId, + this.patientId, + this.languageId, + this.data, + }); + + factory PatientEducationJourneyInsert.fromRawJson(String str) => PatientEducationJourneyInsert.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory PatientEducationJourneyInsert.fromJson(Map json) => PatientEducationJourneyInsert( + tokenId: json["TokenID"], + patientId: json["PatientID"], + languageId: json["LanguageID"], + data: json["data"] == null ? [] : List.from(json["data"]!.map((x) => Data.fromJson(x))), + ); + + Map toJson() => { + "TokenID": tokenId, + "PatientID": patientId, + "LanguageID": languageId, + "data": data == null ? [] : List.from(data!.map((x) => x.toJson())), + }; +} + +class Data { + String? type; + int? consultationId; + int? contentClassId; + int? topicId; + int? contentId; + int? percentage; + int? flavorId; + String? srcType; + String? screenType; + + Data({ + this.type, + this.consultationId, + this.contentClassId, + this.topicId, + this.contentId, + this.percentage, + this.flavorId, + this.srcType, + this.screenType, + }); + + factory Data.fromRawJson(String str) => Data.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory Data.fromJson(Map json) => Data( + type: json["Type"], + consultationId: json["ConsultationID"], + contentClassId: json["ContentClassId"], + topicId: json["TopicID"], + contentId: json["ContentID"], + percentage: json["Percentage"], + flavorId: json["FlavorId"], + srcType: json["SrcType"], + screenType: json["ScreenType"], + ); + + Map toJson() => { + "Type": type, + "ConsultationID": consultationId, + "ContentClassId": contentClassId, + "TopicID": topicId, + "ContentID": contentId, + "Percentage": percentage, + "FlavorId": flavorId, + "SrcType": srcType, + "ScreenType": screenType, + }; +} diff --git a/lib/pages/learning/course_detailed.dart b/lib/pages/learning/course_detailed.dart index 4feb81de..8ba6ae1a 100644 --- a/lib/pages/learning/course_detailed.dart +++ b/lib/pages/learning/course_detailed.dart @@ -123,7 +123,7 @@ class _CourseDetailedPageState extends State { // "Heart diseases include conditions like coronary and heart failure, often caused by factors ", // style: TextStyle(fontSize: 10.0, height: 15 / 10, color: Color(0xFF575757)), // ), - // SizedBox(height: 6.0), + // SizedBox(height: 6.0), Text( provider.consultation!.stats!.videosCount.toString() + " Videos", style: TextStyle( @@ -271,7 +271,7 @@ class _CourseDetailedPageState extends State { ), ), child: Icon( - content.controller!.value.isPlaying ? Icons.pause : Icons.play_arrow, + getVideoIcon(provider.videoState), size: 18, ).onTap(() { setState(() { diff --git a/lib/pages/learning/course_list.dart b/lib/pages/learning/course_list.dart index 20116105..9332c7ce 100644 --- a/lib/pages/learning/course_list.dart +++ b/lib/pages/learning/course_list.dart @@ -68,7 +68,7 @@ class _CourseListState extends State { ClipRRect( borderRadius: BorderRadius.circular(10), child: CachedNetworkImage( - imageUrl: conClass[index].image!.thumbUrl!, + imageUrl: conClass.first.image!.thumbUrl!, width: double.infinity, height: MediaQuery.of(context).size.height * .25, imageBuilder: (context, imageProvider) => Container( @@ -86,7 +86,7 @@ class _CourseListState extends State { ), SizedBox(height: 20.0), Text( - conClass[index].title ?? "", + conClass.first.title ?? "", // "Basics of Heart", style: TextStyle( fontSize: 16.0, @@ -103,8 +103,8 @@ class _CourseListState extends State { ), SizedBox(height: 6.0), Text( - conClass[index].readPercentage.toString(), - // "2 Hours", + conClass.first.readPercentage.toString() + " Hour Watched", + // "2 Hours", style: TextStyle( fontSize: 10.0, height: 15 / 10, @@ -151,6 +151,7 @@ class _CourseListState extends State { ), ).onTap(() { provider.navigate(context, data.id!, onBack: (val) { + provider.uploadStats(); provider.clear(); }); }); diff --git a/lib/services/course_service/course_service.dart b/lib/services/course_service/course_service.dart index 9cf195b4..778b4dae 100644 --- a/lib/services/course_service/course_service.dart +++ b/lib/services/course_service/course_service.dart @@ -1,12 +1,10 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:developer'; -import 'dart:io'; - import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/models/course/education_journey_insert_model.dart'; import 'package:diplomaticquarterapp/models/course/education_journey_list_model.dart'; import 'package:diplomaticquarterapp/models/course/education_journey_model.dart'; import 'package:diplomaticquarterapp/pages/learning/question_sheet.dart'; @@ -31,6 +29,8 @@ class CourseServiceProvider with ChangeNotifier { List? courseTopics; Consultation? consultation; + List? playedData = []; + //Main Video Controller & Timer VideoPlayerState _videoState = VideoPlayerState.paused; @@ -124,16 +124,20 @@ class CourseServiceProvider with ChangeNotifier { controller?.pause(); setVideoState(VideoPlayerState.paused); } else { + setVideoState(VideoPlayerState.loading); + notifyListeners(); + try { final videoUrl = content.video?.flavor?.downloadable ?? ""; if (videoUrl.isEmpty) { Utils.showErrorToast("No video URL provided."); + setVideoState(VideoPlayerState.paused); return; } controller = VideoPlayerController.networkUrl( Uri.parse(videoUrl), - formatHint: VideoFormat.hls, + //formatHint: VideoFormat.hls, ); await controller!.initialize(); @@ -154,12 +158,14 @@ class CourseServiceProvider with ChangeNotifier { Utils.showErrorToast("Failed to load video."); controller = null; setVideoState(VideoPlayerState.paused); + notifyListeners(); } }); } catch (e) { Utils.showErrorToast("Error loading video: $e"); controller = null; setVideoState(VideoPlayerState.paused); + notifyListeners(); } } } @@ -197,6 +203,38 @@ class CourseServiceProvider with ChangeNotifier { timer = null; } + Future uploadStats() async { + // if(courseTopics != null) { + // Future.forEach(courseTopics!, (topic) { + // Future.forEach(topic.contents!, (content){ + // content.controller + // }); + // }); + // } + + if (courseTopics != null) { + await Future.forEach(courseTopics!, (topic) async { + await Future.forEach(topic.contents!, (content) { + print(content.controller?.value); + playedData!.add(new Data( + type: "content_watch", + consultationId: 2660, + contentClassId: 46, + contentId: 322, + topicId: 6, + percentage: content.controller?.value.position.inSeconds ?? 0, + flavorId: 1, + srcType: "educate-external", + screenType: "journey_screen", + )); + }); + }); + } + print("==============="); + print(playedData.toString()); + print("==============="); + } + // void playVideo(BuildContext context, {required Content content}) async { // print("OnTap"); // if (_videoState == VideoPlayerState.playing) { @@ -280,10 +318,10 @@ class CourseServiceProvider with ChangeNotifier { // timer = null; // } - void onComplete() { - stopTimer(); - setVideoState(VideoPlayerState.completed); - } + // void onComplete() { + // stopTimer(); + // setVideoState(VideoPlayerState.completed); + // } Future clearData() async { data = courseData = nabedJourneyResponse = selectedJourney = courseTopics = consultation = timer = controller = null; @@ -295,8 +333,19 @@ class CourseServiceProvider with ChangeNotifier { } } -enum VideoPlayerState { - playing, - paused, - completed, +enum VideoPlayerState { playing, paused, completed, loading } + +IconData getVideoIcon(VideoPlayerState state) { + switch (state) { + case VideoPlayerState.loading: + return Icons.hourglass_top; + case VideoPlayerState.playing: + return Icons.pause; + case VideoPlayerState.paused: + return Icons.play_arrow; + case VideoPlayerState.completed: + return Icons.replay; + default: + return Icons.play_arrow; + } } diff --git a/lib/uitl/LocalNotification.dart b/lib/uitl/LocalNotification.dart index 0cdef6ca..ead098fe 100644 --- a/lib/uitl/LocalNotification.dart +++ b/lib/uitl/LocalNotification.dart @@ -31,7 +31,7 @@ class LocalNotification { _initialize() async { try { var initializationSettingsAndroid = new AndroidInitializationSettings('app_icon'); - var initializationSettingsIOS = DarwinInitializationSettings(onDidReceiveLocalNotification: null); + var initializationSettingsIOS = DarwinInitializationSettings(); var initializationSettings = InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsIOS); await flutterLocalNotificationsPlugin.initialize( initializationSettings, diff --git a/lib/uitl/penguin_method_channel.dart b/lib/uitl/penguin_method_channel.dart index f2d51573..5e9a2b23 100644 --- a/lib/uitl/penguin_method_channel.dart +++ b/lib/uitl/penguin_method_channel.dart @@ -27,7 +27,7 @@ class PenguinMethodChannel { "clientKey": "UGVuZ3VpbklOX1Blbk5hdl9QSUY=", "mapBoxKey": "sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg", // "clinicID": details?.clinicId ?? "", - "clinicID": details?.clinicId ?? "", // 46 ,49, 133 + "clinicID": details?.clinicId ?? "", // 46 ,49, 133 "patientID": details?.patientId ?? "", "projectID": details?.projectId ?? "", }); @@ -36,14 +36,12 @@ class PenguinMethodChannel { } } - void setMethodCallHandler(){ + void setMethodCallHandler() { _channel.setMethodCallHandler((MethodCall call) async { try { - print(call.method); switch (call.method) { - case PenguinMethodNames.onPenNavInitializationError: _handleInitializationError(call.arguments); // Handle onPenNavInitializationError errors. break; @@ -52,7 +50,7 @@ class PenguinMethodChannel { // _handlePenNavUIDismiss(); // Handle UI dismissal event. break; case PenguinMethodNames.onReportIssue: - // Handle the report issue event. + // Handle the report issue event. _handleInitializationError(call.arguments); break; default: @@ -64,20 +62,19 @@ class PenguinMethodChannel { } }); } + static void _handleUnknownMethod(String method) { print("Unknown method: $method"); // Optionally, handle this unknown method case, such as reporting or ignoring it } - static void _handleInitializationError(Map error) { final type = error['type'] as String?; final description = error['description'] as String?; print("Initialization Error: ${type ?? 'Unknown Type'}, ${description ?? 'No Description'}"); - } - } + // Define constants for method names class PenguinMethodNames { static const String showPenguinUI = 'showPenguinUI'; @@ -88,7 +85,7 @@ class PenguinMethodNames { static const String onPenNavInitializationError = 'onPenNavInitializationError'; // Tested Android,iOS static const String onPenNavUIDismiss = 'onPenNavUIDismiss'; //Tested Android,iOS static const String onReportIssue = 'onReportIssue'; // Tested Android,iOS - static const String onLocationOffCampus = 'onLocationOffCampus'; // Tested iOS,Android + static const String onLocationOffCampus = 'onLocationOffCampus'; // Tested iOS,Android static const String navigateToPOI = 'navigateToPOI'; // Tested Android,iOS }