LCOV - code coverage report
Current view: top level - search/bloc - search_story_bloc.dart (source / functions) Hit Total Coverage
Test: SWE574 - Fall2023 - Group1 - Mobile Test Coverage Lines: 56 60 93.3 %
Date: 2023-12-31 10:28:05 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : import 'dart:async';
       2             : import 'dart:io';
       3             : import 'package:flutter_map/flutter_map.dart';
       4             : import 'package:equatable/equatable.dart';
       5             : import 'package:flutter_bloc/flutter_bloc.dart';
       6             : import 'package:memories_app/routes/home/model/story_model.dart';
       7             : import 'package:memories_app/routes/search/model/search_story_repository.dart';
       8             : import 'package:memories_app/routes/search/model/search_story_request_model.dart';
       9             : import 'package:memories_app/routes/search/model/search_story_response_model.dart';
      10             : 
      11             : part 'search_story_event.dart';
      12             : part 'search_story_state.dart';
      13             : 
      14             : class _Constants {
      15             :   static const String errorMessage =
      16             :       'Error searching stories.\n Please check your request';
      17             :   static const String errorEmptyStories =
      18             :       'Cannot find any stories with your search';
      19             :   static const String offlineMessage =
      20             :       'You are currently offline.\n Please check your internet connection!';
      21             : }
      22             : 
      23             : class SearchStoryBloc extends Bloc<SearchStoryEvent, SearchStoryState> {
      24             :   final SearchStoryRepository _repository;
      25             : 
      26           1 :   SearchStoryBloc({required SearchStoryRepository repository})
      27             :       : _repository = repository,
      28           1 :         super(const SearchStoryState()) {
      29           2 :     on<SearchStoryEventSearchPressed>(_searchStory);
      30           2 :     on<SearchStoryErrorPopupClosedEvent>(_onErrorPopupClosed);
      31             :   }
      32             : 
      33           1 :   Future<void> _searchStory(SearchStoryEventSearchPressed event,
      34             :       Emitter<SearchStoryState> emit) async {
      35           1 :     final SearchStoryRequestModel model = createSearchModel(event);
      36             :     SearchStoryResponseModel? response;
      37             : 
      38             :     try {
      39           2 :       response = await _repository.searchStory(model);
      40           0 :     } on SocketException {
      41           0 :       emit(const SearchStoryOffline(offlineMessage: _Constants.offlineMessage));
      42             :     } catch (error) {
      43           0 :       emit(SearchStoryFailure(error: error.toString()));
      44             :     }
      45             : 
      46             :     if (response != null) {
      47           1 :       if (response.stories != null) {
      48           2 :         if (response.stories!.isNotEmpty) {
      49           3 :           emit(SearchStorySuccess(response.stories));
      50             :         } else {
      51           1 :           emit(const SearchStoryFailure(error: _Constants.errorEmptyStories));
      52             :         }
      53             :       } else {
      54           0 :         emit(const SearchStoryFailure(error: _Constants.errorMessage));
      55             :       }
      56             :     }
      57             :   }
      58             : 
      59           1 :   SearchStoryRequestModel createSearchModel(
      60             :       SearchStoryEventSearchPressed event) {
      61           3 :     final String dateType = mapDateTypeToValue(event.timeType!.toLowerCase());
      62             : 
      63           1 :     return SearchStoryRequestModel(
      64           1 :         title: event.title,
      65           1 :         author: event.author,
      66           1 :         tag: event.tag,
      67           1 :         tagLabel: event.tagLabel,
      68             :         timeType: dateType,
      69           1 :         timeValue: setTimeModel(event),
      70           1 :         location: setLocationModel(event),
      71           1 :         radiusDiff: event.radius,
      72           1 :         dateDiff: event.dateDiff);
      73             :   }
      74             : 
      75           1 :   TimeValue? setTimeModel(SearchStoryEventSearchPressed event) {
      76           2 :     if (event.timeType == "Year") {
      77           1 :       return NormalYear(
      78           2 :           year: event.year ?? "", seasonName: event.seasonName ?? "");
      79             :     }
      80           2 :     if (event.timeType == "Interval Year") {
      81           1 :       return IntervalYear(
      82           1 :           startYear: event.startYear ?? "",
      83           1 :           endYear: event.endYear ?? "",
      84           1 :           seasonName: event.seasonName ?? "");
      85             :     }
      86             : 
      87           2 :     if (event.timeType == "Date") {
      88           2 :       return NormalDate(date: event.date ?? "");
      89             :     }
      90             : 
      91           2 :     if (event.timeType == "Interval Date") {
      92           1 :       return IntervalDate(
      93           2 :           startDate: event.startDate ?? "", endDate: event.endDate ?? "");
      94             :     }
      95             : 
      96           2 :     if (event.timeType == "Decade") {
      97           3 :       return Decade(decade: extractDecade(event.decade) ?? 1900);
      98             :     }
      99             :     return null;
     100             :   }
     101             : 
     102           1 :   Location? setLocationModel(SearchStoryEventSearchPressed event) {
     103           1 :     if (event.marker != null) {
     104           2 :       return Location(coordinates: <double>[
     105           3 :         event.marker!.point.longitude,
     106           3 :         event.marker!.point.latitude
     107             :       ], type: "Point");
     108             :     } else {
     109             :       return null;
     110             :     }
     111             :   }
     112             : 
     113           1 :   int? extractDecade(String? decade) {
     114           1 :     if (decade == null || decade.isEmpty) {
     115             :       return null;
     116             :     }
     117             : 
     118             :     // Remove trailing 's' and parse the remaining part as an integer
     119           3 :     String numericPart = decade.substring(0, decade.length - 1);
     120           1 :     return int.tryParse(numericPart);
     121             :   }
     122             : 
     123           1 :   void _onErrorPopupClosed(
     124             :       SearchStoryErrorPopupClosedEvent event, Emitter<SearchStoryState> emit) {
     125           1 :     emit(const SearchStoryState());
     126             :   }
     127             : 
     128           1 :   String mapDateTypeToValue(String selectedDateType) {
     129           1 :     switch (selectedDateType.toLowerCase()) {
     130           1 :       case "year":
     131             :         return "year";
     132           1 :       case "interval year":
     133             :         return "year_interval";
     134           1 :       case "normal date":
     135             :         return "normal_date";
     136           1 :       case "interval date":
     137             :         return "interval_date";
     138           1 :       case "decade":
     139             :         return "decade";
     140             :       default:
     141             :         return "year";
     142             :     }
     143             :   }
     144             : }

Generated by: LCOV version 1.14