ft/adds account_info and late_person pages
This commit is contained in:
parent
cc6841448d
commit
ebe3426c2c
BIN
frontend/app/assets/icons/icon.jpg
Normal file
BIN
frontend/app/assets/icons/icon.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
@ -1,6 +1,8 @@
|
||||
import 'package:app/model/services/auth_service.dart';
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/model/view_model/base_vm.dart';
|
||||
import 'package:app/pages/account_info_page.dart';
|
||||
import 'package:app/pages/late_person_page.dart';
|
||||
import 'package:app/pages/notifications_page.dart';
|
||||
import 'package:app/pages/registration_page.dart';
|
||||
import 'package:app/pages/security_page.dart';
|
||||
@ -110,30 +112,30 @@ class _DigitalerFriedenState extends State<DigitalerFrieden> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_loading) {
|
||||
return SafeArea(
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 150,
|
||||
),
|
||||
Hero(
|
||||
tag: 'logo',
|
||||
child: Image.asset(
|
||||
'assets/JPEG.jpg',
|
||||
height: 180,
|
||||
),
|
||||
),
|
||||
CircularProgressIndicator(
|
||||
color: CustomColors.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
return const StartPage();
|
||||
// return SafeArea(
|
||||
// child: Center(
|
||||
// child: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// Hero(
|
||||
// tag: 'logo',
|
||||
// child: Image.asset(
|
||||
// 'assets/JPEG.jpg',
|
||||
// height: 180,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
if (verified) {
|
||||
switch (accountLevel) {
|
||||
case 6:
|
||||
return const LatePersonPage();
|
||||
case 4 || 5:
|
||||
return const AccountInfoPage();
|
||||
default:
|
||||
return const StartPage();
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import 'package:app/pb/google/protobuf/timestamp.pb.dart';
|
||||
import 'package:app/pb/person.pb.dart';
|
||||
import 'package:app/data/database.dart';
|
||||
import 'package:app/pb/rpc_create_account.pb.dart';
|
||||
import 'package:app/pb/rpc_create_account_info.pb.dart';
|
||||
import 'package:app/pb/rpc_create_person.pb.dart';
|
||||
import 'package:app/pb/rpc_get_account.pb.dart';
|
||||
import 'package:app/pb/rpc_get_account_info.pb.dart';
|
||||
@ -143,15 +144,60 @@ class BackendService {
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> createAccountInfo(
|
||||
{required String firstname,
|
||||
required String lastname,
|
||||
required String streetAddress,
|
||||
required String zip,
|
||||
required String city,
|
||||
required String country,
|
||||
required String phoneNumber,
|
||||
required DateTime birthday}) async {
|
||||
try {
|
||||
final acc = await account;
|
||||
if (acc == null) {
|
||||
throw FetchDataException('AccountID nicht gespeichert');
|
||||
}
|
||||
final resp = BackendService.client.createAccountInfo(
|
||||
CreateAccountInfoRequest(
|
||||
accountId: acc.id,
|
||||
firstname: firstname,
|
||||
lastname: lastname,
|
||||
street: streetAddress,
|
||||
zip: zip,
|
||||
city: city,
|
||||
country: country,
|
||||
phone: phoneNumber,
|
||||
birthday: Timestamp.fromDateTime(birthday),
|
||||
),
|
||||
options: CallOptions(
|
||||
metadata: {
|
||||
'Authorization': 'Bearer ${await _storageService.accessToken}'
|
||||
},
|
||||
),
|
||||
);
|
||||
return resp != null;
|
||||
} on SocketException {
|
||||
throw FetchDataException('Keine Internet Verbindung');
|
||||
} on GrpcError catch (err) {
|
||||
throw FetchDataException('${err.message}');
|
||||
} catch (err) {
|
||||
throw InternalException(err.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> resendVerification({required Int64 accountId}) async {
|
||||
try {
|
||||
final resp = await BackendService.client.resendVerification(
|
||||
ResendVerificationRequest(
|
||||
accountId: accountId,
|
||||
),
|
||||
options: CallOptions(metadata: {
|
||||
ResendVerificationRequest(
|
||||
accountId: accountId,
|
||||
),
|
||||
options: CallOptions(
|
||||
metadata: {
|
||||
'Authorization': 'Bearer ${await _storageService.accessToken}'
|
||||
}));
|
||||
},
|
||||
),
|
||||
);
|
||||
return resp.account.id == accountId;
|
||||
} on SocketException {
|
||||
throw FetchDataException('Keine Internet Verbindung');
|
||||
|
@ -149,6 +149,67 @@ class BaseViewModel with ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<bool> createAccountInfo(
|
||||
BuildContext context, {
|
||||
required String firstname,
|
||||
required String lastname,
|
||||
required String streetAddress,
|
||||
required String zip,
|
||||
required String city,
|
||||
required String country,
|
||||
required String phoneNumber,
|
||||
required DateTime birthday,
|
||||
}) async {
|
||||
notifyListeners();
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
bool resp = false;
|
||||
try {
|
||||
resp = await _service.createAccountInfo(
|
||||
firstname: firstname,
|
||||
lastname: lastname,
|
||||
streetAddress: streetAddress,
|
||||
zip: zip,
|
||||
city: city,
|
||||
country: country,
|
||||
phoneNumber: phoneNumber,
|
||||
birthday: birthday,
|
||||
);
|
||||
if (resp) {
|
||||
_apiResponse = ApiResponse.completed('Registrierung abgeschlossen');
|
||||
}
|
||||
return resp;
|
||||
} catch (e) {
|
||||
messenger.showSnackBar(SnackBar(
|
||||
backgroundColor: CustomColors.error,
|
||||
content: const Text(
|
||||
'Daten konnten nicht übertragen werden',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
action: SnackBarAction(
|
||||
label: 'Details',
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
backgroundColor: Colors.black,
|
||||
icon: Icon(
|
||||
Icons.error,
|
||||
color: CustomColors.error,
|
||||
),
|
||||
content: Text(
|
||||
e.toString(),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
));
|
||||
},
|
||||
),
|
||||
));
|
||||
_apiResponse = ApiResponse.error(e.toString());
|
||||
}
|
||||
notifyListeners();
|
||||
return resp;
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
_apiResponse = ApiResponse.loading('Logge aus');
|
||||
notifyListeners();
|
||||
|
359
frontend/app/lib/pages/account_info_page.dart
Normal file
359
frontend/app/lib/pages/account_info_page.dart
Normal file
@ -0,0 +1,359 @@
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/model/view_model/base_vm.dart';
|
||||
import 'package:app/pages/late_person_page.dart';
|
||||
import 'package:app/pages/loading_page.dart';
|
||||
import 'package:app/pages/notifications_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:app/util/validation.dart';
|
||||
import 'package:app/widgets/custom_scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AccountInfoPage extends StatefulWidget {
|
||||
const AccountInfoPage({super.key});
|
||||
|
||||
@override
|
||||
State<AccountInfoPage> createState() => _AccountInfoPageState();
|
||||
}
|
||||
|
||||
class _AccountInfoPageState extends State<AccountInfoPage> {
|
||||
bool _loading = true;
|
||||
final StorageService _storageService = StorageService();
|
||||
final BaseViewModel _vm = BaseViewModel();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _firstNameController = TextEditingController();
|
||||
final _lastNameController = TextEditingController();
|
||||
final _streetController = TextEditingController();
|
||||
final _houseNumberController = TextEditingController();
|
||||
final _zipController = TextEditingController();
|
||||
final _cityController = TextEditingController();
|
||||
final _phoneController = TextEditingController();
|
||||
final _countryController = TextEditingController();
|
||||
final _birthdayController = TextEditingController();
|
||||
final _birthPlaceController = TextEditingController();
|
||||
|
||||
DateTime? _birthday;
|
||||
@override
|
||||
void initState() {
|
||||
_init();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_firstNameController.dispose();
|
||||
_lastNameController.dispose();
|
||||
_streetController.dispose();
|
||||
_houseNumberController.dispose();
|
||||
_zipController.dispose();
|
||||
_cityController.dispose();
|
||||
_phoneController.dispose();
|
||||
_countryController.dispose();
|
||||
_birthPlaceController.dispose();
|
||||
_birthdayController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _init() async {
|
||||
_countryController.text = 'Deutschland';
|
||||
if (await _storageService.accountLevel < 5) {
|
||||
await _storageService.setAccountLevel(5);
|
||||
}
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _selectDate(BuildContext context) async {
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: context,
|
||||
builder: (context, child) => Theme(
|
||||
data: ThemeData.dark(),
|
||||
child: child ?? const Text(''),
|
||||
),
|
||||
initialDate: DateTime.now().add(const Duration(days: 365 * -18)),
|
||||
firstDate: DateTime.now().add(const Duration(days: 365 * -100)),
|
||||
lastDate: DateTime.now().add(const Duration(days: 365 * -18)),
|
||||
);
|
||||
// firstDate: DateTime.now().add(const Duration(days: 365 * -100)),
|
||||
// lastDate: DateTime.now().add(const Duration(days: 365 * -18)));
|
||||
if (picked != null && picked != _birthday) {
|
||||
setState(() {
|
||||
_birthday = picked;
|
||||
_birthdayController.text =
|
||||
'${picked.day.toString().padLeft(2, '0')}.${picked.month.toString().padLeft(2, '0')}.${picked.year}';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: CustomScaffold(
|
||||
backButton: BackButton(
|
||||
color: CustomColors.primary,
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const NotificationsPage()));
|
||||
},
|
||||
),
|
||||
children: _loading
|
||||
? [
|
||||
LoadingPage(),
|
||||
]
|
||||
: [
|
||||
const Text(
|
||||
'Registrierung abschließen',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2.0,
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).viewInsets.bottom > 0 ? 230 : 460,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: Stack(
|
||||
children: [
|
||||
Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: _firstNameController,
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Vorname'),
|
||||
filled: true,
|
||||
),
|
||||
keyboardType: TextInputType.name,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidName) {
|
||||
return 'Bitte einen gültigen Vornamen eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
controller: _lastNameController,
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Nachname'),
|
||||
filled: true,
|
||||
),
|
||||
keyboardType: TextInputType.name,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidName) {
|
||||
return 'Bitte einen gültigen Nachnamen eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
controller: _streetController,
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Straße'),
|
||||
filled: true,
|
||||
),
|
||||
keyboardType: TextInputType.streetAddress,
|
||||
validator: (value) {
|
||||
if (value == null ||
|
||||
!value.isValidStreetAddress) {
|
||||
return 'Bitte eine gültige Straße eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 130,
|
||||
child: TextFormField(
|
||||
controller: _houseNumberController,
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Hausnummer'),
|
||||
filled: true,
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
validator: (value) {
|
||||
if (value == null ||
|
||||
!value.isValidHouseNumber) {
|
||||
return 'Nur Zahlen erlaubt';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
SizedBox(
|
||||
width: 160,
|
||||
child: TextFormField(
|
||||
controller: _zipController,
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Postleitzahl'),
|
||||
filled: true,
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
validator: (value) {
|
||||
if (value == null ||
|
||||
!value.isValidZip) {
|
||||
return 'Bitte eine gültige Postleitzahl eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
controller: _cityController,
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Stadt'),
|
||||
filled: true,
|
||||
),
|
||||
keyboardType: TextInputType.name,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidCity) {
|
||||
return 'Bitte einen gültigen Ort eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
controller: _countryController,
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
readOnly: true,
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Land'),
|
||||
filled: true,
|
||||
),
|
||||
keyboardType: TextInputType.name,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidName) {
|
||||
return 'Bitte einen gültigen Ort eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
controller: _phoneController,
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Telefonnummer'),
|
||||
filled: true,
|
||||
),
|
||||
keyboardType: TextInputType.phone,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidPhone) {
|
||||
return 'Bitte eine gültige Telefonnummer eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
onTap: () => _selectDate(context),
|
||||
controller: _birthdayController,
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
readOnly: true,
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Geburtsdatum'),
|
||||
filled: true,
|
||||
),
|
||||
keyboardType: TextInputType.datetime,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Bitte ein gültiges Datum eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Hero(
|
||||
tag: 'flow-button',
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
),
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
final resp = await _vm.createAccountInfo(
|
||||
context,
|
||||
firstname: _firstNameController.text,
|
||||
lastname: _lastNameController.text,
|
||||
city: _cityController.text,
|
||||
country: _countryController.text,
|
||||
zip: _zipController.text,
|
||||
phoneNumber: _phoneController.text,
|
||||
streetAddress: _streetController.text,
|
||||
birthday: _birthday!,
|
||||
);
|
||||
|
||||
if (resp) {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const LatePersonPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const SizedBox(
|
||||
height: 60,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Weiter',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
64
frontend/app/lib/pages/late_person_page.dart
Normal file
64
frontend/app/lib/pages/late_person_page.dart
Normal file
@ -0,0 +1,64 @@
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/pages/loading_page.dart';
|
||||
import 'package:app/pages/notifications_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:app/widgets/custom_scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LatePersonPage extends StatefulWidget {
|
||||
const LatePersonPage({super.key});
|
||||
|
||||
@override
|
||||
State<LatePersonPage> createState() => _LatePersonPageState();
|
||||
}
|
||||
|
||||
class _LatePersonPageState extends State<LatePersonPage> {
|
||||
final StorageService _storageService = StorageService();
|
||||
bool _loading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_init();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void _init() async {
|
||||
if (await _storageService.accountLevel < 6) {
|
||||
await _storageService.setAccountLevel(6);
|
||||
}
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomScaffold(
|
||||
backButton: BackButton(
|
||||
color: CustomColors.primary,
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const NotificationsPage()));
|
||||
},
|
||||
),
|
||||
children: _loading
|
||||
? [
|
||||
LoadingPage(),
|
||||
]
|
||||
: [
|
||||
const Text(
|
||||
'Daten der Verstorbenen',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2.0,
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
18
frontend/app/lib/pages/loading_page.dart
Normal file
18
frontend/app/lib/pages/loading_page.dart
Normal file
@ -0,0 +1,18 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LoadingPage extends StatelessWidget {
|
||||
LoadingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Hero(
|
||||
tag: 'logo',
|
||||
child: Image.asset(
|
||||
'assets/icons/icon.jpg',
|
||||
// height: 180,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/pages/account_info_page.dart';
|
||||
import 'package:app/pages/late_person_page.dart';
|
||||
import 'package:app/pages/registration_page.dart';
|
||||
import 'package:app/pages/security_page.dart';
|
||||
import 'package:app/pages/verify_email_page.dart';
|
||||
@ -123,13 +125,39 @@ class _NotificationsPageState extends State<NotificationsPage> {
|
||||
onPressed: () async {
|
||||
await _setNotificationSetting(true);
|
||||
if (await _storageService.accessToken != null) {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const VerifyEmailPage(),
|
||||
),
|
||||
);
|
||||
if (await _storageService.verified) {
|
||||
switch (await _storageService.accountLevel) {
|
||||
case 4 || 5:
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) =>
|
||||
const AccountInfoPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
case 6:
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) =>
|
||||
const LatePersonPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) =>
|
||||
const VerifyEmailPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mounted) {
|
||||
@ -171,14 +199,38 @@ class _NotificationsPageState extends State<NotificationsPage> {
|
||||
onPressed: () async {
|
||||
await _setNotificationSetting(false);
|
||||
if (await _storageService.accessToken != null) {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const VerifyEmailPage(),
|
||||
// builder: (builder) => SecurityPage(),
|
||||
),
|
||||
);
|
||||
if (await _storageService.verified) {
|
||||
switch (await _storageService.accountLevel) {
|
||||
case 4 || 5:
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) =>
|
||||
const AccountInfoPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
case 6:
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) =>
|
||||
const LatePersonPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const VerifyEmailPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mounted) {
|
||||
@ -186,7 +238,6 @@ class _NotificationsPageState extends State<NotificationsPage> {
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const RegistrationPage(),
|
||||
// builder: (builder) => SecurityPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:app/model/view_model/base_vm.dart';
|
||||
import 'package:app/pages/account_info_page.dart';
|
||||
import 'package:app/pages/verify_email_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -201,7 +202,17 @@ class _PasswordPageState extends State<PasswordPage> {
|
||||
password: _passwordController1.text,
|
||||
);
|
||||
}
|
||||
if (loggedin && mounted) {
|
||||
if (loggedin) {
|
||||
FocusManager.instance.primaryFocus
|
||||
?.unfocus();
|
||||
final acc = await _vm.account;
|
||||
if (acc!.emailVerified) {
|
||||
navigator.push(
|
||||
MaterialPageRoute(
|
||||
builder: (builder) =>
|
||||
const AccountInfoPage()),
|
||||
);
|
||||
}
|
||||
navigator.push(
|
||||
MaterialPageRoute(
|
||||
builder: (builder) =>
|
||||
@ -220,7 +231,7 @@ class _PasswordPageState extends State<PasswordPage> {
|
||||
children: [
|
||||
Text(
|
||||
widget.register
|
||||
? 'Registrierung abschließen'
|
||||
? 'Konto erstellen'
|
||||
: 'Einloggen',
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
|
@ -1,8 +1,10 @@
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/pages/loading_page.dart';
|
||||
import 'package:app/pages/notifications_page.dart';
|
||||
import 'package:app/pages/password_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:app/util/validation.dart';
|
||||
import 'package:app/widgets/custom_scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class RegistrationPage extends StatefulWidget {
|
||||
@ -42,169 +44,140 @@ class _RegistrationPageState extends State<RegistrationPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: _loading
|
||||
? Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 150,
|
||||
),
|
||||
Hero(
|
||||
tag: 'logo',
|
||||
child: Image.asset(
|
||||
'assets/JPEG.jpg',
|
||||
height: 180,
|
||||
),
|
||||
),
|
||||
CircularProgressIndicator(
|
||||
color: CustomColors.primary,
|
||||
),
|
||||
],
|
||||
return CustomScaffold(
|
||||
backButton: BackButton(
|
||||
color: CustomColors.primary,
|
||||
onPressed: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const NotificationsPage()),
|
||||
(route) => false);
|
||||
},
|
||||
),
|
||||
children: _loading
|
||||
? [
|
||||
LoadingPage(),
|
||||
]
|
||||
: [
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
)
|
||||
: Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: BackButton(
|
||||
color: CustomColors.primary,
|
||||
onPressed: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const NotificationsPage()),
|
||||
(route) => false);
|
||||
},
|
||||
),
|
||||
iconTheme: IconThemeData(
|
||||
color: CustomColors.primary,
|
||||
const Text(
|
||||
'Jetzt Registrieren',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2.0,
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 20, 20, 16),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
'Gib deine E-Mail Adresse ein.',
|
||||
// textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
'Jetzt Registrieren',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2.0,
|
||||
fontSize: 25,
|
||||
TextFormField(
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
controller: mailController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
decoration: const InputDecoration(
|
||||
helperText: 'test',
|
||||
label: Text('E-Mail Adresse'),
|
||||
filled: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
'Gib deine E-Mail Adresse ein.',
|
||||
// textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
controller: mailController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
decoration: const InputDecoration(
|
||||
helperText: 'test',
|
||||
label: Text('E-Mail Adresse'),
|
||||
filled: true,
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidEmail) {
|
||||
return 'Bitte eine valide E-Mail Adresse angeben';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
if (formKey.currentState!.validate()) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => PasswordPage(
|
||||
email: mailController.text,
|
||||
register: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
'Stattdessen anmelden',
|
||||
// textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: CustomColors.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
Hero(
|
||||
tag: 'flow-button',
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
),
|
||||
onPressed: () {
|
||||
if (formKey.currentState!.validate()) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => PasswordPage(
|
||||
email: mailController.text,
|
||||
register: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const SizedBox(
|
||||
height: 50,
|
||||
width: 100,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Weiter',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(
|
||||
flex: 2,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidEmail) {
|
||||
return 'Bitte eine valide E-Mail Adresse angeben';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
if (formKey.currentState!.validate()) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => PasswordPage(
|
||||
email: mailController.text,
|
||||
register: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
'Stattdessen anmelden',
|
||||
// textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: CustomColors.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
Hero(
|
||||
tag: 'flow-button',
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
),
|
||||
onPressed: () {
|
||||
if (formKey.currentState!.validate()) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => PasswordPage(
|
||||
email: mailController.text,
|
||||
register: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const SizedBox(
|
||||
height: 50,
|
||||
width: 100,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Weiter',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(
|
||||
flex: 2,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
import 'package:app/model/services/auth_service.dart';
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/pages/loading_page.dart';
|
||||
import 'package:app/pages/notifications_page.dart';
|
||||
import 'package:app/pages/start_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:app/widgets/custom_scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SecurityPage extends StatefulWidget {
|
||||
@ -33,151 +35,130 @@ class _SecurityPageState extends State<SecurityPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: _loading
|
||||
? Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 150,
|
||||
return CustomScaffold(
|
||||
backButton: BackButton(
|
||||
color: CustomColors.primary,
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (builder) => const StartPage()),
|
||||
);
|
||||
},
|
||||
),
|
||||
children: _loading
|
||||
? [
|
||||
LoadingPage(),
|
||||
// Center(
|
||||
// child: Hero(
|
||||
// tag: 'logo',
|
||||
// child: Image.asset(
|
||||
// 'assets/JPEG.jpg',
|
||||
// height: 180,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
]
|
||||
: [
|
||||
const Spacer(),
|
||||
const Hero(
|
||||
tag: 'flow-icon',
|
||||
child: Icon(
|
||||
Icons.fingerprint,
|
||||
color: Colors.white,
|
||||
size: 200,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const Text(
|
||||
'Deine Sicherheit kommt an erster Stelle',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
const Text(
|
||||
'Schütze dein Konto mit der biometrischen Erkennung deines Geräts oder lege einen Code fest.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
const Spacer(),
|
||||
Hero(
|
||||
tag: 'flow-button',
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
),
|
||||
Hero(
|
||||
tag: 'logo',
|
||||
child: Image.asset(
|
||||
'assets/JPEG.jpg',
|
||||
height: 180,
|
||||
onPressed: () async {
|
||||
bool isAuthenticated =
|
||||
await AuthService.authenticateWithBiometrics();
|
||||
if (isAuthenticated) {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const NotificationsPage()),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const SizedBox(
|
||||
height: 60,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'App absichern',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
CircularProgressIndicator(
|
||||
color: CustomColors.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: BackButton(
|
||||
color: CustomColors.primary,
|
||||
onPressed: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const StartPage()),
|
||||
(route) => false);
|
||||
},
|
||||
),
|
||||
iconTheme: IconThemeData(color: CustomColors.primary),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 20, 16, 16),
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const Spacer(),
|
||||
const Hero(
|
||||
tag: 'flow-icon',
|
||||
child: Icon(
|
||||
Icons.fingerprint,
|
||||
color: Colors.white,
|
||||
size: 200,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const Text(
|
||||
'Deine Sicherheit kommt an erster Stelle',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
const Text(
|
||||
'Schütze dein Konto mit der biometrischen Erkennung deines Geräts oder lege einen Code fest.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
const Spacer(),
|
||||
Hero(
|
||||
tag: 'flow-button',
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
),
|
||||
onPressed: () async {
|
||||
bool isAuthenticated =
|
||||
await AuthService.authenticateWithBiometrics();
|
||||
if (isAuthenticated) {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
const NotificationsPage()),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const SizedBox(
|
||||
height: 60,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'App absichern',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// ElevatedButton(
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: CustomColors.secondary,
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (builder) => SecurityPage(),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// child: const SizedBox(
|
||||
// height: 60,
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// Text(
|
||||
// 'Eigenen Code festlegen',
|
||||
// style: TextStyle(
|
||||
// color: Colors.white,
|
||||
// fontSize: 22,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
const Spacer(
|
||||
flex: 2,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// ElevatedButton(
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: CustomColors.secondary,
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (builder) => SecurityPage(),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// child: const SizedBox(
|
||||
// height: 60,
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// Text(
|
||||
// 'Eigenen Code festlegen',
|
||||
// style: TextStyle(
|
||||
// color: Colors.white,
|
||||
// fontSize: 22,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
const Spacer(
|
||||
flex: 2,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:app/pages/agb_page.dart';
|
||||
import 'package:app/pages/security_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:app/widgets/custom_scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StartPage extends StatelessWidget {
|
||||
@ -8,105 +9,94 @@ class StartPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
iconTheme: IconThemeData(color: CustomColors.primary),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 20, 16, 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Hero(
|
||||
tag: 'flow-icon',
|
||||
child: Image.asset(
|
||||
'assets/JPEG.jpg',
|
||||
height: 180,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
const Text(
|
||||
'Hallo. Digitale Spuren\nentfernen\nper Knopfdruck.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2.0,
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
'Mit uns finden Sie Ihre Digitalen Spuren und können diese entfernen.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
Hero(
|
||||
tag: 'flow-button',
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const SecurityPage(),
|
||||
// builder: (builder) => SecurityPage(),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: const SizedBox(
|
||||
height: 60,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Weiter',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
const Text(
|
||||
'Mit der weiteren Nutzung stimmst du den folgenden Bedingungen zu:',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context, builder: (builder) => AgbPage());
|
||||
},
|
||||
child: Text(
|
||||
'AGB - Datenschutzerklärung',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: CustomColors.primary),
|
||||
))
|
||||
],
|
||||
return CustomScaffold(
|
||||
children: [
|
||||
Hero(
|
||||
tag: 'flow-icon',
|
||||
child: Image.asset(
|
||||
'assets/JPEG.jpg',
|
||||
height: 180,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
const Text(
|
||||
'Hallo. Digitale Spuren\nentfernen\nper Knopfdruck.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2.0,
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
'Mit uns finden Sie Ihre Digitalen Spuren und können diese entfernen.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
Hero(
|
||||
tag: 'flow-button',
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const SecurityPage(),
|
||||
// builder: (builder) => SecurityPage(),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: const SizedBox(
|
||||
height: 60,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Weiter',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
const Text(
|
||||
'Mit der weiteren Nutzung stimmst du den folgenden Bedingungen zu:',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
showDialog(context: context, builder: (builder) => AgbPage());
|
||||
},
|
||||
child: Text(
|
||||
'AGB - Datenschutzerklärung',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: CustomColors.primary),
|
||||
))
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/model/view_model/base_vm.dart';
|
||||
import 'package:app/pages/account_info_page.dart';
|
||||
import 'package:app/pages/notifications_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -113,7 +114,31 @@ class _VerifyEmailPageState extends State<VerifyEmailPage> {
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
),
|
||||
onPressed: () {},
|
||||
onPressed: () async {
|
||||
final acc = await _vm.account;
|
||||
if (acc != null && acc.emailVerified) {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) =>
|
||||
const AccountInfoPage()),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).clearSnackBars();
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(SnackBar(
|
||||
backgroundColor: CustomColors.error,
|
||||
content: const Text(
|
||||
'E-Mail Adresse ist noch nicht verifiziert.',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const SizedBox(
|
||||
height: 50,
|
||||
width: 100,
|
||||
|
@ -1,8 +1,12 @@
|
||||
final emailRegExp = RegExp(r"^[a-zA-Z0-9.]+@[a-zA-Z0-9]+\.[a-zA-Z]+");
|
||||
final nameRegExp =
|
||||
RegExp(r"^\s*([A-Za-z]{1,}([\.,] |[-']| ))+[A-Za-z]+\.?\s*$");
|
||||
final phoneRegExp = RegExp(r"^\+?0[0-9]{10}$");
|
||||
final passwordRegExp = RegExp(r'^[0-9a-zA-Z\-\_\.\,\*\+\=?!]{12,64}$');
|
||||
final nameRegExp = RegExp(r"^[a-zA-ZäöüÄÖÜß]+(?:[-\s][a-zA-ZäöüÄÖÜß]+)?$");
|
||||
final phoneRegExp = RegExp(r"^(?:\+49|0)[1-9][0-9\s\-\/]*$");
|
||||
final streetRegExp = RegExp(r"^[a-zA-ZäöüÄÖÜß\s\-\d]+$");
|
||||
final houseNumberRegExp = RegExp(r"^[0-9]+$");
|
||||
final zipRegExp = RegExp(r"^\d{5}$");
|
||||
final cityRegExp = RegExp(r"^[a-zA-ZäöüÄÖÜß\s\-\.,]+$");
|
||||
final passwordRegExp = RegExp(
|
||||
r'^(?=.*[a-zäöü])(?=.*[A-ZÄÖÜ])(?=.*\d)(?=.*[@$!%*?&])[A-Za-zäöüÄÖÜ\d@$!%*?&]{8,}$');
|
||||
|
||||
extension valString on String {
|
||||
bool get isValidEmail {
|
||||
@ -13,6 +17,22 @@ extension valString on String {
|
||||
return nameRegExp.hasMatch(this);
|
||||
}
|
||||
|
||||
bool get isValidStreetAddress {
|
||||
return streetRegExp.hasMatch(this);
|
||||
}
|
||||
|
||||
bool get isValidHouseNumber {
|
||||
return houseNumberRegExp.hasMatch(this);
|
||||
}
|
||||
|
||||
bool get isValidZip {
|
||||
return zipRegExp.hasMatch(this);
|
||||
}
|
||||
|
||||
bool get isValidCity {
|
||||
return cityRegExp.hasMatch(this);
|
||||
}
|
||||
|
||||
bool get isValidPassword {
|
||||
return passwordRegExp.hasMatch(this);
|
||||
}
|
||||
|
33
frontend/app/lib/widgets/custom_scaffold.dart
Normal file
33
frontend/app/lib/widgets/custom_scaffold.dart
Normal file
@ -0,0 +1,33 @@
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CustomScaffold extends StatelessWidget {
|
||||
const CustomScaffold({
|
||||
super.key,
|
||||
required this.children,
|
||||
this.backButton,
|
||||
});
|
||||
|
||||
final List<Widget> children;
|
||||
final Widget? backButton;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
leading: backButton,
|
||||
iconTheme: IconThemeData(color: CustomColors.primary),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 45, vertical: 40),
|
||||
child: Column(
|
||||
children: children,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -230,7 +230,7 @@ packages:
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
|
@ -46,7 +46,6 @@ dependencies:
|
||||
path: ^1.8.3
|
||||
fixnum: ^1.1.0
|
||||
provider: ^6.0.5
|
||||
intl: ^0.18.1
|
||||
flutter_secure_storage: ^9.0.0
|
||||
|
||||
dev_dependencies:
|
||||
@ -75,6 +74,7 @@ flutter:
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
assets:
|
||||
- assets/chat_bubbles.png
|
||||
- assets/icons/icon.jpg
|
||||
- assets/JPEG.jpg
|
||||
- lib/assets/logo_300x200.png
|
||||
- lib/assets/hero-pattern-300x200.png
|
||||
|
Loading…
x
Reference in New Issue
Block a user