- Updated import paths across multiple files to reflect the new package name. - Changed application name and identifiers in CMakeLists.txt, Runner.rc, and other configuration files. - Modified web index.html and manifest.json to update the app title and name. - Adjusted macOS and Windows project settings to align with the new application name. - Ensured consistency in naming across all relevant files and directories.
1402 lines
47 KiB
Dart
1402 lines
47 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:on_field_work/helpers/widgets/my_card.dart';
|
|
import 'package:on_field_work/helpers/widgets/my_spacing.dart';
|
|
import 'package:on_field_work/helpers/utils/my_shadow.dart';
|
|
|
|
class SkeletonLoaders {
|
|
static Widget buildLoadingSkeleton() {
|
|
return SizedBox(
|
|
height: 360,
|
|
child: Column(
|
|
children: List.generate(5, (index) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 6),
|
|
child: SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
child: Row(
|
|
children: List.generate(6, (i) {
|
|
return Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 4),
|
|
width: 48,
|
|
height: 16,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Inside SkeletonLoaders class
|
|
static Widget dashboardCardsSkeleton({double? maxWidth}) {
|
|
return LayoutBuilder(builder: (context, constraints) {
|
|
double width = maxWidth ?? constraints.maxWidth;
|
|
int crossAxisCount = (width ~/ 80).clamp(2, 4);
|
|
double cardWidth = (width - (crossAxisCount - 1) * 6) / crossAxisCount;
|
|
|
|
return Wrap(
|
|
spacing: 6,
|
|
runSpacing: 6,
|
|
children: List.generate(6, (index) {
|
|
return MyCard.bordered(
|
|
width: cardWidth,
|
|
height: 60,
|
|
paddingAll: 4,
|
|
borderRadiusAll: 5,
|
|
border: Border.all(color: Colors.grey.withOpacity(0.15)),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Container(
|
|
width: 16,
|
|
height: 16,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
MySpacing.height(4),
|
|
Container(
|
|
width: cardWidth * 0.5,
|
|
height: 10,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}),
|
|
);
|
|
});
|
|
}
|
|
|
|
// Inside SkeletonLoaders class
|
|
static Widget paymentRequestListSkeletonLoader() {
|
|
return ListView.separated(
|
|
padding: const EdgeInsets.fromLTRB(12, 12, 12, 80),
|
|
itemCount: 6,
|
|
separatorBuilder: (_, __) =>
|
|
Divider(color: Colors.grey.shade300, height: 20),
|
|
itemBuilder: (context, index) {
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Category name placeholder
|
|
Container(
|
|
height: 14,
|
|
width: 120,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
const SizedBox(height: 6),
|
|
|
|
// Payee placeholder
|
|
Row(
|
|
children: [
|
|
Container(
|
|
height: 12,
|
|
width: 50,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade200,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: Container(
|
|
height: 12,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 6),
|
|
|
|
// Due date and status placeholders
|
|
Row(
|
|
children: [
|
|
// Due date label + value
|
|
Row(
|
|
children: [
|
|
Container(
|
|
height: 12,
|
|
width: 50,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade200,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
const SizedBox(width: 6),
|
|
Container(
|
|
height: 12,
|
|
width: 80,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const Spacer(),
|
|
// Status chip placeholder
|
|
Container(
|
|
height: 20,
|
|
width: 60,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
// Add this inside SkeletonLoaders class
|
|
static Widget paymentRequestDetailSkeletonLoader() {
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.fromLTRB(12, 12, 12, 30),
|
|
child: Center(
|
|
child: Container(
|
|
constraints: const BoxConstraints(maxWidth: 520),
|
|
child: MyCard.bordered(
|
|
paddingAll: 16,
|
|
borderRadiusAll: 8,
|
|
shadow: MyShadow(elevation: 3),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Header (Created At + Status)
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Container(
|
|
width: 140,
|
|
height: 16,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
Container(
|
|
width: 80,
|
|
height: 20,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(5),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
MySpacing.height(24),
|
|
|
|
// Parties Section
|
|
...List.generate(
|
|
4,
|
|
(index) => Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
child: Container(
|
|
height: 14,
|
|
width: double.infinity,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
)),
|
|
MySpacing.height(24),
|
|
|
|
// Details Table
|
|
...List.generate(
|
|
6,
|
|
(index) => Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
child: Container(
|
|
height: 14,
|
|
width: double.infinity,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
)),
|
|
MySpacing.height(24),
|
|
|
|
// Documents Section
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: List.generate(
|
|
3,
|
|
(index) => Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
child: Container(
|
|
height: 40,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
)),
|
|
),
|
|
MySpacing.height(24),
|
|
|
|
// Logs / Timeline
|
|
Column(
|
|
children: List.generate(
|
|
3,
|
|
(index) => Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
width: 16,
|
|
height: 16,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
MySpacing.width(12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
height: 14,
|
|
width: 120,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
MySpacing.height(6),
|
|
Container(
|
|
height: 12,
|
|
width: double.infinity,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
MySpacing.height(6),
|
|
Container(
|
|
height: 12,
|
|
width: 80,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
MySpacing.height(16),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
)),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Employee Detail Skeleton Loader
|
|
static Widget employeeDetailSkeletonLoader() {
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.fromLTRB(12, 20, 12, 80),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
// Header skeleton (avatar + name + role)
|
|
MyCard(
|
|
borderRadiusAll: 8,
|
|
paddingAll: 16,
|
|
margin: MySpacing.bottom(16),
|
|
shadow: MyShadow(elevation: 2),
|
|
child: Row(
|
|
children: [
|
|
// Avatar
|
|
Container(
|
|
width: 45,
|
|
height: 45,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
MySpacing.width(16),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
height: 14,
|
|
width: 120,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
MySpacing.height(6),
|
|
Container(
|
|
height: 12,
|
|
width: 80,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Container(
|
|
width: 24,
|
|
height: 24,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Sections skeleton
|
|
...List.generate(
|
|
4,
|
|
(_) => Column(
|
|
children: [
|
|
MyCard(
|
|
borderRadiusAll: 8,
|
|
paddingAll: 16,
|
|
margin: MySpacing.bottom(16),
|
|
shadow: MyShadow(elevation: 2),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Section header
|
|
Row(
|
|
children: [
|
|
Container(
|
|
width: 20,
|
|
height: 20,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
MySpacing.width(8),
|
|
Container(
|
|
width: 120,
|
|
height: 14,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
],
|
|
),
|
|
MySpacing.height(8),
|
|
const Divider(color: Colors.grey),
|
|
|
|
// 2 rows placeholder
|
|
...List.generate(
|
|
2,
|
|
(_) => Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 12),
|
|
child: Row(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
width: 20,
|
|
height: 20,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
MySpacing.width(16),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
height: 12,
|
|
width: 100,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
MySpacing.height(4),
|
|
Container(
|
|
height: 12,
|
|
width: 150,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Container(
|
|
width: 20,
|
|
height: 20,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
],
|
|
),
|
|
)),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
)),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// Daily Progress Planning - Infra (Expanded) Skeleton Loader
|
|
static Widget dailyProgressPlanningInfraSkeleton() {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: List.generate(3, (floorIndex) {
|
|
return MyCard(
|
|
borderRadiusAll: 8,
|
|
paddingAll: 5,
|
|
margin: MySpacing.bottom(10),
|
|
shadow: MyShadow(elevation: 1.5),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Floor header placeholder
|
|
Container(
|
|
height: 14,
|
|
width: 160,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
),
|
|
MySpacing.height(10),
|
|
|
|
// Divider
|
|
Divider(color: Colors.grey.withOpacity(0.3)),
|
|
|
|
// Work areas skeleton
|
|
Column(
|
|
children: List.generate(2, (areaIndex) {
|
|
return Padding(
|
|
padding: const EdgeInsets.only(top: 8, bottom: 6),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Area title
|
|
Container(
|
|
height: 12,
|
|
width: 120,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
MySpacing.height(8),
|
|
|
|
// Work items skeleton rows
|
|
Column(
|
|
children: List.generate(2, (itemIndex) {
|
|
return Padding(
|
|
padding: const EdgeInsets.only(top: 4),
|
|
child: Row(
|
|
children: [
|
|
// Bullet / icon
|
|
Container(
|
|
width: 8,
|
|
height: 8,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
MySpacing.width(8),
|
|
// Item text placeholder
|
|
Expanded(
|
|
child: Container(
|
|
height: 10,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}),
|
|
);
|
|
}
|
|
|
|
// Chart Skeleton Loader (Donut Chart)
|
|
static Widget chartSkeletonLoader() {
|
|
return MyCard.bordered(
|
|
paddingAll: 16,
|
|
borderRadiusAll: 12,
|
|
shadow: MyShadow(
|
|
elevation: 1.5,
|
|
position: MyShadowPosition.bottom,
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Chart Header Placeholder
|
|
Container(
|
|
height: 16,
|
|
width: 180,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Donut Skeleton Placeholder
|
|
Expanded(
|
|
child: Center(
|
|
child: Container(
|
|
width: 180,
|
|
height: 180,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
color: Colors.grey.shade300.withOpacity(0.5),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
// Legend placeholders
|
|
Wrap(
|
|
spacing: 8,
|
|
runSpacing: 8,
|
|
children: List.generate(5, (index) {
|
|
return Container(
|
|
width: 100,
|
|
height: 14,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// Date Skeleton Loader
|
|
static Widget dateSkeletonLoader() {
|
|
return Container(
|
|
height: 14,
|
|
width: 90,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Expense By Status Skeleton Loader
|
|
static Widget expenseByStatusSkeletonLoader() {
|
|
return Container(
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(5),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.grey.withOpacity(0.05),
|
|
blurRadius: 6,
|
|
spreadRadius: 1,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Title
|
|
Container(
|
|
height: 16,
|
|
width: 160,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// 4 Status Rows
|
|
...List.generate(4, (index) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 6),
|
|
child: Row(
|
|
children: [
|
|
// Icon placeholder
|
|
Container(
|
|
height: 44,
|
|
width: 44,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
|
|
// Title + Amount
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
height: 12,
|
|
width: 100,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
const SizedBox(height: 6),
|
|
Container(
|
|
height: 12,
|
|
width: 60,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Count + arrow placeholder
|
|
Container(
|
|
height: 12,
|
|
width: 30,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
const SizedBox(width: 6),
|
|
Icon(Icons.chevron_right,
|
|
color: Colors.grey.shade300, size: 24),
|
|
],
|
|
),
|
|
);
|
|
}),
|
|
|
|
const SizedBox(height: 16),
|
|
Divider(color: Colors.grey.shade300),
|
|
const SizedBox(height: 12),
|
|
|
|
// Bottom Row (Project Spendings)
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
height: 12,
|
|
width: 120,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Container(
|
|
height: 10,
|
|
width: 140,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
Container(
|
|
height: 16,
|
|
width: 80,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// Document List Skeleton Loader
|
|
static Widget documentSkeletonLoader() {
|
|
return Column(
|
|
children: List.generate(5, (index) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Date placeholder
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
|
child: Container(
|
|
height: 12,
|
|
width: 80,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
),
|
|
),
|
|
|
|
// Document Card Skeleton
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(12),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.05),
|
|
blurRadius: 4,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Icon Placeholder
|
|
Container(
|
|
padding: const EdgeInsets.all(10),
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: const Icon(Icons.description,
|
|
color: Colors.transparent), // invisible icon
|
|
),
|
|
const SizedBox(width: 12),
|
|
|
|
// Text placeholders
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
height: 12,
|
|
width: 80,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
MySpacing.height(6),
|
|
Container(
|
|
height: 14,
|
|
width: double.infinity,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
MySpacing.height(6),
|
|
Container(
|
|
height: 12,
|
|
width: 100,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Action icon placeholder
|
|
Container(
|
|
width: 20,
|
|
height: 20,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}),
|
|
);
|
|
}
|
|
|
|
// Document Details Card Skeleton Loader
|
|
static Widget documentDetailsSkeletonLoader() {
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Details Card
|
|
Container(
|
|
constraints: const BoxConstraints(maxWidth: 460),
|
|
padding: const EdgeInsets.all(20),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(10),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.06),
|
|
blurRadius: 16,
|
|
offset: const Offset(0, 4),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Header
|
|
Row(
|
|
children: [
|
|
Container(
|
|
width: 56,
|
|
height: 56,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
const SizedBox(width: 16),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
height: 16,
|
|
width: 180,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
const SizedBox(height: 8),
|
|
Container(
|
|
height: 12,
|
|
width: 120,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 12),
|
|
|
|
// Tags placeholder
|
|
Wrap(
|
|
spacing: 6,
|
|
runSpacing: 6,
|
|
children: List.generate(3, (index) {
|
|
return Container(
|
|
height: 20,
|
|
width: 60,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Info rows placeholders
|
|
Column(
|
|
children: List.generate(10, (index) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 6),
|
|
child: Row(
|
|
children: [
|
|
Container(
|
|
height: 12,
|
|
width: 120,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Container(
|
|
height: 12,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 20),
|
|
|
|
// Versions section skeleton
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 12),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: List.generate(3, (index) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 6),
|
|
child: Row(
|
|
children: [
|
|
Container(
|
|
width: 40,
|
|
height: 40,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
height: 12,
|
|
width: 180,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
const SizedBox(height: 6),
|
|
Container(
|
|
height: 10,
|
|
width: 120,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Container(
|
|
width: 24,
|
|
height: 24,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// Employee List - Card Style
|
|
static Widget employeeListSkeletonLoader() {
|
|
return Column(
|
|
children: List.generate(4, (index) {
|
|
return MyCard.bordered(
|
|
borderRadiusAll: 12,
|
|
paddingAll: 10,
|
|
margin: MySpacing.bottom(12),
|
|
shadow: MyShadow(elevation: 3),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Avatar
|
|
Container(
|
|
width: 41,
|
|
height: 41,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
MySpacing.width(16),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Container(
|
|
height: 14,
|
|
width: 100,
|
|
color: Colors.grey.shade300),
|
|
MySpacing.width(8),
|
|
Container(
|
|
height: 12, width: 60, color: Colors.grey.shade300),
|
|
],
|
|
),
|
|
MySpacing.height(8),
|
|
Row(
|
|
children: [
|
|
Icon(Icons.email,
|
|
size: 16, color: Colors.grey.shade300),
|
|
MySpacing.width(4),
|
|
Container(
|
|
height: 10,
|
|
width: 140,
|
|
color: Colors.grey.shade300),
|
|
],
|
|
),
|
|
MySpacing.height(8),
|
|
Row(
|
|
children: [
|
|
Icon(Icons.phone,
|
|
size: 16, color: Colors.grey.shade300),
|
|
MySpacing.width(4),
|
|
Container(
|
|
height: 10,
|
|
width: 100,
|
|
color: Colors.grey.shade300),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}),
|
|
);
|
|
}
|
|
|
|
// Employee List - Compact Collapsed Style
|
|
static Widget employeeListCollapsedSkeletonLoader() {
|
|
return MyCard.bordered(
|
|
borderRadiusAll: 4,
|
|
paddingAll: 8,
|
|
child: Column(
|
|
children: List.generate(4, (index) {
|
|
return Column(
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.only(bottom: 8),
|
|
child: Row(
|
|
children: [
|
|
// Avatar
|
|
Container(
|
|
width: 31,
|
|
height: 31,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
MySpacing.width(16),
|
|
// Name, Designation & Buttons
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
height: 12,
|
|
width: 100,
|
|
color: Colors.grey.shade300),
|
|
MySpacing.height(8),
|
|
Container(
|
|
height: 10,
|
|
width: 80,
|
|
color: Colors.grey.shade300),
|
|
MySpacing.height(12),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
Container(
|
|
height: 28,
|
|
width: 60,
|
|
color: Colors.grey.shade300),
|
|
MySpacing.width(8),
|
|
Container(
|
|
height: 28,
|
|
width: 60,
|
|
color: Colors.grey.shade300),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
if (index != 3)
|
|
Divider(
|
|
color: Colors.grey.withOpacity(0.3),
|
|
thickness: 1,
|
|
height: 1,
|
|
),
|
|
],
|
|
);
|
|
}),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Daily Progress Report Header Loader
|
|
static Widget dailyProgressReportSkeletonLoader() {
|
|
return MyCard.bordered(
|
|
borderRadiusAll: 4,
|
|
border: Border.all(color: Colors.grey.withOpacity(0.2)),
|
|
shadow: MyShadow(elevation: 1, position: MyShadowPosition.bottom),
|
|
paddingAll: 8,
|
|
child: Column(
|
|
children: List.generate(3, (index) {
|
|
return Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Container(
|
|
height: 14, width: 120, color: Colors.grey.shade300),
|
|
Icon(Icons.add_circle, color: Colors.grey.shade300),
|
|
],
|
|
),
|
|
if (index != 2) ...[
|
|
MySpacing.height(12),
|
|
Divider(color: Colors.grey.withOpacity(0.3), thickness: 1),
|
|
MySpacing.height(12),
|
|
],
|
|
],
|
|
);
|
|
}),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Daily Progress Planning (Collapsed View)
|
|
|
|
static Widget dailyProgressPlanningSkeletonCollapsedOnly() {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: List.generate(3, (index) {
|
|
return MyCard.bordered(
|
|
borderRadiusAll: 12,
|
|
paddingAll: 16,
|
|
margin: MySpacing.bottom(12),
|
|
shadow: MyShadow(elevation: 3),
|
|
child: Row(
|
|
children: [
|
|
// Icon placeholder
|
|
Container(
|
|
width: 40,
|
|
height: 40,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
MySpacing.width(12),
|
|
// Text line
|
|
Expanded(
|
|
child: Container(height: 16, color: Colors.grey.shade300),
|
|
),
|
|
MySpacing.width(12),
|
|
// Expand button placeholder
|
|
Container(
|
|
width: 28,
|
|
height: 28,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}),
|
|
);
|
|
}
|
|
|
|
static Widget expenseListSkeletonLoader() {
|
|
return ListView.separated(
|
|
padding: const EdgeInsets.fromLTRB(12, 12, 12, 80),
|
|
itemCount: 6, // Show 6 skeleton items
|
|
separatorBuilder: (_, __) =>
|
|
Divider(color: Colors.grey.shade300, height: 20),
|
|
itemBuilder: (context, index) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Title and Amount
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Container(
|
|
height: 14,
|
|
width: 120,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
),
|
|
Container(
|
|
height: 14,
|
|
width: 80,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 6),
|
|
// Date and Status
|
|
Row(
|
|
children: [
|
|
Container(
|
|
height: 12,
|
|
width: 100,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
),
|
|
const Spacer(),
|
|
Container(
|
|
height: 12,
|
|
width: 50,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
static Widget employeeSkeletonCard() {
|
|
return MyCard.bordered(
|
|
margin: MySpacing.only(bottom: 12),
|
|
paddingAll: 12,
|
|
borderRadiusAll: 12,
|
|
shadow: MyShadow(
|
|
elevation: 1.5,
|
|
position: MyShadowPosition.bottom,
|
|
),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Avatar
|
|
Container(
|
|
height: 35,
|
|
width: 35,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
MySpacing.width(12),
|
|
|
|
// Name, org, email, phone
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(height: 12, width: 120, color: Colors.grey.shade300),
|
|
MySpacing.height(6),
|
|
Container(height: 10, width: 80, color: Colors.grey.shade300),
|
|
MySpacing.height(8),
|
|
|
|
// Email placeholder
|
|
Row(
|
|
children: [
|
|
Icon(Icons.email_outlined,
|
|
size: 14, color: Colors.grey.shade300),
|
|
MySpacing.width(4),
|
|
Container(
|
|
height: 10, width: 140, color: Colors.grey.shade300),
|
|
],
|
|
),
|
|
MySpacing.height(8),
|
|
|
|
// Phone placeholder
|
|
Row(
|
|
children: [
|
|
Icon(Icons.phone_outlined,
|
|
size: 14, color: Colors.grey.shade300),
|
|
MySpacing.width(4),
|
|
Container(
|
|
height: 10, width: 100, color: Colors.grey.shade300),
|
|
MySpacing.width(8),
|
|
Container(
|
|
height: 16,
|
|
width: 16,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
MySpacing.height(8),
|
|
|
|
// Tags placeholder
|
|
Container(height: 8, width: 80, color: Colors.grey.shade300),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Arrow
|
|
Icon(Icons.arrow_forward_ios, size: 14, color: Colors.grey.shade300),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
static Widget contactSkeletonCard() {
|
|
return MyCard.bordered(
|
|
margin: MySpacing.only(bottom: 12),
|
|
paddingAll: 16,
|
|
borderRadiusAll: 16,
|
|
shadow: MyShadow(
|
|
elevation: 1.5,
|
|
position: MyShadowPosition.bottom,
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Container(
|
|
height: 40,
|
|
width: 40,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
MySpacing.width(12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
height: 12,
|
|
width: 100,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
MySpacing.height(6),
|
|
Container(
|
|
height: 10,
|
|
width: 60,
|
|
color: Colors.grey.shade300,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
MySpacing.height(16),
|
|
Container(height: 10, width: 150, color: Colors.grey.shade300),
|
|
MySpacing.height(8),
|
|
Container(height: 10, width: 100, color: Colors.grey.shade300),
|
|
MySpacing.height(8),
|
|
Container(height: 10, width: 120, color: Colors.grey.shade300),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|