Files
Client/lib/view/pages/parent_letters/parent_letters_view.dart
T

133 lines
4.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../api/marianumconnect/queries/get_capabilities/guardian_child.dart';
import '../../../push/notification_permission_prompt.dart';
import '../../../routing/app_routes.dart';
import '../../../state/app/infrastructure/loadable_state/view/loadable_state_consumer.dart';
import '../../../state/app/modules/capabilities/bloc/capabilities_cubit.dart';
import '../../../state/app/modules/parent_letters/bloc/parent_letters_bloc.dart';
import '../../../state/app/modules/parent_letters/bloc/parent_letters_state.dart';
import '../../../state/app/modules/parent_letters/parent_letters_logic.dart';
import '../../../widget/async_action_button.dart';
import '../../../widget/child_switcher.dart';
import '../../../widget/placeholder_view.dart';
import 'widgets/parent_letter_tile.dart';
class ParentLettersView extends StatefulWidget {
const ParentLettersView({super.key});
@override
State<ParentLettersView> createState() => _ParentLettersViewState();
}
class _ParentLettersViewState extends State<ParentLettersView> {
/// Null shows the letters of all children. Deliberately independent of the
/// app-wide child selection: the inbox must not hide a sibling's letters.
String? _childFilter;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
context.read<ParentLettersBloc>().refresh(silent: true);
maybePromptParentLetterNotifications(context);
});
}
@override
Widget build(BuildContext context) {
final children = context.watch<CapabilitiesCubit>().state.children;
final filter = children.any((child) => child.id == _childFilter)
? _childFilter
: null;
return Scaffold(
appBar: AppBar(title: const Text('Elternbriefe')),
body: Column(
children: [
if (children.length > 1)
_ChildFilterBar(
children: children,
selected: filter,
onSelected: (id) => setState(() => _childFilter = id),
),
Expanded(
child: LoadableStateConsumer<ParentLettersBloc, ParentLettersState>(
child: (state, loading) {
if (children.isEmpty) return const NoChildrenPlaceholder();
final letters = filterLettersByChild(state.letters, filter);
if (letters.isEmpty && !state.hasMore) {
return const PlaceholderView(
icon: Icons.mark_email_read_outlined,
text: 'Keine Elternbriefe vorhanden.',
);
}
return ListView.separated(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: letters.length + (state.hasMore ? 1 : 0),
separatorBuilder: (_, _) => const Divider(height: 1),
itemBuilder: (context, index) {
if (index == letters.length) {
return Padding(
padding: const EdgeInsets.all(8),
child: AsyncTextButton(
onPressed: context
.read<ParentLettersBloc>()
.loadOlder,
child: const Text('Ältere Elternbriefe laden'),
),
);
}
final letter = letters[index];
return ParentLetterTile(
letter: letter,
children: children,
onTap: () =>
AppRoutes.openParentLetter(context, id: letter.id),
);
},
);
},
),
),
],
),
);
}
}
class _ChildFilterBar extends StatelessWidget {
final List<GuardianChild> children;
final String? selected;
final ValueChanged<String?> onSelected;
const _ChildFilterBar({
required this.children,
required this.selected,
required this.onSelected,
});
@override
Widget build(BuildContext context) => SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
child: Row(
spacing: 8,
children: [
ChoiceChip(
label: const Text('Alle'),
selected: selected == null,
onSelected: (_) => onSelected(null),
),
for (final child in children)
ChoiceChip(
label: Text(child.firstName),
selected: selected == child.id,
onSelected: (_) => onSelected(child.id),
),
],
),
);
}