feat: add shimmer loading skeletons for various pages and components

- Implemented ReorderCardSkeleton and ReorderSectionSkeleton for the client home page.
- Added SpendingCardSkeleton and SpendingSectionSkeleton for spending-related UI.
- Created OrderCardSkeleton and associated skeletons for the view orders page.
- Developed MetricCardSkeleton and MetricsGridSkeleton for reports page metrics.
- Introduced HomePageSkeleton and its components for staff home page.
- Added PaymentItemSkeleton and PaymentsPageSkeleton for payments page.
- Created ShiftDetailsPageSkeleton and related components for shift details.
- Implemented ShiftsPageSkeleton and ShiftCardSkeleton for shifts page.
This commit is contained in:
Achintha Isuru
2026-03-10 14:25:56 -04:00
parent 2d6133aba8
commit 4423775fa1
52 changed files with 1603 additions and 1443 deletions

View File

@@ -1,135 +1 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
/// Shimmer loading skeleton for the billing page content area.
///
/// Mimics the loaded layout with a pending invoices section,
/// a spending breakdown card, and an invoice history list.
class BillingPageSkeleton extends StatelessWidget {
/// Creates a [BillingPageSkeleton].
const BillingPageSkeleton({super.key});
@override
Widget build(BuildContext context) {
return UiShimmer(
child: Padding(
padding: const EdgeInsets.all(UiConstants.space5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Pending invoices section header
const UiShimmerSectionHeader(),
const SizedBox(height: UiConstants.space3),
// Pending invoice cards
const _InvoiceCardSkeleton(),
const SizedBox(height: UiConstants.space4),
const _InvoiceCardSkeleton(),
const SizedBox(height: UiConstants.space6),
// Spending breakdown card
Container(
padding: const EdgeInsets.all(UiConstants.space5),
decoration: BoxDecoration(
border: Border.all(color: UiColors.border),
borderRadius: UiConstants.radiusLg,
),
child: const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
UiShimmerLine(width: 160, height: 16),
SizedBox(height: UiConstants.space4),
// Breakdown rows
_BreakdownRowSkeleton(),
SizedBox(height: UiConstants.space3),
_BreakdownRowSkeleton(),
SizedBox(height: UiConstants.space3),
_BreakdownRowSkeleton(),
],
),
),
const SizedBox(height: UiConstants.space6),
// Invoice history section header
const UiShimmerSectionHeader(),
const SizedBox(height: UiConstants.space3),
const UiShimmerListItem(),
const UiShimmerListItem(),
const UiShimmerListItem(),
],
),
),
);
}
}
/// Shimmer placeholder for a single pending invoice card.
class _InvoiceCardSkeleton extends StatelessWidget {
const _InvoiceCardSkeleton();
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(UiConstants.space4),
decoration: BoxDecoration(
border: Border.all(color: UiColors.border),
borderRadius: UiConstants.radiusLg,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
UiShimmerBox(
width: 72,
height: 24,
borderRadius: UiConstants.radiusFull,
),
const UiShimmerLine(width: 80, height: 12),
],
),
const SizedBox(height: UiConstants.space4),
const UiShimmerLine(width: 200, height: 16),
const SizedBox(height: UiConstants.space2),
const UiShimmerLine(width: 160, height: 12),
const SizedBox(height: UiConstants.space4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
UiShimmerLine(width: 80, height: 10),
SizedBox(height: UiConstants.space1),
UiShimmerLine(width: 100, height: 18),
],
),
UiShimmerBox(
width: 100,
height: 36,
borderRadius: UiConstants.radiusMd,
),
],
),
],
),
);
}
}
/// Shimmer placeholder for a spending breakdown row.
class _BreakdownRowSkeleton extends StatelessWidget {
const _BreakdownRowSkeleton();
@override
Widget build(BuildContext context) {
return const Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
UiShimmerLine(width: 100, height: 14),
UiShimmerLine(width: 60, height: 14),
],
);
}
}
export 'billing_page_skeleton/index.dart';

View File

@@ -0,0 +1,67 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'breakdown_row_skeleton.dart';
import 'invoice_card_skeleton.dart';
/// Shimmer loading skeleton for the billing page content area.
///
/// Mimics the loaded layout with a pending invoices section,
/// a spending breakdown card, and an invoice history list.
class BillingPageSkeleton extends StatelessWidget {
/// Creates a [BillingPageSkeleton].
const BillingPageSkeleton({super.key});
@override
Widget build(BuildContext context) {
return UiShimmer(
child: Padding(
padding: const EdgeInsets.all(UiConstants.space5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Pending invoices section header
const UiShimmerSectionHeader(),
const SizedBox(height: UiConstants.space3),
// Pending invoice cards
const InvoiceCardSkeleton(),
const SizedBox(height: UiConstants.space4),
const InvoiceCardSkeleton(),
const SizedBox(height: UiConstants.space6),
// Spending breakdown card
Container(
padding: const EdgeInsets.all(UiConstants.space5),
decoration: BoxDecoration(
border: Border.all(color: UiColors.border),
borderRadius: UiConstants.radiusLg,
),
child: const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
UiShimmerLine(width: 160, height: 16),
SizedBox(height: UiConstants.space4),
// Breakdown rows
BreakdownRowSkeleton(),
SizedBox(height: UiConstants.space3),
BreakdownRowSkeleton(),
SizedBox(height: UiConstants.space3),
BreakdownRowSkeleton(),
],
),
),
const SizedBox(height: UiConstants.space6),
// Invoice history section header
const UiShimmerSectionHeader(),
const SizedBox(height: UiConstants.space3),
const UiShimmerListItem(),
const UiShimmerListItem(),
const UiShimmerListItem(),
],
),
),
);
}
}

View File

@@ -0,0 +1,19 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
/// Shimmer placeholder for a spending breakdown row.
class BreakdownRowSkeleton extends StatelessWidget {
/// Creates a [BreakdownRowSkeleton].
const BreakdownRowSkeleton({super.key});
@override
Widget build(BuildContext context) {
return const Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
UiShimmerLine(width: 100, height: 14),
UiShimmerLine(width: 60, height: 14),
],
);
}
}

View File

@@ -0,0 +1,3 @@
export 'billing_page_skeleton.dart';
export 'breakdown_row_skeleton.dart';
export 'invoice_card_skeleton.dart';

View File

@@ -0,0 +1,58 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
/// Shimmer placeholder for a single pending invoice card.
class InvoiceCardSkeleton extends StatelessWidget {
/// Creates an [InvoiceCardSkeleton].
const InvoiceCardSkeleton({super.key});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(UiConstants.space4),
decoration: BoxDecoration(
border: Border.all(color: UiColors.border),
borderRadius: UiConstants.radiusLg,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
UiShimmerBox(
width: 72,
height: 24,
borderRadius: UiConstants.radiusFull,
),
const UiShimmerLine(width: 80, height: 12),
],
),
const SizedBox(height: UiConstants.space4),
const UiShimmerLine(width: 200, height: 16),
const SizedBox(height: UiConstants.space2),
const UiShimmerLine(width: 160, height: 12),
const SizedBox(height: UiConstants.space4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
UiShimmerLine(width: 80, height: 10),
SizedBox(height: UiConstants.space1),
UiShimmerLine(width: 100, height: 18),
],
),
UiShimmerBox(
width: 100,
height: 36,
borderRadius: UiConstants.radiusMd,
),
],
),
],
),
);
}
}