refactor: move HubDetailsPage edit/delete actions to a bottom navigation bar and display hub name/address within the body, adding loading state management.

This commit is contained in:
Achintha Isuru
2026-02-24 14:06:58 -05:00
parent e084dad4a7
commit f30cd89217

View File

@@ -42,81 +42,146 @@ class HubDetailsPage extends StatelessWidget {
); );
} }
}, },
child: Scaffold( child: BlocBuilder<HubDetailsBloc, HubDetailsState>(
appBar: UiAppBar( builder: (BuildContext context, HubDetailsState state) {
title: hub.name, final bool isLoading = state.status == HubDetailsStatus.loading;
subtitle: t.client_hubs.hub_details.title,
onLeadingPressed: () => Modular.to.pop(), return Scaffold(
actions: <Widget>[ appBar: UiAppBar(
IconButton( title: t.client_hubs.hub_details.title,
onPressed: () => _confirmDeleteHub(context), onLeadingPressed: () => Modular.to.pop(),
icon: const Icon(UiIcons.delete, color: UiColors.iconSecondary),
), ),
UiIconButton( bottomNavigationBar: SafeArea(
icon: UiIcons.edit, child: Column(
onTap: () => _navigateToEditPage(context), mainAxisSize: MainAxisSize.min,
backgroundColor: UiColors.transparent, children: <Widget>[
iconColor: UiColors.iconSecondary, const Divider(height: 1, thickness: 0.5),
Padding(
padding: const EdgeInsets.all(UiConstants.space5),
child: Row(
children: <Widget>[
Expanded(
child: UiButton.secondary(
onPressed: isLoading
? null
: () => _confirmDeleteHub(context),
text: t.common.delete,
leadingIcon: UiIcons.delete,
style: OutlinedButton.styleFrom(
foregroundColor: UiColors.destructive,
side: const BorderSide(
color: UiColors.destructive,
),
),
),
),
const SizedBox(width: UiConstants.space4),
Expanded(
child: UiButton.secondary(
onPressed: isLoading
? null
: () => _navigateToEditPage(context),
text: t.client_hubs.hub_details.edit_button,
leadingIcon: UiIcons.edit,
),
),
],
),
),
],
),
), ),
], backgroundColor: UiColors.bgMenu,
), body: Stack(
backgroundColor: UiColors.bgMenu, children: <Widget>[
body: SingleChildScrollView( SingleChildScrollView(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
// ── Header ──────────────────────────────────────────
Padding(
padding: const EdgeInsets.all(UiConstants.space5),
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[ children: <Widget>[
Container( // ── Header ──────────────────────────────────────────
width: 114, Padding(
decoration: BoxDecoration( padding: const EdgeInsets.all(UiConstants.space5),
color: UiColors.primary.withValues(alpha: 0.08), child: IntrinsicHeight(
borderRadius: BorderRadius.circular( child: Row(
UiConstants.radiusBase, crossAxisAlignment: CrossAxisAlignment.stretch,
), children: <Widget>[
border: Border.all(color: UiColors.primary), Container(
), width: 114,
child: const Center( decoration: BoxDecoration(
child: Icon( color: UiColors.primary.withValues(
UiIcons.nfc, alpha: 0.08,
color: UiColors.primary, ),
size: 32, borderRadius: BorderRadius.circular(
UiConstants.radiusBase,
),
border: Border.all(color: UiColors.primary),
),
child: const Center(
child: Icon(
UiIcons.nfc,
color: UiColors.primary,
size: 32,
),
),
),
const SizedBox(width: UiConstants.space4),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
hub.name,
style:
UiTypography.headline1b.textPrimary,
),
const SizedBox(
height: UiConstants.space1,
),
Row(
children: <Widget>[
const Icon(
UiIcons.mapPin,
size: 16,
color: UiColors.textSecondary,
),
const SizedBox(
width: UiConstants.space1,
),
Expanded(
child: Text(
hub.address,
style: UiTypography
.body2r
.textSecondary,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
],
),
],
),
),
],
), ),
), ),
), ),
const SizedBox(width: UiConstants.space4), const Divider(height: 1, thickness: 0.5),
Expanded(
Padding(
padding: const EdgeInsets.all(UiConstants.space5),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Text( _buildDetailItem(
hub.name, label: t.client_hubs.hub_details.nfc_label,
style: UiTypography.headline1b.textPrimary, value:
), hub.nfcTagId ??
const SizedBox(height: UiConstants.space1), t.client_hubs.hub_details.nfc_not_assigned,
Row( icon: UiIcons.nfc,
children: <Widget>[ isHighlight: hub.nfcTagId != null,
const Icon(
UiIcons.mapPin,
size: 16,
color: UiColors.textSecondary,
),
const SizedBox(width: UiConstants.space1),
Expanded(
child: Text(
hub.address,
style: UiTypography.body2r.textSecondary,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
],
), ),
], ],
), ),
@@ -124,28 +189,15 @@ class HubDetailsPage extends StatelessWidget {
], ],
), ),
), ),
), if (isLoading)
const Divider(height: 1, thickness: 0.5), Container(
color: UiColors.black.withValues(alpha: 0.1),
Padding( child: const Center(child: CircularProgressIndicator()),
padding: const EdgeInsets.all(UiConstants.space5), ),
child: Column( ],
crossAxisAlignment: CrossAxisAlignment.stretch, ),
children: <Widget>[ );
_buildDetailItem( },
label: t.client_hubs.hub_details.nfc_label,
value:
hub.nfcTagId ??
t.client_hubs.hub_details.nfc_not_assigned,
icon: UiIcons.nfc,
isHighlight: hub.nfcTagId != null,
),
],
),
),
],
),
),
), ),
), ),
); );
@@ -210,11 +262,11 @@ class HubDetailsPage extends StatelessWidget {
title: Text(t.client_hubs.delete_dialog.title), title: Text(t.client_hubs.delete_dialog.title),
content: Text(t.client_hubs.delete_dialog.message(hubName: hub.name)), content: Text(t.client_hubs.delete_dialog.message(hubName: hub.name)),
actions: <Widget>[ actions: <Widget>[
TextButton( UiButton.text(
onPressed: () => Navigator.of(context).pop(false), onPressed: () => Navigator.of(context).pop(false),
child: Text(t.client_hubs.delete_dialog.cancel), child: Text(t.client_hubs.delete_dialog.cancel),
), ),
TextButton( UiButton.text(
onPressed: () => Navigator.of(context).pop(true), onPressed: () => Navigator.of(context).pop(true),
style: TextButton.styleFrom(foregroundColor: UiColors.destructive), style: TextButton.styleFrom(foregroundColor: UiColors.destructive),
child: Text(t.client_hubs.delete_dialog.delete), child: Text(t.client_hubs.delete_dialog.delete),