Files
apskel-owner-flutter/lib/presentation/pages/inventory/inventory_page.dart
T

213 lines
6.6 KiB
Dart
Raw Normal View History

2025-08-15 18:02:09 +07:00
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
2025-08-17 23:54:28 +07:00
import 'package:flutter_bloc/flutter_bloc.dart';
2025-08-15 18:02:09 +07:00
2025-08-17 23:54:28 +07:00
import '../../../application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart';
2025-08-15 18:02:09 +07:00
import '../../../common/theme/theme.dart';
2025-08-17 23:54:28 +07:00
import '../../../injection.dart';
2026-06-24 10:28:13 +07:00
import '../../components/spacer/spacer.dart';
import 'widgets/inventory_header.dart';
import 'widgets/inventory_stock_report.dart';
2025-08-15 18:02:09 +07:00
@RoutePage()
2025-08-17 23:54:28 +07:00
class InventoryPage extends StatefulWidget implements AutoRouteWrapper {
2025-08-15 18:02:09 +07:00
const InventoryPage({super.key});
@override
State<InventoryPage> createState() => _InventoryPageState();
2025-08-17 23:54:28 +07:00
@override
Widget wrappedRoute(BuildContext context) => BlocProvider(
create: (_) =>
getIt<InventoryAnalyticLoaderBloc>()
..add(InventoryAnalyticLoaderEvent.fetched()),
child: this,
);
2025-08-15 18:02:09 +07:00
}
class _InventoryPageState extends State<InventoryPage>
2026-06-24 10:28:13 +07:00
with SingleTickerProviderStateMixin {
late AnimationController _fadeController;
2025-08-15 18:02:09 +07:00
late Animation<double> _fadeAnimation;
2026-06-24 10:28:13 +07:00
int _selectedTabIndex = 0;
2025-08-15 18:02:09 +07:00
@override
void initState() {
super.initState();
2026-06-24 10:28:13 +07:00
_fadeController = AnimationController(
2025-08-15 18:02:09 +07:00
duration: const Duration(milliseconds: 1000),
vsync: this,
);
2026-06-24 10:28:13 +07:00
_fadeAnimation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(parent: _fadeController, curve: Curves.easeIn));
2025-08-15 18:02:09 +07:00
2026-06-24 10:28:13 +07:00
_fadeController.forward();
2025-08-15 18:02:09 +07:00
}
@override
void dispose() {
2026-06-24 10:28:13 +07:00
_fadeController.dispose();
2025-08-15 18:02:09 +07:00
super.dispose();
}
@override
Widget build(BuildContext context) {
2026-06-24 10:28:13 +07:00
return Scaffold(
backgroundColor: AppColor.background,
body:
BlocListener<
InventoryAnalyticLoaderBloc,
InventoryAnalyticLoaderState
>(
listenWhen: (previous, current) =>
previous.dateFrom != current.dateFrom ||
previous.dateTo != current.dateTo,
listener: (context, state) {
context.read<InventoryAnalyticLoaderBloc>().add(
InventoryAnalyticLoaderEvent.fetched(),
);
},
child:
BlocBuilder<
InventoryAnalyticLoaderBloc,
InventoryAnalyticLoaderState
>(
builder: (context, state) {
return CustomScrollView(
slivers: [
// Header with gradient background, tabs, and summary
SliverToBoxAdapter(
child: FadeTransition(
opacity: _fadeAnimation,
child: InventoryHeader(
state: state,
selectedTabIndex: _selectedTabIndex,
onTabChanged: (index) {
setState(() {
_selectedTabIndex = index;
});
},
2025-08-18 17:27:36 +07:00
onDateRangeChanged: (startDate, endDate) {
2026-06-24 10:28:13 +07:00
_onDateRangeChanged(
context,
startDate,
endDate,
2025-08-18 17:27:36 +07:00
);
},
2025-08-17 23:54:28 +07:00
),
),
2026-06-24 10:28:13 +07:00
),
// Stock Report Table
SliverToBoxAdapter(
child: FadeTransition(
opacity: _fadeAnimation,
child: state.isFetching
? _buildLoadingReport()
: InventoryStockReport(
inventoryAnalytic: state.inventoryAnalytic,
selectedTabIndex: _selectedTabIndex,
),
),
),
// Bottom spacing
const SliverToBoxAdapter(child: SpaceHeight(100)),
],
);
},
),
),
);
}
Widget _buildLoadingReport() {
return Container(
margin: const EdgeInsets.all(16),
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: AppColor.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: AppColor.textLight.withOpacity(0.08),
spreadRadius: 1,
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Column(
children: List.generate(
5,
(index) => Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
children: [
Expanded(
flex: 4,
child: Container(
height: 14,
decoration: BoxDecoration(
color: AppColor.borderLight,
borderRadius: BorderRadius.circular(4),
2025-08-15 18:02:09 +07:00
),
),
2026-06-24 10:28:13 +07:00
),
const SpaceWidth(12),
Expanded(
flex: 2,
child: Container(
height: 14,
decoration: BoxDecoration(
color: AppColor.borderLight,
borderRadius: BorderRadius.circular(4),
),
),
),
const SpaceWidth(12),
Expanded(
flex: 2,
child: Container(
height: 14,
decoration: BoxDecoration(
color: AppColor.borderLight,
borderRadius: BorderRadius.circular(4),
),
),
),
const SpaceWidth(12),
Expanded(
flex: 2,
child: Container(
height: 14,
decoration: BoxDecoration(
color: AppColor.borderLight,
borderRadius: BorderRadius.circular(4),
),
),
),
],
2025-08-18 17:27:36 +07:00
),
2026-06-24 10:28:13 +07:00
),
),
2025-08-18 17:27:36 +07:00
),
2025-08-15 18:02:09 +07:00
);
}
2026-06-24 10:28:13 +07:00
void _onDateRangeChanged(
BuildContext context,
DateTime startDate,
DateTime endDate,
2025-08-15 18:02:09 +07:00
) {
2026-06-24 10:28:13 +07:00
context.read<InventoryAnalyticLoaderBloc>().add(
InventoryAnalyticLoaderEvent.rangeDateChanged(startDate, endDate),
2025-08-15 18:02:09 +07:00
);
}
}