import 'dart:async'; import 'package:didvan/config/design_config.dart'; import 'package:didvan/config/theme_data.dart'; import 'package:didvan/constants/app_icons.dart'; import 'package:didvan/models/enums.dart'; import 'package:didvan/models/radar_category.dart'; import 'package:didvan/models/view/action_sheet_data.dart'; import 'package:didvan/pages/home/radar/radar_state.dart'; import 'package:didvan/pages/home/radar/widgets/categories_gird.dart'; import 'package:didvan/pages/home/radar/widgets/categories_list.dart'; import 'package:didvan/pages/home/radar/widgets/radar_item.dart'; import 'package:didvan/pages/home/radar/widgets/search_field.dart'; import 'package:didvan/pages/home/widgets/logo_app_bar.dart'; import 'package:didvan/utils/action_sheet.dart'; import 'package:didvan/widgets/date_picker_button.dart'; import 'package:didvan/widgets/didvan/card.dart'; import 'package:didvan/widgets/didvan/checkbox.dart'; import 'package:didvan/widgets/didvan/divider.dart'; import 'package:didvan/widgets/didvan/text.dart'; import 'package:didvan/widgets/item_title.dart'; import 'package:didvan/widgets/shimmer_placeholder.dart'; import 'package:didvan/widgets/sliver_state_handler.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class Radar extends StatefulWidget { const Radar({Key? key}) : super(key: key); @override State createState() => _RadarState(); } class _RadarState extends State { final ScrollController _scrollController = ScrollController(); bool _isColapsed = false; bool _isAnimating = false; Timer? _timer; @override void initState() { _scrollController.addListener(() async { _handleAnimations(); }); Future.delayed(Duration.zero, () { context.read().getRadarOverviews(page: 1); }); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( body: Consumer( child: SliverPadding( padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16), sliver: SliverToBoxAdapter( child: Row( children: [ Expanded( child: SearchField(title: 'رادار', onChanged: _onChanged), ), const SizedBox(width: 8), GestureDetector( onTap: _showFilterBottomSheet, child: const Icon( DidvanIcons.filter_regular, size: 32, ), ), ], ), ), ), builder: (context, state, child) => Stack( children: [ CustomScrollView( physics: _isAnimating || (state.appState == AppState.busy && state.radars.isEmpty) ? const NeverScrollableScrollPhysics() : const ScrollPhysics(), controller: _scrollController, slivers: [ const SliverToBoxAdapter(child: LogoAppBar()), child!, if (!state.isFiltering) const SliverToBoxAdapter( child: SizedBox(height: 284), ), if (state.radars.isNotEmpty && !state.isFiltering) SliverPadding( padding: const EdgeInsets.only(right: 16, bottom: 20), sliver: SliverToBoxAdapter( child: DidvanText( 'آخرین رصد', style: Theme.of(context).textTheme.subtitle1, color: Theme.of(context).colorScheme.title, ), ), ), SliverStateHandler( state: state, itemPadding: const EdgeInsets.only( bottom: 20, left: 16, right: 16, ), placeholder: const _RadarItemPlaceholder(), builder: (context, state, index) => RadarItem( radar: state.radars[index], ), childCount: state.radars.length, ), ], ), CategoriesRow1(isColapsed: _isColapsed || state.isFiltering), CategoriesRow2(isColapsed: _isColapsed || state.isFiltering), if (!state.isFiltering) CategoriesList(isColapsed: _isColapsed), ], ), ), ); } void _onChanged(String value) { context.read().resetFilters(); if (value.length < 4 && value.isNotEmpty) return; _timer?.cancel(); _timer = Timer(const Duration(seconds: 2), () { context.read().getRadarOverviews( page: 1, search: value, ); }); } void _handleAnimations() async { if (_isAnimating) return; final double position = _scrollController.position.pixels; if (position > 5 && !_isColapsed) { _isColapsed = true; _isAnimating = true; setState(() {}); await _scrollController.animateTo( 380, duration: DesignConfig.mediumAnimationDuration, curve: Curves.ease, ); _isAnimating = false; setState(() {}); } else if (position < 380 && _isColapsed) { _isColapsed = false; _isAnimating = true; setState(() {}); await _scrollController.animateTo( 0, duration: DesignConfig.mediumAnimationDuration, curve: Curves.ease, ); _isAnimating = false; setState(() {}); } } Future _showFilterBottomSheet() async { final state = context.read(); await ActionSheetUtils.showBottomSheet( data: ActionSheetData( title: 'فیلتر جستجو', smallDismissButton: true, titleIcon: DidvanIcons.filter_regular, dismissTitle: 'حذف فیلتر', confrimTitle: 'نمایش نتایج', onDismissed: state.resetFilters, onConfirmed: () => state.getRadarOverviews(page: 1, filter: true), content: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ItemTitle( title: 'تاریخ رادار', style: Theme.of(context).textTheme.bodyText2, icon: DidvanIcons.calendar_range_regular, ), const SizedBox(height: 8), StatefulBuilder( builder: (context, setState) => Row( children: [ DatePickerButton( initialValue: state.startDate, emptyText: 'از تاریخ', onPicked: (date) => setState(() => state.startDate = date), lastDate: state.endDate, ), const SizedBox(width: 8), DatePickerButton( initialValue: state.endDate, emptyText: 'تا تاریخ', onPicked: (date) => setState(() => state.endDate = date), firstDate: state.startDate, ), ], ), ), const SizedBox(height: 28), ItemTitle( title: 'دسته بندی', icon: DidvanIcons.radar_regular, style: Theme.of(context).textTheme.bodyText2, ), const SizedBox(height: 12), Wrap( children: [ for (var i = 0; i < state.categories.length; i++) SizedBox( width: (MediaQuery.of(context).size.width - 40) / 2, child: DidvanCheckbox( title: state.categories[i].title, value: state.selectedCats.contains(state.categories[i]), onChanged: (value) { if (value) { state.selectedCats.add(state.categories[i]); return; } state.selectedCats.remove(state.categories[i]); }, ), ), ], ), ], ), ), ); } } class _RadarItemPlaceholder extends StatelessWidget { const _RadarItemPlaceholder({ Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return DidvanCard( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const ShimmerPlaceholder( width: 200, height: 16, ), const SizedBox(height: 8), const ShimmerPlaceholder(height: 140), const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: const [ ShimmerPlaceholder( height: 12, width: 70, ), ShimmerPlaceholder( height: 12, width: 70, ), ], ), const SizedBox(height: 8), const ShimmerPlaceholder( height: 16, ), const SizedBox(height: 8), const ShimmerPlaceholder( height: 16, ), const SizedBox(height: 8), const ShimmerPlaceholder( height: 16, ), const DidvanDivider(), Row( children: const [ ShimmerPlaceholder( height: 32, width: 32, ), Spacer(), ShimmerPlaceholder( height: 32, width: 32, ), SizedBox(width: 16), ShimmerPlaceholder( height: 32, width: 32, ), ], ), ], ), ); } }