Fix: Gestione dipendenti nei negozi funzionante con doppio Cubit e UI reattiva

This commit is contained in:
2026-04-15 09:58:27 +02:00
parent 7b3dc449a6
commit 92febadd61
3 changed files with 111 additions and 40 deletions

View File

@@ -1,6 +1,8 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flux/core/blocs/session/session_bloc.dart';
import 'package:flux/features/master_data/staff/data/staff_repository.dart';
import 'package:flux/features/master_data/staff/models/staff_member_model.dart';
import 'package:flux/features/master_data/store/data/store_repository.dart';
import 'package:flux/features/master_data/store/models/store_model.dart';
import 'package:get_it/get_it.dart';
@@ -9,6 +11,7 @@ part 'store_state.dart';
class StoreCubit extends Cubit<StoreState> {
final StoreRepository _repository = GetIt.I<StoreRepository>();
final StaffRepository _staffRepository = GetIt.I<StaffRepository>();
final SessionBloc _sessionBloc;
StoreCubit(this._sessionBloc) : super(const StoreState(stores: []));
@@ -31,10 +34,17 @@ class StoreCubit extends Cubit<StoreState> {
final stores = await _repository.getStoresByCompany(
_sessionBloc.state.company!.id,
);
final Map<String, List<StaffMemberModel>> staffByStore = {};
for (StoreModel store in stores) {
staffByStore[store.id!] = await _staffRepository.getStaffMembersInStore(
store.id!,
);
}
emit(
state.copyWith(
status: StoreStatus.success,
stores: stores, // Assicurati di avere 'stores' nello StoreState
stores: stores,
staffByStore: staffByStore,
),
);
} catch (e) {
@@ -43,4 +53,45 @@ class StoreCubit extends Cubit<StoreState> {
);
}
}
Future<void> assignStaffToStore(String storeId, String staffId) async {
try {
await _staffRepository.assignToStore(staffId, storeId);
// Dopo l'assegnazione, potresti voler ricaricare lo staff per quel negozio
final updatedStaff = await _staffRepository.getStaffMembersInStore(
storeId,
);
final newMap = Map<String, List<StaffMemberModel>>.from(
state.staffByStore,
);
newMap[storeId] = updatedStaff;
emit(state.copyWith(status: StoreStatus.success, staffByStore: newMap));
} catch (e) {
emit(
state.copyWith(status: StoreStatus.failure, errorMessage: e.toString()),
);
}
}
// Rimuove un dipendente da un negozio
Future<void> removeStaffFromStore(String staffId, String storeId) async {
try {
await _staffRepository.removeFromStore(staffId, storeId);
final updatedStaff = await _staffRepository.getStaffMembersInStore(
storeId,
);
final newMap = Map<String, List<StaffMemberModel>>.from(
state.staffByStore,
);
newMap[storeId] = updatedStaff;
emit(state.copyWith(staffByStore: newMap));
} catch (e) {
emit(
state.copyWith(
status: StoreStatus.failure,
errorMessage: "Errore nella rimozione: $e",
),
);
}
}
}

View File

@@ -7,12 +7,14 @@ class StoreState extends Equatable {
final StoreModel? store;
final String? errorMessage;
final List<StoreModel> stores;
final Map<String, List<StaffMemberModel>> staffByStore;
const StoreState({
this.status = StoreStatus.initial,
this.store,
this.errorMessage,
required this.stores,
this.staffByStore = const {},
});
StoreState copyWith({
@@ -20,15 +22,23 @@ class StoreState extends Equatable {
StoreModel? store,
String? errorMessage,
List<StoreModel>? stores,
Map<String, List<StaffMemberModel>>? staffByStore,
}) {
return StoreState(
status: status ?? this.status,
store: store ?? this.store,
errorMessage: errorMessage ?? this.errorMessage,
stores: stores ?? this.stores,
staffByStore: staffByStore ?? this.staffByStore,
);
}
@override
List<Object?> get props => [status, store, errorMessage, stores];
List<Object?> get props => [
status,
store,
errorMessage,
stores,
staffByStore,
];
}

View File

@@ -90,10 +90,10 @@ class _StoresScreenState extends State<StoresScreen> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Mostra quanti dipendenti ci sono (usando lo StaffCubit)
BlocBuilder<StaffCubit, StaffState>(
builder: (context, staffState) {
BlocBuilder<StoreCubit, StoreState>(
builder: (context, storeState) {
final staffCount =
staffState.storesByStaff[store.id]?.length ?? 0;
storeState.staffByStore[store.id]?.length ?? 0;
return ActionChip(
avatar: const Icon(Icons.people, size: 16),
label: Text("$staffCount Dipendenti"),
@@ -119,33 +119,41 @@ class _StoresScreenState extends State<StoresScreen> {
context: context,
isScrollControlled: true,
builder: (context) => BlocBuilder<StaffCubit, StaffState>(
builder: (context, state) {
// 1. Prendi TUTTI i dipendenti
builder: (context, staffState) {
return BlocBuilder<StoreCubit, StoreState>(
// 2. Prendi le ASSEGNAZIONI
builder: (context, storeState) {
final assignedToThisStore =
storeState.staffByStore[store.id!] ?? [];
return Container(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("Personale di ${store.nome}", style: context.titleLarge),
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.storesByStaff[store.id!]?.any(
...staffState.allStaff.map((person) {
// La spunta deve dipendere dallo StoreCubit!
final bool isAssigned = assignedToThisStore.any(
(s) => s.id == person.id,
) ??
false;
);
return CheckboxListTile(
title: Text(person.name),
value: isAssigned,
onChanged: (selected) {
if (selected == true) {
context.read<StaffCubit>().assignMemberToStore(
person.id!,
context.read<StoreCubit>().assignStaffToStore(
store.id!,
person.id!,
);
} else {
context.read<StaffCubit>().removeMemberFromStore(
context.read<StoreCubit>().removeStaffFromStore(
person.id!,
store.id!,
);
@@ -157,6 +165,8 @@ class _StoresScreenState extends State<StoresScreen> {
),
);
},
);
},
),
);
}