refactor: Standardize shift details UI by adopting UiButton and UiChip components, adjusting layout, and refining chip styling.

This commit is contained in:
Achintha Isuru
2026-02-22 19:59:22 -05:00
parent c48d981ddb
commit 68d6e7c5e3
4 changed files with 17 additions and 60 deletions

View File

@@ -29,7 +29,6 @@ enum UiChipVariant {
/// A custom chip widget with supports for different sizes, themes, and icons. /// A custom chip widget with supports for different sizes, themes, and icons.
class UiChip extends StatelessWidget { class UiChip extends StatelessWidget {
/// Creates a [UiChip]. /// Creates a [UiChip].
const UiChip({ const UiChip({
super.key, super.key,
@@ -42,6 +41,7 @@ class UiChip extends StatelessWidget {
this.onTrailingIconTap, this.onTrailingIconTap,
this.isSelected = false, this.isSelected = false,
}); });
/// The text label to display. /// The text label to display.
final String label; final String label;
@@ -99,7 +99,7 @@ class UiChip extends StatelessWidget {
padding: padding, padding: padding,
decoration: BoxDecoration( decoration: BoxDecoration(
color: backgroundColor, color: backgroundColor,
borderRadius: UiConstants.radiusFull, borderRadius: UiConstants.radiusMd,
border: _getBorder(), border: _getBorder(),
), ),
child: content, child: content,

View File

@@ -140,8 +140,6 @@ class _ShiftDetailsPageState extends State<ShiftDetailsPage> {
children: [ children: [
ShiftDetailsHeader(shift: displayShift), ShiftDetailsHeader(shift: displayShift),
const Divider(height: 1, thickness: 0.5), const Divider(height: 1, thickness: 0.5),
ShiftScheduleSummarySection(shift: displayShift),
const Divider(height: 1, thickness: 0.5),
ShiftStatsRow( ShiftStatsRow(
estimatedTotal: estimatedTotal, estimatedTotal: estimatedTotal,
hourlyRate: displayShift.hourlyRate, hourlyRate: displayShift.hourlyRate,
@@ -160,6 +158,8 @@ class _ShiftDetailsPageState extends State<ShiftDetailsPage> {
clockOutLabel: i18n.end_time, clockOutLabel: i18n.end_time,
), ),
const Divider(height: 1, thickness: 0.5), const Divider(height: 1, thickness: 0.5),
ShiftScheduleSummarySection(shift: displayShift),
const Divider(height: 1, thickness: 0.5),
if (displayShift.breakInfo != null && if (displayShift.breakInfo != null &&
displayShift.breakInfo!.duration != displayShift.breakInfo!.duration !=
BreakDuration.none) ...[ BreakDuration.none) ...[

View File

@@ -1,21 +1,21 @@
import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart'; import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart'; import 'package:flutter_modular/flutter_modular.dart';
import 'package:krow_domain/krow_domain.dart';
import 'package:core_localization/core_localization.dart';
import 'package:krow_core/core.dart'; import 'package:krow_core/core.dart';
import 'package:krow_domain/krow_domain.dart';
/// A bottom action bar containing contextual buttons based on shift status. /// A bottom action bar containing contextual buttons based on shift status.
class ShiftDetailsBottomBar extends StatelessWidget { class ShiftDetailsBottomBar extends StatelessWidget {
/// The current shift. /// The current shift.
final Shift shift; final Shift shift;
/// Callback for applying/booking a shift. /// Callback for applying/booking a shift.
final VoidCallback onApply; final VoidCallback onApply;
/// Callback for declining a shift. /// Callback for declining a shift.
final VoidCallback onDecline; final VoidCallback onDecline;
/// Callback for accepting a shift. /// Callback for accepting a shift.
final VoidCallback onAccept; final VoidCallback onAccept;
@@ -57,19 +57,9 @@ class ShiftDetailsBottomBar extends StatelessWidget {
Widget _buildButtons(String status, dynamic i18n, BuildContext context) { Widget _buildButtons(String status, dynamic i18n, BuildContext context) {
if (status == 'confirmed') { if (status == 'confirmed') {
return SizedBox( return Expanded(
width: double.infinity, child: UiButton.primary(
child: ElevatedButton(
onPressed: () => Modular.to.toClockIn(), onPressed: () => Modular.to.toClockIn(),
style: ElevatedButton.styleFrom(
backgroundColor: UiColors.success,
foregroundColor: UiColors.white,
padding: const EdgeInsets.symmetric(vertical: UiConstants.space4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
),
elevation: 0,
),
child: Text(i18n.clock_in, style: UiTypography.body2b.white), child: Text(i18n.clock_in, style: UiTypography.body2b.white),
), ),
); );
@@ -79,36 +69,15 @@ class ShiftDetailsBottomBar extends StatelessWidget {
return Row( return Row(
children: [ children: [
Expanded( Expanded(
child: OutlinedButton( child: UiButton.secondary(
onPressed: onDecline, onPressed: onDecline,
style: OutlinedButton.styleFrom(
foregroundColor: UiColors.destructive,
padding: const EdgeInsets.symmetric(
vertical: UiConstants.space4,
),
side: const BorderSide(color: UiColors.destructive),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
),
),
child: Text(i18n.decline, style: UiTypography.body2b.textError), child: Text(i18n.decline, style: UiTypography.body2b.textError),
), ),
), ),
const SizedBox(width: UiConstants.space4), const SizedBox(width: UiConstants.space4),
Expanded( Expanded(
child: ElevatedButton( child: UiButton.primary(
onPressed: onAccept, onPressed: onAccept,
style: ElevatedButton.styleFrom(
backgroundColor: UiColors.primary,
foregroundColor: UiColors.white,
padding: const EdgeInsets.symmetric(
vertical: UiConstants.space4,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
),
elevation: 0,
),
child: Text(i18n.accept_shift, style: UiTypography.body2b.white), child: Text(i18n.accept_shift, style: UiTypography.body2b.white),
), ),
), ),
@@ -117,17 +86,9 @@ class ShiftDetailsBottomBar extends StatelessWidget {
} }
if (status == 'open' || status == 'available') { if (status == 'open' || status == 'available') {
return ElevatedButton( return UiButton.primary(
onPressed: onApply, onPressed: onApply,
style: ElevatedButton.styleFrom( fullWidth: true,
backgroundColor: UiColors.primary,
foregroundColor: UiColors.white,
padding: const EdgeInsets.symmetric(vertical: UiConstants.space4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
),
elevation: 0,
),
child: Text(i18n.apply_now, style: UiTypography.body2b.white), child: Text(i18n.apply_now, style: UiTypography.body2b.white),
); );
} }

View File

@@ -41,14 +41,10 @@ class ShiftScheduleSummarySection extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Shift Type Title // Shift Type Title
Text( UiChip(label: typeLabel, variant: UiChipVariant.secondary),
typeLabel.toUpperCase(), const SizedBox(height: UiConstants.space2),
style: UiTypography.titleUppercase4b.textSecondary,
),
if (isMultiDay) ...[ if (isMultiDay) ...[
const SizedBox(height: UiConstants.space3),
// Date Range // Date Range
if (shift.startDate != null && shift.endDate != null) if (shift.startDate != null && shift.endDate != null)
Row( Row(