import 'dart:convert'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:manager_api_new/api.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Models/weatherData.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; class WeatherPage extends StatefulWidget { final WeatherDTO section; WeatherPage({required this.section}); @override State createState() => _WeatherPageState(); } class _WeatherPageState extends State { WeatherDTO weatherDTO = WeatherDTO(); WeatherData? weatherData = null; int nbrNextHours = 5; @override void initState() { /*print(widget.section!.data); weatherDTO = WeatherDTO.fromJson(jsonDecode(widget.section!.data!))!; print(weatherDTO);*/ weatherDTO = widget.section; if(weatherDTO.result != null) { Map weatherResultInJson = jsonDecode(weatherDTO.result!); weatherData = WeatherData.fromJson(weatherResultInJson); } super.initState(); } String formatTimestamp(int timestamp, AppContext appContext, bool isHourOnly, bool isDateOnly) { DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000); // Determine the date format based on the application language String dateFormat = appContext.getContext().language.toString().toUpperCase() == "EN" ? 'MM/dd/yyyy HH:mm' : 'dd/MM/yyyy HH:mm'; if(isHourOnly) { dateFormat = 'HH:mm'; } if(isDateOnly) { dateFormat = dateFormat.replaceAll('/yyyy HH:mm', ''); } String formattedDate = DateFormat(dateFormat).format(dateTime); return formattedDate; } String getTranslatedDayOfWeek(int timestamp, AppContext appContext, bool isDate) { DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000); String dayToPrint = ""; print("dateTime.weekday"); print(dateTime.weekday); switch(dateTime.weekday) { case 1: dayToPrint = TranslationHelper.getFromLocale("monday", appContext.getContext()); break; case 2: dayToPrint = TranslationHelper.getFromLocale("tuesday", appContext.getContext()); break; case 3: dayToPrint = TranslationHelper.getFromLocale("wednesday", appContext.getContext()); break; case 4: dayToPrint = TranslationHelper.getFromLocale("thursday", appContext.getContext()); break; case 5: dayToPrint = TranslationHelper.getFromLocale("friday", appContext.getContext()); break; case 6: dayToPrint = TranslationHelper.getFromLocale("saturday", appContext.getContext()); break; case 7: dayToPrint = TranslationHelper.getFromLocale("sunday", appContext.getContext()); break; } return isDate ? "${dayToPrint} ${formatTimestamp(timestamp, appContext, false, true)}" : dayToPrint; } List getNextFiveDaysForecast(List allForecasts) { List nextFiveDaysForecast = []; DateTime today = DateTime.now(); List nextDay1All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 1))).day).toList(); List nextDay2All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 2))).day).toList(); List nextDay3All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 3))).day).toList(); List nextDay4All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 4))).day).toList(); List nextDay5All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 5))).day).toList(); var nextDay1MiddayTest = nextDay1All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; if(nextDay1All.isNotEmpty) { WeatherForecast nextDay1AllSummary = nextDay1MiddayTest ?? nextDay1All.last; nextFiveDaysForecast.add(nextDay1AllSummary); } var nextDay2MiddayTest = nextDay2All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; if(nextDay2All.isNotEmpty) { WeatherForecast nextDay2Midday = nextDay2MiddayTest ?? nextDay2All.last; nextFiveDaysForecast.add(nextDay2Midday); } var nextDay3MiddayTest = nextDay3All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; if(nextDay3All.isNotEmpty) { WeatherForecast nextDay3Midday = nextDay3MiddayTest ?? nextDay3All.last; nextFiveDaysForecast.add(nextDay3Midday); } var nextDay4MiddayTest = nextDay4All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; if(nextDay4All.isNotEmpty) { WeatherForecast nextDay4Midday = nextDay4MiddayTest ?? nextDay4All.last; nextFiveDaysForecast.add(nextDay4Midday); } var nextDay5MiddayTest = nextDay5All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; if(nextDay5All.isNotEmpty) { WeatherForecast nextDay5Midday = nextDay5MiddayTest ?? nextDay5All.last; nextFiveDaysForecast.add(nextDay5Midday); } return nextFiveDaysForecast; } @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; final appContext = Provider.of(context); VisitAppContext visitAppContext = appContext.getContext(); var primaryColor = visitAppContext.configuration != null ? visitAppContext.configuration!.primaryColor != null ? Color(int.parse(visitAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)) : kSecondColor : kSecondColor; return Stack( children: [ weatherData == null ? const Center(child: Text("Aucune donnée à afficher")) : Container( // TODO translate ? decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), gradient: LinearGradient( begin: Alignment.topRight, end: Alignment.bottomLeft, stops: const [ 0.2, 0.5, 0.9, 0.95 ], colors: [ Colors.blue[50]!, Colors.blue[100]!, Colors.blue[200]!, Colors.blue[300]! ] ) ), //color: Colors.yellow, //height: 300, //width: 300, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.all(10.0), child: Center(child: Text(weatherDTO.city!, style: const TextStyle(fontSize: kSectionTitleDetailSize, fontWeight: FontWeight.w500, color: Colors.black54, fontFamily: "Roboto"))), ), Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.all(8.0), child: Text("${weatherData!.list!.first.main!.temp!.round().toString()}°", style: const TextStyle(fontSize: 55.0, fontWeight: FontWeight.w400, color: Colors.black54, fontFamily: "Roboto")), ), Container( //color: Colors.green, height: size.height * 0.2, width: size.width * 0.45, constraints: BoxConstraints(minWidth: 80), child: Center( child: CachedNetworkImage(imageUrl: "https://openweathermap.org/img/wn/${weatherData!.list!.first.weather!.first.icon!}@4x.png") ) ), Container( // color: Colors.green, width: size.width * 0.2, //color: Colors.red, constraints: BoxConstraints(minWidth: 100), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ const Icon(Icons.water_drop_outlined, color: kSecondColor), Text("${weatherData!.list!.first.pop!.round().toString()}%", style: const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w400, color: Colors.black54, fontFamily: "Roboto")), ], ), ), Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ const Icon(Icons.air, color: kSecondColor), Text("${(weatherData!.list!.first.wind!.speed! * 3.6).toStringAsFixed(1)}km/h", style: const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w400, color: Colors.black54, fontFamily: "Roboto")), ], ), ), ], ), ), ]), Container( height: size.height * 0.25, width: size.width, /*decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), //color: Colors.grey, ),*/ child: Column( children: [ Padding( padding: const EdgeInsets.only(left: 15, bottom: 10), child: Align(alignment: Alignment.centerLeft, child: Text(TranslationHelper.getFromLocale("weather.hourly", appContext.getContext()), style: const TextStyle(fontSize: 22, fontWeight: FontWeight.w400, color: Colors.black54, fontFamily: "Roboto"))), ), Container( height: size.height * 0.18, width: size.width, //color: Colors.lightGreen, child: ListView( scrollDirection: Axis.horizontal, children: List.generate( nbrNextHours, (index) { final weatherForecast = weatherData!.list!.sublist(1)[index]; return Padding( padding: const EdgeInsets.all(8.0), child: Container( height: size.height * 0.15, width: size.width * 0.25, constraints: const BoxConstraints(minWidth: 125, maxWidth: 250), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), color: Colors.lightBlueAccent, boxShadow: [ BoxShadow( color: kBackgroundGrey.withValues(alpha: 0.6), spreadRadius: 0.75, blurRadius: 3.1, offset: Offset(0, 2.5), // changes position of shadow ), ], ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text(formatTimestamp(weatherForecast.dt!, appContext, true, false), style: const TextStyle(fontSize: 12.0, fontWeight: FontWeight.w400, color: Colors.white, fontFamily: "Roboto")), Center(child: CachedNetworkImage(imageUrl: "https://openweathermap.org/img/wn/${weatherForecast.weather!.first.icon!}.png")), Text('${weatherForecast.main!.temp!.round().toString()}°', style: const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w600, color: Colors.white, fontFamily: "Roboto")), ], ), ), ); }, ), ), ), ], ), ), Padding( padding: const EdgeInsets.all(0.0), child: Container( height: size.height * 0.3, width: size.width, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), //color: Colors.amber, ), child: Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: Align(alignment: Alignment.centerLeft, child: Text(TranslationHelper.getFromLocale("weather.nextdays", appContext.getContext()), style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w400, color: Colors.black54, fontFamily: "Roboto"))), ), Container( height: size.height * 0.23, width: size.width, //color: Colors.lightGreen, child: ListView( scrollDirection: Axis.horizontal, children:List.generate( getNextFiveDaysForecast(weatherData!.list!).length, // nbrNextHours (index) { final weatherForecastNextDay = getNextFiveDaysForecast(weatherData!.list!)[index]; return Padding( padding: const EdgeInsets.all(8.0), child: Container( height: size.height * 0.22, width: size.width * 0.125, constraints: const BoxConstraints(minWidth: 150, maxWidth: 250), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), color: Colors.lightBlue, boxShadow: [ BoxShadow( color: kBackgroundGrey.withValues(alpha: 0.5), spreadRadius: 0.75, blurRadius: 3.1, offset: const Offset(0, 2.5), // changes position of shadow ), ], ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.center, children: [ Center(child: CachedNetworkImage(imageUrl: "https://openweathermap.org/img/wn/${weatherForecastNextDay.weather!.first.icon!}@2x.png")), Text('${weatherForecastNextDay.main!.temp!.round().toString()}°', style: const TextStyle(fontSize: 25.0, fontWeight: FontWeight.w600, color: Colors.white, fontFamily: "Roboto")), Text(getTranslatedDayOfWeek(weatherForecastNextDay.dt!, appContext, true), style: const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w400, color: Colors.white, fontFamily: "Roboto")), ], ), ), ); }, ), ), ), ], ), ), ) ], ), ), Positioned( top: 35, left: 10, child: SizedBox( width: 50, height: 50, child: InkWell( onTap: () { Navigator.of(context).pop(); }, child: Container( decoration: BoxDecoration( color: primaryColor, shape: BoxShape.circle, ), child: const Icon(Icons.arrow_back, size: 23, color: Colors.white) ), ) ), ), ], ); } } //_webView