From 7750972a421477070f8b92a2caa6a5ed13cc555f Mon Sep 17 00:00:00 2001 From: itsscb Date: Sat, 4 Nov 2023 01:44:49 +0100 Subject: [PATCH] rf/replaces home_screen and login backs up old screens to pages_old --- frontend/app/lib/data/database.dart | 10 +- frontend/app/lib/main.dart | 10 +- .../lib/model/services/backend_service.dart | 10 +- frontend/app/lib/pages/home_page.dart | 160 ++++++++++++++++++ frontend/app/lib/pages/login_overlay.dart | 134 +++++++++++++++ frontend/app/lib/pages/pages.dart | 1 - .../{pages => pages_old}/dashboard_page.dart | 2 +- .../lib/{pages => pages_old}/login_page.dart | 2 +- .../{pages => pages_old}/register_page.dart | 2 +- .../lib/{pages => pages_old}/start_page.dart | 6 +- .../app/lib/widgets/bottom_navigation.dart | 48 ++++++ .../lib/widgets/bottom_navigation_item.dart | 45 +++++ frontend/app/lib/widgets/drawer.dart | 31 ++++ .../app/lib/widgets/side_drawer_item.dart | 50 ++++++ 14 files changed, 490 insertions(+), 21 deletions(-) create mode 100644 frontend/app/lib/pages/home_page.dart create mode 100644 frontend/app/lib/pages/login_overlay.dart delete mode 100644 frontend/app/lib/pages/pages.dart rename frontend/app/lib/{pages => pages_old}/dashboard_page.dart (99%) rename frontend/app/lib/{pages => pages_old}/login_page.dart (99%) rename frontend/app/lib/{pages => pages_old}/register_page.dart (99%) rename frontend/app/lib/{pages => pages_old}/start_page.dart (98%) create mode 100644 frontend/app/lib/widgets/bottom_navigation.dart create mode 100644 frontend/app/lib/widgets/bottom_navigation_item.dart create mode 100644 frontend/app/lib/widgets/drawer.dart create mode 100644 frontend/app/lib/widgets/side_drawer_item.dart diff --git a/frontend/app/lib/data/database.dart b/frontend/app/lib/data/database.dart index 7d7e411..1ae9a7f 100644 --- a/frontend/app/lib/data/database.dart +++ b/frontend/app/lib/data/database.dart @@ -14,9 +14,7 @@ class Session { this.refreshToken, this.refreshTokenExpiresAt, this.accountId, - }) { - _init(); - } + }); String? sessionId; String? accessToken; @@ -169,12 +167,14 @@ class Session { final db = await database; final List> maps = await db.query('sessions'); - + print(maps); final List sessions = List.generate( maps.length, (i) { // print('GOT MAP: ${maps[i]}'); - + if (maps[i]['sessionId'] == null) { + return Session(); + } return Session( sessionId: maps[i]['sessionId'] as String, accessToken: maps[i]['accessToken'] as String, diff --git a/frontend/app/lib/main.dart b/frontend/app/lib/main.dart index e790121..14f789a 100644 --- a/frontend/app/lib/main.dart +++ b/frontend/app/lib/main.dart @@ -1,6 +1,4 @@ -import 'package:app/gapi/client.dart'; -import 'package:app/pages/start_page.dart'; -import 'package:app/widgets/background.dart'; +import 'package:app/pages/home_page.dart'; import 'package:flutter/material.dart'; void main() async { @@ -43,11 +41,7 @@ void main() async { backgroundColor: Colors.black, foregroundColor: Colors.white, )), - home: Background( - child: StartPage( - // client: await GClient.client, - ), - ), + home: const HomePage(), ), ); } diff --git a/frontend/app/lib/model/services/backend_service.dart b/frontend/app/lib/model/services/backend_service.dart index 6cc42d0..f67b83d 100644 --- a/frontend/app/lib/model/services/backend_service.dart +++ b/frontend/app/lib/model/services/backend_service.dart @@ -202,7 +202,15 @@ class BackendService { password: password, ), ); - await Session.newSession(response as Session); + Session s = Session( + accessToken: response.accessToken, + sessionId: response.sessionId, + accessTokenExpiresAt: response.accessTokenExpiresAt, + refreshToken: response.refreshToken, + refreshTokenExpiresAt: response.refreshTokenExpiresAt, + accountId: response.accountId, + ); + await Session.newSession(s); return response.accessToken != ''; } on SocketException { throw FetchDataException('Keine Internet Verbindung'); diff --git a/frontend/app/lib/pages/home_page.dart b/frontend/app/lib/pages/home_page.dart new file mode 100644 index 0000000..d34c4d6 --- /dev/null +++ b/frontend/app/lib/pages/home_page.dart @@ -0,0 +1,160 @@ +import 'dart:io'; + +import 'package:app/model/services/backend_service.dart'; +import 'package:app/model/view_model/account_vm.dart'; +import 'package:app/pages/login_overlay.dart'; +import 'package:app/widgets/background.dart'; +import 'package:app/widgets/bottom_navigation.dart'; +import 'package:app/widgets/bottom_navigation_item.dart'; +import 'package:app/widgets/drawer.dart'; +import 'package:app/widgets/side_drawer_item.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class HomePage extends StatefulWidget { + const HomePage({super.key}); + + @override + State createState() => _HomePageState(); +} + +class _HomePageState extends State { + @override + void initState() { + super.initState(); + _init(); + } + + void _init() async { + _setLoading(true); + _loggedin = await BackendService.isLoggedIn; + _setLoading(false); + } + + void _setLoading(bool loading) { + setState(() { + _loading = loading; + }); + } + + bool _loading = true; + bool _loggedin = false; + @override + Widget build(BuildContext context) { + return Background( + child: ChangeNotifierProvider( + create: (context) => AccountViewModel(), + child: Consumer( + builder: (context, value, child) => Scaffold( + appBar: AppBar( + automaticallyImplyLeading: false, + // flexibleSpace: Image.asset( + // 'lib/assets/logo_300x200.png', + // // height: 400, + // ), + ), + drawer: SideDrawer( + children: [ + const Spacer( + flex: 3, + ), + SideDrawerItem( + onPressed: () {}, + icon: Icons.question_answer, + color: Colors.white, + label: 'About', + ), + SideDrawerItem( + onPressed: () {}, + icon: Icons.privacy_tip, + color: Colors.white, + label: 'Datenschutz', + ), + SideDrawerItem( + onPressed: () {}, + icon: Icons.apartment, + color: Colors.white, + label: 'Impressum', + ), + const Spacer( + flex: 1, + ), + if (_loggedin || value.response.data != null) + SideDrawerItem( + onPressed: () {}, + icon: Icons.logout, + color: Colors.white, + label: 'Logout', + ), + ], + ), + bottomNavigationBar: BottomNavigation( + children: [ + if (!_loggedin) ...[ + BottomNavigationItem( + onPressed: () {}, + icon: Icons.person_add_alt, + color: Colors.white, + label: 'Registrieren', + ), + BottomNavigationItem( + onPressed: () async { + _loggedin = await showLogin(context); + }, + icon: Icons.login, + color: Colors.white, + label: 'Login', + ), + ] else + BottomNavigationItem( + onPressed: () {}, + icon: Icons.person_search, + color: Colors.white, + label: 'Personen', + ), + BottomNavigationItem( + onPressed: () {}, + icon: Icons.dashboard, + color: Colors.white, + label: 'Dashboard', + ), + ...[] + ], + ), + body: Padding( + padding: const EdgeInsets.fromLTRB(16, 40, 16, 16), + child: Center( + child: _loading + ? const CircularProgressIndicator( + color: Colors.grey, + ) + : Column( + children: [ + Image.asset( + 'lib/assets/logo_300x200.png', + ), + const SizedBox( + height: 40, + ), + Text( + 'Digitale Spuren auf Knopfdruck entfernen' + .toUpperCase(), + textAlign: TextAlign.center, + style: const TextStyle( + fontFamily: 'sans-serif', + fontSize: 24, + height: 1.6, + fontWeight: FontWeight.normal, + letterSpacing: 6, + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/frontend/app/lib/pages/login_overlay.dart b/frontend/app/lib/pages/login_overlay.dart new file mode 100644 index 0000000..21e265f --- /dev/null +++ b/frontend/app/lib/pages/login_overlay.dart @@ -0,0 +1,134 @@ +import 'package:app/model/services/backend_service.dart'; +import 'package:app/widgets/background.dart'; +import 'package:flutter/material.dart'; + +Future showLogin(BuildContext context) async { + final _formKey = GlobalKey(); + final mailController = TextEditingController(); + final passwordController = TextEditingController(); + + bool _loggedin = false; + + await showModalBottomSheet( + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.black, + context: context, + builder: (builder) { + return Background( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + height: 50, + ), + const Image( + width: 180, + image: AssetImage( + 'lib/assets/logo_300x200.png', + ), + ), + const SizedBox( + height: 30, + ), + const Text( + 'Login', + style: TextStyle( + fontFamily: 'sans-serif', + fontSize: 24, + height: 1.6, + fontWeight: FontWeight.normal, + letterSpacing: 6, + ), + ), + Form( + key: _formKey, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox( + height: 40, + ), + TextFormField( + controller: mailController, + decoration: const InputDecoration( + fillColor: Color.fromARGB(30, 255, 255, 255), + filled: true, + hintStyle: TextStyle( + color: Colors.white38, + ), + hintText: 'E-Mail Adresse', + ), + keyboardType: TextInputType.emailAddress, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Bitte eine gültige E-Mail Adresse eingeben'; + } + return null; + }, + ), + TextFormField( + style: const TextStyle( + color: Colors.white, + ), + controller: passwordController, + decoration: const InputDecoration( + fillColor: Color.fromARGB(30, 255, 255, 255), + filled: true, + hintStyle: TextStyle( + color: Colors.white38, + ), + hintText: 'Passwort', + ), + keyboardType: TextInputType.visiblePassword, + obscureText: true, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Bitte geben Sie Ihr Passwort ein'; + } + return null; + }, + ), + const SizedBox( + height: 15, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + onPressed: () { + Navigator.pop(context); + }, + child: const Icon(Icons.arrow_back), + ), + ElevatedButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + BackendService.login( + email: mailController.text, + password: passwordController.text, + ).then( + (r) { + if (r) { + _loggedin = r; + Navigator.pop(context, true); + } + }, + ); + } + }, + child: const Icon(Icons.login), + ), + ], + ) + ], + ), + ), + const Spacer(), + ], + ), + ); + }); + return _loggedin; +} diff --git a/frontend/app/lib/pages/pages.dart b/frontend/app/lib/pages/pages.dart deleted file mode 100644 index 6db3efe..0000000 --- a/frontend/app/lib/pages/pages.dart +++ /dev/null @@ -1 +0,0 @@ -enum Pages { start, login, about, persons, dashboard } diff --git a/frontend/app/lib/pages/dashboard_page.dart b/frontend/app/lib/pages_old/dashboard_page.dart similarity index 99% rename from frontend/app/lib/pages/dashboard_page.dart rename to frontend/app/lib/pages_old/dashboard_page.dart index 14d3a25..3c8503b 100644 --- a/frontend/app/lib/pages/dashboard_page.dart +++ b/frontend/app/lib/pages_old/dashboard_page.dart @@ -1,5 +1,5 @@ import 'package:app/gapi/client.dart'; -import 'package:app/pages/start_page.dart'; +import 'package:app/pages_old/start_page.dart'; import 'package:app/pb/account_info.pb.dart'; import 'package:app/pb/rpc_get_account_info.pb.dart'; import 'package:app/widgets/background.dart'; diff --git a/frontend/app/lib/pages/login_page.dart b/frontend/app/lib/pages_old/login_page.dart similarity index 99% rename from frontend/app/lib/pages/login_page.dart rename to frontend/app/lib/pages_old/login_page.dart index b7d49d2..d2207e7 100644 --- a/frontend/app/lib/pages/login_page.dart +++ b/frontend/app/lib/pages_old/login_page.dart @@ -1,6 +1,6 @@ import 'package:app/gapi/client.dart'; import 'package:app/model/services/backend_service.dart'; -import 'package:app/pages/start_page.dart'; +import 'package:app/pages_old/start_page.dart'; import 'package:app/widgets/background.dart'; import 'package:app/widgets/bottom_bar.dart'; import 'package:app/widgets/loading_widget.dart'; diff --git a/frontend/app/lib/pages/register_page.dart b/frontend/app/lib/pages_old/register_page.dart similarity index 99% rename from frontend/app/lib/pages/register_page.dart rename to frontend/app/lib/pages_old/register_page.dart index d5ee106..2a40fd6 100644 --- a/frontend/app/lib/pages/register_page.dart +++ b/frontend/app/lib/pages_old/register_page.dart @@ -1,5 +1,5 @@ import 'package:app/gapi/client.dart'; -import 'package:app/pages/start_page.dart'; +import 'package:app/pages_old/start_page.dart'; import 'package:app/widgets/background.dart'; import 'package:app/widgets/bottom_bar.dart'; import 'package:app/widgets/loading_widget.dart'; diff --git a/frontend/app/lib/pages/start_page.dart b/frontend/app/lib/pages_old/start_page.dart similarity index 98% rename from frontend/app/lib/pages/start_page.dart rename to frontend/app/lib/pages_old/start_page.dart index 39d6ecf..6235c2c 100644 --- a/frontend/app/lib/pages/start_page.dart +++ b/frontend/app/lib/pages_old/start_page.dart @@ -1,9 +1,9 @@ import 'package:app/gapi/client.dart'; import 'package:app/model/apis/api_response.dart'; import 'package:app/model/view_model/account_vm.dart'; -import 'package:app/pages/dashboard_page.dart'; -import 'package:app/pages/login_page.dart'; -import 'package:app/pages/register_page.dart'; +import 'package:app/pages_old/dashboard_page.dart'; +import 'package:app/pages_old/login_page.dart'; +import 'package:app/pages_old/register_page.dart'; import 'package:app/pb/account.pb.dart'; import 'package:app/widgets/background.dart'; import 'package:app/widgets/bottom_bar.dart'; diff --git a/frontend/app/lib/widgets/bottom_navigation.dart b/frontend/app/lib/widgets/bottom_navigation.dart new file mode 100644 index 0000000..25e74b9 --- /dev/null +++ b/frontend/app/lib/widgets/bottom_navigation.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; + +class BottomNavigation extends StatelessWidget { + BottomNavigation({ + super.key, + required this.children, + this.backgroundColor, + this.iconColor, + }) { + backgroundColor ??= Colors.black; + } + + List children; + Color? backgroundColor; + Color? iconColor; + + @override + Widget build(BuildContext context) { + return Container( + height: 70, + color: backgroundColor, + child: Center( + child: Padding( + padding: const EdgeInsets.symmetric( + // horizontal: 10, + ), + child: Row( + mainAxisAlignment: children.isEmpty + ? MainAxisAlignment.center + : MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ...children, + Builder(builder: (context) { + return IconButton( + onPressed: () => Scaffold.of(context).openDrawer(), + icon: const Icon( + Icons.menu, + color: Colors.white, + )); + }), + ], + ), + ), + ), + ); + } +} diff --git a/frontend/app/lib/widgets/bottom_navigation_item.dart b/frontend/app/lib/widgets/bottom_navigation_item.dart new file mode 100644 index 0000000..72f46c3 --- /dev/null +++ b/frontend/app/lib/widgets/bottom_navigation_item.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; + +class BottomNavigationItem extends StatelessWidget { + BottomNavigationItem({ + super.key, + required this.onPressed, + required this.icon, + required this.color, + this.textSize, + this.iconSize, + this.label, + }) { + textSize ??= 15; + iconSize ??= 25; + } + + void Function() onPressed; + IconData icon; + Color color; + double? textSize; + double? iconSize; + String? label; + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: + label != null ? MainAxisAlignment.center : MainAxisAlignment.center, + children: [ + IconButton( + onPressed: onPressed, + icon: Icon( + icon, + size: iconSize, + color: color, + )), + if (label != null) + Text( + label!, + style: TextStyle(fontSize: textSize, color: color), + ), + ], + ); + } +} diff --git a/frontend/app/lib/widgets/drawer.dart b/frontend/app/lib/widgets/drawer.dart new file mode 100644 index 0000000..5ec955b --- /dev/null +++ b/frontend/app/lib/widgets/drawer.dart @@ -0,0 +1,31 @@ +import 'package:app/pages/home_page.dart'; +import 'package:app/widgets/side_drawer_item.dart'; +import 'package:flutter/material.dart'; + +class SideDrawer extends StatelessWidget { + SideDrawer({super.key, required this.children, this.backgroundColor}) { + backgroundColor ??= Colors.black; + } + + List children; + Color? backgroundColor; + + @override + Widget build(BuildContext context) { + return Drawer( + backgroundColor: backgroundColor, + child: Padding( + padding: const EdgeInsets.all(40.0), + child: Center( + child: Builder(builder: (context) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: children, + ); + }), + ), + ), + ); + } +} diff --git a/frontend/app/lib/widgets/side_drawer_item.dart b/frontend/app/lib/widgets/side_drawer_item.dart new file mode 100644 index 0000000..35668a4 --- /dev/null +++ b/frontend/app/lib/widgets/side_drawer_item.dart @@ -0,0 +1,50 @@ +import 'package:app/pages/home_page.dart'; +import 'package:flutter/material.dart'; + +class SideDrawerItem extends StatelessWidget { + SideDrawerItem({ + super.key, + required this.onPressed, + required this.icon, + required this.color, + required this.label, + this.textSize, + this.iconSize, + }) { + textSize ??= 15; + iconSize ??= 25; + } + + void Function() onPressed; + IconData icon; + Color color; + String label; + double? textSize; + double? iconSize; + + @override + Widget build(BuildContext context) { + return TextButton( + onPressed: onPressed, + child: Row( + // mainAxisAlignment: MainAxisAlignment.start, + children: [ + Icon( + icon, + color: color, + ), + const SizedBox( + width: 20, + ), + Text( + label, + style: TextStyle( + fontSize: textSize, + color: color, + ), + ) + ], + ), + ); + } +}