La carte « Où le guide est disponible » affichait la valeur entière de l'enum AppType (0, 1, 2…) au lieu d'un libellé. Réutilise les clés statsChannel* déjà traduites en FR/EN/NL pour l'écran Statistiques. L'activation de l'assistant par canal se réglait dans chaque onglet d'application, alors que le champ vit sur ApplicationInstance et se résout par (InstanceId, AppType). Le réglage passe dans la liste des canaux du Guide IA, où tous les canaux sont visibles au même endroit ; le paramètre showAssistant de AppConfigurationLinkScreen devient inutile. Les notifications de cet écran passaient par ScaffoldMessenger (en bas), contrairement au reste de l'application qui utilise showNotification (toastification, topRight). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
201 lines
6.3 KiB
Dart
201 lines
6.3 KiB
Dart
import 'package:collection/collection.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:manager_app/Screens/Applications/app_configuration_link_screen.dart';
|
|
import 'package:manager_app/app_context.dart';
|
|
import 'package:manager_app/Components/message_notification.dart';
|
|
import 'package:manager_app/constants.dart';
|
|
import 'package:manager_app/Models/managerContext.dart';
|
|
import 'package:manager_api_new/api.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
class WebInstanceLoader extends StatefulWidget {
|
|
const WebInstanceLoader({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
State<WebInstanceLoader> createState() => _WebInstanceLoaderState();
|
|
}
|
|
|
|
class _WebInstanceLoaderState extends State<WebInstanceLoader> {
|
|
bool _creating = false;
|
|
String? _error;
|
|
ApplicationInstanceDTO? _instance;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
WidgetsBinding.instance.addPostFrameCallback((_) => _init());
|
|
}
|
|
|
|
void _init() {
|
|
final appContext = Provider.of<AppContext>(context, listen: false);
|
|
final managerCtx = appContext.getContext() as ManagerAppContext;
|
|
final existing = managerCtx.instanceDTO?.applicationInstanceDTOs
|
|
?.firstWhereOrNull((ai) => ai.appType == AppType.Web);
|
|
if (existing != null) {
|
|
setState(() => _instance = existing);
|
|
}
|
|
}
|
|
|
|
Future<void> _create() async {
|
|
final appContext = Provider.of<AppContext>(context, listen: false);
|
|
final managerCtx = appContext.getContext() as ManagerAppContext;
|
|
final instanceDTO = managerCtx.instanceDTO!;
|
|
|
|
setState(() {
|
|
_creating = true;
|
|
_error = null;
|
|
});
|
|
|
|
try {
|
|
final newInstance = ApplicationInstanceDTO(
|
|
instanceId: instanceDTO.id,
|
|
appType: AppType.Web,
|
|
languages: ['fr'],
|
|
isAssistant: false,
|
|
);
|
|
|
|
final created = await managerCtx.clientAPI!.applicationInstanceApi!
|
|
.applicationInstanceCreate(newInstance);
|
|
|
|
if (created != null) {
|
|
instanceDTO.applicationInstanceDTOs = [...?instanceDTO.applicationInstanceDTOs, created];
|
|
setState(() => _instance = created);
|
|
} else {
|
|
setState(() => _error = 'La création a échoué (réponse vide)');
|
|
}
|
|
} catch (e) {
|
|
setState(() => _error = e.toString());
|
|
} finally {
|
|
setState(() => _creating = false);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (_instance != null) {
|
|
return WebAppScreen(applicationInstanceDTO: _instance!);
|
|
}
|
|
|
|
return Center(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text(
|
|
'L\'application web n\'est pas encore initialisée.',
|
|
style: TextStyle(color: kBodyTextColor),
|
|
),
|
|
if (_error != null) ...[
|
|
const SizedBox(height: 8),
|
|
Text(_error!, style: TextStyle(color: kError, fontSize: 12)),
|
|
],
|
|
const SizedBox(height: 16),
|
|
_creating
|
|
? const CircularProgressIndicator()
|
|
: ElevatedButton(
|
|
onPressed: _create,
|
|
child: const Text('Initialiser l\'application web'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class WebAppScreen extends StatelessWidget {
|
|
final ApplicationInstanceDTO applicationInstanceDTO;
|
|
|
|
const WebAppScreen({Key? key, required this.applicationInstanceDTO}) : super(key: key);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final appContext = Provider.of<AppContext>(context);
|
|
final managerAppContext = appContext.getContext() as ManagerAppContext;
|
|
final instanceDTO = managerAppContext.instanceDTO;
|
|
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
if (instanceDTO?.webSlug != null || instanceDTO?.publicApiKey != null)
|
|
Card(
|
|
margin: const EdgeInsets.fromLTRB(16, 8, 16, 8),
|
|
color: kWhite,
|
|
elevation: 0,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Accès web', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 21)),
|
|
const SizedBox(height: 12),
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Expanded(
|
|
child: _InfoRow(
|
|
label: 'URL visiteurs',
|
|
value: 'app.myinfomate.be/${instanceDTO?.webSlug ?? '—'}',
|
|
),
|
|
),
|
|
const SizedBox(width: 24),
|
|
Expanded(
|
|
child: _InfoRow(
|
|
label: 'Clé publique API',
|
|
value: instanceDTO?.publicApiKey ?? '—',
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
Expanded(
|
|
child: AppConfigurationLinkScreen(
|
|
applicationInstanceDTO: applicationInstanceDTO,
|
|
configTitle: 'Contenu de l\'application web',
|
|
appUpdatedLabel: 'Application web mise à jour',
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
class _InfoRow extends StatelessWidget {
|
|
final String label;
|
|
final String value;
|
|
|
|
const _InfoRow({required this.label, required this.value});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Row(
|
|
children: [
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(label, style: TextStyle(fontSize: 12, color: kBodyTextColor)),
|
|
const SizedBox(height: 2),
|
|
Text(
|
|
value,
|
|
style: TextStyle(fontSize: 13, fontFamily: 'monospace', color: kPrimaryColor),
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
IconButton(
|
|
icon: Icon(Icons.copy_outlined, size: 18, color: kPrimaryColor),
|
|
tooltip: 'Copier',
|
|
onPressed: () {
|
|
Clipboard.setData(ClipboardData(text: value));
|
|
showNotification(kSuccess, kWhite, 'Copié !', context, null);
|
|
},
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|