import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../domain/mission/mission_warnings.dart'; import '../providers/active_drone_profile_provider.dart'; import '../providers/mission_meta_provider.dart'; import 'missions_drones_panel.dart'; /// Statuszeile am unteren Bildschirmrand (HTML-Demonstrator: #bottomBar/ /// #statsRow). Details-Pille (mittig) oeffnet die Wegpunktliste; die /// Mission-/Drohnen-Chips (links) oeffnen das Verwaltungsmenue mit dem /// passenden Starttab (HTML-Demonstrator: #missionNameBtn/#droneNameBtn). /// Der Send-Button ist bewusst nicht Teil dieses Schritts - die dafuer /// noetige Upload-Anbindung existiert noch nicht. class BottomStatsBar extends ConsumerWidget { const BottomStatsBar({ super.key, required this.waypointCount, required this.totalDistanceM, required this.totalDurationSec, required this.onTap, required this.onSettingsTap, this.warnings = const [], this.onWarningsTap, }); final int waypointCount; final double totalDistanceM; final double totalDurationSec; final VoidCallback onTap; /// Oeffnet das Settings-Menue (runder Zahnrad-Knopf rechts der /// Details-Pille). final VoidCallback onSettingsTap; /// Aktive Warnungen zur Mission (Doku 3.10) - der Button erscheint nur, /// solange diese Liste nicht leer ist (HTML-Demonstrator: #warningsBtn, /// per default versteckt). final List warnings; final VoidCallback? onWarningsTap; @override Widget build(BuildContext context, WidgetRef ref) { final missionName = ref.watch(currentMissionMetaProvider).name; final droneName = ref.watch(activeDroneProfileProvider).name; // Row statt Stack: ein Align/Center ohne width-/heightFactor nimmt sich // immer den gesamten verfuegbaren Platz seines Elternwidgets (auch wenn // sein Kind viel kleiner ist) - in einem Stack ohne begrenzende // Positioned-Kinder blaeht das dessen eigene Groesse unkontrolliert auf // und verschiebt die Details-Pille aus ihrer sichtbaren Position. // Zwei gleich grosse Expanded-Bereiche links/rechts der Pille halten sie // dagegen zuverlaessig zentriert. return SafeArea( top: false, child: Padding( padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 12), child: Row( children: [ Expanded( child: Align( alignment: Alignment.centerLeft, child: Row( children: [ Flexible( child: _NameChip( label: 'Mission: $missionName', color: Colors.white.withValues(alpha: 0.12), textColor: Colors.white, maxWidth: 160, onTap: () => Navigator.of(context).push(MaterialPageRoute( builder: (_) => const MissionsDronesPanel.missions(), )), ), ), const SizedBox(width: 6), Flexible( child: _NameChip( label: 'Drone: $droneName', color: const Color(0xFF4D9DFF).withValues(alpha: 0.18), textColor: const Color(0xFFCFE2FF), maxWidth: 140, onTap: () => Navigator.of(context).push(MaterialPageRoute( builder: (_) => const MissionsDronesPanel.drones(), )), ), ), ], ), ), ), _detailsPill(), Expanded( child: Align( alignment: Alignment.centerRight, child: Row( mainAxisSize: MainAxisSize.min, children: [ if (warnings.isNotEmpty) ...[ _WarningButton(onTap: onWarningsTap), const SizedBox(width: 6), ], _SettingsButton(onTap: onSettingsTap), ], ), ), ), ], ), ), ); } Widget _detailsPill() { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 9), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(20), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Text( 'Details:', style: TextStyle( color: Colors.white70, fontWeight: FontWeight.w600, fontSize: 14, ), ), const SizedBox(width: 10), const Icon(Icons.flag, size: 14, color: Colors.white), const SizedBox(width: 4), Text('$waypointCount WP', style: const TextStyle(color: Colors.white, fontSize: 14)), const SizedBox(width: 14), const Icon(Icons.straighten, size: 14, color: Colors.white), const SizedBox(width: 4), Text('${totalDistanceM.round()} m', style: const TextStyle(color: Colors.white, fontSize: 14)), const SizedBox(width: 14), const Icon(Icons.access_time, size: 14, color: Colors.white), const SizedBox(width: 4), Text(_fmtDuration(totalDurationSec), style: const TextStyle(color: Colors.white, fontSize: 14)), ], ), ), ); } String _fmtDuration(double seconds) { final total = seconds.round(); final minutes = total ~/ 60; final secs = total % 60; return '$minutes:${secs.toString().padLeft(2, '0')}'; } } /// Kleiner, roter Rundknopf fuer aktive Warnungen (Doku 3.10, HTML- /// Demonstrator: #warningsBtn) - oeffnet die Warnungsliste. class _WarningButton extends StatelessWidget { const _WarningButton({required this.onTap}); final VoidCallback? onTap; @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( width: 34, height: 34, decoration: BoxDecoration( shape: BoxShape.circle, color: const Color(0xFFE2574A).withValues(alpha: 0.18), border: Border.all(color: const Color(0xFFE2574A).withValues(alpha: 0.5)), ), child: const Icon(Icons.warning_amber_rounded, color: Color(0xFFFFB3A8), size: 18), ), ); } } /// Runder Zahnrad-Knopf rechts der Details-Pille - oeffnet das /// Settings-Menue (SettingsScreen). class _SettingsButton extends StatelessWidget { const _SettingsButton({required this.onTap}); final VoidCallback onTap; @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( width: 34, height: 34, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withValues(alpha: 0.12), ), child: const Icon(Icons.settings, color: Colors.white, size: 18), ), ); } } class _NameChip extends StatelessWidget { const _NameChip({ required this.label, required this.color, required this.textColor, required this.onTap, required this.maxWidth, }); final String label; final Color color; final Color textColor; final VoidCallback onTap; final double maxWidth; @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: ConstrainedBox( constraints: BoxConstraints(maxWidth: maxWidth), child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 7), decoration: BoxDecoration( color: color, borderRadius: BorderRadius.circular(14), ), child: Text( label, overflow: TextOverflow.ellipsis, maxLines: 1, style: TextStyle( color: textColor, fontWeight: FontWeight.w600, fontSize: 12, ), ), ), ), ); } }