feat: Add cancellation reason handling and display in shift details
This commit is contained in:
@@ -12,6 +12,7 @@ import 'package:staff_shifts/src/presentation/blocs/shift_details/shift_details_
|
||||
import 'package:staff_shifts/src/presentation/blocs/shift_details/shift_details_state.dart';
|
||||
import 'package:staff_shifts/src/presentation/widgets/shift_details/shift_date_time_section.dart';
|
||||
import 'package:staff_shifts/src/presentation/widgets/shift_details/shift_description_section.dart';
|
||||
import 'package:staff_shifts/src/presentation/widgets/shift_details/cancellation_reason_banner.dart';
|
||||
import 'package:staff_shifts/src/presentation/widgets/shift_details/shift_details_bottom_bar.dart';
|
||||
import 'package:staff_shifts/src/presentation/widgets/shift_details/shift_details_header.dart';
|
||||
import 'package:staff_shifts/src/presentation/widgets/shift_details_page_skeleton.dart';
|
||||
@@ -117,6 +118,15 @@ class _ShiftDetailsPageState extends State<ShiftDetailsPage> {
|
||||
icon: UiIcons.sparkles,
|
||||
),
|
||||
),
|
||||
if (detail.assignmentStatus ==
|
||||
AssignmentStatus.cancelled &&
|
||||
detail.cancellationReason != null &&
|
||||
detail.cancellationReason!.isNotEmpty)
|
||||
CancellationReasonBanner(
|
||||
reason: detail.cancellationReason!,
|
||||
titleLabel: context.t.staff_shifts.shift_details
|
||||
.shift_cancelled,
|
||||
),
|
||||
ShiftDetailsHeader(detail: detail),
|
||||
const Divider(height: 1, thickness: 0.5),
|
||||
ShiftStatsRow(
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// A banner displaying the cancellation reason for a cancelled shift.
|
||||
///
|
||||
/// Uses error styling to draw attention to the cancellation without being
|
||||
/// overly alarming. Shown at the top of the shift details page when the
|
||||
/// shift has been cancelled with a reason.
|
||||
class CancellationReasonBanner extends StatelessWidget {
|
||||
/// Creates a [CancellationReasonBanner].
|
||||
const CancellationReasonBanner({
|
||||
super.key,
|
||||
required this.reason,
|
||||
required this.titleLabel,
|
||||
});
|
||||
|
||||
/// The cancellation reason text.
|
||||
final String reason;
|
||||
|
||||
/// Localized title label (e.g., "Shift Cancelled").
|
||||
final String titleLabel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space5,
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.tagError,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
border: Border.all(
|
||||
color: UiColors.error.withValues(alpha: 0.3),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
const Icon(
|
||||
UiIcons.error,
|
||||
color: UiColors.error,
|
||||
size: UiConstants.iconMd,
|
||||
),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
titleLabel,
|
||||
style: UiTypography.body2b.copyWith(color: UiColors.error),
|
||||
),
|
||||
const SizedBox(height: UiConstants.space1),
|
||||
Text(
|
||||
reason,
|
||||
style: UiTypography.body3r.textPrimary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user