diff --git a/lib/presentation/cubit/weather_forecast_cubit_cubit.dart b/lib/presentation/cubit/weather_forecast_cubit_cubit.dart index cafa765..40a259c 100644 --- a/lib/presentation/cubit/weather_forecast_cubit_cubit.dart +++ b/lib/presentation/cubit/weather_forecast_cubit_cubit.dart @@ -1,4 +1,5 @@ import 'package:bloc/bloc.dart'; +import 'package:intl/intl.dart'; import 'package:meta/meta.dart'; import 'package:weather_app/domain/model/forecast_responce.dart'; import 'package:weather_app/domain/api/weather_service.dart'; @@ -13,13 +14,43 @@ class WeatherForecastCubitCubit extends Cubit { ForecastResponse forecastResponse = await WeatherApi().fetchWeatherForecast('Nairobi'); if (forecastResponse.list.isNotEmpty) { - final temperature = forecastResponse.list.first.main.temp; - final weather = forecastResponse.list.first.weather.first.main.name; + List dataToBeReturned = []; + Map mappedResponse = { for (var item in forecastResponse.list) item.dtTxt : item }; + + final currentDate = DateTime.now(); + //final formattedCurrentDate = _getFormattedDate(currentDate); + final formattedCurrentHour = _getFormattedHour(currentDate); + int hourOfWeatherToBeDisplayed = 0; + + final listOfHours = [0, 3, 6, 9, 12, 15, 18, 21, 24]; + for (int h in listOfHours) { + if(h - int.parse(formattedCurrentHour) > 0 && h - int.parse(formattedCurrentHour) < 3) { + hourOfWeatherToBeDisplayed = h; + } + } + + mappedResponse.forEach((key, value) { + if(key.hour == hourOfWeatherToBeDisplayed) { + print(key); + dataToBeReturned.add(value); + } + }); + + final temperature = dataToBeReturned.first.main.temp; + final weather = dataToBeReturned.first.weather.first; + final tempCurrent = dataToBeReturned.first.main.temp; + final tempMin = dataToBeReturned.first.main.tempMin; + final tempMax = dataToBeReturned.first.main.tempMax; emit(WeatherForecastCubitSuccess( + tempCurrent: tempCurrent, + tempMin: tempMin, + tempMax: tempMax, forecastRes: forecastResponse, temperature: temperature, + weatherList: dataToBeReturned.sublist(0, dataToBeReturned.length), weather: weather)); + } else { emit(WeatherForecastCubitFail(error: "Weather not found")); } @@ -27,4 +58,6 @@ class WeatherForecastCubitCubit extends Cubit { emit(WeatherForecastCubitFail(error: e.toString())); } } + + String _getFormattedHour(DateTime date) => DateFormat.H().format(date); } diff --git a/lib/presentation/cubit/weather_forecast_cubit_state.dart b/lib/presentation/cubit/weather_forecast_cubit_state.dart index cb5a73b..d5f33a3 100644 --- a/lib/presentation/cubit/weather_forecast_cubit_state.dart +++ b/lib/presentation/cubit/weather_forecast_cubit_state.dart @@ -10,10 +10,20 @@ final class WeatherForecastCubitLoading extends WeatherForecastCubitState {} final class WeatherForecastCubitSuccess extends WeatherForecastCubitState { final ForecastResponse forecastRes; final double temperature; - final String weather; + final Weather weather; + final double tempCurrent; + final double tempMin; + final double tempMax; + final List weatherList; - WeatherForecastCubitSuccess( - {required this.forecastRes, required this.temperature, required this.weather,}); + WeatherForecastCubitSuccess({required this.forecastRes, + required this.temperature, + required this.weather, + required this.weatherList, + required this.tempCurrent, + required this.tempMax, + required this.tempMin + }); } final class WeatherForecastCubitFail extends WeatherForecastCubitState { diff --git a/lib/presentation/views/days_weather_view.dart b/lib/presentation/views/days_weather_view.dart index 3601e7a..ea0b154 100644 --- a/lib/presentation/views/days_weather_view.dart +++ b/lib/presentation/views/days_weather_view.dart @@ -1,64 +1,28 @@ import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:weather_app/domain/model/forecast_responce.dart'; +import 'package:weather_app/presentation/cubit/weather_forecast_cubit_cubit.dart'; import 'package:weather_app/presentation/views/weather_home_view.dart'; class DaysWeatherView extends StatelessWidget { - const DaysWeatherView({super.key}); + final WeatherForecastCubitSuccess weatherForecastCubitSuccess; + const DaysWeatherView({super.key, required this.weatherForecastCubitSuccess}); @override Widget build(BuildContext context) { return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ // title - const Row( - children: [ - // min - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - "10°", - style: TextStyle(color: Colors.white), - ), - Text( - "min", - style: TextStyle(color: Colors.white), - ), - ], - )), - //curent - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - "19°", - style: TextStyle(color: Colors.white), - ), - Text( - "current", - style: TextStyle(color: Colors.white), - ), - ], - )), - // max - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - "19°", - style: TextStyle(color: Colors.white), - ), - Text( - "max", - style: TextStyle(color: Colors.white), - ), - ], - )) - ], - ), - const Divider(color: Colors.white), - ...[ + ...weatherForecastCubitSuccess.weatherList.map((weatherData) { + return _weatherListTile( + DayWeather( + day: DateFormat.E().format(weatherData.dtTxt), + weather: weatherData.weather.first.main, + temperature: weatherData.main.temp + ) + ); + }).toList(), + /*...[ DayWeather(day: "Monday", temperature: 23), DayWeather(day: "Tuesday", temperature: 23), DayWeather(day: "Wednesday", temperature: 23), @@ -92,8 +56,35 @@ class DaysWeatherView extends StatelessWidget { ), ), ) - .toList(), + .toList(),*/ ], ); } +} + +Widget _weatherListTile(final DayWeather dayWeather) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Expanded( + child: Text( + dayWeather.day, + style: const TextStyle(color: Colors.white), + )), + Expanded( + flex: 2, + child: Icon( + dayWeather.weather == MainEnum.CLEAR ? Icons.sunny : dayWeather.weather == MainEnum.RAIN ? Icons.shower : Icons.cloud, + color: Colors.white, + ), + ), + const SizedBox(width: 60), + Text( + "${dayWeather.temperature.toStringAsFixed(2)}°", + style: const TextStyle(color: Colors.white), + ), + ], + ), + ); } \ No newline at end of file diff --git a/lib/presentation/views/image_widget.dart b/lib/presentation/views/image_widget.dart index 10b8dc6..a28cf29 100644 --- a/lib/presentation/views/image_widget.dart +++ b/lib/presentation/views/image_widget.dart @@ -2,16 +2,13 @@ import 'package:flutter/material.dart'; import 'package:weather_app/domain/model/forecast_responce.dart'; +import 'package:weather_app/presentation/cubit/weather_forecast_cubit_cubit.dart'; class ImageWidget extends StatelessWidget { - final ForecastResponse response; - final String weather; - final double temperature; + final WeatherForecastCubitSuccess weatherForecastCubitSuccess; const ImageWidget( {super.key, - required this.response, - required this.weather, - required this.temperature}); + required this.weatherForecastCubitSuccess}); @override Widget build(BuildContext context) { @@ -20,33 +17,95 @@ class ImageWidget extends StatelessWidget { width: MediaQuery.of(context).size.width, decoration: BoxDecoration( image: DecorationImage( - image: AssetImage(response.list[0].weather[0].main == "Clouds" - ? 'assets/images/forest_sunny.png' - : response.list[0].weather[0].main == "Rainy" - ? 'assets/images/forest_rainy.png' - : 'assets/images/forest_cloudy.png'), + image: AssetImage(_getWeatherBanner(weatherForecastCubitSuccess.weather.main)), fit: BoxFit.fitHeight), ), child: Column( - mainAxisSize: MainAxisSize.min, + //mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ + const Spacer(), Text( - temperature.toString(), + weatherForecastCubitSuccess.temperature.toString(), style: const TextStyle( fontSize: 60, fontWeight: FontWeight.bold, color: Colors.white), ), Text( - weather, + weatherForecastCubitSuccess.weather.main.name, style: const TextStyle( fontSize: 32, fontWeight: FontWeight.normal, color: Colors.white), ), + const Spacer(), + /// + Row( + children: [ + // min + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "${weatherForecastCubitSuccess.tempMin}°", + style: const TextStyle(color: Colors.white), + ), + const Text( + "min", + style: TextStyle(color: Colors.white), + ), + ], + )), + //curent + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "${weatherForecastCubitSuccess.tempCurrent}°", + style: const TextStyle(color: Colors.white), + ), + const Text( + "current", + style: TextStyle(color: Colors.white), + ), + ], + )), + // max + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "${weatherForecastCubitSuccess.tempMax}°", + style: const TextStyle(color: Colors.white), + ), + const Text( + "max", + style: TextStyle(color: Colors.white), + ), + ], + )) + ], + ), + const Divider(color: Colors.white), // Text(state.forecastResponce.city.name), ], ), ); } +} + +String _getWeatherBanner(MainEnum weatherType) { + switch(weatherType) { + case MainEnum.CLOUDS: + return "assets/images/forest_cloudy.png"; + case MainEnum.RAIN: + return "assets/images/forest_rainy.png"; + case MainEnum.CLEAR: + return "assets/images/forest_sunny.png"; + default: + return ""; + } } \ No newline at end of file diff --git a/lib/presentation/views/weather_home_view.dart b/lib/presentation/views/weather_home_view.dart index 2e1eacf..bd93e0f 100644 --- a/lib/presentation/views/weather_home_view.dart +++ b/lib/presentation/views/weather_home_view.dart @@ -1,6 +1,7 @@ // ignore_for_file: unrelated_type_equality_checks import 'package:flutter/material.dart'; +import 'package:weather_app/domain/model/forecast_responce.dart'; import 'package:weather_app/presentation/views/days_weather_view.dart'; import 'package:weather_app/presentation/views/image_widget.dart'; import 'package:weather_app/presentation/widgets/consts/theme.dart'; @@ -33,11 +34,11 @@ class _RainyView extends State { children: [ // Text(state.forecastRes.city.name), ImageWidget( - response: state.forecastRes, - weather: state.weather, - temperature: state.temperature, + weatherForecastCubitSuccess: state, ), - const Expanded(child: DaysWeatherView()) + Expanded(child: DaysWeatherView( + weatherForecastCubitSuccess: state + )) ], ); } else { @@ -53,9 +54,10 @@ class _RainyView extends State { class DayWeather { final String day; final num temperature; + final MainEnum weather; DayWeather({ required this.day, - required this.temperature, + required this.temperature, required this.weather, }); } diff --git a/pubspec.lock b/pubspec.lock index cd32b56..998f2b5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -168,6 +168,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + intl: + dependency: "direct main" + description: + name: intl + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + url: "https://pub.dev" + source: hosted + version: "0.18.1" js: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 0299d55..4669d72 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,6 +17,7 @@ dependencies: bloc: ^8.1.2 meta: ^1.9.1 geolocator: ^10.1.0 + intl: ^0.18.1 dev_dependencies: flutter_test: