ft/adds persistence (partial complete)
TODO: Load on start. Not working atm.
This commit is contained in:
parent
5bd03eab7c
commit
dc3a28ba5f
150
frontend/app/lib/data/database.dart
Normal file
150
frontend/app/lib/data/database.dart
Normal file
@ -0,0 +1,150 @@
|
||||
import 'dart:async';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
|
||||
import 'package:app/pb/google/protobuf/timestamp.pb.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
|
||||
class Session {
|
||||
Session({
|
||||
this.sessionId,
|
||||
this.accessToken,
|
||||
this.accessTokenExpiresAt,
|
||||
this.refreshToken,
|
||||
this.refreshTokenExpiresAt,
|
||||
this.accountId,
|
||||
}) {
|
||||
_init();
|
||||
}
|
||||
|
||||
String? sessionId;
|
||||
String? accessToken;
|
||||
String? refreshToken;
|
||||
Timestamp? accessTokenExpiresAt;
|
||||
Timestamp? refreshTokenExpiresAt;
|
||||
Int64? accountId;
|
||||
|
||||
late Database _database;
|
||||
|
||||
Future<Database> get database async => _database;
|
||||
|
||||
static Future<Session> get newSession async {
|
||||
final Database db = await openDatabase(
|
||||
join(await getDatabasesPath(), 'df_database.db'),
|
||||
onCreate: (db, version) {
|
||||
return db.execute(
|
||||
'CREATE TABLE sessions(accountId INTEGER PRIMARY KEY, sessionId TEXT, accessToken TEXT, accessTokenExpiresAt TEXT, refreshToken TEXT, refreshTokenExpiresAt TEXT)',
|
||||
);
|
||||
},
|
||||
version: 1,
|
||||
);
|
||||
Session s = Session();
|
||||
s._database = db;
|
||||
return s;
|
||||
}
|
||||
|
||||
void _init() {
|
||||
_initDatabase();
|
||||
}
|
||||
|
||||
Future<Database> _initDatabase() async {
|
||||
print('DB: INITIALIZING - start');
|
||||
_database = await openDatabase(
|
||||
join(await getDatabasesPath(), 'df_database.db'),
|
||||
onCreate: (db, version) {
|
||||
return db.execute(
|
||||
'CREATE TABLE sessions(accountId INTEGER PRIMARY KEY, sessionId TEXT, accessToken TEXT, accessTokenExpiresAt TEXT, refreshToken TEXT, refreshTokenExpiresAt TEXT)',
|
||||
);
|
||||
},
|
||||
version: 1,
|
||||
);
|
||||
print('DB: INITIALIZING - end');
|
||||
|
||||
return _database;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'accountId': accountId?.toInt(),
|
||||
'sessionId': sessionId,
|
||||
'accessToken': accessToken,
|
||||
'accessTokenExpiresAt': accessTokenExpiresAt?.toDateTime().toString(),
|
||||
'refreshToken': refreshToken,
|
||||
'refreshTokenExpiresAt': refreshTokenExpiresAt?.toDateTime().toString(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Session{accountId: $accountId, sessionId: $sessionId, accessToken: $accessToken, accessTokenExpiresAt: ${accessTokenExpiresAt.toString()}, refreshToken: $refreshToken, refreshTokenExpiresAt: ${refreshTokenExpiresAt.toString()}}';
|
||||
}
|
||||
|
||||
Future<void> insertSession(Session session) async {
|
||||
print('INSERTING SESSION: ${session.sessionId}');
|
||||
final db = _database;
|
||||
final result = await db.insert(
|
||||
'sessions',
|
||||
session.toMap(),
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
print('INSERT RESULT: $result');
|
||||
}
|
||||
|
||||
Future<List<Session>> getSessions() async {
|
||||
final db = await database;
|
||||
|
||||
final List<Map<String, Object?>> maps = await db.query('sessions');
|
||||
|
||||
final List<Session> sessions = List.generate(
|
||||
maps.length,
|
||||
(i) {
|
||||
print('GOT MAP: ${maps[i]}');
|
||||
|
||||
return Session(
|
||||
sessionId: maps[i]['sessionId'] as String,
|
||||
accessToken: maps[i]['accessToken'] as String,
|
||||
accessTokenExpiresAt: Timestamp.fromDateTime(
|
||||
DateTime.parse(maps[i]['accessTokenExpiresAt'] as String)),
|
||||
refreshToken: maps[i]['refreshToken'] as String,
|
||||
refreshTokenExpiresAt: Timestamp.fromDateTime(
|
||||
DateTime.parse(maps[i]['refreshTokenExpiresAt'] as String)),
|
||||
accountId: Int64(maps[i]['accountId'] as int),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return sessions;
|
||||
}
|
||||
|
||||
static Future<Session> getSession(Int64 accountId) async {
|
||||
final Database db = await openDatabase(
|
||||
join(await getDatabasesPath(), 'df_database.db'),
|
||||
onCreate: (db, version) {
|
||||
return db.execute(
|
||||
'CREATE TABLE sessions(accountId INTEGER PRIMARY KEY, sessionId TEXT, accessToken TEXT, accessTokenExpiresAt TEXT, refreshToken TEXT, refreshTokenExpiresAt TEXT)',
|
||||
);
|
||||
},
|
||||
version: 1,
|
||||
);
|
||||
|
||||
final List<Map<String, Object?>> maps = await db.query('sessions',
|
||||
where: 'accountId = ?', whereArgs: [accountId], limit: 1);
|
||||
|
||||
final List<Session> sessions = List.generate(
|
||||
maps.length,
|
||||
(i) {
|
||||
return Session(
|
||||
sessionId: maps[i]['sessionId'] as String,
|
||||
accessToken: maps[i]['accessToken'] as String,
|
||||
accessTokenExpiresAt: maps[i]['accessTokenExpiresAt'] as Timestamp,
|
||||
refreshToken: maps[i]['refreshToken'] as String,
|
||||
refreshTokenExpiresAt: maps[i]['refreshTokenExpiresAt'] as Timestamp,
|
||||
accountId: maps[i]['accountId'] as Int64,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return sessions[0];
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
import 'package:app/data/database.dart';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
import 'package:app/pb/rpc_create_account.pb.dart';
|
||||
import 'package:app/pb/rpc_get_account_info.pb.dart';
|
||||
@ -6,12 +7,28 @@ import 'package:app/pb/service_df.pbgrpc.dart';
|
||||
import 'package:grpc/grpc.dart';
|
||||
|
||||
class GClient {
|
||||
GClient() {
|
||||
// session = Session.newSession();
|
||||
_init();
|
||||
}
|
||||
|
||||
String baseUrl = 'localhost';
|
||||
int port = 9090;
|
||||
|
||||
Map<String, String> metadata = {'Authorization': ''};
|
||||
String accessToken = '';
|
||||
Int64 accountId = Int64();
|
||||
// String accessToken = '';
|
||||
// Int64 accountId = Int64();
|
||||
|
||||
late Session session;
|
||||
|
||||
static Future<GClient> get client async {
|
||||
Session s = await Session.newSession;
|
||||
GClient c = GClient();
|
||||
c.session = s;
|
||||
final sessions = await c.session.getSessions();
|
||||
c.session = sessions[0];
|
||||
return c;
|
||||
}
|
||||
|
||||
dfClient stub = dfClient(
|
||||
ClientChannel('10.0.2.2',
|
||||
@ -25,6 +42,19 @@ class GClient {
|
||||
);
|
||||
Future<void> main(List<String> args) async {}
|
||||
|
||||
void _init() async {
|
||||
// print('CLIENT: INITIALIZING CLIENT - start');
|
||||
|
||||
session = await Session.newSession;
|
||||
// print('CLIENT: getting sessions from database');
|
||||
|
||||
final sessions = await session.getSessions();
|
||||
print('CLIENT: got sessions from database: ${sessions.toString()}');
|
||||
session = sessions[0];
|
||||
// print('CLIENT: INITIALIZING CLIENT - end');
|
||||
print(session.toString());
|
||||
}
|
||||
|
||||
Future<CreateAccountResponse> createAccount(
|
||||
CreateAccountRequest request) async {
|
||||
try {
|
||||
@ -47,8 +77,19 @@ class GClient {
|
||||
email: email,
|
||||
password: password,
|
||||
));
|
||||
accessToken = response.accessToken;
|
||||
accountId = response.accountId;
|
||||
print(response);
|
||||
session.accessToken = response.accessToken;
|
||||
session.accountId = response.accountId;
|
||||
session.sessionId = response.sessionId;
|
||||
session.refreshToken = response.refreshToken;
|
||||
session.accessTokenExpiresAt = response.accessTokenExpiresAt;
|
||||
session.refreshTokenExpiresAt = response.refreshTokenExpiresAt;
|
||||
print('GOT: ${session.toString()}');
|
||||
try {
|
||||
session.insertSession(session);
|
||||
} catch (err) {
|
||||
print('ERROR WRITING DB: $err');
|
||||
}
|
||||
metadata['Authorization'] = 'Bearer ${response.accessToken}';
|
||||
print('auth: ${metadata['Authorization']}');
|
||||
onSuccess();
|
||||
|
@ -1,4 +1,3 @@
|
||||
import 'package:app/pages/home_page.dart';
|
||||
import 'package:app/pages/start_page.dart';
|
||||
import 'package:app/widgets/background.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -5,29 +5,8 @@ import 'package:app/widgets/background.dart';
|
||||
import 'package:app/widgets/loading_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
GlobalKey<ScaffoldState> scaffolKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
List<BottomNavigationBarItem> bottomBarButtons = const [
|
||||
BottomNavigationBarItem(
|
||||
label: 'Zurueck',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'AccountInf',
|
||||
icon: Icon(
|
||||
Icons.person,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
class DashboardPage extends StatefulWidget {
|
||||
DashboardPage({super.key, required this.client});
|
||||
const DashboardPage({super.key, required this.client});
|
||||
|
||||
final GClient client;
|
||||
|
||||
@ -48,15 +27,15 @@ class _DashboardPageState extends State<DashboardPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.client.accessToken == '') {
|
||||
Navigator.of(context).pop();
|
||||
return;
|
||||
}
|
||||
// if (widget.client.session.accessToken == '') {
|
||||
// Navigator.of(context).pop();
|
||||
// return;
|
||||
// }
|
||||
|
||||
_setLoading(true);
|
||||
widget.client.getAccountInfo(
|
||||
GetAccountInfoRequest(
|
||||
accountId: widget.client.accountId,
|
||||
accountId: widget.client.session?.accountId,
|
||||
),
|
||||
onError: () {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||
@ -73,7 +52,6 @@ class _DashboardPageState extends State<DashboardPage> {
|
||||
Widget build(BuildContext context) {
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
key: scaffolKey,
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
flexibleSpace: Image.asset(
|
||||
@ -81,10 +59,7 @@ class _DashboardPageState extends State<DashboardPage> {
|
||||
height: 80,
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
items: bottomBarButtons,
|
||||
backgroundColor: Colors.black,
|
||||
),
|
||||
bottomNavigationBar: BottomBar(),
|
||||
body: !_loading
|
||||
? Background(
|
||||
child: Center(
|
||||
@ -108,3 +83,40 @@ class _DashboardPageState extends State<DashboardPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BottomBar extends StatelessWidget {
|
||||
const BottomBar({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BottomNavigationBar(
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
label: 'back',
|
||||
backgroundColor: Colors.white,
|
||||
icon: IconButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
icon: const Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.person,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
backgroundColor: Colors.black,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,158 +0,0 @@
|
||||
import 'package:app/gapi/client.dart';
|
||||
import 'package:app/pages/login_page.dart';
|
||||
import 'package:app/pages/start_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:app/pages/pages.dart';
|
||||
|
||||
Map<Pages, List<BottomNavigationBarItem>> bottomBarButtons = {
|
||||
Pages.start: const [
|
||||
BottomNavigationBarItem(
|
||||
label: 'Zurueck',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'AccountInf',
|
||||
icon: Icon(
|
||||
Icons.person,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
Pages.persons: const [
|
||||
BottomNavigationBarItem(
|
||||
label: 'Zurueck',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'AccountInf',
|
||||
icon: Icon(
|
||||
Icons.person,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
Pages.about: const [
|
||||
BottomNavigationBarItem(
|
||||
label: 'Zurueck',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'AccountInf',
|
||||
icon: Icon(
|
||||
Icons.person,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
Pages.login: const [
|
||||
BottomNavigationBarItem(
|
||||
label: 'Zurueck',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'AccountInf',
|
||||
icon: Icon(
|
||||
Icons.person,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
]
|
||||
};
|
||||
|
||||
class HomePage extends StatefulWidget {
|
||||
const HomePage({super.key});
|
||||
|
||||
@override
|
||||
State<HomePage> createState() => _HomePageState();
|
||||
}
|
||||
|
||||
class _HomePageState extends State<HomePage> {
|
||||
bool _loading = false;
|
||||
|
||||
Pages _selectedPage = Pages.start;
|
||||
|
||||
Widget _selectPage(Pages page) {
|
||||
switch (page) {
|
||||
case Pages.login:
|
||||
return LoginPage(
|
||||
// onChangePage: changePage,
|
||||
);
|
||||
default:
|
||||
return StartPage(
|
||||
// onChangePage: changePage,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _onWillPop() async {
|
||||
changePage(Pages.start);
|
||||
return false;
|
||||
}
|
||||
|
||||
void changePage(Pages page) {
|
||||
if (!Pages.values.contains(page)) {
|
||||
page = _selectedPage;
|
||||
}
|
||||
setState(() {
|
||||
_selectedPage = page;
|
||||
});
|
||||
}
|
||||
|
||||
void _setLoading(bool loading) {
|
||||
setState(() {
|
||||
_loading = loading;
|
||||
});
|
||||
}
|
||||
|
||||
final GClient client = GClient();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: _selectedPage == Pages.start
|
||||
? AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
)
|
||||
: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
flexibleSpace: Image.asset(
|
||||
'lib/assets/logo_300x200.png',
|
||||
height: 80,
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
items: bottomBarButtons[_selectedPage]!.toList(),
|
||||
backgroundColor: Colors.black,
|
||||
),
|
||||
body: Container(
|
||||
padding: const EdgeInsets.fromLTRB(16, 32, 16, 32),
|
||||
child: Center(
|
||||
child: WillPopScope(
|
||||
child: _selectPage(_selectedPage),
|
||||
onWillPop: () => _onWillPop(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -5,29 +5,7 @@ import 'package:app/widgets/loading_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grpc/grpc.dart';
|
||||
|
||||
GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
List<BottomNavigationBarItem> bottomBarButtons = [
|
||||
const BottomNavigationBarItem(
|
||||
label: 'back',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () => scaffoldKey.currentState!.openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
// GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
LoginPage({
|
||||
@ -43,16 +21,46 @@ class LoginPage extends StatefulWidget {
|
||||
|
||||
class _LoginPageState extends State<LoginPage> {
|
||||
bool _loading = false;
|
||||
final List<BottomNavigationBarItem> bottombarButtons = [];
|
||||
|
||||
List<BottomNavigationBarItem> _selectedBottomBarButtons = bottomBarButtons;
|
||||
// List<BottomNavigationBarItem> _selectedBottomBarButtons = bottomBarButtons;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_addBottomBarButtons();
|
||||
}
|
||||
|
||||
void _bottomBarAction(int index) {
|
||||
switch (_selectedBottomBarButtons[index].label?.toLowerCase()) {
|
||||
switch (bottombarButtons[index].label?.toLowerCase()) {
|
||||
case 'back':
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
|
||||
void _addBottomBarButtons() {
|
||||
bottombarButtons.addAll([
|
||||
const BottomNavigationBarItem(
|
||||
label: 'back',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
void _setLoading(bool loading) {
|
||||
setState(() {
|
||||
_loading = loading;
|
||||
@ -69,7 +77,6 @@ class _LoginPageState extends State<LoginPage> {
|
||||
Widget build(BuildContext context) {
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
key: scaffoldKey,
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
// flexibleSpace: Image.asset(
|
||||
@ -77,81 +84,8 @@ class _LoginPageState extends State<LoginPage> {
|
||||
// height: 80,
|
||||
// ),
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
items: bottomBarButtons,
|
||||
backgroundColor: Colors.black,
|
||||
fixedColor: Colors.black,
|
||||
onTap: (value) => _bottomBarAction(value),
|
||||
),
|
||||
drawer: Drawer(
|
||||
backgroundColor: Colors.black,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(40.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
scaffoldKey.currentState!.closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'About',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.question_answer,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
scaffoldKey.currentState!.closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Datenschutz',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.privacy_tip,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
scaffoldKey.currentState!.closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Impressum',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.apartment,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 250,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: const BottomBar(),
|
||||
drawer: const SideDrawer(),
|
||||
body: !_loading
|
||||
? Form(
|
||||
key: _formKey,
|
||||
@ -227,7 +161,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
return null;
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
ElevatedButton(
|
||||
@ -322,3 +256,121 @@ class _LoginPageState extends State<LoginPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SideDrawer extends StatelessWidget {
|
||||
const SideDrawer({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Drawer(
|
||||
backgroundColor: Colors.black,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(40.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'About',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.question_answer,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Datenschutz',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.privacy_tip,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Impressum',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.apartment,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 250,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BottomBar extends StatelessWidget {
|
||||
const BottomBar({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BottomNavigationBar(
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
label: 'back',
|
||||
backgroundColor: Colors.white,
|
||||
icon: IconButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
icon: const Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
backgroundColor: Colors.black,
|
||||
fixedColor: Colors.black,
|
||||
// onTap: (value) => _bottomBarAction(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,170 +4,41 @@ import 'package:app/widgets/background.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:core';
|
||||
|
||||
GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
List<BottomNavigationBarItem> bottomBarButtons = [
|
||||
const BottomNavigationBarItem(
|
||||
label: 'register',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.person_add,
|
||||
color: Colors.white,
|
||||
),
|
||||
Text(
|
||||
'Registrieren',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
label: 'login',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.login,
|
||||
color: Colors.white,
|
||||
),
|
||||
Text(
|
||||
'Login',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () => scaffoldKey.currentState!.openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
class StartPage extends StatefulWidget {
|
||||
StartPage({
|
||||
super.key,
|
||||
this.client,
|
||||
});
|
||||
|
||||
final GClient? client;
|
||||
GClient? client;
|
||||
|
||||
@override
|
||||
State<StartPage> createState() => _StartPageState();
|
||||
}
|
||||
|
||||
class _StartPageState extends State<StartPage> {
|
||||
List<BottomNavigationBarItem> _selectedBottomBarButtons = bottomBarButtons;
|
||||
// List<BottomNavigationBarItem> _selectedBottomBarButtons = bottomBarButtons;
|
||||
final List<BottomNavigationBarItem> bottombarButtons = [];
|
||||
|
||||
void _bottomBarAction(int index) {
|
||||
switch (_selectedBottomBarButtons[index].label?.toLowerCase()) {
|
||||
case 'login':
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(builder: (context) => LoginPage()));
|
||||
}
|
||||
void _init() async {
|
||||
widget.client ??= await GClient.client;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_init();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
key: scaffoldKey,
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
// flexibleSpace: Image.asset(
|
||||
// 'lib/assets/logo_300x200.png',
|
||||
// height: 80,
|
||||
// ),
|
||||
),
|
||||
drawer: Drawer(
|
||||
backgroundColor: Colors.black,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(40.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
scaffoldKey.currentState!.closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'About',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.question_answer,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
scaffoldKey.currentState!.closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Datenschutz',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.privacy_tip,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
scaffoldKey.currentState!.closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Impressum',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.apartment,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 250,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
onTap: (value) => _bottomBarAction(value),
|
||||
items: bottomBarButtons,
|
||||
backgroundColor: Colors.black,
|
||||
fixedColor: Colors.black,
|
||||
),
|
||||
drawer: const SideDrawer(),
|
||||
bottomNavigationBar: BottomBar(widget: widget),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
@ -192,6 +63,16 @@ class _StartPageState extends State<StartPage> {
|
||||
letterSpacing: 6,
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
final s = widget.client?.session.getSessions();
|
||||
print(s);
|
||||
print(widget.client?.session.accessToken);
|
||||
},
|
||||
child: const Text(
|
||||
"GET SESSIONS",
|
||||
),
|
||||
),
|
||||
// const Spacer(),
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
@ -238,3 +119,199 @@ class _StartPageState extends State<StartPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SideDrawer extends StatelessWidget {
|
||||
const SideDrawer({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Drawer(
|
||||
backgroundColor: Colors.black,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(40.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'About',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.question_answer,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Datenschutz',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.privacy_tip,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Impressum',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.apartment,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 250,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BottomBar extends StatelessWidget {
|
||||
const BottomBar({
|
||||
super.key,
|
||||
required this.widget,
|
||||
});
|
||||
|
||||
final StartPage widget;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BottomNavigationBar(
|
||||
// onTap: (value) => _bottomBarAction(value),
|
||||
items: widget.client?.session.accessToken != null
|
||||
? [
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Personen',
|
||||
icon: Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.group,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
'Personen',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
)
|
||||
]
|
||||
: [
|
||||
BottomNavigationBarItem(
|
||||
label: 'register',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => LoginPage()));
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.login,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
'Registrieren',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
label: 'login',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => LoginPage()));
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.login,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
'Login',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
backgroundColor: Colors.black,
|
||||
fixedColor: Colors.black,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ packages:
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: fixnum
|
||||
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
|
||||
@ -196,7 +196,7 @@ packages:
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
path:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||
@ -232,6 +232,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
sqflite:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sqflite
|
||||
sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
sqflite_common:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -256,6 +272,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: synchronized
|
||||
sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -298,3 +322,4 @@ packages:
|
||||
version: "0.1.4-beta"
|
||||
sdks:
|
||||
dart: ">=3.1.4 <4.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
|
@ -39,6 +39,9 @@ dependencies:
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.2
|
||||
grpc: ^3.2.4
|
||||
sqflite: ^2.3.0
|
||||
path: ^1.8.3
|
||||
fixnum: ^1.1.0
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^2.0.0
|
||||
|
Loading…
x
Reference in New Issue
Block a user