382 lines
18 KiB
Dart
382 lines
18 KiB
Dart
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<WeatherPage> createState() => _WeatherPageState();
|
|
}
|
|
|
|
class _WeatherPageState extends State<WeatherPage> {
|
|
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<String, dynamic> 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<WeatherForecast> getNextFiveDaysForecast(List<WeatherForecast> allForecasts) {
|
|
List<WeatherForecast> nextFiveDaysForecast = [];
|
|
DateTime today = DateTime.now();
|
|
|
|
List<WeatherForecast> nextDay1All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 1))).day).toList();
|
|
List<WeatherForecast> nextDay2All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 2))).day).toList();
|
|
List<WeatherForecast> nextDay3All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 3))).day).toList();
|
|
List<WeatherForecast> nextDay4All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 4))).day).toList();
|
|
List<WeatherForecast> 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<AppContext>(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 |