Update project

This commit is contained in:
2026-07-23 15:36:11 +05:30
parent 1197cfc161
commit 14fffa40c6
84 changed files with 20918 additions and 2761 deletions

View File

@@ -81,6 +81,210 @@ class TenantApiService {
}
}
// ─────────────────────────────────────────────
// SHIMMER WIDGET
// ─────────────────────────────────────────────
class _ShimmerBox extends StatefulWidget {
final double width;
final double height;
final double borderRadius;
const _ShimmerBox({
required this.width,
required this.height,
this.borderRadius = 8,
});
@override
State<_ShimmerBox> createState() => _ShimmerBoxState();
}
class _ShimmerBoxState extends State<_ShimmerBox>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1200),
)..repeat();
_animation = Tween<double>(begin: -1.5, end: 1.5).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOutSine),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (_, __) => Container(
width: widget.width,
height: widget.height,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(widget.borderRadius),
gradient: LinearGradient(
begin: Alignment(_animation.value - 1, 0),
end: Alignment(_animation.value, 0),
colors: const [
Color(0xFFE8E8E8),
Color(0xFFF5F5F5),
Color(0xFFE8E8E8),
],
),
),
),
);
}
}
// Shimmer skeleton that mimics the actual screen layout
class _StoreOverviewShimmer extends StatelessWidget {
const _StoreOverviewShimmer();
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Top bar
Row(
children: [
_ShimmerBox(width: 40, height: 40, borderRadius: 20),
],
),
const SizedBox(height: 16),
// Store card shimmer
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.04),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_ShimmerBox(width: 200, height: 22, borderRadius: 6),
const SizedBox(height: 10),
_ShimmerBox(width: double.infinity, height: 13, borderRadius: 4),
const SizedBox(height: 6),
_ShimmerBox(width: 160, height: 13, borderRadius: 4),
const SizedBox(height: 14),
Row(
children: [
_ShimmerBox(width: 40, height: 40, borderRadius: 20),
const SizedBox(width: 12),
_ShimmerBox(width: 40, height: 40, borderRadius: 20),
],
),
const Divider(height: 24, thickness: 0.5),
Row(
children: [
_ShimmerBox(width: 20, height: 20, borderRadius: 4),
const SizedBox(width: 12),
_ShimmerBox(width: 100, height: 13, borderRadius: 4),
],
),
const Divider(height: 24, thickness: 0.5),
Row(
children: [
_ShimmerBox(width: 20, height: 20, borderRadius: 4),
const SizedBox(width: 12),
_ShimmerBox(width: 150, height: 13, borderRadius: 4),
],
),
],
),
),
const SizedBox(height: 12),
// Bad experience card shimmer
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.04),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
child: Row(
children: [
_ShimmerBox(width: 36, height: 36, borderRadius: 18),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_ShimmerBox(width: 180, height: 13, borderRadius: 4),
const SizedBox(height: 6),
_ShimmerBox(width: 140, height: 11, borderRadius: 4),
],
),
],
),
),
const SizedBox(height: 12),
// Legal card shimmer
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.04),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: List.generate(4, (i) => Padding(
padding: EdgeInsets.only(bottom: i < 3 ? 16.0 : 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_ShimmerBox(width: 80, height: 11, borderRadius: 4),
const SizedBox(height: 5),
_ShimmerBox(width: 160, height: 13, borderRadius: 4),
],
),
)),
),
),
],
),
);
}
}
// ─────────────────────────────────────────────
// SCREEN
// ─────────────────────────────────────────────
@@ -285,9 +489,16 @@ class _StoreOverviewScreenState extends State<StoreOverviewScreen> {
child: FutureBuilder<TenantDetails>(
future: _future,
builder: (context, snap) {
// ── SHIMMER while loading ──────────────
if (snap.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
return Column(
children: [
Expanded(child: const _StoreOverviewShimmer()),
_bottomButton(),
],
);
}
if (snap.hasError) {
return Center(
child: Column(