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/booking/widgets/booking_header.dart

172 lines
4.6 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:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import '../../../domain/models/booking/booking.dart';
import '../../../utils/image_error_listener.dart';
import '../../core/localization/applocalization.dart';
import '../../core/themes/colors.dart';
import '../../core/themes/dimens.dart';
import '../../core/ui/date_format_start_end.dart';
import '../../core/ui/home_button.dart';
import '../../core/ui/tag_chip.dart';
class BookingHeader extends StatelessWidget {
const BookingHeader({super.key, required this.booking});
final Booking booking;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_Top(booking: booking),
Padding(
padding: Dimens.of(context).edgeInsetsScreenHorizontal,
child: Text(
booking.destination.knownFor,
style: Theme.of(context).textTheme.bodyLarge,
),
),
const SizedBox(height: Dimens.paddingVertical),
_Tags(booking: booking),
const SizedBox(height: Dimens.paddingVertical),
Padding(
padding: Dimens.of(context).edgeInsetsScreenHorizontal,
child: Text(
AppLocalization.of(context).yourChosenActivities,
style: Theme.of(context).textTheme.headlineSmall,
),
),
],
);
}
}
class _Top extends StatelessWidget {
const _Top({required this.booking});
final Booking booking;
@override
Widget build(BuildContext context) {
return SizedBox(
height: 260,
child: Stack(
fit: StackFit.expand,
children: [
_HeaderImage(booking: booking),
const _Gradient(),
_Headline(booking: booking),
Positioned(
right: Dimens.of(context).paddingScreenHorizontal,
top: Dimens.of(context).paddingScreenVertical,
child: const SafeArea(top: true, child: HomeButton(blur: true)),
),
],
),
);
}
}
class _Tags extends StatelessWidget {
const _Tags({required this.booking});
final Booking booking;
@override
Widget build(BuildContext context) {
final brightness = Theme.of(context).brightness;
final chipColor = switch (brightness) {
Brightness.dark => AppColors.whiteTransparent,
Brightness.light => AppColors.blackTransparent,
};
return Padding(
padding: Dimens.of(context).edgeInsetsScreenHorizontal,
child: Wrap(
spacing: 6,
runSpacing: 6,
children: booking.destination.tags
.map(
(tag) => TagChip(
tag: tag,
fontSize: 16,
height: 32,
chipColor: chipColor,
onChipColor: Theme.of(context).colorScheme.onSurface,
),
)
.toList(),
),
);
}
}
class _Headline extends StatelessWidget {
const _Headline({required this.booking});
final Booking booking;
@override
Widget build(BuildContext context) {
return Align(
alignment: AlignmentDirectional.bottomStart,
child: Padding(
padding: Dimens.of(context).edgeInsetsScreenSymmetric,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
booking.destination.name,
style: Theme.of(context).textTheme.headlineLarge,
),
Text(
dateFormatStartEnd(
DateTimeRange(start: booking.startDate, end: booking.endDate),
),
style: Theme.of(context).textTheme.headlineSmall,
),
],
),
),
);
}
}
class _HeaderImage extends StatelessWidget {
const _HeaderImage({required this.booking});
final Booking booking;
@override
Widget build(BuildContext context) {
return CachedNetworkImage(
fit: BoxFit.fitWidth,
imageUrl: booking.destination.imageUrl,
errorListener: imageErrorListener,
);
}
}
class _Gradient extends StatelessWidget {
const _Gradient();
@override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.transparent, Theme.of(context).colorScheme.surface],
),
),
);
}
}