refactor dashboard operation list e task list with applifecycle
This commit is contained in:
@@ -5,8 +5,10 @@ import 'package:flux/core/routes/routes.dart';
|
||||
import 'package:flux/core/theme/theme.dart';
|
||||
import 'package:flux/core/utils/extensions.dart';
|
||||
import 'package:flux/core/widgets/staff_selector_modal.dart';
|
||||
import 'package:flux/features/home/dashboard_store_operation_list/bloc/dashboard_store_operation_list_cubit.dart';
|
||||
import 'package:flux/features/home/dashboard_task_list/blocs/dashboard_task_list_cubit.dart';
|
||||
import 'package:flux/features/home/dashboard_task_list/ui/dashboard_tasks_card.dart';
|
||||
import 'package:flux/features/home/latest_store_operations/ui/latest_store_operations_card.dart';
|
||||
import 'package:flux/features/home/dashboard_store_operation_list/ui/latest_store_operations_card.dart';
|
||||
import 'package:flux/features/home/latest_store_tickets/ui/latest_store_tickets_card.dart';
|
||||
import 'package:flux/features/home/ui/quick_actions_widget.dart';
|
||||
import 'package:flux/features/master_data/staff/blocs/staff_cubit.dart';
|
||||
@@ -17,85 +19,140 @@ import 'package:flux/features/notes/ui/dashboard_notes_widget.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class HomeScreen extends StatelessWidget {
|
||||
class HomeScreen extends StatefulWidget {
|
||||
const HomeScreen({super.key});
|
||||
|
||||
@override
|
||||
State<HomeScreen> createState() => _HomeScreenState();
|
||||
}
|
||||
|
||||
class _HomeScreenState extends State<HomeScreen> {
|
||||
late final AppLifecycleListener _lifecycleListener;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
// Inizializziamo il sensore del ciclo di vita
|
||||
_lifecycleListener = AppLifecycleListener(
|
||||
onPause: () {
|
||||
// L'utente ha messo l'app in background (es. per rispondere a un messaggio su WhatsApp)
|
||||
// Chiudiamo i rubinetti per non sprecare risorse e prevenire crash
|
||||
context.read<DashboardStoreOperationListCubit>().stopListening();
|
||||
context.read<DashboardTaskListCubit>().stopListening();
|
||||
debugPrint('App in background: Stream sospesi.');
|
||||
},
|
||||
onResume: () {
|
||||
// L'utente è tornato sull'app!
|
||||
// Riappriamo i rubinetti, Supabase ricreerà una connessione fresca
|
||||
context.read<DashboardStoreOperationListCubit>().startListening();
|
||||
context.read<DashboardTaskListCubit>().startListening();
|
||||
debugPrint('App in foreground: Stream riattivati.');
|
||||
},
|
||||
);
|
||||
|
||||
// Facciamo partire gli stream la primissima volta che la schermata si carica
|
||||
context.read<DashboardStoreOperationListCubit>().startListening();
|
||||
context.read<DashboardTaskListCubit>().startListening();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// Pulizia fondamentale
|
||||
_lifecycleListener.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final sessionCubit = GetIt.I.get<SessionCubit>();
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
// ==========================================
|
||||
// 1. HEADER FISSO (Non scrolla mai)
|
||||
// ==========================================
|
||||
Container(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
// Un leggero colore di sfondo aiuta a staccare l'header quando il contenuto ci passa sotto
|
||||
color: theme.colorScheme.surface,
|
||||
child: _buildHeader(context, theme),
|
||||
),
|
||||
|
||||
// ==========================================
|
||||
// 2. CORPO DELLA DASHBOARD (Scrollabile)
|
||||
// ==========================================
|
||||
Expanded(
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
// --- QUICK ACTIONS: AZIONI RAPIDE ---
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
child: _buildQuickActions(context),
|
||||
),
|
||||
),
|
||||
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 32)),
|
||||
|
||||
// --- I WIDGET DELLA DASHBOARD (Responsive Grid) ---
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 500,
|
||||
mainAxisSpacing: 16,
|
||||
crossAxisSpacing: 16,
|
||||
childAspectRatio: 1.3,
|
||||
),
|
||||
delegate: SliverChildListDelegate([
|
||||
LatestStoreOperationsCard(),
|
||||
LatestStoreTicketsCard(),
|
||||
_buildDashboardWidget(
|
||||
title: context.l10n.homeExpiringContracts,
|
||||
icon: Icons.assignment_late_outlined,
|
||||
color: Colors.orange,
|
||||
context: context,
|
||||
),
|
||||
DashboardNotesWidget(),
|
||||
DashboardTasksCard(),
|
||||
]),
|
||||
),
|
||||
),
|
||||
|
||||
// Spazio finale per non far attaccare l'ultima card al fondo
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 40)),
|
||||
],
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider<DashboardStoreOperationListCubit>(
|
||||
create: (context) => DashboardStoreOperationListCubit(
|
||||
companyId: sessionCubit.state.company?.id,
|
||||
storeId: sessionCubit.state.currentStore?.id,
|
||||
),
|
||||
),
|
||||
BlocProvider<DashboardTaskListCubit>(
|
||||
create: (context) => DashboardTaskListCubit(
|
||||
companyId: sessionCubit.state.company?.id,
|
||||
staffId: sessionCubit.state.currentStaffMember?.id,
|
||||
),
|
||||
),
|
||||
],
|
||||
child: Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
// ==========================================
|
||||
// 1. HEADER FISSO (Non scrolla mai)
|
||||
// ==========================================
|
||||
Container(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
// Un leggero colore di sfondo aiuta a staccare l'header quando il contenuto ci passa sotto
|
||||
color: theme.colorScheme.surface,
|
||||
child: _buildHeader(context, theme),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
// ==========================================
|
||||
// 2. CORPO DELLA DASHBOARD (Scrollabile)
|
||||
// ==========================================
|
||||
Expanded(
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
// --- QUICK ACTIONS: AZIONI RAPIDE ---
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
child: _buildQuickActions(context),
|
||||
),
|
||||
),
|
||||
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 32)),
|
||||
|
||||
// --- I WIDGET DELLA DASHBOARD (Responsive Grid) ---
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 500,
|
||||
mainAxisSpacing: 16,
|
||||
crossAxisSpacing: 16,
|
||||
childAspectRatio: 1.3,
|
||||
),
|
||||
delegate: SliverChildListDelegate([
|
||||
DashboardStoreOperationListCard(),
|
||||
LatestStoreTicketsCard(),
|
||||
_buildDashboardWidget(
|
||||
title: context.l10n.homeExpiringContracts,
|
||||
icon: Icons.assignment_late_outlined,
|
||||
color: Colors.orange,
|
||||
context: context,
|
||||
),
|
||||
DashboardNotesWidget(),
|
||||
DashboardTasksCard(),
|
||||
]),
|
||||
),
|
||||
),
|
||||
|
||||
// Spazio finale per non far attaccare l'ultima card al fondo
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 40)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// WIDGET BUILDERS
|
||||
// ==========================================
|
||||
|
||||
Widget _buildHeader(BuildContext context, ThemeData theme) {
|
||||
final user = context.watch<SessionCubit>().state.currentStaffMember;
|
||||
final currentStore = context.watch<SessionCubit>().state.currentStore;
|
||||
|
||||
Reference in New Issue
Block a user