diff --git a/lib/Components/rounded_button.dart b/lib/Components/rounded_button.dart new file mode 100644 index 0000000..9a3d67d --- /dev/null +++ b/lib/Components/rounded_button.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:manager_app/constants.dart'; + +class RoundedButton extends StatelessWidget { + final String text; + final Function press; + final Color color, textColor; + final double fontSize; + + const RoundedButton({ + Key key, + this.text, + this.press, + this.color = kPrimaryColor, + this.textColor = kWhite, + this.fontSize + }) : super(key: key); + + @override + Widget build(BuildContext context) { + Size size = MediaQuery.of(context).size; + return TextButton( + style: ButtonStyle( + padding: MaterialStateProperty.resolveWith((states) => EdgeInsets.symmetric(vertical: 25, horizontal: 85)), + backgroundColor: MaterialStateColor.resolveWith((states) => color), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30.0), + ) + ) + ), + + onPressed: () => { + press() + }, + child: Text( + text, + style: new TextStyle(color: textColor, fontSize: fontSize, fontWeight: FontWeight.w400), + ), + ); + } +} \ No newline at end of file diff --git a/lib/Components/rounded_input_field.dart b/lib/Components/rounded_input_field.dart new file mode 100644 index 0000000..9acde31 --- /dev/null +++ b/lib/Components/rounded_input_field.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:manager_app/Components/text_field_container.dart'; +import 'package:manager_app/constants.dart'; + +class RoundedInputField extends StatelessWidget { + final String hintText; + final IconData icon; + final ValueChanged onChanged; + const RoundedInputField({ + Key key, + this.hintText, + this.icon = Icons.person, + this.onChanged, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return TextFieldContainer( + child: TextField( + onChanged: onChanged, + cursorColor: kPrimaryColor, + style: TextStyle(fontSize: 20, color: kBlack), + decoration: InputDecoration( + icon: Icon( + icon, + color: kPrimaryColor, + ), + hintText: hintText, + hintStyle: TextStyle(fontSize: 20.0, color: kBlack), + border: InputBorder.none, + ), + ), + ); + } +} diff --git a/lib/Components/rounded_password_field.dart b/lib/Components/rounded_password_field.dart new file mode 100644 index 0000000..e259c1f --- /dev/null +++ b/lib/Components/rounded_password_field.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:manager_app/Components/text_field_container.dart'; +import 'package:manager_app/constants.dart'; + +class RoundedPasswordField extends StatefulWidget { + final ValueChanged onChanged; + const RoundedPasswordField({ + Key key, + this.onChanged, + }) : super(key: key); + + @override + _RoundedPasswordFieldState createState() => _RoundedPasswordFieldState(); +} + +class _RoundedPasswordFieldState extends State { + bool isVisible = true; + + @override + Widget build(BuildContext context) { + return TextFieldContainer( + child: TextField( + obscureText: isVisible, + onChanged: widget.onChanged, + cursorColor: kPrimaryColor, + style: TextStyle(fontSize: 20, color: kBlack), + decoration: InputDecoration( + hintText: "Password", + hintStyle: TextStyle(fontSize: 20.0, color: kBlack), + icon: Icon( + Icons.lock, + color: kPrimaryColor, + ), + suffixIcon: IconButton( + icon: Icon(Icons.visibility), + onPressed: () { + setState(() { + isVisible = !isVisible; + }); + }, + color: kPrimaryColor, + ), + border: InputBorder.none, + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/Components/text_field_container.dart b/lib/Components/text_field_container.dart new file mode 100644 index 0000000..9241d20 --- /dev/null +++ b/lib/Components/text_field_container.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:manager_app/constants.dart'; + +class TextFieldContainer extends StatelessWidget { + final Widget child; + const TextFieldContainer({ + Key key, + this.child, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + Size size = MediaQuery.of(context).size; + return Container( + margin: EdgeInsets.symmetric(vertical: 10), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 5), + width: size.width * 0.8, + decoration: BoxDecoration( + color: kTextLightColor, + borderRadius: BorderRadius.circular(29), + ), + child: child, + ); + } +} \ No newline at end of file diff --git a/lib/Models/managerContext.dart b/lib/Models/managerContext.dart new file mode 100644 index 0000000..4325d2f --- /dev/null +++ b/lib/Models/managerContext.dart @@ -0,0 +1,18 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:managerapi/api.dart'; + + +class ManagerAppContext with ChangeNotifier{ + String email; + TokenDTO token; + dynamic clientAPI; + + ManagerAppContext({this.email, this.token}); + + // Implement toString to make it easier to see information about + @override + String toString() { + return 'ManagerAppContext{email: $email, token: $token}'; + } +} \ No newline at end of file diff --git a/lib/Screens/Main/main_screen.dart b/lib/Screens/Main/main_screen.dart new file mode 100644 index 0000000..d606481 --- /dev/null +++ b/lib/Screens/Main/main_screen.dart @@ -0,0 +1,46 @@ +import 'package:manager_app/app_context.dart'; +import 'package:managerapi/api.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class MainScreen extends StatefulWidget { + MainScreen({Key key, this.title}) : super(key: key); + + final String title; + + @override + _MainScreenState createState() => _MainScreenState(); +} + +class _MainScreenState extends State { + int _counter = 0; + + @override + Widget build(BuildContext context) { + final appContext = Provider.of(context); + + print(appContext.getContext().email); + + return Scaffold( + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'You have pushed the button this many times:', + ), + Text( + '$_counter', + style: Theme.of(context).textTheme.headline4, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () => print("YOULOU"), + tooltip: 'Increment', + child: Icon(Icons.add), + ), // This trailing comma makes auto-formatting nicer for build methods. + ); + } +} \ No newline at end of file diff --git a/lib/Screens/login_screen.dart b/lib/Screens/login_screen.dart new file mode 100644 index 0000000..9133471 --- /dev/null +++ b/lib/Screens/login_screen.dart @@ -0,0 +1,155 @@ +import 'package:flutter/material.dart'; +import 'package:manager_app/Components/rounded_button.dart'; +import 'package:manager_app/Components/rounded_input_field.dart'; +import 'package:manager_app/Components/rounded_password_field.dart'; +import 'package:manager_app/Models/managerContext.dart'; +import 'package:manager_app/Screens/Main/main_screen.dart'; +import 'package:manager_app/app_context.dart'; +import 'package:manager_app/client.dart'; +import 'package:manager_app/constants.dart'; +import 'package:managerapi/api.dart'; +import 'package:provider/provider.dart'; + +class LoginScreen extends StatefulWidget { + LoginScreen({Key key}) : super(key: key); + + @override + _LoginScreenState createState() => _LoginScreenState(); +} + +class _LoginScreenState extends State { + String email;// = "test@email.be"; + String password;// = "kljqsdkljqsd"; + final clientAPI = Client(); + + void authenticateTRY(dynamic appContext) async { + print("try auth.. "); + print(this.email); + print(this.password); + + // if () {} // Add if token exist and not null + not expired + var isError = true; + try { + LoginDTO loginDTO = new LoginDTO(email: email, password: password); + TokenDTO token = await clientAPI.authenticationApi.authenticationAuthenticateWithJson(loginDTO); + print("Token ??"); + print(token); + print(token.accessToken); + setAccessToken(token.accessToken); + isError = false; + // Set the appContext + if (appContext.getContext() == null) { + ManagerAppContext managerAppContext = new ManagerAppContext(); + // store user info locally + managerAppContext.email = email; + managerAppContext.token = token; + managerAppContext.clientAPI = clientAPI; + print(managerAppContext); + + appContext.setContext(managerAppContext); + } + + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute( + builder: (context) { + return MainScreen(); + }, + ), + (Route route) => false // For pushAndRemoveUntil + ); + } + catch (e) { + print("error auth"); + } + + /*if (!isError) { + UserDetailDTO user = await clientAPI.userApi.userGetDetail("6071f74aaf542f03116f2b9b"); + print("user values ??"); + print(user.email); + print(user.id); + + List configurations = await clientAPI.configurationApi.configurationGet(); + print("number of configurations " + configurations.length.toString()); + configurations.forEach((element) { + print(element); + }); + + List sections = await clientAPI.sectionApi.sectionGet(); + print("number of sections " + sections.length.toString()); + sections.forEach((element) { + print(element); + }); + + List ressources = await clientAPI.ressourceApi.ressourceGet(); + print("number of ressources " + ressources.length.toString()); + ressources.forEach((element) { + print(element); + }); + }*/ + } + + void setAccessToken(String accessToken) { + clientAPI.apiApi.authentications.forEach((key, auth) { + if (auth is OAuth) { + auth.accessToken = accessToken; + } + }); + } + + @override + Widget build(BuildContext context) { + final appContext = Provider.of(context); + Size size = MediaQuery.of(context).size; + + return Scaffold( + body: Center( + child: SingleChildScrollView( + child: Container( + height: size.height *0.5, + width: size.width *0.5, + decoration: BoxDecoration( + color: kWhite, + borderRadius: BorderRadius.circular(8.0), + boxShadow: [ + BoxShadow( + color: kWhite.withOpacity(0.3), + spreadRadius: 0.5, + blurRadius: 0.5, + offset: Offset(0, 1.5), // changes position of shadow + ), + ], + ), + child: Padding( + padding: const EdgeInsets.only(left: 60.0, right: 60.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + RoundedInputField( + hintText: "Your Email", + onChanged: (value) { + email = value; + }, + ), + RoundedPasswordField( + onChanged: (value) { + password = value; + }, + ), + SizedBox(height: size.height * 0.02), + RoundedButton( + text: "LOGIN", + fontSize: 25, + press: () { + authenticateTRY(appContext); + }, + ), + ], + ), + ), + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/app_context.dart b/lib/app_context.dart new file mode 100644 index 0000000..59927f7 --- /dev/null +++ b/lib/app_context.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +import 'Models/managerContext.dart'; + +class AppContext with ChangeNotifier { + ManagerAppContext _managerContext; + + AppContext(this._managerContext); + + getContext() => _managerContext; + setContext(ManagerAppContext appContext) async { + _managerContext = appContext; + + // STORE IT LOCALLY (SQLite) + //await DatabaseHelper.instance.update(appContext); + + // Store it in Firestore + //await FirestoreHelper.instance.add(appContext); + + notifyListeners(); + } +} diff --git a/lib/constants.dart b/lib/constants.dart index ff0b8e4..75b0ca6 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,10 +1,17 @@ import 'package:flutter/material.dart'; // Colors - TO FILL WIT CORRECT COLOR -const kBackgroundColor = Color(0xFFFFFFFF); +//const kBackgroundColor = Color(0xFFFFFFFF); const kTitleTextColor = Color(0xFF303030); const kBodyTextColor = Color(0xFF4B4B4B); // TODO -const kTextLightColor = Color(0xFFCED5DF); // #ced5df + + +const kBackgroundColor = Color(0xFFf5f5f7); +const kPrimaryColor = Color(0xFFCA413F); +const kTextLightColor = Color(0xFFE3DfDE); +const kSecond = Color(0xFFC4B1AE); +const kWhite = Color(0xFFFFFFFF); +const kBlack = Color(0xFF000000); /* const kTextStyle = TextStyle( diff --git a/lib/main.dart b/lib/main.dart index 8b57b5e..ccb1caa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,17 @@ +import 'package:manager_app/Models/managerContext.dart'; +import 'package:manager_app/Screens/Main/main_screen.dart'; import 'package:managerapi/api.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'Screens/login_screen.dart'; +import 'app_context.dart'; import 'client.dart'; import 'constants.dart'; void main() { String initialRoute; - initialRoute = '/home'; + initialRoute = '/welcome'; final MyApp myApp = MyApp( initialRoute: initialRoute, @@ -18,8 +23,8 @@ void main() { class MyApp extends StatefulWidget { final String initialRoute; - //final Context context; - MyApp({this.initialRoute}); + final ManagerAppContext managerAppContext; + MyApp({this.initialRoute, this.managerAppContext}); // This widget is the root of your application. @override @@ -29,152 +34,29 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { @override Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - title: 'Manager App Demo', - initialRoute: widget.initialRoute, - /*supportedLocales: [ - const Locale('en', 'US'), - //const Locale('fr', 'FR'), - ],*/ - theme: ThemeData( - primarySwatch: Colors.blue, - scaffoldBackgroundColor: kBackgroundColor, - //fontFamily: "Vollkorn", - textTheme: TextTheme(bodyText1: TextStyle(color: kBodyTextColor)), - visualDensity: VisualDensity.adaptivePlatformDensity, - ), - routes: { - '/home': (context) => MyHomePage(title: 'Manager App Demo Home Page') - } + return ChangeNotifierProvider( + create: (_) => AppContext(widget.managerAppContext), + child: MaterialApp( + debugShowCheckedModeBanner: false, + title: 'Manager App Demo', + initialRoute: widget.initialRoute, + /*supportedLocales: [ + const Locale('en', 'US'), + //const Locale('fr', 'FR'), + ],*/ + theme: ThemeData( + primarySwatch: Colors.blue, + scaffoldBackgroundColor: kBackgroundColor, + //fontFamily: "Vollkorn", + textTheme: TextTheme(bodyText1: TextStyle(color: kBodyTextColor)), + visualDensity: VisualDensity.adaptivePlatformDensity, + ), + routes: { + '/welcome': (context) => LoginScreen(), + '/main': (context) => MainScreen(title: 'Manager App Demo Home Page') + } + ), ); } } -class MyHomePage extends StatefulWidget { - MyHomePage({Key key, this.title}) : super(key: key); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; - - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - final clientAPI = Client(); - - void authenticateTRY() async { - print("try auth.. "); - - // if () {} // Add if token exist and not null + not expired - var isError = true; - try { - LoginDTO loginDTO = new LoginDTO(email: "test@email.be", password: "kljqsdkljqsd"); - TokenDTO token = await clientAPI.authenticationApi.authenticationAuthenticateWithJson(loginDTO); - print("Token ??"); - print(token); - print(token.accessToken); - setAccessToken(token.accessToken); - isError = false; - } - catch (e) { - print("error auth"); - } - - if (!isError) { - UserDetailDTO user = await clientAPI.userApi.userGetDetail("6071f74aaf542f03116f2b9b"); - print("user values ??"); - print(user.email); - print(user.id); - - List configurations = await clientAPI.configurationApi.configurationGet(); - print("number of configurations " + configurations.length.toString()); - configurations.forEach((element) { - print(element); - }); - - List sections = await clientAPI.sectionApi.sectionGet(); - print("number of sections " + sections.length.toString()); - sections.forEach((element) { - print(element); - }); - - List ressources = await clientAPI.ressourceApi.ressourceGet(); - print("number of ressources " + ressources.length.toString()); - ressources.forEach((element) { - print(element); - }); - } - } - - void setAccessToken(String accessToken) { - clientAPI.apiApi.authentications.forEach((key, auth) { - if (auth is OAuth) { - auth.accessToken = accessToken; - } - }); - } - - @override - Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. - return Scaffold( - appBar: AppBar( - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Invoke "debug painting" (press "p" in the console, choose the - // "Toggle Debug Paint" action from the Flutter Inspector in Android - // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) - // to see the wireframe for each widget. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headline4, - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: authenticateTRY, - tooltip: 'Increment', - child: Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. - ); - } -} diff --git a/pubspec.lock b/pubspec.lock index 9a02ad2..f4bba9d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -109,6 +109,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" path: dependency: transitive description: @@ -123,6 +130,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.11.0" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.0" rxdart: dependency: "direct main" description: @@ -193,3 +207,4 @@ packages: version: "2.1.0" sdks: dart: ">=2.12.0-0.0 <3.0.0" + flutter: ">=1.16.0" diff --git a/pubspec.yaml b/pubspec.yaml index 3c11e34..50b6331 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,6 +25,7 @@ dependencies: sdk: flutter rxdart: 0.22.0 + provider: ^5.0.0 managerapi: path: manager_api