Fix agenda + weather finetuning

This commit is contained in:
Thomas Fransolet 2024-02-28 12:01:56 +01:00
parent 0559600efc
commit 9eaad8b0cf
8 changed files with 114 additions and 76 deletions

View File

@ -3,42 +3,52 @@ import 'package:tablet_app/Models/translation.dart';
List<Translation> translations = [ List<Translation> translations = [
Translation(language: "FR", data: { Translation(language: "FR", data: {
"weather.hourly": "Prochaines heures", "weather.hourly": "Prochaines heures",
"weather.nextdays": "Prochains jours" "weather.nextdays": "Prochains jours",
"agenda.all": "Tout"
}), }),
Translation(language: "EN", data: { Translation(language: "EN", data: {
"weather.hourly": "Hourly", "weather.hourly": "Hourly",
"weather.nextdays": "Next days" "weather.nextdays": "Next days",
"agenda.all": "All"
}), }),
Translation(language: "DE", data: { Translation(language: "DE", data: {
"weather.hourly": "Nächste Stunden", "weather.hourly": "Nächste Stunden",
"weather.nextdays": "Nächsten Tage" "weather.nextdays": "Nächsten Tage",
"agenda.all": "Alle"
}), }),
Translation(language: "NL", data: { Translation(language: "NL", data: {
"weather.hourly": "Volgende uren", "weather.hourly": "Volgende uren",
"weather.nextdays": "Volgende dagen" "weather.nextdays": "Volgende dagen",
"agenda.all": "Alle"
}), }),
Translation(language: "IT", data: { Translation(language: "IT", data: {
"weather.hourly": "Le prossime ore", "weather.hourly": "Le prossime ore",
"weather.nextdays": "Prossimi giorni" "weather.nextdays": "Prossimi giorni",
"agenda.all": "Tutto"
}), }),
Translation(language: "ES", data: { Translation(language: "ES", data: {
"weather.hourly": "Próximas horas", "weather.hourly": "Próximas horas",
"weather.nextdays": "Proximos dias" "weather.nextdays": "Proximos dias",
"agenda.all": "Todo"
}), }),
Translation(language: "PL", data: { Translation(language: "PL", data: {
"weather.hourly": "Następne godziny", "weather.hourly": "Następne godziny",
"weather.nextdays": "Następne dni" "weather.nextdays": "Następne dni",
"agenda.all": "Wszystko"
}), }),
Translation(language: "CN", data: { Translation(language: "CN", data: {
"weather.hourly": "接下来的几个小时", "weather.hourly": "接下来的几个小时",
"weather.nextdays": "未来几天" "weather.nextdays": "未来几天",
"agenda.all": "全部"
}), }),
Translation(language: "UK", data: { Translation(language: "UK", data: {
"weather.hourly": "Наступні години", "weather.hourly": "Наступні години",
"weather.nextdays": "Наступні дні" "weather.nextdays": "Наступні дні",
"agenda.all": "все"
}), }),
Translation(language: "AR", data: { Translation(language: "AR", data: {
"weather.hourly": "الساعات القادمة", "weather.hourly": "الساعات القادمة",
"weather.nextdays": "الايام القادمة" "weather.nextdays": "الايام القادمة",
"agenda.all": "الجميع"
}), }),
]; ];

View File

@ -8,11 +8,14 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:tablet_app/Components/loading_common.dart'; import 'package:tablet_app/Components/loading_common.dart';
import 'package:tablet_app/Models/agenda.dart'; import 'package:tablet_app/Models/agenda.dart';
import 'package:tablet_app/Models/tabletContext.dart';
import 'package:tablet_app/Screens/Agenda/event_list_item.dart'; import 'package:tablet_app/Screens/Agenda/event_list_item.dart';
import 'package:tablet_app/Screens/Agenda/event_popup.dart'; import 'package:tablet_app/Screens/Agenda/event_popup.dart';
import 'package:tablet_app/Screens/Agenda/month_filter.dart'; import 'package:tablet_app/Screens/Agenda/month_filter.dart';
import 'package:tablet_app/app_context.dart';
import 'package:tablet_app/constants.dart'; import 'package:tablet_app/constants.dart';
@ -42,11 +45,16 @@ class _AgendaView extends State<AgendaView> {
super.dispose(); super.dispose();
} }
Future<Agenda?> getAndParseJsonInfo() async { Future<Agenda?> getAndParseJsonInfo(TabletAppContext tabletAppContext) async {
try { try {
// Récupération du contenu JSON depuis l'URL // Récupération du contenu JSON depuis l'URL
var httpClient = HttpClient(); var httpClient = HttpClient();
var request = await httpClient.getUrl(Uri.parse(agendaDTO.resourceUrl!));
// We need to get detail to get url from resourceId
var resourceIdForSelectedLanguage = agendaDTO.resourceIds!.where((ri) => ri.language == tabletAppContext.language).first.value;
ResourceDTO? resourceDTO = await tabletAppContext.clientAPI!.resourceApi!.resourceGetDetail(resourceIdForSelectedLanguage!);
var request = await httpClient.getUrl(Uri.parse(resourceDTO!.url!));
var response = await request.close(); var response = await request.close();
var jsonString = await response.transform(utf8.decoder).join(); var jsonString = await response.transform(utf8.decoder).join();
@ -64,8 +72,9 @@ class _AgendaView extends State<AgendaView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size; Size size = MediaQuery.of(context).size;
final TabletAppContext tabletAppContext = Provider.of<AppContext>(context).getContext();
return FutureBuilder(future: getAndParseJsonInfo(), return FutureBuilder(future: getAndParseJsonInfo(tabletAppContext),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) { builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.done) { if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data == null) { if (snapshot.data == null) {
@ -93,7 +102,7 @@ class _AgendaView extends State<AgendaView> {
events: snapshot.data.events, events: snapshot.data.events,
onMonthSelected: (filteredList) { onMonthSelected: (filteredList) {
print('events sélectionné: $filteredList'); print('events sélectionné: $filteredList');
var result = filteredList!; var result = filteredList != null ? filteredList : <EventAgenda>[];
result.sort((a, b) => a.dateFrom!.compareTo(b.dateFrom!)); result.sort((a, b) => a.dateFrom!.compareTo(b.dateFrom!));
filteredAgenda.value = result; filteredAgenda.value = result;
}), }),

View File

@ -1,5 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tablet_app/Helpers/translationHelper.dart';
import 'package:tablet_app/Models/agenda.dart'; import 'package:tablet_app/Models/agenda.dart';
import 'package:tablet_app/app_context.dart';
import 'package:tablet_app/constants.dart'; import 'package:tablet_app/constants.dart';
class MonthFilter extends StatefulWidget { class MonthFilter extends StatefulWidget {
@ -25,24 +28,29 @@ class _MonthFilterState extends State<MonthFilter> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<Map<String, dynamic>> sortedMonths = _getSortedMonths(); List<Map<String, dynamic>> sortedMonths = _getSortedMonths();
final appContext = Provider.of<AppContext>(context);
return ListView.builder( return ListView.builder(
itemCount: sortedMonths.length + 1, // +1 for "Tout (nbr total events)" itemCount: sortedMonths.length + 1, // +1 for "Tout (nbr total events)"
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (index == 0) { if (index == 0) {
return _buildAllItem(); return _buildAllItem(appContext);
} else { } else {
final monthYear = sortedMonths[index - 1]['monthYear']; final monthYear = sortedMonths[index - 1]['monthYear'];
List<EventAgenda>? filteredEvents = _filterEvents(monthYear); List<EventAgenda>? filteredEvents = _filterEvents(monthYear);
var nbrEvents = filteredEvents == null ? 0 : filteredEvents.length;
// Vérifier si nbrEvents est supérieur à 0
if (nbrEvents > 0) {
String monthName = _getTranslatedMonthName(monthYear); String monthName = _getTranslatedMonthName(monthYear);
RegExp regExp = RegExp(r'\d{4}'); RegExp regExp = RegExp(r'\d{4}');
String annee = regExp.stringMatch(monthYear)!; String annee = regExp.stringMatch(monthYear)!;
return ListTile( return ListTile(
title: Text( title: Text(
'$monthName $annee (${filteredEvents!.length})', '$monthName $annee (${nbrEvents})',
style: TextStyle( style: TextStyle(
fontSize: 16.0, fontSize: 16.0,
fontWeight: _selectedMonth == monthYear ? FontWeight.bold : FontWeight.normal, fontWeight: _selectedMonth == monthYear ? FontWeight.bold : FontWeight.normal,
@ -57,6 +65,10 @@ class _MonthFilterState extends State<MonthFilter> {
}, },
tileColor: _selectedMonth == monthYear ? kTestSecondColor : null, tileColor: _selectedMonth == monthYear ? kTestSecondColor : null,
); );
} else {
// Si nbrEvents est 0, ne retourne pas de widget
return SizedBox.shrink();
}
} }
}, },
); );
@ -70,11 +82,11 @@ class _MonthFilterState extends State<MonthFilter> {
return translatedMonthName; return translatedMonthName;
} }
Widget _buildAllItem() { Widget _buildAllItem(AppContext appContext) {
int totalEvents = widget.events.length; int totalEvents = widget.events.length;
return ListTile( return ListTile(
title: Text( title: Text(
'Tout ($totalEvents)', '${TranslationHelper.getFromLocale("agenda.all", appContext.getContext())} ($totalEvents)',
style: TextStyle( style: TextStyle(
fontSize: 16.0, fontSize: 16.0,
fontWeight: _selectedMonth == null ? FontWeight.bold : FontWeight.normal, fontWeight: _selectedMonth == null ? FontWeight.bold : FontWeight.normal,

View File

@ -49,24 +49,34 @@ class WeatherView extends StatelessWidget {
List<WeatherForecast> nextDay5All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 5))).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; var nextDay1MiddayTest = nextDay1All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull;
if(nextDay1All.isNotEmpty) {
WeatherForecast nextDay1AllSummary = nextDay1MiddayTest != null ? nextDay1MiddayTest : nextDay1All.last; WeatherForecast nextDay1AllSummary = nextDay1MiddayTest != null ? nextDay1MiddayTest : nextDay1All.last;
nextFiveDaysForecast.add(nextDay1AllSummary); nextFiveDaysForecast.add(nextDay1AllSummary);
}
var nextDay2MiddayTest = nextDay2All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; var nextDay2MiddayTest = nextDay2All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull;
if(nextDay2All.isNotEmpty) {
WeatherForecast nextDay2Midday = nextDay2MiddayTest != null ? nextDay2MiddayTest : nextDay2All.last; WeatherForecast nextDay2Midday = nextDay2MiddayTest != null ? nextDay2MiddayTest : nextDay2All.last;
nextFiveDaysForecast.add(nextDay2Midday); nextFiveDaysForecast.add(nextDay2Midday);
}
var nextDay3MiddayTest = nextDay3All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; var nextDay3MiddayTest = nextDay3All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull;
if(nextDay3All.isNotEmpty) {
WeatherForecast nextDay3Midday = nextDay3MiddayTest != null ? nextDay3MiddayTest : nextDay3All.last; WeatherForecast nextDay3Midday = nextDay3MiddayTest != null ? nextDay3MiddayTest : nextDay3All.last;
nextFiveDaysForecast.add(nextDay3Midday); nextFiveDaysForecast.add(nextDay3Midday);
}
var nextDay4MiddayTest = nextDay4All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; var nextDay4MiddayTest = nextDay4All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull;
if(nextDay4All.isNotEmpty) {
WeatherForecast nextDay4Midday = nextDay4MiddayTest != null ? nextDay4MiddayTest : nextDay4All.last; WeatherForecast nextDay4Midday = nextDay4MiddayTest != null ? nextDay4MiddayTest : nextDay4All.last;
nextFiveDaysForecast.add(nextDay4Midday); nextFiveDaysForecast.add(nextDay4Midday);
}
var nextDay5MiddayTest = nextDay5All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; var nextDay5MiddayTest = nextDay5All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull;
if(nextDay5All.isNotEmpty) {
WeatherForecast nextDay5Midday = nextDay5MiddayTest != null ? nextDay5MiddayTest : nextDay5All.last; WeatherForecast nextDay5Midday = nextDay5MiddayTest != null ? nextDay5MiddayTest : nextDay5All.last;
nextFiveDaysForecast.add(nextDay5Midday); nextFiveDaysForecast.add(nextDay5Midday);
}
return nextFiveDaysForecast; return nextFiveDaysForecast;
} }
@ -272,7 +282,7 @@ class WeatherView extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: List.generate( children: List.generate(
nbrNextHours, getNextFiveDaysForecast(weatherData.list!).length, // nbrNextHours
(index) { (index) {
final weatherForecastNextDay = getNextFiveDaysForecast(weatherData.list!)[index]; final weatherForecastNextDay = getNextFiveDaysForecast(weatherData.list!)[index];
return Padding( return Padding(

View File

@ -2,6 +2,7 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tablet_app/Models/tabletContext.dart'; import 'package:tablet_app/Models/tabletContext.dart';
@ -50,7 +51,6 @@ class _DownloadConfigurationWidgetState extends State<DownloadConfigurationWidge
Permission.storage, Permission.storage,
].request(); ].request();
if(statuses[Permission.storage] == PermissionStatus.granted) { if(statuses[Permission.storage] == PermissionStatus.granted) {
try{ try{
try { try {
Directory directory = Directory('${tabletAppContext.localPath}'); Directory directory = Directory('${tabletAppContext.localPath}');
@ -110,6 +110,16 @@ class _DownloadConfigurationWidgetState extends State<DownloadConfigurationWidge
return false; return false;
} }
} else { } else {
print("PermissionStatus.granted NOT GRANTED");
Fluttertoast.showToast(
msg: "PermissionStatus not granted",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.redAccent,
textColor: Colors.white,
fontSize: 16.0
);
return false; return false;
} }
} }

View File

@ -2424,12 +2424,11 @@ components:
type: object type: object
additionalProperties: false additionalProperties: false
properties: properties:
resourceId: resourceIds:
type: string type: array
nullable: true
resourceUrl:
type: string
nullable: true nullable: true
items:
$ref: '#/components/schemas/TranslationDTO'
User: User:
type: object type: object
additionalProperties: false additionalProperties: false

View File

@ -8,8 +8,7 @@ import 'package:manager_api/api.dart';
## Properties ## Properties
Name | Type | Description | Notes Name | Type | Description | Notes
------------ | ------------- | ------------- | ------------- ------------ | ------------- | ------------- | -------------
**resourceId** | **String** | | [optional] **resourceIds** | [**List<TranslationDTO>**](TranslationDTO.md) | | [optional] [default to const []]
**resourceUrl** | **String** | | [optional]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@ -13,39 +13,29 @@ part of openapi.api;
class AgendaDTO { class AgendaDTO {
/// Returns a new [AgendaDTO] instance. /// Returns a new [AgendaDTO] instance.
AgendaDTO({ AgendaDTO({
this.resourceId, this.resourceIds = const [],
this.resourceUrl,
}); });
String? resourceId; List<TranslationDTO>? resourceIds;
String? resourceUrl;
@override @override
bool operator ==(Object other) => identical(this, other) || other is AgendaDTO && bool operator ==(Object other) => identical(this, other) || other is AgendaDTO &&
other.resourceId == resourceId && other.resourceIds == resourceIds;
other.resourceUrl == resourceUrl;
@override @override
int get hashCode => int get hashCode =>
// ignore: unnecessary_parenthesis // ignore: unnecessary_parenthesis
(resourceId == null ? 0 : resourceId!.hashCode) + (resourceIds == null ? 0 : resourceIds!.hashCode);
(resourceUrl == null ? 0 : resourceUrl!.hashCode);
@override @override
String toString() => 'AgendaDTO[resourceId=$resourceId, resourceUrl=$resourceUrl]'; String toString() => 'AgendaDTO[resourceIds=$resourceIds]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
if (this.resourceId != null) { if (this.resourceIds != null) {
json[r'resourceId'] = this.resourceId; json[r'resourceIds'] = this.resourceIds;
} else { } else {
json[r'resourceId'] = null; json[r'resourceIds'] = null;
}
if (this.resourceUrl != null) {
json[r'resourceUrl'] = this.resourceUrl;
} else {
json[r'resourceUrl'] = null;
} }
return json; return json;
} }
@ -69,8 +59,7 @@ class AgendaDTO {
}()); }());
return AgendaDTO( return AgendaDTO(
resourceId: mapValueOfType<String>(json, r'resourceId'), resourceIds: TranslationDTO.listFromJson(json[r'resourceIds']),
resourceUrl: mapValueOfType<String>(json, r'resourceUrl'),
); );
} }
return null; return null;