pennellato git da rosso ad arancio e verde

This commit is contained in:
2026-04-21 11:26:42 +02:00
parent a19fd1104f
commit 09398a1b34
27 changed files with 237 additions and 389 deletions

View File

@@ -11,7 +11,7 @@ part 'product_state.dart';
class ProductCubit extends Cubit<ProductState> {
final ProductRepository _repository = GetIt.I<ProductRepository>();
final SessionBloc _sessionBloc = GetIt.I<SessionBloc>();
final SessionCubit _sessionCubit = GetIt.I<SessionCubit>();
ProductCubit() : super(const ProductState());
@@ -20,7 +20,7 @@ class ProductCubit extends Cubit<ProductState> {
emit(state.copyWith(status: ProductStatus.loading));
try {
final brands = await _repository.getBrands(
_sessionBloc.state.company!.id,
_sessionCubit.state.company!.id!,
);
emit(state.copyWith(status: ProductStatus.success, brands: brands));
} catch (e) {
@@ -54,7 +54,7 @@ class ProductCubit extends Cubit<ProductState> {
final brand = BrandModel(
id: id,
name: name,
companyId: _sessionBloc.state.company!.id,
companyId: _sessionCubit.state.company!.id!,
);
final newBrand = await _repository.upsertBrand(brand);
await loadBrands(); // Ricarichiamo la lista aggiornata
@@ -137,7 +137,10 @@ class ProductCubit extends Cubit<ProductState> {
// 1. Cerchiamo o creiamo il Brand
// (Usa una funzione upsert o una ricerca rapida nel repository)
brand ??= await _repository.upsertBrand(
BrandModel(name: brandName, companyId: _sessionBloc.state.company!.id),
BrandModel(
name: brandName,
companyId: _sessionCubit.state.company!.id!,
),
);
// 2. Creiamo il Modello legato al Brand

View File

@@ -52,7 +52,7 @@ class ProvidersState extends Equatable {
class ProvidersCubit extends Cubit<ProvidersState> {
final ProviderRepository _repository = GetIt.I<ProviderRepository>();
final SessionBloc _sessionBloc = GetIt.I<SessionBloc>();
final SessionCubit _sessionCubit = GetIt.I<SessionCubit>();
ProvidersCubit() : super(const ProvidersState());
@@ -61,7 +61,7 @@ class ProvidersCubit extends Cubit<ProvidersState> {
emit(state.copyWith(isLoading: true));
try {
final all = await _repository.fetchAllCompanyProviders(
_sessionBloc.state.company!.id,
_sessionCubit.state.company!.id!,
);
List<String> associated = [];
@@ -135,7 +135,7 @@ class ProvidersCubit extends Cubit<ProvidersState> {
) async {
emit(state.copyWith(isLoading: true));
// Assicuriamoci di settare la companyId prima di salvare
provider = provider.copyWith(companyId: _sessionBloc.state.company!.id);
provider = provider.copyWith(companyId: _sessionCubit.state.company!.id);
try {
// 1. Salviamo l'anagrafica (upsert)
// Se è un nuovo provider, l'ID potrebbe essere generato qui dal DB

View File

@@ -10,7 +10,7 @@ part 'staff_state.dart';
class StaffCubit extends Cubit<StaffState> {
final StaffRepository _repository = GetIt.I.get<StaffRepository>();
final SessionBloc _sessionBloc = GetIt.I<SessionBloc>();
final SessionCubit _sessionCubit = GetIt.I<SessionCubit>();
StaffCubit() : super(const StaffState());
@@ -19,7 +19,7 @@ class StaffCubit extends Cubit<StaffState> {
emit(state.copyWith(isLoading: true, error: null));
try {
final staff = await _repository.getStaffMembers(
_sessionBloc.state.company!.id,
_sessionCubit.state.company!.id!,
);
final Map<String, List<StoreModel>> storesByStaff = {};
for (StaffMemberModel member in staff) {

View File

@@ -18,44 +18,61 @@ enum SystemRole {
class StaffMemberModel extends Equatable {
final String? id;
final String companyId;
final String storeId;
final String userId;
final String name;
final String surname;
final String?
jobTitle; // Testo libero! Il cliente ci scrive quello che vuole.
final SystemRole systemRole; // ENUM! Il sistema non si frega.
final String? email;
final String? phoneNumber;
final String? jobTitle;
final SystemRole systemRole;
final bool isActive;
const StaffMemberModel({
this.id,
required this.companyId,
required this.storeId,
required this.userId,
required this.name,
required this.surname,
this.email,
this.phoneNumber,
this.jobTitle,
this.systemRole = SystemRole.user, // Sicurezza di default
this.systemRole = SystemRole.user,
this.isActive = true,
});
StaffMemberModel copyWith({
String? id,
String? companyId,
String? storeId,
String? userId,
String? name,
String? surname,
String? email,
String? phoneNumber,
String? jobTitle,
SystemRole? systemRole,
bool? isActive,
}) {
return StaffMemberModel(
id: id ?? this.id,
companyId: companyId ?? this.companyId,
storeId: storeId ?? this.storeId,
userId: userId ?? this.userId,
name: name ?? this.name,
surname: surname ?? this.surname,
email: email ?? this.email,
phoneNumber: phoneNumber ?? this.phoneNumber,
jobTitle: jobTitle ?? this.jobTitle,
systemRole: systemRole ?? this.systemRole,
isActive: isActive ?? this.isActive,
);
}
factory StaffMemberModel.empty() {
return const StaffMemberModel(
companyId: '',
userId: '',
name: '',
email: '',
phoneNumber: '',
jobTitle: '',
systemRole: SystemRole.user,
isActive: true,
);
}
@@ -63,14 +80,13 @@ class StaffMemberModel extends Equatable {
return StaffMemberModel(
id: map['id'] as String?,
companyId: map['company_id'] ?? '',
storeId: map['store_id'] ?? '',
userId: map['user_id'] ?? '',
name: map['name'] ?? '',
surname: map['surname'] ?? '',
jobTitle: map['job_title'] as String?, // Semplice stringa
systemRole: SystemRole.fromString(
map['system_role'],
), // Lettura tipizzata
email: map['email'] as String?,
phoneNumber: map['phone_number'] as String?,
jobTitle: map['job_title'] as String?,
systemRole: SystemRole.fromString(map['system_role']),
isActive: map['is_active'] ?? true,
);
}
@@ -78,12 +94,13 @@ class StaffMemberModel extends Equatable {
return {
if (id != null) 'id': id,
'company_id': companyId,
'store_id': storeId,
'user_id': userId,
'name': name,
'surname': surname,
if (email != null) 'email': email,
if (phoneNumber != null) 'phone_number': phoneNumber,
if (jobTitle != null) 'job_title': jobTitle,
'system_role': systemRole.name, // Trasforma SystemRole.admin in 'admin'
'is_active': isActive,
};
}
@@ -91,11 +108,12 @@ class StaffMemberModel extends Equatable {
List<Object?> get props => [
id,
companyId,
storeId,
userId,
name,
surname,
email,
phoneNumber,
jobTitle,
systemRole,
isActive,
];
}

View File

@@ -135,8 +135,13 @@ class _StaffScreenState extends State<StaffScreen> {
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (member.email.isNotEmpty) Text(member.email),
Text(member.phone.isNotEmpty ? member.phone : "Nessun telefono"),
if (member.email != null && member.email!.isNotEmpty)
Text(member.email!),
Text(
member.phoneNumber != null && member.phoneNumber!.isNotEmpty
? member.phoneNumber!
: "Nessun telefono",
),
],
),
trailing: const Icon(Icons.edit_note),
@@ -148,7 +153,7 @@ class _StaffScreenState extends State<StaffScreen> {
void _openStaffForm(BuildContext context, {StaffMemberModel? member}) {
final nameController = TextEditingController(text: member?.name);
final emailController = TextEditingController(text: member?.email);
final phoneController = TextEditingController(text: member?.phone);
final phoneController = TextEditingController(text: member?.phoneNumber);
// 1. Inizializziamo la lista temporanea attingendo dallo stato del Cubit
// Usiamo storesByStaff (la mappa che indicizza i negozi per ogni ID dipendente)
@@ -264,16 +269,16 @@ class _StaffScreenState extends State<StaffScreen> {
child: ElevatedButton(
onPressed: () {
final companyId = context
.read<SessionBloc>()
.read<SessionCubit>()
.state
.company!
.id;
final updatedMember = StaffMemberModel(
.id!;
//TODO sistemare StaffScreen per il nuovo modello
/* final updatedMember = StaffMemberModel(
id: member?.id,
name: nameController.text,
email: emailController.text,
phone: phoneController.text,
phoneNumber: phoneController.text,
companyId: companyId,
);
@@ -281,7 +286,7 @@ class _StaffScreenState extends State<StaffScreen> {
context.read<StaffCubit>().saveStaffWithStores(
member: updatedMember,
selectedStoreIds: tempSelectedStores,
);
); */
Navigator.pop(context);
},

View File

@@ -13,7 +13,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 = GetIt.I<SessionBloc>();
final SessionCubit _sessionCubit = GetIt.I<SessionCubit>();
StoreCubit() : super(const StoreState(stores: []));
@@ -33,7 +33,7 @@ class StoreCubit extends Cubit<StoreState> {
emit(state.copyWith(status: StoreStatus.loading));
try {
final stores = await _repository.fetchAllCompanyStores(
_sessionBloc.state.company!.id,
_sessionCubit.state.company!.id!,
);
final Map<String, List<StaffMemberModel>> staffByStore = {};
for (StoreModel store in stores) {

View File

@@ -81,6 +81,17 @@ class StoreModel extends Equatable {
);
}
factory StoreModel.empty() {
return const StoreModel(
nome: '',
companyId: '',
indirizzo: '',
cap: '',
comune: '',
provincia: '',
);
}
factory StoreModel.fromMap(Map<String, dynamic> map) {
final providersPivotList = map['associated_providers'] as List?;
List<ProviderModel> providers = [];

View File

@@ -34,7 +34,7 @@ class _CreateStoreScreenState extends State<CreateStoreScreen> {
/// Funzione magica per copiare i dati dall'azienda salvata in GetIt
void _useCompanyAddress() {
final company = context.read<SessionBloc>().state.company;
final company = context.read<SessionCubit>().state.company;
if (company != null) {
setState(() {
_indirizzoController.text = company.indirizzo;
@@ -58,7 +58,7 @@ class _CreateStoreScreenState extends State<CreateStoreScreen> {
void _onSave() {
if (_formKey.currentState!.validate()) {
final company = context.read<SessionBloc>().state.company;
final company = context.read<SessionCubit>().state.company;
if (company == null) {
ScaffoldMessenger.of(context).showSnackBar(
@@ -69,7 +69,7 @@ class _CreateStoreScreenState extends State<CreateStoreScreen> {
final store = StoreModel(
nome: _nomeController.text.trim(),
companyId: company.id,
companyId: company.id!,
indirizzo: _indirizzoController.text.trim(),
cap: _capController.text.trim(),
comune: _comuneController.text.trim(),
@@ -84,10 +84,10 @@ class _CreateStoreScreenState extends State<CreateStoreScreen> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Il tuo primo Negozio')),
body: BlocConsumer<StoreCubit, StoreState>(
listener: (context, state) {
body: BlocBuilder<StoreCubit, StoreState>(
/* listener: (context, state) {
if (state.status == StoreStatus.success) {
context.read<SessionBloc>().add(AppStarted());
context.read<SessionCubit>().;
}
if (state.status == StoreStatus.failure) {
ScaffoldMessenger.of(context).showSnackBar(
@@ -96,7 +96,7 @@ class _CreateStoreScreenState extends State<CreateStoreScreen> {
),
);
}
},
}, */
builder: (context, state) {
return SafeArea(
child: SingleChildScrollView(

View File

@@ -130,10 +130,10 @@ class _StoreFormState extends State<StoreForm> {
comune: comuneController.text,
provincia: provinciaController.text,
companyId: context
.read<SessionBloc>()
.read<SessionCubit>()
.state
.company!
.id, // Recuperiamo la companyId
.id!, // Recuperiamo la companyId
isActive: widget.store?.isActive ?? true,
isPaid: widget.store?.isPaid ?? false,
paymentExpiration: widget.store?.paymentExpiration,