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(
appBar: UiAppBar(
title: hub.name,
subtitle: t.client_hubs.hub_details.title,
onLeadingPressed: () => Modular.to.pop(),
actions: <Widget>[
IconButton(
onPressed: () => _confirmDeleteHub(context),
icon: const Icon(UiIcons.delete, color: UiColors.iconSecondary),
child: BlocBuilder<HubDetailsBloc, HubDetailsState>(
builder: (BuildContext context, HubDetailsState state) {
final bool isLoading = state.status == HubDetailsStatus.loading;
return Scaffold(
appBar: UiAppBar(
title: t.client_hubs.hub_details.title,
onLeadingPressed: () => Modular.to.pop(),
),
UiIconButton(
icon: UiIcons.edit,
onTap: () => _navigateToEditPage(context),
backgroundColor: UiColors.transparent,
iconColor: UiColors.iconSecondary,
bottomNavigationBar: SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
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: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
// ── Header ──────────────────────────────────────────
Padding(
padding: const EdgeInsets.all(UiConstants.space5),
child: IntrinsicHeight(
child: Row(
backgroundColor: UiColors.bgMenu,
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
width: 114,
decoration: BoxDecoration(
color: UiColors.primary.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(
UiConstants.radiusBase,
),
border: Border.all(color: UiColors.primary),
),
child: const Center(
child: Icon(
UiIcons.nfc,
color: UiColors.primary,
size: 32,
// ── Header ──────────────────────────────────────────
Padding(
padding: const EdgeInsets.all(UiConstants.space5),
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
width: 114,
decoration: BoxDecoration(
color: UiColors.primary.withValues(
alpha: 0.08,
),
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),
Expanded(
const Divider(height: 1, thickness: 0.5),
Padding(
padding: const EdgeInsets.all(UiConstants.space5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
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,
),
),
],
_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,
),
],
),
@@ -124,28 +189,15 @@ class HubDetailsPage extends StatelessWidget {
],
),
),
),
const Divider(height: 1, thickness: 0.5),
Padding(
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,
),
],
),
),
],
),
),
if (isLoading)
Container(
color: UiColors.black.withValues(alpha: 0.1),
child: const Center(child: CircularProgressIndicator()),
),
],
),
);
},
),
),
);
@@ -210,11 +262,11 @@ class HubDetailsPage extends StatelessWidget {
title: Text(t.client_hubs.delete_dialog.title),
content: Text(t.client_hubs.delete_dialog.message(hubName: hub.name)),
actions: <Widget>[
TextButton(
UiButton.text(
onPressed: () => Navigator.of(context).pop(false),
child: Text(t.client_hubs.delete_dialog.cancel),
),
TextButton(
UiButton.text(
onPressed: () => Navigator.of(context).pop(true),
style: TextButton.styleFrom(foregroundColor: UiColors.destructive),
child: Text(t.client_hubs.delete_dialog.delete),