diff --git a/assets/icons/google.png b/assets/icons/google.png new file mode 100644 index 0000000..c81a2e2 Binary files /dev/null and b/assets/icons/google.png differ diff --git a/assets/images/big_logo.png b/assets/images/big_logo.png new file mode 100644 index 0000000..61c100f Binary files /dev/null and b/assets/images/big_logo.png differ diff --git a/lib/providers/auth_provider.dart b/lib/providers/auth_provider.dart index c778636..e35ca60 100644 --- a/lib/providers/auth_provider.dart +++ b/lib/providers/auth_provider.dart @@ -66,6 +66,11 @@ class AuthProvider extends ChangeNotifier { } } + void clearGoogleAccount()async{ + await _googleSignIn.signOut(); + notifyListeners(); + } + void signOut() async { await _googleSignIn.signOut(); await _firebaseAuth.signOut(); diff --git a/lib/screens/auth_screen.dart b/lib/screens/auth_screen.dart index c6984a8..abb0977 100644 --- a/lib/screens/auth_screen.dart +++ b/lib/screens/auth_screen.dart @@ -3,8 +3,7 @@ import 'package:drinkable/screens/data_entry_screen.dart'; import 'package:flutter/material.dart'; import 'package:google_sign_in/google_sign_in.dart'; import 'package:provider/provider.dart'; -import '../widgets/custom_drawer.dart'; -import 'package:firebase_auth/firebase_auth.dart'; +import 'package:google_fonts/google_fonts.dart'; class AuthScreen extends StatefulWidget { static const routeName = 'auth-screen'; @@ -22,65 +21,154 @@ class _AuthScreenState extends State { }); } - // void checkSignedIn(BuildContext context) async { - // toggleLoading(); - // try{ - // User user = await FirebaseAuth.instance.currentUser; - // if(user==null){ - // print('user not logged in'); - // //toggleLoading(); - // }else{ - // Navigator.of(context).popAndPushNamed(CustomDrawer.routeName); - // return; - // } - // }catch(e){ - // print(e); - // } - // } + void selectAccount(BuildContext ctx) async { + toggleLoading(); + bool newuser = await Provider.of(ctx,listen: false).selectGoogleAcount(); + print('new user $newuser'); + if(!newuser){ + await Provider.of(ctx,listen: false).signIn(); + }else{ + toggleLoading(); + } + } + @override - Widget build(BuildContext ctx) { - print('Auth screen'); + Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: Text('Auth screen'), - actions: [ - IconButton( - icon: Icon(Icons.account_circle), - onPressed: ()async{ - toggleLoading(); - bool newuser = await Provider.of(ctx,listen: false).selectGoogleAcount(); - print('new user $newuser'); - if(!newuser){ - await Provider.of(ctx,listen: false).signIn(); - //Navigator.of(context).popAndPushNamed(CustomDrawer.routeName); - }else{ - toggleLoading(); - } - } - ) - ], - ), - body: Center( - child:_loading ? CircularProgressIndicator() : Consumer( - builder: (context, value, child) { - GoogleSignInAccount googleAccount = value.googleAcount; - return googleAccount!=null ? Column( + body: Container( + padding: EdgeInsets.fromLTRB(30, 0, 30, 30), + child: Column( + children: [ + Expanded( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Image.asset('assets/images/big_logo.png',height: 90,), + SizedBox(height: 10,), + Text( + 'drinkable', + style: GoogleFonts.pacifico( + fontWeight: FontWeight.w500, + fontSize: 26, + color: Color.fromARGB(255, 0, 60, 192), + ), + ), + SizedBox(height: 15,), + Container( + constraints: BoxConstraints( + maxWidth: 250 + ), + child: Text( + 'Drinkable keeps track your daily water intake and reminds you to drink water by sending notification in intervals', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + color: Colors.black.withOpacity(0.60) + ), + ), + ), + ], + ), + ), + ), + Column( mainAxisSize: MainAxisSize.min, children: [ - CircleAvatar( - backgroundImage: NetworkImage(googleAccount.photoUrl), - ), - Text(googleAccount.displayName), - Text(googleAccount.email), - RaisedButton( - onPressed: (){ - Navigator.of(ctx).pushNamed(DataEntryScreen.routeName); + _loading ? CircularProgressIndicator() : Consumer( + builder: (ctx, authProvider, child) { + GoogleSignInAccount googleAccount = authProvider.googleAcount; + return googleAccount!=null ? + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CircleAvatar( + backgroundImage: NetworkImage(googleAccount.photoUrl), + ), + FlatButton( + child: Text('Continue as ${googleAccount.displayName}'), + onPressed: (){ + Navigator.of(context).pushNamed(DataEntryScreen.routeName); + }, + ), + InkWell( + splashColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: (){ + Provider.of(ctx,listen: false).clearGoogleAccount(); + }, + child: Padding( + padding: EdgeInsets.fromLTRB(10, 10, 0, 10), + child: Icon(Icons.clear), + ), + ), + ], + ) : GestureDetector( + onTap: (){ + selectAccount(context); + }, + child: Card( + elevation: 3, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10) + ), + color: Colors.blueAccent, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Container( + padding: EdgeInsets.all(3), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8) + ), + child: Image.asset('assets/icons/google.png',height: 20,) + ), + Text( + 'Continue with Google', + style: TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.w500 + ), + ) + ], + ), + ), + ), + ); + }, + ), + Container( + padding: EdgeInsets.fromLTRB(20, 10, 20, 0), + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 12 + ), + children: [ + TextSpan( + text: 'By signing up you accept the ', + ), + TextSpan( + text: 'Terms of Service and Privacy Policy.', + style: TextStyle( + fontWeight: FontWeight.w500 + ) + ) + ] + ), + ) ) ], - ) : Text('No account selected'); - }, - ) + ) + ], + ), ), ); } diff --git a/lib/screens/data_entry_screen.dart b/lib/screens/data_entry_screen.dart index e6fbf6a..d7cc775 100644 --- a/lib/screens/data_entry_screen.dart +++ b/lib/screens/data_entry_screen.dart @@ -1,24 +1,337 @@ import 'package:drinkable/providers/auth_provider.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:google_sign_in/google_sign_in.dart'; +import 'package:intl/intl.dart'; +import '../utils/time_converter.dart'; class DataEntryScreen extends StatelessWidget { static const routeName = 'data-entry-screen'; @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: Text('Data entry'), - ), - body: Center( - child: RaisedButton( - child: Text('Lest go'), - onPressed: ()async{ - await Provider.of(context,listen: false).signUp(); - Navigator.of(context).pop(); - }, + body: Container( + padding: EdgeInsets.fromLTRB(30,30, 30, 0), + child: SingleChildScrollView( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + InkWell( + onTap: (){ + Navigator.of(context).pop(); + }, + child: Icon(Icons.arrow_back_ios) + ) + ], + ), + SizedBox(height: 20,), + Column( + children: [ + Icon(Icons.date_range), + SizedBox(height: 10,), + Text('About you',style: TextStyle(fontSize: 23),), + SizedBox(height: 20,), + Container( + constraints: BoxConstraints( + maxWidth: 270 + ), + child: Text( + 'This information will let us help to calculate your daily recommended water intake amount and remind you to drink water in intervals.', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + color: Colors.black.withOpacity(0.60), + height: 1.4 + ), + ), + ), + SizedBox(height: 30,), + Consumer( + builder: (context, authProvider, child) { + GoogleSignInAccount googleAccount = authProvider.googleAcount; + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + CircleAvatar( + backgroundImage: NetworkImage(googleAccount.photoUrl), + ), + SizedBox(height: 15,), + Text('${googleAccount.email}'), + ], + ); + }, + ), + ], + ), + SizedBox(height: 50,), + DataEntryForm(), + ], + ), ), ), ); } -} \ No newline at end of file +} + +class DataEntryForm extends StatefulWidget { + @override + _DataEntryFormState createState() => _DataEntryFormState(); +} + +class _DataEntryFormState extends State { + bool _loading = false; + GlobalKey _formKey = GlobalKey(); + + void toggleLoading(){ + setState(() { + _loading = !_loading; + }); + } + + // data + String _gender = 'male'; + DateTime _birthday = DateTime(1997,4,1); + double _weight; + TimeOfDay _wakeUpTime = TimeOfDay(hour: 8, minute: 0); + + void submit()async{ + if(!_formKey.currentState.validate()){ + return; + } + } + + @override + Widget build(BuildContext context) { + return Form( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Expanded( + flex: 47, + child: CustomFormField( + label: 'Gender', + child: DropdownButtonFormField( + value: _gender, + items: >[ + DropdownMenuItem( + child: Text('Male',style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w500 + ),), + value: 'male', + ), + DropdownMenuItem( + child: Text('Female',style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w500 + ),), + value: 'female', + ), + ], + decoration: InputDecoration( + border: InputBorder.none + ), + onChanged: (String gender){ + setState(() { + _gender = gender; + }); + }, + ), + ) + ), + Expanded( + flex: 6, + child: SizedBox(height: 20,) + ), + Expanded( + flex: 47, + child: GestureDetector( + onTap: ()async{ + DateTime date = await showDatePicker( + context: context, + initialDate:DateTime(1997,4,1), + firstDate: DateTime(1960), + lastDate: DateTime(DateTime.now().year-12,12,31), + ); + print(date); + }, + child: CustomFormField( + label: 'Birthday', + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + DateFormat.yMMMd('en_US').format(_birthday), + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w500 + ), + ), + Icon(Icons.arrow_drop_down) + ], + ) + ), + ) + ), + ], + ), + SizedBox(height: 15,), + Row( + children: [ + Expanded( + flex: 47, + child: CustomFormField( + label: 'Weight', + child: TextFormField( + decoration: InputDecoration( + border: InputBorder.none, + hintText: '60 kg', + suffixText: 'kg', + ), + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w500 + ), + keyboardType: TextInputType.number, + textInputAction: TextInputAction.done, + validator: (String value){ + if(value.isEmpty){ + return 'Enter weight'; + } + if(double.parse(value)<40){ + return 'You are underweight'; + } + return null; + }, + ), + ) + ), + Expanded( + flex: 6, + child: SizedBox(height: 20,), + ), + Expanded( + flex: 47, + child: GestureDetector( + onTap: ()async{ + TimeOfDay time = await showTimePicker( + context: context, + initialTime: TimeOfDay(hour: 8, minute: 0), + ); + if(time!=null){ + setState(() { + _wakeUpTime = time; + }); + } + }, + child: CustomFormField( + label: 'Wakes Up', + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + timeConverter(_wakeUpTime), + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w500 + ), + ), + Icon(Icons.arrow_drop_down) + ], + ) + ), + ) + ), + ], + ), + SizedBox(height: 15,), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + RaisedButton( + elevation: 1, + color: Color.fromARGB(255, 0, 60, 192), + + child: _loading ? SizedBox( + height: 22,width: 22, + child: CircularProgressIndicator( + strokeWidth: 2, + ) + ) : Text( + 'Let\'t go', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.w400, + fontSize: 12 + ), + ), + + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(3)), + onPressed: (){ + //toggleLoading(); + submit(); + }, + ) + ], + ) + ], + ), + ); + } +} + +class CustomFormField extends StatelessWidget { + final String label; + final Widget child; + CustomFormField({this.child,this.label}); + @override + Widget build(BuildContext context) { + return Container( + //color: Colors.yellow, + height: 60, + child: Stack( + children: [ + Container( + width: double.infinity, + height: double.infinity, + margin: EdgeInsets.only(top: 6), + padding: EdgeInsets.symmetric(horizontal: 12), + decoration: BoxDecoration( + border: Border.all(color: Colors.black.withOpacity(0.3),width: 1.1), + borderRadius: BorderRadius.circular(4) + ), + alignment: Alignment.centerLeft, + child: child + ), + Positioned( + left: 14, + child: Container( + color: Colors.white, + padding: EdgeInsets.symmetric(horizontal: 3), + child: Text( + label, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500 + ), + ) + ), + ) + ], + ), + ); + } +} + +// RaisedButton( +// child: Text('Lest go'), +// onPressed: ()async{ +// await Provider.of(context,listen: false).signUp(); +// Navigator.of(context).pop(); +// }, +// ), \ No newline at end of file diff --git a/lib/utils/time_converter.dart b/lib/utils/time_converter.dart new file mode 100644 index 0000000..f86d44e --- /dev/null +++ b/lib/utils/time_converter.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +String timeConverter(TimeOfDay time) { + int hour = time.hourOfPeriod == 0 ? 12 : time.hourOfPeriod; + int min = time.minute; + DayPeriod period = time.period; + String formatedTime = ''; + if(hour<10){ + formatedTime += '0$hour:'; + }else{ + formatedTime += '$hour:'; + } + + if(min<9){ + formatedTime += '0$min '; + }else{ + formatedTime += '$min '; + } + + if(period==DayPeriod.am){ + formatedTime += 'AM'; + }else{ + formatedTime += 'PM'; + } + return formatedTime; +} \ No newline at end of file diff --git a/lib/widgets/custom_app_bar.dart b/lib/widgets/custom_app_bar.dart index 4a6a5eb..ace87bb 100644 --- a/lib/widgets/custom_app_bar.dart +++ b/lib/widgets/custom_app_bar.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; class CustomAppBar extends StatelessWidget { final Function openDrawer; @@ -15,8 +16,16 @@ class CustomAppBar extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Image.asset('assets/icons/logo.png',height: 20,), - SizedBox(width: 15,), - Text('Drinkable',style: TextStyle(fontWeight: FontWeight.w600,fontSize: 17),) + SizedBox(width: 12,), + //Text('Drinkable',style: TextStyle(fontWeight: FontWeight.w600,fontSize: 17),) + Text( + 'drinkable', + style: GoogleFonts.pacifico( + fontWeight: FontWeight.w500, + fontSize: 18, + color: Color.fromARGB(255, 0, 60, 192), + ), + ) ], ), CircleAvatar( diff --git a/pubspec.lock b/pubspec.lock index 4018088..ec96b37 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -64,6 +64,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.14.13" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.5" cupertino_icons: dependency: "direct main" description: @@ -149,6 +163,13 @@ packages: description: flutter source: sdk version: "0.0.0" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" google_sign_in: dependency: "direct main" description: @@ -185,7 +206,7 @@ packages: source: hosted version: "3.1.4" intl: - dependency: transitive + dependency: "direct main" description: name: intl url: "https://pub.dartlang.org" @@ -247,6 +268,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.7.0" + path_provider: + dependency: transitive + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.14" path_provider_linux: dependency: transitive description: @@ -254,6 +282,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.0.1+2" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.4+3" path_provider_platform_interface: dependency: transitive description: @@ -408,4 +443,4 @@ packages: version: "0.1.0" sdks: dart: ">=2.9.0-14.0.dev <3.0.0" - flutter: ">=1.16.0 <2.0.0" + flutter: ">=1.17.0 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8c80287..6df116b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: drinkable -description: A Flutter application which keep track your water intake and remind you to drink water by sending notification. +description: A Flutter application which keeps track your water intake and remind you to drink water by sending notification. publish_to: 'none' @@ -13,6 +13,8 @@ dependencies: sdk: flutter cupertino_icons: ^0.1.3 + intl: ^0.16.1 + google_fonts: ^1.1.0 shared_preferences: ^0.5.10 provider: ^4.3.2+1 firebase_core: ^0.5.0