import 'dart:async'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:mileograph_flutter/objects/objects.dart'; import 'package:mileograph_flutter/services/data_service.dart'; import 'package:provider/provider.dart'; class LegShareNotificationCard extends StatelessWidget { const LegShareNotificationCard({super.key, required this.notification}); final UserNotification notification; @override Widget build(BuildContext context) { final data = context.read(); final legShareId = notification.body.trim(); if (legShareId.isEmpty) { return const Text('Invalid leg share notification.'); } final future = data.fetchLegShare(legShareId); return FutureBuilder( future: future, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Padding( padding: EdgeInsets.symmetric(vertical: 6.0), child: SizedBox( height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2), ), ); } if (snapshot.hasError) { return const Text('Failed to load shared entry.'); } final share = snapshot.data; final entry = share?.entry; if (share == null || entry == null) { return const Text('Shared entry unavailable.'); } final begin = entry.beginTime; final beginStr = '${begin.year.toString().padLeft(4, '0')}-${begin.month.toString().padLeft(2, '0')}-${begin.day.toString().padLeft(2, '0')} ${begin.hour.toString().padLeft(2, '0')}:${begin.minute.toString().padLeft(2, '0')}'; final start = entry.route.isNotEmpty ? entry.route.first : entry.start; final end = entry.route.isNotEmpty ? entry.route.last : entry.end; final sharedAt = share.sharedAt; final sharedAtStr = sharedAt == null ? null : '${sharedAt.year.toString().padLeft(4, '0')}-${sharedAt.month.toString().padLeft(2, '0')}-${sharedAt.day.toString().padLeft(2, '0')} ${sharedAt.hour.toString().padLeft(2, '0')}:${sharedAt.minute.toString().padLeft(2, '0')}'; final from = share.sharedFromName; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('$beginStr • $start → $end'), if (from.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 4.0), child: Text( 'From $from', style: Theme.of(context).textTheme.bodySmall, ), ), if (sharedAtStr != null) Padding( padding: const EdgeInsets.only(top: 4.0), child: Text( 'Shared at $sharedAtStr', style: Theme.of(context).textTheme.bodySmall, ), ), const SizedBox(height: 8), Wrap( spacing: 8, runSpacing: 8, children: [ ElevatedButton( onPressed: () => _accept(context, share), child: const Text('Accept'), ), OutlinedButton( onPressed: () => _inspect(context, share), child: const Text('Inspect'), ), TextButton( onPressed: () => _reject(context, share), child: const Text('Reject'), ), ], ), ], ); }, ); } Future _accept(BuildContext context, LegShareData share) async { final data = context.read(); final messenger = ScaffoldMessenger.maybeOf(context); try { await data.acceptLegShare(share); if (!context.mounted) return; await data.dismissNotifications([notification.id]); // Refresh legs in the background. unawaited(data.refreshLegs()); messenger?.showSnackBar( const SnackBar(content: Text('Shared entry added to logbook')), ); } catch (e) { messenger?.showSnackBar( SnackBar(content: Text('Failed to add shared entry: $e')), ); } } Future _reject(BuildContext context, LegShareData share) async { final data = context.read(); final messenger = ScaffoldMessenger.maybeOf(context); try { await data.rejectLegShare(share.id); if (!context.mounted) return; await data.dismissNotifications([notification.id]); messenger?.showSnackBar( const SnackBar(content: Text('Share rejected')), ); } catch (e) { messenger?.showSnackBar( SnackBar(content: Text('Failed to reject share: $e')), ); } } Future _inspect(BuildContext context, LegShareData share) async { final router = GoRouter.of(context); // Close notifications panel if open. if (Navigator.canPop(context)) { Navigator.of(context).pop(); } await Future.delayed(Duration.zero); final target = share.copyWith(notificationId: notification.id); final ts = DateTime.now().millisecondsSinceEpoch; final path = '/add?share=${Uri.encodeComponent(share.id)}&ts=$ts'; router.go(path, extra: target); } }