ft/adds dashboard screen and refactores
adds: - loading screen - global background image refactores: - no more screens, just pages fixes: - login callback functions
This commit is contained in:
parent
a14b87012a
commit
d0687e2d3f
@ -1,16 +1,16 @@
|
|||||||
import 'package:app/main.dart';
|
|
||||||
import 'package:app/pb/rpc_create_account.pb.dart';
|
import 'package:app/pb/rpc_create_account.pb.dart';
|
||||||
import 'package:app/pb/rpc_get_account_info.pb.dart';
|
import 'package:app/pb/rpc_get_account_info.pb.dart';
|
||||||
import 'package:app/pb/rpc_login.pb.dart';
|
import 'package:app/pb/rpc_login.pb.dart';
|
||||||
import 'package:app/pb/service_df.pbgrpc.dart';
|
import 'package:app/pb/service_df.pbgrpc.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:grpc/grpc.dart';
|
import 'package:grpc/grpc.dart';
|
||||||
|
|
||||||
class Client {
|
class Client {
|
||||||
String baseUrl = 'localhost';
|
String baseUrl = 'localhost';
|
||||||
int port = 9090;
|
int port = 9090;
|
||||||
|
|
||||||
|
Map<String, dynamic> metadata = {'Authorization': ''};
|
||||||
|
String accessToken = '';
|
||||||
|
|
||||||
dfClient stub = dfClient(
|
dfClient stub = dfClient(
|
||||||
ClientChannel('10.0.2.2',
|
ClientChannel('10.0.2.2',
|
||||||
port: 9090,
|
port: 9090,
|
||||||
@ -35,44 +35,51 @@ class Client {
|
|||||||
return CreateAccountResponse();
|
return CreateAccountResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoginResponse Login(BuildContext context, LoginRequest request ){
|
Future<LoginResponse> login(
|
||||||
// try {
|
{required String email,
|
||||||
// final response = stub.login(request);
|
required String password,
|
||||||
// return response;
|
required Function onError,
|
||||||
// } catch (e) {
|
required Function onSuccess}) async {
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
LoginResponse response = LoginResponse();
|
||||||
// content: Text('Login fehlgeschlagen: $e'),
|
|
||||||
// ));
|
|
||||||
// }
|
|
||||||
// return LoginResponse();
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
Future<LoginResponse> login(LoginRequest request, {Function? onError}) async {
|
|
||||||
try {
|
try {
|
||||||
final response = await stub.login(request);
|
response = await stub.login(LoginRequest(
|
||||||
return response;
|
email: email,
|
||||||
|
password: password,
|
||||||
|
));
|
||||||
|
accessToken = response.accessToken;
|
||||||
|
metadata['Authorization'] = 'Bearer ${response.accessToken}';
|
||||||
|
print('auth: ${metadata['Authorization']}');
|
||||||
|
onSuccess();
|
||||||
|
// return response;
|
||||||
} on GrpcError catch (e) {
|
} on GrpcError catch (e) {
|
||||||
print('caught error: ${e.message}');
|
print('caught error: ${e.message}');
|
||||||
onError!();
|
metadata['Authorization'] = '';
|
||||||
|
onError();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('caught error: $e');
|
print('caught error: ${e}');
|
||||||
onError!();
|
metadata['Authorization'] = '';
|
||||||
|
onError();
|
||||||
}
|
}
|
||||||
return LoginResponse();
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GetAccountInfoResponse> getAccountInfo(GetAccountInfoRequest request,
|
Future<GetAccountInfoResponse> getAccountInfo(GetAccountInfoRequest request,
|
||||||
{Function? onError}) async {
|
{required String token, required Function onError}) async {
|
||||||
try {
|
try {
|
||||||
final response = await stub.getAccountInfo(request);
|
Map<String, String> metadata = {'Authorization': 'Bearer $token'};
|
||||||
|
final response = await stub.getAccountInfo(
|
||||||
|
request,
|
||||||
|
options: CallOptions(
|
||||||
|
metadata: metadata,
|
||||||
|
),
|
||||||
|
);
|
||||||
return response;
|
return response;
|
||||||
} on GrpcError catch (e) {
|
} on GrpcError catch (e) {
|
||||||
print('caught error: ${e.message}');
|
print('caught error: ${e.message}');
|
||||||
onError!();
|
onError();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('caught error: $e');
|
print('caught error: $e');
|
||||||
onError!();
|
onError();
|
||||||
}
|
}
|
||||||
return GetAccountInfoResponse();
|
return GetAccountInfoResponse();
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,35 @@
|
|||||||
|
import 'package:app/pages/login_page.dart';
|
||||||
|
import 'package:app/widgets/background.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:app/pages/main_screen.dart';
|
|
||||||
|
|
||||||
class GlobalVariable {
|
|
||||||
/// This global key is used in material app for navigation through firebase notifications.
|
|
||||||
static final GlobalKey<NavigatorState> navigatorState =
|
|
||||||
GlobalKey<NavigatorState>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
runApp(MaterialApp(
|
|
||||||
navigatorKey: GlobalVariable.navigatorState,
|
runApp(
|
||||||
home: MainScreen(),
|
MaterialApp(
|
||||||
));
|
theme: ThemeData().copyWith(
|
||||||
|
textTheme: const TextTheme().copyWith(
|
||||||
|
titleLarge: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
titleMedium: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
titleSmall: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
inputDecorationTheme: const InputDecorationTheme(
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
scaffoldBackgroundColor: Colors.transparent,
|
||||||
|
appBarTheme: const AppBarTheme().copyWith(
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
)),
|
||||||
|
home: Background(child: LoginPage()),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
62
frontend/app/lib/pages/dashboard_page.dart
Normal file
62
frontend/app/lib/pages/dashboard_page.dart
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import 'package:app/gapi/client.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DashboardPage extends StatefulWidget {
|
||||||
|
DashboardPage({super.key, required this.client});
|
||||||
|
|
||||||
|
final Client client;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DashboardPage> createState() => _DashboardPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DashboardPageState extends State<DashboardPage> {
|
||||||
|
bool _loading = false;
|
||||||
|
|
||||||
|
void _setLoading(bool loading) {
|
||||||
|
setState(() {
|
||||||
|
_loading = loading;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
if (widget.client.accessToken == '') {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
print(widget.client.accessToken);
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
flexibleSpace: Image.asset(
|
||||||
|
'lib/assets/logo_300x200.png',
|
||||||
|
height: 80,
|
||||||
|
),
|
||||||
|
// actions: [
|
||||||
|
// IconButton(
|
||||||
|
// onPressed: () {},
|
||||||
|
// icon: const Icon(Icons.menu),
|
||||||
|
// tooltip: 'Menu',
|
||||||
|
// ),
|
||||||
|
// IconButton(
|
||||||
|
// onPressed: () {},
|
||||||
|
// icon: const Icon(Icons.login_sharp),
|
||||||
|
// tooltip: 'Login',
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
),
|
||||||
|
body: Text(
|
||||||
|
widget.client.accessToken,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,23 +0,0 @@
|
|||||||
import 'package:app/pb/account_info.pb.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class HomeScreen extends StatelessWidget {
|
|
||||||
HomeScreen({super.key, required this.account_info});
|
|
||||||
|
|
||||||
AccountInfo account_info;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Willkommen ${account_info.firstname}!',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 30,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
179
frontend/app/lib/pages/login_page.dart
Normal file
179
frontend/app/lib/pages/login_page.dart
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
import 'package:app/gapi/client.dart';
|
||||||
|
import 'package:app/pages/dashboard_page.dart';
|
||||||
|
import 'package:app/pb/rpc_login.pb.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class LoginPage extends StatefulWidget {
|
||||||
|
const LoginPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<LoginPage> createState() => _LoginPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LoginPageState extends State<LoginPage> {
|
||||||
|
bool _loading = false;
|
||||||
|
|
||||||
|
void _setLoading(bool loading) {
|
||||||
|
setState(() {
|
||||||
|
_loading = loading;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
final Client client = Client();
|
||||||
|
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
final mailController = TextEditingController();
|
||||||
|
final passwordController = TextEditingController();
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// void initState() {
|
||||||
|
// super.initState();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<String> _login(
|
||||||
|
// {required BuildContext context,
|
||||||
|
// required String email,
|
||||||
|
// required String password,
|
||||||
|
// required Function onSuccess,
|
||||||
|
// required Function onError}) async {
|
||||||
|
// LoginResponse r = await client.login(
|
||||||
|
// LoginRequest(
|
||||||
|
// email: email,
|
||||||
|
// password: password,
|
||||||
|
// ),
|
||||||
|
// onError: onError,
|
||||||
|
// onSuccess: onSuccess,
|
||||||
|
// );
|
||||||
|
// return r.accessToken;
|
||||||
|
// }
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
flexibleSpace: Image.asset(
|
||||||
|
'lib/assets/logo_300x200.png',
|
||||||
|
height: 80,
|
||||||
|
),
|
||||||
|
// actions: [
|
||||||
|
// IconButton(
|
||||||
|
// onPressed: () {},
|
||||||
|
// icon: const Icon(Icons.menu),
|
||||||
|
// tooltip: 'Menu',
|
||||||
|
// ),
|
||||||
|
// IconButton(
|
||||||
|
// onPressed: () {},
|
||||||
|
// icon: const Icon(Icons.login_sharp),
|
||||||
|
// tooltip: 'Login',
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
),
|
||||||
|
body: !_loading
|
||||||
|
? Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
controller: mailController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||||
|
filled: true,
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: Colors.white38,
|
||||||
|
),
|
||||||
|
hintText: 'E-Mail Adresse',
|
||||||
|
),
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Bitte eine gültige E-Mail Adresse eingeben';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
controller: passwordController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||||
|
filled: true,
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: Colors.white38,
|
||||||
|
),
|
||||||
|
hintText: 'Passwort',
|
||||||
|
),
|
||||||
|
keyboardType: TextInputType.visiblePassword,
|
||||||
|
obscureText: true,
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Bitte geben Sie Ihr Passwort ein';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
// final navigator = Navigator.of(context);
|
||||||
|
_setLoading(true);
|
||||||
|
client
|
||||||
|
.login(
|
||||||
|
email: mailController.text,
|
||||||
|
password: passwordController.text,
|
||||||
|
onError: () {
|
||||||
|
_setLoading(false);
|
||||||
|
ScaffoldMessenger.of(context)
|
||||||
|
.showSnackBar(const SnackBar(
|
||||||
|
content: Text('Login fehlgeschlagen'),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
onSuccess: () {
|
||||||
|
// _setLoading(false);
|
||||||
|
ScaffoldMessenger.of(context)
|
||||||
|
.showSnackBar(const SnackBar(
|
||||||
|
content: Text('Login erfolgreich'),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(r) {
|
||||||
|
if (r.accessToken != '') {
|
||||||
|
Navigator.pushAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (ctx) => DashboardPage(
|
||||||
|
client: client,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(route) => false);
|
||||||
|
}
|
||||||
|
// _setLoading(false);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.arrow_forward))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
'lib/assets/logo_300x200.png',
|
||||||
|
height: 300,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,102 +0,0 @@
|
|||||||
import 'package:app/gapi/client.dart';
|
|
||||||
import 'package:app/pages/home_screen.dart';
|
|
||||||
import 'package:app/pb/rpc_get_account_info.pb.dart';
|
|
||||||
import 'package:app/pb/rpc_login.pb.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class LoginScreen extends StatelessWidget {
|
|
||||||
LoginScreen({super.key});
|
|
||||||
|
|
||||||
Client client = Client();
|
|
||||||
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
|
||||||
final mailController = TextEditingController();
|
|
||||||
final passwordController = TextEditingController();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Form(
|
|
||||||
key: _formKey,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
TextFormField(
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
controller: mailController,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
|
||||||
filled: true,
|
|
||||||
hintStyle: TextStyle(
|
|
||||||
color: Colors.white38,
|
|
||||||
),
|
|
||||||
hintText: 'E-Mail Adresse',
|
|
||||||
),
|
|
||||||
keyboardType: TextInputType.emailAddress,
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'Bitte eine gültige E-Mail Adresse eingeben';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextFormField(
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
controller: passwordController,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
|
||||||
filled: true,
|
|
||||||
hintStyle: TextStyle(
|
|
||||||
color: Colors.white38,
|
|
||||||
),
|
|
||||||
hintText: 'Passwort',
|
|
||||||
),
|
|
||||||
keyboardType: TextInputType.visiblePassword,
|
|
||||||
obscureText: true,
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'Bitte geben Sie Ihr Passwort ein';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () async {
|
|
||||||
if (_formKey.currentState!.validate()) {
|
|
||||||
// final navigator = Navigator.of(context);
|
|
||||||
LoginResponse response = await client.login(
|
|
||||||
LoginRequest(
|
|
||||||
email: mailController.text,
|
|
||||||
password: passwordController.text,
|
|
||||||
),
|
|
||||||
onError: () {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
|
||||||
content: Text('Login fehlgeschlagen'),
|
|
||||||
));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
print(response);
|
|
||||||
|
|
||||||
// GetAccountInfoResponse resp = await client.getAccountInfo(
|
|
||||||
// GetAccountInfoRequest(accountId: response.accountId));
|
|
||||||
// Navigator.push(
|
|
||||||
// context,
|
|
||||||
// MaterialPageRoute(
|
|
||||||
// builder: (context) => HomeScreen(
|
|
||||||
// account_info: resp.accountInfo,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: const Icon(Icons.arrow_forward))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
import 'package:app/gapi/client.dart';
|
|
||||||
import 'package:app/pages/login_screen.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
Map<String, Widget> screens = {
|
|
||||||
// 'main': MainScreen(),
|
|
||||||
'login': LoginScreen(),
|
|
||||||
};
|
|
||||||
|
|
||||||
class MainScreen extends StatelessWidget {
|
|
||||||
MainScreen({super.key});
|
|
||||||
|
|
||||||
Client client = Client();
|
|
||||||
|
|
||||||
String currentScreen = 'login';
|
|
||||||
|
|
||||||
setPage(String screen) {
|
|
||||||
currentScreen = screen;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
// color: Color.fromARGB(230, 255, 255, 255),
|
|
||||||
gradient: LinearGradient(
|
|
||||||
colors: [Colors.black, Colors.white],
|
|
||||||
begin: Alignment.topCenter,
|
|
||||||
end: Alignment.bottomCenter,
|
|
||||||
),
|
|
||||||
image: DecorationImage(
|
|
||||||
image: AssetImage(
|
|
||||||
'lib/assets/hero-pattern-300x200.png',
|
|
||||||
// color: Colors.grey,
|
|
||||||
),
|
|
||||||
repeat: ImageRepeat.repeat,
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Scaffold(
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
appBar: AppBar(
|
|
||||||
backgroundColor: Colors.black,
|
|
||||||
flexibleSpace: Image.asset(
|
|
||||||
'lib/assets/logo_300x200.png',
|
|
||||||
height: 80,
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
IconButton(
|
|
||||||
onPressed: () {},
|
|
||||||
icon: const Icon(Icons.menu),
|
|
||||||
tooltip: 'Menu',
|
|
||||||
),
|
|
||||||
// IconButton(
|
|
||||||
// onPressed: () {},
|
|
||||||
// icon: const Icon(Icons.login_sharp),
|
|
||||||
// tooltip: 'Login',
|
|
||||||
// ),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
child: screens[currentScreen],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
29
frontend/app/lib/widgets/background.dart
Normal file
29
frontend/app/lib/widgets/background.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Background extends StatelessWidget {
|
||||||
|
const Background({super.key, required this.child});
|
||||||
|
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
// color: Color.fromARGB(230, 255, 255, 255),
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [Colors.black, Colors.white],
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
),
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(
|
||||||
|
'lib/assets/hero-pattern-300x200.png',
|
||||||
|
// color: Colors.grey,
|
||||||
|
),
|
||||||
|
repeat: ImageRepeat.repeat,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: child);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user