204 lines
6.8 KiB
Dart
204 lines
6.8 KiB
Dart
import 'package:auto_route/auto_route.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:shimmer/shimmer.dart';
|
|
|
|
import '../../../application/analytic/profit_sharing_loader/profit_sharing_loader_bloc.dart';
|
|
import '../../../common/theme/theme.dart';
|
|
import '../../../injection.dart';
|
|
import '../../components/field/date_range_picker_field.dart';
|
|
import '../../components/spacer/spacer.dart';
|
|
import '../../router/app_router.gr.dart';
|
|
import 'widgets/profit_sharing_allocation.dart';
|
|
import 'widgets/profit_sharing_categories.dart';
|
|
import 'widgets/profit_sharing_header.dart';
|
|
import 'widgets/profit_sharing_periods.dart';
|
|
|
|
@RoutePage()
|
|
class ProfitSharingPage extends StatefulWidget implements AutoRouteWrapper {
|
|
const ProfitSharingPage({super.key});
|
|
|
|
@override
|
|
State<ProfitSharingPage> createState() => _ProfitSharingPageState();
|
|
|
|
@override
|
|
Widget wrappedRoute(BuildContext context) => BlocProvider(
|
|
create: (_) =>
|
|
getIt<ProfitSharingLoaderBloc>()
|
|
..add(ProfitSharingLoaderEvent.fetched()),
|
|
child: this,
|
|
);
|
|
}
|
|
|
|
class _ProfitSharingPageState extends State<ProfitSharingPage>
|
|
with SingleTickerProviderStateMixin {
|
|
late AnimationController _fadeController;
|
|
late Animation<double> _fadeAnimation;
|
|
|
|
@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,
|
|
body: BlocListener<ProfitSharingLoaderBloc, ProfitSharingLoaderState>(
|
|
listenWhen: (previous, current) =>
|
|
previous.dateFrom != current.dateFrom ||
|
|
previous.dateTo != current.dateTo,
|
|
listener: (context, state) {
|
|
context.read<ProfitSharingLoaderBloc>().add(
|
|
const ProfitSharingLoaderEvent.fetched(),
|
|
);
|
|
},
|
|
child: BlocBuilder<ProfitSharingLoaderBloc, ProfitSharingLoaderState>(
|
|
builder: (context, state) {
|
|
return RefreshIndicator(
|
|
backgroundColor: AppColor.white,
|
|
color: AppColor.primary,
|
|
onRefresh: () async {
|
|
context.read<ProfitSharingLoaderBloc>().add(
|
|
const ProfitSharingLoaderEvent.fetched(),
|
|
);
|
|
await context.read<ProfitSharingLoaderBloc>().stream.firstWhere(
|
|
(s) => !s.isFetching,
|
|
);
|
|
},
|
|
child: CustomScrollView(
|
|
physics: const AlwaysScrollableScrollPhysics(),
|
|
slivers: [
|
|
SliverToBoxAdapter(
|
|
child: FadeTransition(
|
|
opacity: _fadeAnimation,
|
|
child: ProfitSharingHeader(state: state),
|
|
),
|
|
),
|
|
|
|
SliverToBoxAdapter(
|
|
child: FadeTransition(
|
|
opacity: _fadeAnimation,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: DateRangePickerField(
|
|
startDate: state.dateFrom,
|
|
endDate: state.dateTo,
|
|
onChanged: (startDate, endDate) {
|
|
if (startDate == null || endDate == null) return;
|
|
context.read<ProfitSharingLoaderBloc>().add(
|
|
ProfitSharingLoaderEvent.rangeDateChanged(
|
|
startDate,
|
|
endDate,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
if (state.isFetching)
|
|
SliverToBoxAdapter(child: _buildShimmer())
|
|
else ...[
|
|
SliverToBoxAdapter(
|
|
child: FadeTransition(
|
|
opacity: _fadeAnimation,
|
|
child: ProfitSharingCategories(
|
|
categories: state.profitSharing.categories,
|
|
onCategoryTap: (category) => context.router.push(
|
|
ProfitSharingDetailRoute(
|
|
parentCategoryId: category.parentCategoryId,
|
|
parentCategoryName: category.parentCategoryName,
|
|
dateFrom: state.dateFrom,
|
|
dateTo: state.dateTo,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
|
|
|
SliverToBoxAdapter(
|
|
child: FadeTransition(
|
|
opacity: _fadeAnimation,
|
|
child: ProfitSharingAllocation(
|
|
budget: state.profitSharing.budget,
|
|
),
|
|
),
|
|
),
|
|
|
|
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
|
|
|
SliverToBoxAdapter(
|
|
child: FadeTransition(
|
|
opacity: _fadeAnimation,
|
|
child: ProfitSharingPeriods(
|
|
state: state,
|
|
onPeriodTypeChanged: (type) {
|
|
context.read<ProfitSharingLoaderBloc>().add(
|
|
ProfitSharingLoaderEvent.periodTypeChanged(type),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
],
|
|
|
|
const SliverToBoxAdapter(child: SizedBox(height: 100)),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildShimmer() {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Column(
|
|
children: [
|
|
_shimmerBox(height: 240),
|
|
const SpaceHeight(16),
|
|
_shimmerBox(height: 300),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _shimmerBox({required double height}) {
|
|
return Shimmer.fromColors(
|
|
baseColor: Colors.grey[300]!,
|
|
highlightColor: Colors.grey[100]!,
|
|
child: Container(
|
|
height: height,
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(16),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|