measurement and nutrition chart issues fixes

This commit is contained in:
Abhishek Saini
2023-11-05 22:23:16 +05:30
parent bedd65e5b1
commit 3d948dfec4
29 changed files with 657 additions and 92 deletions

View File

@@ -1,15 +1,25 @@
# Proposed Changes
## Description (Proposed Changes)
(Please try to mention in bullet points.)
-
-
-
Related Issues (if applicable)
## Link to the issue :
-
(Add link of the issue you have proposed changes to)
## Please check that the PR fulfills these requirements
- Link :
## Tests
Please make sure to add tests when implementing new features.
## Checklist
Please check that the PR fulfills all requirements listed below by checking the relevant checkboxes (`[x]`). This will ensure a smooth and quick review process.
- [ ] Set a 100 character limit in your editor/IDE to avoid white space diffs in the PR
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Added yourself to AUTHORS.md
- [ ] Updated/added relevant documentation (doc comments with `///`).
- [ ] Added relevant reviewers.

View File

@@ -22,6 +22,7 @@
- Miroslav Mazel - <https://gitlab.com/12people>
- artchiee - <https://github.com/artchiee>
- Tejas Bir Singh - <https://github.com/tejasbirsingh>
- Abhishek Saini - <https://github.com/Abhisheksainii>
## Translators

View File

@@ -31,7 +31,13 @@ height="80">](https://f-droid.org/packages/de.wger.flutter/)
Install the [wger server](https://github.com/wger-project/wger), the easiest way
is to start the development docker-compose: <https://github.com/wger-project/docker>
Alternatively, you can use one of our test servers, just ask us for access.
Alternatively, you can use the test server (the db is reset every day):
* URL: `https://wger-master.rge.uber.space`
* username: `user`
* password: `flutteruser`
* API key: `31e2ea0322c07b9df583a9b6d1e794f7139e78d4`
### 2

View File

@@ -26,6 +26,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@@ -1,4 +1,4 @@
Od ljubitelja fitnessa za ljubitelja fitnessa organiziraj svoje zdravlje s WGER, tvojim upravljaöem treninga!
Od ljubitelja fitnessa za ljubitelje fitnessa organiziraj svoje zdravlje s WGER, tvojim upravljačem treninga!
Već si pronašao/la omiljeni program za fitness i voliš stvarati vlastite sportske rutine? Bez obzira na vrstu sportske zvijeri svi imamo nešto zajedničko: Volimo pratiti naše zdravstvene podatke <3
@@ -8,9 +8,9 @@ Razvili smo 100 % besplatan program za digitalno praćenje zdravlja i fitnessa,
wger je projekt otvorenog koda za:
* Tvoje tijelo
* Tvoje treninge
* Tvoji treninzi
* Tvoj napredak
* Tvoje podatke
* Tvoji podaci
Tvoje tijelo:
Nema potrebe za guglanjem sastojaka omiljenih poslastica odaberi dnevne obroke od više od 78.000 proizvoda i pogledaj nutritivne vrijednosti. Dodaj obroke u plan prehrane i čuvaj pregled svoje prehrane u kalendaru.
@@ -22,7 +22,7 @@ Tvoj napredak:
Nikada ne gubi iz vida svoje ciljeve. Prati svoju težinu i vodi statistiku.
Tvoji podaci:
wger je tvoj personalizirani dnevnik fitnessa ali ti posjeduješ svoje podatke. Koristi REST API za pristup i obavi s njim nevjerojatnih stvari.
wger je tvoj personalizirani dnevnik fitnessa ali ti posjeduješ svoje podatke. Koristi REST API za pristup i obavi s njim nevjerojatne stvari.
Napomena: Ovaj besplatni program ne temelji se na dodatnim sredstvima i ne tražimo da doniraš novac. Više od toga, ovo je projekt zajednice koji stalno raste. Stoga budi spreman/na za nove funkcije u bilo kojem trenutku!

5
lib/helpers/charts.dart Normal file
View File

@@ -0,0 +1,5 @@
double chartGetInterval(DateTime first, DateTime last, {divider = 3}) {
final dayDiff = last.difference(first);
return dayDiff.inMilliseconds == 0 ? 1000 : dayDiff.inMilliseconds.abs() / divider;
}

View File

@@ -730,5 +730,23 @@
"swiss_ball": "Gymnastikball",
"@swiss_ball": {},
"none__bodyweight_exercise_": "keine (Körpergewichtsübung)",
"@none__bodyweight_exercise_": {}
"@none__bodyweight_exercise_": {},
"body_weight": "Körpergewicht",
"@body_weight": {
"description": "Generated entry for translation for server strings"
},
"kg": "kg",
"@kg": {
"description": "Generated entry for translation for server strings"
},
"kilometers_per_hour": "Kilometer pro Stunde",
"@kilometers_per_hour": {
"description": "Generated entry for translation for server strings"
},
"miles_per_hour": "Meilen pro Stunde",
"@miles_per_hour": {
"description": "Generated entry for translation for server strings"
},
"verify": "Verifizieren",
"@verify": {}
}

View File

@@ -136,5 +136,23 @@
"description": "Error message when the user enters an invalid email"
},
"confirmPassword": "Επιβεβαίωση κωδικού πρόσβασης",
"@confirmPassword": {}
"@confirmPassword": {},
"images": "Εικόνες",
"@images": {},
"save": "Αποθήκευση",
"@save": {},
"description": "Περιγραφή",
"@description": {},
"name": "Όνομα",
"@name": {
"description": "Name for a workout or nutritional plan"
},
"translation": "Μετάφραση",
"@translation": {},
"language": "Γλώσσα",
"@language": {},
"category": "Κατηγορία",
"@category": {
"description": "Category for an exercise, ingredient, etc."
}
}

View File

@@ -91,7 +91,7 @@
"@exercise": {
"description": "An exercise for a workout"
},
"logHelpEntriesUnits": "Imaj na umu da su ovdje ucrtani samo unosi s jedinicom težine (kg ili lb) i ponavljanjima, druge kombinacije kao što su vrijeme ili do neuspjeha se ovdje zanemaruju.",
"logHelpEntriesUnits": "Napomena: prikazuju se samo unosi s jedinicom težine (kg ili lb) i ponavljanja, druge kombinacije kao što su vrijeme ili do neuspjeha se ovdje zanemaruju.",
"@logHelpEntriesUnits": {},
"description": "Opis",
"@description": {},

View File

@@ -40,5 +40,447 @@
"register": "Inscrever-se",
"@register": {
"description": "Text for registration button"
}
},
"useDefaultServer": "Usar servidor padrão",
"@useDefaultServer": {
"description": "Toggle button allowing users to switch between the default and a custom wger server"
},
"reset": "Redefinir",
"@reset": {
"description": "Button text allowing the user to reset the entered values to the default"
},
"password": "Senha",
"@password": {},
"invalidUsername": "Por favor insira um nome de usuário válido",
"@invalidUsername": {
"description": "Error message when the user enters an invalid username"
},
"passwordTooShort": "A senha é muito curta",
"@passwordTooShort": {
"description": "Error message when the user a password that is too short"
},
"email": "Endereço de email",
"@email": {},
"username": "Usuário",
"@username": {},
"customServerHint": "Digite o endereço do seu próprio servidor, caso contrário o padrão será usado",
"@customServerHint": {
"description": "Hint text for the form where the users can enter their own wger instance"
},
"useCustomServer": "Usar servidor customizado",
"@useCustomServer": {
"description": "Toggle button allowing users to switch between the default and a custom wger server"
},
"registerInstead": "Não tem uma conta? Registrar agora",
"@registerInstead": {},
"usernameValidChars": "Um usuário deve apenas conter letras, digitos e os caracteres @, +, ., -, ou _",
"@usernameValidChars": {
"description": "Error message when the user tries to register a username with forbidden characters"
},
"invalidUrl": "Por favor, digite uma URL válida",
"@invalidUrl": {
"description": "Error message when the user enters an invalid URL, e.g. in the login form"
},
"customServerUrl": "URL da instância wger",
"@customServerUrl": {
"description": "Label in the form where the users can enter their own wger instance"
},
"passwordsDontMatch": "As senhas não coincidem",
"@passwordsDontMatch": {
"description": "Error message when the user enters two different passwords during registration"
},
"invalidEmail": "Por favor insira um endereço de e-mail válido",
"@invalidEmail": {
"description": "Error message when the user enters an invalid email"
},
"confirmPassword": "Confirme sua senha",
"@confirmPassword": {},
"comment": "Comente",
"@comment": {
"description": "Comment, additional information"
},
"logIngredient": "Salvar no diário nutricional",
"@logIngredient": {},
"equipment": "Equipamento",
"@equipment": {
"description": "Equipment needed to perform an exercise"
},
"saturatedFat": "Gordura saturada",
"@saturatedFat": {},
"mealLogged": "Refeição registrada no diário",
"@mealLogged": {},
"images": "Imagens",
"@images": {},
"close": "Fechar",
"@close": {
"description": "Translation for close"
},
"successfullyDeleted": "Excluído",
"@successfullyDeleted": {
"description": "Message when an item was successfully deleted"
},
"save": "Salvar",
"@save": {},
"goToToday": "Vá para hoje",
"@goToToday": {
"description": "Label on button to jump back to 'today' in the calendar widget"
},
"enterRepetitionsOrWeight": "Por favor preencha as repetições ou o peso para pelo menos uma das séries",
"@enterRepetitionsOrWeight": {
"description": "Error message when the user hasn't filled in the forms for exercise sets"
},
"set": "Definir",
"@set": {
"description": "A set in a workout plan"
},
"noMeasurementEntries": "Você não tem entradas de medição",
"@noMeasurementEntries": {},
"newSet": "Novo conjunto",
"@newSet": {
"description": "Header when adding a new set to a workout day"
},
"impression": "Impressão",
"@impression": {
"description": "General impression (e.g. for a workout session) such as good, bad, etc."
},
"plateCalculator": "Pratos",
"@plateCalculator": {
"description": "Label used for the plate calculator in the gym mode"
},
"newNutritionalPlan": "Novo plano nutricional",
"@newNutritionalPlan": {},
"setNr": "Definir {nr}",
"@setNr": {
"description": "Header in form indicating the number of the current set. Can also be translated as something like 'Set Nr. xy'.",
"type": "text",
"placeholders": {
"nr": {}
}
},
"fat": "Gordura",
"@fat": {},
"timeStartAhead": "O horário de início não pode ser anterior ao horário de término",
"@timeStartAhead": {},
"carbohydrates": "Carboidratos",
"@carbohydrates": {},
"noWorkoutPlans": "Você não tem planos de treino",
"@noWorkoutPlans": {
"description": "Message shown when the user has no workout plans"
},
"aboutTranslationTitle": "Tradução",
"@aboutTranslationTitle": {
"description": "Title for translation section in the about dialog"
},
"muscles": "Músculos",
"@muscles": {
"description": "(main) muscles trained by an exercise"
},
"total": "Total",
"@total": {
"description": "Label used for total sums of e.g. calories or similar"
},
"dayDescriptionHelp": "Uma descrição do que é feito neste dia (por exemplo, 'dia de puxar') ou quais partes do corpo são treinadas (por exemplo, 'peito e ombros')",
"@dayDescriptionHelp": {},
"gymMode": "Modo Gym",
"@gymMode": {
"description": "Label when starting the gym mode"
},
"logged": "Desconectar",
"@logged": {
"description": "Header for the column of 'logged' nutritional values, i.e. what was eaten"
},
"amount": "Quantia",
"@amount": {
"description": "The amount (e.g. in grams) of an ingredient in a meal"
},
"loginInstead": "Já tem uma conta ? Entre",
"@loginInstead": {},
"pause": "Pausar",
"@pause": {
"description": "Noun, not an imperative! Label used for the pause when using the gym mode"
},
"success": "Sucesso",
"@success": {
"description": "Message when an action completed successfully, usually used as a heading"
},
"repetitionUnit": "Unidade de repetição",
"@repetitionUnit": {},
"weightUnit": "Unidade de peso",
"@weightUnit": {},
"searchIngredient": "Pesquisar Ingrediente",
"@searchIngredient": {
"description": "Label on ingredient search form"
},
"aboutBugsText": "Entre em contato se algo não se comportou conforme o esperado ou se houver algum recurso que você acha que está faltando.",
"@aboutBugsText": {
"description": "Text for bugs section in the about dialog"
},
"anErrorOccurred": "Ocorreu um erro!",
"@anErrorOccurred": {},
"aboutContactUsTitle": "Diga oi!",
"@aboutContactUsTitle": {
"description": "Title for contact us section in the about dialog"
},
"enterValue": "por favor insira um valor",
"@enterValue": {
"description": "Error message when the user hasn't entered a value on a required field"
},
"logMeal": "Registrar esta refeição",
"@logMeal": {},
"newEntry": "Nova entrada",
"@newEntry": {
"description": "Title when adding a new entry such as a weight or log entry"
},
"addSet": "Adicionar set",
"@addSet": {
"description": "Label for the button that adds a set (to a workout day)"
},
"newWorkout": "Novo plano de treino",
"@newWorkout": {
"description": "Header when adding a new workout"
},
"energyShort": "E",
"@energyShort": {
"description": "The first letter or short name of the word 'Energy', used in overviews"
},
"name": "Nome",
"@name": {
"description": "Name for a workout or nutritional plan"
},
"percentEnergy": "Porcentagem de energia",
"@percentEnergy": {},
"searchNamesInEnglish": "Pesquise também por nomes em inglês",
"@searchNamesInEnglish": {},
"exercise": "Exercício",
"@exercise": {
"description": "An exercise for a workout"
},
"addIngredient": "Adicionar ingrediente",
"@addIngredient": {},
"fatShort": "G",
"@fatShort": {
"description": "The first letter or short name of the word 'Fat', used in overviews"
},
"start": "Começar",
"@start": {
"description": "Label on button to start the gym mode (i.e., an imperative)"
},
"jumpTo": "Pule para",
"@jumpTo": {
"description": "Imperative. Label used in popup allowing the user to jump to a specific exercise while in the gym mode"
},
"difference": "Diferença",
"@difference": {},
"fibres": "Fibra",
"@fibres": {},
"aboutDescription": "Obrigado por usar o Wger! Wger é um projeto colaborativo de código aberto, feito por entusiastas do fitness de todo o mundo.",
"@aboutDescription": {
"description": "Text in the about dialog"
},
"timeStart": "Hora de início",
"@timeStart": {
"description": "The starting time of a workout"
},
"searchExercise": "Exercício de pesquisa para adicionar",
"@searchExercise": {
"description": "Label on set form. Selected exercises are added to the set"
},
"moreMeasurementEntries": "Adicionar nova medição",
"@moreMeasurementEntries": {
"description": "Message shown when the user wants to add new measurement"
},
"loadingText": "Carregando...",
"@loadingText": {
"description": "Text to show when entries are being loaded in the background: Loading..."
},
"selectExercises": "Se quiser fazer um superset você pode procurar vários exercícios, eles estarão agrupados",
"@selectExercises": {},
"nutritionalDiary": "Diário nutricional",
"@nutritionalDiary": {},
"protein": "Proteína",
"@protein": {},
"labelWorkoutPlans": "Planos de treino",
"@labelWorkoutPlans": {
"description": "Title for screen workout plans"
},
"proteinShort": "P",
"@proteinShort": {
"description": "The first letter or short name of the word 'Protein', used in overviews"
},
"noWeightEntries": "Você não tem entradas de peso",
"@noWeightEntries": {
"description": "Message shown when the user has no logged weight entries"
},
"noNutritionalPlans": "Você não tem planos nutricionais",
"@noNutritionalPlans": {
"description": "Message shown when the user has no nutritional plans"
},
"goToDetailPage": "Ir para a página de detalhes",
"@goToDetailPage": {},
"labelWorkoutLogs": "Registros de treinos",
"@labelWorkoutLogs": {
"description": "(Workout) logs"
},
"aboutTranslationText": "Este aplicativo está traduzido no weblate. Se você também quiser ajudar, clique no link e comece a traduzir",
"@aboutTranslationText": {
"description": "Text for translation section in the about dialog"
},
"ingredient": "Ingrediente",
"@ingredient": {},
"measurementCategoriesHelpText": "Categoria de medição, como 'bíceps' ou 'gordura corporal'",
"@measurementCategoriesHelpText": {},
"rirNotUsed": "RiR não usado",
"@rirNotUsed": {
"description": "Label used in RiR slider when the RiR value is not used/saved for the current setting or log"
},
"todaysWorkout": "Seu treino hoje",
"@todaysWorkout": {},
"aboutSourceText": "Obtenha o código fonte deste aplicativo e seu servidor no github",
"@aboutSourceText": {
"description": "Text for source code section in the about dialog"
},
"kJ": "kJ",
"@kJ": {
"description": "Energy in a meal in kilo joules, kJ"
},
"sodium": "Sódio",
"@sodium": {},
"translation": "Tradução",
"@translation": {},
"successfullySaved": "Salvo",
"@successfullySaved": {
"description": "Message when an item was successfully saved"
},
"exerciseList": "Lista de exercícios",
"@exerciseList": {},
"energy": "Energia",
"@energy": {
"description": "Energy in a meal, ingredient etc. e.g. in kJ"
},
"newDay": "Novo dia",
"@newDay": {},
"toggleDetails": "Alterar detalhes",
"@toggleDetails": {
"description": "Switch to toggle detail / overview"
},
"musclesSecondary": "Músculos secundários",
"@musclesSecondary": {
"description": "secondary muscles trained by an exercise"
},
"aboutContactUsText": "Se você quiser bater um papo conosco, entre no servidor Discord e entre em contato",
"@aboutContactUsText": {
"description": "Text for contact us section in the about dialog"
},
"labelDashboard": "Painel",
"@labelDashboard": {
"description": "Title for screen dashboard"
},
"timeEnd": "Fim do tempo",
"@timeEnd": {
"description": "The end time of a workout"
},
"planned": "Planejado",
"@planned": {
"description": "Header for the column of 'planned' nutritional values, i.e. what should be eaten"
},
"logHelpEntries": "Se em um mesmo dia houver mais de uma inscrição com o mesmo número de repetições, mas pesos diferentes, apenas a inscrição com maior peso será mostrada no diagrama.",
"@logHelpEntries": {},
"exerciseName": "Nome do exercício",
"@exerciseName": {
"description": "Label for the name of a workout exercise"
},
"labelBottomNavNutrition": "Nutrição",
"@labelBottomNavNutrition": {
"description": "Label used in bottom navigation, use a short word"
},
"language": "Linguagem",
"@language": {},
"nutritionalPlans": "Planos nutricionais",
"@nutritionalPlans": {},
"kcal": "kcal",
"@kcal": {
"description": "Energy in a meal in kilocalories, kcal"
},
"g": "g",
"@g": {
"description": "Abbreviation for gram"
},
"addMeal": "Adicionar refeição",
"@addMeal": {},
"sameRepetitions": "Se você fizer as mesmas repetições e peso para todas as séries, poderá preencher apenas uma linha. Por exemplo, para 4 séries basta inserir 10 para as repetições, isso automaticamente se torna \"4 x 10\".",
"@sameRepetitions": {},
"measurementEntriesHelpText": "A unidade usada para medir a categoria, como 'cm' ou '%'",
"@measurementEntriesHelpText": {},
"supersetWith": "superset com",
"@supersetWith": {
"description": "Text used between exercise cards when adding a new set. Translate as something like 'in a superset with'"
},
"sugars": "Açúcar",
"@sugars": {},
"aboutBugsTitle": "Tem um problema ou ideia?",
"@aboutBugsTitle": {
"description": "Title for bugs section in the about dialog"
},
"carbohydratesShort": "C",
"@carbohydratesShort": {
"description": "The first letter or short name of the word 'Carbohydrates', used in overviews"
},
"measurements": "Medidas",
"@measurements": {
"description": "Categories for the measurements such as biceps size, body fat, etc."
},
"macronutrients": "Macronutrientes",
"@macronutrients": {},
"plateCalculatorNotDivisible": "Não é possível atingir o peso com os pratos disponíveis",
"@plateCalculatorNotDivisible": {
"description": "Error message when the current weight is not reachable with plates (e.g. 33.1 kg)"
},
"confirmDelete": "Tem certeza de que deseja excluir '{toDelete}'?",
"@confirmDelete": {
"description": "Confirmation text before the user deletes an object",
"type": "text",
"placeholders": {
"toDelete": {}
}
},
"gPerBodyKg": "g por kg corporal",
"@gPerBodyKg": {
"description": "Label used for total sums of e.g. calories or similar in grams per Kg of body weight"
},
"weekAverage": "Média de 7 dias",
"@weekAverage": {
"description": "Header for the column of '7 day average' nutritional values, i.e. what was logged last week"
},
"labelWorkoutPlan": "Plano de treino",
"@labelWorkoutPlan": {
"description": "Title for screen workout plan"
},
"category": "Categoria",
"@category": {
"description": "Category for an exercise, ingredient, etc."
},
"exercises": "Exercícios",
"@exercises": {
"description": "Multiple exercises for a workout"
},
"time": "Tempo",
"@time": {
"description": "The time of a meal or workout"
},
"calendar": "Calendário",
"@calendar": {},
"verify": "Verificar",
"@verify": {},
"workoutSession": "Sessão de treino",
"@workoutSession": {
"description": "A (logged) workout session"
},
"logHelpEntriesUnits": "Observe que apenas as entradas com uma unidade de peso (kg ou lb) e repetições são registradas; outras combinações, como tempo ou até a falha, são ignoradas aqui.",
"@logHelpEntriesUnits": {},
"aboutSourceTitle": "Código fonte",
"@aboutSourceTitle": {
"description": "Title for source code section in the about dialog"
},
"measurement": "Medição",
"@measurement": {}
}

View File

@@ -351,7 +351,6 @@ class WorkoutPlansProvider with ChangeNotifier {
'weightUnit': _weightUnits.map((e) => e.toJson()).toList(),
};
prefs.setString('workoutUnits', json.encode(exerciseData));
log(json.encode(exerciseData));
notifyListeners();
}

View File

@@ -29,7 +29,7 @@ import 'package:wger/screens/form_screen.dart';
import 'package:wger/widgets/core/about.dart';
import 'package:wger/widgets/user/forms.dart';
class MainAppBar extends StatelessWidget with PreferredSizeWidget {
class MainAppBar extends StatelessWidget implements PreferredSizeWidget {
final String _title;
MainAppBar(this._title);
@@ -113,7 +113,7 @@ class MainAppBar extends StatelessWidget with PreferredSizeWidget {
}
/// App bar that only displays a title
class EmptyAppBar extends StatelessWidget with PreferredSizeWidget {
class EmptyAppBar extends StatelessWidget implements PreferredSizeWidget {
final String _title;
EmptyAppBar(this._title);

View File

@@ -9,7 +9,7 @@ import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/models/measurements/measurement_entry.dart';
import 'package:wger/widgets/core/charts.dart';
import 'package:wger/widgets/measurements/charts.dart';
//import 'package:intl/intl.dart';
//import 'package:wger/widgets/core/charts.dart';
@@ -177,14 +177,13 @@ class _LineChartSample2State extends State<LineChartSample2> {
// );
// }
// #TODO : needs to be changed (values for (y) axis)
Widget leftTitleWidgets(double value, TitleMeta meta) {
const style = TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
);
String text;
switch (value.toInt()) {
case 1:

View File

@@ -35,7 +35,7 @@ import 'package:wger/screens/nutritional_plan_screen.dart';
import 'package:wger/screens/weight_screen.dart';
import 'package:wger/screens/workout_plan_screen.dart';
import 'package:wger/theme/theme.dart';
import 'package:wger/widgets/core/charts.dart';
import 'package:wger/widgets/measurements/charts.dart';
import 'package:wger/widgets/core/core.dart';
import 'package:wger/widgets/measurements/categories_card.dart';
import 'package:wger/widgets/measurements/forms.dart';

View File

@@ -4,7 +4,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import '../../models/measurements/measurement_category.dart';
import '../../screens/form_screen.dart';
import '../../screens/measurement_entries_screen.dart';
import '../core/charts.dart';
import 'charts.dart';
import 'forms.dart';
class CategoriesCard extends StatelessWidget {

View File

@@ -19,6 +19,7 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:wger/helpers/charts.dart';
import 'package:wger/theme/theme.dart';
class MeasurementChartWidgetFl extends StatefulWidget {
@@ -32,8 +33,6 @@ class MeasurementChartWidgetFl extends StatefulWidget {
}
class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
final interval = 15 * Duration.millisecondsPerDay / 1000 / 60;
@override
Widget build(BuildContext context) {
return AspectRatio(
@@ -52,8 +51,20 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
);
}
LineTouchData tooltipData() {
return LineTouchData(touchTooltipData: LineTouchTooltipData(getTooltipItems: (touchedSpots) {
return touchedSpots.map((touchedSpot) {
return LineTooltipItem(
'${touchedSpot.y} kg',
const TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
);
}).toList();
}));
}
LineChartData mainData() {
return LineChartData(
lineTouchData: tooltipData(),
gridData: FlGridData(
show: true,
drawVerticalLine: true,
@@ -84,12 +95,19 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (value, meta) {
final DateTime date = DateTime.fromMillisecondsSinceEpoch(value.toInt() * 1000 * 60);
// Don't show the first and last entries, otherwise they'll overlap with the
// calculated interval
if (value == meta.min || value == meta.max) {
return const Text('');
}
final DateTime date = DateTime.fromMillisecondsSinceEpoch(value.toInt());
return Text(
DateFormat.yMd(Localizations.localeOf(context).languageCode).format(date),
);
},
interval: interval,
interval: widget._entries.isNotEmpty
? chartGetInterval(widget._entries.last.date, widget._entries.first.date)
: 1000,
),
),
leftTitles: AxisTitles(
@@ -112,7 +130,7 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
LineChartBarData(
spots: [
...widget._entries
.map((e) => FlSpot(e.date.millisecondsSinceEpoch / 1000 / 60, e.value.toDouble()))
.map((e) => FlSpot(e.date.millisecondsSinceEpoch.toDouble(), e.value.toDouble()))
],
isCurved: false,
color: wgerSecondaryColor,

View File

@@ -24,7 +24,7 @@ import 'package:wger/models/measurements/measurement_category.dart';
import 'package:wger/providers/measurement.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/theme/theme.dart';
import 'package:wger/widgets/core/charts.dart';
import 'package:wger/widgets/measurements/charts.dart';
import 'forms.dart';

View File

@@ -23,7 +23,7 @@ import 'package:intl/intl.dart';
import 'package:wger/helpers/colors.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/models/nutrition/nutritional_values.dart';
import 'package:wger/widgets/core/charts.dart';
import 'package:wger/widgets/measurements/charts.dart';
class NutritionData {
final String name;

View File

@@ -20,12 +20,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/colors.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/models/nutrition/nutritional_values.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/screens/nutritional_diary_screen.dart';
import 'package:wger/theme/theme.dart';
import 'package:wger/widgets/measurements/charts.dart';
import 'package:wger/widgets/nutrition/charts.dart';
import 'package:wger/widgets/nutrition/forms.dart';
import 'package:wger/widgets/nutrition/meal.dart';
@@ -212,12 +214,42 @@ class NutritionalPlanDetailWidget extends StatelessWidget {
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline6,
),
Container(
padding: const EdgeInsets.all(15),
padding: const EdgeInsets.only(top: 15, left: 15, right: 15),
height: 300,
child: NutritionalDiaryChartWidgetFl(nutritionalPlan: _nutritionalPlan), // chart
),
const Padding(padding: EdgeInsets.all(8.0)),
// const Padding(padding: EdgeInsets.all(8.0)),
Padding(
padding: const EdgeInsets.only(bottom: 40, left: 25, right: 25),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Indicator(
color: LIST_OF_COLORS3[0],
text: AppLocalizations.of(context).planned,
isSquare: true,
),
const SizedBox(
width: 4,
),
Indicator(
color: LIST_OF_COLORS3[1],
text: AppLocalizations.of(context).logged,
isSquare: true,
),
const SizedBox(
width: 4,
),
Indicator(
color: LIST_OF_COLORS3[2],
text: AppLocalizations.of(context).weekAverage,
isSquare: true,
),
],
),
),
Text(
AppLocalizations.of(context).nutritionalDiary,
textAlign: TextAlign.center,

View File

@@ -24,7 +24,7 @@ import 'package:wger/providers/body_weight.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/screens/measurement_categories_screen.dart';
import 'package:wger/theme/theme.dart';
import 'package:wger/widgets/core/charts.dart';
import 'package:wger/widgets/measurements/charts.dart';
import 'package:wger/widgets/weight/forms.dart';
class WeightEntriesList extends StatelessWidget {

View File

@@ -26,7 +26,7 @@ enum _WorkoutAppBarOptions {
contribute,
}
class WorkoutOverviewAppBar extends StatelessWidget with PreferredSizeWidget {
class WorkoutOverviewAppBar extends StatelessWidget implements PreferredSizeWidget {
@override
Widget build(BuildContext context) {
return AppBar(

View File

@@ -20,6 +20,7 @@ import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:wger/helpers/charts.dart';
import 'package:wger/helpers/colors.dart';
/// Sample time series data type.
@@ -47,8 +48,6 @@ class _LogChartWidgetFlState extends State<LogChartWidgetFl> {
aspectRatio: 1.70,
child: Padding(
padding: const EdgeInsets.only(
right: 18,
left: 12,
top: 24,
bottom: 12,
),
@@ -60,17 +59,12 @@ class _LogChartWidgetFlState extends State<LogChartWidgetFl> {
}
LineChartData mainData() {
final dayDiff = DateTime.parse(widget._data['logs'].keys.last)
.difference(DateTime.parse(widget._data['logs'].keys.first));
final interval = dayDiff.inDays * 1.3 * Duration.millisecondsPerDay;
final colors = generateChartColors(widget._data['chart_data'].length).iterator;
return LineChartData(
gridData: FlGridData(
show: true,
drawVerticalLine: true,
//horizontalInterval: 1,
//verticalInterval: interval,
getDrawingHorizontalLine: (value) {
return FlLine(
color: Colors.grey,
@@ -96,12 +90,21 @@ class _LogChartWidgetFlState extends State<LogChartWidgetFl> {
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (value, meta) {
// Don't show the first and last entries, otherwise they'll overlap with the
// calculated interval
if (value == meta.min || value == meta.max) {
return const Text('');
}
final DateTime date = DateTime.fromMillisecondsSinceEpoch(value.toInt());
return Text(
DateFormat.yMd(Localizations.localeOf(context).languageCode).format(date),
);
},
interval: interval,
interval: chartGetInterval(
DateTime.parse(widget._data['logs'].keys.first),
DateTime.parse(widget._data['logs'].keys.last),
),
),
),
leftTitles: AxisTitles(
@@ -121,15 +124,18 @@ class _LogChartWidgetFlState extends State<LogChartWidgetFl> {
lineBarsData: [
...widget._data['chart_data'].map(
(e) {
colors.moveNext();
return LineChartBarData(
spots: [
...e.map((entry) => FlSpot(
DateTime.parse(entry['date']).millisecondsSinceEpoch.toDouble(),
double.parse(entry['weight']),
))
...e.map(
(entry) => FlSpot(
DateTime.parse(entry['date']).millisecondsSinceEpoch.toDouble(),
double.parse(entry['weight']),
),
)
],
isCurved: false,
color: getRandomColor(widget._data['chart_data'].length, e.first['reps']),
color: colors.current,
barWidth: 2,
isStrokeCapRound: true,
dotData: FlDotData(

View File

@@ -44,7 +44,7 @@ class ExerciseLogChart extends StatelessWidget {
return FutureBuilder(
future: getChartEntries(context),
builder: (context, AsyncSnapshot<Map<String, dynamic>> snapshot) => SizedBox(
height: 150,
height: 190,
child: snapshot.connectionState == ConnectionState.waiting
? const Center(child: CircularProgressIndicator())
: LogChartWidgetFl(snapshot.data!, _currentDate),

View File

@@ -13,7 +13,7 @@ import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))

View File

@@ -53,10 +53,10 @@ packages:
dependency: transitive
description:
name: async
sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.dev"
source: hosted
version: "2.10.0"
version: "2.11.0"
boolean_selector:
dependency: transitive
description:
@@ -189,10 +189,10 @@ packages:
dependency: transitive
description:
name: characters
sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
version: "1.3.0"
charcode:
dependency: transitive
description:
@@ -253,10 +253,10 @@ packages:
dependency: "direct main"
description:
name: collection
sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
url: "https://pub.dev"
source: hosted
version: "1.17.0"
version: "1.17.2"
conventional_commit:
dependency: transitive
description:
@@ -784,18 +784,18 @@ packages:
dependency: transitive
description:
name: matcher
sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72"
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev"
source: hosted
version: "0.12.13"
version: "0.12.16"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
version: "0.5.0"
melos:
dependency: transitive
description:
@@ -808,10 +808,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42"
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
url: "https://pub.dev"
source: hosted
version: "1.8.0"
version: "1.9.1"
mime:
dependency: transitive
description:
@@ -824,10 +824,10 @@ packages:
dependency: "direct dev"
description:
name: mockito
sha256: dd61809f04da1838a680926de50a9e87385c1de91c6579629c3d1723946e8059
sha256: "8b46d7eb40abdda92d62edd01546051f0c27365e65608c284de336dccfef88cc"
url: "https://pub.dev"
source: hosted
version: "5.4.0"
version: "5.4.1"
multi_select_flutter:
dependency: "direct main"
description:
@@ -872,10 +872,10 @@ packages:
dependency: "direct main"
description:
name: package_info_plus
sha256: "6ff267fcd9d48cb61c8df74a82680e8b82e940231bb5f68356672fde0397334a"
sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017"
url: "https://pub.dev"
source: hosted
version: "4.1.0"
version: "4.2.0"
package_info_plus_platform_interface:
dependency: transitive
description:
@@ -888,10 +888,10 @@ packages:
dependency: transitive
description:
name: path
sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev"
source: hosted
version: "1.8.2"
version: "1.8.3"
path_parsing:
dependency: transitive
description:
@@ -1056,10 +1056,10 @@ packages:
dependency: "direct main"
description:
name: shared_preferences
sha256: b7f41bad7e521d205998772545de63ff4e6c97714775902c199353f8bf1511ac
sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
version: "2.2.2"
shared_preferences_android:
dependency: transitive
description:
@@ -1157,10 +1157,10 @@ packages:
dependency: transitive
description:
name: source_span
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
version: "1.10.0"
stack_trace:
dependency: transitive
description:
@@ -1221,10 +1221,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
url: "https://pub.dev"
source: hosted
version: "0.4.16"
version: "0.6.0"
timing:
dependency: transitive
description:
@@ -1405,10 +1405,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: e7fb6c2282f7631712b69c19d1bff82f3767eea33a2321c14fa59ad67ea391c7
sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f
url: "https://pub.dev"
source: hosted
version: "9.4.0"
version: "11.7.1"
watcher:
dependency: transitive
description:
@@ -1417,6 +1417,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.2"
web:
dependency: transitive
description:
name: web
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
web_socket_channel:
dependency: transitive
description:
@@ -1429,10 +1437,10 @@ packages:
dependency: transitive
description:
name: webdriver
sha256: ef67178f0cc7e32c1494645b11639dd1335f1d18814aa8435113a92e9ef9d841
sha256: "3c923e918918feeb90c4c9fdf1fe39220fa4c0e8e2c0fffaded174498ef86c49"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
version: "3.0.2"
win32:
dependency: transitive
description:
@@ -1474,5 +1482,5 @@ packages:
source: hosted
version: "2.1.1"
sdks:
dart: ">=2.19.0 <3.0.0"
dart: ">=3.1.0-185.0.dev <4.0.0"
flutter: ">=3.7.0"

View File

@@ -24,7 +24,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.5.6+34
environment:
sdk: '>=2.17.0 <3.0.0'
sdk: ">=2.17.0 <3.0.0"
dependencies:
flutter:
@@ -45,10 +45,10 @@ dependencies:
intl: ^0.17.0
json_annotation: ^4.8.1
version: ^3.0.2
package_info_plus: ^4.1.0
package_info_plus: ^4.2.0
provider: ^6.0.5
rive: ^0.11.4
shared_preferences: ^2.2.1
shared_preferences: ^2.2.2
table_calendar: ^3.0.8
url_launcher: ^6.1.11
flutter_barcode_scanner: ^2.0.0
@@ -60,6 +60,9 @@ dependencies:
fl_chart: ^0.62.0
flutter_zxing: ^1.1.2
dependency_overrides:
intl: any
dev_dependencies:
flutter_test:
sdk: flutter

View File

@@ -26,7 +26,7 @@ import 'package:wger/models/measurements/measurement_category.dart';
import 'package:wger/models/measurements/measurement_entry.dart';
import 'package:wger/providers/measurement.dart';
import 'package:wger/screens/measurement_categories_screen.dart';
import 'package:wger/widgets/core/charts.dart';
import 'package:wger/widgets/measurements/charts.dart';
import 'measurement_categories_screen_test.mocks.dart';

View File

@@ -73,8 +73,8 @@ void main() {
expect(find.text('body fat'), findsOneWidget);
// Entries
expect(find.text('10.2 %'), findsOneWidget);
expect(find.text('18.1 %'), findsOneWidget);
expect(find.text('10.2 %'), findsNWidgets(2));
expect(find.text('18.1 %'), findsNWidgets(2));
});
testWidgets('Tests the localization of dates - EN', (WidgetTester tester) async {
@@ -83,8 +83,8 @@ void main() {
await tester.pumpAndSettle();
// From the entries list and from the chart
expect(find.text('8/1/2021'), findsNWidgets(3));
expect(find.text('8/10/2021'), findsNWidgets(2));
expect(find.text('8/1/2021'), findsWidgets);
expect(find.text('8/10/2021'), findsWidgets);
});
testWidgets('Tests the localization of dates - DE', (WidgetTester tester) async {
@@ -92,7 +92,7 @@ void main() {
await tester.tap(find.byType(TextButton));
await tester.pumpAndSettle();
expect(find.text('1.8.2021'), findsOneWidget);
expect(find.text('10.8.2021'), findsOneWidget);
expect(find.text('1.8.2021'), findsWidgets);
expect(find.text('10.8.2021'), findsWidgets);
});
}

View File

@@ -25,7 +25,7 @@ import 'package:provider/provider.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/screens/weight_screen.dart';
import 'package:wger/widgets/core/charts.dart';
import 'package:wger/widgets/measurements/charts.dart';
import 'package:wger/widgets/weight/forms.dart';
import '../../test_data/body_weight.dart';
@@ -84,8 +84,8 @@ void main() {
await tester.pumpWidget(createWeightScreen());
// One in the entries list, one in the chart
expect(find.text('1/1/2021'), findsNWidgets(2));
expect(find.text('1/10/2021'), findsNWidgets(2));
expect(find.text('1/1/2021'), findsOneWidget);
expect(find.text('1/10/2021'), findsOneWidget);
});
testWidgets('Tests the localization of dates - DE', (WidgetTester tester) async {