From 9c7ba321bc9488cfd84d17e4bf09e4d8fd65babc Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Tue, 10 Mar 2026 14:32:05 -0400 Subject: [PATCH] feat: implement shimmer loading skeletons for client home header and enhance loading states in banners --- .../widgets/client_home_edit_banner.dart | 9 +++- .../widgets/client_home_header.dart | 6 +++ .../widgets/client_home_header_skeleton.dart | 50 +++++++++++++++++++ .../reorder_card_skeleton.dart | 1 - .../reorder_section_skeleton.dart | 4 +- 5 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_header_skeleton.dart diff --git a/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_edit_banner.dart b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_edit_banner.dart index bcfe0d31..0a1f4489 100644 --- a/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_edit_banner.dart +++ b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_edit_banner.dart @@ -22,8 +22,15 @@ class ClientHomeEditBanner extends StatelessWidget { @override Widget build(BuildContext context) { return BlocBuilder( - buildWhen: (ClientHomeState prev, ClientHomeState curr) => prev.isEditMode != curr.isEditMode, + buildWhen: (ClientHomeState prev, ClientHomeState curr) => + prev.isEditMode != curr.isEditMode || + prev.status != curr.status, builder: (BuildContext context, ClientHomeState state) { + if (state.status == ClientHomeStatus.initial || + state.status == ClientHomeStatus.loading) { + return const SizedBox.shrink(); + } + return AnimatedContainer( duration: const Duration(milliseconds: 300), height: state.isEditMode ? 80 : 0, diff --git a/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_header.dart b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_header.dart index aebf6e36..9d311d2f 100644 --- a/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_header.dart +++ b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_header.dart @@ -7,6 +7,7 @@ import '../blocs/client_home_bloc.dart'; import '../blocs/client_home_event.dart'; import '../blocs/client_home_state.dart'; import 'header_icon_button.dart'; +import 'client_home_header_skeleton.dart'; /// The header section of the client home page. /// @@ -26,6 +27,11 @@ class ClientHomeHeader extends StatelessWidget { Widget build(BuildContext context) { return BlocBuilder( builder: (BuildContext context, ClientHomeState state) { + if (state.status == ClientHomeStatus.initial || + state.status == ClientHomeStatus.loading) { + return const ClientHomeHeaderSkeleton(); + } + final String businessName = state.businessName; final String? photoUrl = state.photoUrl; final String avatarLetter = businessName.trim().isNotEmpty diff --git a/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_header_skeleton.dart b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_header_skeleton.dart new file mode 100644 index 00000000..2e186863 --- /dev/null +++ b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_header_skeleton.dart @@ -0,0 +1,50 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; + +/// Shimmer placeholder for the client home header during loading. +/// +/// Mimics the avatar, welcome text, business name, and action buttons. +class ClientHomeHeaderSkeleton extends StatelessWidget { + /// Creates a [ClientHomeHeaderSkeleton]. + const ClientHomeHeaderSkeleton({super.key}); + + @override + Widget build(BuildContext context) { + return UiShimmer( + child: Padding( + padding: const EdgeInsets.fromLTRB( + UiConstants.space4, + UiConstants.space4, + UiConstants.space4, + UiConstants.space3, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + const UiShimmerCircle(size: UiConstants.space10), + const SizedBox(width: UiConstants.space3), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + UiShimmerLine(width: 80, height: 12), + SizedBox(height: UiConstants.space1), + UiShimmerLine(width: 120, height: 16), + ], + ), + ], + ), + Row( + spacing: UiConstants.space2, + children: const [ + UiShimmerBox(width: 36, height: 36), + UiShimmerBox(width: 36, height: 36), + ], + ), + ], + ), + ), + ); + } +} diff --git a/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_page_skeleton/reorder_card_skeleton.dart b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_page_skeleton/reorder_card_skeleton.dart index b07431ad..c5550a68 100644 --- a/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_page_skeleton/reorder_card_skeleton.dart +++ b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_page_skeleton/reorder_card_skeleton.dart @@ -9,7 +9,6 @@ class ReorderCardSkeleton extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - width: 260, padding: const EdgeInsets.all(UiConstants.space3), decoration: BoxDecoration( border: Border.all(color: UiColors.border, width: 0.6), diff --git a/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_page_skeleton/reorder_section_skeleton.dart b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_page_skeleton/reorder_section_skeleton.dart index 0e292f5a..783fc2b0 100644 --- a/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_page_skeleton/reorder_section_skeleton.dart +++ b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/client_home_page_skeleton/reorder_section_skeleton.dart @@ -19,9 +19,9 @@ class ReorderSectionSkeleton extends StatelessWidget { height: 164, child: Row( children: [ - ReorderCardSkeleton(), + Expanded(child: ReorderCardSkeleton()), SizedBox(width: UiConstants.space3), - ReorderCardSkeleton(), + Expanded(child: ReorderCardSkeleton()), ], ), ),