Compare commits
2 Commits
a082441826
...
debbddd05b
Author | SHA1 | Date | |
---|---|---|---|
debbddd05b | |||
c9769fcada |
2
Mobile/.gitignore
vendored
2
Mobile/.gitignore
vendored
@ -41,3 +41,5 @@ app.*.map.json
|
|||||||
/android/app/debug
|
/android/app/debug
|
||||||
/android/app/profile
|
/android/app/profile
|
||||||
/android/app/release
|
/android/app/release
|
||||||
|
|
||||||
|
environment.json
|
||||||
|
7
Mobile/.run/main.dart.run.xml
Normal file
7
Mobile/.run/main.dart.run.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="main.dart" type="FlutterRunConfigurationType" factoryName="Flutter">
|
||||||
|
<option name="additionalArgs" value="--dart-define-from-file environment.json" />
|
||||||
|
<option name="filePath" value="$PROJECT_DIR$/lib/main.dart" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
15
Mobile/.vscode/launch.json
vendored
Normal file
15
Mobile/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Launch",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "dart",
|
||||||
|
"program": "lib/main.dart",
|
||||||
|
"args": [
|
||||||
|
"--dart-define-from-file",
|
||||||
|
"environment.json"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
6
Mobile/README.md
Normal file
6
Mobile/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# SkanTravels frontend
|
||||||
|
|
||||||
|
### Running
|
||||||
|
|
||||||
|
- Copy `environment.example.json` to `environment.json` and fill out the values
|
||||||
|
- Run `flutter run --dart-define-from-file environment.json`
|
@ -1,4 +1,6 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="mobile"
|
android:label="mobile"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
|
4
Mobile/environment.example.json
Normal file
4
Mobile/environment.example.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"AUTH_SERVICE_HOST": "http://localhost:5287",
|
||||||
|
"APP_SERVICE_HOST": "http://localhost:8080"
|
||||||
|
}
|
53
Mobile/lib/api.dart
Normal file
53
Mobile/lib/api.dart
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
enum ApiService {
|
||||||
|
auth,
|
||||||
|
app,
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> request(BuildContext context, ApiService service, String method, String path, Object? body) async {
|
||||||
|
final messenger = ScaffoldMessenger.of(context);
|
||||||
|
|
||||||
|
final host = switch (service) {
|
||||||
|
ApiService.auth => const String.fromEnvironment('AUTH_SERVICE_HOST'),
|
||||||
|
ApiService.app => const String.fromEnvironment('APP_SERVICE_HOST'),
|
||||||
|
};
|
||||||
|
|
||||||
|
final http.Response response;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (method == 'GET') {
|
||||||
|
response = await http.get(Uri.parse(host + path));
|
||||||
|
} else {
|
||||||
|
final function = switch (method) {
|
||||||
|
'POST' => http.post,
|
||||||
|
'PUT' => http.put,
|
||||||
|
'DELETE' => http.delete,
|
||||||
|
_ => throw const FormatException('Invalid method'),
|
||||||
|
};
|
||||||
|
|
||||||
|
response = await function(
|
||||||
|
Uri.parse(host + path),
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: body != null ? jsonEncode(body) : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
messenger.showSnackBar(const SnackBar(content: Text('Unable to connect to server')));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode < 200 || response.statusCode >= 300) {
|
||||||
|
try {
|
||||||
|
final json = jsonDecode(response.body);
|
||||||
|
messenger.showSnackBar(SnackBar(content: Text(json['message'])));
|
||||||
|
} catch (_) {
|
||||||
|
messenger.showSnackBar(SnackBar(content: Text('Something went wrong (HTTP ${response.statusCode})')));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.body;
|
||||||
|
}
|
@ -1,5 +1,9 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'register.dart';
|
import 'register.dart';
|
||||||
|
import 'api.dart' as api;
|
||||||
|
|
||||||
class LoginPage extends StatefulWidget {
|
class LoginPage extends StatefulWidget {
|
||||||
const LoginPage({super.key, required this.title});
|
const LoginPage({super.key, required this.title});
|
||||||
@ -11,6 +15,26 @@ class LoginPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _LoginPageState extends State<LoginPage> {
|
class _LoginPageState extends State<LoginPage> {
|
||||||
|
final emailInput = TextEditingController();
|
||||||
|
final passwordInput = TextEditingController();
|
||||||
|
|
||||||
|
Future<void> _login() async {
|
||||||
|
final token = await api.request(context, api.ApiService.auth, 'POST', '/api/Users/login', {
|
||||||
|
'email': emailInput.text,
|
||||||
|
'password': passwordInput.text,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (token == null) return;
|
||||||
|
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
prefs.setString('token', token);
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Successfully logged in')));
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -25,16 +49,16 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 80),
|
const SizedBox(height: 80),
|
||||||
const Text('Email'),
|
const Text('Email'),
|
||||||
const TextField(),
|
TextField(controller: emailInput),
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
const Text('Password'),
|
const Text('Password'),
|
||||||
const TextField(obscureText: true, enableSuggestions: false, autocorrect: false),
|
TextField(controller: passwordInput, obscureText: true, enableSuggestions: false, autocorrect: false),
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
ElevatedButton(child: const Text('Log ind'), onPressed: () => Navigator.pop(context)),
|
ElevatedButton(onPressed: _login, child: const Text('Log ind')),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
TextButton(
|
TextButton(
|
||||||
child: const Text('Registrer konto'),
|
child: const Text('Registrer konto'),
|
||||||
onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (context) => const RegisterPage(title: 'Registrer'))),
|
onPressed: () => Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const RegisterPage(title: 'Registrer'))),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -42,4 +66,11 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
emailInput.dispose();
|
||||||
|
passwordInput.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
|||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
TextButton(
|
TextButton(
|
||||||
child: const Text('Log ind'),
|
child: const Text('Log ind'),
|
||||||
onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (context) => const LoginPage(title: 'Log ind')))
|
onPressed: () => Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const LoginPage(title: 'Log ind')))
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
import shared_preferences_foundation
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,7 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.network.server</key>
|
<key>com.apple.security.network.server</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -4,5 +4,7 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.app-sandbox</key>
|
<key>com.apple.security.app-sandbox</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -65,6 +65,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
version: "1.3.1"
|
||||||
|
ffi:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ffi
|
||||||
|
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.3"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -91,6 +107,11 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_web_plugins:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
http:
|
http:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -211,6 +232,46 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.0"
|
version: "1.9.0"
|
||||||
|
path_provider_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_linux
|
||||||
|
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
|
path_provider_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_platform_interface
|
||||||
|
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
path_provider_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_windows
|
||||||
|
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.0"
|
||||||
|
platform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: platform
|
||||||
|
sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.5"
|
||||||
|
plugin_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: plugin_platform_interface
|
||||||
|
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.8"
|
||||||
polylabel:
|
polylabel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -227,6 +288,62 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.0"
|
||||||
|
shared_preferences:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: shared_preferences
|
||||||
|
sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
shared_preferences_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_android
|
||||||
|
sha256: a7e8467e9181cef109f601e3f65765685786c1a738a83d7fbbde377589c0d974
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.1"
|
||||||
|
shared_preferences_foundation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_foundation
|
||||||
|
sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.2"
|
||||||
|
shared_preferences_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_linux
|
||||||
|
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
shared_preferences_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_platform_interface
|
||||||
|
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
shared_preferences_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_web
|
||||||
|
sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.2"
|
||||||
|
shared_preferences_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_windows
|
||||||
|
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -328,6 +445,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
|
xdg_directories:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xdg_directories
|
||||||
|
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.3.4 <4.0.0"
|
dart: ">=3.4.0 <4.0.0"
|
||||||
flutter: ">=3.18.0-18.0.pre.54"
|
flutter: ">=3.22.0"
|
||||||
|
@ -37,6 +37,7 @@ dependencies:
|
|||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.6
|
cupertino_icons: ^1.0.6
|
||||||
|
shared_preferences: ^2.3.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
# mobile
|
|
||||||
|
|
||||||
A new Flutter project.
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
This project is a starting point for a Flutter application.
|
|
||||||
|
|
||||||
A few resources to get you started if this is your first Flutter project:
|
|
||||||
|
|
||||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
|
||||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
|
||||||
|
|
||||||
For help getting started with Flutter development, view the
|
|
||||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
|
||||||
samples, guidance on mobile development, and a full API reference.
|
|
Loading…
Reference in New Issue
Block a user