feat: section preprod (env prod/preprod) + intégration ANTS (prod+preprod, jeu web)
Build APK / build (push) Successful in 2m27s

- servers groupés par environnement (Production / Preprod) avec en-têtes
- ANTS prod (ants-web) + preprod (ants-web-rd) intégrés : jeu web, bouton Ouvrir
- The Cycle preprod (the-cycle-api-rd) ajouté
- badge PREPROD sur les cartes concernées, thème ANTS (fourmi/ambre)
- supprime le widget_test.dart par défaut (cassé, non compilé dans l'APK)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
neckfire
2026-07-13 11:28:22 +02:00
co-authored by Claude Opus 4.8
parent 6b7287cefd
commit 25890d7bbc
3 changed files with 119 additions and 16 deletions
+60 -7
View File
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import '../models.dart';
@@ -41,13 +42,23 @@ class ServerCard extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(server.name,
style: const TextStyle(
color: Colors.white,
fontSize: 19,
fontWeight: FontWeight.w800),
maxLines: 1,
overflow: TextOverflow.ellipsis),
Row(
children: [
Flexible(
child: Text(server.name,
style: const TextStyle(
color: Colors.white,
fontSize: 19,
fontWeight: FontWeight.w800),
maxLines: 1,
overflow: TextOverflow.ellipsis),
),
if (server.isPreprod) ...[
const SizedBox(width: 8),
const _Tag(label: 'PREPROD'),
],
],
),
if (server.subtitle != null)
Text(server.subtitle!,
style: TextStyle(
@@ -80,6 +91,10 @@ class ServerCard extends StatelessWidget {
)
else
const Spacer(),
if (server.web && server.openUrl != null) ...[
_OpenButton(url: server.openUrl!),
const SizedBox(width: 8),
],
_ToggleButton(up: server.isUp, busy: busy, onToggle: onToggle),
],
),
@@ -118,6 +133,44 @@ class _Icon extends StatelessWidget {
);
}
class _Tag extends StatelessWidget {
const _Tag({required this.label});
final String label;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 2),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.28),
borderRadius: BorderRadius.circular(6),
border: Border.all(color: Colors.white.withOpacity(0.5), width: 1),
),
child: Text(label,
style: const TextStyle(
color: Colors.white, fontSize: 10, fontWeight: FontWeight.w800, letterSpacing: 0.6)),
);
}
}
class _OpenButton extends StatelessWidget {
const _OpenButton({required this.url});
final String url;
@override
Widget build(BuildContext context) {
return OutlinedButton.icon(
onPressed: () => launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication),
style: OutlinedButton.styleFrom(
foregroundColor: Colors.white,
side: BorderSide(color: Colors.white.withOpacity(0.7)),
),
icon: const Icon(Icons.open_in_new, size: 18),
label: const Text('Ouvrir'),
);
}
}
class _StatusPill extends StatelessWidget {
const _StatusPill({required this.label, required this.color, required this.pulse});
final String label;