refined responsive ui for dashboard and start customer work

This commit is contained in:
2026-04-10 10:47:56 +02:00
parent e06f7329f0
commit 8d6e8647b1
13 changed files with 543 additions and 503 deletions

View File

@@ -0,0 +1,82 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flux/features/customers/data/customer_repository.dart';
import 'package:flux/features/customers/models/customer_model.dart';
import 'package:get_it/get_it.dart';
part 'customer_events.dart';
part 'customer_state.dart';
class CustomerBloc extends Bloc<CustomerEvent, CustomerState> {
final CustomerRepository _repository = GetIt.I<CustomerRepository>();
CustomerBloc() : super(const CustomerState()) {
on<LoadCustomersRequested>(_onLoadCustomers);
on<CreateCustomerRequested>(_onCreateCustomer);
on<SearchCustomersRequested>(_onSearchCustomers);
}
Future<void> _onLoadCustomers(
LoadCustomersRequested event,
Emitter<CustomerState> emit,
) async {
emit(state.copyWith(status: CustomerStatus.loading));
try {
final customers = await _repository.getCustomers(event.companyId);
emit(
state.copyWith(status: CustomerStatus.success, customers: customers),
);
} catch (e) {
emit(
state.copyWith(
status: CustomerStatus.failure,
errorMessage: e.toString(),
),
);
}
}
Future<void> _onCreateCustomer(
CreateCustomerRequested event,
Emitter<CustomerState> emit,
) async {
emit(state.copyWith(status: CustomerStatus.loading));
try {
final newCustomer = await _repository.createCustomer(event.customer);
// Aggiorniamo la lista locale aggiungendo il nuovo cliente in cima
final updatedList = List<CustomerModel>.from(state.customers)
..insert(0, newCustomer);
emit(
state.copyWith(
status: CustomerStatus.success,
customers: updatedList,
lastCreatedCustomer:
newCustomer, // Lo passiamo per le Dialog "al volo"
),
);
} catch (e) {
emit(
state.copyWith(
status: CustomerStatus.failure,
errorMessage: e.toString(),
),
);
}
}
Future<void> _onSearchCustomers(
SearchCustomersRequested event,
Emitter<CustomerState> emit,
) async {
// Non mettiamo loading per evitare flickering durante la digitazione
try {
final results = await _repository.searchCustomers(
event.companyId,
event.query,
);
emit(state.copyWith(status: CustomerStatus.success, customers: results));
} catch (_) {}
}
}

View File

@@ -0,0 +1,26 @@
part of 'customer_bloc.dart';
abstract class CustomerEvent extends Equatable {
const CustomerEvent();
@override
List<Object?> get props => [];
}
// Carica tutti i clienti dell'azienda
class LoadCustomersRequested extends CustomerEvent {
final String companyId;
const LoadCustomersRequested(this.companyId);
}
// Crea un cliente (usato sia dalla lista che dalla Dialog operazioni)
class CreateCustomerRequested extends CustomerEvent {
final CustomerModel customer;
const CreateCustomerRequested(this.customer);
}
// Ricerca in tempo reale
class SearchCustomersRequested extends CustomerEvent {
final String companyId;
final String query;
const SearchCustomersRequested(this.companyId, this.query);
}

View File

@@ -0,0 +1,40 @@
part of 'customer_bloc.dart';
enum CustomerStatus { initial, loading, success, failure }
class CustomerState extends Equatable {
final CustomerStatus status;
final List<CustomerModel> customers; // Per la lista generale
final CustomerModel?
lastCreatedCustomer; // <--- Fondamentale per la Dialog "al volo"
final String? errorMessage;
const CustomerState({
this.status = CustomerStatus.initial,
this.customers = const [],
this.lastCreatedCustomer,
this.errorMessage,
});
CustomerState copyWith({
CustomerStatus? status,
List<CustomerModel>? customers,
CustomerModel? lastCreatedCustomer,
String? errorMessage,
}) {
return CustomerState(
status: status ?? this.status,
customers: customers ?? this.customers,
lastCreatedCustomer: lastCreatedCustomer ?? this.lastCreatedCustomer,
errorMessage: errorMessage ?? this.errorMessage,
);
}
@override
List<Object?> get props => [
status,
customers,
lastCreatedCustomer,
errorMessage,
];
}