import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../utils/translations.dart'; import '../utils/target_colors.dart'; import '../services/notification_service.dart'; class SettingsScreen extends StatefulWidget { const SettingsScreen({super.key}); @override State createState() => _SettingsScreenState(); } class _SettingsScreenState extends State { Color _backgroundColor = Colors.grey[900]!; List _cameraIPs = List.generate(6, (index) => 'Not Set'); final List _defaultIPs = [ '192.168.0.134:9081', '192.168.0.134:9082', '192.168.0.134:9083', '192.168.0.134:9084', '192.168.0.134:9085', '192.168.0.134:9086', ]; String _selectedBulletColor = 'Blue'; final List _bulletColors = [ 'Blue', 'Green', 'Yellow', 'Purple', 'Cyan', 'Teal', 'Indigo', 'Pink', 'Lime', 'Mint', 'Orange', 'Violet', 'Amber', 'Brown', 'Grey', ]; int _notificationHours = 1; final List _notificationHourOptions = [1, 2, 3, 6, 12, 24, 48]; bool _notifyDezuranje = true; bool _notifySestanek = true; bool _notifyTekma = true; String _selectedLanguage = 'English'; final List> _languages = [ {'code': 'en', 'name': 'English', 'flag': '🇬🇧'}, {'code': 'sl', 'name': 'Slovenian', 'flag': '🇸🇮'}, ]; String _selectedTarget = 'assets/target.png'; final List _availableTargets = [ 'assets/target.png', 'assets/targets/Target1.jpg', 'assets/targets/Target2.jpg', 'assets/targets/Target3.jpg', 'assets/targets/Target4.jpg', 'assets/targets/Target5.jpg', 'assets/targets/Target6.jpg', 'assets/targets/Target7.jpg', 'assets/targets/Target8.jpg', 'assets/targets/Target9.jpg', 'assets/targets/Target10.jpg', 'assets/targets/Target11.jpg', 'assets/targets/Target12.jpg', 'assets/targets/Target13.jpg', 'assets/targets/Target14.jpg', 'assets/targets/Target15.jpg', 'assets/targets/Target16.jpg', 'assets/targets/Target17.jpg', 'assets/targets/Target18.jpg', 'assets/targets/Target19.jpg', 'assets/targets/Target20.jpg', 'assets/targets/Target21.jpg', 'assets/targets/Target22.jpg', 'assets/targets/Target23.jpg', 'assets/targets/Target24.jpg', 'assets/targets/Target25.jpg', 'assets/targets/Target26.jpg', 'assets/targets/Target27.jpg', 'assets/targets/Target28.jpg', 'assets/targets/Target29.jpg', 'assets/targets/Target30.jpg', 'assets/targets/Target31.jpg', 'assets/targets/Target32.jpg', 'assets/targets/Target33.jpg', 'assets/targets/Target34.jpg', 'assets/targets/Target35.jpg', ]; @override void initState() { super.initState(); _loadCameraIPs(); _loadBulletColor(); _loadLanguage(); _loadSelectedTarget(); _loadNotificationSettings(); } String _t(String key) { return AppTranslations.translate(key, _selectedLanguage); } Color _getColorFromName(String colorName) { switch (colorName.toLowerCase()) { case 'blue': return Colors.blue; case 'green': return Colors.green; case 'yellow': return Colors.yellow; case 'purple': return Colors.purple; case 'cyan': return Colors.cyan; case 'teal': return Colors.teal; case 'indigo': return Colors.indigo; case 'pink': return Colors.pink; case 'lime': return Colors.lime; case 'mint': return Colors.greenAccent; case 'orange': return Colors.orange; case 'violet': return Colors.deepPurpleAccent; case 'amber': return Colors.amber; case 'brown': return Colors.brown; case 'grey': return Colors.grey; default: return Colors.blue; // fallback } } Future _loadBulletColor() async { final prefs = await SharedPreferences.getInstance(); String savedColor = prefs.getString('bulletColor') ?? 'Blue'; // Fallback in case old color is no longer valid if (!_bulletColors.contains(savedColor)) { savedColor = 'Blue'; await prefs.setString('bulletColor', savedColor); } setState(() { _selectedBulletColor = savedColor; }); } Future _saveBulletColor(String color) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('bulletColor', color); setState(() => _selectedBulletColor = color); } Future _loadLanguage() async { final prefs = await SharedPreferences.getInstance(); String savedLanguage = prefs.getString('language') ?? 'English'; setState(() { _selectedLanguage = savedLanguage; }); } Future _saveLanguage(String language) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('language', language); setState(() => _selectedLanguage = language); } Future _loadSelectedTarget() async { final prefs = await SharedPreferences.getInstance(); String savedTarget = prefs.getString('selectedTarget') ?? 'assets/target.png'; setState(() { _selectedTarget = savedTarget; _backgroundColor = TargetColors.getBackgroundColor(savedTarget); }); } Future _saveSelectedTarget(String target) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('selectedTarget', target); setState(() { _selectedTarget = target; _backgroundColor = TargetColors.getBackgroundColor(target); }); } String _getTargetDisplayName(String targetPath) { if (targetPath == 'assets/target.png') { return _t('Default Target'); } final targetName = targetPath .replaceAll('assets/targets/', '') .replaceAll('.jpg', ''); return _t(targetName); } Future _loadNotificationSettings() async { final prefs = await SharedPreferences.getInstance(); setState(() { _notificationHours = prefs.getInt('notificationHours_single') ?? 1; _notifyDezuranje = prefs.getBool('notifyDezuranje') ?? true; _notifySestanek = prefs.getBool('notifySestanek') ?? true; _notifyTekma = prefs.getBool('notifyTekma') ?? true; }); } Future _saveNotificationHours(int hours) async { final prefs = await SharedPreferences.getInstance(); await prefs.setInt('notificationHours_single', hours); await prefs.setStringList('notificationHours', [hours.toString()]); setState(() => _notificationHours = hours); } Future _saveNotifyType(String key, bool value) async { final prefs = await SharedPreferences.getInstance(); await prefs.setBool(key, value); } Future _loadCameraIPs() async { final prefs = await SharedPreferences.getInstance(); List tempIPs = []; for (int i = 0; i < 6; i++) { String key = 'cameraIP_${i + 1}'; String? savedIP = prefs.getString(key); // If not saved, use default and write it to prefs if (savedIP == null) { await prefs.setString(key, _defaultIPs[i]); tempIPs.add(_defaultIPs[i]); } else { tempIPs.add(savedIP); } } setState(() { _cameraIPs = tempIPs; }); } Future _saveCameraIP(int index, String ip) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('cameraIP_${index + 1}', ip); _loadCameraIPs(); } Future _clearCameraIP(int index) async { final prefs = await SharedPreferences.getInstance(); await prefs.remove('cameraIP_${index + 1}'); _loadCameraIPs(); } void _editCameraIP(int index) { TextEditingController controller = TextEditingController( text: _cameraIPs[index], ); showDialog( context: context, builder: (context) { return RepaintBoundary( child: Dialog( backgroundColor: Colors.grey[900], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(24.0), child: StatefulBuilder( builder: (context, setState) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( "${_t('Camera')} ${index + 1}", style: const TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), const SizedBox(height: 16), SizedBox( width: double.infinity, child: TextField( controller: controller, style: const TextStyle(color: Colors.white), textAlign: TextAlign.center, decoration: InputDecoration( filled: true, fillColor: Colors.grey[800], hintText: _t("Enter Camera IP"), hintStyle: const TextStyle(color: Colors.white54), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: _getColorFromName(_selectedBulletColor)), ), ), ), ), const SizedBox(height: 24), // Save Button SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () async { String newIP = controller.text.trim(); if (newIP.isNotEmpty) { await _saveCameraIP(index, newIP); if (context.mounted) { Navigator.pop(context); } } }, style: ElevatedButton.styleFrom( backgroundColor: _getColorFromName(_selectedBulletColor), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text(_t("Save")), ), ), const SizedBox(height: 12), // Reset Button SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () async { await _clearCameraIP(index); if (context.mounted) { Navigator.pop(context); } }, style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[700], foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text(_t("Reset to Default")), ), ), const SizedBox(height: 12), // Cancel Button SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () => Navigator.pop(context), style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[800], foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text(_t("Cancel")), ), ), ], ); }, ), ), ), ); }, ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: _backgroundColor, body: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), child: Column( children: [ const SizedBox(height: 8), _buildLanguageSelector(), const SizedBox(height: 16), _buildAppearanceSelector(), const SizedBox(height: 16), _buildNotificationSettings(), const SizedBox(height: 16), _buildCameraList(), ], ), ), ); } Widget _buildLanguageSelector() { final selectedLang = _languages.firstWhere( (lang) => lang['name'] == _selectedLanguage, orElse: () => _languages[0], ); return Container( margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 0), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: Colors.grey[900], borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), ), ), child: Row( children: [ Container( width: 4, height: 16, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 12), Text( _t("Language"), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), ), // Content GestureDetector( onTap: _showLanguagePopup, child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(12), bottomRight: Radius.circular(12), ), ), child: Row( children: [ Text( selectedLang['flag'] ?? '🌐', style: const TextStyle(fontSize: 20), ), const SizedBox(width: 12), Expanded( child: Text( _t(selectedLang['name'] ?? 'English'), style: const TextStyle(color: Colors.black87, fontSize: 14), ), ), const Icon(Icons.chevron_right, color: Colors.black54), ], ), ), ), ], ), ); } Widget _buildAppearanceSelector() { return Container( margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 0), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: Colors.grey[900], borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), ), ), child: Row( children: [ Container( width: 4, height: 16, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 12), Text( _t("Appearance"), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), ), // Content GestureDetector( onTap: _showAppearancePopup, child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(12), bottomRight: Radius.circular(12), ), ), child: Row( children: [ // Preview box with target ClipRRect( borderRadius: BorderRadius.circular(8), child: Container( width: 70, height: 70, decoration: BoxDecoration( border: Border.all(color: Colors.black12), borderRadius: BorderRadius.circular(8), color: TargetColors.getBackgroundColor(_selectedTarget), ), child: Image.asset( _selectedTarget, fit: BoxFit.contain, errorBuilder: (context, error, stackTrace) { return Icon(Icons.image_not_supported, color: Colors.grey[400]); }, ), ), ), const SizedBox(width: 16), // Details section Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( _t("Bullet:"), style: const TextStyle( color: Colors.black54, fontSize: 12, fontWeight: FontWeight.w600, ), ), const SizedBox(width: 8), Container( width: 16, height: 16, decoration: BoxDecoration( color: _getColorFromName(_selectedBulletColor), shape: BoxShape.circle, border: Border.all(color: Colors.black26, width: 1), ), ), const SizedBox(width: 6), Expanded( child: Text( _selectedBulletColor, style: const TextStyle( color: Colors.black87, fontSize: 12, fontWeight: FontWeight.w500, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), const SizedBox(height: 8), Row( children: [ Text( _t("Target:"), style: const TextStyle( color: Colors.black54, fontSize: 12, fontWeight: FontWeight.w600, ), ), const SizedBox(width: 8), Expanded( child: Text( _getTargetDisplayName(_selectedTarget), style: const TextStyle( color: Colors.black87, fontSize: 12, fontWeight: FontWeight.w500, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ], ), ), const SizedBox(width: 8), Icon(Icons.chevron_right, color: Colors.black54), ], ), ), ), ], ), ); } void _showLanguagePopup() { showDialog( context: context, builder: (context) { return Dialog( backgroundColor: Colors.grey[900], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( _t("Select Language"), style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 20), ..._languages.map((lang) { final isSelected = lang['name'] == _selectedLanguage; return Padding( padding: const EdgeInsets.only(bottom: 12.0), child: SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () async { await _saveLanguage(lang['name']!); if (context.mounted) { Navigator.of(context).pop(); } }, style: ElevatedButton.styleFrom( backgroundColor: isSelected ? _getColorFromName(_selectedBulletColor) : Colors.grey[800], foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( lang['flag']!, style: const TextStyle(fontSize: 20), ), const SizedBox(width: 12), Text( _t(lang['name']!), style: const TextStyle(fontSize: 16), ), ], ), ), ), ); }), const SizedBox(height: 8), TextButton( onPressed: () => Navigator.of(context).pop(), child: Text(_t("Cancel"), style: const TextStyle(color: Colors.white70)), ), ], ), ), ); }, ); } void _showAppearancePopup() { String previewBulletColor = _selectedBulletColor; String previewTarget = _selectedTarget; int selectedTab = 0; // 0 for Bullet, 1 for Target showDialog( context: context, builder: (context) { return StatefulBuilder( builder: (context, innerSetState) { return Dialog( backgroundColor: Colors.grey[900], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), insetPadding: const EdgeInsets.all(24), child: SizedBox( height: 700, width: 400, child: Padding( padding: const EdgeInsets.all(24), child: Column( children: [ Text( _t("Appearance Settings"), style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 20), // Preview with multiple bullets on target - ALWAYS ON TOP Container( width: double.infinity, height: 280, decoration: BoxDecoration( color: TargetColors.getBackgroundColor(previewTarget), borderRadius: BorderRadius.circular(12), ), child: ClipRRect( borderRadius: BorderRadius.circular(12), child: Stack( alignment: Alignment.center, clipBehavior: Clip.hardEdge, children: [ Center( child: Image.asset( previewTarget, fit: BoxFit.contain, errorBuilder: (context, error, stackTrace) { return Container( color: Colors.grey[800], child: const Center( child: Icon(Icons.image_not_supported, color: Colors.white54), ), ); }, ), ), // Multiple preview bullets scattered around Positioned( left: 90, top: 100, child: _buildPreviewBullet(previewBulletColor), ), Positioned( right: 90, top: 110, child: _buildPreviewBullet(previewBulletColor), ), Positioned( left: 100, bottom: 90, child: _buildPreviewBullet(previewBulletColor), ), Positioned( right: 95, bottom: 100, child: _buildPreviewBullet(previewBulletColor), ), Positioned( left: 110, top: 140, child: _buildPreviewBullet(previewBulletColor), ), Positioned( right: 110, bottom: 140, child: _buildPreviewBullet(previewBulletColor), ), ], ), ), ), const SizedBox(height: 24), // Tab Buttons and Content as one unit Expanded( child: Container( decoration: BoxDecoration( color: Colors.grey[800], borderRadius: BorderRadius.circular(8), ), child: Column( children: [ // Selection Buttons (Tabs) Row( children: [ Expanded( child: ElevatedButton( onPressed: () => innerSetState(() => selectedTab = 0), style: ElevatedButton.styleFrom( backgroundColor: selectedTab == 0 ? _getColorFromName(previewBulletColor) : Colors.grey[700], foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: const BorderRadius.only( topLeft: Radius.circular(8), ), ), ), child: Text( _t("Bullet"), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, ), ), ), ), Expanded( child: ElevatedButton( onPressed: () => innerSetState(() => selectedTab = 1), style: ElevatedButton.styleFrom( backgroundColor: selectedTab == 1 ? _getColorFromName(previewBulletColor) : Colors.grey[700], foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: const BorderRadius.only( topRight: Radius.circular(8), ), ), ), child: Text( _t("Target"), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, ), ), ), ), ], ), // Tab Content Expanded( child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: selectedTab == 0 ? Center( child: Wrap( spacing: 20, runSpacing: 20, alignment: WrapAlignment.center, children: _bulletColors.map((colorName) { final color = _getColorFromName(colorName); final isSelected = colorName == previewBulletColor; return GestureDetector( onTap: () => innerSetState(() => previewBulletColor = colorName), child: Container( width: 62, height: 62, decoration: BoxDecoration( color: color, shape: BoxShape.circle, border: Border.all( color: isSelected ? Colors.white : Colors.white24, width: isSelected ? 4 : 2, ), ), ), ); }).toList(), ), ) : Column( mainAxisSize: MainAxisSize.min, children: _availableTargets.map((targetPath) { final isSelected = targetPath == previewTarget; final displayName = _getTargetDisplayName(targetPath); return Padding( padding: const EdgeInsets.only(bottom: 8.0), child: SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () => innerSetState(() => previewTarget = targetPath), style: ElevatedButton.styleFrom( backgroundColor: isSelected ? _getColorFromName(previewBulletColor) : Colors.grey[700], foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 12), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), child: Text( displayName, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 12), ), ), ), ); }).toList(), ), ), ), ], ), ), ), const SizedBox(height: 16), // Action Buttons Row( children: [ Expanded( child: ElevatedButton( onPressed: () async { await _saveBulletColor(previewBulletColor); await _saveSelectedTarget(previewTarget); if (context.mounted) { Navigator.of(context).pop(); } }, style: ElevatedButton.styleFrom( backgroundColor: _getColorFromName(previewBulletColor), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), child: Text(_t("Apply")), ), ), const SizedBox(width: 12), Expanded( child: TextButton( onPressed: () => Navigator.of(context).pop(), child: Text(_t("Cancel"), style: const TextStyle(color: Colors.white70)), ), ), ], ), ], ), ), ), ); }, ); }, ); } Widget _buildPreviewBullet(String bulletColor) { const double bulletOpacity = 0.8; return Container( width: 14, height: 14, decoration: BoxDecoration( color: _getColorFromName(bulletColor).withValues(alpha: bulletOpacity), shape: BoxShape.circle, border: Border.all( color: Colors.black, width: 1, ), ), ); } Widget _buildCameraList() { return Container( margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 0), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: Colors.grey[900], borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), ), ), child: Row( children: [ Container( width: 4, height: 16, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 12), Text( _t("Camera Settings"), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), ), // Content - all cameras ...List.generate(6, (index) { return GestureDetector( onTap: () => _editCameraIP(index), child: Column( children: [ Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: index == 5 ? const BorderRadius.only( bottomLeft: Radius.circular(12), bottomRight: Radius.circular(12), ) : null, border: index < 5 ? Border( bottom: BorderSide( color: Colors.grey[400]!, width: 1, ), ) : null, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "${_t('Camera')} ${index + 1}", style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.black87, ), ), Text( _cameraIPs[index], style: const TextStyle(color: Colors.black54), ), ], ), const Icon(Icons.chevron_right, color: Colors.black54), ], ), ), ], ), ); }), ], ), ); } Widget _buildNotifyToggle(String label, bool value, ValueChanged onChanged) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(label, style: const TextStyle(color: Colors.black87, fontSize: 14)), Switch( value: value, onChanged: onChanged, activeThumbColor: _getColorFromName(_selectedBulletColor), ), ], ), ); } Widget _buildNotificationSettings() { return Container( margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 0), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: Colors.grey[900], borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), ), ), child: Row( children: [ Container( width: 4, height: 16, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 12), Expanded( child: Text( _t('Notifications'), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.white, ), ), ), GestureDetector( onTap: () async { await NotificationService().scheduleTestNotification(); }, child: const Icon(Icons.notifications_active_outlined, color: Colors.white, size: 20), ), ], ), ), // Hours before picker Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(12), bottomRight: Radius.circular(12), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 4), Text( _t('Event types'), style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.black87, ), ), const SizedBox(height: 8), _buildNotifyToggle(_t('Dežuranje'), _notifyDezuranje, (v) { setState(() => _notifyDezuranje = v); _saveNotifyType('notifyDezuranje', v); }), _buildNotifyToggle(_t('Sestanek'), _notifySestanek, (v) { setState(() => _notifySestanek = v); _saveNotifyType('notifySestanek', v); }), _buildNotifyToggle(_t('Tekma'), _notifyTekma, (v) { setState(() => _notifyTekma = v); _saveNotifyType('notifyTekma', v); }), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( _t('Notify before event'), style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.black87), ), Text( _notificationHours == 1 ? '1 ${_t('hour')}' : '$_notificationHours ${_t('hours')}', style: TextStyle( color: _getColorFromName(_selectedBulletColor), fontWeight: FontWeight.bold, fontSize: 13, ), ), ], ), const SizedBox(height: 12), ClipRRect( borderRadius: BorderRadius.circular(10), child: Row( children: _notificationHourOptions.asMap().entries.map((entry) { final i = entry.key; final hours = entry.value; final isSelected = hours == _notificationHours; final label = '${hours}h'; final isFirst = i == 0; final isLast = i == _notificationHourOptions.length - 1; return Expanded( child: GestureDetector( onTap: () => _saveNotificationHours(hours), child: Container( padding: const EdgeInsets.symmetric(vertical: 10), decoration: BoxDecoration( color: isSelected ? _getColorFromName(_selectedBulletColor) : Colors.grey[700], border: Border( right: isLast ? BorderSide.none : BorderSide(color: Colors.grey[600]!, width: 1), ), borderRadius: isFirst ? const BorderRadius.only(topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)) : isLast ? const BorderRadius.only(topRight: Radius.circular(10), bottomRight: Radius.circular(10)) : BorderRadius.zero, ), child: Text( label, textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 12, fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, ), ), ), ), ); }).toList(), ), ), ], ), ), ], ), ); } }