Files
Client/lib/view/pages/rmv/disruptions/disruptions_view.dart
T

184 lines
5.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter/material.dart';
import '../../../../api/connect/rmv/rmv_models.dart';
import '../../../../api/errors/error_mapper.dart';
import '../../../../extensions/date_time.dart';
import '../../../../state/app/modules/rmv/repository/rmv_repository.dart';
import '../../../../widget/app_progress_indicator.dart';
import '../../../../widget/details_bottom_sheet.dart';
class DisruptionsView extends StatefulWidget {
const DisruptionsView({super.key});
@override
State<DisruptionsView> createState() => _DisruptionsViewState();
}
class _DisruptionsViewState extends State<DisruptionsView> {
final RmvRepository _repo = RmvRepository();
List<HimMessage>? _items;
bool _loading = true;
Object? _error;
@override
void initState() {
super.initState();
_load();
}
Future<void> _load() async {
setState(() {
_loading = true;
_error = null;
});
try {
final r = await _repo.disruptions();
if (!mounted) return;
r.sort((a, b) => (b.priority ?? 0).compareTo(a.priority ?? 0));
setState(() {
_items = r;
_loading = false;
});
} catch (e) {
if (!mounted) return;
setState(() {
_error = e;
_loading = false;
});
}
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text('Störungsmeldungen')),
body: _body(),
);
Widget _body() {
if (_loading) return const Center(child: AppProgressIndicator.large());
final err = _error;
if (err != null) {
return Center(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
errorToUserMessage(err),
textAlign: TextAlign.center,
style: TextStyle(color: Theme.of(context).colorScheme.error),
),
const SizedBox(height: 12),
FilledButton.icon(
icon: const Icon(Icons.refresh),
onPressed: _load,
label: const Text('Erneut versuchen'),
),
],
),
),
);
}
final list = _items ?? const <HimMessage>[];
if (list.isEmpty) {
return RefreshIndicator(
onRefresh: _load,
child: ListView(
physics: const AlwaysScrollableScrollPhysics(),
children: const [
Padding(
padding: EdgeInsets.symmetric(vertical: 80, horizontal: 24),
child: Center(child: Text('Keine aktiven Meldungen.')),
),
],
),
);
}
return RefreshIndicator(
onRefresh: _load,
child: ListView.separated(
itemCount: list.length,
separatorBuilder: (_, _) => const Divider(height: 1),
itemBuilder: (_, i) => _tile(list[i]),
),
);
}
Widget _tile(HimMessage msg) => ListTile(
leading: Icon(
Icons.warning_amber_outlined,
color: _priorityColor(msg.priority),
),
title: Text(
msg.head ?? msg.lead ?? msg.text ?? 'Meldung',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
subtitle: msg.lead == null
? null
: Text(msg.lead!, maxLines: 2, overflow: TextOverflow.ellipsis),
trailing: const Icon(Icons.chevron_right),
onTap: () => _showDetails(msg),
);
Color _priorityColor(int? priority) {
if (priority == null) return Colors.orange;
if (priority >= 100) return Colors.red;
if (priority >= 50) return Colors.orange;
return Colors.amber;
}
void _showDetails(HimMessage msg) {
showDetailsBottomSheet(
context,
header: Padding(
padding: const EdgeInsets.fromLTRB(16, 4, 16, 12),
child: Text(
msg.head ?? 'Störungsmeldung',
style: Theme.of(context).textTheme.titleLarge,
),
),
children: (ctx) => [
if (msg.lead != null)
ListTile(
leading: const Icon(Icons.short_text),
title: Text(msg.lead!),
),
if (msg.text != null)
ListTile(
leading: const Icon(Icons.notes),
title: Text(msg.text!),
),
if (msg.category != null)
ListTile(
leading: const Icon(Icons.category_outlined),
title: Text(msg.category!),
),
if (msg.company != null)
ListTile(
leading: const Icon(Icons.business_outlined),
title: Text(msg.company!),
),
if (msg.startValidity != null || msg.endValidity != null)
ListTile(
leading: const Icon(Icons.event_outlined),
title: Text(_validityRange(msg)),
),
if (msg.modified != null)
ListTile(
leading: const Icon(Icons.update_outlined),
title: Text('Aktualisiert: ${msg.modified!.formatDateTime()}'),
),
],
);
}
String _validityRange(HimMessage msg) {
final start = msg.startValidity?.formatDateTime();
final end = msg.endValidity?.formatDateTime();
if (start != null && end != null) return '$start $end';
return start ?? end ?? '';
}
}