You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
samples/compass_app/app/lib/ui/activities/widgets/activities_screen.dart

189 lines
5.9 KiB

// Copyright 2024 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../../../routing/routes.dart';
import '../../core/localization/applocalization.dart';
import '../../core/themes/dimens.dart';
import '../../core/ui/error_indicator.dart';
import '../view_models/activities_viewmodel.dart';
import 'activities_header.dart';
import 'activities_list.dart';
import 'activities_title.dart';
import 'activity_time_of_day.dart';
const String confirmButtonKey = 'confirm-button';
class ActivitiesScreen extends StatefulWidget {
const ActivitiesScreen({
super.key,
required this.viewModel,
});
final ActivitiesViewModel viewModel;
@override
State<ActivitiesScreen> createState() => _ActivitiesScreenState();
}
class _ActivitiesScreenState extends State<ActivitiesScreen> {
@override
void initState() {
super.initState();
widget.viewModel.saveActivities.addListener(_onResult);
}
@override
void didUpdateWidget(covariant ActivitiesScreen oldWidget) {
super.didUpdateWidget(oldWidget);
oldWidget.viewModel.saveActivities.removeListener(_onResult);
widget.viewModel.saveActivities.addListener(_onResult);
}
@override
void dispose() {
widget.viewModel.saveActivities.removeListener(_onResult);
super.dispose();
}
@override
Widget build(BuildContext context) {
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, r) {
if (!didPop) context.go(Routes.results);
},
child: Scaffold(
body: ListenableBuilder(
listenable: widget.viewModel.loadActivities,
builder: (context, child) {
if (widget.viewModel.loadActivities.completed) {
return child!;
}
return Column(
children: [
const ActivitiesHeader(),
if (widget.viewModel.loadActivities.running)
const Expanded(
child: Center(child: CircularProgressIndicator())),
if (widget.viewModel.loadActivities.error)
Expanded(
child: Center(
child: ErrorIndicator(
title: AppLocalization.of(context)
.errorWhileLoadingActivities,
label: AppLocalization.of(context).tryAgain,
onPressed: widget.viewModel.loadActivities.execute,
),
),
),
],
);
},
child: ListenableBuilder(
listenable: widget.viewModel,
builder: (context, child) {
return Column(
children: [
Expanded(
child: CustomScrollView(
slivers: [
const SliverToBoxAdapter(
child: ActivitiesHeader(),
),
ActivitiesTitle(
viewModel: widget.viewModel,
activityTimeOfDay: ActivityTimeOfDay.daytime,
),
ActivitiesList(
viewModel: widget.viewModel,
activityTimeOfDay: ActivityTimeOfDay.daytime,
),
ActivitiesTitle(
viewModel: widget.viewModel,
activityTimeOfDay: ActivityTimeOfDay.evening,
),
ActivitiesList(
viewModel: widget.viewModel,
activityTimeOfDay: ActivityTimeOfDay.evening,
),
],
),
),
_BottomArea(viewModel: widget.viewModel),
],
);
},
),
),
),
);
}
void _onResult() {
if (widget.viewModel.saveActivities.completed) {
widget.viewModel.saveActivities.clearResult();
context.go(Routes.booking);
}
if (widget.viewModel.saveActivities.error) {
widget.viewModel.saveActivities.clearResult();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(AppLocalization.of(context).errorWhileSavingActivities),
action: SnackBarAction(
label: AppLocalization.of(context).tryAgain,
onPressed: widget.viewModel.saveActivities.execute,
),
),
);
}
}
}
class _BottomArea extends StatelessWidget {
const _BottomArea({
required this.viewModel,
});
final ActivitiesViewModel viewModel;
@override
Widget build(BuildContext context) {
return SafeArea(
bottom: true,
child: Material(
elevation: 8,
child: Padding(
padding: EdgeInsets.only(
left: Dimens.of(context).paddingScreenHorizontal,
right: Dimens.of(context).paddingScreenVertical,
top: Dimens.paddingVertical,
bottom: Dimens.of(context).paddingScreenVertical,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
AppLocalization.of(context)
.selected(viewModel.selectedActivities.length),
style: Theme.of(context).textTheme.labelLarge,
),
FilledButton(
key: const Key(confirmButtonKey),
onPressed: viewModel.selectedActivities.isNotEmpty
? viewModel.saveActivities.execute
: null,
child: Text(AppLocalization.of(context).confirm),
),
],
),
),
),
);
}
}