refactot ticket model + cubit
This commit is contained in:
169
lib/features/tickets/blocs/ticket_form_cubit.dart
Normal file
169
lib/features/tickets/blocs/ticket_form_cubit.dart
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||||
|
import 'package:flux/features/customers/models/customer_model.dart';
|
||||||
|
import 'package:flux/features/tickets/models/ticket_model.dart';
|
||||||
|
import 'package:flux/features/tickets/data/ticket_repository.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'ticket_form_state.dart';
|
||||||
|
|
||||||
|
class TicketFormCubit extends Cubit<TicketFormState> {
|
||||||
|
final TicketRepository _repository = GetIt.I.get<TicketRepository>();
|
||||||
|
final SessionCubit _sessionCubit = GetIt.I.get<SessionCubit>();
|
||||||
|
|
||||||
|
TicketFormCubit()
|
||||||
|
: super(
|
||||||
|
// Inizializziamo con un ticket vuoto di default
|
||||||
|
TicketFormState(
|
||||||
|
ticket: TicketModel.empty(
|
||||||
|
companyId: GetIt.I.get<SessionCubit>().state.company!.id!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 1. INIZIALIZZAZIONE (Se stiamo modificando un ticket esistente)
|
||||||
|
void initForm(TicketModel? existingTicket) {
|
||||||
|
if (existingTicket != null) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(ticket: existingTicket, status: TicketFormStatus.ready),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// È un nuovo ticket! Inseriamo i default base (Azienda, Negozio, Creatore)
|
||||||
|
final currentUser = _sessionCubit.state.currentStaffMember;
|
||||||
|
final currentStore = _sessionCubit.state.currentStore;
|
||||||
|
final companyId = _sessionCubit.state.company?.id ?? '';
|
||||||
|
|
||||||
|
final newTicket =
|
||||||
|
TicketModel.empty(
|
||||||
|
companyId: _sessionCubit.state.company!.id!,
|
||||||
|
).copyWith(
|
||||||
|
companyId: companyId,
|
||||||
|
storeId: currentStore?.id,
|
||||||
|
staffId: currentUser?.id,
|
||||||
|
createdById: currentUser?.name,
|
||||||
|
// Impostiamo lo stato iniziale
|
||||||
|
status: TicketStatus.open,
|
||||||
|
ticketType: TicketType.repair, // Default
|
||||||
|
);
|
||||||
|
|
||||||
|
emit(state.copyWith(ticket: newTicket, status: TicketFormStatus.ready));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 2. AGGIORNAMENTO CLIENTE (Usato dal nostro SharedCustomerSection!)
|
||||||
|
void updateCustomer(CustomerModel customer) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
ticket: state.ticket.copyWith(
|
||||||
|
customerId: customer.id,
|
||||||
|
customerName: customer.name,
|
||||||
|
alternativePhoneNumber: customer.phoneNumber, // Comodo come fallback!
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 3. AGGIORNAMENTO MODELLO (Usato dal nostro SharedModelSection!)
|
||||||
|
void updateModel({required String modelId, required String modelName}) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
ticket: state.ticket.copyWith(
|
||||||
|
targetModelId: modelId,
|
||||||
|
targetModelName: modelName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateCreator({required String staffId, required String staffName}) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
ticket: state.ticket.copyWith(staffId: staffId, createdById: staffName),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 4. AGGIORNAMENTO GENERICO DEI CAMPI
|
||||||
|
void updateFields({
|
||||||
|
TicketType? ticketType,
|
||||||
|
TicketStatus? status,
|
||||||
|
String? request,
|
||||||
|
String? targetSn,
|
||||||
|
String? alternativePhoneNumber,
|
||||||
|
bool? hasCourtesyDevice,
|
||||||
|
String? includedAccessories,
|
||||||
|
String? publicNotes,
|
||||||
|
String? internalNotes,
|
||||||
|
double? customerPrice,
|
||||||
|
double? internalCost,
|
||||||
|
String? assignedToId,
|
||||||
|
String? assignedToName,
|
||||||
|
}) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
ticket: state.ticket.copyWith(
|
||||||
|
ticketType: ticketType ?? state.ticket.ticketType,
|
||||||
|
status: status ?? state.ticket.status,
|
||||||
|
request: request ?? state.ticket.request,
|
||||||
|
targetSn: targetSn ?? state.ticket.targetSn,
|
||||||
|
alternativePhoneNumber:
|
||||||
|
alternativePhoneNumber ?? state.ticket.alternativePhoneNumber,
|
||||||
|
hasCourtesyDevice:
|
||||||
|
hasCourtesyDevice ?? state.ticket.hasCourtesyDevice,
|
||||||
|
includedAccessories:
|
||||||
|
includedAccessories ?? state.ticket.includedAccessories,
|
||||||
|
publicNotes: publicNotes ?? state.ticket.publicNotes,
|
||||||
|
internalNotes: internalNotes ?? state.ticket.internalNotes,
|
||||||
|
customerPrice: customerPrice ?? state.ticket.customerPrice,
|
||||||
|
internalCost: internalCost ?? state.ticket.internalCost,
|
||||||
|
assignedToId: assignedToId ?? state.ticket.assignedToId,
|
||||||
|
assignedToName: assignedToName ?? state.ticket.assignedToName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 5. SALVATAGGIO
|
||||||
|
Future<void> saveTicket({required bool keepAdding}) async {
|
||||||
|
emit(state.copyWith(status: TicketFormStatus.saving));
|
||||||
|
|
||||||
|
try {
|
||||||
|
final ticketToSave = state.ticket;
|
||||||
|
|
||||||
|
// Validazione base
|
||||||
|
if (ticketToSave.customerId == null || ticketToSave.customerId!.isEmpty) {
|
||||||
|
throw Exception("Seleziona un cliente prima di salvare.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final savedTicket = await _repository.saveTicket(ticketToSave);
|
||||||
|
|
||||||
|
if (keepAdding) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
status: TicketFormStatus.successAndAddAnother,
|
||||||
|
// Svuotiamo il form per il prossimo, mantenendo Store e Creatore ATTUALI
|
||||||
|
ticket: TicketModel.empty().copyWith(
|
||||||
|
companyId: savedTicket.companyId,
|
||||||
|
storeId: savedTicket.storeId,
|
||||||
|
createdById: ticketToSave
|
||||||
|
.createdById, // Manteniamo quello selezionato nella tendina!
|
||||||
|
createdByName: ticketToSave.createdByName,
|
||||||
|
status: TicketStatus.open,
|
||||||
|
ticketType: TicketType.repair,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
emit(
|
||||||
|
state.copyWith(status: TicketFormStatus.success, ticket: savedTicket),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
status: TicketFormStatus.failure,
|
||||||
|
errorMessage: e.toString(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
lib/features/tickets/blocs/ticket_form_state.dart
Normal file
40
lib/features/tickets/blocs/ticket_form_state.dart
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flux/features/tickets/models/ticket_model.dart';
|
||||||
|
// Adatta gli import al tuo progetto!
|
||||||
|
|
||||||
|
enum TicketFormStatus {
|
||||||
|
initial,
|
||||||
|
ready,
|
||||||
|
loading,
|
||||||
|
saving,
|
||||||
|
success,
|
||||||
|
successAndAddAnother,
|
||||||
|
failure,
|
||||||
|
}
|
||||||
|
|
||||||
|
class TicketFormState extends Equatable {
|
||||||
|
final TicketModel ticket;
|
||||||
|
final TicketFormStatus status;
|
||||||
|
final String? errorMessage;
|
||||||
|
|
||||||
|
const TicketFormState({
|
||||||
|
required this.ticket,
|
||||||
|
this.status = TicketFormStatus.initial,
|
||||||
|
this.errorMessage,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [ticket, status, errorMessage];
|
||||||
|
|
||||||
|
TicketFormState copyWith({
|
||||||
|
TicketModel? ticket,
|
||||||
|
TicketFormStatus? status,
|
||||||
|
String? errorMessage,
|
||||||
|
}) {
|
||||||
|
return TicketFormState(
|
||||||
|
ticket: ticket ?? this.ticket,
|
||||||
|
status: status ?? this.status,
|
||||||
|
errorMessage: errorMessage,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -96,7 +96,6 @@ class TicketModel extends Equatable {
|
|||||||
final DateTime? closedAt;
|
final DateTime? closedAt;
|
||||||
final DateTime? returnedAt;
|
final DateTime? returnedAt;
|
||||||
final String request;
|
final String request;
|
||||||
final String? staffId;
|
|
||||||
final WarrantyType? warrantyType;
|
final WarrantyType? warrantyType;
|
||||||
final String? publicNotes;
|
final String? publicNotes;
|
||||||
final String? internalNotes;
|
final String? internalNotes;
|
||||||
@@ -112,7 +111,10 @@ class TicketModel extends Equatable {
|
|||||||
final String? customerName;
|
final String? customerName;
|
||||||
final String? targetModelName;
|
final String? targetModelName;
|
||||||
final String? sourceModelName;
|
final String? sourceModelName;
|
||||||
final String? staffName;
|
final String? createdById;
|
||||||
|
final String? createdByName;
|
||||||
|
final String? assignedToId;
|
||||||
|
final String? assignedToName;
|
||||||
final String? includedAccessories;
|
final String? includedAccessories;
|
||||||
|
|
||||||
const TicketModel({
|
const TicketModel({
|
||||||
@@ -130,7 +132,6 @@ class TicketModel extends Equatable {
|
|||||||
this.closedAt,
|
this.closedAt,
|
||||||
this.returnedAt,
|
this.returnedAt,
|
||||||
this.request = '',
|
this.request = '',
|
||||||
this.staffId,
|
|
||||||
this.warrantyType,
|
this.warrantyType,
|
||||||
this.publicNotes,
|
this.publicNotes,
|
||||||
this.internalNotes,
|
this.internalNotes,
|
||||||
@@ -146,14 +147,17 @@ class TicketModel extends Equatable {
|
|||||||
this.customerName,
|
this.customerName,
|
||||||
this.targetModelName,
|
this.targetModelName,
|
||||||
this.sourceModelName,
|
this.sourceModelName,
|
||||||
this.staffName,
|
this.createdById,
|
||||||
|
this.createdByName,
|
||||||
|
this.assignedToId,
|
||||||
|
this.assignedToName,
|
||||||
this.includedAccessories,
|
this.includedAccessories,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Factory per creare un ticket vuoto (utile per i form di creazione)
|
/// Factory per creare un ticket vuoto (utile per i form di creazione)
|
||||||
factory TicketModel.empty({required String companyId, String? storeId}) {
|
factory TicketModel.empty({String? companyId, String? storeId}) {
|
||||||
return TicketModel(
|
return TicketModel(
|
||||||
companyId: companyId,
|
companyId: companyId ?? '',
|
||||||
storeId: storeId,
|
storeId: storeId,
|
||||||
ticketType: TicketType.repair, // Valore di default
|
ticketType: TicketType.repair, // Valore di default
|
||||||
status: TicketStatus.open,
|
status: TicketStatus.open,
|
||||||
@@ -195,7 +199,10 @@ class TicketModel extends Equatable {
|
|||||||
String? customerName,
|
String? customerName,
|
||||||
String? targetModelName,
|
String? targetModelName,
|
||||||
String? sourceModelName,
|
String? sourceModelName,
|
||||||
String? staffName,
|
String? createdById,
|
||||||
|
String? createdByName,
|
||||||
|
String? assignedToId,
|
||||||
|
String? assignedToName,
|
||||||
String? includedAccessories,
|
String? includedAccessories,
|
||||||
}) {
|
}) {
|
||||||
return TicketModel(
|
return TicketModel(
|
||||||
@@ -213,7 +220,6 @@ class TicketModel extends Equatable {
|
|||||||
closedAt: closedAt ?? this.closedAt,
|
closedAt: closedAt ?? this.closedAt,
|
||||||
returnedAt: returnedAt ?? this.returnedAt,
|
returnedAt: returnedAt ?? this.returnedAt,
|
||||||
request: request ?? this.request,
|
request: request ?? this.request,
|
||||||
staffId: staffId ?? this.staffId,
|
|
||||||
warrantyType: warrantyType ?? this.warrantyType,
|
warrantyType: warrantyType ?? this.warrantyType,
|
||||||
publicNotes: publicNotes ?? this.publicNotes,
|
publicNotes: publicNotes ?? this.publicNotes,
|
||||||
internalNotes: internalNotes ?? this.internalNotes,
|
internalNotes: internalNotes ?? this.internalNotes,
|
||||||
@@ -230,7 +236,10 @@ class TicketModel extends Equatable {
|
|||||||
customerName: customerName ?? this.customerName,
|
customerName: customerName ?? this.customerName,
|
||||||
targetModelName: targetModelName ?? this.targetModelName,
|
targetModelName: targetModelName ?? this.targetModelName,
|
||||||
sourceModelName: sourceModelName ?? this.sourceModelName,
|
sourceModelName: sourceModelName ?? this.sourceModelName,
|
||||||
staffName: staffName ?? this.staffName,
|
createdById: createdById ?? this.createdById,
|
||||||
|
createdByName: createdByName ?? this.createdByName,
|
||||||
|
assignedToId: assignedToId ?? this.assignedToId,
|
||||||
|
assignedToName: assignedToName ?? this.assignedToName,
|
||||||
includedAccessories: includedAccessories ?? this.includedAccessories,
|
includedAccessories: includedAccessories ?? this.includedAccessories,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -259,7 +268,6 @@ class TicketModel extends Equatable {
|
|||||||
? DateTime.parse(map['returned_at']).toLocal()
|
? DateTime.parse(map['returned_at']).toLocal()
|
||||||
: null,
|
: null,
|
||||||
request: map['request'] as String? ?? '',
|
request: map['request'] as String? ?? '',
|
||||||
staffId: map['staff_id'] as String?,
|
|
||||||
warrantyType: WarrantyType.fromString(map['warranty_type'] as String?),
|
warrantyType: WarrantyType.fromString(map['warranty_type'] as String?),
|
||||||
publicNotes: map['public_notes'] as String?,
|
publicNotes: map['public_notes'] as String?,
|
||||||
internalNotes: map['internal_notes'] as String?,
|
internalNotes: map['internal_notes'] as String?,
|
||||||
@@ -279,7 +287,10 @@ class TicketModel extends Equatable {
|
|||||||
?.myFormat(),
|
?.myFormat(),
|
||||||
sourceModelName: (map['source_model']?['name_with_brand'] as String?)
|
sourceModelName: (map['source_model']?['name_with_brand'] as String?)
|
||||||
?.myFormat(),
|
?.myFormat(),
|
||||||
staffName: (map['staff']?['name'] as String?).myFormat(),
|
createdById: map['staff_id'] as String?,
|
||||||
|
createdByName: (map['staff']?['name'] as String?).myFormat(),
|
||||||
|
assignedToId: map['assigned_to_id'] as String?,
|
||||||
|
assignedToName: (map['assigned_to']?['name'] as String?).myFormat(),
|
||||||
includedAccessories: map['included_accessories'] as String?,
|
includedAccessories: map['included_accessories'] as String?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -301,7 +312,7 @@ class TicketModel extends Equatable {
|
|||||||
if (returnedAt != null)
|
if (returnedAt != null)
|
||||||
'returned_at': returnedAt!.toUtc().toIso8601String(),
|
'returned_at': returnedAt!.toUtc().toIso8601String(),
|
||||||
'request': request,
|
'request': request,
|
||||||
'staff_id': staffId,
|
'created_by_id': createdById,
|
||||||
'warranty_type': warrantyType,
|
'warranty_type': warrantyType,
|
||||||
'public_notes': publicNotes,
|
'public_notes': publicNotes,
|
||||||
'internal_notes': internalNotes,
|
'internal_notes': internalNotes,
|
||||||
@@ -334,7 +345,6 @@ class TicketModel extends Equatable {
|
|||||||
closedAt,
|
closedAt,
|
||||||
returnedAt,
|
returnedAt,
|
||||||
request,
|
request,
|
||||||
staffId,
|
|
||||||
warrantyType,
|
warrantyType,
|
||||||
publicNotes,
|
publicNotes,
|
||||||
internalNotes,
|
internalNotes,
|
||||||
@@ -351,6 +361,9 @@ class TicketModel extends Equatable {
|
|||||||
customerName,
|
customerName,
|
||||||
targetModelName,
|
targetModelName,
|
||||||
sourceModelName,
|
sourceModelName,
|
||||||
staffName,
|
createdById,
|
||||||
|
createdByName,
|
||||||
|
assignedToId,
|
||||||
|
assignedToName,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user