cyberhybridhub/lib/services/questions_api_service.dart

128 lines
3.7 KiB
Dart

import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import '../config/api_config.dart';
import '../models/incoming_question.dart';
import 'auth_service.dart';
/// HTTP client for question queue, answers, and deferrals.
class QuestionsApiService {
QuestionsApiService({http.Client? client}) : _client = client ?? http.Client();
final http.Client _client;
/// Ensures a starter question exists for the signed-in user (login only).
Future<IncomingQuestion?> bootstrapOnLogin() async {
final String? token = await AuthService.instance.getIdToken();
if (token == null) {
return null;
}
final http.Response response = await _client.post(
Uri.parse('$apiBaseUrl/v1/me/questions/bootstrap'),
headers: _authHeaders(token),
);
if (response.statusCode != 200) {
debugPrint(
'bootstrapOnLogin failed: ${response.statusCode} ${response.body}',
);
return null;
}
final Map<String, dynamic> body =
jsonDecode(response.body) as Map<String, dynamic>;
final Map<String, dynamic>? questionJson =
body['question'] as Map<String, dynamic>?;
if (questionJson == null) {
return null;
}
return IncomingQuestion.fromJson(questionJson);
}
Future<List<IncomingQuestion>> fetchUnanswered() async {
final String? token = await AuthService.instance.getIdToken();
if (token == null) {
return <IncomingQuestion>[];
}
final http.Response response = await _client.get(
Uri.parse('$apiBaseUrl/v1/me/questions'),
headers: _authHeaders(token),
);
if (response.statusCode != 200) {
debugPrint(
'fetchUnanswered failed: ${response.statusCode} ${response.body}',
);
return <IncomingQuestion>[];
}
final Map<String, dynamic> body =
jsonDecode(response.body) as Map<String, dynamic>;
final List<dynamic> raw = body['questions'] as List<dynamic>? ?? <dynamic>[];
return raw
.map(
(dynamic item) =>
IncomingQuestion.fromJson(item as Map<String, dynamic>),
)
.toList();
}
Future<int?> submitAnswer({
required String questionId,
num answer = 0,
}) async {
final String? token = await AuthService.instance.getIdToken();
if (token == null) {
return null;
}
final http.Response response = await _client.post(
Uri.parse('$apiBaseUrl/v1/me/questions/$questionId/answer'),
headers: _authHeaders(token),
body: jsonEncode(<String, num>{'answer': answer}),
);
if (response.statusCode != 200) {
debugPrint(
'submitAnswer failed: ${response.statusCode} ${response.body}',
);
return null;
}
final Map<String, dynamic> body =
jsonDecode(response.body) as Map<String, dynamic>;
return (body['unansweredCount'] as num?)?.toInt();
}
Future<int?> deferQuestion({required String questionId}) async {
final String? token = await AuthService.instance.getIdToken();
if (token == null) {
return null;
}
final http.Response response = await _client.post(
Uri.parse('$apiBaseUrl/v1/me/questions/$questionId/defer'),
headers: _authHeaders(token),
);
if (response.statusCode != 200) {
debugPrint(
'deferQuestion failed: ${response.statusCode} ${response.body}',
);
return null;
}
final Map<String, dynamic> body =
jsonDecode(response.body) as Map<String, dynamic>;
return (body['unansweredCount'] as num?)?.toInt();
}
Map<String, String> _authHeaders(String token) {
return <String, String>{
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
}
}