2026-05-26 19:31:25 +02:00
|
|
|
import 'package:equatable/equatable.dart';
|
|
|
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
|
|
|
import 'package:flux/core/blocs/session/session_cubit.dart';
|
|
|
|
|
import 'package:flux/features/master_data/staff/models/staff_member_model.dart';
|
2026-05-29 12:26:41 +02:00
|
|
|
import 'package:flux/features/settings/data/settings_repository.dart';
|
2026-05-26 19:31:25 +02:00
|
|
|
import 'package:flux/features/tasks/data/task_repository.dart';
|
|
|
|
|
import 'package:flux/features/tasks/models/task_model.dart';
|
2026-05-29 12:26:41 +02:00
|
|
|
import 'package:flux/features/tasks/models/task_reminder_config.dart';
|
2026-05-26 19:31:25 +02:00
|
|
|
import 'package:flux/features/tasks/models/task_status.dart';
|
|
|
|
|
import 'package:get_it/get_it.dart';
|
|
|
|
|
part 'task_form_state.dart';
|
|
|
|
|
|
|
|
|
|
class TaskFormCubit extends Cubit<TaskFormState> {
|
2026-05-29 12:26:41 +02:00
|
|
|
final TaskRepository _repository = GetIt.I.get<TaskRepository>();
|
|
|
|
|
final SettingsRepository _settingsRepository = GetIt.I
|
|
|
|
|
.get<SettingsRepository>();
|
|
|
|
|
final SessionCubit _sessionCubit = GetIt.I.get<SessionCubit>();
|
|
|
|
|
|
|
|
|
|
TaskFormCubit({TaskModel? existingTask})
|
|
|
|
|
: super(
|
|
|
|
|
TaskFormState(
|
|
|
|
|
id: existingTask?.id,
|
|
|
|
|
title: existingTask?.title ?? '',
|
|
|
|
|
description: existingTask?.description ?? '',
|
|
|
|
|
dueDate: existingTask?.dueDate,
|
|
|
|
|
isGlobal: existingTask?.isGlobal ?? false,
|
|
|
|
|
selectedStaffIds: existingTask?.assignedToIds ?? [],
|
|
|
|
|
),
|
|
|
|
|
) {
|
|
|
|
|
if (existingTask == null) {
|
|
|
|
|
_initializeNewTaskReminders();
|
|
|
|
|
} else {
|
|
|
|
|
_loadExistingTaskReminders(existingTask.id!);
|
2026-05-27 16:00:50 +02:00
|
|
|
}
|
2026-05-26 19:31:25 +02:00
|
|
|
}
|
|
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
String get _companyId => _sessionCubit.state.company!.id!;
|
|
|
|
|
String get _currentUserId => _sessionCubit.state.currentStaffMember!.id!;
|
2026-05-26 19:31:25 +02:00
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
// --- INIT REMINDER NUOVO TASK ---
|
|
|
|
|
Future<void> _initializeNewTaskReminders() async {
|
|
|
|
|
try {
|
|
|
|
|
final defaults = await _settingsRepository.getMyReminderDefaults(
|
|
|
|
|
companyId: _companyId,
|
|
|
|
|
staffId: _currentUserId,
|
|
|
|
|
);
|
2026-05-26 19:31:25 +02:00
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
final initialReminders = defaults
|
|
|
|
|
.map(
|
|
|
|
|
(d) => TaskReminderConfig(
|
|
|
|
|
minutesBefore: d.minutesBefore,
|
|
|
|
|
channel: d.channel,
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
.toList();
|
2026-05-27 16:00:50 +02:00
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
emit(state.copyWith(reminders: initialReminders));
|
|
|
|
|
} catch (e) {
|
|
|
|
|
// Fallback in caso di errore
|
|
|
|
|
emit(
|
|
|
|
|
state.copyWith(
|
|
|
|
|
reminders: const [
|
|
|
|
|
TaskReminderConfig(minutesBefore: 15, channel: 'push'),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
);
|
2026-05-27 16:00:50 +02:00
|
|
|
}
|
2026-05-26 19:31:25 +02:00
|
|
|
}
|
|
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
// --- INIT REMINDER TASK ESISTENTE ---
|
|
|
|
|
Future<void> _loadExistingTaskReminders(String taskId) async {
|
|
|
|
|
try {
|
|
|
|
|
// Recuperiamo SOLO i reminder non forzati dell'utente loggato per popolare il form
|
|
|
|
|
final existingConfigs = await _repository.fetchPersonalReminders(
|
|
|
|
|
taskId: taskId,
|
|
|
|
|
staffId: _currentUserId,
|
|
|
|
|
);
|
|
|
|
|
emit(state.copyWith(reminders: existingConfigs));
|
|
|
|
|
} catch (e) {
|
|
|
|
|
print('Errore caricamento reminder: $e');
|
2026-05-26 19:31:25 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
// --- UPDATE CAMPI BASE ---
|
|
|
|
|
void updateTitle(String t) => emit(state.copyWith(title: t));
|
|
|
|
|
void updateDescription(String d) => emit(state.copyWith(description: d));
|
|
|
|
|
void updateDueDate(DateTime? d) => emit(state.copyWith(dueDate: d));
|
|
|
|
|
void toggleGlobalScope(bool g) => emit(state.copyWith(isGlobal: g));
|
2026-05-26 19:31:25 +02:00
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
void toggleStaffSelection(String staffId) {
|
|
|
|
|
final updated = List<String>.from(state.selectedStaffIds);
|
|
|
|
|
updated.contains(staffId) ? updated.remove(staffId) : updated.add(staffId);
|
|
|
|
|
emit(state.copyWith(selectedStaffIds: updated));
|
2026-05-26 19:31:25 +02:00
|
|
|
}
|
|
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
// --- GESTIONE REMINDER NEL FORM ---
|
|
|
|
|
void addReminderRule(int minutesBefore, String channel) {
|
|
|
|
|
final updated = List<TaskReminderConfig>.from(state.reminders);
|
|
|
|
|
final newConfig = TaskReminderConfig(
|
|
|
|
|
minutesBefore: minutesBefore,
|
|
|
|
|
channel: channel,
|
|
|
|
|
);
|
2026-05-26 19:31:25 +02:00
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
if (!updated.contains(newConfig)) {
|
|
|
|
|
updated.add(newConfig);
|
|
|
|
|
updated.sort((a, b) => a.minutesBefore.compareTo(b.minutesBefore));
|
|
|
|
|
emit(state.copyWith(reminders: updated));
|
|
|
|
|
}
|
2026-05-26 19:31:25 +02:00
|
|
|
}
|
|
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
void removeReminderRule(int index) {
|
|
|
|
|
final updated = List<TaskReminderConfig>.from(state.reminders)
|
|
|
|
|
..removeAt(index);
|
|
|
|
|
emit(state.copyWith(reminders: updated));
|
2026-05-26 19:31:25 +02:00
|
|
|
}
|
|
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
// --- SALVATAGGIO FINALE ---
|
|
|
|
|
Future<void> saveTask() async {
|
2026-05-26 19:31:25 +02:00
|
|
|
if (!state.isFormValid) return;
|
|
|
|
|
emit(state.copyWith(status: TaskFormStatus.submitting));
|
|
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
final taskToSave = TaskModel(
|
|
|
|
|
id: state.id,
|
|
|
|
|
companyId: _companyId,
|
|
|
|
|
createdBy: _currentUserId,
|
|
|
|
|
title: state.title.trim(),
|
|
|
|
|
description: state.description.trim(),
|
|
|
|
|
dueDate: state.dueDate,
|
|
|
|
|
isGlobal: state.isGlobal,
|
|
|
|
|
assignedToIds: state.selectedStaffIds,
|
|
|
|
|
);
|
2026-05-26 19:31:25 +02:00
|
|
|
|
2026-05-29 12:26:41 +02:00
|
|
|
try {
|
2026-05-26 19:31:25 +02:00
|
|
|
if (state.id == null) {
|
2026-05-29 12:26:41 +02:00
|
|
|
// NUOVO TASK -> CREATE
|
|
|
|
|
// Qui potresti passare un managerForcedOverride se implementi la UI per quello
|
|
|
|
|
await _repository.createTask(
|
|
|
|
|
task: taskToSave,
|
|
|
|
|
assignedStaffIds: state.selectedStaffIds,
|
|
|
|
|
currentUserId: _currentUserId,
|
|
|
|
|
currentUserCustomReminders: state.reminders,
|
|
|
|
|
);
|
2026-05-26 19:31:25 +02:00
|
|
|
} else {
|
2026-05-29 12:26:41 +02:00
|
|
|
// VECCHIO TASK -> UPDATE
|
|
|
|
|
await _repository.updateTask(
|
|
|
|
|
task: taskToSave,
|
|
|
|
|
assignedStaffIds: state.selectedStaffIds,
|
|
|
|
|
currentUserId: _currentUserId,
|
|
|
|
|
currentUserCustomReminders: state.reminders,
|
|
|
|
|
);
|
2026-05-26 19:31:25 +02:00
|
|
|
}
|
|
|
|
|
emit(state.copyWith(status: TaskFormStatus.success));
|
|
|
|
|
} catch (e) {
|
|
|
|
|
emit(
|
|
|
|
|
state.copyWith(
|
|
|
|
|
status: TaskFormStatus.failure,
|
2026-05-29 12:26:41 +02:00
|
|
|
errorMessage: e.toString(),
|
2026-05-26 19:31:25 +02:00
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|