import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:terepi_seged/pages/tracking/presentation/controllers/tracking_controller.dart'; import 'tracking_sheet.dart'; /// Kompakt tracking státusz kártya a térkép bal felső sarkában. /// /// Rögzítés közben: idő, távolság, pontok + szünet/stop gombok /// Rögzítésen kívül: egyetlen start gomb /// /// Mindig látható — tap → TrackingSheet (teljes lista + vezérlők) class TrackInfoCard extends StatelessWidget { const TrackInfoCard({super.key}); @override Widget build(BuildContext context) { return Obx(() { final ctrl = TrackingController.to; final isRec = ctrl.isRecording.value; return GestureDetector( onTap: () => _openSheet(context), child: Container( constraints: const BoxConstraints(minWidth: 140), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), decoration: BoxDecoration( color: Colors.black.withOpacity(0.72), borderRadius: BorderRadius.circular(10), border: Border.all( color: isRec ? Colors.red.withOpacity(0.5) : Colors.white.withOpacity(0.12), ), ), child: isRec ? _RecordingContent(ctrl: ctrl) : _IdleContent(), ), ); }); } void _openSheet(BuildContext context) { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (_) => const TrackingSheet(), ); } } // ─── Rögzítés közben ────────────────────────────────────────────────────────── class _RecordingContent extends StatelessWidget { final TrackingController ctrl; const _RecordingContent({required this.ctrl}); @override Widget build(BuildContext context) { return Obx(() => Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Fejléc sor — piros pont + "REC" vagy "SZÜNET" Row(mainAxisSize: MainAxisSize.min, children: [ _StatusDot(paused: ctrl.isPaused.value), const SizedBox(width: 5), Text( ctrl.isPaused.value ? 'SZÜNET' : 'REC', style: TextStyle( color: ctrl.isPaused.value ? Colors.orange : Colors.red, fontSize: 11, fontWeight: FontWeight.w700, letterSpacing: 0.5, ), ), const Spacer(), // Kártya bezárása (csak megkisebbíti, nem állítja le) GestureDetector( onTap: () {}, // placeholder — a kártya mindig látható child: Icon(Icons.unfold_less, size: 14, color: Colors.white.withOpacity(0.3)), ), ]), const SizedBox(height: 4), // Statisztika sor Row( mainAxisSize: MainAxisSize.min, children: [ _MiniStat( icon: Icons.timer_outlined, value: ctrl.elapsedFormatted.value, ), const SizedBox(width: 10), _MiniStat( icon: Icons.route, value: _fmtDist(ctrl.sessionDistance.value), ), const SizedBox(width: 10), _MiniStat( icon: Icons.location_on_outlined, value: '${ctrl.livePoints.length}', ), ], ), const SizedBox(height: 6), // Vezérlő gombok Row(children: [ // Szünet / Folytatás _CardButton( icon: ctrl.isPaused.value ? Icons.play_arrow : Icons.pause, color: ctrl.isPaused.value ? Colors.greenAccent : Colors.orange, onTap: ctrl.isPaused.value ? ctrl.resumeRecording : ctrl.pauseRecording, tooltip: ctrl.isPaused.value ? 'Folytatás' : 'Szünet', ), const SizedBox(width: 6), // Stop _CardButton( icon: Icons.stop, color: Colors.red, onTap: () => _confirmStop(context), tooltip: 'Befejezés', ), const Spacer(), // Nyíl → sheet megnyitás Icon(Icons.keyboard_arrow_up, size: 14, color: Colors.white.withOpacity(0.35)), ]), ], )); } void _confirmStop(BuildContext context) { Get.dialog(AlertDialog( title: const Text('Rögzítés befejezése'), content: Obx(() => Text( '${ctrl.elapsedFormatted.value} · ' '${_fmtDist(ctrl.sessionDistance.value)}\n' '${ctrl.livePoints.length} pont', )), actions: [ TextButton(onPressed: Get.back, child: const Text('Mégse')), FilledButton( style: FilledButton.styleFrom(backgroundColor: Colors.red.shade700), onPressed: () { Get.back(); ctrl.stopRecording(); }, child: const Text('Befejezés'), ), ], )); } String _fmtDist(double m) => m < 1000 ? '${m.toStringAsFixed(0)} m' : '${(m / 1000).toStringAsFixed(2)} km'; } // ─── Idle állapot ───────────────────────────────────────────────────────────── class _IdleContent extends StatelessWidget { @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.route_outlined, size: 14, color: Colors.white.withOpacity(0.5)), const SizedBox(width: 6), Text( 'Track', style: TextStyle( color: Colors.white.withOpacity(0.55), fontSize: 12, ), ), const SizedBox(width: 8), // Indítás gomb GestureDetector( onTap: () => _startRecording(context), child: Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: Colors.red.withOpacity(0.2), borderRadius: BorderRadius.circular(6), border: Border.all(color: Colors.red.withOpacity(0.4)), ), child: const Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.fiber_manual_record, size: 10, color: Colors.red), SizedBox(width: 4), Text('Start', style: TextStyle( color: Colors.red, fontSize: 11, fontWeight: FontWeight.w600)), ], ), ), ), ], ); } void _startRecording(BuildContext context) { final nameCtrl = TextEditingController( text: 'Track ${DateTime.now().toString().substring(5, 16)}', ); Get.dialog(AlertDialog( title: const Text('Rögzítés indítása'), content: TextField( controller: nameCtrl, autofocus: true, decoration: const InputDecoration( labelText: 'Track neve', border: OutlineInputBorder(), ), ), actions: [ TextButton(onPressed: Get.back, child: const Text('Mégse')), FilledButton( onPressed: () { Get.back(); TrackingController.to.startRecording(); // .startRecording(name: nameCtrl.text.trim()); }, child: const Text('Indítás'), ), ], )); } } // ─── Segéd widgetek ─────────────────────────────────────────────────────────── class _StatusDot extends StatefulWidget { final bool paused; const _StatusDot({required this.paused}); @override State<_StatusDot> createState() => _StatusDotState(); } class _StatusDotState extends State<_StatusDot> with SingleTickerProviderStateMixin { late AnimationController _ctrl; late Animation _anim; @override void initState() { super.initState(); _ctrl = AnimationController( vsync: this, duration: const Duration(milliseconds: 700), )..repeat(reverse: true); _anim = Tween(begin: 0.3, end: 1.0) .animate(CurvedAnimation(parent: _ctrl, curve: Curves.easeInOut)); } @override void didUpdateWidget(_StatusDot old) { super.didUpdateWidget(old); widget.paused ? _ctrl.stop() : _ctrl.repeat(reverse: true); } @override void dispose() { _ctrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final color = widget.paused ? Colors.orange : Colors.red; return AnimatedBuilder( animation: _anim, builder: (_, __) => Opacity( opacity: widget.paused ? 0.6 : _anim.value, child: Container( width: 7, height: 7, decoration: BoxDecoration(color: color, shape: BoxShape.circle), ), ), ); } } class _MiniStat extends StatelessWidget { final IconData icon; final String value; const _MiniStat({required this.icon, required this.value}); @override Widget build(BuildContext context) { return Row(mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 11, color: Colors.white54), const SizedBox(width: 3), Text( value, style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.w600, fontFeatures: [FontFeature.tabularFigures()], ), ), ]); } } class _CardButton extends StatelessWidget { final IconData icon; final Color color; final VoidCallback onTap; final String tooltip; const _CardButton({ required this.icon, required this.color, required this.onTap, required this.tooltip, }); @override Widget build(BuildContext context) { return Tooltip( message: tooltip, child: GestureDetector( onTap: onTap, child: Container( width: 28, height: 24, decoration: BoxDecoration( color: color.withOpacity(0.18), borderRadius: BorderRadius.circular(6), border: Border.all(color: color.withOpacity(0.45)), ), child: Icon(icon, size: 14, color: color), ), ), ); } }