Files
BrandManager/lib/views/link_talkgroup_view.dart
2026-01-19 10:20:45 +01:00

167 lines
4.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import '../models/device.dart';
import '../services/authentication_manager.dart';
import '../services/brandmeister_client.dart';
class LinkTalkgroupView extends StatefulWidget {
final Device device;
final VoidCallback onSuccess;
const LinkTalkgroupView({
super.key,
required this.device,
required this.onSuccess,
});
@override
State<LinkTalkgroupView> createState() => _LinkTalkgroupViewState();
}
class _LinkTalkgroupViewState extends State<LinkTalkgroupView> {
final TextEditingController _talkgroupController = TextEditingController();
int _selectedTimeslot = 1;
bool _isLoading = false;
String? _errorMessage;
@override
void dispose() {
_talkgroupController.dispose();
super.dispose();
}
Future<void> _linkTalkgroup() async {
if (_talkgroupController.text.isEmpty) {
setState(() {
_errorMessage = 'Please enter a talkgroup ID';
});
return;
}
final talkgroupId = int.tryParse(_talkgroupController.text);
if (talkgroupId == null) {
setState(() {
_errorMessage = 'Invalid talkgroup ID';
});
return;
}
setState(() {
_isLoading = true;
_errorMessage = null;
});
try {
final authManager = context.read<AuthenticationManager>();
await authManager.linkTalkgroup(
talkgroupId: talkgroupId,
dmrId: widget.device.id,
timeslot: _selectedTimeslot,
);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Talkgroup linked successfully')),
);
widget.onSuccess();
}
} on BrandmeisterError catch (e) {
setState(() {
_errorMessage = e.message;
_isLoading = false;
});
} catch (e) {
setState(() {
_errorMessage = e.toString();
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Link Talkgroup',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
IconButton(
icon: const Icon(Icons.close),
onPressed: () => Navigator.pop(context),
),
],
),
const SizedBox(height: 24),
TextField(
controller: _talkgroupController,
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
decoration: InputDecoration(
labelText: 'Talkgroup ID',
hintText: 'Enter talkgroup ID',
border: const OutlineInputBorder(),
prefixIcon: const Icon(Icons.speaker_group),
errorText: _errorMessage,
),
enabled: !_isLoading,
autofocus: true,
),
const SizedBox(height: 24),
Text(
'Timeslot',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
SegmentedButton<int>(
segments: const [
ButtonSegment(
value: 1,
label: Text('TS1'),
icon: Icon(Icons.looks_one),
),
ButtonSegment(
value: 2,
label: Text('TS2'),
icon: Icon(Icons.looks_two),
),
],
selected: {_selectedTimeslot},
onSelectionChanged: _isLoading
? null
: (Set<int> newSelection) {
setState(() {
_selectedTimeslot = newSelection.first;
});
},
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: _isLoading ? null : _linkTalkgroup,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
),
child: _isLoading
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Text('Link Talkgroup'),
),
],
),
);
}
}