import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/core/blocs/session/session_bloc.dart'; import 'package:flux/core/theme/theme.dart'; import 'package:flux/core/widgets/flux_text_field.dart'; import 'package:flux/features/staff/blocs/staff_cubit.dart'; import 'package:flux/features/staff/models/staff_member_model.dart'; import 'package:flux/features/store/bloc/store_bloc.dart'; import 'package:flux/features/store/models/store_model.dart'; class StoresScreen extends StatefulWidget { const StoresScreen({super.key}); @override State createState() => _StoresScreenState(); } class _StoresScreenState extends State { @override void initState() { super.initState(); // Carichiamo i negozi e anche lo staff (per poterlo assegnare) context.read().add(LoadStoresRequested()); context.read().loadAllStaff(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("I Tuoi Negozi")), body: BlocBuilder( builder: (context, state) { if (state.status == StoreStatus.loading) { return const Center(child: CircularProgressIndicator()); } return ListView.builder( padding: const EdgeInsets.all(16), itemCount: state.stores.length, itemBuilder: (context, index) { final store = state.stores[index]; return _buildStoreCard(store, state.staffByStore); }, ); }, ), floatingActionButton: FloatingActionButton.extended( onPressed: () => _openStoreForm(context), label: const Text("Nuovo Negozio"), icon: const Icon(Icons.store), ), ); } Widget _buildStoreCard( StoreModel store, Map> map, ) { return Card( margin: const EdgeInsets.only(bottom: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: BorderSide( color: store.isActive ? Colors.transparent : Colors.red.withValues(alpha: 0.3), ), ), child: Column( children: [ ListTile( leading: Icon( Icons.storefront, color: store.isActive ? context.accent : Colors.grey, ), title: Text( store.nome, style: const TextStyle(fontWeight: FontWeight.bold), ), subtitle: Text( "${store.comune} (${store.provincia}) - ${store.indirizzo}", ), trailing: Switch( value: store.isActive, onChanged: (val) { // context.read().add(ToggleStoreStatus(store.id, val)); }, ), ), const Divider(height: 1), Padding( padding: const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // Mostra quanti dipendenti ci sono (usando lo StaffCubit) ActionChip( avatar: const Icon(Icons.people, size: 16), label: Text("${map[store]?.length ?? 0} Dipendenti"), onPressed: () => _manageStoreStaff(store), ), TextButton.icon( onPressed: () => _openStoreForm(context, store: store), icon: const Icon(Icons.edit, size: 18), label: const Text("Modifica"), ), ], ), ), ], ), ); } void _openStoreForm(BuildContext context, {StoreModel? store}) { final nomeController = TextEditingController(text: store?.nome); final indirizzoController = TextEditingController(text: store?.indirizzo); final capController = TextEditingController(text: store?.cap); final comuneController = TextEditingController(text: store?.comune); final provinciaController = TextEditingController(text: store?.provincia); showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (context) => Container( decoration: BoxDecoration( color: Theme.of(context).scaffoldBackgroundColor, borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), ), padding: EdgeInsets.only( top: 24, left: 24, right: 24, bottom: MediaQuery.of(context).viewInsets.bottom + 24, ), child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( store == null ? "Nuovo Punto Vendita" : "Modifica Negozio", style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 24), // --- DATI PRINCIPALI --- FluxTextField( controller: nomeController, label: "Nome Negozio (es. Flux Milano)", icon: Icons.storefront_rounded, keyboardType: TextInputType.text, ), const SizedBox(height: 16), FluxTextField( controller: indirizzoController, label: "Indirizzo", icon: Icons.map_outlined, keyboardType: TextInputType.streetAddress, ), const SizedBox(height: 16), // --- CAP, COMUNE, PROVINCIA (In riga) --- Row( children: [ Expanded( flex: 2, child: FluxTextField( controller: capController, label: "CAP", icon: Icons.local_post_office_outlined, keyboardType: TextInputType.number, maxLength: 5, ), ), const SizedBox(width: 8), Expanded( flex: 4, child: FluxTextField( controller: comuneController, label: "Comune", icon: Icons.location_city_rounded, keyboardType: TextInputType.text, ), ), const SizedBox(width: 8), Expanded( flex: 2, child: FluxTextField( controller: provinciaController, label: "Prov", icon: Icons.explore_outlined, keyboardType: TextInputType.text, maxLength: 2, onChanged: (val) => provinciaController.text = val .toUpperCase(), // Rimpiazzo automatico in maiuscolo // Qui potresti aggiungere un rimpiazzo automatico in maiuscolo ), ), ], ), const SizedBox(height: 32), // --- TASTO SALVA --- SizedBox( width: double.infinity, height: 50, child: ElevatedButton( onPressed: () { if (nomeController.text.isEmpty) return; final storeData = StoreModel( id: store?.id, // Se nullo, Supabase ne crea uno nuovo nome: nomeController.text, indirizzo: indirizzoController.text, cap: capController.text, comune: comuneController.text, provincia: provinciaController.text, companyId: context .read() .state .company! .id, // Recuperiamo la companyId isActive: store?.isActive ?? true, isPaid: store?.isPaid ?? false, paymentExpiration: store?.paymentExpiration, ); // Chiamata al Bloc per il salvataggio context.read().add( CreateStoreRequested(store: storeData), ); Navigator.pop(context); }, child: Text(store == null ? "CREA NEGOZIO" : "AGGIORNA DATI"), ), ), ], ), ), ), ); } void _manageStoreStaff(StoreModel store) { showModalBottomSheet( context: context, isScrollControlled: true, builder: (context) => BlocBuilder( builder: (context, state) { return Container( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text("Personale di ${store.nome}", style: context.titleLarge), const SizedBox(height: 16), // Lista di TUTTO lo staff dell'azienda con checkbox ...state.allStaff.map((person) { final bool isAssigned = state.staffByStore[store.id!]?.any( (s) => s.id == person.id, ) ?? false; return CheckboxListTile( title: Text(person.name), value: isAssigned, onChanged: (selected) { if (selected == true) { context.read().assignMemberToStore( person.id!, store.id!, ); } else { context.read().removeMemberFromStore( person.id!, store.id!, ); } }, ); }), ], ), ); }, ), ); } }