Aitrainer_app 0.0.1

This commit is contained in:
Bossanyi Tibor
2020-05-24 10:04:37 +02:00
commit 2c10480ffd
87 changed files with 3025 additions and 0 deletions
+235
View File
@@ -0,0 +1,235 @@
import 'package:aitrainer_app/view/customer_modify_page.dart';
import 'package:aitrainer_app/view/customer_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_new_page.dart';
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
import 'package:flutter/material.dart';
import 'package:aitrainer_app/view/customer_list_page.dart';
import 'package:aitrainer_app/view/exercise_type_list_page.dart';
import 'package:aitrainer_app/widgets/nav_drawer.dart';
import 'package:provider/provider.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
void main() {
runApp(
ChangeNotifierProvider(
// Initialize the model in the builder. That way, Provider
// can own Models's lifecycle, making sure to call `dispose`
// when not needed anymore.
create: (context) => ExerciseChangingViewModel(null),
child: AitrainerApp(),
),
);
}
class AitrainerApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
// ... app-specific localization delegate[s] here
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [
const Locale('en'), // English
const Locale('hu'), // Hungarian
// ... other locales the app supports
],
routes: {
'home': (context) => AitrainerHome(),
'customersPage': (context) => CustomerListPage(),
'customerNewPage': (context) => CustomerNewPage(),
'customerModifyPage': (context) => CustomerModifyPage(),
'exerciseTypeListPage': (context) => ExerciseTypeListPage(),
'exerciseTypeNewPage': (context) => ExerciseTypeNewPage(),
'exerciseTypeModifyPage': (context) => ExerciseTypeModifyPage(),
'exerciseNewPage': (context) => ExerciseNewPage(),
},
initialRoute: 'home',
title: 'Aitrainer Demo',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: AitrainerHome(),
);
}
}
class AitrainerHome extends StatelessWidget {
final _biggerFont = const TextStyle(fontSize: 24.0, color: Color.fromRGBO(94, 123, 122, 0.9));
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: NavDrawer(),
appBar: AppBar(
title: Text('Menu'),
),
body: Center(
child: Text(
'Welcome to the AITRAINER',
style: _biggerFont),
),
);
}
}
/*
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();
}
*/
+32
View File
@@ -0,0 +1,32 @@
class Customer {
String name;
String email;
String firstName;
String sex;
int age;
String active;
int customerId;
Customer({this.customerId, this.name, this.firstName, this.email, this.sex, this.age, this.active});
Customer.fromJson(Map json) {
this.customerId = json['customer_id'];
this.name = json['name'];
this.firstName = json['firstname'];
this.email = json['email'];
this.sex = json['sex'];
this.age = json['age'];
this.active = json['active'];
}
Map<String, dynamic> toJson() =>
{
"name": name,
"firstName": firstName,
"email": email,
"age": age,
"sex": sex,
"active": 'Y'
};
}
+29
View File
@@ -0,0 +1,29 @@
import 'package:intl/intl.dart';
class Exercise {
int exerciseId;
int exerciseTypeId;
int customerId;
int quantity;
DateTime datetimeExercise;
Exercise({this.exerciseTypeId, this.customerId, this.quantity, this.datetimeExercise});
Exercise.fromJson(Map json) {
this.exerciseTypeId = json['exerciseTypeId'];
this.customerId = json['customerId'];
this.quantity = json['quantity'];
this.datetimeExercise = json['datetimeExercise'];
}
Map<String, dynamic> toJson() =>
{
"exerciseTypeId": exerciseTypeId,
"customerId": customerId,
"quantity": quantity,
"datetimeExercise": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.datetimeExercise),
};
}
+22
View File
@@ -0,0 +1,22 @@
import 'package:flutter/services.dart';
class ExerciseType {
int exerciseTypeId;
String name;
String description;
BinaryCodec video;
ExerciseType({this.name, this.description});
ExerciseType.fromJson(Map json) {
this.exerciseTypeId = json['exerciseTypeId'];
this.name = json['name'];
this.description = json['description'];
}
Map<String, dynamic> toJson() =>
{
"name": name,
"description": description,
};
}
+28
View File
@@ -0,0 +1,28 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
class APIClient {
final String _baseUrl = 'http://andio.eu:8888/api/';
Future<String> get(String endPoint, String param) async {
final url = _baseUrl + endPoint + param;
final response = await http.get(url, headers: {'Content-Type': 'application/json'});
if(response.statusCode == 200) {
return utf8.decode(response.bodyBytes);
} else {
throw Exception("Unable to perform HTTP request!");
}
}
Future<String> post(String endPoint, String body) async {
final url = _baseUrl + endPoint;
print(" ------------ http/post endpoint $endPoint body $body");
final response = await http.post(url,
headers: {'Content-Type': 'application/json'},
body: body
);
print(" ------------ response: " + response.body.toString());
return response.body;
}
}
+32
View File
@@ -0,0 +1,32 @@
import 'dart:convert';
import 'package:aitrainer_app/model/customer.dart';
import 'package:aitrainer_app/service/api.dart';
class CustomerApi {
final APIClient _client=new APIClient();
Future<List<Customer>> getRealCustomers(String param) async {
final body = await _client.get("customers/", param);
final Iterable json = jsonDecode(body);
final List<Customer> customers = json.map( (customer) => Customer.fromJson(customer) ).toList();
return customers;
}
Future<void> saveCustomer(Customer customer) async {
String body = JsonEncoder().convert(customer.toJson());
print(" ===== saving exerciseType id: " + customer.customerId.toString() + ":" + body );
await _client.post(
"customers/"+customer.customerId.toString(),
body);
}
Future<void> addCustomer(Customer customer) async {
String body = JsonEncoder().convert(customer.toJson());
print(" ===== add new customer: " + body );
await _client.post(
"customers",
body);
}
}
+33
View File
@@ -0,0 +1,33 @@
import 'dart:convert';
import 'package:aitrainer_app/model/exercise.dart';
import 'package:aitrainer_app/service/api.dart';
class ExerciseApi {
final APIClient _client=new APIClient();
Future<List<Exercise>> getExerciseTypes(String param) async {
final body = await _client.get("exercises", param);
final Iterable json = jsonDecode(body);
final List<Exercise> exerciseTypes = json.map( (exerciseType) => Exercise.fromJson(exerciseType) ).toList();
return exerciseTypes;
}
Future<void> saveExercise(Exercise exercise) async {
String body = JsonEncoder().convert(exercise.toJson());
print(" ===== saving exercise id: " + exercise.exerciseId.toString() + ":" + body );
await _client.post(
"exercises/"+exercise.exerciseId.toString(),
body);
}
Future<void> addExercise(Exercise exercise) async {
String body = JsonEncoder().convert(exercise.toJson());
print(" ===== add new exercise: " + body );
await _client.post(
"exercises",
body);
}
}
+32
View File
@@ -0,0 +1,32 @@
import 'dart:convert';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/service/api.dart';
class ExerciseTypeApi {
final APIClient _client=new APIClient();
Future<List<ExerciseType>> getExerciseTypes(String param) async {
final body = await _client.get("exercise_type", param);
final Iterable json = jsonDecode(body);
final List<ExerciseType> exerciseTypes = json.map( (exerciseType) => ExerciseType.fromJson(exerciseType) ).toList();
return exerciseTypes;
}
Future<void> saveExerciseType(ExerciseType exerciseType) async {
String body = JsonEncoder().convert(exerciseType.toJson());
print(" ===== saving exerciseType id: " + exerciseType.exerciseTypeId.toString() + ":" + body );
await _client.post(
"exercise_type/"+exerciseType.exerciseTypeId.toString(),
body);
}
Future<void> addExerciseType(ExerciseType exerciseType) async {
String body = JsonEncoder().convert(exerciseType.toJson());
print(" ===== add new exerciseType: " + body );
await _client.post(
"exercise_type",
body);
}
}
+93
View File
@@ -0,0 +1,93 @@
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
import 'package:aitrainer_app/viewmodel/customer_view_model.dart';
import 'package:aitrainer_app/widgets/nav_drawer.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:aitrainer_app/widgets/customer_list_widget.dart';
class CustomerListPage extends StatefulWidget{
_CustomerListPageState createState() => _CustomerListPageState();
}
class _CustomerListPageState extends State<CustomerListPage> {
//final TextEditingController _controller = TextEditingController();
Future<List<CustomerViewModel>> _customers;
final _customerViewModel = CustomerChangingViewModel(null);
@override
void initState() {
super.initState();
_customers = _customerViewModel.getCustomers();
}
@override
Widget build(BuildContext context) {
//final customerViewModel = CustomerChangingViewModel(null);
return Scaffold(
drawer: NavDrawer(),
appBar: AppBar(
title: Text("Real customers")
),
body: Center(
child: FutureBuilder<List<CustomerViewModel>>(
future: _customers,
builder: (context, snapshot) {
if (snapshot.hasData) {
return CustomerListWidget(customers: _customerViewModel.customerList);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
),
/* body: Container(
padding: EdgeInsets.all(10),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(children: <Widget>[
Container(
padding: EdgeInsets.only(left: 10),
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(10)
),
child: TextField(
controller: _controller,
onSubmitted: (value) {
if(value.isNotEmpty) {
customerViewModel.getCustomers();
_controller.clear();
}
},
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
hintText: "Search",
hintStyle: TextStyle(color: Colors.white),
border: InputBorder.none
),
),
),
Expanded(
child: CustomerListWidget(customers: customerViewModel.customers)),
]),
), */
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pushNamed(
context,
'customerNewPage',
),
child: Icon(Icons.add,),
mini: true,
)
);
}
}
+29
View File
@@ -0,0 +1,29 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:aitrainer_app/widgets/nav_drawer.dart';
class CustomerModifyPage extends StatefulWidget{
_CustomerModifyPageState createState() => _CustomerModifyPageState();
}
class _CustomerModifyPageState extends State {
//final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: NavDrawer(),
appBar: AppBar(
title: Text('Modify customer'),
),
body: Center(
child: Text('Modify customer'),
),
floatingActionButton: FloatingActionButton(
onPressed: () => {},
child: Icon(Icons.save,),
mini: true,
)
);
}
}
+112
View File
@@ -0,0 +1,112 @@
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/cupertino.dart';
import 'package:aitrainer_app/widgets/nav_drawer.dart';
class CustomerNewPage extends StatefulWidget{
_CustomerNewPageState createState() => _CustomerNewPageState();
}
class _CustomerNewPageState extends State {
final CustomerViewModel customer = CustomerViewModel();
String groupValue = "m";
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
CustomerChangingViewModel model;
customer.createNew();
customer.setSex(groupValue);
return Scaffold(
drawer: NavDrawer(),
appBar: AppBar(
title: Text('New customer'),
),
body: Center(
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Name',
),
validator: (input) => input.length == 0 ? "Please type the name" : null,
onChanged: (input) => customer.setName(input),
),
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'First Name',
),
validator: (input) => input.length == 0 ? "Please type the first name" : null,
onChanged: (input) => customer.setFirstName(input),
),
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
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:
"Please type an email address";
return ret;
},
onChanged: (input) => customer.setEmail(input),
),
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Age',
),
validator: (input) => (int.parse(input) < 99 && int.parse(input) > 0) ?
null :
"Please type the right age 0-99",
onChanged: (input) => customer.setAge(int.parse(input)),
),
RadioListTile(
title: const Text('Man'),
value: "m",
groupValue: groupValue,
onChanged: (input) => {
setState(() {
groupValue = input;
customer.setSex(input);
}
)},
),RadioListTile(
title: const Text('Woman'),
value: "w",
groupValue: groupValue,
onChanged: (input) => {
setState(() {
groupValue = input;
customer.setSex(input);
}
)},
),
])
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => {
if (_formKey.currentState.validate()) {
model = CustomerChangingViewModel(customer),
model.addCustomer(),
model.addNewCustomerToList(customer),
Navigator.pop(context),
}
},
child: Icon(Icons.save,),
mini: true,
)
);
}
}
+108
View File
@@ -0,0 +1,108 @@
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:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
class ExerciseNewPage extends StatefulWidget{
_ExerciseNewPageState createState() => _ExerciseNewPageState();
}
class _ExerciseNewPageState extends State {
final _formKey = GlobalKey<FormState>();
final format = DateFormat("yyyy-MM-dd HH:mm");
@override
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'),
DateTimeField(
format: format,
initialValue: DateTime.now(),
onShowPicker: (context, currentValue) async {
final date = await showDatePicker(
context: context,
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),
}
},
child: Icon(Icons.save,),
mini: true,
)
);
}
}
+59
View File
@@ -0,0 +1,59 @@
import 'package:aitrainer_app/viewmodel/exercise_type_changing_view_model.dart';
import 'package:aitrainer_app/viewmodel/exercise_type_view_model.dart';
import 'package:aitrainer_app/widgets/exercise_type_list_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:aitrainer_app/widgets/nav_drawer.dart';
class ExerciseTypeListPage extends StatefulWidget{
_ExerciseTypeListPageState createState() => _ExerciseTypeListPageState();
}
class _ExerciseTypeListPageState extends State {
Future<List<ExerciseTypeViewModel>> _exerciseTypes;
final _exerciseTypeViewModel = ExerciseTypeChangingViewModel(null);
// Push the page and remove everything else
navigateToPage(BuildContext context, String page) {
Navigator.of(context).pushNamedAndRemoveUntil(page, (Route<dynamic> route) => false);
}
@override
void initState() {
super.initState();
_exerciseTypes = _exerciseTypeViewModel.getExerciseTypes();
}
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: NavDrawer(),
appBar: AppBar(
title: Text('Exercises'),
),
body: Center(
child: FutureBuilder<List<ExerciseTypeViewModel>>(
future: _exerciseTypes,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ExerciseTypeListWidget(exerciseTypes: _exerciseTypeViewModel.exerciseTypeList);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pushNamed(
context,
'exerciseTypeNewPage',
),
child: Icon(Icons.add,),
mini: true,
)
);
}
}
+67
View File
@@ -0,0 +1,67 @@
import 'package:aitrainer_app/viewmodel/exercise_type_changing_view_model.dart';
import 'package:aitrainer_app/viewmodel/exercise_type_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:aitrainer_app/widgets/nav_drawer.dart';
// ignore: must_be_immutable
class ExerciseTypeModifyPage extends StatefulWidget{
ExerciseTypeViewModel exerciseTypeViewModel;
ExerciseTypeModifyPage({this.exerciseTypeViewModel});
_ExerciseTypeModifyPageState createState() => _ExerciseTypeModifyPageState();
}
class _ExerciseTypeModifyPageState extends State<ExerciseTypeModifyPage> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
final ExerciseTypeViewModel exerciseType = ModalRoute.of(context).settings.arguments;
ExerciseTypeChangingViewModel changeModel;
return Scaffold(
drawer: NavDrawer(),
appBar: AppBar(
title: Text('Modify "' + exerciseType.name + '"' ),
),
body: Center(
child: Form(
key:_formKey,
child: Column(
children: <Widget>[
TextFormField(
initialValue: exerciseType.name,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Exercise',
),
validator: (input) => input.length == 0 ? "Please type the name of the exercise" : null,
onChanged: (input) => exerciseType.setName(input),
) ,
TextFormField(
initialValue: exerciseType.description,
minLines: 4,
maxLines: 10,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Description',
),
onChanged: (input) => exerciseType.setDescription(input),
)
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => {
if (_formKey.currentState.validate()) {
changeModel = ExerciseTypeChangingViewModel(exerciseType),
changeModel.saveExerciseType(),
Navigator.pop(context),
}
},
child: Icon(Icons.save,),
mini: true,
)
);
}
}
+64
View File
@@ -0,0 +1,64 @@
import 'package:aitrainer_app/viewmodel/exercise_type_changing_view_model.dart';
import 'package:aitrainer_app/viewmodel/exercise_type_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:aitrainer_app/widgets/nav_drawer.dart';
class ExerciseTypeNewPage extends StatefulWidget{
_ExerciseTypeNewPageState createState() => _ExerciseTypeNewPageState();
}
class _ExerciseTypeNewPageState extends State {
final ExerciseTypeViewModel exerciseType = ExerciseTypeViewModel();
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
ExerciseTypeChangingViewModel model;
exerciseType.createNew();
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: 'Exercise',
),
validator: (input) => input.length == 0 ? "Please type the name of the exercise" : null,
onChanged: (input) => exerciseType.setName(input),
) ,
TextFormField(
minLines: 4,
maxLines: 10,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Description',
),
onChanged: (input) => exerciseType.setDescription(input),
)
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => {
if (_formKey.currentState.validate()) {
model = ExerciseTypeChangingViewModel(exerciseType),
model.addExerciseType(),
model.addNewExercise(exerciseType),
Navigator.pop(context),
}
},
child: Icon(Icons.save,),
mini: true,
)
);
}
}
@@ -0,0 +1,37 @@
import 'package:aitrainer_app/service/customer_service.dart';
import 'package:flutter/cupertino.dart';
import 'package:aitrainer_app/model/customer.dart';
import 'customer_view_model.dart';
class CustomerChangingViewModel extends ChangeNotifier {
CustomerViewModel customer = CustomerViewModel();
List<CustomerViewModel> customerList = List<CustomerViewModel>();
CustomerChangingViewModel(customer) {
this.customer = customer;
}
Future<void> addCustomer() async {
this.customer = customer;
final Customer modelCustomer = customer.getCustomer();
await CustomerApi().addCustomer(modelCustomer);
}
Future<void> saveCustomer() async {
this.customer = customer;
final Customer modelCustomer = customer.getCustomer();
await CustomerApi().saveCustomer(modelCustomer);
}
Future<List<CustomerViewModel>> getCustomers() async {
final results = await CustomerApi().getRealCustomers("");
this.customerList = results.map((item) => CustomerViewModel(customer: item)).toList();
notifyListeners();
return this.customerList;
}
addNewCustomerToList(CustomerViewModel customerViewModel) {
customerList.add(customerViewModel);
}
}
+51
View File
@@ -0,0 +1,51 @@
import 'package:aitrainer_app/model/customer.dart';
class CustomerViewModel {
Customer customer;
bool visibleDetails = false;
CustomerViewModel({this.customer});
String get name {
return this.customer.name;
}
String get firstName {
return this.customer.firstName;
}
String get sex {
return this.customer.sex == "m" ? "Man" : "Woman";
}
int get age {
return this.customer.age;
}
setName(String name) {
this.customer.name = name;
}
setFirstName(String firstName) {
this.customer.firstName = firstName;
}
setEmail(String email) {
this.customer.email = email;
}
setAge(int age) {
this.customer.age = age;
}
setSex(String sex) {
this.customer.sex = sex;
}
createNew() {
this.customer = Customer();
}
Customer getCustomer() {
return this.customer;
}
}
@@ -0,0 +1,46 @@
import 'package:aitrainer_app/model/customer.dart';
import 'package:aitrainer_app/model/exercise.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/service/exercise_service.dart';
import 'package:flutter/cupertino.dart';
import 'exercise_view_model.dart';
class ExerciseChangingViewModel with ChangeNotifier {
Customer customer;
ExerciseType exerciseType;
ExerciseViewModel exerciseViewModel = ExerciseViewModel();
ExerciseChangingViewModel(exerciseViewModel) {
this.exerciseViewModel = exerciseViewModel;
}
int quantity;
setCustomer(Customer customer) {
this.customer = customer;
}
setExerciseType( ExerciseType exerciseType) {
this.exerciseType = exerciseType;
}
setQuantity(int quantity) {
this.quantity = quantity;
}
addExercise() async {
this.exerciseViewModel = exerciseViewModel;
final Exercise modelExercise = exerciseViewModel.getExercise();
modelExercise.customerId = this.customer.customerId;
modelExercise.exerciseTypeId = this.exerciseType.exerciseTypeId;
await ExerciseApi().addExercise(modelExercise);
}
createNewModel() {
exerciseViewModel = ExerciseViewModel();
exerciseViewModel.createNew();
}
}
@@ -0,0 +1,36 @@
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/viewmodel/exercise_type_view_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:aitrainer_app/service/exercisetype_service.dart';
class ExerciseTypeChangingViewModel extends ChangeNotifier {
ExerciseTypeViewModel exerciseType = ExerciseTypeViewModel();
List<ExerciseTypeViewModel> exerciseTypeList = List<ExerciseTypeViewModel>();
ExerciseTypeChangingViewModel(exerciseType) {
this.exerciseType = exerciseType;
}
Future<void> addExerciseType() async {
this.exerciseType = exerciseType;
final ExerciseType modelExerciseType = exerciseType.getExerciseType();
await ExerciseTypeApi().addExerciseType(modelExerciseType);
}
Future<void> saveExerciseType() async {
this.exerciseType = exerciseType;
final ExerciseType modelExerciseType = exerciseType.getExerciseType();
await ExerciseTypeApi().saveExerciseType(modelExerciseType);
}
Future<List<ExerciseTypeViewModel>> getExerciseTypes() async {
final results = await ExerciseTypeApi().getExerciseTypes("");
this.exerciseTypeList = results.map((item) => ExerciseTypeViewModel( exerciseType: item) ).toList();
notifyListeners();
return this.exerciseTypeList;
}
addNewExercise(ExerciseTypeViewModel exerciseTypeViewModel) {
exerciseTypeList.add(exerciseTypeViewModel);
}
}
@@ -0,0 +1,36 @@
import 'package:aitrainer_app/model/exercise_type.dart';
class ExerciseTypeViewModel {
ExerciseType exerciseType;
bool visible = false;
ExerciseTypeViewModel( {this.exerciseType} );
String get name {
return this.exerciseType.name;
}
setName(String name) {
this.exerciseType.name = name;
}
String get description {
return this.exerciseType.description;
}
setDescription(String description) {
this.exerciseType.description = description;
}
int get exerciseTypeId {
return this.exerciseType.exerciseTypeId;
}
ExerciseType getExerciseType() {
return this.exerciseType;
}
createNew() {
this.exerciseType = ExerciseType();
}
}
+23
View File
@@ -0,0 +1,23 @@
import 'package:aitrainer_app/model/exercise.dart';
class ExerciseViewModel {
Exercise exercise;
ExerciseViewModel({this.exercise});
createNew() {
this.exercise = Exercise();
exercise.datetimeExercise = DateTime.now();
}
setQuantity(int quantity) {
this.exercise.quantity = quantity;
}
setDatetimeExercise(DateTime datetimeExercise) {
this.exercise.datetimeExercise = datetimeExercise;
}
Exercise getExercise() {
return this.exercise;
}
}
+67
View File
@@ -0,0 +1,67 @@
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:aitrainer_app/viewmodel/customer_view_model.dart';
import 'package:provider/provider.dart';
class CustomerListWidget extends StatefulWidget {
static const routeName = '/customer_list';
final List<CustomerViewModel> customers;
CustomerListWidget({this.customers});
@override
_CustomerListWidget createState() => _CustomerListWidget();
}
class _CustomerListWidget extends State<CustomerListWidget> {
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: widget.customers.length,
itemBuilder: (context, index) {
final customer = widget.customers[index];
return ListTile(
contentPadding: EdgeInsets.all(10),
leading:Icon(Icons.accessibility),
title: Text(customer.name + " " + customer.firstName),
subtitle:
Container(
child: Visibility(
visible: customer.visibleDetails,
child: Row(
children: <Widget>[
Text(customer.age.toString() + " years, " + customer.sex),
new RaisedButton(
child: new Text('Modify'),
color: Color.fromRGBO(244, 122, 22, 0.9),
onPressed: () => {
},
),
new RaisedButton(
child: new Text('Select'),
color: Colors.blueGrey,
onPressed: () => {
Provider.of<ExerciseChangingViewModel>(context, listen: false).setCustomer(customer.customer),
Navigator.pop(context)
},
),
],
),
),
),
onTap: () { setState( () {
customer.visibleDetails = true;
});
},
);
},
);
}
}
+65
View File
@@ -0,0 +1,65 @@
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
class CustomPicker extends CommonPickerModel {
String digits(int value, int length) {
return '$value'.padLeft(length, "0");
}
CustomPicker({DateTime currentTime, LocaleType locale}) : super(locale: locale) {
this.currentTime = currentTime ?? DateTime.now();
this.setLeftIndex(this.currentTime.hour);
this.setMiddleIndex(this.currentTime.minute);
this.setRightIndex(this.currentTime.second);
}
@override
String leftStringAtIndex(int index) {
if (index >= 0 && index < 24) {
return this.digits(index, 2);
} else {
return null;
}
}
@override
String middleStringAtIndex(int index) {
if (index >= 0 && index < 60) {
return this.digits(index, 2);
} else {
return null;
}
}
@override
String rightStringAtIndex(int index) {
if (index >= 0 && index < 60) {
return this.digits(index, 2);
} else {
return null;
}
}
@override
String leftDivider() {
return "|";
}
@override
String rightDivider() {
return "|";
}
@override
List<int> layoutProportions() {
return [1, 2, 1];
}
@override
DateTime finalTime() {
return currentTime.isUtc
? DateTime.utc(currentTime.year, currentTime.month, currentTime.day,
this.currentLeftIndex(), this.currentMiddleIndex(), this.currentRightIndex())
: DateTime(currentTime.year, currentTime.month, currentTime.day, this.currentLeftIndex(),
this.currentMiddleIndex(), this.currentRightIndex());
}
}
@@ -0,0 +1,75 @@
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
import 'package:aitrainer_app/viewmodel/exercise_type_view_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ExerciseTypeListWidget extends StatefulWidget {
final List<ExerciseTypeViewModel> exerciseTypes;
ExerciseTypeListWidget({this.exerciseTypes});
@override
_ExerciseTypeListWidgetState createState() => _ExerciseTypeListWidgetState();
}
class _ExerciseTypeListWidgetState extends State<ExerciseTypeListWidget> {
//static const routeName = '/exercise_type_list';
bool visible = false;
// Push the page and remove everything else
navigateToPage(BuildContext context, String page) {
Navigator.of(context).pushNamedAndRemoveUntil(page, (Route<dynamic> route) => false);
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: widget.exerciseTypes.length,
itemBuilder: (context, index) {
final exerciseType = widget.exerciseTypes[index];
return ListTile(
contentPadding: EdgeInsets.all(10),
leading: Icon(Icons.directions_run),
title: Text(exerciseType.name),
subtitle:
Container(
child: Visibility(
visible: exerciseType.visible,
child: Column(
children: <Widget>[
Text(exerciseType.description),
new RaisedButton(
child: new Text('Modify'),
color: Color.fromRGBO(244, 122, 22, 0.9),
onPressed: () => {
Navigator.pushNamed(
context,
'exerciseTypeModifyPage',
arguments: exerciseType
)
},
),
new RaisedButton(
child: new Text('Select'),
color: Colors.blueGrey,
onPressed: () => {
Navigator.pop(context),
Provider.of<ExerciseChangingViewModel>(context, listen: false).setExerciseType(exerciseType.exerciseType),
},
),
],
),
),
),
onTap: () { setState( () {
exerciseType.visible = true;
});
},
);
},
);
}
}
+44
View File
@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
class NavDrawer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text(
'Customers And Exercises',
style: TextStyle(color: Colors.blue, fontSize: 25),
),
),
ListTile(
leading: Icon(Icons.home),
title: Text('Home'),
onTap: () => Navigator.of(context).pushNamed('home'),
),
ListTile(
leading: Icon(Icons.people),
title: Text('Customers'),
//onTap: () => navigateToPage(context, 'customersPage'),
onTap: () => Navigator.of(context).pushNamed('customersPage'),
),
ListTile(
leading: Icon(Icons.directions_run),
title: Text('Exercises'),
onTap: () => Navigator.of(context).pushNamed('exerciseTypeListPage'),
),
ListTile(
leading: Icon(Icons.arrow_upward),
title: Text("TRAINING!"),
onTap: () => Navigator.of(context).pushNamed('exerciseNewPage'),
),
],
),
);
}
}