Files
apskel-owner-flutter/lib/presentation/pages/finance/finance_page.dart
T

146 lines
4.3 KiB
Dart
Raw Normal View History

2025-08-15 23:53:05 +07:00
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
2025-08-17 22:36:46 +07:00
import 'package:flutter_bloc/flutter_bloc.dart';
2025-08-15 23:53:05 +07:00
2025-08-17 22:49:28 +07:00
import '../../../application/analytic/profit_loss_loader/profit_loss_loader_bloc.dart';
2025-08-15 23:53:05 +07:00
import '../../../common/theme/theme.dart';
2025-08-17 22:36:46 +07:00
import '../../../injection.dart';
2026-06-24 10:14:37 +07:00
import 'widgets/cost_breakdown.dart';
import 'widgets/profit_loss_header.dart';
import 'widgets/profit_loss_report.dart';
2025-08-15 23:53:05 +07:00
@RoutePage()
2025-08-17 22:36:46 +07:00
class FinancePage extends StatefulWidget implements AutoRouteWrapper {
2025-08-15 23:53:05 +07:00
const FinancePage({super.key});
@override
State<FinancePage> createState() => _FinancePageState();
2025-08-17 22:36:46 +07:00
@override
2026-06-24 10:14:37 +07:00
Widget wrappedRoute(BuildContext context) => BlocProvider(
create: (_) =>
getIt<ProfitLossLoaderBloc>()..add(ProfitLossLoaderEvent.fetched()),
2025-08-17 22:36:46 +07:00
child: this,
);
2025-08-15 23:53:05 +07:00
}
class _FinancePageState extends State<FinancePage>
2026-06-24 10:14:37 +07:00
with SingleTickerProviderStateMixin {
2025-08-15 23:53:05 +07:00
late AnimationController _fadeController;
late Animation<double> _fadeAnimation;
2026-06-24 10:14:37 +07:00
int _selectedTabIndex = 0;
2025-08-15 23:53:05 +07:00
@override
void initState() {
super.initState();
_fadeController = AnimationController(
duration: const Duration(milliseconds: 1000),
vsync: this,
);
_fadeAnimation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(parent: _fadeController, curve: Curves.easeIn));
_fadeController.forward();
}
@override
void dispose() {
_fadeController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.background,
2025-08-18 16:48:35 +07:00
body: BlocListener<ProfitLossLoaderBloc, ProfitLossLoaderState>(
listenWhen: (previous, current) =>
2025-08-18 17:07:15 +07:00
previous.dateFrom != current.dateFrom ||
2025-08-18 16:48:35 +07:00
previous.dateTo != current.dateTo,
listener: (context, state) {
context.read<ProfitLossLoaderBloc>().add(
ProfitLossLoaderEvent.fetched(),
2025-08-17 22:36:46 +07:00
);
},
2025-08-18 16:48:35 +07:00
child: BlocBuilder<ProfitLossLoaderBloc, ProfitLossLoaderState>(
builder: (context, state) {
return CustomScrollView(
slivers: [
2026-06-24 10:14:37 +07:00
// Header with gradient background, tabs, and summary
2025-08-18 16:48:35 +07:00
SliverToBoxAdapter(
child: FadeTransition(
opacity: _fadeAnimation,
2026-06-24 10:14:37 +07:00
child: ProfitLossHeader(
state: state,
selectedTabIndex: _selectedTabIndex,
onTabChanged: (index) {
setState(() {
_selectedTabIndex = index;
});
_onTabChanged(context, index);
},
2025-08-18 16:48:35 +07:00
),
2025-08-15 23:53:05 +07:00
),
2025-08-18 16:48:35 +07:00
),
2026-06-24 10:14:37 +07:00
// Profit Loss Report Table
2025-08-18 16:48:35 +07:00
SliverToBoxAdapter(
child: FadeTransition(
opacity: _fadeAnimation,
2026-06-24 10:14:37 +07:00
child: ProfitLossReport(
mainSummary: state.profitLoss.mainSummary,
summary: state.profitLoss.summary,
selectedTabIndex: _selectedTabIndex,
),
2025-08-18 16:48:35 +07:00
),
),
2026-06-24 10:14:37 +07:00
// Cost Breakdown
2025-08-18 16:48:35 +07:00
SliverToBoxAdapter(
2026-06-24 10:14:37 +07:00
child: FadeTransition(
opacity: _fadeAnimation,
child: CostBreakdown(
purchasing: state.profitLoss.purchasing,
selectedTabIndex: _selectedTabIndex,
dateFrom: state.dateFrom,
dateTo: state.dateTo,
),
2025-08-18 16:48:35 +07:00
),
),
// Bottom spacing
const SliverToBoxAdapter(child: SizedBox(height: 100)),
],
);
},
),
2025-08-15 23:53:05 +07:00
),
);
}
2026-06-24 10:14:37 +07:00
void _onTabChanged(BuildContext context, int index) {
final now = DateTime.now();
DateTime dateFrom;
DateTime dateTo;
2025-08-15 23:53:05 +07:00
2026-06-24 10:14:37 +07:00
if (index == 0) {
// Today
dateFrom = DateTime(now.year, now.month, now.day);
dateTo = DateTime(now.year, now.month, now.day, 23, 59, 59);
} else {
// MTD (Month-to-Date)
dateFrom = DateTime(now.year, now.month, 1);
dateTo = now;
}
context.read<ProfitLossLoaderBloc>().add(
ProfitLossLoaderEvent.rangeDateChanged(dateFrom, dateTo),
2025-08-15 23:53:05 +07:00
);
}
}