feat: add shimmer skeletons for various sections in the staff profile and onboarding features
- Implemented ProfilePageSkeleton for loading state in staff profile. - Added ReliabilityScoreSkeleton and ReliabilityStatsSkeleton for reliability metrics. - Created CertificatesSkeleton and related components for loading certificates. - Developed DocumentsSkeleton and associated document card skeletons. - Introduced TaxFormsSkeleton for loading tax forms. - Added BankAccountSkeleton and its components for bank account loading state. - Created TimeCardSkeleton for displaying time card loading state. - Implemented AttireSkeleton for loading attire items. - Added PersonalInfoSkeleton for loading personal information. - Developed FaqsSkeleton for loading FAQ sections. - Created PrivacySecuritySkeleton for loading privacy settings.
This commit is contained in:
@@ -10,6 +10,7 @@ import 'package:krow_domain/krow_domain.dart';
|
||||
import '../bloc/clock_in_bloc.dart';
|
||||
import '../bloc/clock_in_event.dart';
|
||||
import '../bloc/clock_in_state.dart';
|
||||
import '../widgets/clock_in_page_skeleton/clock_in_page_skeleton.dart';
|
||||
import '../widgets/commute_tracker.dart';
|
||||
import '../widgets/date_selector.dart';
|
||||
import '../widgets/lunch_break_modal.dart';
|
||||
@@ -52,8 +53,9 @@ class _ClockInPageState extends State<ClockInPage> {
|
||||
builder: (BuildContext context, ClockInState state) {
|
||||
if (state.status == ClockInStatus.loading &&
|
||||
state.todayShifts.isEmpty) {
|
||||
return const Scaffold(
|
||||
body: Center(child: CircularProgressIndicator()),
|
||||
return Scaffold(
|
||||
appBar: UiAppBar(title: i18n.title, showBackButton: false),
|
||||
body: const SafeArea(child: ClockInPageSkeleton()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Shimmer placeholder for the "Your Activity" section header text.
|
||||
class ActivityHeaderSkeleton extends StatelessWidget {
|
||||
/// Creates a shimmer line matching the activity header.
|
||||
const ActivityHeaderSkeleton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: UiShimmerLine(width: 120, height: 18),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'activity_header_skeleton.dart';
|
||||
import 'date_selector_skeleton.dart';
|
||||
import 'shift_card_skeleton.dart';
|
||||
import 'swipe_action_skeleton.dart';
|
||||
|
||||
/// Full-page shimmer skeleton shown while clock-in data loads.
|
||||
///
|
||||
/// Mirrors the loaded [ClockInPage] layout: date selector, activity header,
|
||||
/// two shift cards, and the swipe-to-check-in bar.
|
||||
class ClockInPageSkeleton extends StatelessWidget {
|
||||
/// Creates the clock-in page shimmer skeleton.
|
||||
const ClockInPageSkeleton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return UiShimmer(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: UiConstants.space24,
|
||||
top: UiConstants.space6,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space5,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: const <Widget>[
|
||||
// Date selector row
|
||||
DateSelectorSkeleton(),
|
||||
SizedBox(height: UiConstants.space5),
|
||||
|
||||
// "Your Activity" header
|
||||
ActivityHeaderSkeleton(),
|
||||
SizedBox(height: UiConstants.space4),
|
||||
|
||||
// Shift cards (show two placeholders)
|
||||
ShiftCardSkeleton(),
|
||||
ShiftCardSkeleton(),
|
||||
|
||||
// Swipe action bar
|
||||
SwipeActionSkeleton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Shimmer placeholder for the [DateSelector] row of 7 day chips.
|
||||
class DateSelectorSkeleton extends StatelessWidget {
|
||||
/// Creates a shimmer placeholder matching the date selector layout.
|
||||
const DateSelectorSkeleton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 80,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: List<Widget>.generate(7, (int index) {
|
||||
return Expanded(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space1,
|
||||
),
|
||||
child: const UiShimmerBox(
|
||||
width: double.infinity,
|
||||
height: 80,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Shimmer placeholder for a single shift info card.
|
||||
///
|
||||
/// Mirrors the two-column layout: left side has badge, title, and subtitle
|
||||
/// lines; right side has time range and rate lines.
|
||||
class ShiftCardSkeleton extends StatelessWidget {
|
||||
/// Creates a shimmer placeholder for one shift card.
|
||||
const ShiftCardSkeleton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(UiConstants.space3),
|
||||
margin: const EdgeInsets.only(bottom: UiConstants.space3),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.white,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
child: const Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
// Left column: badge + title + subtitle
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
UiShimmerLine(width: 80, height: 10),
|
||||
SizedBox(height: UiConstants.space2),
|
||||
UiShimmerLine(width: 160, height: 14),
|
||||
SizedBox(height: UiConstants.space1),
|
||||
UiShimmerLine(width: 200, height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: UiConstants.space3),
|
||||
// Right column: time + rate
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
UiShimmerLine(width: 100, height: 12),
|
||||
SizedBox(height: UiConstants.space1),
|
||||
UiShimmerLine(width: 60, height: 12),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Shimmer placeholder for the swipe-to-check-in action area.
|
||||
class SwipeActionSkeleton extends StatelessWidget {
|
||||
/// Creates a shimmer placeholder matching the swipe bar height.
|
||||
const SwipeActionSkeleton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const UiShimmerBox(
|
||||
width: double.infinity,
|
||||
height: 60,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user