2026-04-26 16:29:31 +02:00
|
|
|
import 'dart:math';
|
|
|
|
|
|
2026-04-14 11:29:49 +02:00
|
|
|
import 'package:equatable/equatable.dart';
|
|
|
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
2026-04-22 11:06:02 +02:00
|
|
|
import 'package:flux/core/blocs/session/session_cubit.dart';
|
2026-04-14 11:29:49 +02:00
|
|
|
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/models/store_model.dart';
|
|
|
|
|
import 'package:get_it/get_it.dart';
|
|
|
|
|
|
|
|
|
|
part 'staff_state.dart';
|
|
|
|
|
|
|
|
|
|
class StaffCubit extends Cubit<StaffState> {
|
|
|
|
|
final StaffRepository _repository = GetIt.I.get<StaffRepository>();
|
2026-04-22 11:06:02 +02:00
|
|
|
final SessionCubit _sessionCubit = GetIt.I<SessionCubit>();
|
2026-04-14 11:29:49 +02:00
|
|
|
|
2026-04-20 16:52:20 +02:00
|
|
|
StaffCubit() : super(const StaffState());
|
2026-04-14 11:29:49 +02:00
|
|
|
|
|
|
|
|
// Carica tutto lo staff della compagnia
|
|
|
|
|
Future<void> loadAllStaff() async {
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(status: StaffStatus.loading, error: null));
|
2026-04-14 11:29:49 +02:00
|
|
|
try {
|
|
|
|
|
final staff = await _repository.getStaffMembers(
|
2026-04-22 11:06:02 +02:00
|
|
|
_sessionCubit.state.company!.id!,
|
2026-04-14 11:29:49 +02:00
|
|
|
);
|
|
|
|
|
final Map<String, List<StoreModel>> storesByStaff = {};
|
|
|
|
|
for (StaffMemberModel member in staff) {
|
|
|
|
|
storesByStaff[member.id!] = await loadStoresByStaff(member.id!);
|
|
|
|
|
}
|
|
|
|
|
emit(
|
|
|
|
|
state.copyWith(
|
2026-04-26 16:29:31 +02:00
|
|
|
status: StaffStatus.success,
|
2026-04-14 11:29:49 +02:00
|
|
|
allStaff: staff,
|
|
|
|
|
storesByStaff: storesByStaff,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
} catch (e) {
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(status: StaffStatus.error, error: e.toString()));
|
2026-04-14 11:29:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<List<StoreModel>> loadStoresByStaff(String staffId) async {
|
|
|
|
|
try {
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(error: null));
|
2026-04-14 11:29:49 +02:00
|
|
|
return await _repository.getStaffMemberStore(staffId);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
emit(state.copyWith(error: e.toString()));
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Carica lo staff di uno specifico negozio e aggiorna la mappa
|
|
|
|
|
Future<void> loadStaffForStore(String storeId) async {
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(error: null));
|
2026-04-14 11:29:49 +02:00
|
|
|
try {
|
|
|
|
|
final staffInStore = await _repository.getStaffMembersInStore(storeId);
|
|
|
|
|
final newMap = Map<String, List<StaffMemberModel>>.from(
|
|
|
|
|
state.staffByStore,
|
|
|
|
|
);
|
|
|
|
|
newMap[storeId] = staffInStore;
|
|
|
|
|
emit(state.copyWith(staffByStore: newMap));
|
|
|
|
|
} catch (e) {
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(status: StaffStatus.error, error: e.toString()));
|
2026-04-14 11:29:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Salva o aggiorna un membro
|
|
|
|
|
Future<void> saveStaffMember(StaffMemberModel member) async {
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(status: StaffStatus.loading, error: null));
|
2026-04-14 11:29:49 +02:00
|
|
|
try {
|
|
|
|
|
await _repository.saveStaffMember(member);
|
|
|
|
|
await loadAllStaff(); // Ricarichiamo la lista aggiornata
|
|
|
|
|
} catch (e) {
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(status: StaffStatus.error, error: e.toString()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> inviteStaffMember({
|
|
|
|
|
required StaffMemberModel member,
|
|
|
|
|
required List<String> selectedStoreIds,
|
|
|
|
|
}) async {
|
|
|
|
|
emit(state.copyWith(status: StaffStatus.loading, error: null));
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 1. Invitiamo il membro e ci facciamo dare l'ID
|
|
|
|
|
final newStaffId = await _repository.inviteStaffMember(member);
|
|
|
|
|
|
|
|
|
|
// 2. Assegniamo i negozi uno ad uno (usando il metodo che avevi già nel repo!)
|
|
|
|
|
if (selectedStoreIds.isNotEmpty) {
|
|
|
|
|
final List<Future> assignTasks = [];
|
|
|
|
|
for (var storeId in selectedStoreIds) {
|
|
|
|
|
assignTasks.add(_repository.assignStaffToStore(newStaffId, storeId));
|
|
|
|
|
}
|
|
|
|
|
await Future.wait(assignTasks); // In parallelo per la massima velocità
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. Ricarichiamo la lista globale così la UI si aggiorna
|
|
|
|
|
await loadAllStaff();
|
|
|
|
|
// (Nota: se hai un loadStaffForStore o loadAllStaff, chiamalo qui per rinfrescare lo stato)
|
|
|
|
|
|
|
|
|
|
emit(state.copyWith(status: StaffStatus.success));
|
|
|
|
|
} catch (e) {
|
|
|
|
|
emit(state.copyWith(status: StaffStatus.error, error: e.toString()));
|
2026-04-14 11:29:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Associa un dipendente a un negozio
|
|
|
|
|
Future<void> assignMemberToStore(String staffId, String storeId) async {
|
|
|
|
|
try {
|
2026-04-26 16:29:31 +02:00
|
|
|
await _repository.assignStaffToStore(staffId, storeId);
|
2026-04-14 11:29:49 +02:00
|
|
|
final stuffStores = await loadStoresByStaff(staffId);
|
|
|
|
|
final Map<String, List<StoreModel>> storesByStaff = Map.from(
|
|
|
|
|
state.storesByStaff,
|
|
|
|
|
);
|
|
|
|
|
storesByStaff[staffId] = stuffStores;
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(storesByStaff: storesByStaff, error: null));
|
2026-04-14 11:29:49 +02:00
|
|
|
} catch (e) {
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(
|
|
|
|
|
state.copyWith(
|
|
|
|
|
status: StaffStatus.error,
|
|
|
|
|
error: "Errore nell'assegnazione: $e",
|
|
|
|
|
),
|
|
|
|
|
);
|
2026-04-14 11:29:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Rimuove un dipendente da un negozio
|
|
|
|
|
Future<void> removeMemberFromStore(String staffId, String storeId) async {
|
|
|
|
|
try {
|
2026-04-26 16:29:31 +02:00
|
|
|
await _repository.removeStaffFromStore(staffId, storeId);
|
2026-04-14 11:29:49 +02:00
|
|
|
final stuffStores = await loadStoresByStaff(staffId);
|
|
|
|
|
final Map<String, List<StoreModel>> storesByStaff = Map.from(
|
|
|
|
|
state.storesByStaff,
|
|
|
|
|
);
|
|
|
|
|
storesByStaff[staffId] = stuffStores;
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(storesByStaff: storesByStaff, error: null));
|
2026-04-14 11:29:49 +02:00
|
|
|
} catch (e) {
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(
|
|
|
|
|
state.copyWith(
|
|
|
|
|
status: StaffStatus.error,
|
|
|
|
|
error: "Errore nella rimozione: $e",
|
|
|
|
|
),
|
|
|
|
|
);
|
2026-04-14 11:29:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> saveStaffWithStores({
|
|
|
|
|
required StaffMemberModel member,
|
|
|
|
|
required List<String> selectedStoreIds,
|
|
|
|
|
}) async {
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(status: StaffStatus.loading, error: null));
|
2026-04-14 11:29:49 +02:00
|
|
|
try {
|
|
|
|
|
// 1. Salva o aggiorna l'anagrafica (ci serve l'ID)
|
|
|
|
|
// Se è un nuovo membro, Supabase ci restituirà l'ID generato
|
|
|
|
|
final savedMember = await _repository.saveStaffMember(member);
|
|
|
|
|
final String staffId = savedMember.id!;
|
|
|
|
|
|
|
|
|
|
// 2. Sincronizzazione Negozi
|
|
|
|
|
// Per semplicità e pulizia, rimuoviamo le vecchie assegnazioni e inseriamo le nuove
|
|
|
|
|
// (Oppure facciamo un confronto tra liste, ma il reset & rewrite è più sicuro qui)
|
|
|
|
|
await _repository.clearStoreAssignments(staffId);
|
|
|
|
|
|
|
|
|
|
if (selectedStoreIds.isNotEmpty) {
|
|
|
|
|
await Future.wait(
|
|
|
|
|
selectedStoreIds.map(
|
2026-04-26 16:29:31 +02:00
|
|
|
(storeId) => _repository.assignStaffToStore(staffId, storeId),
|
2026-04-14 11:29:49 +02:00
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. Rinfresca i dati
|
|
|
|
|
await loadAllStaff();
|
|
|
|
|
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(status: StaffStatus.success));
|
2026-04-14 11:29:49 +02:00
|
|
|
} catch (e) {
|
2026-04-26 16:29:31 +02:00
|
|
|
emit(state.copyWith(status: StaffStatus.error, error: e.toString()));
|
2026-04-14 11:29:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|