Files
Client/lib/widget/child_switcher.dart
T

110 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../api/marianumconnect/queries/get_capabilities/guardian_child.dart';
import '../state/app/modules/capabilities/bloc/capabilities_cubit.dart';
import '../state/app/modules/children/child_selection_cubit.dart';
import '../utils/haptics.dart';
import 'app_progress_indicator.dart';
import 'async_action_button.dart';
import 'centered_leading.dart';
import 'details_bottom_sheet.dart';
import 'placeholder_view.dart';
/// AppBar action that shows the selected child and lets a guardian switch to
/// another one. Invisible unless there is a choice to make.
class ChildSwitcher extends StatelessWidget {
const ChildSwitcher({super.key});
@override
Widget build(BuildContext context) {
final children = context.watch<CapabilitiesCubit>().state.children;
if (children.length < 2) return const SizedBox.shrink();
final selected = effectiveChild(
children,
context.watch<ChildSelectionCubit>().state,
)!;
return TextButton.icon(
icon: const Icon(Icons.face_outlined),
label: Text(selected.firstName),
onPressed: () => _pick(context, selected.id),
);
}
void _pick(BuildContext context, String selectedId) {
final selection = context.read<ChildSelectionCubit>();
final children = context.read<CapabilitiesCubit>().state.children;
showDetailsBottomSheet(
context,
header: const ListTile(title: Text('Kind auswählen')),
children: (sheetContext) => [
for (final child in children)
ChildTile(
child: child,
trailing: child.id == selectedId ? const Icon(Icons.check) : null,
onTap: () {
Haptics.selection();
selection.select(child.id);
Navigator.pop(sheetContext);
},
),
],
);
}
}
/// One linked child: name and class.
class ChildTile extends StatelessWidget {
final GuardianChild child;
final Widget? trailing;
final VoidCallback? onTap;
const ChildTile({required this.child, this.trailing, this.onTap, super.key});
@override
Widget build(BuildContext context) => ListTile(
leading: const CenteredLeading(Icon(Icons.face_outlined)),
title: Text(child.displayName),
subtitle: child.className.isEmpty
? null
: Text('Klasse ${child.className}'),
trailing: trailing,
onTap: onTap,
);
}
/// Shown by per-child modules while a guardian has no linked child. The
/// children come from `me/capabilities`, so a failed or pending load must not
/// be presented as "no child assigned" — that sends parents to the secretariat
/// over a network error.
class NoChildrenPlaceholder extends StatelessWidget {
const NoChildrenPlaceholder({super.key});
@override
Widget build(BuildContext context) {
final capabilities = context.watch<CapabilitiesCubit>().state;
if (!capabilities.loaded) {
return const Center(child: AppProgressIndicator.large());
}
if (capabilities.loadFailed) {
return PlaceholderView(
icon: Icons.cloud_off_outlined,
text:
'Die zugeordneten Kinder konnten nicht geladen werden. Bitte '
'prüfe deine Internetverbindung.',
button: AsyncActionButton(
icon: Icons.refresh,
onPressed: context.read<CapabilitiesCubit>().load,
child: const Text('Erneut versuchen'),
),
);
}
return const PlaceholderView(
icon: Icons.family_restroom_outlined,
text:
'Deinem Konto ist noch kein Kind zugeordnet. Bitte wende dich an '
'das Sekretariat.',
);
}
}