uto_manager/lib/presentation/screens/dialogs/add_edit_unit_dialog.dart

203 lines
6.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:uto_manager/domain/entities/doctrinal_branch.dart';
import 'package:uto_manager/domain/entities/echelon.dart';
import 'package:uto_manager/domain/entities/unit_node.dart';
import 'package:uuid/uuid.dart';
/// Dialog for creating or editing a [UnitNode].
///
/// Pass [existing] to edit; leave null to create a new unit.
/// Pass [parentUnit] to pre-select the parent and constrain the echelon.
class AddEditUnitDialog extends StatefulWidget {
const AddEditUnitDialog({
super.key,
this.existing,
this.parentUnit,
this.availableParents = const [],
});
final UnitNode? existing;
final UnitNode? parentUnit;
final List<UnitNode> availableParents;
@override
State<AddEditUnitDialog> createState() => _AddEditUnitDialogState();
}
class _AddEditUnitDialogState extends State<AddEditUnitDialog> {
final _formKey = GlobalKey<FormState>();
late final TextEditingController _nameCtrl;
late Echelon _echelon;
late DoctrinalBranch _branch;
String? _parentUnitId;
late bool _isKeyLeader;
bool get _isEditing => widget.existing != null;
@override
void initState() {
super.initState();
final e = widget.existing;
_nameCtrl = TextEditingController(text: e?.name ?? '');
_echelon = e?.echelon ?? _defaultChildEchelon();
_branch = e?.branch ?? DoctrinalBranch.infantry;
_parentUnitId = e?.parentUnitId ?? widget.parentUnit?.unitId;
_isKeyLeader = e?.isKeyLeader ?? false;
}
Echelon _defaultChildEchelon() {
final parent = widget.parentUnit;
if (parent == null) return Echelon.brigade;
// Default to one level below parent
final childLevel = parent.echelon.level + 1;
return Echelon.values.firstWhere(
(e) => e.level == childLevel,
orElse: () => Echelon.team,
);
}
@override
void dispose() {
_nameCtrl.dispose();
super.dispose();
}
void _submit() {
if (!_formKey.currentState!.validate()) return;
// If no name provided, generate a default from echelon + branch abbreviation
final rawName = _nameCtrl.text.trim();
final name = rawName.isEmpty ? '${_echelon.displayName} (${_branch.abbreviation})' : rawName;
final unit = UnitNode(
unitId: widget.existing?.unitId ?? const Uuid().v4(),
echelon: _echelon,
branch: _branch,
name: name,
isKeyLeader: _isKeyLeader,
parentUnitId: _parentUnitId,
);
Navigator.of(context).pop(unit);
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Row(
children: [
Icon(_isEditing ? Icons.edit : Icons.add_box_outlined, size: 20),
const SizedBox(width: 8),
Text(_isEditing ? 'Edit Unit' : 'Add Unit'),
],
),
content: SizedBox(
width: 420,
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Unit Name
TextFormField(
controller: _nameCtrl,
decoration: const InputDecoration(
labelText: 'Unit Name / Designation (optional)',
hintText: 'e.g. 1-68 AR, Alpha Company, 3rd Platoon',
helperText: 'Leave blank to auto-generate from echelon & branch',
prefixIcon: Icon(Icons.account_tree_outlined),
),
textCapitalization: TextCapitalization.words,
),
const SizedBox(height: 12),
// Echelon
DropdownButtonFormField<Echelon>(
initialValue: _echelon,
decoration: const InputDecoration(
labelText: 'Echelon',
prefixIcon: Icon(Icons.layers_outlined),
),
items: Echelon.values.map((e) {
return DropdownMenuItem(
value: e,
child: Text(e.displayName),
);
}).toList(),
onChanged: (v) => setState(() => _echelon = v!),
),
const SizedBox(height: 12),
// Branch
DropdownButtonFormField<DoctrinalBranch>(
initialValue: _branch,
decoration: const InputDecoration(
labelText: 'Branch / Functional Area',
prefixIcon: Icon(Icons.category_outlined),
),
items: DoctrinalBranch.values.map((b) {
return DropdownMenuItem(
value: b,
child: Text('${b.abbreviation} — ${b.displayName}'),
);
}).toList(),
onChanged: (v) => setState(() => _branch = v!),
),
const SizedBox(height: 12),
// Parent Unit (optional)
if (widget.availableParents.isNotEmpty) ...[
DropdownButtonFormField<String?>(
initialValue: _parentUnitId,
decoration: const InputDecoration(
labelText: 'Parent Unit (optional)',
prefixIcon: Icon(Icons.device_hub_outlined),
),
items: [
const DropdownMenuItem<String?>(
child: Text('— None (root unit) —'),
),
...widget.availableParents.map((u) {
return DropdownMenuItem<String?>(
value: u.unitId,
child: Text('${u.echelon.displayName}: ${u.name}'),
);
}),
],
onChanged: (v) => setState(() => _parentUnitId = v),
),
const SizedBox(height: 12),
],
// Key Leader toggle
SwitchListTile(
title: const Text('Key Leader Unit'),
subtitle: const Text('Marks this as a command/key leader node'),
value: _isKeyLeader,
onChanged: (v) => setState(() => _isKeyLeader = v),
contentPadding: EdgeInsets.zero,
dense: true,
),
],
),
),
),
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancel'),
),
FilledButton.icon(
icon: Icon(_isEditing ? Icons.save : Icons.add, size: 16),
label: Text(_isEditing ? 'Save Changes' : 'Add Unit'),
onPressed: _submit,
),
],
);
}
}