x
This commit is contained in:
@@ -3,19 +3,53 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flux/features/tasks/blocs/task_form_cubit.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class TaskFormScreen extends StatelessWidget {
|
||||
class TaskFormScreen extends StatefulWidget {
|
||||
const TaskFormScreen({super.key});
|
||||
|
||||
@override
|
||||
State<TaskFormScreen> createState() => _TaskFormScreenState();
|
||||
}
|
||||
|
||||
class _TaskFormScreenState extends State<TaskFormScreen> {
|
||||
late final TextEditingController _titleController;
|
||||
late final TextEditingController _descController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// Leggiamo lo stato iniziale dal Cubit (che ha già i dati del task esistente)
|
||||
final initialState = context.read<TaskFormCubit>().state;
|
||||
|
||||
_titleController = TextEditingController(text: initialState.title);
|
||||
_descController = TextEditingController(text: initialState.description);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_titleController.dispose();
|
||||
_descController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocConsumer<TaskFormCubit, TaskFormState>(
|
||||
listenWhen: (previous, current) => previous.status != current.status,
|
||||
listener: (context, state) {
|
||||
// GESTIONE DEEP LINK: Se eravamo in caricamento e ora siamo pronti, popoliamo i controller!
|
||||
if (state.status == TaskFormStatus.initial) {
|
||||
if (_titleController.text != state.title) {
|
||||
_titleController.text = state.title;
|
||||
}
|
||||
if (_descController.text != state.description) {
|
||||
_descController.text = state.description;
|
||||
}
|
||||
}
|
||||
if (state.status == TaskFormStatus.success) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Task salvato con successo! 🎉')),
|
||||
);
|
||||
context.pop(); // Usciamo dalla pagina
|
||||
context.pop();
|
||||
} else if (state.status == TaskFormStatus.failure) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
@@ -33,7 +67,6 @@ class TaskFormScreen extends StatelessWidget {
|
||||
appBar: AppBar(
|
||||
title: Text(isEditing ? 'Modifica Task' : 'Nuovo Task'),
|
||||
actions: [
|
||||
// Tasto Salva (abilitato solo se il form è valido)
|
||||
if (state.status == TaskFormStatus.submitting)
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
@@ -46,81 +79,84 @@ class TaskFormScreen extends StatelessWidget {
|
||||
else
|
||||
TextButton.icon(
|
||||
onPressed: state.isFormValid
|
||||
? () =>
|
||||
cubit.saveTask(
|
||||
currentUserId: 'TODO_USER_ID',
|
||||
) // Passa l'id utente loggato dal SessionCubit
|
||||
? () => cubit.saveTask(currentUserId: 'TODO_USER_ID')
|
||||
: null,
|
||||
icon: const Icon(Icons.save),
|
||||
label: const Text('Salva'),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: Colors.orange, // Il tuo colore primario
|
||||
foregroundColor: Colors.orange,
|
||||
disabledForegroundColor: Colors.grey,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final isWideScreen = constraints.maxWidth > 800;
|
||||
body: state.status == TaskFormStatus.loading
|
||||
// Se sta scaricando i dati dal Deep Link, mostriamo un bel loader centrato
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final isWideScreen = constraints.maxWidth > 800;
|
||||
|
||||
if (isWideScreen) {
|
||||
// --- VISTA DESKTOP / TABLET LARGHI (2 Colonne) ---
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 6,
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: _buildFormFields(context, state, cubit),
|
||||
),
|
||||
),
|
||||
VerticalDivider(color: Theme.of(context).dividerColor),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: _buildStaffSelectorInline(context, state, cubit),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
if (isWideScreen) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 6,
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: _buildFormFields(context, state, cubit),
|
||||
),
|
||||
),
|
||||
VerticalDivider(
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: _buildStaffSelectorInline(
|
||||
context,
|
||||
state,
|
||||
cubit,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// --- VISTA MOBILE (1 Colonna + BottomSheet) ---
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_buildFormFields(context, state, cubit),
|
||||
const SizedBox(height: 30),
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_buildFormFields(context, state, cubit),
|
||||
const SizedBox(height: 30),
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
onPressed: () =>
|
||||
_showStaffBottomSheet(context, cubit),
|
||||
icon: const Icon(Icons.group_add),
|
||||
label: Text(
|
||||
state.selectedStaffIds.isEmpty
|
||||
? 'Assegna Staff'
|
||||
: 'Assegnato a ${state.selectedStaffIds.length} persone',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () => _showStaffBottomSheet(context, cubit),
|
||||
icon: const Icon(Icons.group_add),
|
||||
label: Text(
|
||||
state.selectedStaffIds.isEmpty
|
||||
? 'Assegna Staff'
|
||||
: 'Assegnato a ${state.selectedStaffIds.length} persone',
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 1. I CAMPI DEL FORM PRINCIPALE
|
||||
// =========================================================================
|
||||
// --- I CAMPI DEL FORM (Aggiornati con i Controller) ---
|
||||
Widget _buildFormFields(
|
||||
BuildContext context,
|
||||
TaskFormState state,
|
||||
@@ -129,7 +165,6 @@ class TaskFormScreen extends StatelessWidget {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// --- SCOPE TOGGLE ---
|
||||
Card(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
@@ -153,9 +188,9 @@ class TaskFormScreen extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// --- TITOLO E DESCRIZIONE ---
|
||||
// Addio initialValue, benvenuto controller!
|
||||
TextFormField(
|
||||
initialValue: state.title,
|
||||
controller: _titleController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Titolo del Task*',
|
||||
border: OutlineInputBorder(),
|
||||
@@ -165,7 +200,7 @@ class TaskFormScreen extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
initialValue: state.description,
|
||||
controller: _descController,
|
||||
maxLines: 4,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Descrizione (opzionale)',
|
||||
|
||||
Reference in New Issue
Block a user