Files

126 lines
3.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../core/theme/app_theme.dart';
import '../../core/widgets/app_widgets.dart';
import '../../shared/widgets/eco_floating_button.dart';
import '../notifications/notification_service.dart';
import '../alerts/alerts_provider.dart';
class CitizenShell extends ConsumerStatefulWidget {
const CitizenShell({super.key, required this.child});
final Widget child;
@override
ConsumerState<CitizenShell> createState() => _CitizenShellState();
}
class _CitizenShellState extends ConsumerState<CitizenShell> {
@override
void initState() {
super.initState();
NotificationService.onFcmMessage.addListener(_onGlobalPush);
}
@override
void dispose() {
NotificationService.onFcmMessage.removeListener(_onGlobalPush);
super.dispose();
}
void _onGlobalPush() {
final msg = NotificationService.onFcmMessage.lastMessage;
if (msg?.notification != null) {
final title = msg!.notification!.title ?? 'Nueva Alerta';
final body = msg.notification!.body ?? '';
// Guardamos la alerta en el historial
ref.read(alertsProvider.notifier).addAlert(title, body);
// Mostramos un globo de notificación amigable dentro de la app
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: AppTheme.primaryDark,
behavior: SnackBarBehavior.floating,
margin: const EdgeInsets.all(16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
duration: const Duration(seconds: 5),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
const Icon(
Icons.notifications_active,
color: Colors.white,
size: 20,
),
const SizedBox(width: 8),
Expanded(
child: Text(
title,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
],
),
const SizedBox(height: 4),
Text(
body,
style: const TextStyle(color: Colors.white70, fontSize: 13),
),
],
),
action: SnackBarAction(
label: 'VER',
textColor: AppTheme.primaryLight,
onPressed: () => context.go('/alerts'),
),
),
);
}
}
}
int _currentIndex(BuildContext context) {
final location = GoRouterState.of(context).matchedLocation;
if (location.startsWith('/alerts')) return 1;
if (location.startsWith('/house')) return 2;
if (location.startsWith('/profile')) return 3;
return 0;
}
void _onTap(BuildContext context, int index) {
switch (index) {
case 0:
context.go('/home');
case 1:
context.go('/alerts');
case 2:
context.go('/house');
case 3:
context.go('/profile');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: widget.child,
floatingActionButton: const EcoFloatingButton(),
bottomNavigationBar: AppBottomNav(
currentIndex: _currentIndex(context),
onTap: (i) => _onTap(context, i),
),
);
}
}