133 lines
4.7 KiB
Dart
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),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|