Aitrainer_app 1.1.1
test menu, customer modification, exercise save images, localization
Before Width: | Height: | Size: 3.0 MiB After Width: | Height: | Size: 3.0 MiB |
BIN
asset/image/WT_OK.png
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
asset/image/WT_gain_muscle.png
Normal file
After Width: | Height: | Size: 1.6 MiB |
BIN
asset/image/WT_light_background.png
Normal file
After Width: | Height: | Size: 2.3 MiB |
BIN
asset/image/WT_login.png
Normal file
After Width: | Height: | Size: 2.1 MiB |
BIN
asset/image/WT_long_logo.png
Normal file
After Width: | Height: | Size: 181 KiB |
BIN
asset/image/WT_menu.png
Normal file
After Width: | Height: | Size: 4.4 MiB |
BIN
asset/image/WT_menu_backround.png
Normal file
After Width: | Height: | Size: 2.9 MiB |
BIN
asset/image/WT_menu_dark.png
Normal file
After Width: | Height: | Size: 2.8 MiB |
BIN
asset/image/WT_menu_welcome.png
Normal file
After Width: | Height: | Size: 3.9 MiB |
BIN
asset/image/WT_weight_loss.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
asset/image/dots.gif
Normal file
After Width: | Height: | Size: 119 KiB |
BIN
asset/menu/1.1.1.cooper.png
Normal file
After Width: | Height: | Size: 781 KiB |
BIN
asset/menu/1.1.aerob.png
Normal file
After Width: | Height: | Size: 1.6 MiB |
BIN
asset/menu/1.2.1.300m.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
asset/menu/1.2.2.400m.png
Normal file
After Width: | Height: | Size: 1.6 MiB |
BIN
asset/menu/1.2.anaerob.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
asset/menu/1.cardio.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
asset/menu/2.1.1.pull-ups.png
Normal file
After Width: | Height: | Size: 1.5 MiB |
BIN
asset/menu/2.1.2.pushup.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
asset/menu/2.1.3.sit-ups.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
asset/menu/2.1.4.squats.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
asset/menu/2.1.5.timedpushup.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
asset/menu/2.1.6.core.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
asset/menu/2.1.endurance.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
asset/menu/2.2.1.1.chestpress.png
Normal file
After Width: | Height: | Size: 1.5 MiB |
BIN
asset/menu/2.2.1.1RM.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
asset/menu/2.2.1.2.pullups.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
asset/menu/2.2.1.3.biceps.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
asset/menu/2.2.1.4.triceps.png
Normal file
After Width: | Height: | Size: 1.5 MiB |
BIN
asset/menu/2.2.1.5.shoulders.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
asset/menu/2.strength.png
Normal file
After Width: | Height: | Size: 988 KiB |
BIN
asset/menu/3.1.BMI.png
Normal file
After Width: | Height: | Size: 1.8 MiB |
BIN
asset/menu/3.2.BMR.png
Normal file
After Width: | Height: | Size: 1.8 MiB |
BIN
asset/menu/3.3.sizes.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
asset/menu/3.bcs1.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
79
i18n/en.json
Normal file
79
i18n/hu.json
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"Customers And Exercises": "Ügyfelek és gyakorlatok",
|
||||||
|
"Home": "Főoldal",
|
||||||
|
"Customers": "Ügyfelek",
|
||||||
|
"Exercises": "Gyakorlatok",
|
||||||
|
"TRAINING!": "EDZÉS!",
|
||||||
|
"Login": "Bejelentkezés",
|
||||||
|
"Logout": "Kijelentkezés",
|
||||||
|
"Change Language": "Nyelv",
|
||||||
|
"Password too short": "A jelszó min. 6 karakterből álljon",
|
||||||
|
"Please type an email address": "Kérlek írj be egy email címet",
|
||||||
|
"SignUp": "Regisztráció",
|
||||||
|
"Privacy": "Adatkezelés",
|
||||||
|
"Change App Language": "Nyelvválasztás",
|
||||||
|
"English": "Angol",
|
||||||
|
"Hungarian": "Magyar",
|
||||||
|
"Events": "Események",
|
||||||
|
"Account": "Fiók",
|
||||||
|
"Settings": "Beállítások",
|
||||||
|
"Profile": "Személyes adatok",
|
||||||
|
"Selected Language": "Választott nyelv",
|
||||||
|
"gdpr_text": "",
|
||||||
|
|
||||||
|
"Please select an exercise": "Válassz ki egy gyakorlatot",
|
||||||
|
"Cardio": "Kardió",
|
||||||
|
"400m": "400m",
|
||||||
|
"300m": "300m",
|
||||||
|
"Aerobic": "Aerob",
|
||||||
|
"Anaerobic": "Anaerob",
|
||||||
|
"Cooper": "Cooper teszt",
|
||||||
|
"Strength": "Erő",
|
||||||
|
"Endurance": "Erő állóképesség",
|
||||||
|
"Pushups": "Fekvőtámasz",
|
||||||
|
"Timed Pushups": "Fekvőtámasz időre",
|
||||||
|
"Core": "Core (plank)",
|
||||||
|
"Squats": "Guggolás",
|
||||||
|
"Sit-ups": "Felülés",
|
||||||
|
"1RM": "1RM - Maxerő",
|
||||||
|
"Chest Press": "Fekvenyomás",
|
||||||
|
"Pull Ups": "Húzódszkodás",
|
||||||
|
"Biceps": "Bicepsz",
|
||||||
|
"Triceps": "Tricepsz",
|
||||||
|
"Shoulders": "Vállak",
|
||||||
|
"Body Compositions": "Testformálás",
|
||||||
|
"BMI": "Testtömegindex",
|
||||||
|
"BMR": "Alapanyagcsere érték",
|
||||||
|
"Sizes": "Méretek",
|
||||||
|
"Save Exercise": "gyakorlat mentése",
|
||||||
|
"Save": "Save",
|
||||||
|
|
||||||
|
"Name": "Név",
|
||||||
|
"Exercise": "Gyakorlat",
|
||||||
|
"Quantity": "Mennyiség",
|
||||||
|
"Unit": "Egység",
|
||||||
|
"Exercise date and time": "A gyakorlat időpontja",
|
||||||
|
"Please type the right quantity 0-1000": "Kérlek írj be egy helyes számot 0-10000 között",
|
||||||
|
|
||||||
|
"repeat": "ismétlés",
|
||||||
|
"meter": "meter",
|
||||||
|
"percent": "százalék",
|
||||||
|
"kg": "kg",
|
||||||
|
"lbs": "lbs",
|
||||||
|
"second": "másodperc",
|
||||||
|
|
||||||
|
"Email": "Email",
|
||||||
|
"Password": "Jelszó",
|
||||||
|
"Password (Leave empty if you don't want to change)":"Jelszó (hagyd üresen, ha nem akarod megváltoztatni)",
|
||||||
|
"First Name": "Keresztnév",
|
||||||
|
"Birth Year": "Születési év",
|
||||||
|
"Weight": "Tömeg",
|
||||||
|
"Gender": "Nemed",
|
||||||
|
"Man": "Férfi",
|
||||||
|
"Woman": "Nő",
|
||||||
|
"Next": "Tovább",
|
||||||
|
"Select a gender": "Válaszd ki a nemet",
|
||||||
|
|
||||||
|
"Goal Settings": "Cél"
|
||||||
|
|
||||||
|
}
|
@ -29,8 +29,6 @@
|
|||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
|
||||||
</array>
|
</array>
|
||||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
<array>
|
<array>
|
||||||
|
55
lib/localization/app_language.dart
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
class AppLanguage extends ChangeNotifier {
|
||||||
|
static final AppLanguage _singleton = AppLanguage._internal();
|
||||||
|
|
||||||
|
Locale _appLocale = Locale('en');
|
||||||
|
|
||||||
|
factory AppLanguage() {
|
||||||
|
return _singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppLanguage._internal();
|
||||||
|
|
||||||
|
static Future<AppLanguage> getInstance() async {
|
||||||
|
return _singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
Locale get appLocal => _appLocale ?? Locale("en");
|
||||||
|
|
||||||
|
fetchLocale() async {
|
||||||
|
var prefs = await SharedPreferences.getInstance();
|
||||||
|
if (prefs.getString('language_code') == null) {
|
||||||
|
_appLocale = Locale('en');
|
||||||
|
}
|
||||||
|
_appLocale = Locale(prefs.getString('language_code'));
|
||||||
|
print(" ---- Fetched lang: " + _appLocale.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
getLocale(SharedPreferences prefs) {
|
||||||
|
if (prefs.getString('language_code') == null) {
|
||||||
|
_appLocale = Locale('en');
|
||||||
|
}
|
||||||
|
_appLocale = Locale(prefs.getString('language_code'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void changeLanguage(Locale type) async {
|
||||||
|
var prefs = await SharedPreferences.getInstance();
|
||||||
|
if (_appLocale == type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type == Locale("hu")) {
|
||||||
|
_appLocale = Locale("hu");
|
||||||
|
await prefs.setString('language_code', 'hu');
|
||||||
|
await prefs.setString('countryCode', 'HU');
|
||||||
|
} else {
|
||||||
|
_appLocale = Locale("en");
|
||||||
|
await prefs.setString('language_code', 'en');
|
||||||
|
await prefs.setString('countryCode', 'US');
|
||||||
|
}
|
||||||
|
print(" ---- Stored lang: " + _appLocale.toString());
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
70
lib/localization/app_localization.dart
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
class AppLocalizations {
|
||||||
|
Locale locale;
|
||||||
|
|
||||||
|
AppLocalizations(this.locale);
|
||||||
|
|
||||||
|
// Helper method to keep the code in the widgets concise
|
||||||
|
// Localizations are accessed using an InheritedWidget "of" syntax
|
||||||
|
static AppLocalizations of(BuildContext context) {
|
||||||
|
return Localizations.of<AppLocalizations>(context, AppLocalizations);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static member to have a simple access to the delegate from the MaterialApp
|
||||||
|
static const LocalizationsDelegate<AppLocalizations> delegate =
|
||||||
|
_AppLocalizationsDelegate();
|
||||||
|
|
||||||
|
Map<String, String> _localizedStrings;
|
||||||
|
|
||||||
|
setLocale(Locale locale) {
|
||||||
|
this.locale = locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> load() async {
|
||||||
|
// Load the language JSON file from the "lang" folder
|
||||||
|
String jsonString =
|
||||||
|
await rootBundle.loadString('i18n/${locale.languageCode}.json');
|
||||||
|
Map<String, dynamic> jsonMap = json.decode(jsonString);
|
||||||
|
|
||||||
|
_localizedStrings = jsonMap.map((key, value) {
|
||||||
|
return MapEntry(key, value.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method will be called from every widget which needs a localized text
|
||||||
|
String translate(String key) {
|
||||||
|
return _localizedStrings[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppLocalizationsDelegate
|
||||||
|
extends LocalizationsDelegate<AppLocalizations> {
|
||||||
|
// This delegate instance will never change (it doesn't even have fields!)
|
||||||
|
// It can provide a constant constructor.
|
||||||
|
const _AppLocalizationsDelegate();
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isSupported(Locale locale) {
|
||||||
|
// Include all of your supported language codes here
|
||||||
|
return ['en', 'hu'].contains(locale.languageCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<AppLocalizations> load(Locale locale) async {
|
||||||
|
// AppLocalizations class is where the JSON loading actually runs
|
||||||
|
AppLocalizations localizations = new AppLocalizations(locale);
|
||||||
|
await localizations.load();
|
||||||
|
return localizations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
||||||
|
}
|
334
lib/main.dart
@ -1,33 +1,43 @@
|
|||||||
import 'package:aitrainer_app/model/auth.dart';
|
import 'package:aitrainer_app/view/account.dart';
|
||||||
import 'package:aitrainer_app/service/api.dart';
|
import 'package:aitrainer_app/view/customer_bodytype_page.dart';
|
||||||
import 'package:aitrainer_app/service/customer_service.dart';
|
import 'package:aitrainer_app/view/customer_fitness_page.dart';
|
||||||
|
import 'package:aitrainer_app/view/customer_goal_page.dart';
|
||||||
import 'package:aitrainer_app/view/customer_modify_page.dart';
|
import 'package:aitrainer_app/view/customer_modify_page.dart';
|
||||||
import 'package:aitrainer_app/view/customer_new_page.dart';
|
import 'package:aitrainer_app/view/customer_new_page.dart';
|
||||||
|
import 'package:aitrainer_app/view/customer_welcome_page.dart';
|
||||||
|
import 'package:aitrainer_app/view/gdpr.dart';
|
||||||
import 'package:aitrainer_app/view/login.dart';
|
import 'package:aitrainer_app/view/login.dart';
|
||||||
import 'package:aitrainer_app/view/exercise_new_page.dart';
|
import 'package:aitrainer_app/view/exercise_new_page.dart';
|
||||||
import 'package:aitrainer_app/view/exercise_type_modify_page.dart';
|
import 'package:aitrainer_app/view/exercise_type_modify_page.dart';
|
||||||
import 'package:aitrainer_app/view/exercise_type_new_page.dart';
|
import 'package:aitrainer_app/view/exercise_type_new_page.dart';
|
||||||
|
import 'package:aitrainer_app/view/menu_page.dart';
|
||||||
import 'package:aitrainer_app/view/registration.dart';
|
import 'package:aitrainer_app/view/registration.dart';
|
||||||
|
import 'package:aitrainer_app/view/settings.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/home.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/loading.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:aitrainer_app/view/customer_list_page.dart';
|
import 'package:aitrainer_app/view/customer_list_page.dart';
|
||||||
import 'package:aitrainer_app/view/exercise_type_list_page.dart';
|
import 'package:aitrainer_app/view/exercise_type_list_page.dart';
|
||||||
import 'package:aitrainer_app/widgets/nav_drawer.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(
|
runApp(
|
||||||
MultiProvider(
|
MultiProvider(
|
||||||
// Initialize the model in the builder. That way, Provider
|
// Initialize the model in the builder. That way, Provider
|
||||||
// can own Models's lifecycle, making sure to call `dispose`
|
// can own Models's lifecycle, making sure to call `dispose`
|
||||||
// when not needed anymore.
|
// when not needed anymore.
|
||||||
providers: [
|
providers: [
|
||||||
ChangeNotifierProvider(create: (context) => ExerciseChangingViewModel(null)),
|
ChangeNotifierProvider(create: (context) => ExerciseChangingViewModel(null)),
|
||||||
],
|
ChangeNotifierProvider(create: (context) => CustomerChangingViewModel(null)),
|
||||||
child: AitrainerApp(),
|
],
|
||||||
|
|
||||||
|
child: AitrainerApp(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -36,308 +46,54 @@ class AitrainerApp extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
localizationsDelegates: [
|
localizationsDelegates: [
|
||||||
// ... app-specific localization delegate[s] here
|
// ... app-specific localization delegate[s] here
|
||||||
GlobalMaterialLocalizations.delegate,
|
AppLocalizations.delegate,
|
||||||
GlobalWidgetsLocalizations.delegate,
|
GlobalWidgetsLocalizations.delegate,
|
||||||
GlobalCupertinoLocalizations.delegate,
|
GlobalCupertinoLocalizations.delegate,
|
||||||
],
|
],
|
||||||
supportedLocales: [
|
supportedLocales: [
|
||||||
const Locale('en'), // English
|
const Locale('en', "US"), // English
|
||||||
const Locale('hu'), // Hungarian
|
const Locale('hu', "HU"), // Hungarian
|
||||||
// ... other locales the app supports
|
// ... other locales the app supports
|
||||||
],
|
],
|
||||||
routes: {
|
routes: {
|
||||||
'home': (context) => AitrainerHome(),
|
'home': (context) => AitrainerHome(),
|
||||||
|
'loading': (context) => LoadingScreenMain(),
|
||||||
'customersPage': (context) => CustomerListPage(),
|
'customersPage': (context) => CustomerListPage(),
|
||||||
'customerNewPage': (context) => CustomerNewPage(),
|
'customerNewPage': (context) => CustomerNewPage(),
|
||||||
'customerModifyPage': (context) => CustomerModifyPage(),
|
'customerModifyPage': (context) => CustomerModifyPage(),
|
||||||
|
'customerGoalPage': (context) => CustomerGoalPage(),
|
||||||
|
'customerFitnessPage': (context) => CustomerFitnessPage(),
|
||||||
|
'customerBodyTypePage': (context) => CustomerBodyTypePage(),
|
||||||
|
'customerWelcomePage': (context) => CustomerWelcomePage(),
|
||||||
'exerciseTypeListPage': (context) => ExerciseTypeListPage(),
|
'exerciseTypeListPage': (context) => ExerciseTypeListPage(),
|
||||||
'exerciseTypeNewPage': (context) => ExerciseTypeNewPage(),
|
'exerciseTypeNewPage': (context) => ExerciseTypeNewPage(),
|
||||||
'exerciseTypeModifyPage': (context) => ExerciseTypeModifyPage(),
|
'exerciseTypeModifyPage': (context) => ExerciseTypeModifyPage(),
|
||||||
'exerciseNewPage': (context) => ExerciseNewPage(),
|
'exerciseNewPage': (context) => ExerciseNewPage(),
|
||||||
'login': (context) => LoginPage(),
|
'login': (context) => LoginPage(),
|
||||||
'registration': (context) => RegistrationPage(),
|
'registration': (context) => RegistrationPage(),
|
||||||
|
'gdpr': (context) => Gdpr(),
|
||||||
|
'menu_page': (context) => MenuPage(),
|
||||||
|
'account': (context) => AccountPage(),
|
||||||
|
'settings': (context) => SettingsPage(),
|
||||||
},
|
},
|
||||||
initialRoute: 'home',
|
initialRoute: 'loading',
|
||||||
title: 'Aitrainer Demo',
|
title: 'Aitrainer',
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
primarySwatch: Colors.green,
|
brightness: Brightness.light,
|
||||||
),
|
//primarySwatch: Colors.transparent,
|
||||||
home: AitrainerHome(),
|
fontFamily: 'Arial',
|
||||||
);
|
textTheme: TextTheme(
|
||||||
}
|
bodyText1: TextStyle(fontSize: 14.0),
|
||||||
}
|
|
||||||
|
|
||||||
class AitrainerHome extends StatefulWidget {
|
|
||||||
static final String routeName = 'home';
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<StatefulWidget> createState() {
|
|
||||||
return new _HomePageState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _HomePageState extends State<AitrainerHome> {
|
|
||||||
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
|
||||||
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
|
|
||||||
Auth _auth = Auth();
|
|
||||||
SharedPreferences _sharedPreferences;
|
|
||||||
var _authToken;
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_fetchSessionAndNavigate();
|
|
||||||
}
|
|
||||||
|
|
||||||
_fetchSessionAndNavigate() async {
|
|
||||||
_sharedPreferences = await _prefs;
|
|
||||||
String authToken = Auth.getToken(_sharedPreferences);
|
|
||||||
var customerId = _sharedPreferences.getInt(Auth.customerIdKey);
|
|
||||||
|
|
||||||
if ( _auth.firstLoad ) {
|
|
||||||
_fetchToken(_sharedPreferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Auth flow of the user, see auth.dart
|
|
||||||
*/
|
|
||||||
_fetchToken(SharedPreferences prefs) async {
|
|
||||||
var responseJson = await APIClient.authenticateUser(
|
|
||||||
Auth.username,
|
|
||||||
Auth.password
|
|
||||||
);
|
|
||||||
|
|
||||||
if(responseJson['error'] != null) {
|
|
||||||
showSnackBar(_scaffoldKey, responseJson['error']);
|
|
||||||
print("************** Here big error - no authentication");
|
|
||||||
} else if (responseJson['token'] != null) {
|
|
||||||
prefs.setString(Auth.authTokenKey, responseJson['token']);
|
|
||||||
Auth auth = Auth();
|
|
||||||
auth.authToken = responseJson['token'];
|
|
||||||
if ( prefs.get(Auth.customerIdKey) == null ) {
|
|
||||||
print("************** Registration");
|
|
||||||
// registration
|
|
||||||
Navigator.of(context).pushNamed('registration');
|
|
||||||
prefs.setBool(Auth.isRegisteredKey, true);
|
|
||||||
} else {
|
|
||||||
DateTime now = DateTime.now();
|
|
||||||
DateTime lastStoreDate = DateTime.parse( prefs.get(Auth.lastStoreDateKey) );
|
|
||||||
DateTime minStoreDate = now.add(Duration(days: -10));
|
|
||||||
|
|
||||||
if ( lastStoreDate == null ||
|
|
||||||
lastStoreDate.difference(minStoreDate) > Duration(days: 10) ||
|
|
||||||
prefs.get(Auth.isLoggedInKey) == null ||
|
|
||||||
prefs.get(Auth.isLoggedInKey) == false ) {
|
|
||||||
print("************* Login");
|
|
||||||
Navigator.of(context).pushNamed('login');
|
|
||||||
|
|
||||||
} else {
|
|
||||||
print("************** Store SharedPreferences");
|
|
||||||
// get API customer
|
|
||||||
await CustomerApi().getCustomer( prefs.getInt(Auth.customerIdKey));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_auth.firstLoad = false;
|
|
||||||
_authToken = auth.authToken;
|
|
||||||
_sharedPreferences.setString(Auth.authTokenKey, _authToken);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static showSnackBar(GlobalKey<ScaffoldState> scaffoldKey, String message) {
|
|
||||||
scaffoldKey.currentState.showSnackBar(
|
|
||||||
new SnackBar(
|
|
||||||
content: new Text(message ?? 'You are offline'),
|
|
||||||
)
|
)
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
key: _scaffoldKey,
|
|
||||||
drawer: NavDrawer(),
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('Home'),
|
|
||||||
backgroundColor: Colors.transparent
|
|
||||||
),
|
),
|
||||||
body: Image.asset('asset/WT01_loading_layers.png',
|
home: LoadingScreenMain(),
|
||||||
fit: BoxFit.fill,
|
|
||||||
height: double.infinity,
|
|
||||||
width: double.infinity,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
),
|
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
class CustomerScreen extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
drawer: NavDrawer(),
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('Customers'),
|
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
child: CustomerListPage(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* class AitrainerApp extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return MaterialApp(
|
|
||||||
title: "AITRAINER customers",
|
|
||||||
home:
|
|
||||||
ChangeNotifierProvider(
|
|
||||||
create: (context) => CustomerListViewModel(),
|
|
||||||
child: CustomerListPage(),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
// #docregion MyApp
|
|
||||||
class MyApp extends StatelessWidget {
|
|
||||||
// #docregion build
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return MaterialApp(
|
|
||||||
title: 'Startup Name Generator',
|
|
||||||
theme: ThemeData( // Add the 3 lines from here...
|
|
||||||
primaryColor: Colors.white,
|
|
||||||
),
|
|
||||||
home: RandomWords(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// #enddocregion build
|
|
||||||
}
|
|
||||||
// #enddocregion MyApp
|
|
||||||
|
|
||||||
// #docregion RWS-var
|
|
||||||
class RandomWordsState extends State<RandomWords> {
|
|
||||||
final _suggestions = <WordPair>[];
|
|
||||||
final _biggerFont = const TextStyle(fontSize: 18.0);
|
|
||||||
final Set<WordPair> _saved = Set<WordPair>();
|
|
||||||
|
|
||||||
// #enddocregion RWS-var
|
|
||||||
|
|
||||||
// #docregion _buildSuggestions
|
|
||||||
Widget _buildSuggestions() {
|
|
||||||
return ListView.builder(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
itemBuilder: /*1*/ (context, i) {
|
|
||||||
if (i.isOdd) return Divider(); /*2*/
|
|
||||||
|
|
||||||
final index = i ~/ 2; /*3*/
|
|
||||||
if (index >= _suggestions.length) {
|
|
||||||
_suggestions.addAll(generateWordPairs().take(10)); /*4*/
|
|
||||||
}
|
|
||||||
return _buildRow(_suggestions[index]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// #enddocregion _buildSuggestions
|
|
||||||
|
|
||||||
// #docregion _buildRow
|
|
||||||
Widget _buildRow(WordPair pair) {
|
|
||||||
final bool alreadySaved = _saved.contains(pair);
|
|
||||||
return ListTile(
|
|
||||||
title: Text(
|
|
||||||
pair.asPascalCase,
|
|
||||||
style: _biggerFont,
|
|
||||||
),
|
|
||||||
trailing: Icon( // Add the lines from here...
|
|
||||||
alreadySaved ? Icons.favorite : Icons.favorite_border,
|
|
||||||
color: alreadySaved ? Colors.red : null,
|
|
||||||
),
|
|
||||||
onTap: () { // Add 9 lines from here...
|
|
||||||
setState(() {
|
|
||||||
if (alreadySaved) {
|
|
||||||
_saved.remove(pair);
|
|
||||||
} else {
|
|
||||||
_saved.add(pair);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// #enddocregion _buildRow
|
|
||||||
|
|
||||||
// #docregion RWS-build
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('Startup Name Generator'),
|
|
||||||
actions: <Widget>[ // Add 3 lines from here...
|
|
||||||
IconButton(icon: Icon(Icons.list), onPressed: _pushSaved),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: _buildSuggestions(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _pushSaved() {
|
|
||||||
Navigator.of(context).push(
|
|
||||||
MaterialPageRoute<void>( // Add 20 lines from here...
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
final Iterable<ListTile> tiles = _saved.map(
|
|
||||||
(WordPair pair) {
|
|
||||||
return ListTile(
|
|
||||||
title: Text(
|
|
||||||
pair.asPascalCase,
|
|
||||||
style: _biggerFont,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
final List<Widget> divided = ListTile
|
|
||||||
.divideTiles(
|
|
||||||
context: context,
|
|
||||||
tiles: tiles,
|
|
||||||
).toList();
|
|
||||||
return Scaffold( // Add 6 lines from here...
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('Saved Suggestions'),
|
|
||||||
),
|
|
||||||
body: ListView(children: divided),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
),
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// #enddocregion RWS-build
|
|
||||||
// #docregion RWS-var
|
|
||||||
}
|
|
||||||
// #enddocregion RWS-var
|
|
||||||
|
|
||||||
class RandomWords extends StatefulWidget {
|
|
||||||
@override
|
|
||||||
RandomWordsState createState() => new RandomWordsState();
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'package:aitrainer_app/model/customer.dart';
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
|
import 'package:aitrainer_app/service/exercisetype_service.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
|
||||||
enum SharePrefsChange {
|
enum SharePrefsChange {
|
||||||
login,
|
login,
|
||||||
@ -40,6 +42,7 @@ class Auth {
|
|||||||
String authToken = "";
|
String authToken = "";
|
||||||
Customer userLoggedIn;
|
Customer userLoggedIn;
|
||||||
bool firstLoad = true;
|
bool firstLoad = true;
|
||||||
|
List<ExerciseType> _exerciseTypes;
|
||||||
|
|
||||||
factory Auth() {
|
factory Auth() {
|
||||||
return _singleton;
|
return _singleton;
|
||||||
@ -79,6 +82,7 @@ class Auth {
|
|||||||
//firstLoad = true;
|
//firstLoad = true;
|
||||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||||
setPreferences(prefs, SharePrefsChange.logout, 0);
|
setPreferences(prefs, SharePrefsChange.logout, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setPreferences(Future<SharedPreferences> prefs,
|
setPreferences(Future<SharedPreferences> prefs,
|
||||||
@ -93,13 +97,24 @@ class Auth {
|
|||||||
sharedPreferences.setInt(Auth.customerIdKey, customerId);
|
sharedPreferences.setInt(Auth.customerIdKey, customerId);
|
||||||
sharedPreferences.setBool(Auth.isRegisteredKey, true);
|
sharedPreferences.setBool(Auth.isRegisteredKey, true);
|
||||||
sharedPreferences.setBool(Auth.isLoggedInKey, true);
|
sharedPreferences.setBool(Auth.isLoggedInKey, true);
|
||||||
|
await ExerciseTypeApi().getExerciseTypes("");
|
||||||
} else if ( type == SharePrefsChange.login ) {
|
} else if ( type == SharePrefsChange.login ) {
|
||||||
|
|
||||||
sharedPreferences.setInt(Auth.customerIdKey, customerId);
|
sharedPreferences.setInt(Auth.customerIdKey, customerId);
|
||||||
sharedPreferences.setBool(Auth.isLoggedInKey, true);
|
sharedPreferences.setBool(Auth.isLoggedInKey, true);
|
||||||
} else if ( type == SharePrefsChange.login ) {
|
await ExerciseTypeApi().getExerciseTypes("");
|
||||||
|
} else if ( type == SharePrefsChange.logout ) {
|
||||||
sharedPreferences.setBool(Auth.isLoggedInKey, false);
|
sharedPreferences.setBool(Auth.isLoggedInKey, false);
|
||||||
sharedPreferences.setInt(Auth.customerIdKey, 0);
|
//sharedPreferences.setInt(Auth.customerIdKey, 0);
|
||||||
|
sharedPreferences.setString(authTokenKey, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setExerciseTypes( List<ExerciseType> exerciseTypes) {
|
||||||
|
this._exerciseTypes = exerciseTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ExerciseType> getExerciseTypes() {
|
||||||
|
return this._exerciseTypes;
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,18 +7,46 @@ class Customer {
|
|||||||
String active;
|
String active;
|
||||||
int customerId;
|
int customerId;
|
||||||
String password;
|
String password;
|
||||||
|
int birthYear;
|
||||||
|
int weight;
|
||||||
|
String goal;
|
||||||
|
String fitnessLevel;
|
||||||
|
String bodyType;
|
||||||
|
int admin;
|
||||||
|
int dataPolicyAllowed;
|
||||||
|
|
||||||
|
|
||||||
Customer({this.customerId, this.name, this.firstName, this.email, this.sex, this.age, this.active, this.password});
|
Customer({this.customerId,
|
||||||
|
this.name,
|
||||||
|
this.firstName,
|
||||||
|
this.email,
|
||||||
|
this.sex,
|
||||||
|
this.age,
|
||||||
|
this.active,
|
||||||
|
this.password,
|
||||||
|
this.birthYear,
|
||||||
|
this.bodyType,
|
||||||
|
this.fitnessLevel,
|
||||||
|
this.goal,
|
||||||
|
this.weight,
|
||||||
|
this.admin,
|
||||||
|
this.dataPolicyAllowed
|
||||||
|
});
|
||||||
|
|
||||||
Customer.fromJson(Map json) {
|
Customer.fromJson(Map json) {
|
||||||
this.customerId = json['customer_id'];
|
this.customerId = json['customerId'];
|
||||||
this.name = json['name'];
|
this.name = json['name'];
|
||||||
this.firstName = json['firstname'];
|
this.firstName = json['firstname'];
|
||||||
this.email = json['email'];
|
this.email = json['email'];
|
||||||
this.sex = json['sex'];
|
this.sex = json['sex'];
|
||||||
this.age = json['age'];
|
this.age = json['age'];
|
||||||
this.active = json['active'];
|
this.active = json['active'];
|
||||||
|
this.birthYear = json['birthYear'];
|
||||||
|
this.bodyType = json['bodyType'];
|
||||||
|
this.fitnessLevel = json['fitnessLevel'];
|
||||||
|
this.goal = json['goal'];
|
||||||
|
this.weight = json['weight'];
|
||||||
|
this.admin = json['admin'];
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() =>
|
Map<String, dynamic> toJson() =>
|
||||||
@ -30,5 +58,12 @@ class Customer {
|
|||||||
"sex": sex,
|
"sex": sex,
|
||||||
"active": 'Y',
|
"active": 'Y',
|
||||||
"password": password,
|
"password": password,
|
||||||
|
"birthYear": birthYear,
|
||||||
|
"bodyType": bodyType,
|
||||||
|
"fitnessLevel": fitnessLevel,
|
||||||
|
"goal": goal,
|
||||||
|
"weight": weight,
|
||||||
|
"admin": admin,
|
||||||
|
"dataPolicyAllowed": dataPolicyAllowed,
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -4,18 +4,22 @@ class Exercise {
|
|||||||
int exerciseId;
|
int exerciseId;
|
||||||
int exerciseTypeId;
|
int exerciseTypeId;
|
||||||
int customerId;
|
int customerId;
|
||||||
int quantity;
|
double quantity;
|
||||||
DateTime datetimeExercise;
|
String unit;
|
||||||
|
double unitQuantity;
|
||||||
|
DateTime dateAdd;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Exercise({this.exerciseTypeId, this.customerId, this.quantity, this.datetimeExercise});
|
Exercise({this.exerciseTypeId, this.customerId, this.quantity, this.dateAdd});
|
||||||
|
|
||||||
Exercise.fromJson(Map json) {
|
Exercise.fromJson(Map json) {
|
||||||
this.exerciseTypeId = json['exerciseTypeId'];
|
this.exerciseTypeId = json['exerciseTypeId'];
|
||||||
this.customerId = json['customerId'];
|
this.customerId = json['customerId'];
|
||||||
this.quantity = json['quantity'];
|
this.quantity = json['quantity'];
|
||||||
this.datetimeExercise = json['datetimeExercise'];
|
this.unit = json['unit'];
|
||||||
|
this.unitQuantity = json['unitQuantity'];
|
||||||
|
this.dateAdd = DateTime.parse( json['dateAdd'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() =>
|
Map<String, dynamic> toJson() =>
|
||||||
@ -23,7 +27,8 @@ class Exercise {
|
|||||||
"exerciseTypeId": exerciseTypeId,
|
"exerciseTypeId": exerciseTypeId,
|
||||||
"customerId": customerId,
|
"customerId": customerId,
|
||||||
"quantity": quantity,
|
"quantity": quantity,
|
||||||
|
"unit": unit,
|
||||||
"datetimeExercise": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.datetimeExercise),
|
"unitQuantity": unitQuantity,
|
||||||
|
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd),
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -5,6 +5,9 @@ class ExerciseType {
|
|||||||
String name;
|
String name;
|
||||||
String description;
|
String description;
|
||||||
BinaryCodec video;
|
BinaryCodec video;
|
||||||
|
String unit;
|
||||||
|
String unitQuantity;
|
||||||
|
String unitQuantityUnit;
|
||||||
|
|
||||||
ExerciseType({this.name, this.description});
|
ExerciseType({this.name, this.description});
|
||||||
|
|
||||||
@ -12,11 +15,17 @@ class ExerciseType {
|
|||||||
this.exerciseTypeId = json['exerciseTypeId'];
|
this.exerciseTypeId = json['exerciseTypeId'];
|
||||||
this.name = json['name'];
|
this.name = json['name'];
|
||||||
this.description = json['description'];
|
this.description = json['description'];
|
||||||
|
this.unit = json['unit'];
|
||||||
|
this.unitQuantity = json['unitQuantity'];
|
||||||
|
this.unitQuantityUnit = json['unitQuantityUnit'];
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() =>
|
Map<String, dynamic> toJson() =>
|
||||||
{
|
{
|
||||||
"name": name,
|
"name": name,
|
||||||
"description": description,
|
"description": description,
|
||||||
|
"unit": unit,
|
||||||
|
"unitQuantity": unitQuantity,
|
||||||
|
"unitQuantityUnit": unitQuantityUnit
|
||||||
};
|
};
|
||||||
}
|
}
|
16
lib/model/workout_tree.dart
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
class WorkoutTree {
|
||||||
|
int id;
|
||||||
|
int parent;
|
||||||
|
String name; // is also the key
|
||||||
|
String imageName;
|
||||||
|
Color color;
|
||||||
|
double fontSize;
|
||||||
|
bool child;
|
||||||
|
int exercise_type_id;
|
||||||
|
|
||||||
|
WorkoutTree(this.id, this.parent, this.name, this.imageName, this.color, this.fontSize, this.child, this.exercise_type_id);
|
||||||
|
|
||||||
|
}
|
@ -7,11 +7,18 @@ class APIClient extends ChangeNotifier {
|
|||||||
|
|
||||||
Future<String> get(String endPoint, String param) async {
|
Future<String> get(String endPoint, String param) async {
|
||||||
final url = Auth.getBaseUrl() + endPoint + param;
|
final url = Auth.getBaseUrl() + endPoint + param;
|
||||||
Auth auth = Auth();
|
String authToken = Auth().getAuthToken();
|
||||||
|
if ( authToken.length == 0 ) {
|
||||||
|
var responseJson = await APIClient.authenticateUser(
|
||||||
|
Auth.username,
|
||||||
|
Auth.password
|
||||||
|
);
|
||||||
|
authToken = responseJson['token'];
|
||||||
|
}
|
||||||
final response = await http.get(url,
|
final response = await http.get(url,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization' : "Bearer " + auth.getAuthToken() }
|
'Authorization' : "Bearer " + authToken }
|
||||||
);
|
);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
if(response.statusCode == 200) {
|
if(response.statusCode == 200) {
|
||||||
@ -24,11 +31,18 @@ class APIClient extends ChangeNotifier {
|
|||||||
Future<String> post(String endPoint, String body) async {
|
Future<String> post(String endPoint, String body) async {
|
||||||
final url = Auth.getBaseUrl() + endPoint;
|
final url = Auth.getBaseUrl() + endPoint;
|
||||||
print(" ------------ http/post endpoint $endPoint body $body - url: $url ");
|
print(" ------------ http/post endpoint $endPoint body $body - url: $url ");
|
||||||
Auth auth = Auth();
|
String authToken = Auth().getAuthToken();
|
||||||
|
if ( authToken.length == 0 ) {
|
||||||
|
var responseJson = await APIClient.authenticateUser(
|
||||||
|
Auth.username,
|
||||||
|
Auth.password
|
||||||
|
);
|
||||||
|
authToken = responseJson['token'];
|
||||||
|
}
|
||||||
final response = await http.post(url,
|
final response = await http.post(url,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization' : "Bearer " + auth.getAuthToken()
|
'Authorization' : "Bearer " + authToken
|
||||||
},
|
},
|
||||||
body: body
|
body: body
|
||||||
);
|
);
|
||||||
@ -59,7 +73,8 @@ class APIClient extends ChangeNotifier {
|
|||||||
return responseJson;
|
return responseJson;
|
||||||
|
|
||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
return { "error" : "Network error, try again later"};
|
return { "error" : "Network error, try again later "
|
||||||
|
+ exception.toString()};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +37,8 @@ class CustomerApi {
|
|||||||
final String responseBody = await _client.post(
|
final String responseBody = await _client.post(
|
||||||
"registration",
|
"registration",
|
||||||
body);
|
body);
|
||||||
Auth auth = Auth();
|
|
||||||
Customer customer = Customer.fromJson(jsonDecode(responseBody));
|
Customer customer = Customer.fromJson(jsonDecode(responseBody));
|
||||||
auth.afterRegistration(customer);
|
Auth().afterRegistration(customer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,9 +48,8 @@ class CustomerApi {
|
|||||||
final String responseBody = await _client.post(
|
final String responseBody = await _client.post(
|
||||||
"login",
|
"login",
|
||||||
body);
|
body);
|
||||||
Auth auth = Auth();
|
|
||||||
Customer customer = Customer.fromJson(jsonDecode(responseBody));
|
Customer customer = Customer.fromJson(jsonDecode(responseBody));
|
||||||
auth.afterRegistration(customer);
|
Auth().afterRegistration(customer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getCustomer(int customerId) async {
|
Future<void> getCustomer(int customerId) async {
|
||||||
@ -60,8 +58,7 @@ class CustomerApi {
|
|||||||
final String responseBody = await _client.get(
|
final String responseBody = await _client.get(
|
||||||
"customers/"+customerId.toString(),
|
"customers/"+customerId.toString(),
|
||||||
body);
|
body);
|
||||||
Auth auth = Auth();
|
|
||||||
Customer customer = Customer.fromJson(jsonDecode(responseBody));
|
Customer customer = Customer.fromJson(jsonDecode(responseBody));
|
||||||
auth.afterRegistration(customer);
|
Auth().afterRegistration(customer);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,4 +30,12 @@ class ExerciseApi {
|
|||||||
body);
|
body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<Exercise>> getExercisesByCustomer(int customerId ) async {
|
||||||
|
final body = await _client.get("exercises/customer/", customerId.toString() );
|
||||||
|
final Iterable json = jsonDecode(body);
|
||||||
|
final List<Exercise> exercises = json.map( (exercise) => Exercise.fromJson(exercise) ).toList();
|
||||||
|
|
||||||
|
return exercises;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
import 'package:aitrainer_app/service/api.dart';
|
import 'package:aitrainer_app/service/api.dart';
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ class ExerciseTypeApi {
|
|||||||
final body = await _client.get("exercise_type", param);
|
final body = await _client.get("exercise_type", param);
|
||||||
final Iterable json = jsonDecode(body);
|
final Iterable json = jsonDecode(body);
|
||||||
final List<ExerciseType> exerciseTypes = json.map( (exerciseType) => ExerciseType.fromJson(exerciseType) ).toList();
|
final List<ExerciseType> exerciseTypes = json.map( (exerciseType) => ExerciseType.fromJson(exerciseType) ).toList();
|
||||||
|
Auth().setExerciseTypes(exerciseTypes);
|
||||||
return exerciseTypes;
|
return exerciseTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
import 'dart:collection';
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
class Common {
|
class Common {
|
||||||
|
|
||||||
@ -13,4 +15,29 @@ class Common {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ExerciseType getExerciseType( int exerciseTypeId ) {
|
||||||
|
ExerciseType returnElement = null;
|
||||||
|
List<ExerciseType> listExerciseType = Auth().getExerciseTypes();
|
||||||
|
if ( listExerciseType != null ) {
|
||||||
|
for ( var element in listExerciseType ) {
|
||||||
|
if (exerciseTypeId == element.exerciseTypeId) {
|
||||||
|
returnElement = element;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return returnElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getDateLocale( DateTime datetime, bool timeDisplay ) {
|
||||||
|
AppLanguage appLanguage = AppLanguage();
|
||||||
|
var date = datetime;
|
||||||
|
|
||||||
|
String dateName = DateFormat(DateFormat.YEAR_MONTH_DAY, appLanguage.appLocal.toString()).format(date.toUtc());
|
||||||
|
if ( timeDisplay ) {
|
||||||
|
dateName += " " +DateFormat(DateFormat.HOUR_MINUTE, appLanguage.appLocal.toString()).format(date.toUtc());
|
||||||
|
}
|
||||||
|
|
||||||
|
return dateName;
|
||||||
|
}
|
||||||
}
|
}
|
61
lib/util/loading_screen.dart
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import 'package:aitrainer_app/util/loading_screen_state.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
||||||
|
|
||||||
|
/// Loading Screen Widget that updates the screen once all inistializer methods
|
||||||
|
/// are called
|
||||||
|
class LoadingScreen extends StatefulWidget {
|
||||||
|
/// List of methods that are called once the Loading Screen is rendered
|
||||||
|
/// for the first time. These are the methods that can update the messages
|
||||||
|
/// that are shown under the loading symbol
|
||||||
|
final List<dynamic> initializers;
|
||||||
|
|
||||||
|
/// The name of the application that is shown at the top of the loading screen
|
||||||
|
RichText title = RichText(text: TextSpan(text: 'AI Trainer'));
|
||||||
|
//final Text title;
|
||||||
|
|
||||||
|
/// The background colour which is used as a filler when the image doesn't
|
||||||
|
/// occupy the full screen
|
||||||
|
final Color backgroundColor;
|
||||||
|
|
||||||
|
/// The styling that is used with the text (messages) that are displayed under
|
||||||
|
/// the loader symbol
|
||||||
|
final TextStyle styleTextUnderTheLoader;
|
||||||
|
|
||||||
|
/// The Layout/Scaffold Widget that is loaded once all the initializer methods
|
||||||
|
/// have been executed
|
||||||
|
final dynamic navigateToWidget;
|
||||||
|
|
||||||
|
/// The colour that is used for the loader symbol
|
||||||
|
final Color loaderColor;
|
||||||
|
|
||||||
|
/// The image widget that is used as a background cover to the loading screen
|
||||||
|
final Image image;
|
||||||
|
|
||||||
|
/// The message that is displayed on the first load of the widget
|
||||||
|
final String initialMessage;
|
||||||
|
|
||||||
|
/// Constructor for the LoadingScreen widget with all the required
|
||||||
|
/// initializers
|
||||||
|
LoadingScreen(
|
||||||
|
{this.initializers,
|
||||||
|
this.navigateToWidget,
|
||||||
|
this.loaderColor,
|
||||||
|
this.image,
|
||||||
|
//this.title = Text("Welcome"),
|
||||||
|
this.backgroundColor = Colors.white,
|
||||||
|
this.styleTextUnderTheLoader = const TextStyle(
|
||||||
|
fontSize: 18.0, fontWeight: FontWeight.bold, color: Colors.black),
|
||||||
|
this.initialMessage})
|
||||||
|
// The Widget depends on the initializers and navigateToWidget to have a
|
||||||
|
// valid value. Thus we assert that the values passed are valid and
|
||||||
|
// not null
|
||||||
|
: assert(initializers != null && initializers.length > 0),
|
||||||
|
assert(navigateToWidget != null);
|
||||||
|
|
||||||
|
/// Bind the Widget to the custom State object
|
||||||
|
@override
|
||||||
|
LoadingScreenState createState() => LoadingScreenState();
|
||||||
|
}
|
||||||
|
|
131
lib/util/loading_screen_state.dart
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
import 'dart:core';
|
||||||
|
import 'dart:async';
|
||||||
|
import 'file:///D:/projects/aitrainer/src/aitrainer_app/lib/util/loading_screen.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/home.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
|
import 'package:aitrainer_app/util/message_state.dart';
|
||||||
|
|
||||||
|
/// The custom state that is used by the Loading Screen widget to handle the
|
||||||
|
/// messages that are provided by the initializer methods.
|
||||||
|
///
|
||||||
|
/// Note: Although the class is not exported from the package as not required by
|
||||||
|
/// the implementers using the package, the protected metatag is added to make
|
||||||
|
/// the code clearer.
|
||||||
|
@protected
|
||||||
|
class LoadingScreenState extends MessageState<LoadingScreen> {
|
||||||
|
|
||||||
|
/// Initialise the state
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
/// If the LoadingScreen widget has an initial message set, then the default
|
||||||
|
/// message in the MessageState class needs to be updated
|
||||||
|
if (widget.initialMessage != null) {
|
||||||
|
initialMessage = widget.initialMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// We require the initializers to run after the loading screen is rendered
|
||||||
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
|
runInitTasks();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This method calls the initializers and once they complete redirects to
|
||||||
|
/// the widget provided in navigateAfterInit
|
||||||
|
@protected
|
||||||
|
Future runInitTasks() async {
|
||||||
|
print(" ----- runInitTasks");
|
||||||
|
/// Run each initializer method sequentially
|
||||||
|
Future.forEach(widget.initializers, (init) => init(this, callbackFunction)).whenComplete(() {
|
||||||
|
// When all the initializers has been called and terminated their
|
||||||
|
// execution. The screen is navigated to the next scaffolding widget
|
||||||
|
if (widget.navigateToWidget is String) {
|
||||||
|
// It's fairly safe to assume this is using the in-built material
|
||||||
|
// named route component
|
||||||
|
print(" ----- navigate to " + widget.navigateToWidget);
|
||||||
|
Navigator.of(context).pushReplacementNamed(widget.navigateToWidget);
|
||||||
|
} else if (widget.navigateToWidget is Widget) {
|
||||||
|
Navigator.of(context).pushReplacement(new MaterialPageRoute(
|
||||||
|
builder: (BuildContext context) => widget.navigateToWidget));
|
||||||
|
print(" ----- navigate to main ");
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new ArgumentError(
|
||||||
|
'widget.navigateAfterSeconds must either be a String or Widget');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void callbackFunction() {
|
||||||
|
print("Call Home callback if widget");
|
||||||
|
if (widget.navigateToWidget is Widget) {
|
||||||
|
AitrainerHome home = widget.navigateToWidget as AitrainerHome;
|
||||||
|
home.callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the LoadingScreen widget
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: widget.backgroundColor,
|
||||||
|
body: new InkWell(
|
||||||
|
child: new Stack(
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: <Widget>[
|
||||||
|
/// Paint the area where the inner widgets are loaded with the
|
||||||
|
/// background to keep consistency with the screen background
|
||||||
|
new Container(
|
||||||
|
decoration: BoxDecoration(color: widget.backgroundColor),
|
||||||
|
),
|
||||||
|
/// Render the background image
|
||||||
|
new Container(
|
||||||
|
child: widget.image,
|
||||||
|
),
|
||||||
|
/// Render the Title widget, loader and messages below each other
|
||||||
|
new Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
new Expanded(
|
||||||
|
flex: 3,
|
||||||
|
child: new Container(
|
||||||
|
child: new Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
new Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 30.0),
|
||||||
|
),
|
||||||
|
widget.title,
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
/// Loader Animation Widget
|
||||||
|
CircularProgressIndicator(
|
||||||
|
valueColor: new AlwaysStoppedAnimation<Color>(
|
||||||
|
widget.loaderColor),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 20.0),
|
||||||
|
),
|
||||||
|
Text(getMessage, style: widget.styleTextUnderTheLoader),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
93
lib/util/menu_tests.dart
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class MenuTests {
|
||||||
|
LinkedHashMap tree = LinkedHashMap();
|
||||||
|
|
||||||
|
MenuTests(BuildContext context) {
|
||||||
|
this.tree['Cardio']= WorkoutTree(1, 0, AppLocalizations.of(context).translate("Cardio"),
|
||||||
|
'asset/menu/1.cardio.png',
|
||||||
|
Colors.white, 48, false,0);
|
||||||
|
this.tree['Aerobic']= WorkoutTree(2, 1, AppLocalizations.of(context).translate("Aerobic"),
|
||||||
|
'asset/menu/1.1.aerob.png',
|
||||||
|
Colors.white, 48, false,0);
|
||||||
|
this.tree['Cooper']= WorkoutTree(21, 2, AppLocalizations.of(context).translate("Cooper"),
|
||||||
|
'asset/menu/1.1.1.cooper.png',
|
||||||
|
Colors.white, 48, true,30);
|
||||||
|
this.tree['Anaerobic']= WorkoutTree(3, 1, AppLocalizations.of(context).translate("Anaerobic"),
|
||||||
|
'asset/menu/1.2.anaerob.png',
|
||||||
|
Colors.white, 48, false,0);
|
||||||
|
this.tree['300m']= WorkoutTree(22, 3, "300m",
|
||||||
|
'asset/menu/1.2.1.300m.png',
|
||||||
|
Colors.white, 48, true,31);
|
||||||
|
this.tree['400m']= WorkoutTree(24, 3, "400m",
|
||||||
|
'asset/menu/1.2.2.400m.png',
|
||||||
|
Colors.white, 48, true,32);
|
||||||
|
|
||||||
|
this.tree['Strength']= WorkoutTree(4, 0, AppLocalizations.of(context).translate("Strength"),
|
||||||
|
'asset/menu/2.strength.png',
|
||||||
|
Colors.white, 48, false,0);
|
||||||
|
this.tree['Endurance']= WorkoutTree(5, 4, AppLocalizations.of(context).translate("Endurance"),
|
||||||
|
'asset/menu/2.1.endurance.png',
|
||||||
|
Colors.white, 36, false,0);
|
||||||
|
this.tree['Pullups']= WorkoutTree(6, 5, AppLocalizations.of(context).translate("Pull Ups"),
|
||||||
|
'asset/menu/2.1.1.pull-ups.png',
|
||||||
|
Colors.white, 48, true,38);
|
||||||
|
this.tree['Pushups']= WorkoutTree(7, 5, AppLocalizations.of(context).translate("Pushups"),
|
||||||
|
'asset/menu/2.1.2.pushup.png',
|
||||||
|
Colors.white, 48, true,33);
|
||||||
|
this.tree['Situps']= WorkoutTree(10, 5, AppLocalizations.of(context).translate("Sit-ups"),
|
||||||
|
'asset/menu/2.1.3.sit-ups.png',
|
||||||
|
Colors.white, 48, true,36);
|
||||||
|
this.tree['Squats']= WorkoutTree(11, 5, AppLocalizations.of(context).translate("Squats"),
|
||||||
|
'asset/menu/2.1.4.squats.png',
|
||||||
|
Colors.white, 48, true,35);
|
||||||
|
this.tree['TimedPushups']= WorkoutTree(12, 5, AppLocalizations.of(context).translate("Timed Pushups"),
|
||||||
|
'asset/menu/2.1.5.timedpushup.png',
|
||||||
|
Colors.white, 32, true,34);
|
||||||
|
this.tree['Core']= WorkoutTree(43, 5, AppLocalizations.of(context).translate("Core"),
|
||||||
|
'asset/menu/2.1.6.core.png',
|
||||||
|
Colors.white, 48, true,45);
|
||||||
|
|
||||||
|
this.tree['1RM']= WorkoutTree(8, 4, AppLocalizations.of(context).translate("1RM"),
|
||||||
|
'asset/menu/2.2.1.1RM.png',
|
||||||
|
Colors.white, 48, false,0);
|
||||||
|
this.tree['Chestpress']= WorkoutTree(13, 8, AppLocalizations.of(context).translate("Chest Press"),
|
||||||
|
'asset/menu/2.2.1.1.chestpress.png',
|
||||||
|
Colors.white, 48, true,37);
|
||||||
|
this.tree['PullUps1rm']= WorkoutTree(14, 8, AppLocalizations.of(context).translate("Pull Ups"),
|
||||||
|
'asset/menu/2.2.1.2.pullups.png',
|
||||||
|
Colors.white, 48, true, 38);
|
||||||
|
this.tree['Biceps']= WorkoutTree(15, 8, AppLocalizations.of(context).translate("Biceps"),
|
||||||
|
'asset/menu/2.2.1.3.biceps.png',
|
||||||
|
Colors.white, 48, true, 39);
|
||||||
|
this.tree['Triceps']= WorkoutTree(16, 8, AppLocalizations.of(context).translate("Triceps"),
|
||||||
|
'asset/menu/2.2.1.4.triceps.png',
|
||||||
|
Colors.white, 48, true, 40);
|
||||||
|
this.tree['Shoulders']= WorkoutTree(17, 8, AppLocalizations.of(context).translate("Shoulders"),
|
||||||
|
'asset/menu/2.2.1.5.shoulders.png',
|
||||||
|
Colors.white, 48, true, 41);
|
||||||
|
|
||||||
|
this.tree['BodyCompositions']= WorkoutTree(9, 0, AppLocalizations.of(context).translate("Body Compositions"),
|
||||||
|
'asset/menu/3.bcs1.png',
|
||||||
|
Colors.white, 40, false,0);
|
||||||
|
this.tree['BMI']= WorkoutTree(18, 9, AppLocalizations.of(context).translate("BMI"),
|
||||||
|
'asset/menu/3.1.BMI.png',
|
||||||
|
Colors.white, 32, true,42);
|
||||||
|
this.tree['BMR']= WorkoutTree(19, 9, AppLocalizations.of(context).translate("BMR"),
|
||||||
|
'asset/menu/3.2.BMR.png',
|
||||||
|
Colors.white, 32, true,0);
|
||||||
|
this.tree['Sizes']= WorkoutTree(20, 9, AppLocalizations.of(context).translate("Sizes"),
|
||||||
|
'asset/menu/3.3.sizes.png',
|
||||||
|
Colors.black, 48, true,0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkedHashMap getMenuItems() {
|
||||||
|
return this.tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
32
lib/util/message_state.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
/// An extension class to the Flutter standard State. The class provides getter
|
||||||
|
/// and setters for updating the message section of the loading screen
|
||||||
|
///
|
||||||
|
/// Note: The class is marked as abstract to avoid IDE issues that expects
|
||||||
|
/// protected methods to be overloaded
|
||||||
|
abstract class MessageState<T extends StatefulWidget> extends State<T> {
|
||||||
|
/// The state variable that will hold the latest message that needs to be
|
||||||
|
/// displayed.
|
||||||
|
///
|
||||||
|
/// Note: Although Flutter standard allow member variables to be used from
|
||||||
|
/// instance object reference, this is not a best practice with OOP. OOP
|
||||||
|
/// design proposes that member variables should be accessed through getter
|
||||||
|
/// and setter methods.
|
||||||
|
@protected
|
||||||
|
String _message = 'Loading . . .';
|
||||||
|
|
||||||
|
/// The member variable is set as protected this it is not exposed to the
|
||||||
|
/// widget state class. As a workaround a protected setter is set so it is
|
||||||
|
/// not used outside the package
|
||||||
|
@protected
|
||||||
|
set initialMessage(String message) => _message = message;
|
||||||
|
|
||||||
|
/// Setter for the message variable
|
||||||
|
set setMessage(String message) => setState(() {
|
||||||
|
_message = message;
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Getter for the message variable
|
||||||
|
String get getMessage => _message;
|
||||||
|
}
|
74
lib/util/session.dart
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/service/api.dart';
|
||||||
|
import 'package:aitrainer_app/service/customer_service.dart';
|
||||||
|
import 'package:aitrainer_app/service/exercisetype_service.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/exercise_type_changing_view_model.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
|
||||||
|
class Session {
|
||||||
|
|
||||||
|
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
|
||||||
|
Auth _auth = Auth();
|
||||||
|
SharedPreferences _sharedPreferences;
|
||||||
|
final AppLanguage appLanguage = AppLanguage();
|
||||||
|
|
||||||
|
fetchSessionAndNavigate(Function callback ) async {
|
||||||
|
_sharedPreferences = await _prefs;
|
||||||
|
|
||||||
|
|
||||||
|
if ( _auth.firstLoad ) {
|
||||||
|
_fetchToken(_sharedPreferences, callback);
|
||||||
|
appLanguage.fetchLocale();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Auth flow of the user, see auth.dart
|
||||||
|
*/
|
||||||
|
_fetchToken(SharedPreferences prefs, Function callback) async {
|
||||||
|
|
||||||
|
var responseJson = await APIClient.authenticateUser(
|
||||||
|
Auth.username,
|
||||||
|
Auth.password
|
||||||
|
);
|
||||||
|
print("--- Lang: " + appLanguage.appLocal.toString());
|
||||||
|
if(responseJson['error'] != null) {
|
||||||
|
print("************** Here big error - no authentication");
|
||||||
|
} else if (responseJson['token'] != null) {
|
||||||
|
prefs.setString(Auth.authTokenKey, responseJson['token']);
|
||||||
|
Auth auth = Auth();
|
||||||
|
auth.authToken = responseJson['token'];
|
||||||
|
if (prefs.get(Auth.customerIdKey) == null) {
|
||||||
|
print("************** Registration");
|
||||||
|
// registration
|
||||||
|
//Navigator.of(context).pushNamed('registration');
|
||||||
|
prefs.setBool(Auth.isRegisteredKey, true);
|
||||||
|
} else {
|
||||||
|
DateTime now = DateTime.now();
|
||||||
|
DateTime lastStoreDate = DateTime.parse(
|
||||||
|
prefs.get(Auth.lastStoreDateKey));
|
||||||
|
DateTime minStoreDate = now.add(Duration(days: -10));
|
||||||
|
|
||||||
|
if (lastStoreDate == null ||
|
||||||
|
lastStoreDate.difference(minStoreDate) > Duration(days: 10) ||
|
||||||
|
prefs.get(Auth.isLoggedInKey) == null ||
|
||||||
|
prefs.get(Auth.isLoggedInKey) == false) {
|
||||||
|
print("************* Login");
|
||||||
|
//Navigator.of(context).pushNamed('login');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
print("************** Store SharedPreferences");
|
||||||
|
// get API customer
|
||||||
|
await CustomerApi().getCustomer(prefs.getInt(Auth.customerIdKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
await ExerciseTypeApi().getExerciseTypes("");
|
||||||
|
print("--- Session finished, call callback ");
|
||||||
|
callback();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
248
lib/view/account.dart
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
|
||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/exercise_view_model.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/user_view_model.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class AccountPage extends StatefulWidget{
|
||||||
|
_AccountPagePageState _state;
|
||||||
|
|
||||||
|
_AccountPagePageState createState() {
|
||||||
|
_state = new _AccountPagePageState();
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AccountPagePageState extends State<AccountPage> {
|
||||||
|
final UserViewModel user = UserViewModel();
|
||||||
|
final AppLanguage appLanguage = AppLanguage();
|
||||||
|
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
|
||||||
|
final BottomNavigator bottomNav = BottomNavigator();
|
||||||
|
bool _loggedIn = Auth().userLoggedIn != null && Auth().userLoggedIn.email.length > 0;
|
||||||
|
Future<List<ExerciseViewModel>> _exercises;
|
||||||
|
ExerciseChangingViewModel model;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
model = Provider.of<ExerciseChangingViewModel>(context, listen: false);
|
||||||
|
if ( Auth().userLoggedIn != null ) {
|
||||||
|
_exercises = model.getExercisesByCustomer(Auth().userLoggedIn.customerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(AppLocalizations.of(context).translate('Account')),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
foregroundDecoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_long_logo.png'),
|
||||||
|
//fit: BoxFit.scaleDown,
|
||||||
|
scale: 1.2,
|
||||||
|
alignment: Alignment.topRight,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child:
|
||||||
|
ListView(
|
||||||
|
padding: EdgeInsets.only(top: 135),
|
||||||
|
children: <Widget>[
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.perm_identity),
|
||||||
|
subtitle: Text(
|
||||||
|
AppLocalizations.of(context).translate("Profile")),
|
||||||
|
title: FlatButton(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(_loggedIn ? Auth().userLoggedIn.email + " " +
|
||||||
|
Auth().userLoggedIn.name + " " +
|
||||||
|
Auth().userLoggedIn.firstName : "",
|
||||||
|
style: TextStyle(color: Colors.blue)),
|
||||||
|
Icon(Icons.arrow_forward_ios),
|
||||||
|
]),
|
||||||
|
textColor: Colors.grey,
|
||||||
|
color: Colors.white,
|
||||||
|
onPressed: () {
|
||||||
|
if (_loggedIn) {
|
||||||
|
Navigator.of(context).pushNamed('customerModifyPage');
|
||||||
|
print("Profile");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.language),
|
||||||
|
title: Text(appLanguage.appLocal == Locale('en') ?
|
||||||
|
AppLocalizations.of(context).translate("English") :
|
||||||
|
AppLocalizations.of(context).translate("Hungarian")),
|
||||||
|
subtitle: Text(AppLocalizations.of(context).translate(
|
||||||
|
"Selected Language")),
|
||||||
|
),
|
||||||
|
loginOut(),
|
||||||
|
exercises( model ),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
bottomNavigationBar: bottomNav.buildBottomNavigator(context, widget._state)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ListTile loginOut() {
|
||||||
|
ListTile element = ListTile();
|
||||||
|
|
||||||
|
String text = "Logout";
|
||||||
|
Color buttonColor = Colors.orange;
|
||||||
|
|
||||||
|
if ( ! _loggedIn ) {
|
||||||
|
text = "Login";
|
||||||
|
buttonColor = Colors.blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
element = ListTile(
|
||||||
|
enabled: true,
|
||||||
|
leading: Icon(Icons.input),
|
||||||
|
title: FlatButton(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(AppLocalizations.of(context).translate(text),
|
||||||
|
style: TextStyle(
|
||||||
|
color: buttonColor
|
||||||
|
)),
|
||||||
|
Icon(Icons.arrow_forward_ios),
|
||||||
|
]),
|
||||||
|
textColor: buttonColor,
|
||||||
|
color: Colors.white,
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
if ( ! _loggedIn) {
|
||||||
|
print("Login");
|
||||||
|
Navigator.of(context).pushNamed("login");
|
||||||
|
} else {
|
||||||
|
print("Logout");
|
||||||
|
_loggedIn = false;
|
||||||
|
Auth().logout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
ListTile exercises( ExerciseChangingViewModel model ) {
|
||||||
|
ListTile element = ListTile();
|
||||||
|
if ( Auth().userLoggedIn == null ) {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
element = ListTile(
|
||||||
|
title: Text(AppLocalizations.of(context).translate("Exercises")),
|
||||||
|
subtitle: Column(
|
||||||
|
children: [
|
||||||
|
FutureBuilder<List<ExerciseViewModel>>(
|
||||||
|
future: _exercises,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
return getExercises( model );//CustomerListWidget(customers: _exerciseViewModel.exerciseList);
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
return Text("${snapshot.error}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// By default, show a loading spinner.
|
||||||
|
return CircularProgressIndicator();
|
||||||
|
}
|
||||||
|
),]
|
||||||
|
));
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget getExercises( ExerciseChangingViewModel model ) {
|
||||||
|
List<ExerciseViewModel> exercises = model.exerciseList;
|
||||||
|
|
||||||
|
Column element = Column();
|
||||||
|
if (exercises.length > 0) {
|
||||||
|
List<Column> rows = List();
|
||||||
|
|
||||||
|
exercises.forEach((exercise) {
|
||||||
|
String exerciseName = AppLocalizations.of(context).translate(
|
||||||
|
Common.getExerciseType(exercise.getExercise().exerciseTypeId).name);
|
||||||
|
|
||||||
|
String quantity = exercise.getExercise().quantity.toString() + " " +
|
||||||
|
AppLocalizations.of(context).translate(exercise.getExercise().unit);
|
||||||
|
|
||||||
|
String unitQuantity = "";
|
||||||
|
String unitQuantityUnit = "";
|
||||||
|
String date = Common.getDateLocale(exercise.getExercise().dateAdd, false);
|
||||||
|
if (exercise.getExercise().unitQuantity != null) {
|
||||||
|
unitQuantity = exercise.getExercise().unitQuantity.toString();
|
||||||
|
unitQuantityUnit = AppLocalizations.of(context).translate(
|
||||||
|
Common.getExerciseType(exercise.getExercise().exerciseTypeId).unitQuantityUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
TableRow row = TableRow(
|
||||||
|
children: [
|
||||||
|
Text(date),
|
||||||
|
Text(exerciseName),
|
||||||
|
Text(quantity),
|
||||||
|
|
||||||
|
Text(unitQuantity + " " + unitQuantityUnit),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
Table table = Table(
|
||||||
|
defaultColumnWidth: FractionColumnWidth(0.28),
|
||||||
|
children: [row],
|
||||||
|
);
|
||||||
|
|
||||||
|
Column col = Column(
|
||||||
|
children: [
|
||||||
|
table,
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(" "),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
rows.add(col);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
element = Column(
|
||||||
|
children: rows,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
81
lib/view/customer_bodytype_page.dart
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class CustomerBodyTypePage extends StatefulWidget{
|
||||||
|
_CustomerBodyTypePageState _state;
|
||||||
|
|
||||||
|
_CustomerBodyTypePageState createState() {
|
||||||
|
_state = _CustomerBodyTypePageState();
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GenderItem {
|
||||||
|
GenderItem(this.dbValue,this.name);
|
||||||
|
final String dbValue;
|
||||||
|
String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomerBodyTypePageState extends State<CustomerBodyTypePage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final CustomerChangingViewModel changingViewModel = ModalRoute.of(context).settings.arguments;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
|
||||||
|
Image.asset(
|
||||||
|
'asset/image/WT_long_logo.png',
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
height: 65.0,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Divider(),
|
||||||
|
InkWell(
|
||||||
|
child: Text("Your Body Type",
|
||||||
|
style: TextStyle(color: Colors.orange,
|
||||||
|
fontSize: 50, fontFamily: 'Arial',
|
||||||
|
fontWeight: FontWeight.w900 ),),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
RaisedButton(
|
||||||
|
|
||||||
|
color: Colors.orange,
|
||||||
|
textColor: Colors.white,
|
||||||
|
child: InkWell(
|
||||||
|
child: Text(AppLocalizations.of(context).translate("Next"))),
|
||||||
|
onPressed: () => {
|
||||||
|
//changingViewModel.saveCustomer(),
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
Navigator.of(context).pushNamed("customerWelcomePage", arguments: changingViewModel)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
80
lib/view/customer_fitness_page.dart
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class CustomerFitnessPage extends StatefulWidget{
|
||||||
|
_CustomerFitnessPageState _state;
|
||||||
|
|
||||||
|
_CustomerFitnessPageState createState() {
|
||||||
|
_state = _CustomerFitnessPageState();
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GenderItem {
|
||||||
|
GenderItem(this.dbValue,this.name);
|
||||||
|
final String dbValue;
|
||||||
|
String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomerFitnessPageState extends State<CustomerFitnessPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final CustomerChangingViewModel changingViewModel = ModalRoute.of(context).settings.arguments;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
|
||||||
|
Image.asset(
|
||||||
|
'asset/image/WT_long_logo.png',
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
height: 65.0,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Divider(),
|
||||||
|
InkWell(
|
||||||
|
child: Text("Your Fitness State",
|
||||||
|
style: TextStyle(color: Colors.orange,
|
||||||
|
fontSize: 50, fontFamily: 'Arial',
|
||||||
|
fontWeight: FontWeight.w900 ),),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
),
|
||||||
|
|
||||||
|
RaisedButton(
|
||||||
|
|
||||||
|
color: Colors.orange,
|
||||||
|
textColor: Colors.white,
|
||||||
|
child: InkWell(
|
||||||
|
child: Text(AppLocalizations.of(context).translate("Next"))),
|
||||||
|
onPressed: () => {
|
||||||
|
//changingViewModel.saveCustomer(),
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
Navigator.of(context).pushNamed("customerBodyTypePage", arguments: changingViewModel)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
124
lib/view/customer_goal_page.dart
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class CustomerGoalPage extends StatefulWidget{
|
||||||
|
_CustomerGoalPageState _state;
|
||||||
|
|
||||||
|
_CustomerGoalPageState createState() {
|
||||||
|
_state = _CustomerGoalPageState();
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GenderItem {
|
||||||
|
GenderItem(this.dbValue,this.name);
|
||||||
|
final String dbValue;
|
||||||
|
String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomerGoalPageState extends State<CustomerGoalPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final CustomerChangingViewModel changingViewModel = ModalRoute.of(context).settings.arguments;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
|
||||||
|
Image.asset(
|
||||||
|
'asset/image/WT_long_logo.png',
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
height: 65.0,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Divider(),
|
||||||
|
InkWell(
|
||||||
|
child: Text("Set Your Goals",
|
||||||
|
style: TextStyle(color: Colors.orange,
|
||||||
|
fontSize: 50, fontFamily: 'Arial',
|
||||||
|
fontWeight: FontWeight.w900 ),),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
),
|
||||||
|
|
||||||
|
Stack(
|
||||||
|
alignment: Alignment.bottomLeft,
|
||||||
|
overflow: Overflow.visible,
|
||||||
|
children: [
|
||||||
|
FlatButton(
|
||||||
|
child: Image.asset("asset/image/WT_gain_muscle.png", height: 250,),
|
||||||
|
padding: EdgeInsets.all(0.0),
|
||||||
|
onPressed:() =>
|
||||||
|
{
|
||||||
|
print("gain muscle"),
|
||||||
|
changingViewModel.customer.setGoal("gain_muscle"),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
child: Text("Gain Muscle",
|
||||||
|
style: TextStyle(color: Colors.white,
|
||||||
|
fontSize: 36, fontFamily: 'Arial',
|
||||||
|
fontWeight: FontWeight.w900 ),),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
Stack(
|
||||||
|
alignment: Alignment.bottomLeft,
|
||||||
|
overflow: Overflow.visible,
|
||||||
|
children: [
|
||||||
|
FlatButton(
|
||||||
|
child: Image.asset("asset/image/WT_weight_loss.png", height: 220,),
|
||||||
|
padding: EdgeInsets.all(0.0),
|
||||||
|
onPressed:() =>
|
||||||
|
{
|
||||||
|
print("weight_loss"),
|
||||||
|
changingViewModel.customer.setGoal("weight_loss"),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
child: Text("Loose Weight",
|
||||||
|
style: TextStyle(color: Colors.white,
|
||||||
|
fontSize: 36, fontFamily: 'Arial',
|
||||||
|
fontWeight: FontWeight.w900 ),),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
RaisedButton(
|
||||||
|
|
||||||
|
color: Colors.orange,
|
||||||
|
textColor: Colors.white,
|
||||||
|
child: InkWell(
|
||||||
|
child: Text(AppLocalizations.of(context).translate("Next"))),
|
||||||
|
onPressed: () => {
|
||||||
|
//changingViewModel.saveCustomer(),
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
Navigator.of(context).pushNamed("customerFitnessPage", arguments: changingViewModel)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,29 +1,277 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/customer_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:aitrainer_app/widgets/nav_drawer.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
class CustomerModifyPage extends StatefulWidget{
|
class CustomerModifyPage extends StatefulWidget{
|
||||||
_CustomerModifyPageState createState() => _CustomerModifyPageState();
|
_CustomerModifyPageState _state;
|
||||||
|
|
||||||
|
_CustomerModifyPageState createState() {
|
||||||
|
_state = _CustomerModifyPageState();
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CustomerModifyPageState extends State {
|
class GenderItem {
|
||||||
//final _formKey = GlobalKey<FormState>();
|
GenderItem(this.dbValue,this.name);
|
||||||
|
final String dbValue;
|
||||||
|
String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomerModifyPageState extends State<CustomerModifyPage> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
GenderItem selectedGender;
|
||||||
|
List<GenderItem> genders;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
genders = [
|
||||||
|
GenderItem("m", "Man"),
|
||||||
|
GenderItem("w", "Woman"),
|
||||||
|
];
|
||||||
|
selectedGender = genders[0];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final CustomerViewModel model = CustomerViewModel();
|
||||||
|
model.customer = Auth().userLoggedIn;
|
||||||
|
final CustomerChangingViewModel customerChangeModel =
|
||||||
|
CustomerChangingViewModel(model);
|
||||||
|
customerChangeModel.customer.customer.sex = selectedGender.dbValue;
|
||||||
|
|
||||||
|
// we cannot initialize the translations in the initState
|
||||||
|
genders.forEach((GenderItem element) {
|
||||||
|
if ( element.dbValue == "m") {
|
||||||
|
element.name = AppLocalizations.of(context).translate("Man");
|
||||||
|
}
|
||||||
|
if ( element.dbValue == "w") {
|
||||||
|
element.name = AppLocalizations.of(context).translate("Woman");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
drawer: NavDrawer(),
|
resizeToAvoidBottomInset: true,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('Modify customer'),
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: <Widget>[
|
||||||
|
Text("Profil"),
|
||||||
|
Image.asset(
|
||||||
|
'asset/image/WT_long_logo.png',
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
height: 65.0,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
//title: Text(AppLocalizations.of(context).translate('Settings')),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
),
|
),
|
||||||
body: Center(
|
body: Container(
|
||||||
child: Text('Modify customer'),
|
decoration: BoxDecoration(
|
||||||
),
|
image: DecorationImage(
|
||||||
floatingActionButton: FloatingActionButton(
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
onPressed: () => {},
|
fit: BoxFit.cover,
|
||||||
child: Icon(Icons.save,),
|
alignment: Alignment.center,
|
||||||
mini: true,
|
),
|
||||||
|
),
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
padding: EdgeInsets.only(top: 40, left: 25, right: 45, bottom:100),
|
||||||
|
|
||||||
|
child: Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white24,
|
||||||
|
filled: true,
|
||||||
|
labelText: AppLocalizations.of(context).translate('Email'),
|
||||||
|
),
|
||||||
|
initialValue: customerChangeModel.customer.customer.email,
|
||||||
|
onFieldSubmitted: (input) => customerChangeModel.customer.setEmail(input)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
obscureText: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white24,
|
||||||
|
filled: true,
|
||||||
|
labelText: AppLocalizations.of(context).translate('Password (Leave empty if you don\'t want to change)' ),
|
||||||
|
),
|
||||||
|
initialValue: customerChangeModel.customer.customer.password,
|
||||||
|
onFieldSubmitted: (input) => customerChangeModel.customer.setPassword(input)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white24,
|
||||||
|
filled: true,
|
||||||
|
labelText: AppLocalizations.of(context).translate('Name'),
|
||||||
|
),
|
||||||
|
initialValue: customerChangeModel.customer.customer.name,
|
||||||
|
onFieldSubmitted: (input) => customerChangeModel.customer.setName(input)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white24,
|
||||||
|
filled: true,
|
||||||
|
|
||||||
|
labelText: AppLocalizations.of(context).translate('First Name'),
|
||||||
|
),
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
|
initialValue: customerChangeModel.customer.customer.firstName,
|
||||||
|
onFieldSubmitted: (input) => customerChangeModel.customer.setFirstName(input)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white24,
|
||||||
|
filled: true,
|
||||||
|
labelText: AppLocalizations.of(context).translate('Birth Year'),
|
||||||
|
),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
inputFormatters: <TextInputFormatter>[
|
||||||
|
WhitelistingTextInputFormatter.digitsOnly
|
||||||
|
],
|
||||||
|
initialValue: customerChangeModel.customer.customer.birthYear.toString(),
|
||||||
|
onFieldSubmitted: (input) => customerChangeModel.customer.setBirthYear(int.parse(input))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white24,
|
||||||
|
filled: true,
|
||||||
|
labelText: AppLocalizations.of(context).translate('Weight'),
|
||||||
|
),
|
||||||
|
inputFormatters: <TextInputFormatter>[
|
||||||
|
WhitelistingTextInputFormatter.digitsOnly
|
||||||
|
],
|
||||||
|
initialValue: customerChangeModel.customer.customer.weight.toString(),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
onFieldSubmitted: (input) => customerChangeModel.customer.setWeight(int.parse(input)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: DropdownButtonHideUnderline(
|
||||||
|
child: DropdownButton<GenderItem>(
|
||||||
|
hint: Text(AppLocalizations.of(context).translate('Select a gender')),
|
||||||
|
style: TextStyle(fontSize: 12, color: Colors.black),
|
||||||
|
focusColor: Colors.white24,
|
||||||
|
value: selectedGender,
|
||||||
|
items: genders.map((GenderItem gender){
|
||||||
|
return DropdownMenuItem<GenderItem>(
|
||||||
|
value: gender,
|
||||||
|
child: Text(gender.name)
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
onChanged:(GenderItem gender) => {
|
||||||
|
setState(() {
|
||||||
|
selectedGender = gender;
|
||||||
|
customerChangeModel.customer.setSex(gender.dbValue);
|
||||||
|
|
||||||
|
print ("Gender " + gender.name);
|
||||||
|
})
|
||||||
|
//model.customer.sex =
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: RaisedButton(
|
||||||
|
|
||||||
|
color: Colors.orange,
|
||||||
|
textColor: Colors.white,
|
||||||
|
child: InkWell(
|
||||||
|
child: Text(AppLocalizations.of(context).translate("Next"))),
|
||||||
|
onPressed: () => {
|
||||||
|
customerChangeModel.saveCustomer(),
|
||||||
|
Navigator.of(context).pushNamed("customerGoalPage", arguments: customerChangeModel)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -68,7 +68,7 @@ class _CustomerNewPageState extends State {
|
|||||||
validator: (input) => (int.parse(input) < 99 && int.parse(input) > 0) ?
|
validator: (input) => (int.parse(input) < 99 && int.parse(input) > 0) ?
|
||||||
null :
|
null :
|
||||||
"Please type the right age 0-99",
|
"Please type the right age 0-99",
|
||||||
onChanged: (input) => customer.setAge(int.parse(input)),
|
onChanged: (input) => customer.setBirthYear(int.parse(input)),
|
||||||
),
|
),
|
||||||
RadioListTile(
|
RadioListTile(
|
||||||
title: const Text('Man'),
|
title: const Text('Man'),
|
||||||
|
75
lib/view/customer_welcome_page.dart
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class CustomerWelcomePage extends StatefulWidget{
|
||||||
|
_CustomerWelcomePageState _state;
|
||||||
|
|
||||||
|
_CustomerWelcomePageState createState() {
|
||||||
|
_state = _CustomerWelcomePageState();
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GenderItem {
|
||||||
|
GenderItem(this.dbValue,this.name);
|
||||||
|
final String dbValue;
|
||||||
|
String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomerWelcomePageState extends State<CustomerWelcomePage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final CustomerChangingViewModel changingViewModel = ModalRoute.of(context).settings.arguments;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
|
||||||
|
Image.asset(
|
||||||
|
'asset/image/WT_long_logo.png',
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
height: 65.0,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_welcome.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Divider(),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RaisedButton(
|
||||||
|
|
||||||
|
color: Colors.orange,
|
||||||
|
textColor: Colors.white,
|
||||||
|
child: InkWell(
|
||||||
|
child: Text(AppLocalizations.of(context).translate("Next"))),
|
||||||
|
onPressed: () => {
|
||||||
|
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
Navigator.of(context).pushNamed("home", arguments: changingViewModel)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,108 +1,226 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
||||||
import 'package:aitrainer_app/widgets/nav_drawer.dart';
|
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
|
//import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
|
||||||
|
|
||||||
class ExerciseNewPage extends StatefulWidget{
|
class ExerciseNewPage extends StatefulWidget{
|
||||||
_ExerciseNewPageState createState() => _ExerciseNewPageState();
|
_ExerciseNewPageState createState() => _ExerciseNewPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ExerciseNewPageState extends State {
|
class _ExerciseNewPageState extends State {
|
||||||
|
final List excluded = [43,44];
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
final format = DateFormat("yyyy-MM-dd HH:mm");
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
ExerciseChangingViewModel model = Provider.of<ExerciseChangingViewModel>(context, listen: false);
|
|
||||||
model.createNewModel();
|
|
||||||
return Scaffold(
|
|
||||||
drawer: NavDrawer(),
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('New exercise'),
|
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
child: Form(
|
|
||||||
key: _formKey,
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
TextFormField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'Name',
|
|
||||||
),
|
|
||||||
readOnly: true,
|
|
||||||
initialValue: model != null && model.customer != null ? model.customer.name + " " + model.customer.firstName : "Please select a customer",
|
|
||||||
),
|
|
||||||
TextFormField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'Exercise',
|
|
||||||
),
|
|
||||||
readOnly: true,
|
|
||||||
initialValue: model != null && model.exerciseType != null ? model.exerciseType.name : "Please select an exercise",
|
|
||||||
),
|
|
||||||
TextFormField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'Quantity',
|
|
||||||
),
|
|
||||||
validator: (input) => (int.parse(input) < 1000 && int.parse(input) > 0) ?
|
|
||||||
null :
|
|
||||||
"Please type the right quantity 0-1000",
|
|
||||||
onChanged: (input) => model.exerciseViewModel.setQuantity(int.parse(input)),
|
|
||||||
),
|
|
||||||
|
|
||||||
Text('Exercise date and time'),
|
return Consumer<ExerciseChangingViewModel>(
|
||||||
DateTimeField(
|
builder: (context, model, child ) {
|
||||||
format: format,
|
String exerciseName = "";
|
||||||
initialValue: DateTime.now(),
|
String customerName = "";
|
||||||
onShowPicker: (context, currentValue) async {
|
if ( model != null ) {
|
||||||
final date = await showDatePicker(
|
if ( model.exerciseViewModel == null ) {
|
||||||
context: context,
|
model.createNewModel();
|
||||||
firstDate: DateTime(1900),
|
|
||||||
initialDate: DateTime.now(),
|
|
||||||
lastDate: DateTime(2100),
|
|
||||||
builder: (context, child) => Localizations.override(
|
|
||||||
context: context,
|
|
||||||
locale: Locale('hu'),
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (date != null) {
|
|
||||||
final time = await showTimePicker(
|
|
||||||
context: context,
|
|
||||||
initialTime:
|
|
||||||
TimeOfDay.fromDateTime(currentValue ?? DateTime.now()),
|
|
||||||
builder: (context, child) => Localizations.override(
|
|
||||||
context: context,
|
|
||||||
locale: Locale('hu'),
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return DateTimeField.combine(date, time);
|
|
||||||
} else {
|
|
||||||
return currentValue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onChanged: (input) => model.exerciseViewModel.setDatetimeExercise(input),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: () => {
|
|
||||||
if (_formKey.currentState.validate()) {
|
|
||||||
//model = ExerciseChangingViewModel(model.exerciseViewModel),
|
|
||||||
model.addExercise(),
|
|
||||||
Navigator.pop(context),
|
|
||||||
}
|
}
|
||||||
},
|
model.exerciseViewModel.createNew();
|
||||||
child: Icon(Icons.save,),
|
customerName = model != null && model.customer != null
|
||||||
mini: true,
|
? model.customer.name + " " +
|
||||||
)
|
model.customer.firstName
|
||||||
);
|
: "Please select a customer";
|
||||||
|
|
||||||
|
exerciseName = model != null &&
|
||||||
|
model.exerciseType != null
|
||||||
|
? model.exerciseType.name
|
||||||
|
: "Please select an exercise";
|
||||||
|
}
|
||||||
|
|
||||||
|
AppLanguage appLanguage = AppLanguage();
|
||||||
|
var date = DateTime.now();
|
||||||
|
String dateName = DateFormat(DateFormat.YEAR_MONTH_DAY, appLanguage.appLocal.toString()).format(date.toUtc()) +
|
||||||
|
" " +DateFormat(DateFormat.HOUR_MINUTE, appLanguage.appLocal.toString()).format(date.toUtc());
|
||||||
|
|
||||||
|
return Form(
|
||||||
|
key: _formKey,
|
||||||
|
autovalidate: true,
|
||||||
|
child: Scaffold(
|
||||||
|
resizeToAvoidBottomInset: false,
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: IconButton(
|
||||||
|
icon: Icon(Icons.arrow_back, color: Colors.deepOrange),
|
||||||
|
onPressed: () => {
|
||||||
|
Navigator.of(context).pop()
|
||||||
|
},
|
||||||
|
),
|
||||||
|
title: Text(AppLocalizations.of(context).translate(exerciseName) + " " +
|
||||||
|
AppLocalizations.of(context).translate('Save Exercise'),
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.deepOrange)),
|
||||||
|
backgroundColor: Colors.white70,
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_login.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
//height: double.infinity,
|
||||||
|
//width: double.infinity,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only (top: 65, left:25, right: 100),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: <Widget>[
|
||||||
|
columnQuantityUnit(model),
|
||||||
|
columnQuantity(model),
|
||||||
|
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(dateName,
|
||||||
|
style: TextStyle( fontSize: 16,color: Colors.blue)),
|
||||||
|
),
|
||||||
|
ButtonTheme(
|
||||||
|
minWidth: 30.0,
|
||||||
|
height: 30.0,
|
||||||
|
child: FlatButton(
|
||||||
|
|
||||||
|
padding: EdgeInsets.only(bottom: 0),
|
||||||
|
color: Colors.transparent,
|
||||||
|
splashColor: Colors.black26,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
|
||||||
|
Icon(Icons.arrow_forward_ios, color: Colors.orange,)
|
||||||
|
]),
|
||||||
|
onPressed:() { print("date change");},
|
||||||
|
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(AppLocalizations.of(context).translate('Exercise date and time'),
|
||||||
|
style: TextStyle( fontSize: 16)),
|
||||||
|
),
|
||||||
|
|
||||||
|
]),
|
||||||
|
RaisedButton(
|
||||||
|
textColor: Colors.white,
|
||||||
|
color: Colors.deepOrange,
|
||||||
|
focusColor: Colors.white,
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
if (_formKey.currentState.validate()) {
|
||||||
|
//model = ExerciseChangingViewModel(model.exerciseViewModel),
|
||||||
|
|
||||||
|
if ( ! excluded.contains(model.exerciseType.exerciseTypeId) ) {
|
||||||
|
model.addExercise(),
|
||||||
|
},
|
||||||
|
Navigator.pop(context),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text("Save", style: TextStyle(fontSize: 16),)
|
||||||
|
),
|
||||||
|
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Column columnQuantityUnit( ExerciseChangingViewModel model) {
|
||||||
|
Column column = Column();
|
||||||
|
if ( model.exerciseType != null && model.exerciseType.unitQuantity == "1") {
|
||||||
|
column = Column(
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
autovalidate: true,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
initialValue: "0",
|
||||||
|
style: TextStyle(fontSize: 30,
|
||||||
|
color: Colors.lightBlue,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
validator: (input) {
|
||||||
|
return validateNumberInput(input);
|
||||||
|
},
|
||||||
|
onFieldSubmitted: (input) => {
|
||||||
|
print ("UnitQuantity value $input"),
|
||||||
|
model.exerciseViewModel.setUnitQuantity(
|
||||||
|
double.parse(input))
|
||||||
|
},
|
||||||
|
|
||||||
|
),
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(AppLocalizations.of(context).translate(
|
||||||
|
model.exerciseType.unitQuantityUnit),
|
||||||
|
style: TextStyle(fontSize: 16)),
|
||||||
|
),
|
||||||
|
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
Column columnQuantity( ExerciseChangingViewModel model) {
|
||||||
|
Column column = Column();
|
||||||
|
|
||||||
|
column = Column(
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
autovalidate: true,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
initialValue: "0",
|
||||||
|
style: TextStyle(fontSize: 60,
|
||||||
|
color: Colors.deepOrange,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
validator: (input) {
|
||||||
|
return validateNumberInput(input);
|
||||||
|
},
|
||||||
|
onFieldSubmitted: (input) =>
|
||||||
|
{
|
||||||
|
print ("Quantity value $input"),
|
||||||
|
model.exerciseViewModel.setQuantity(
|
||||||
|
double.parse(input)),
|
||||||
|
model.exerciseViewModel.setUnit(model.exerciseType.unit)
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(AppLocalizations.of(context).translate(model.exerciseType.unit),
|
||||||
|
style: TextStyle(fontSize: 16)),
|
||||||
|
),
|
||||||
|
|
||||||
|
]);
|
||||||
|
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
String validateNumberInput( input ) {
|
||||||
|
String error = AppLocalizations.of(context).translate("Please type the right quantity 0-10000");
|
||||||
|
dynamic rc = ( input != null && input.length > 0);
|
||||||
|
if ( ! rc ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = double.tryParse(input);
|
||||||
|
if ( rc == null ) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! ( double.parse(input) < 10000 && double.parse(input) > 0) ) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
lib/view/gdpr.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Gdpr extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Container(
|
||||||
|
padding: const EdgeInsets.only (left:15, right: 15),
|
||||||
|
child: ListView(
|
||||||
|
children: <Widget>[
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(
|
||||||
|
AppLocalizations.of(context).translate('gdpr_text'),
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
customBorder: Border.all(color:Colors.teal, width:1),
|
||||||
|
),
|
||||||
|
Spacer(flex:2),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
FlatButton(
|
||||||
|
textColor: Colors.black,
|
||||||
|
|
||||||
|
onPressed: () { },
|
||||||
|
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,9 +1,12 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/user_changing_view_model.dart';
|
import 'package:aitrainer_app/viewmodel/user_changing_view_model.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/user_view_model.dart';
|
import 'package:aitrainer_app/viewmodel/user_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:aitrainer_app/widgets/nav_drawer.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
|
||||||
class LoginPage extends StatefulWidget{
|
class LoginPage extends StatefulWidget{
|
||||||
_LoginPageState createState() => _LoginPageState();
|
_LoginPageState createState() => _LoginPageState();
|
||||||
@ -11,71 +14,126 @@ class LoginPage extends StatefulWidget{
|
|||||||
|
|
||||||
class _LoginPageState extends State {
|
class _LoginPageState extends State {
|
||||||
final UserViewModel user = UserViewModel();
|
final UserViewModel user = UserViewModel();
|
||||||
bool _obscureText = true;
|
final bool _obscureText = true;
|
||||||
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
UserChangingViewModel model = UserChangingViewModel(user);
|
UserChangingViewModel model = UserChangingViewModel(user);
|
||||||
|
ExerciseChangingViewModel exerciseModel = Provider.of<ExerciseChangingViewModel>(context, listen: false);
|
||||||
user.createNew();
|
user.createNew();
|
||||||
return Scaffold(
|
|
||||||
drawer: NavDrawer(),
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('Login'),
|
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
child: Form(
|
|
||||||
key: _formKey,
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
TextFormField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'Email',
|
|
||||||
icon: const Padding(
|
|
||||||
padding:const EdgeInsets.only(left: 20.0, top: 50.0),
|
|
||||||
child: const Icon(Icons.people)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
validator: (String input) {
|
|
||||||
RegExp exp = new RegExp(r"[\w._]+\@[\w._]+.[a-z]+",
|
|
||||||
caseSensitive: false,
|
|
||||||
multiLine: false,);
|
|
||||||
String ret = exp.hasMatch(input) == true ?
|
|
||||||
null:
|
|
||||||
"Please type an email address";
|
|
||||||
return ret;
|
|
||||||
},
|
|
||||||
onChanged: (input) => user.setEmail(input),
|
|
||||||
),
|
|
||||||
new TextFormField(
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Password',
|
|
||||||
icon: const Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 20.0, top: 15.0),
|
|
||||||
child: const Icon(Icons.lock))),
|
|
||||||
validator: (val) => val.length < 6 ? 'Password too short.' : null,
|
|
||||||
obscureText: _obscureText,
|
|
||||||
onChanged: (input) => user.setPassword(input),
|
|
||||||
),
|
|
||||||
new InkWell(
|
|
||||||
child: new Text('SignUp'),
|
|
||||||
onTap: () => Navigator.of(context).pushNamed('registration'),
|
|
||||||
),
|
|
||||||
new FloatingActionButton(
|
|
||||||
child: Icon(Icons.cloud_done,),
|
|
||||||
onPressed:() => {
|
|
||||||
if (_formKey.currentState.validate()) {
|
|
||||||
model = UserChangingViewModel(user),
|
|
||||||
model.getUser(),
|
|
||||||
Navigator.pop(context),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
])
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
body: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_login.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
//height: double.infinity,
|
||||||
|
//width: double.infinity,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only (left: 25, right: 100),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: <Widget>[
|
||||||
|
Spacer(flex: 4),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(
|
||||||
|
AppLocalizations.of(context).translate(
|
||||||
|
'Login'),
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 24)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
TextFormField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: true,
|
||||||
|
labelText: 'Email',
|
||||||
|
),
|
||||||
|
validator: (String input) {
|
||||||
|
RegExp exp = new RegExp(r"[\w._]+\@[\w._]+.[a-z]+",
|
||||||
|
caseSensitive: false,
|
||||||
|
multiLine: false,);
|
||||||
|
String ret = exp.hasMatch(input) == true ?
|
||||||
|
null :
|
||||||
|
AppLocalizations.of(context).translate(
|
||||||
|
'Please type an email address');
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
onChanged: (input) => user.setEmail(input),
|
||||||
|
),
|
||||||
|
Spacer(flex: 1),
|
||||||
|
new TextFormField(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
filled: true,
|
||||||
|
labelText: "Password",
|
||||||
|
fillColor: Colors.white,
|
||||||
|
focusColor: Colors.white,
|
||||||
|
),
|
||||||
|
validator: (val) => val.length < 6
|
||||||
|
? AppLocalizations.of(context).translate(
|
||||||
|
'Password too short')
|
||||||
|
: null,
|
||||||
|
obscureText: _obscureText,
|
||||||
|
onChanged: (input) => user.setPassword(input),
|
||||||
|
),
|
||||||
|
Spacer(flex: 1),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[ new FlatButton(
|
||||||
|
child: Image.asset('asset/image/WT_OK.png',
|
||||||
|
width: 100,
|
||||||
|
height: 100
|
||||||
|
),
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
if (_formKey.currentState.validate()) {
|
||||||
|
model = UserChangingViewModel(user),
|
||||||
|
model.getUser(),
|
||||||
|
exerciseModel.setCustomer(
|
||||||
|
Auth().userLoggedIn),
|
||||||
|
Navigator.pop(context),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
Spacer(flex: 2),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: <Widget>[
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(
|
||||||
|
AppLocalizations.of(context).translate(
|
||||||
|
'SignUp')),
|
||||||
|
onTap: () =>
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
'registration'),
|
||||||
|
),
|
||||||
|
Spacer(flex: 1),
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(
|
||||||
|
AppLocalizations.of(context).translate(
|
||||||
|
'Privacy')),
|
||||||
|
onTap: () =>
|
||||||
|
Navigator.of(context).pushNamed('gdpr'),
|
||||||
|
),
|
||||||
|
Spacer(flex: 2),
|
||||||
|
]),
|
||||||
|
Spacer(flex: 2),
|
||||||
|
])
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
154
lib/view/menu_page.dart
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
|
import 'package:aitrainer_app/util/menu_tests.dart';
|
||||||
|
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'dart:collection';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class MenuPage extends StatefulWidget {
|
||||||
|
_MenuPageState _state;
|
||||||
|
static const routeName = '/menu_page';
|
||||||
|
int parent;
|
||||||
|
|
||||||
|
MenuPage({this.parent});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_MenuPageState createState() {
|
||||||
|
_state = new _MenuPageState();
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MenuPageState extends State<MenuPage> {
|
||||||
|
final BottomNavigator bottomNav = BottomNavigator();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final MenuTests menu = MenuTests(context);
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
Image.asset(
|
||||||
|
'asset/image/WT_long_logo.png',
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
height: 65.0,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
leading: IconButton(
|
||||||
|
icon: Icon(Icons.arrow_back, color: Colors.black),
|
||||||
|
onPressed: () => {
|
||||||
|
this.setState(() {
|
||||||
|
widget.parent = 0;
|
||||||
|
},
|
||||||
|
)},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
body: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_menu_dark.png'),
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
child: CustomScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
slivers: <Widget>[
|
||||||
|
buildMenuColumn(widget.parent, context, menu)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SliverList buildMenuColumn(int parent, BuildContext context, MenuTests menu) {
|
||||||
|
LinkedHashMap tree = menu.getMenuItems();
|
||||||
|
List<Widget> _columnChildren = List();
|
||||||
|
ExerciseType exerciseType;
|
||||||
|
ExerciseChangingViewModel model = Provider.of<ExerciseChangingViewModel>(context, listen: false);
|
||||||
|
|
||||||
|
tree.forEach((treeName, value) {
|
||||||
|
WorkoutTree workoutTree = value as WorkoutTree;
|
||||||
|
|
||||||
|
if ( workoutTree.parent == parent ) {
|
||||||
|
_columnChildren.add(
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(top: 16.0),
|
||||||
|
child: Center(
|
||||||
|
child: Stack(
|
||||||
|
alignment: Alignment.bottomLeft,
|
||||||
|
overflow: Overflow.visible,
|
||||||
|
children: [
|
||||||
|
FlatButton(
|
||||||
|
child: _getButtonImage(workoutTree),
|
||||||
|
padding: EdgeInsets.all(0.0),
|
||||||
|
onPressed:() =>
|
||||||
|
{
|
||||||
|
print("Hi!, Menu clicked " + workoutTree.id.toString()),
|
||||||
|
if ( workoutTree.child == false ) {
|
||||||
|
this.setState(() {
|
||||||
|
widget.parent = workoutTree.id;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
} else {
|
||||||
|
exerciseType = Common.getExerciseType(workoutTree.exercise_type_id),
|
||||||
|
model.setExerciseType(exerciseType),
|
||||||
|
model.setCustomer(Auth().userLoggedIn),
|
||||||
|
if ( Auth().userLoggedIn == null ) {
|
||||||
|
Scaffold.of(context)
|
||||||
|
. showSnackBar(SnackBar(content: Text('Please log in')))
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).pushNamed('exerciseNewPage'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
child: Text(workoutTree.name, style: TextStyle(color: workoutTree.color, fontSize: workoutTree.fontSize, fontFamily: 'Arial', fontWeight: FontWeight.w900 ),),
|
||||||
|
highlightColor: workoutTree.color,
|
||||||
|
)]))));
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//_columnChildren.add(Spacer(flex: 3));
|
||||||
|
SliverList sliverList =
|
||||||
|
SliverList(
|
||||||
|
delegate: SliverChildListDelegate(
|
||||||
|
_columnChildren
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return sliverList;
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamic _getButtonImage(WorkoutTree workoutTree) {
|
||||||
|
dynamic image;
|
||||||
|
if ( workoutTree.imageName.startsWith("http") ) {
|
||||||
|
image = FadeInImage.assetNetwork(
|
||||||
|
image: workoutTree.imageName,
|
||||||
|
placeholder: 'asset/image/dots.gif',
|
||||||
|
//imageScale: 0.1,
|
||||||
|
height: 180,
|
||||||
|
placeholderScale: 0.1,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
image = Image.asset(workoutTree.imageName, height: 180,);
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/user_changing_view_model.dart';
|
import 'package:aitrainer_app/viewmodel/user_changing_view_model.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/user_view_model.dart';
|
import 'package:aitrainer_app/viewmodel/user_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -19,66 +20,102 @@ class _RegistrationPageState extends State {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
UserChangingViewModel model = UserChangingViewModel(user);
|
UserChangingViewModel model = UserChangingViewModel(user);
|
||||||
user.createNew();
|
user.createNew();
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
drawer: NavDrawer(),
|
|
||||||
appBar: AppBar(
|
body: Container(
|
||||||
title: Text('Registration'),
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_login.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
//height: double.infinity,
|
||||||
|
//width: double.infinity,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: Center(
|
child: Form(
|
||||||
child: Form(
|
key: _formKey,
|
||||||
key: _formKey,
|
child: Container(
|
||||||
child: Column(
|
padding: const EdgeInsets.only (left:25, right: 100),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
Spacer(flex:4),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(AppLocalizations.of(context).translate('SignUp'),
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
TextFormField(
|
TextFormField(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
fillColor: Colors.white,
|
||||||
|
filled:true,
|
||||||
labelText: 'Email',
|
labelText: 'Email',
|
||||||
icon: const Padding(
|
|
||||||
padding:const EdgeInsets.only(left: 20.0, top: 50.0),
|
|
||||||
child: const Icon(Icons.people)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
/* validator: (String input) {
|
validator: (String input) {
|
||||||
RegExp exp = new RegExp(r"[\w._]+\@[\w._]+.[a-z]+",
|
RegExp exp = new RegExp(r"[\w._]+\@[\w._]+.[a-z]+",
|
||||||
caseSensitive: false,
|
caseSensitive: false,
|
||||||
multiLine: false,);
|
multiLine: false,);
|
||||||
String ret = exp.hasMatch(input) == true ?
|
String ret = exp.hasMatch(input) == true ?
|
||||||
null:
|
null:
|
||||||
"Please type an email address";
|
AppLocalizations.of(context).translate('Please type an email address');
|
||||||
return ret;
|
return ret;
|
||||||
},*/
|
},
|
||||||
onChanged: (input) => user.setEmail(input),
|
onChanged: (input) => user.setEmail(input),
|
||||||
),
|
),
|
||||||
|
Spacer(flex:1),
|
||||||
new TextFormField(
|
new TextFormField(
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Password',
|
filled:true,
|
||||||
icon: const Padding(
|
labelText: "Password",
|
||||||
padding: const EdgeInsets.only(left: 20.0, top: 15.0),
|
fillColor: Colors.white,
|
||||||
child: const Icon(Icons.lock))),
|
focusColor: Colors.white,
|
||||||
/* validator: (String input) {
|
),
|
||||||
String rc = input.length < 4 ? 'Password too short.' : null;
|
validator: (val) => val.length < 6 ? AppLocalizations.of(context).translate('Password too short') : null,
|
||||||
return rc;
|
|
||||||
}, */
|
|
||||||
onChanged: (input) => user.setPassword(input),
|
|
||||||
obscureText: _obscureText,
|
obscureText: _obscureText,
|
||||||
|
onChanged: (input) => user.setPassword(input),
|
||||||
),
|
),
|
||||||
new InkWell(
|
Spacer(flex:1),
|
||||||
child: new Text('I have an account'),
|
Row(
|
||||||
onTap: () => Navigator.of(context).pushNamed('login'),
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
),
|
children: <Widget>[ new FlatButton(
|
||||||
new FloatingActionButton(
|
child: Image.asset('asset/image/WT_OK.png',
|
||||||
child: Icon(Icons.cloud_done,),
|
width: 100,
|
||||||
onPressed:() => {
|
height:100
|
||||||
if (_formKey.currentState.validate()) {
|
),
|
||||||
model = UserChangingViewModel(user),
|
onPressed:() => {
|
||||||
model.addUser(),
|
if (_formKey.currentState.validate()) {
|
||||||
Navigator.pop(context),
|
model = UserChangingViewModel(user),
|
||||||
}
|
model.addUser(),
|
||||||
}
|
Navigator.of(context).pushNamed("customerModifyPage",)
|
||||||
)
|
}
|
||||||
])
|
}),
|
||||||
),
|
]),
|
||||||
|
Spacer(flex:2),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: <Widget>[
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(AppLocalizations.of(context).translate('Login')),
|
||||||
|
onTap: () => Navigator.of(context).pushNamed('login'),
|
||||||
|
),
|
||||||
|
Spacer(flex:1),
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(AppLocalizations.of(context).translate('Privacy')),
|
||||||
|
onTap: () => Navigator.of(context).pushNamed('gdpr'),
|
||||||
|
),
|
||||||
|
Spacer(flex:2),
|
||||||
|
]),
|
||||||
|
Spacer(flex:2),
|
||||||
|
])
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
103
lib/view/settings.dart
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SettingsPage extends StatefulWidget{
|
||||||
|
_SettingsPageState _state;
|
||||||
|
|
||||||
|
_SettingsPageState createState() {
|
||||||
|
_state = new _SettingsPageState();
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SettingsPageState extends State<SettingsPage> {
|
||||||
|
final AppLanguage appLanguage = AppLanguage();
|
||||||
|
Locale _locale;
|
||||||
|
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
BottomNavigator bottomNav = BottomNavigator();
|
||||||
|
_locale = appLanguage.appLocal;
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(AppLocalizations.of(context).translate('Settings')),
|
||||||
|
Image.asset(
|
||||||
|
'asset/image/WT_long_logo.png',
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
height: 65.0,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
//title: Text(AppLocalizations.of(context).translate('Settings')),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child:
|
||||||
|
ListView(
|
||||||
|
padding: EdgeInsets.only(top: 150),
|
||||||
|
children: <Widget>[
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.language),
|
||||||
|
subtitle: Text(AppLocalizations.of(context).translate("Change App Language")),
|
||||||
|
title: DropdownButton(
|
||||||
|
value: _locale == Locale('en') ? AppLocalizations.of(context).translate("English") : AppLocalizations.of(context).translate("Hungarian"),
|
||||||
|
items: [AppLocalizations.of(context).translate("English"), AppLocalizations.of(context).translate("Hungarian")]
|
||||||
|
.map<DropdownMenuItem<String>>((String value) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
value: value,
|
||||||
|
child: Text(value),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
onChanged:(String lang) => _changeLanguage(lang),
|
||||||
|
)
|
||||||
|
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
bottomNavigationBar: bottomNav.buildBottomNavigator(context, widget._state)
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_changeLanguage( String lang ) {
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
switch ( lang ) {
|
||||||
|
case "English":
|
||||||
|
case "Angol":
|
||||||
|
_locale = Locale('en');
|
||||||
|
break;
|
||||||
|
case "Hungarian":
|
||||||
|
case "Magyar":
|
||||||
|
_locale = Locale('hu');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
appLanguage.changeLanguage(_locale);
|
||||||
|
AppLocalizations.of(context).setLocale(_locale);
|
||||||
|
AppLocalizations.of(context).load();
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,7 @@ class CustomerChangingViewModel extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveCustomer() async {
|
Future<void> saveCustomer() async {
|
||||||
this.customer = customer;
|
//this.customer = customer;
|
||||||
final Customer modelCustomer = customer.getCustomer();
|
final Customer modelCustomer = customer.getCustomer();
|
||||||
await CustomerApi().saveCustomer(modelCustomer);
|
await CustomerApi().saveCustomer(modelCustomer);
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@ class CustomerViewModel {
|
|||||||
return this.customer.sex == "m" ? "Man" : "Woman";
|
return this.customer.sex == "m" ? "Man" : "Woman";
|
||||||
}
|
}
|
||||||
|
|
||||||
int get age {
|
int get birthYear {
|
||||||
return this.customer.age;
|
return this.birthYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
setName(String name) {
|
setName(String name) {
|
||||||
@ -29,18 +29,39 @@ class CustomerViewModel {
|
|||||||
this.customer.firstName = firstName;
|
this.customer.firstName = firstName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setPassword( String password ) {
|
||||||
|
this.customer.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
setEmail(String email) {
|
setEmail(String email) {
|
||||||
this.customer.email = email;
|
this.customer.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
setAge(int age) {
|
|
||||||
this.customer.age = age;
|
|
||||||
}
|
|
||||||
|
|
||||||
setSex(String sex) {
|
setSex(String sex) {
|
||||||
this.customer.sex = sex;
|
this.customer.sex = sex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setWeight( int weight) {
|
||||||
|
this.customer.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBirthYear( int birthYear ) {
|
||||||
|
this.customer.birthYear = birthYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFitnessLevel( String level ) {
|
||||||
|
this.customer.fitnessLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
setGoal( String goal ) {
|
||||||
|
this.customer.goal = goal;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBodyType(String bodyType) {
|
||||||
|
this.customer.bodyType = bodyType;
|
||||||
|
}
|
||||||
|
|
||||||
createNew() {
|
createNew() {
|
||||||
this.customer = Customer();
|
this.customer = Customer();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import 'exercise_view_model.dart';
|
|||||||
class ExerciseChangingViewModel with ChangeNotifier {
|
class ExerciseChangingViewModel with ChangeNotifier {
|
||||||
Customer customer;
|
Customer customer;
|
||||||
ExerciseType exerciseType;
|
ExerciseType exerciseType;
|
||||||
|
List<ExerciseViewModel> exerciseList = List<ExerciseViewModel>();
|
||||||
|
|
||||||
ExerciseViewModel exerciseViewModel = ExerciseViewModel();
|
ExerciseViewModel exerciseViewModel = ExerciseViewModel();
|
||||||
|
|
||||||
@ -20,10 +21,12 @@ class ExerciseChangingViewModel with ChangeNotifier {
|
|||||||
|
|
||||||
setCustomer(Customer customer) {
|
setCustomer(Customer customer) {
|
||||||
this.customer = customer;
|
this.customer = customer;
|
||||||
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
setExerciseType( ExerciseType exerciseType) {
|
setExerciseType( ExerciseType exerciseType) {
|
||||||
this.exerciseType = exerciseType;
|
this.exerciseType = exerciseType;
|
||||||
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
setQuantity(int quantity) {
|
setQuantity(int quantity) {
|
||||||
@ -31,7 +34,7 @@ class ExerciseChangingViewModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addExercise() async {
|
addExercise() async {
|
||||||
this.exerciseViewModel = exerciseViewModel;
|
// this.exerciseViewModel = exerciseViewModel;
|
||||||
final Exercise modelExercise = exerciseViewModel.getExercise();
|
final Exercise modelExercise = exerciseViewModel.getExercise();
|
||||||
modelExercise.customerId = this.customer.customerId;
|
modelExercise.customerId = this.customer.customerId;
|
||||||
modelExercise.exerciseTypeId = this.exerciseType.exerciseTypeId;
|
modelExercise.exerciseTypeId = this.exerciseType.exerciseTypeId;
|
||||||
@ -43,4 +46,11 @@ class ExerciseChangingViewModel with ChangeNotifier {
|
|||||||
exerciseViewModel.createNew();
|
exerciseViewModel.createNew();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<ExerciseViewModel>> getExercisesByCustomer( int customerId ) async {
|
||||||
|
final results = await ExerciseApi().getExercisesByCustomer(customerId);
|
||||||
|
this.exerciseList = results.map((item) => ExerciseViewModel(exercise: item)).toList();
|
||||||
|
notifyListeners();
|
||||||
|
return this.exerciseList;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -6,15 +6,23 @@ class ExerciseViewModel {
|
|||||||
|
|
||||||
createNew() {
|
createNew() {
|
||||||
this.exercise = Exercise();
|
this.exercise = Exercise();
|
||||||
exercise.datetimeExercise = DateTime.now();
|
exercise.dateAdd = DateTime.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
setQuantity(int quantity) {
|
setQuantity(double quantity) {
|
||||||
this.exercise.quantity = quantity;
|
this.exercise.quantity = quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setUnitQuantity(double unitQuantity) {
|
||||||
|
this.exercise.unitQuantity = unitQuantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUnit( String unit) {
|
||||||
|
this.exercise.unit = unit;
|
||||||
|
}
|
||||||
|
|
||||||
setDatetimeExercise(DateTime datetimeExercise) {
|
setDatetimeExercise(DateTime datetimeExercise) {
|
||||||
this.exercise.datetimeExercise = datetimeExercise;
|
this.exercise.dateAdd = datetimeExercise;
|
||||||
}
|
}
|
||||||
|
|
||||||
Exercise getExercise() {
|
Exercise getExercise() {
|
||||||
|
58
lib/widgets/bottom_nav.dart
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class BottomNavigator {
|
||||||
|
BottomNavigationBar buildBottomNavigator(BuildContext context, State state) {
|
||||||
|
return BottomNavigationBar(
|
||||||
|
currentIndex: 0, // this will be set when a new tab is tapped
|
||||||
|
backgroundColor: Colors.black12,
|
||||||
|
selectedItemColor: Colors.yellow,
|
||||||
|
unselectedItemColor: Colors.lightGreen,
|
||||||
|
type: BottomNavigationBarType.shifting,
|
||||||
|
showSelectedLabels: true,
|
||||||
|
items: [
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
backgroundColor: Colors.black12,
|
||||||
|
icon: new Icon(Icons.home, color: Colors.lightGreen),
|
||||||
|
activeIcon: new Icon(Icons.home, color: Colors.yellow,),
|
||||||
|
title: new Text(AppLocalizations.of(context).translate("Home")),
|
||||||
|
),
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
icon: new Icon(Icons.event, color: Colors.lightGreen),
|
||||||
|
activeIcon: new Icon(Icons.event, color: Colors.yellow,),
|
||||||
|
title: new Text(AppLocalizations.of(context).translate("Events")),
|
||||||
|
),
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
icon: Icon(Icons.person, color: Colors.lightGreen,),
|
||||||
|
activeIcon: new Icon(Icons.person, color: Colors.yellow,),
|
||||||
|
title: Text(AppLocalizations.of(context).translate("Account"))
|
||||||
|
),
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
icon: Icon(Icons.settings, color: Colors.lightGreen),
|
||||||
|
activeIcon: new Icon(Icons.settings, color: Colors.yellow,),
|
||||||
|
title: Text(AppLocalizations.of(context).translate("Settings"))
|
||||||
|
)
|
||||||
|
],
|
||||||
|
onTap:(index) {
|
||||||
|
// ignore: invalid_use_of_protected_member
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Navigator.of(context).pushNamed('home');
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Navigator.of(context).pushNamed('account');
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Navigator.of(context).pushNamed('settings');
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -36,7 +36,7 @@ class _CustomerListWidget extends State<CustomerListWidget> {
|
|||||||
visible: customer.visibleDetails,
|
visible: customer.visibleDetails,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(customer.age.toString() + " years, " + customer.sex),
|
Text(customer.birthYear.toString() + " years, " + customer.sex),
|
||||||
new RaisedButton(
|
new RaisedButton(
|
||||||
child: new Text('Modify'),
|
child: new Text('Modify'),
|
||||||
color: Color.fromRGBO(244, 122, 22, 0.9),
|
color: Color.fromRGBO(244, 122, 22, 0.9),
|
||||||
|
57
lib/widgets/home.dart
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/view/menu_page.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'bottom_nav.dart';
|
||||||
|
import 'nav_drawer.dart';
|
||||||
|
|
||||||
|
class AitrainerHome extends StatefulWidget {
|
||||||
|
_HomePageState _state;
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() {
|
||||||
|
_state = new _HomePageState();
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void callback() {
|
||||||
|
_state.setLangNoContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HomePageState extends State<AitrainerHome> {
|
||||||
|
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||||
|
final AppLanguage appLanguage = AppLanguage();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
MenuPage menu = MenuPage();
|
||||||
|
BottomNavigator bottomNav = BottomNavigator();
|
||||||
|
return Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
drawer: NavDrawer(),
|
||||||
|
body:Container(
|
||||||
|
child: MenuPage(parent: 0),
|
||||||
|
),
|
||||||
|
bottomNavigationBar: bottomNav.buildBottomNavigator(context, widget._state)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLangNoContext() {
|
||||||
|
print("--- Callback ");
|
||||||
|
setState(() {
|
||||||
|
final AppLanguage appLanguage = AppLanguage();
|
||||||
|
AppLocalizations.of(context).setLocale(appLanguage.appLocal);
|
||||||
|
AppLocalizations.of(context).load();
|
||||||
|
print("--- Lang for context reloaded");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
55
lib/widgets/loading.dart
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import 'package:aitrainer_app/util/message_state.dart';
|
||||||
|
import 'package:aitrainer_app/util/session.dart';
|
||||||
|
import 'package:aitrainer_app/view/menu_page.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/home.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'file:///D:/projects/aitrainer/src/aitrainer_app/lib/util/loading_screen.dart';
|
||||||
|
|
||||||
|
class LoadingScreenMain extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
LoadingScreenMainState createState() => LoadingScreenMainState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadingScreenMainState extends State<LoadingScreenMain> {
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Image _backgroundImage = Image.asset('asset/WT01_loading_layers.png',
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
height: double.infinity,
|
||||||
|
width: double.infinity,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
);
|
||||||
|
dynamic _timer = <dynamic>[TimeMessages.timer];
|
||||||
|
return Scaffold(
|
||||||
|
body: LoadingScreen(
|
||||||
|
initializers: _timer,
|
||||||
|
navigateToWidget: AitrainerHome(),
|
||||||
|
loaderColor: Colors.yellow,
|
||||||
|
image: _backgroundImage,
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
styleTextUnderTheLoader: TextStyle(
|
||||||
|
fontSize: 14.0,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.lightGreenAccent),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimeMessages {
|
||||||
|
static Future timer(MessageState state, Function callback) async {
|
||||||
|
//while (true) {
|
||||||
|
await Future.delayed(Duration(seconds: 4), () {
|
||||||
|
state.setMessage = DateTime.now().toIso8601String();
|
||||||
|
print("---- TimeMessages initializer");
|
||||||
|
Session session = Session();
|
||||||
|
session.fetchSessionAndNavigate(callback);
|
||||||
|
});
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,25 @@
|
|||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/model/auth.dart';
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class NavDrawer extends StatelessWidget {
|
class NavDrawer extends StatefulWidget {
|
||||||
|
|
||||||
|
@override
|
||||||
|
_NawDrawerWidget createState() => _NawDrawerWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NawDrawerWidget extends State<NavDrawer> {
|
||||||
final Auth auth = Auth();
|
final Auth auth = Auth();
|
||||||
|
final AppLanguage appLanguage = AppLanguage();
|
||||||
|
Locale _locale;
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Drawer(
|
return Drawer(
|
||||||
@ -11,49 +28,64 @@ class NavDrawer extends StatelessWidget {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
DrawerHeader(
|
DrawerHeader(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Customers And Exercises',
|
AppLocalizations.of(context).translate('Customers And Exercises'),
|
||||||
style: TextStyle(color: Colors.blue, fontSize: 25),
|
style: TextStyle(color: Colors.blue, fontSize: 25),
|
||||||
),
|
),
|
||||||
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.home),
|
leading: Icon(Icons.home),
|
||||||
title: Text('Home'),
|
title: Text( AppLocalizations.of(context).translate('Home')),
|
||||||
onTap: () => Navigator.of(context).pushNamed('home'),
|
onTap: () => Navigator.of(context).pushNamed('home'),
|
||||||
),
|
),
|
||||||
|
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.people),
|
leading: Icon(Icons.people),
|
||||||
title: Text('Customers'),
|
title: Text( AppLocalizations.of(context).translate('Customers')),
|
||||||
//onTap: () => navigateToPage(context, 'customersPage'),
|
|
||||||
onTap: () => Navigator.of(context).pushNamed('customersPage'),
|
onTap: () => Navigator.of(context).pushNamed('customersPage'),
|
||||||
),
|
),
|
||||||
|
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.directions_run),
|
leading: Icon(Icons.directions_run),
|
||||||
title: Text('Exercises'),
|
title: Text(AppLocalizations.of(context).translate('Exercises')),
|
||||||
onTap: () => Navigator.of(context).pushNamed('exerciseTypeListPage'),
|
onTap: () =>
|
||||||
|
Navigator.of(context).pushNamed('exerciseTypeListPage'),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.arrow_upward),
|
leading: Icon(Icons.arrow_upward),
|
||||||
title: Text("TRAINING!"),
|
title: Text(AppLocalizations.of(context).translate("TRAINING!")),
|
||||||
onTap: () => Navigator.of(context).pushNamed('exerciseNewPage'),
|
onTap: () => Navigator.of(context).pushNamed('exerciseNewPage'),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.perm_identity),
|
leading: Icon(Icons.perm_identity),
|
||||||
title: Text('Login'),
|
title: Text(AppLocalizations.of(context).translate('Login')),
|
||||||
onTap: () => Navigator.of(context).pushNamed('login'),
|
onTap: () => Navigator.of(context).pushNamed('login'),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.cancel),
|
leading: Icon(Icons.cancel),
|
||||||
title: Text("Logout"),
|
title: Text(AppLocalizations.of(context).translate('Logout')),
|
||||||
onTap: () => {
|
onTap: () =>
|
||||||
auth.logout(),
|
{
|
||||||
Navigator.of(context).pushNamed('home'),
|
auth.logout(),
|
||||||
}
|
Navigator.of(context).pushNamed('home'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.hearing),
|
||||||
|
title: Text(AppLocalizations.of(context).translate('Change Language')),
|
||||||
|
onTap: () => _tapped(),
|
||||||
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _tapped() => {
|
||||||
|
/* _locale = Locale("hu"),
|
||||||
|
appLanguage.changeLanguage(_locale),
|
||||||
|
AppLocalizations.of(context).setLocale(_locale),
|
||||||
|
AppLocalizations.of(context).load() */
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
40
pubspec.yaml
@ -56,8 +56,44 @@ flutter:
|
|||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
assets:
|
assets:
|
||||||
- asset/WT01_loading_layers.png
|
- asset/image/WT_menu_welcome.png
|
||||||
# - images/a_dot_ham.jpeg
|
- asset/image/WT_menu_backround.png
|
||||||
|
- asset/image/WT_menu.png
|
||||||
|
- asset/image/WT_login.png
|
||||||
|
- asset/image/WT_OK.png
|
||||||
|
- asset/image/dots.gif
|
||||||
|
- asset/image/WT_long_logo.png
|
||||||
|
- asset/image/WT_light_background.png
|
||||||
|
- asset/image/WT_menu_dark.png
|
||||||
|
- asset/image/WT_gain_muscle.png
|
||||||
|
- asset/image/WT_weight_loss.png
|
||||||
|
- asset/image/WT_welcome.png
|
||||||
|
- asset/menu/1.cardio.png
|
||||||
|
- asset/menu/1.1.aerob.png
|
||||||
|
- asset/menu/1.2.anaerob.png
|
||||||
|
- asset/menu/1.1.1.cooper.png
|
||||||
|
- asset/menu/1.2.1.300m.png
|
||||||
|
- asset/menu/1.2.2.400m.png
|
||||||
|
- asset/menu/2.strength.png
|
||||||
|
- asset/menu/2.1.endurance.png
|
||||||
|
- asset/menu/2.1.1.pull-ups.png
|
||||||
|
- asset/menu/2.1.2.pushup.png
|
||||||
|
- asset/menu/2.1.3.sit-ups.png
|
||||||
|
- asset/menu/2.1.4.squats.png
|
||||||
|
- asset/menu/2.1.5.timedpushup.png
|
||||||
|
- asset/menu/2.1.6.core.png
|
||||||
|
- asset/menu/2.2.1.1RM.png
|
||||||
|
- asset/menu/2.2.1.1.chestpress.png
|
||||||
|
- asset/menu/2.2.1.2.pullups.png
|
||||||
|
- asset/menu/2.2.1.3.biceps.png
|
||||||
|
- asset/menu/2.2.1.4.triceps.png
|
||||||
|
- asset/menu/2.2.1.5.shoulders.png
|
||||||
|
- asset/menu/3.bcs1.png
|
||||||
|
- asset/menu/3.1.BMI.png
|
||||||
|
- asset/menu/3.2.BMR.png
|
||||||
|
- asset/menu/3.3.sizes.png
|
||||||
|
- i18n/en.json
|
||||||
|
- i18n/hu.json
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||||
|