131 lines
4.3 KiB
Dart
131 lines
4.3 KiB
Dart
// lib/services/saha/saha_service.dart
|
|
//
|
|
// Small client for the panel's `/delphi/my-forms` endpoint. Used from the
|
|
// home explore state to decide whether to render a Saha section (and to seed
|
|
// it with one card per panel). The card tap opens the existing `/saha`
|
|
// WebView page on the panel origin.
|
|
|
|
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io' show SocketException;
|
|
|
|
import 'package:flutter/foundation.dart' show debugPrint;
|
|
|
|
// ignore: depend_on_referenced_packages
|
|
import 'package:http/http.dart' as http;
|
|
|
|
import 'package:didvan/config/auth_config.dart';
|
|
import 'package:didvan/services/auth/token_storage.dart';
|
|
|
|
class SahaPanel {
|
|
final String id;
|
|
final String title;
|
|
final String? description;
|
|
final String? type;
|
|
|
|
const SahaPanel({
|
|
required this.id,
|
|
required this.title,
|
|
this.description,
|
|
this.type,
|
|
});
|
|
|
|
factory SahaPanel.fromJson(Map<String, dynamic> json) => SahaPanel(
|
|
id: json['id'] as String,
|
|
title: (json['title'] ?? '') as String,
|
|
description: json['description'] as String?,
|
|
type: json['type'] as String?,
|
|
);
|
|
}
|
|
|
|
class SahaService {
|
|
SahaService._();
|
|
static final SahaService instance = SahaService._();
|
|
|
|
static const _timeout = Duration(seconds: 15);
|
|
String get _base => AuthConfig.apiBaseUrl;
|
|
|
|
Future<List<SahaPanel>> fetchMyPanels() async {
|
|
final token = TokenStorage.accessToken;
|
|
if (token == null || token.isEmpty) {
|
|
debugPrint('🗳️ SAHA: no access token in TokenStorage');
|
|
return [];
|
|
}
|
|
try {
|
|
final res = await http.get(
|
|
Uri.parse('$_base/delphi/my-forms'),
|
|
headers: {
|
|
'Accept': 'application/json',
|
|
'Authorization': 'Bearer $token',
|
|
},
|
|
).timeout(_timeout);
|
|
if (res.statusCode != 200) {
|
|
final body = res.body.length > 300 ? res.body.substring(0, 300) : res.body;
|
|
debugPrint('🗳️ SAHA: my-forms HTTP ${res.statusCode}: $body');
|
|
return [];
|
|
}
|
|
final decoded = json.decode(res.body);
|
|
if (decoded is List) {
|
|
return decoded
|
|
.whereType<Map>()
|
|
.map((m) => SahaPanel.fromJson(Map<String, dynamic>.from(m)))
|
|
.toList();
|
|
}
|
|
debugPrint('🗳️ SAHA: my-forms returned non-list payload: '
|
|
'${res.body.length > 300 ? res.body.substring(0, 300) : res.body}');
|
|
return [];
|
|
} on TimeoutException {
|
|
debugPrint('🗳️ SAHA: my-forms timed out');
|
|
return [];
|
|
} on SocketException catch (e) {
|
|
debugPrint('🗳️ SAHA: my-forms network error: $e');
|
|
return [];
|
|
} catch (e) {
|
|
debugPrint('🗳️ SAHA: fetchMyPanels error: $e');
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/// Signs a magic-link invite token for the current Keycloak user on a
|
|
/// specific panel and returns the ready-to-open respondent URL, or null
|
|
/// on failure. The URL points at the panel origin so `Routes.web` can
|
|
/// open it in the cookie-injecting WebView.
|
|
Future<String?> buildMyPanelUrl(String panelId) async {
|
|
final token = TokenStorage.accessToken;
|
|
if (token == null || token.isEmpty) {
|
|
debugPrint('🗳️ SAHA: my-link no access token');
|
|
return null;
|
|
}
|
|
try {
|
|
final res = await http.post(
|
|
Uri.parse('$_base/delphi/forms/$panelId/my-link'),
|
|
headers: {
|
|
'Accept': 'application/json',
|
|
'Authorization': 'Bearer $token',
|
|
},
|
|
).timeout(_timeout);
|
|
if (res.statusCode != 200 && res.statusCode != 201) {
|
|
final body = res.body.length > 300 ? res.body.substring(0, 300) : res.body;
|
|
debugPrint('🗳️ SAHA: my-link HTTP ${res.statusCode}: $body');
|
|
return null;
|
|
}
|
|
final decoded = json.decode(res.body);
|
|
if (decoded is! Map || decoded['token'] is! String) {
|
|
debugPrint('🗳️ SAHA: my-link bad payload: ${res.body}');
|
|
return null;
|
|
}
|
|
final t = Uri.encodeComponent(decoded['token'] as String);
|
|
return 'https://app.didvan.com/panel/delphi/forms/user/$panelId?token=$t';
|
|
} on TimeoutException {
|
|
debugPrint('🗳️ SAHA: my-link timed out');
|
|
return null;
|
|
} on SocketException catch (e) {
|
|
debugPrint('🗳️ SAHA: my-link network error: $e');
|
|
return null;
|
|
} catch (e) {
|
|
debugPrint('🗳️ SAHA: buildMyPanelUrl error: $e');
|
|
return null;
|
|
}
|
|
}
|
|
}
|