ft/adds backend service
TODO: everything new
This commit is contained in:
parent
06d3b4bc19
commit
5f0e46a1b8
@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:app/pb/session.pbjson.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
|
|
||||||
import 'package:app/pb/google/protobuf/timestamp.pb.dart';
|
import 'package:app/pb/google/protobuf/timestamp.pb.dart';
|
||||||
@ -40,6 +41,12 @@ class Session {
|
|||||||
);
|
);
|
||||||
Session s = Session();
|
Session s = Session();
|
||||||
s._database = db;
|
s._database = db;
|
||||||
|
final sessions = await s.getSessions();
|
||||||
|
if (sessions.isNotEmpty) {
|
||||||
|
final session = sessions[0];
|
||||||
|
session._database = db;
|
||||||
|
return session;
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +97,41 @@ class Session {
|
|||||||
return 'Session{accountId: $accountId, sessionId: $sessionId, accessToken: $accessToken, accessTokenExpiresAt: ${accessTokenExpiresAt.toString()}, refreshToken: $refreshToken, refreshTokenExpiresAt: ${refreshTokenExpiresAt.toString()}}';
|
return 'Session{accountId: $accountId, sessionId: $sessionId, accessToken: $accessToken, accessTokenExpiresAt: ${accessTokenExpiresAt.toString()}, refreshToken: $refreshToken, refreshTokenExpiresAt: ${refreshTokenExpiresAt.toString()}}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static newSession(Session session) async {
|
||||||
|
final 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,
|
||||||
|
);
|
||||||
|
|
||||||
|
await db.insert(
|
||||||
|
'sessions',
|
||||||
|
session.toMap(),
|
||||||
|
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<Session> updateToken(Session s) async {
|
||||||
|
final 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,
|
||||||
|
);
|
||||||
|
await db.update(
|
||||||
|
'sessions',
|
||||||
|
s.toMap(),
|
||||||
|
);
|
||||||
|
return s; //await getSession(s.accountId!);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> insertSession(Session session) async {
|
Future<void> insertSession(Session session) async {
|
||||||
// print('INSERTING SESSION: ${session.sessionId}');
|
// print('INSERTING SESSION: ${session.sessionId}');
|
||||||
final db = _database;
|
final db = _database;
|
||||||
@ -101,6 +143,17 @@ class Session {
|
|||||||
// print('INSERT RESULT: $result');
|
// print('INSERT RESULT: $result');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Session> updateSession(Session session) async {
|
||||||
|
sessionId = session.sessionId;
|
||||||
|
accessToken = session.accessToken;
|
||||||
|
accessTokenExpiresAt = session.accessTokenExpiresAt;
|
||||||
|
refreshToken = session.refreshToken;
|
||||||
|
refreshTokenExpiresAt = session.refreshTokenExpiresAt;
|
||||||
|
final db = _database;
|
||||||
|
await db.update('sessions', session.toMap());
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> removeSession(String sessionId) async {
|
Future<void> removeSession(String sessionId) async {
|
||||||
final db = _database;
|
final db = _database;
|
||||||
await db.delete('sessions', where: 'sessionId = ?', whereArgs: [sessionId]);
|
await db.delete('sessions', where: 'sessionId = ?', whereArgs: [sessionId]);
|
||||||
|
@ -45,8 +45,8 @@ void main() async {
|
|||||||
)),
|
)),
|
||||||
home: Background(
|
home: Background(
|
||||||
child: StartPage(
|
child: StartPage(
|
||||||
client: await GClient.client,
|
// client: await GClient.client,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
17
frontend/app/lib/model/apis/api_response.dart
Normal file
17
frontend/app/lib/model/apis/api_response.dart
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
class ApiResponse<T> {
|
||||||
|
Status status;
|
||||||
|
T? data;
|
||||||
|
String? message;
|
||||||
|
|
||||||
|
ApiResponse.initial(this.message) : status = Status.INITIAL;
|
||||||
|
ApiResponse.loading(this.message) : status = Status.LOADING;
|
||||||
|
ApiResponse.completed(this.data, this.message) : status = Status.COMPLETED;
|
||||||
|
ApiResponse.error(this.message) : status = Status.ERROR;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return "Status : $status \n Message: $message \n Data : $data";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Status { INITIAL, LOADING, COMPLETED, ERROR }
|
32
frontend/app/lib/model/apis/app_exception.dart
Normal file
32
frontend/app/lib/model/apis/app_exception.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
class AppException implements Exception {
|
||||||
|
final _message;
|
||||||
|
final _prefix;
|
||||||
|
|
||||||
|
AppException([this._message, this._prefix]);
|
||||||
|
|
||||||
|
String toString() {
|
||||||
|
return "$_prefix$_message";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FetchDataException extends AppException {
|
||||||
|
FetchDataException([String? message])
|
||||||
|
: super(message, 'Fehler bei der Kommunikation: ');
|
||||||
|
}
|
||||||
|
|
||||||
|
class BadRequestException extends AppException {
|
||||||
|
BadRequestException([message]) : super(message, 'Ungültige Anfrage; ');
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnauthorizedException extends AppException {
|
||||||
|
UnauthorizedException([message])
|
||||||
|
: super(message, 'Nicht authorisierte Anfrage; ');
|
||||||
|
}
|
||||||
|
|
||||||
|
class InvalidInputException extends AppException {
|
||||||
|
InvalidInputException([message]) : super(message, 'Ungültige Eingabe; ');
|
||||||
|
}
|
||||||
|
|
||||||
|
class InternalException extends AppException {
|
||||||
|
InternalException([message]) : super(message, 'Interner Fehler; ');
|
||||||
|
}
|
237
frontend/app/lib/model/services/backend_service.dart
Normal file
237
frontend/app/lib/model/services/backend_service.dart
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:app/model/apis/app_exception.dart';
|
||||||
|
import 'package:app/pb/account.pb.dart';
|
||||||
|
import 'package:app/pb/account_info.pb.dart';
|
||||||
|
import 'package:app/pb/person.pb.dart';
|
||||||
|
import 'package:app/data/database.dart';
|
||||||
|
import 'package:app/pb/rpc_get_account.pb.dart';
|
||||||
|
import 'package:app/pb/rpc_get_account_info.pb.dart';
|
||||||
|
import 'package:app/pb/rpc_get_person.pb.dart';
|
||||||
|
import 'package:app/pb/rpc_login.pb.dart';
|
||||||
|
import 'package:app/pb/rpc_refresh_token.pb.dart';
|
||||||
|
import 'package:app/pb/service_df.pbgrpc.dart';
|
||||||
|
import 'package:fixnum/fixnum.dart';
|
||||||
|
import 'package:grpc/grpc.dart';
|
||||||
|
import 'package:sqflite/sqflite.dart';
|
||||||
|
|
||||||
|
class BackendService {
|
||||||
|
BackendService() {
|
||||||
|
_init();
|
||||||
|
}
|
||||||
|
final String baseUrl = '10.0.0.2';
|
||||||
|
final String port = '9090';
|
||||||
|
|
||||||
|
late Session _session;
|
||||||
|
|
||||||
|
final dfClient _client = dfClient(
|
||||||
|
ClientChannel('10.0.2.2',
|
||||||
|
port: 9090,
|
||||||
|
options: const ChannelOptions(
|
||||||
|
credentials: ChannelCredentials.insecure(),
|
||||||
|
)),
|
||||||
|
options: CallOptions(
|
||||||
|
timeout: const Duration(seconds: 5),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
static get client => dfClient(
|
||||||
|
ClientChannel('10.0.2.2',
|
||||||
|
port: 9090,
|
||||||
|
options: const ChannelOptions(
|
||||||
|
credentials: ChannelCredentials.insecure(),
|
||||||
|
)),
|
||||||
|
options: CallOptions(
|
||||||
|
timeout: const Duration(seconds: 5),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
void _init() {
|
||||||
|
Session.session.then((value) => _session = value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Session?> _isLoggedIn() async {
|
||||||
|
Session session = await Session.session;
|
||||||
|
if (session.accessToken == null ||
|
||||||
|
session.refreshToken == null ||
|
||||||
|
session.accountId == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.accessTokenExpiresAt == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.refreshTokenExpiresAt == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.refreshTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
if (session.refreshToken != null &&
|
||||||
|
session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
|
||||||
|
session = await refreshToken(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<bool> get isLoggedIn async {
|
||||||
|
Session session = await Session.session;
|
||||||
|
if (session.accessToken == null ||
|
||||||
|
session.refreshToken == null ||
|
||||||
|
session.accountId == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.accessTokenExpiresAt == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.refreshTokenExpiresAt == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.refreshTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Account> getAccount() async {
|
||||||
|
Session? session = await _isLoggedIn();
|
||||||
|
if (session == null) {
|
||||||
|
throw UnauthorizedException('Sitzung ist abgelaufen');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final GetAccountResponse response = await _client.getAccount(
|
||||||
|
GetAccountRequest(id: session!.accountId),
|
||||||
|
options: CallOptions(
|
||||||
|
metadata: {'Authorization': 'Bearer ${session.accessToken}'}));
|
||||||
|
return response.account;
|
||||||
|
} on SocketException {
|
||||||
|
throw FetchDataException('Keine Internet Verbindung');
|
||||||
|
} on GrpcError catch (err) {
|
||||||
|
// if (err.code == 16) {
|
||||||
|
// await refreshToken(session);
|
||||||
|
// return getAccount();
|
||||||
|
// }
|
||||||
|
throw FetchDataException(err.message);
|
||||||
|
} catch (err) {
|
||||||
|
throw InternalException(err.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<AccountInfo> getAccountInfo() async {
|
||||||
|
Session session = await Session.session;
|
||||||
|
if (session.accessTokenExpiresAt == null) {
|
||||||
|
throw UnauthorizedException('Keine Siztung gefunden');
|
||||||
|
}
|
||||||
|
if (session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
|
||||||
|
session = await refreshToken(session);
|
||||||
|
if (session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
|
||||||
|
throw UnauthorizedException('Sitzung ist abgelaufen');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final GetAccountInfoResponse response = await _client
|
||||||
|
.getAccountInfo(GetAccountInfoRequest(accountId: _session.accountId));
|
||||||
|
return response.accountInfo;
|
||||||
|
} on SocketException {
|
||||||
|
throw FetchDataException('Keine Internet Verbindung');
|
||||||
|
} on GrpcError catch (err) {
|
||||||
|
if (err.code == 16) {
|
||||||
|
await refreshToken(session);
|
||||||
|
return getAccountInfo();
|
||||||
|
}
|
||||||
|
throw FetchDataException(err.message);
|
||||||
|
} catch (err) {
|
||||||
|
throw InternalException(err.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Person> getPerson(Int64 personId) async {
|
||||||
|
Session session = await Session.session;
|
||||||
|
if (session.accessTokenExpiresAt == null) {
|
||||||
|
throw UnauthorizedException('Keine Siztung gefunden');
|
||||||
|
}
|
||||||
|
if (session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
|
||||||
|
session = await refreshToken(session);
|
||||||
|
if (session.accessTokenExpiresAt == null) {
|
||||||
|
throw UnauthorizedException('Sitzung ist abgelaufen');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final GetPersonResponse response =
|
||||||
|
await _client.getPerson(GetPersonRequest(id: personId));
|
||||||
|
return response.person;
|
||||||
|
} on SocketException {
|
||||||
|
throw FetchDataException('Keine Internet Verbindung');
|
||||||
|
} on GrpcError catch (err) {
|
||||||
|
throw FetchDataException(err.message);
|
||||||
|
} catch (err) {
|
||||||
|
throw InternalException(err.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Future<List<Person>> listPersons() async {
|
||||||
|
// if (_session.accessToken == null) {
|
||||||
|
// refreshToken();
|
||||||
|
// }
|
||||||
|
// try {
|
||||||
|
// ListPersonsResponse response =
|
||||||
|
// await _client.listPersons(ListPersonsRequest(accountId: _session.accountId));
|
||||||
|
// return response.persons;
|
||||||
|
// } on SocketException {
|
||||||
|
// throw FetchDataException('Keine Internet Verbindung');
|
||||||
|
// } on GrpcError catch (err) {
|
||||||
|
// throw FetchDataException(err.message);
|
||||||
|
// } catch (err) {
|
||||||
|
// throw InternalException(err.toString());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
static Future<bool> login(
|
||||||
|
{required String email, required String password}) async {
|
||||||
|
try {
|
||||||
|
final LoginResponse response = await BackendService.client.login(
|
||||||
|
LoginRequest(
|
||||||
|
email: email,
|
||||||
|
password: password,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await Session.newSession(response as Session);
|
||||||
|
return response.accessToken != '';
|
||||||
|
} on SocketException {
|
||||||
|
throw FetchDataException('Keine Internet Verbindung');
|
||||||
|
} on GrpcError catch (err) {
|
||||||
|
throw FetchDataException(err.message);
|
||||||
|
} catch (err) {
|
||||||
|
throw InternalException(err.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Session> refreshToken(Session session) async {
|
||||||
|
try {
|
||||||
|
final RefreshTokenResponse response = await _client.refreshToken(
|
||||||
|
RefreshTokenRequest(refreshToken: session.refreshToken));
|
||||||
|
session.accessToken = response.accessToken;
|
||||||
|
session.accessTokenExpiresAt = response.accessTokenExpiresAt;
|
||||||
|
session = await Session.updateToken(session);
|
||||||
|
return session;
|
||||||
|
} on SocketException {
|
||||||
|
throw FetchDataException('Keine Internet Verbindung');
|
||||||
|
} on GrpcError catch (err) {
|
||||||
|
throw FetchDataException(err.message);
|
||||||
|
} catch (err) {
|
||||||
|
throw InternalException(err.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> logout() async {
|
||||||
|
Session session = await Session.session;
|
||||||
|
session.reset();
|
||||||
|
}
|
||||||
|
}
|
56
frontend/app/lib/model/view_model/account_vm.dart
Normal file
56
frontend/app/lib/model/view_model/account_vm.dart
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import 'package:app/model/apis/api_response.dart';
|
||||||
|
import 'package:app/model/services/backend_service.dart';
|
||||||
|
import 'package:app/pb/account.pb.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AccountViewModel with ChangeNotifier {
|
||||||
|
AccountViewModel() {
|
||||||
|
_init();
|
||||||
|
}
|
||||||
|
ApiResponse _apiResponse = ApiResponse.initial('Keine Daten');
|
||||||
|
|
||||||
|
final BackendService _service = BackendService();
|
||||||
|
Account? _account;
|
||||||
|
|
||||||
|
ApiResponse get response {
|
||||||
|
return _apiResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
Account? get account {
|
||||||
|
return _account;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _init() async {
|
||||||
|
_apiResponse = ApiResponse.loading('Bereite alles vor');
|
||||||
|
try {
|
||||||
|
_apiResponse = ApiResponse.completed(await _service.getAccount(), 'done');
|
||||||
|
} catch (e) {
|
||||||
|
_apiResponse = ApiResponse.error(e.toString());
|
||||||
|
}
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> fetchAccount() async {
|
||||||
|
_apiResponse = ApiResponse.loading('Hole Account');
|
||||||
|
notifyListeners();
|
||||||
|
try {
|
||||||
|
_apiResponse = ApiResponse.completed(await _service.getAccount(), 'done');
|
||||||
|
} catch (e) {
|
||||||
|
_apiResponse = ApiResponse.error(e.toString());
|
||||||
|
}
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> logout() async {
|
||||||
|
_apiResponse = ApiResponse.loading('Logge aus');
|
||||||
|
notifyListeners();
|
||||||
|
try {
|
||||||
|
await BackendService.logout();
|
||||||
|
_apiResponse = ApiResponse.completed(null, 'Erfolgreich ausgeloggt');
|
||||||
|
} catch (e) {
|
||||||
|
_apiResponse = ApiResponse.error(e.toString());
|
||||||
|
}
|
||||||
|
print(_apiResponse.message);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
@ -11,10 +11,10 @@ import 'package:flutter/material.dart';
|
|||||||
class DashboardPage extends StatefulWidget {
|
class DashboardPage extends StatefulWidget {
|
||||||
const DashboardPage({
|
const DashboardPage({
|
||||||
super.key,
|
super.key,
|
||||||
required this.client,
|
// required this.client,
|
||||||
});
|
});
|
||||||
|
|
||||||
final GClient client;
|
// final GClient client;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<DashboardPage> createState() => _DashboardPageState();
|
State<DashboardPage> createState() => _DashboardPageState();
|
||||||
@ -35,44 +35,44 @@ class _DashboardPageState extends State<DashboardPage> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
_setLoading(true);
|
_setLoading(true);
|
||||||
widget.client.getAccountInfo(
|
// widget.client.getAccountInfo(
|
||||||
GetAccountInfoRequest(
|
// GetAccountInfoRequest(
|
||||||
accountId: widget.client.session.accountId,
|
// accountId: widget.client.session.accountId,
|
||||||
),
|
// ),
|
||||||
onError: ({String? msg}) {
|
// onError: ({String? msg}) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
// ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
// SnackBar(
|
||||||
content: const Text('AccountInfo konnte nicht geladen werden'),
|
// content: const Text('AccountInfo konnte nicht geladen werden'),
|
||||||
action: msg != null
|
// action: msg != null
|
||||||
? SnackBarAction(
|
// ? SnackBarAction(
|
||||||
label: 'Details',
|
// label: 'Details',
|
||||||
textColor: Colors.grey,
|
// textColor: Colors.grey,
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
showDialog(
|
// showDialog(
|
||||||
context: context,
|
// context: context,
|
||||||
builder: (context) {
|
// builder: (context) {
|
||||||
return AlertDialog(
|
// return AlertDialog(
|
||||||
content: Text(
|
// content: Text(
|
||||||
msg,
|
// msg,
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: const TextStyle(color: Colors.black),
|
// style: const TextStyle(color: Colors.black),
|
||||||
),
|
// ),
|
||||||
icon: const Icon(
|
// icon: const Icon(
|
||||||
Icons.warning,
|
// Icons.warning,
|
||||||
color: Colors.red,
|
// color: Colors.red,
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
})
|
// })
|
||||||
: null,
|
// : null,
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
).then((value) {
|
// ).then((value) {
|
||||||
accountInfo = value.accountInfo;
|
// accountInfo = value.accountInfo;
|
||||||
_setLoading(false);
|
// _setLoading(false);
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -144,139 +144,139 @@ class _DashboardPageState extends State<DashboardPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.client.session.accessToken != null)
|
// if (widget.client.session.accessToken != null)
|
||||||
TextButton(
|
// TextButton(
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
widget.client.session.accessToken = null;
|
// widget.client.session.accessToken = null;
|
||||||
widget.client.session
|
// widget.client.session
|
||||||
.removeSession(widget.client.session.sessionId!);
|
// .removeSession(widget.client.session.sessionId!);
|
||||||
|
|
||||||
Navigator.of(context).pushAndRemoveUntil(
|
// Navigator.of(context).pushAndRemoveUntil(
|
||||||
MaterialPageRoute(
|
// MaterialPageRoute(
|
||||||
builder: (context) =>
|
// builder: (context) =>
|
||||||
StartPage(client: widget.client),
|
// StartPage(client: widget.client),
|
||||||
),
|
// ),
|
||||||
(route) => false);
|
// (route) => false);
|
||||||
},
|
// },
|
||||||
child: const Row(
|
// child: const Row(
|
||||||
children: [
|
// children: [
|
||||||
Text(
|
// Text(
|
||||||
'Log out',
|
// 'Log out',
|
||||||
style: TextStyle(fontSize: 20),
|
// style: TextStyle(fontSize: 20),
|
||||||
),
|
// ),
|
||||||
Spacer(),
|
// Spacer(),
|
||||||
Icon(
|
// Icon(
|
||||||
Icons.logout,
|
// Icons.logout,
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 250,
|
height: 250,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
bottomNavigationBar: Builder(
|
// bottomNavigationBar: Builder(
|
||||||
builder: (context) {
|
// builder: (context) {
|
||||||
return BottomBar(
|
// return BottomBar(
|
||||||
children: widget.client.session.accessToken != null
|
// children: widget.client.session.accessToken != null
|
||||||
? [
|
// ? [
|
||||||
BottomNavigationBarItem(
|
// BottomNavigationBarItem(
|
||||||
backgroundColor: Colors.white,
|
// backgroundColor: Colors.white,
|
||||||
label: 'Personen',
|
// label: 'Personen',
|
||||||
icon: Column(
|
// icon: Column(
|
||||||
children: [
|
// children: [
|
||||||
IconButton(
|
// IconButton(
|
||||||
onPressed: () =>
|
// onPressed: () =>
|
||||||
Scaffold.of(context).openDrawer(),
|
// Scaffold.of(context).openDrawer(),
|
||||||
icon: const Icon(
|
// icon: const Icon(
|
||||||
Icons.group,
|
// Icons.group,
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const Text(
|
// const Text(
|
||||||
'Personen',
|
// 'Personen',
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
),
|
// ),
|
||||||
)
|
// )
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
BottomNavigationBarItem(
|
// BottomNavigationBarItem(
|
||||||
backgroundColor: Colors.white,
|
// backgroundColor: Colors.white,
|
||||||
label: 'Home',
|
// label: 'Home',
|
||||||
icon: Column(
|
// icon: Column(
|
||||||
children: [
|
// children: [
|
||||||
IconButton(
|
// IconButton(
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
Navigator.of(context).push(
|
// Navigator.of(context).push(
|
||||||
MaterialPageRoute(
|
// MaterialPageRoute(
|
||||||
builder: (context) => StartPage(
|
// builder: (context) => StartPage(
|
||||||
client: widget.client,
|
// client: widget.client,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
icon: const Icon(
|
// icon: const Icon(
|
||||||
Icons.home,
|
// Icons.home,
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const Text(
|
// const Text(
|
||||||
'Home',
|
// 'Home',
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
),
|
// ),
|
||||||
)
|
// )
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
BottomNavigationBarItem(
|
// BottomNavigationBarItem(
|
||||||
backgroundColor: Colors.white,
|
// backgroundColor: Colors.white,
|
||||||
label: 'Menu',
|
// label: 'Menu',
|
||||||
icon: IconButton(
|
// icon: IconButton(
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
Scaffold.of(context).openDrawer();
|
// Scaffold.of(context).openDrawer();
|
||||||
},
|
// },
|
||||||
icon: const Icon(
|
// icon: const Icon(
|
||||||
Icons.menu,
|
// Icons.menu,
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
)
|
// )
|
||||||
]
|
// ]
|
||||||
: [
|
// : [
|
||||||
BottomNavigationBarItem(
|
// BottomNavigationBarItem(
|
||||||
label: 'back',
|
// label: 'back',
|
||||||
backgroundColor: Colors.white,
|
// backgroundColor: Colors.white,
|
||||||
icon: IconButton(
|
// icon: IconButton(
|
||||||
onPressed: () {},
|
// onPressed: () {},
|
||||||
icon: const Icon(
|
// icon: const Icon(
|
||||||
Icons.arrow_back,
|
// Icons.arrow_back,
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
BottomNavigationBarItem(
|
// BottomNavigationBarItem(
|
||||||
backgroundColor: Colors.white,
|
// backgroundColor: Colors.white,
|
||||||
label: 'Menu',
|
// label: 'Menu',
|
||||||
icon: IconButton(
|
// icon: IconButton(
|
||||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
// onPressed: () => Scaffold.of(context).openDrawer(),
|
||||||
icon: const Icon(
|
// icon: const Icon(
|
||||||
Icons.menu,
|
// Icons.menu,
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
body: !_loading
|
body: !_loading
|
||||||
? Background(
|
? Background(
|
||||||
child: Center(
|
child: Center(
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:app/gapi/client.dart';
|
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/start_page.dart';
|
||||||
import 'package:app/widgets/background.dart';
|
import 'package:app/widgets/background.dart';
|
||||||
import 'package:app/widgets/bottom_bar.dart';
|
import 'package:app/widgets/bottom_bar.dart';
|
||||||
@ -12,11 +13,11 @@ import 'package:grpc/grpc.dart';
|
|||||||
class LoginPage extends StatefulWidget {
|
class LoginPage extends StatefulWidget {
|
||||||
const LoginPage({
|
const LoginPage({
|
||||||
super.key,
|
super.key,
|
||||||
required this.client,
|
// required this.client,
|
||||||
// required this.onChangePage,
|
// required this.onChangePage,
|
||||||
});
|
});
|
||||||
|
|
||||||
final GClient client;
|
// final GClient client;
|
||||||
// void Function(Pages page) onChangePage;
|
// void Function(Pages page) onChangePage;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -87,7 +88,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
label: 'back',
|
label: 'back',
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
icon: IconButton(
|
icon: IconButton(
|
||||||
onPressed: () => Navigator.of(context).pop(widget.client),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.arrow_back,
|
Icons.arrow_back,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@ -250,73 +251,23 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState!.validate()) {
|
||||||
// final navigator = Navigator.of(context);
|
// final navigator = Navigator.of(context);
|
||||||
_setLoading(true);
|
_setLoading(true);
|
||||||
widget.client
|
BackendService.login(
|
||||||
.login(
|
|
||||||
email: mailController.text,
|
email: mailController.text,
|
||||||
password: passwordController.text,
|
password: passwordController.text,
|
||||||
onError: ({GrpcError? error}) {
|
).then(
|
||||||
_setLoading(false);
|
|
||||||
ScaffoldMessenger.of(context)
|
|
||||||
.showSnackBar(SnackBar(
|
|
||||||
content: const Text(
|
|
||||||
'Login fehlgeschlagen',
|
|
||||||
),
|
|
||||||
action: SnackBarAction(
|
|
||||||
textColor: Colors.grey,
|
|
||||||
label: 'Details',
|
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
content: error != null
|
|
||||||
? Text(
|
|
||||||
'Fehler: ${error.message}',
|
|
||||||
textAlign:
|
|
||||||
TextAlign.center,
|
|
||||||
style:
|
|
||||||
const TextStyle(
|
|
||||||
color: Colors
|
|
||||||
.black),
|
|
||||||
)
|
|
||||||
: const Text(
|
|
||||||
'Interner Fehler',
|
|
||||||
textAlign:
|
|
||||||
TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
color:
|
|
||||||
Colors.black),
|
|
||||||
),
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.error,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
},
|
|
||||||
onSuccess: () {
|
|
||||||
// _setLoading(false);
|
|
||||||
ScaffoldMessenger.of(context)
|
|
||||||
.showSnackBar(const SnackBar(
|
|
||||||
content: Text('Login erfolgreich'),
|
|
||||||
));
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.then(
|
|
||||||
(r) {
|
(r) {
|
||||||
if (r.accessToken != '') {
|
if (r) {
|
||||||
Navigator.pushAndRemoveUntil(
|
Navigator.pop(context);
|
||||||
context,
|
Navigator.pop(context);
|
||||||
MaterialPageRoute(
|
// Navigator.pushAndRemoveUntil(
|
||||||
builder: (ctx) => StartPage(
|
// context,
|
||||||
client: widget.client,
|
// MaterialPageRoute(
|
||||||
),
|
// builder: (ctx) => const StartPage(
|
||||||
),
|
// // client: widget.client,
|
||||||
(ctx) => false,
|
// ),
|
||||||
);
|
// ),
|
||||||
|
// (ctx) => false,
|
||||||
|
// );
|
||||||
// widget.onChangePage(
|
// widget.onChangePage(
|
||||||
// Pages.dashboard,
|
// Pages.dashboard,
|
||||||
// );
|
// );
|
||||||
|
@ -10,10 +10,10 @@ import 'package:grpc/grpc.dart';
|
|||||||
class RegisterPage extends StatefulWidget {
|
class RegisterPage extends StatefulWidget {
|
||||||
const RegisterPage({
|
const RegisterPage({
|
||||||
super.key,
|
super.key,
|
||||||
required this.client,
|
// required this.client,
|
||||||
});
|
});
|
||||||
|
|
||||||
final GClient client;
|
// final GClient client;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<RegisterPage> createState() => _RegisterPageState();
|
State<RegisterPage> createState() => _RegisterPageState();
|
||||||
@ -112,7 +112,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
|||||||
label: 'back',
|
label: 'back',
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
icon: IconButton(
|
icon: IconButton(
|
||||||
onPressed: () => Navigator.of(context).pop(widget.client),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.arrow_back,
|
Icons.arrow_back,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@ -209,143 +209,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
|||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState!.validate()) {
|
||||||
_setLoading(true);
|
// _setLoading(true);
|
||||||
widget.client
|
|
||||||
.createAccount(
|
|
||||||
email: mailController.text,
|
|
||||||
password: passwordController.text,
|
|
||||||
onError: ({GrpcError? error}) {
|
|
||||||
_setLoading(false);
|
|
||||||
ScaffoldMessenger.of(context)
|
|
||||||
.showSnackBar(SnackBar(
|
|
||||||
content: const Text(
|
|
||||||
'Login fehlgeschlagen',
|
|
||||||
),
|
|
||||||
action: SnackBarAction(
|
|
||||||
textColor: Colors.grey,
|
|
||||||
label: 'Details',
|
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
content: error != null
|
|
||||||
? Text(
|
|
||||||
'Fehler: ${error.message}',
|
|
||||||
textAlign:
|
|
||||||
TextAlign
|
|
||||||
.center,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors
|
|
||||||
.black),
|
|
||||||
)
|
|
||||||
: const Text(
|
|
||||||
'Interner Fehler',
|
|
||||||
textAlign:
|
|
||||||
TextAlign
|
|
||||||
.center,
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors
|
|
||||||
.black),
|
|
||||||
),
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.error,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
})
|
|
||||||
.then(
|
|
||||||
(r) {
|
|
||||||
if (r.account.secretKey != '') {
|
|
||||||
widget.client
|
|
||||||
.login(
|
|
||||||
email: mailController.text,
|
|
||||||
password:
|
|
||||||
passwordController.text,
|
|
||||||
onError: (
|
|
||||||
{GrpcError? error}) {},
|
|
||||||
onSuccess: () {})
|
|
||||||
.then((resp) {
|
|
||||||
widget.client.getAccount(
|
|
||||||
accountId: r.account.id,
|
|
||||||
onError: ({GrpcError? err}) {
|
|
||||||
_setLoading(false);
|
|
||||||
ScaffoldMessenger.of(context)
|
|
||||||
.showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: const Text(
|
|
||||||
'Login fehlgeschlagen',
|
|
||||||
),
|
|
||||||
action: SnackBarAction(
|
|
||||||
textColor: Colors.grey,
|
|
||||||
label: 'Details',
|
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
content: err !=
|
|
||||||
null
|
|
||||||
? Text(
|
|
||||||
'Hoppla! Da ist etwas schief gelaufen..\n\n${err.message}',
|
|
||||||
textAlign:
|
|
||||||
TextAlign.center,
|
|
||||||
style: const TextStyle(
|
|
||||||
color:
|
|
||||||
Colors.black),
|
|
||||||
)
|
|
||||||
: const Text(
|
|
||||||
'Interner Fehler',
|
|
||||||
textAlign:
|
|
||||||
TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
color:
|
|
||||||
Colors.black),
|
|
||||||
),
|
|
||||||
icon:
|
|
||||||
const Icon(
|
|
||||||
Icons.error,
|
|
||||||
color: Colors
|
|
||||||
.black,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Navigator.pushAndRemoveUntil(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (builder) => StartPage(
|
|
||||||
client: widget.client)),
|
|
||||||
(route) => false);
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (builder) {
|
|
||||||
return const AlertDialog(
|
|
||||||
content: Text(
|
|
||||||
'Account wurde angelegt',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.black),
|
|
||||||
),
|
|
||||||
icon: Icon(
|
|
||||||
Icons.done,
|
|
||||||
size: 50,
|
|
||||||
),
|
|
||||||
iconColor: Colors.green,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: const Icon(Icons.login))
|
child: const Icon(Icons.login))
|
||||||
|
@ -1,21 +1,26 @@
|
|||||||
import 'package:app/gapi/client.dart';
|
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/dashboard_page.dart';
|
||||||
import 'package:app/pages/login_page.dart';
|
import 'package:app/pages/login_page.dart';
|
||||||
import 'package:app/pages/register_page.dart';
|
import 'package:app/pages/register_page.dart';
|
||||||
|
import 'package:app/pb/account.pb.dart';
|
||||||
import 'package:app/widgets/background.dart';
|
import 'package:app/widgets/background.dart';
|
||||||
import 'package:app/widgets/bottom_bar.dart';
|
import 'package:app/widgets/bottom_bar.dart';
|
||||||
import 'package:app/widgets/side_drawer.dart';
|
import 'package:app/widgets/side_drawer.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'dart:core';
|
import 'dart:core';
|
||||||
|
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class StartPage extends StatefulWidget {
|
class StartPage extends StatefulWidget {
|
||||||
StartPage({
|
const StartPage({
|
||||||
super.key,
|
super.key,
|
||||||
required this.client,
|
// required this.client,
|
||||||
});
|
});
|
||||||
|
|
||||||
GClient client;
|
// GClient client;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StartPage> createState() => _StartPageState();
|
State<StartPage> createState() => _StartPageState();
|
||||||
@ -24,320 +29,344 @@ class StartPage extends StatefulWidget {
|
|||||||
class _StartPageState extends State<StartPage> {
|
class _StartPageState extends State<StartPage> {
|
||||||
final List<BottomNavigationBarItem> bottombarButtons = [];
|
final List<BottomNavigationBarItem> bottombarButtons = [];
|
||||||
|
|
||||||
void _updateClient(GClient c) {
|
// void _updateClient(GClient c) {
|
||||||
setState(() {
|
// setState(() {
|
||||||
widget.client = c;
|
// widget.client = c;
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SnackBar _snackBar(BuildContext context, String message, String label,
|
||||||
|
void Function() action) {
|
||||||
|
ScaffoldMessenger.of(context).removeCurrentSnackBar();
|
||||||
|
// ScaffoldMessenger.of(context).clearSnackBars();
|
||||||
|
return SnackBar(
|
||||||
|
content: Text(
|
||||||
|
message,
|
||||||
|
style: const TextStyle(color: Colors.black),
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
action: SnackBarAction(
|
||||||
|
label: label,
|
||||||
|
onPressed: action,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Background(
|
return Background(
|
||||||
child: Scaffold(
|
child: ChangeNotifierProvider<AccountViewModel>(
|
||||||
appBar: AppBar(
|
create: (context) => AccountViewModel(),
|
||||||
automaticallyImplyLeading: false,
|
child: Consumer<AccountViewModel>(builder: (context, value, child) {
|
||||||
),
|
return Scaffold(
|
||||||
drawer: Builder(builder: (context) {
|
appBar: AppBar(
|
||||||
return SideDrawer(children: [
|
automaticallyImplyLeading: false,
|
||||||
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(
|
drawer: Builder(builder: (context) {
|
||||||
onPressed: () {
|
return SideDrawer(children: [
|
||||||
Scaffold.of(context).closeDrawer();
|
const Spacer(),
|
||||||
},
|
TextButton(
|
||||||
child: const Row(
|
onPressed: () {
|
||||||
children: [
|
Scaffold.of(context).closeDrawer();
|
||||||
Text(
|
},
|
||||||
'Datenschutz',
|
child: const Row(
|
||||||
style: TextStyle(fontSize: 20),
|
children: [
|
||||||
|
Text(
|
||||||
|
'About',
|
||||||
|
style: TextStyle(fontSize: 20),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
Icon(
|
||||||
|
Icons.question_answer,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Spacer(),
|
),
|
||||||
Icon(
|
TextButton(
|
||||||
Icons.privacy_tip,
|
onPressed: () {
|
||||||
color: Colors.white,
|
Scaffold.of(context).closeDrawer();
|
||||||
|
},
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Datenschutz',
|
||||||
|
style: TextStyle(fontSize: 20),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
Icon(
|
||||||
|
Icons.privacy_tip,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
TextButton(
|
||||||
),
|
onPressed: () {
|
||||||
TextButton(
|
Scaffold.of(context).closeDrawer();
|
||||||
onPressed: () {
|
},
|
||||||
Scaffold.of(context).closeDrawer();
|
child: const Row(
|
||||||
},
|
children: [
|
||||||
child: const Row(
|
Text(
|
||||||
children: [
|
'Impressum',
|
||||||
Text(
|
style: TextStyle(fontSize: 20),
|
||||||
'Impressum',
|
),
|
||||||
style: TextStyle(fontSize: 20),
|
Spacer(),
|
||||||
|
Icon(
|
||||||
|
Icons.apartment,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Spacer(),
|
),
|
||||||
Icon(
|
TextButton(
|
||||||
Icons.apartment,
|
onPressed: () {
|
||||||
color: Colors.white,
|
value.logout();
|
||||||
|
// ScaffoldMessenger.of(context).clearSnackBars();
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
_snackBar(
|
||||||
|
context,
|
||||||
|
value.response.message != null
|
||||||
|
? value.response.message!
|
||||||
|
: value.response.status.toString(),
|
||||||
|
value.response.status.toString(),
|
||||||
|
() {
|
||||||
|
print('asdf');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Log out',
|
||||||
|
style: TextStyle(fontSize: 20),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
Icon(
|
||||||
|
Icons.logout,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
const SizedBox(
|
||||||
),
|
height: 250,
|
||||||
TextButton(
|
)
|
||||||
onPressed: () {
|
]);
|
||||||
setState(() {
|
}),
|
||||||
widget.client.session.accessToken = null;
|
bottomNavigationBar: Builder(builder: (context) {
|
||||||
widget.client.session
|
return BottomBar(
|
||||||
.removeSession(widget.client.session.sessionId!);
|
// onTap: (value) => _bottomBarAction(value),
|
||||||
});
|
children: value.response.data != null
|
||||||
},
|
? [
|
||||||
child: const Row(
|
BottomNavigationBarItem(
|
||||||
children: [
|
backgroundColor: Colors.white,
|
||||||
Text(
|
label: 'Personen',
|
||||||
'Log out',
|
icon: Column(
|
||||||
style: TextStyle(fontSize: 20),
|
children: [
|
||||||
),
|
IconButton(
|
||||||
Spacer(),
|
onPressed: () =>
|
||||||
Icon(
|
Scaffold.of(context).openDrawer(),
|
||||||
Icons.logout,
|
icon: const Icon(
|
||||||
color: Colors.white,
|
Icons.group,
|
||||||
),
|
color: Colors.white,
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
const Text(
|
||||||
const SizedBox(
|
'Personen',
|
||||||
height: 250,
|
style: TextStyle(
|
||||||
)
|
color: Colors.white,
|
||||||
]);
|
fontSize: 16,
|
||||||
}),
|
),
|
||||||
bottomNavigationBar: Builder(builder: (context) {
|
)
|
||||||
return BottomBar(
|
],
|
||||||
// onTap: (value) => _bottomBarAction(value),
|
),
|
||||||
children: widget.client.session.accessToken != null
|
),
|
||||||
? [
|
BottomNavigationBarItem(
|
||||||
BottomNavigationBarItem(
|
backgroundColor: Colors.white,
|
||||||
backgroundColor: Colors.white,
|
label: 'Dashboard',
|
||||||
label: 'Personen',
|
icon: Column(
|
||||||
icon: Column(
|
children: [
|
||||||
children: [
|
IconButton(
|
||||||
IconButton(
|
onPressed: () {},
|
||||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
icon: const Icon(
|
||||||
|
Icons.dashboard,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
'Dashboard',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
label: 'Menu',
|
||||||
|
icon: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Scaffold.of(context).openDrawer();
|
||||||
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.group,
|
Icons.menu,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Text(
|
)
|
||||||
'Personen',
|
]
|
||||||
style: TextStyle(
|
: [
|
||||||
color: Colors.white,
|
BottomNavigationBarItem(
|
||||||
fontSize: 16,
|
label: 'register',
|
||||||
),
|
backgroundColor: Colors.white,
|
||||||
)
|
icon: Column(
|
||||||
],
|
children: [
|
||||||
),
|
IconButton(
|
||||||
),
|
onPressed: () {},
|
||||||
BottomNavigationBarItem(
|
icon: const Icon(
|
||||||
backgroundColor: Colors.white,
|
Icons.login,
|
||||||
label: 'Dashboard',
|
color: Colors.white,
|
||||||
icon: Column(
|
),
|
||||||
children: [
|
),
|
||||||
IconButton(
|
const Text(
|
||||||
onPressed: () async {
|
'Registrieren',
|
||||||
if (widget.client.session.accessTokenExpiresAt!
|
style: TextStyle(
|
||||||
.toDateTime()
|
color: Colors.white,
|
||||||
.isBefore(DateTime.now())) {
|
fontSize: 16,
|
||||||
await widget.client.refreshToken();
|
),
|
||||||
}
|
)
|
||||||
if (!widget.client.isLoggedIn &&
|
],
|
||||||
context.mounted) {
|
),
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
),
|
||||||
const SnackBar(
|
BottomNavigationBarItem(
|
||||||
content: Text('Sitzung ist abgelaufen.'),
|
label: 'login',
|
||||||
),
|
backgroundColor: Colors.white,
|
||||||
);
|
icon: Column(
|
||||||
if (context.mounted) {
|
children: [
|
||||||
Navigator.pushAndRemoveUntil(
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) =>
|
builder: (builder) =>
|
||||||
LoginPage(client: widget.client)),
|
const LoginPage()));
|
||||||
(route) => false);
|
},
|
||||||
}
|
icon: const Icon(
|
||||||
} else {
|
Icons.login,
|
||||||
final ctx = context;
|
color: Colors.white,
|
||||||
// ignore: use_build_context_synchronously
|
),
|
||||||
GClient c = await Navigator.push(
|
),
|
||||||
ctx,
|
const Text(
|
||||||
MaterialPageRoute(
|
'Login',
|
||||||
builder: (context) => DashboardPage(
|
style: TextStyle(
|
||||||
client: widget.client,
|
color: Colors.white,
|
||||||
),
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
);
|
)
|
||||||
_updateClient(c);
|
],
|
||||||
}
|
),
|
||||||
},
|
),
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
label: 'Menu',
|
||||||
|
icon: IconButton(
|
||||||
|
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.dashboard,
|
Icons.menu,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
if (value.response.status == Status.COMPLETED &&
|
||||||
|
value.response.data != null &&
|
||||||
|
!(value.response.data as Account).emailVerified)
|
||||||
|
Card(
|
||||||
|
color: Colors.orange,
|
||||||
|
child: Center(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
const Text(
|
const Text(
|
||||||
'Dashboard',
|
'E-Mail ist noch nicht verifiziert.',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontFamily: 'sans-serif',
|
||||||
|
fontSize: 14),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.restore,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 16,
|
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
),
|
||||||
backgroundColor: Colors.white,
|
Padding(
|
||||||
label: 'Menu',
|
padding: const EdgeInsets.all(16.0),
|
||||||
icon: IconButton(
|
child: Column(
|
||||||
onPressed: () {
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Scaffold.of(context).openDrawer();
|
children: [
|
||||||
},
|
const Image(
|
||||||
icon: const Icon(
|
image: AssetImage(
|
||||||
Icons.menu,
|
'lib/assets/logo_300x200.png',
|
||||||
color: Colors.white,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
const SizedBox(
|
||||||
]
|
height: 40,
|
||||||
: [
|
|
||||||
BottomNavigationBarItem(
|
|
||||||
label: 'register',
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
icon: Column(
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
onPressed: () async {
|
|
||||||
widget.client = await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => RegisterPage(
|
|
||||||
client: widget.client,
|
|
||||||
)));
|
|
||||||
},
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.login,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Text(
|
|
||||||
'Registrieren',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
Text(
|
||||||
BottomNavigationBarItem(
|
'Digitale Spuren auf Knopfdruck entfernen'
|
||||||
label: 'login',
|
.toUpperCase(),
|
||||||
backgroundColor: Colors.white,
|
textAlign: TextAlign.center,
|
||||||
icon: Column(
|
style: const TextStyle(
|
||||||
children: [
|
fontFamily: 'sans-serif',
|
||||||
IconButton(
|
fontSize: 24,
|
||||||
onPressed: () async {
|
height: 1.6,
|
||||||
final c = await Navigator.push(
|
fontWeight: FontWeight.normal,
|
||||||
context,
|
letterSpacing: 6,
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => LoginPage(
|
|
||||||
client: widget.client,
|
|
||||||
),
|
|
||||||
));
|
|
||||||
_updateClient(c);
|
|
||||||
},
|
|
||||||
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,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
TextButton(
|
||||||
],
|
onPressed: () {
|
||||||
);
|
// ScaffoldMessenger.of(context).clearSnackBars();
|
||||||
}),
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
body: Padding(
|
_snackBar(
|
||||||
padding: const EdgeInsets.all(16.0),
|
context,
|
||||||
child: Column(
|
value.response.message != null
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
? value.response.message!
|
||||||
children: [
|
: value.response.status.toString(),
|
||||||
const Image(
|
value.response.status.toString(),
|
||||||
image: AssetImage(
|
() {
|
||||||
'lib/assets/logo_300x200.png',
|
print('asdf');
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
if (widget.client.account != null &&
|
);
|
||||||
!widget.client.account!.emailVerified)
|
},
|
||||||
Container(
|
child: const Text('asdf'))
|
||||||
height: 120,
|
],
|
||||||
width: double.infinity,
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
|
|
||||||
child: Card(
|
|
||||||
color: Colors.brown.shade300,
|
|
||||||
child: const Text(
|
|
||||||
'Deine E-Mail Adresse ist noch nicht validiert.'),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -195,6 +195,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
version: "1.9.1"
|
||||||
|
nested:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: nested
|
||||||
|
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
path:
|
path:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -219,6 +227,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.1.0"
|
||||||
|
provider:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: provider
|
||||||
|
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.5"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -42,6 +42,7 @@ dependencies:
|
|||||||
sqflite: ^2.3.0
|
sqflite: ^2.3.0
|
||||||
path: ^1.8.3
|
path: ^1.8.3
|
||||||
fixnum: ^1.1.0
|
fixnum: ^1.1.0
|
||||||
|
provider: ^6.0.5
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
lints: ^2.0.0
|
lints: ^2.0.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user