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 '../blocs/availability_bloc.dart';
|
||||
import '../blocs/availability_event.dart';
|
||||
import '../blocs/availability_state.dart';
|
||||
import '../widgets/availability_page_skeleton/availability_page_skeleton.dart';
|
||||
|
||||
class AvailabilityPage extends StatefulWidget {
|
||||
const AvailabilityPage({super.key});
|
||||
@@ -72,7 +73,7 @@ class _AvailabilityPageState extends State<AvailabilityPage> {
|
||||
child: BlocBuilder<AvailabilityBloc, AvailabilityState>(
|
||||
builder: (context, state) {
|
||||
if (state is AvailabilityLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
return const AvailabilityPageSkeleton();
|
||||
} else if (state is AvailabilityLoaded) {
|
||||
return Stack(
|
||||
children: [
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export 'availability_page_skeleton/index.dart';
|
||||
@@ -0,0 +1,36 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'day_availability_skeleton.dart';
|
||||
import 'info_card_skeleton.dart';
|
||||
import 'quick_set_skeleton.dart';
|
||||
import 'week_navigation_skeleton.dart';
|
||||
|
||||
/// Shimmer loading skeleton for the availability page.
|
||||
///
|
||||
/// Mimics the loaded layout: quick-set buttons, week navigation calendar,
|
||||
/// selected day detail with time-slot rows, and an info card.
|
||||
class AvailabilityPageSkeleton extends StatelessWidget {
|
||||
/// Creates an [AvailabilityPageSkeleton].
|
||||
const AvailabilityPageSkeleton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return UiShimmer(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space5,
|
||||
),
|
||||
child: Column(
|
||||
spacing: UiConstants.space6,
|
||||
children: const [
|
||||
QuickSetSkeleton(),
|
||||
WeekNavigationSkeleton(),
|
||||
DayAvailabilitySkeleton(),
|
||||
InfoCardSkeleton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Shimmer placeholder for the selected day detail card (header + time slot rows).
|
||||
class DayAvailabilitySkeleton extends StatelessWidget {
|
||||
/// Creates a [DayAvailabilitySkeleton].
|
||||
const DayAvailabilitySkeleton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(UiConstants.space5),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.white,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Header: date text + toggle placeholder
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: const [
|
||||
UiShimmerLine(width: 160, height: 16),
|
||||
SizedBox(height: UiConstants.space1),
|
||||
UiShimmerLine(width: 80, height: 12),
|
||||
],
|
||||
),
|
||||
UiShimmerBox(
|
||||
width: 48,
|
||||
height: 28,
|
||||
borderRadius: UiConstants.radiusFull,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
// 3 time-slot rows (morning, afternoon, evening)
|
||||
..._buildSlotPlaceholders(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Generates 3 time-slot shimmer rows.
|
||||
List<Widget> _buildSlotPlaceholders() {
|
||||
return List.generate(3, (index) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: index < 2 ? UiConstants.space3 : 0,
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.white,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// Icon placeholder
|
||||
UiShimmerBox(
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius:
|
||||
UiConstants.radiusLg,
|
||||
),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
// Text lines
|
||||
const Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
UiShimmerLine(width: 80, height: 14),
|
||||
SizedBox(height: UiConstants.space1),
|
||||
UiShimmerLine(width: 120, height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Checkbox circle
|
||||
const UiShimmerCircle(size: 24),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export 'availability_page_skeleton.dart';
|
||||
export 'day_availability_skeleton.dart';
|
||||
export 'info_card_skeleton.dart';
|
||||
export 'quick_set_skeleton.dart';
|
||||
export 'week_navigation_skeleton.dart';
|
||||
@@ -0,0 +1,36 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Shimmer placeholder for the info card at the bottom (icon + two text lines).
|
||||
class InfoCardSkeleton extends StatelessWidget {
|
||||
/// Creates an [InfoCardSkeleton].
|
||||
const InfoCardSkeleton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.white,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const UiShimmerCircle(size: 20),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: const [
|
||||
UiShimmerLine(width: 140, height: 14),
|
||||
SizedBox(height: UiConstants.space1),
|
||||
UiShimmerLine(height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Shimmer placeholder for the quick-set section (title + 4 action buttons).
|
||||
class QuickSetSkeleton extends StatelessWidget {
|
||||
/// Creates a [QuickSetSkeleton].
|
||||
const QuickSetSkeleton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.white,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Title line
|
||||
const UiShimmerLine(width: 100, height: 14),
|
||||
const SizedBox(height: UiConstants.space3),
|
||||
// Row of 4 button placeholders
|
||||
Row(
|
||||
children: List.generate(4, (index) {
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: index == 0 ? 0 : UiConstants.space1,
|
||||
right: index == 3 ? 0 : UiConstants.space1,
|
||||
),
|
||||
child: UiShimmerBox(
|
||||
width: double.infinity,
|
||||
height: 32,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Shimmer placeholder for the week navigation card (month header + 7 day cells).
|
||||
class WeekNavigationSkeleton extends StatelessWidget {
|
||||
/// Creates a [WeekNavigationSkeleton].
|
||||
const WeekNavigationSkeleton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.white,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Navigation header: left arrow, month label, right arrow
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: UiConstants.space4),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const UiShimmerCircle(size: 32),
|
||||
UiShimmerLine(width: 140, height: 16),
|
||||
const UiShimmerCircle(size: 32),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 7 day cells
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: List.generate(7, (_) {
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: UiConstants.space1),
|
||||
child: UiShimmerBox(
|
||||
width: double.infinity,
|
||||
height: 64,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user