diff --git a/Mobile/lib/base/sidemenu.dart b/Mobile/lib/base/sidemenu.dart new file mode 100644 index 0000000..3683d8f --- /dev/null +++ b/Mobile/lib/base/sidemenu.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; + +class SideMenu extends StatefulWidget { + final Widget body; + + const SideMenu({Key? key, required this.body}) : super(key: key); + + @override + State createState() => _SideMenuState(); +} + +class _SideMenuState extends State { + int _selectedIndex = 0; + + void _onItemTapped(int index) { + setState(() { + _selectedIndex = index; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: const Text('SkanTavels'), + ), + drawer: Drawer( + child: ListView( + padding: EdgeInsets.zero, + children: [ + const DrawerHeader( + decoration: BoxDecoration( + color: Colors.blue, + ), + child: Text('Drawer Header'), + ), + ListTile( + title: const Text('Home'), + leading: const Icon(Icons.home), + selected: _selectedIndex == 0, + onTap: () { + // Update the state of the app + _onItemTapped(0); + // Then close the drawer + Navigator.pushReplacementNamed(context, '/home'); + }, + ), + ListTile( + title: const Text('Favourites'), + leading: const Icon(Icons.star), + selected: _selectedIndex == 1, + onTap: () { + // Update the state of the app + _onItemTapped(1); + // Then close the drawer + Navigator.pop(context); + }, + ), + ListTile( + title: const Text('Profile'), + leading: const Icon(Icons.person), + selected: _selectedIndex == 2, + onTap: () { + // Update the state of the app + _onItemTapped(2); + // Then close the drawer + Navigator.pushReplacementNamed(context, '/profile'); + }, + ), + const Divider( + color: Colors.grey, + thickness: 2, + indent: 40, + ), + ListTile( + title: const Text('Register'), + leading: const Icon(Icons.add_box_outlined), + selected: _selectedIndex == 3, + onTap: () { + // Update the state of the app + _onItemTapped(3); + // Then close the drawer + Navigator.pushReplacementNamed(context, '/register'); + }, + ), + ListTile( + title: const Text('Login'), + leading: const Icon(Icons.login), + selected: _selectedIndex == 4, + onTap: () { + // Update the state of the app + _onItemTapped(4); + // Then close the drawer + Navigator.pushReplacementNamed(context, '/login'); + }, + ), + ], + ), + ), + body: widget.body, + ); + } +} diff --git a/Mobile/lib/login.dart b/Mobile/lib/login.dart index c5181bb..38ff346 100644 --- a/Mobile/lib/login.dart +++ b/Mobile/lib/login.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:mobile/base/sidemenu.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'register.dart'; import 'api.dart' as api; @@ -17,7 +18,8 @@ class _LoginPageState extends State { final passwordInput = TextEditingController(); Future _login() async { - final token = await api.request(context, api.ApiService.auth, 'POST', '/api/Users/login', { + final token = await api + .request(context, api.ApiService.auth, 'POST', '/api/Users/login', { 'email': emailInput.text, 'password': passwordInput.text, }); @@ -28,41 +30,44 @@ class _LoginPageState extends State { prefs.setString('token', token); if (mounted) { - ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Successfully logged in'))); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Successfully logged in'))); Navigator.pop(context); } } @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Text(widget.title), - ), - body: Center( - child: Container( - constraints: const BoxConstraints(minWidth: 100, maxWidth: 400), - child: Column( - children: [ - const SizedBox(height: 80), - const Text('Email'), - TextField(controller: emailInput), - const SizedBox(height: 30), - const Text('Password'), - TextField(controller: passwordInput, obscureText: true, enableSuggestions: false, autocorrect: false), - const SizedBox(height: 30), - ElevatedButton(onPressed: _login, child: const Text('Log ind')), - const SizedBox(height: 10), - TextButton( - child: const Text('Registrer konto'), - onPressed: () => Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const RegisterPage(title: 'Registrer'))), - ) - ] - ) - ) - ) - ); + return SideMenu( + body: Scaffold( + body: Center( + child: Container( + constraints: + const BoxConstraints(minWidth: 100, maxWidth: 400), + child: Column(children: [ + const SizedBox(height: 80), + const Text('Email'), + TextField(controller: emailInput), + const SizedBox(height: 30), + const Text('Password'), + TextField( + controller: passwordInput, + obscureText: true, + enableSuggestions: false, + autocorrect: false), + const SizedBox(height: 30), + ElevatedButton( + onPressed: _login, child: const Text('Log ind')), + const SizedBox(height: 10), + TextButton( + child: const Text('Registrer konto'), + onPressed: () => Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => + const RegisterPage(title: 'Registrer'))), + ) + ]))))); } @override diff --git a/Mobile/lib/main.dart b/Mobile/lib/main.dart index c7524f0..4b9eab4 100644 --- a/Mobile/lib/main.dart +++ b/Mobile/lib/main.dart @@ -2,7 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import "package:latlong2/latlong.dart"; import 'package:mobile/register.dart'; +import 'base/sidemenu.dart'; import "login.dart"; +import 'profile.dart'; void main() { runApp(const MyApp()); @@ -19,6 +21,15 @@ class MyApp extends StatelessWidget { useMaterial3: true, ), home: const MyHomePage(title: 'SkanTravels'), + initialRoute: '/', + routes: { + '/home': (context) => const MyHomePage( + title: 'SkasdanTravels', + ), + '/profile': (context) => const ProfilePage(), + '/login': (context) => const LoginPage(title: 'SkanTravels'), + '/register': (context) => const RegisterPage(title: 'SkanTravels'), + }, ); } } @@ -33,128 +44,51 @@ class MyHomePage extends StatefulWidget { } class _MyHomePageState extends State { - int _selectedIndex = 0; - - void _onItemTapped(int index) { - setState(() { - _selectedIndex = index; - }); - } - @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Text(widget.title), - ), - drawer: navigationMenu, - body: FlutterMap( - options: const MapOptions( - initialCenter: LatLng(55.9397, 9.5156), initialZoom: 7.0), - children: [ - TileLayer( - urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', - userAgentPackageName: 'dev.fleaflet.flutter_map.example', - ) - ], - ), - floatingActionButton: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - FloatingActionButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const LoginPage(title: "Login"))); - }, - tooltip: 'Login', - child: const Icon(Icons.login), - ), - ], - ), - ); - } - - Drawer get navigationMenu => Drawer( - child: ListView( - padding: EdgeInsets.zero, + return SideMenu( + body: Scaffold( + body: FlutterMap( + options: const MapOptions( + initialCenter: LatLng(55.9397, 9.5156), initialZoom: 7.0), children: [ - const DrawerHeader( - decoration: BoxDecoration( - color: Colors.blue, + openStreetMapTileLayer, + const MarkerLayer(markers: [ + Marker( + point: LatLng(56.465511, 9.411366), + width: 60, + height: 100, + alignment: Alignment.center, + child: Icon( + Icons.location_pin, + size: 60, + color: Colors.purple, + ), ), - child: Text('Drawer Header'), - ), - ListTile( - title: const Text('Home'), - leading: const Icon(Icons.home), - selected: _selectedIndex == 0, - onTap: () { - // Update the state of the app - _onItemTapped(0); - // Then close the drawer - Navigator.pop(context); - }, - ), - ListTile( - title: const Text('Favourites'), - leading: const Icon(Icons.star), - selected: _selectedIndex == 1, - onTap: () { - // Update the state of the app - _onItemTapped(1); - // Then close the drawer - Navigator.pop(context); - }, - ), - ListTile( - title: const Text('Profile'), - leading: const Icon(Icons.person), - selected: _selectedIndex == 2, - onTap: () { - // Update the state of the app - _onItemTapped(2); - // Then close the drawer - Navigator.pop(context); - }, - ), - const Divider( - color: Colors.grey, - thickness: 2, - indent: 40, - ), - ListTile( - title: const Text('Register'), - leading: const Icon(Icons.add_box_outlined), - selected: _selectedIndex == 3, - onTap: () { - // Update the state of the app - _onItemTapped(3); - // Then close the drawer - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - const RegisterPage(title: "Register"))); - }, - ), - ListTile( - title: const Text('Login'), - leading: const Icon(Icons.login), - selected: _selectedIndex == 4, - onTap: () { - // Update the state of the app - _onItemTapped(4); - // Then close the drawer + ]), + ], + ), + floatingActionButton: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + FloatingActionButton( + onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => const LoginPage(title: "Login"))); }, + tooltip: 'Login', + child: const Icon(Icons.login), ), ], ), + ), + ); + } + + TileLayer get openStreetMapTileLayer => TileLayer( + urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', + userAgentPackageName: 'dev.fleaflet.flutter_map.example', ); } diff --git a/Mobile/lib/profile.dart b/Mobile/lib/profile.dart index 8b13789..7b8fcae 100644 --- a/Mobile/lib/profile.dart +++ b/Mobile/lib/profile.dart @@ -1 +1,15 @@ +import 'package:flutter/material.dart'; +import 'base/sidemenu.dart'; // Import the base layout widget +class ProfilePage extends StatelessWidget { + const ProfilePage({super.key}); + + @override + Widget build(BuildContext context) { + return const SideMenu( + body: Center( + child: Text('This is Page 1'), + ), + ); + } +} diff --git a/Mobile/lib/register.dart b/Mobile/lib/register.dart index 6c72e4b..e78440a 100644 --- a/Mobile/lib/register.dart +++ b/Mobile/lib/register.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:mobile/base/sidemenu.dart'; import 'login.dart'; import 'api.dart' as api; @@ -17,7 +18,8 @@ class _RegisterPageState extends State { final passwordInput = TextEditingController(); Future _register() async { - final result = await api.request(context, api.ApiService.auth, 'POST', '/api/Users', { + final result = + await api.request(context, api.ApiService.auth, 'POST', '/api/Users', { 'username': usernameInput.text, 'email': emailInput.text, 'password': passwordInput.text, @@ -26,44 +28,49 @@ class _RegisterPageState extends State { if (result == null) return; if (mounted) { - ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Successfully registered, please login'))); - Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const LoginPage(title: 'Log ind'))); + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text('Successfully registered, please login'))); + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => const LoginPage(title: 'Log ind'))); } } @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Text(widget.title), - ), - body: Center( - child: Container( - constraints: const BoxConstraints(minWidth: 100, maxWidth: 400), - child: Column( - children: [ - const SizedBox(height: 80), - const Text('Brugernavn'), - TextField(controller: usernameInput), - const SizedBox(height: 30), - const Text('Email'), - TextField(controller: emailInput), - const SizedBox(height: 30), - const Text('Password'), - TextField(controller: passwordInput, obscureText: true, enableSuggestions: false, autocorrect: false), - const SizedBox(height: 30), - ElevatedButton(onPressed: _register, child: const Text('Registrer')), - const SizedBox(height: 10), - TextButton( - child: const Text('Log ind'), - onPressed: () => Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const LoginPage(title: 'Log ind'))) - ), - ] - ) - ) - ) - ); + return SideMenu( + body: Scaffold( + body: Center( + child: Container( + constraints: + const BoxConstraints(minWidth: 100, maxWidth: 400), + child: Column(children: [ + const SizedBox(height: 80), + const Text('Brugernavn'), + TextField(controller: usernameInput), + const SizedBox(height: 30), + const Text('Email'), + TextField(controller: emailInput), + const SizedBox(height: 30), + const Text('Password'), + TextField( + controller: passwordInput, + obscureText: true, + enableSuggestions: false, + autocorrect: false), + const SizedBox(height: 30), + ElevatedButton( + onPressed: _register, child: const Text('Registrer')), + const SizedBox(height: 10), + TextButton( + child: const Text('Log ind'), + onPressed: () => Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => + const LoginPage(title: 'Log ind')))), + ]))))); } @override