import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; import '../models/customer.dart'; import '../theme/app_theme.dart'; import '../widgets/customer_preview_sheet.dart'; import '../services/database_service.dart'; class CustomerMapScreen extends StatefulWidget { const CustomerMapScreen({super.key}); @override State createState() => _CustomerMapScreenState(); } class _CustomerMapScreenState extends State { final MapController _mapController = MapController(); Customer? _selectedCustomer; String _searchQuery = ''; final TextEditingController _searchController = TextEditingController(); List _allCustomers = []; // Initial center position (Musterstadt / Frankfurt coordinates) static final LatLng _initialCenter = LatLng(50.1109, 8.6821); @override void initState() { super.initState(); _loadCustomers(); } Future _loadCustomers() async { final list = await DatabaseService.getCustomers(); if (!mounted) return; setState(() { _allCustomers = list; if (_allCustomers.isNotEmpty) { _selectedCustomer = _allCustomers.firstWhere( (c) => c.customerNumber == 'K-10025', orElse: () => _allCustomers.first, ); } }); } @override void dispose() { _searchController.dispose(); _mapController.dispose(); super.dispose(); } List get _filteredCustomers { if (_searchQuery.trim().isEmpty) { return _allCustomers; } final q = _searchQuery.toLowerCase(); return _allCustomers.where((c) { return c.name.toLowerCase().contains(q) || c.customerNumber.toLowerCase().contains(q) || c.city.toLowerCase().contains(q) || c.street.toLowerCase().contains(q); }).toList(); } void _selectCustomer(Customer customer) { setState(() { _selectedCustomer = customer; }); _mapController.move( LatLng(customer.latitude, customer.longitude), 14.5, ); } void _recenterMap() { _mapController.move( _initialCenter, 13.0, ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppTheme.backgroundLight, body: Column( children: [ // Dark Navy Top Header Bar (matches Mockup NaviScreen.png) Container( color: AppTheme.primaryDark, child: SafeArea( bottom: false, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6), child: Row( children: [ IconButton( icon: const Icon(Icons.menu, color: Colors.white), onPressed: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Menü geöffnet')), ); }, ), const Expanded( child: Text( 'Kunden', textAlign: TextAlign.center, style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white, ), ), ), IconButton( icon: const Icon(Icons.search, color: Colors.white), onPressed: () {}, ), IconButton( icon: const Icon(Icons.tune, color: Colors.white), onPressed: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Filter geöffnet')), ); }, ), ], ), ), ), ), // Map Area + Floating Overlays Expanded( child: Stack( children: [ // Clean Minimalistic CartoDB Tile Layer Map View FlutterMap( mapController: _mapController, options: MapOptions( initialCenter: _selectedCustomer != null ? LatLng(_selectedCustomer!.latitude, _selectedCustomer!.longitude) : _initialCenter, initialZoom: 13.5, // Enable full multi-touch gestures (Pinch Zoom, Pan, Double Tap) interactionOptions: const InteractionOptions( flags: InteractiveFlag.all, ), onTap: (tapPosition, point) { setState(() { _selectedCustomer = null; }); }, ), children: [ TileLayer( // Clean minimal map tiles matching the mockup design urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', subdomains: const ['a', 'b', 'c', 'd'], retinaMode: RetinaMode.isHighDensity(context), userAgentPackageName: 'de.handwerksfreund.app', ), MarkerLayer( markers: _filteredCustomers.map((customer) { final isSelected = _selectedCustomer?.id == customer.id; return Marker( width: isSelected ? 50 : 40, height: isSelected ? 50 : 40, point: LatLng(customer.latitude, customer.longitude), child: GestureDetector( onTap: () => _selectCustomer(customer), child: isSelected ? Container( decoration: BoxDecoration( color: Colors.white, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: AppTheme.primaryBlue.withAlpha(102), blurRadius: 12, spreadRadius: 4, ), ], ), padding: const EdgeInsets.all(4), child: Container( decoration: const BoxDecoration( color: AppTheme.primaryBlue, shape: BoxShape.circle, ), child: const Icon( Icons.location_on, color: Colors.white, size: 26, ), ), ) : const Icon( Icons.location_on, color: AppTheme.primaryBlue, size: 38, ), ), ); }).toList(), ), ], ), // Dim Overlay when customer sheet is selected if (_selectedCustomer != null) Positioned.fill( child: GestureDetector( onTap: () { setState(() { _selectedCustomer = null; }); }, child: Container( color: Colors.black.withAlpha(51), ), ), ), // Search Input Card overlay Positioned( top: 12, left: 16, right: 16, child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: const [ BoxShadow( color: Colors.black12, blurRadius: 8, offset: Offset(0, 2), ), ], ), child: TextField( controller: _searchController, onChanged: (val) { setState(() { _searchQuery = val; }); }, decoration: InputDecoration( hintText: 'Kunden suchen...', hintStyle: const TextStyle( color: AppTheme.textSecondary, fontSize: 14, ), prefixIcon: const Icon( Icons.search, color: AppTheme.textSecondary, ), suffixIcon: IconButton( icon: const Icon( Icons.tune, color: AppTheme.textSecondary, size: 20, ), onPressed: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Filteroptionen geöffnet')), ); }, ), border: InputBorder.none, contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 14, ), ), ), ), ), // Map Action Buttons (Center location & Add customer FAB) Positioned( right: 16, bottom: _selectedCustomer != null ? 230 : 24, child: Column( mainAxisSize: MainAxisSize.min, children: [ FloatingActionButton.small( heroTag: 'recenter_fab', onPressed: _recenterMap, backgroundColor: Colors.white, foregroundColor: AppTheme.primaryDark, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), child: const Icon(Icons.my_location, size: 20), ), const SizedBox(height: 12), FloatingActionButton( heroTag: 'add_customer_fab', onPressed: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Neuen Kunden anlegen')), ); }, backgroundColor: AppTheme.primaryDark, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), child: const Icon(Icons.add, size: 28), ), ], ), ), // Bottom Sheet Customer Preview Card Overlay if (_selectedCustomer != null) Positioned( left: 0, right: 0, bottom: 0, child: CustomerPreviewSheet( customer: _selectedCustomer!, onClose: () { setState(() { _selectedCustomer = null; }); }, ), ), ], ), ), ], ), ); } }