import 'package:ebroker/Ui/screens/home/Widgets/property_horizontal_card.dart'; import 'package:ebroker/Ui/screens/widgets/AnimatedRoutes/blur_page_route.dart'; import 'package:ebroker/Ui/screens/widgets/Erros/something_went_wrong.dart'; import 'package:ebroker/utils/Extensions/extensions.dart'; import 'package:ebroker/utils/helper_utils.dart'; import 'package:ebroker/utils/ui_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../app/routes.dart'; import '../../../data/model/property_model.dart'; ///In this file https://dart.dev/language/generics generic types are used For more info you can see this ///This [PropertySuccessStateWireframe] this will force class to have properties list abstract class PropertySuccessStateWireframe { abstract List properties; abstract bool isLoadingMore; } ///this will force class to have error field abstract class PropertyErrorStateWireframe { dynamic error; } ///This implementation is for cubit this will force property cubit to implement this methods. abstract class PropertyCubitWireframe { void fetch(); bool hasMoreData(); void fetchMore(); } class ViewAllScreen, C> extends StatefulWidget { final String title; final StateMap map; ViewAllScreen({ Key? key, required this.title, required this.map, }) : super(key: key) { assert(T is! PropertyErrorStateWireframe, "Please Extend PropertyErrorStateWireframe in cubit"); } void open(BuildContext context) { Navigator.push(context, BlurredRouter( builder: (context) { return ViewAllScreen(title: title, map: map); }, )); } @override _ViewAllScreenState createState() => _ViewAllScreenState(); } class _ViewAllScreenState, C> extends State { final ScrollController _pageScrollListener = ScrollController(); @override void initState() { _pageScrollListener.addListener(onPageEnd); super.initState(); } @override void dispose() { _pageScrollListener.dispose(); super.dispose(); } bool isSubtype() => [] is List; void onPageEnd() { ///This is extension which will check if we reached end or not if (_pageScrollListener.isEndReached()) { if (isSubtype()) { if (read().hasMoreData()) { read().fetchMore(); } } } } dynamic read() { return context.read(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: context.color.primaryColor, // appBar: AppBar( // backgroundColor: context.color.secondaryColor, // elevation: 0, // iconTheme: IconThemeData(color: context.color.teritoryColor), // title: Text( // widget.title, // ).color(context.color.teritoryColor).size(context.font.large), // ), appBar: UiUtils.buildAppBar(context, title: widget.title, showBackButton: true), // body: Container(), body: BlocBuilder(builder: (context, state) { return widget.map._buildState(state, _pageScrollListener); }), ); } } ///From generic type we are getting state so we can return ui according to that state class StateMap { Widget _buildState(dynamic state, ScrollController controller) { if (state is INITIAL) { return Container(); } if (state is PROGRESS) { return Center(child: UiUtils.progress()); } if (state is FAIL) { return const SomethingWentWrong(); } if (state is SUCCESS) { return Column( children: [ Expanded( child: ScrollConfiguration( behavior: RemoveGlow(), child: ListView.builder( controller: controller, padding: const EdgeInsets.all(20), itemBuilder: (context, index) { PropertyModel model = state.properties[index]; return GestureDetector( onTap: () { HelperUtils.goToNextPage( Routes.propertyDetails, context, false, args: { 'propertyData': model, 'propertiesList': state.properties, 'fromMyProperty': false, }, ); }, child: PropertyHorizontalCard(property: model)); }, itemCount: state.properties.length, ), ), ), if (state.isLoadingMore) UiUtils.progress() ], ); } return Container(); } }