Initial commit

This commit is contained in:
2025-07-23 01:48:04 +01:00
parent f077873f02
commit 9fbdd97b15
133 changed files with 5363 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
class ApiService {
final String baseUrl;
ApiService({required this.baseUrl});
Future<dynamic> get(String endpoint, {Map<String, String>? headers}) async {
final response = await http.get(
Uri.parse('$baseUrl$endpoint'),
headers: headers,
);
return _processResponse(response);
}
Future<dynamic> post(
String endpoint,
dynamic data, {
Map<String, String>? headers,
}) async {
final response = await http.post(
Uri.parse('$baseUrl$endpoint'),
headers: _jsonHeaders(headers),
body: jsonEncode(data),
);
return _processResponse(response);
}
Future<dynamic> postForm(String endpoint, Map<String, String> data) async {
final response = await http.post(
Uri.parse('$baseUrl$endpoint'),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'accept': 'application/json',
},
body: data, // http package handles form-encoding for Map<String, String>
);
return _processResponse(response);
}
Future<dynamic> put(
String endpoint,
dynamic data, {
Map<String, String>? headers,
}) async {
final response = await http.put(
Uri.parse('$baseUrl$endpoint'),
headers: _jsonHeaders(headers),
body: jsonEncode(data),
);
return _processResponse(response);
}
Future<dynamic> delete(
String endpoint, {
Map<String, String>? headers,
}) async {
final response = await http.delete(
Uri.parse('$baseUrl$endpoint'),
headers: headers,
);
return _processResponse(response);
}
Map<String, String> _jsonHeaders(Map<String, String>? extra) {
return {'Content-Type': 'application/json', if (extra != null) ...extra};
}
dynamic _processResponse(http.Response res) {
final body = res.body.isNotEmpty ? jsonDecode(res.body) : null;
if (res.statusCode >= 200 && res.statusCode < 300) {
return body;
} else {
throw Exception('API error ${res.statusCode}: $body');
}
}
}

View File

@@ -0,0 +1,68 @@
import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart';
import 'package:mileograph_flutter/objects/objects.dart';
import 'package:mileograph_flutter/services/apiService.dart';
class AuthService extends ChangeNotifier {
final ApiService api;
AuthService({required this.api});
AuthenticatedUserData? _user;
bool get isLoggedIn => _user != null;
String? get token => _user?.access_token;
String? get userId => _user?.user_id;
String? get username => _user?.username;
String? get fullName => _user?.full_name;
void setLoginData({
required String userId,
required String username,
required String fullName,
required String accessToken,
required String email,
}) {
_user = AuthenticatedUserData(
user_id: userId,
username: username,
full_name: fullName,
access_token: accessToken,
email: email,
);
notifyListeners();
}
Future<void> login(String username, String password) async {
final formData = {
'grant_type': 'password',
'username': username,
'password': password,
'scope': '',
'client_id': 'string',
'client_secret': 'string',
};
// 1. Get token
final tokenResponse = await api.postForm('/token', formData);
final accessToken = tokenResponse['access_token'];
// 2. Get user details
final userResponse = await api.get(
'/users/me',
headers: {
'Authorization': 'Bearer $accessToken',
'accept': 'application/json',
},
);
// 3. Populate state
setLoginData(
userId: userResponse['user_id'],
username: userResponse['username'],
fullName: userResponse['full_name'],
accessToken: accessToken,
email: userResponse['email'],
);
}
}