73 lines
2.3 KiB
Dart
73 lines
2.3 KiB
Dart
import 'dart:convert';
|
||
import 'dart:html' as html;
|
||
|
||
/// API-клиент admin-консоли (spec 06 m08): токен в sessionStorage,
|
||
/// 401 → [UnauthorizedException] → экран логина.
|
||
class UnauthorizedException implements Exception {}
|
||
|
||
class Api {
|
||
static const _base = '';
|
||
static String? token = html.window.sessionStorage['adminToken'];
|
||
|
||
static bool get authorized => token != null && token!.isNotEmpty;
|
||
|
||
static void logout() {
|
||
token = null;
|
||
html.window.sessionStorage.remove('adminToken');
|
||
}
|
||
|
||
static Future<Map<String, dynamic>> login(
|
||
String login, String password) async {
|
||
final data = await _send('POST', '/api/admin/login',
|
||
body: {'login': login, 'password': password});
|
||
token = data['token'] as String;
|
||
html.window.sessionStorage['adminToken'] = token!;
|
||
return data;
|
||
}
|
||
|
||
static Future<dynamic> get(String path) => _send('GET', path);
|
||
|
||
static Future<dynamic> post(String path, [Map<String, dynamic>? body]) =>
|
||
_send('POST', path, body: body);
|
||
|
||
/// CSV — запрос с Bearer и Blob-download (spec 06 §2.3).
|
||
static Future<void> downloadCsv(String query) async {
|
||
final request = html.HttpRequest()
|
||
..open('GET', _base + query)
|
||
..responseType = 'blob'
|
||
..setRequestHeader('Authorization', 'Bearer $token');
|
||
await request.onLoad.first;
|
||
if (request.status == 401) {
|
||
logout();
|
||
throw UnauthorizedException();
|
||
}
|
||
final blob = request.response as html.Blob;
|
||
final url = html.Url.createObjectUrlFromBlob(blob);
|
||
html.AnchorElement(href: url)
|
||
..download = 'workouts.csv'
|
||
..click();
|
||
html.Url.revokeObjectUrl(url);
|
||
}
|
||
|
||
static Future<dynamic> _send(String method, String path,
|
||
{Map<String, dynamic>? body}) async {
|
||
final request = html.HttpRequest()
|
||
..open(method, _base + path)
|
||
..setRequestHeader('Content-Type', 'application/json');
|
||
if (token != null) {
|
||
request.setRequestHeader('Authorization', 'Bearer $token');
|
||
}
|
||
await request.onLoad.first;
|
||
// ignore: only_throw_errors
|
||
if (request.status == 401) {
|
||
logout();
|
||
throw UnauthorizedException();
|
||
}
|
||
if (request.status! >= 400) {
|
||
throw Exception('HTTP ${request.status}: ${request.responseText}');
|
||
}
|
||
final text = request.responseText ?? '';
|
||
return text.isEmpty ? <String, dynamic>{} : jsonDecode(text);
|
||
}
|
||
}
|