add refresh button to pending page
All checks were successful
Release / meta (push) Successful in 7s
Release / linux-build (push) Successful in 50s
Release / web-build (push) Successful in 2m23s
Release / android-build (push) Successful in 7m48s
Release / release-master (push) Successful in 18s
Release / release-dev (push) Successful in 20s
All checks were successful
Release / meta (push) Successful in 7s
Release / linux-build (push) Successful in 50s
Release / web-build (push) Successful in 2m23s
Release / android-build (push) Successful in 7m48s
Release / release-master (push) Successful in 18s
Release / release-dev (push) Successful in 20s
This commit is contained in:
@@ -4,6 +4,7 @@ enum _TractionMoreAction {
|
||||
classStats,
|
||||
classLeaderboard,
|
||||
adminPending,
|
||||
adminPendingChanges,
|
||||
}
|
||||
|
||||
class TractionPage extends StatefulWidget {
|
||||
@@ -708,6 +709,19 @@ class _TractionPageState extends State<TractionPage> {
|
||||
);
|
||||
}
|
||||
break;
|
||||
case _TractionMoreAction.adminPendingChanges:
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
try {
|
||||
await context.push('/traction/changes');
|
||||
} catch (_) {
|
||||
if (!mounted) return;
|
||||
messenger.showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Unable to open pending changes'),
|
||||
),
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) {
|
||||
@@ -765,6 +779,12 @@ class _TractionPageState extends State<TractionPage> {
|
||||
),
|
||||
),
|
||||
);
|
||||
items.add(
|
||||
const PopupMenuItem(
|
||||
value: _TractionMoreAction.adminPendingChanges,
|
||||
child: Text('Pending changes'),
|
||||
),
|
||||
);
|
||||
}
|
||||
return items;
|
||||
},
|
||||
|
||||
152
lib/components/pages/traction/traction_pending_changes_page.dart
Normal file
152
lib/components/pages/traction/traction_pending_changes_page.dart
Normal file
@@ -0,0 +1,152 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mileograph_flutter/components/traction/traction_card.dart';
|
||||
import 'package:mileograph_flutter/objects/objects.dart';
|
||||
import 'package:mileograph_flutter/services/api_service.dart';
|
||||
import 'package:mileograph_flutter/services/authservice.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class TractionPendingChangesPage extends StatefulWidget {
|
||||
const TractionPendingChangesPage({super.key});
|
||||
|
||||
@override
|
||||
State<TractionPendingChangesPage> createState() =>
|
||||
_TractionPendingChangesPageState();
|
||||
}
|
||||
|
||||
class _TractionPendingChangesPageState extends State<TractionPendingChangesPage> {
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
List<LocoSummary> _locos = const [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _load());
|
||||
}
|
||||
|
||||
Future<void> _load() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
});
|
||||
try {
|
||||
final api = context.read<ApiService>();
|
||||
final json = await api.get('/event/pending/locos');
|
||||
if (json is List) {
|
||||
setState(() {
|
||||
_locos = json
|
||||
.whereType<Map>()
|
||||
.map((e) => LocoSummary.fromJson(
|
||||
e.map((k, v) => MapEntry(k.toString(), v)),
|
||||
))
|
||||
.toList();
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_error = 'Unexpected response';
|
||||
_locos = const [];
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_error = e.toString();
|
||||
_locos = const [];
|
||||
});
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isElevated = context.select<AuthService, bool>((auth) => auth.isElevated);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.of(context).maybePop(),
|
||||
),
|
||||
title: const Text('Pending changes'),
|
||||
),
|
||||
body: isElevated
|
||||
? RefreshIndicator(
|
||||
onRefresh: _load,
|
||||
child: _buildBody(context),
|
||||
)
|
||||
: ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: const [
|
||||
Text('Admin access required.'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(BuildContext context) {
|
||||
if (_isLoading && _locos.isEmpty) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
if (_error != null) {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: [
|
||||
Text(
|
||||
'Failed to load pending changes: $_error',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
?.copyWith(color: Theme.of(context).colorScheme.error),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
FilledButton.icon(
|
||||
onPressed: _load,
|
||||
icon: const Icon(Icons.refresh),
|
||||
label: const Text('Retry'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
if (_locos.isEmpty) {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: const [
|
||||
Text('No pending changes found.'),
|
||||
],
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(12),
|
||||
itemCount: _locos.length,
|
||||
itemBuilder: (context, index) {
|
||||
final loco = _locos[index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6.0),
|
||||
child: TractionCard(
|
||||
loco: loco,
|
||||
selectionMode: false,
|
||||
isSelected: false,
|
||||
onShowInfo: () => showTractionDetails(
|
||||
context,
|
||||
loco,
|
||||
onActionComplete: _load,
|
||||
),
|
||||
onOpenTimeline: () => context.push(
|
||||
'/traction/${loco.id}/timeline',
|
||||
extra: {
|
||||
'label': '${loco.locoClass} ${loco.number}'.trim(),
|
||||
'showPending': true,
|
||||
},
|
||||
),
|
||||
onOpenLegs: () => context.push('/traction/${loco.id}/legs'),
|
||||
onActionComplete: _load,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user