From 59c96d072026c137e5179c9f663cfb79b958a90f Mon Sep 17 00:00:00 2001 From: Abhibhaw <39991296+abhibhaw@users.noreply.github.com> Date: Fri, 26 Jan 2024 22:15:37 +0530 Subject: [PATCH] feat: Adds search capability --- .../lib/cubit/query/query_cubit.dart | 9 + .../lib/cubit/search/search_cubit.dart | 16 ++ .../lib/cubit/search/search_state.dart | 8 + milkton_executive/lib/main.dart | 4 + .../lib/presentation/screens/home.dart | 244 +++++++++++------- 5 files changed, 191 insertions(+), 90 deletions(-) create mode 100644 milkton_executive/lib/cubit/query/query_cubit.dart create mode 100644 milkton_executive/lib/cubit/search/search_cubit.dart create mode 100644 milkton_executive/lib/cubit/search/search_state.dart diff --git a/milkton_executive/lib/cubit/query/query_cubit.dart b/milkton_executive/lib/cubit/query/query_cubit.dart new file mode 100644 index 0000000..863898f --- /dev/null +++ b/milkton_executive/lib/cubit/query/query_cubit.dart @@ -0,0 +1,9 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; + +class QueryCubit extends Cubit { + QueryCubit() : super(""); + + void setQuery(String query) { + emit(query); + } +} diff --git a/milkton_executive/lib/cubit/search/search_cubit.dart b/milkton_executive/lib/cubit/search/search_cubit.dart new file mode 100644 index 0000000..e8e1a93 --- /dev/null +++ b/milkton_executive/lib/cubit/search/search_cubit.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'search_state.dart'; + +class SearchCubit extends Cubit { + SearchCubit() : super(SearchInitial()); + + void activateSearch() { + emit(SearchActive()); + } + + void closeSearch() { + emit(SearchInitial()); + } +} diff --git a/milkton_executive/lib/cubit/search/search_state.dart b/milkton_executive/lib/cubit/search/search_state.dart new file mode 100644 index 0000000..f414008 --- /dev/null +++ b/milkton_executive/lib/cubit/search/search_state.dart @@ -0,0 +1,8 @@ +part of 'search_cubit.dart'; + +@immutable +sealed class SearchState {} + +final class SearchInitial extends SearchState {} + +final class SearchActive extends SearchState {} diff --git a/milkton_executive/lib/main.dart b/milkton_executive/lib/main.dart index e734854..82e3cf4 100644 --- a/milkton_executive/lib/main.dart +++ b/milkton_executive/lib/main.dart @@ -7,6 +7,8 @@ import 'package:milkton_executive/configs/graphql_client.dart'; import 'package:milkton_executive/configs/remote_config.dart'; import 'package:milkton_executive/cubit/all_orders/all_orders_cubit.dart'; import 'package:milkton_executive/cubit/auth/auth_cubit.dart'; +import 'package:milkton_executive/cubit/query/query_cubit.dart'; +import 'package:milkton_executive/cubit/search/search_cubit.dart'; import 'package:milkton_executive/cubit/status/status_cubit.dart'; import 'package:milkton_executive/cubit/user/user_cubit.dart'; import 'package:milkton_executive/firebase_options.dart'; @@ -34,6 +36,8 @@ class MilktonExecutive extends StatelessWidget { BlocProvider(create: (context) => StatusCubit()), BlocProvider(create: (context) => UserCubit()), BlocProvider(create: (context) => AllOrdersCubit()), + BlocProvider(create: (context) => SearchCubit()), + BlocProvider(create: (context) => QueryCubit()), ], child: MaterialApp( title: 'Milkton Executive', diff --git a/milkton_executive/lib/presentation/screens/home.dart b/milkton_executive/lib/presentation/screens/home.dart index 65daa6c..1c5f9a1 100644 --- a/milkton_executive/lib/presentation/screens/home.dart +++ b/milkton_executive/lib/presentation/screens/home.dart @@ -3,6 +3,8 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/svg.dart'; import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:milkton_executive/cubit/all_orders/all_orders_cubit.dart'; +import 'package:milkton_executive/cubit/query/query_cubit.dart'; +import 'package:milkton_executive/cubit/search/search_cubit.dart'; import 'package:milkton_executive/cubit/status/status_cubit.dart'; import 'package:milkton_executive/cubit/user/user_cubit.dart'; import 'package:milkton_executive/graphql/query.dart'; @@ -39,10 +41,42 @@ class HomeScreen extends StatelessWidget { appBar: AppBar( foregroundColor: Colors.white, backgroundColor: Colors.deepPurple, - title: const Text("Milkton Executive"), - actions: const [ - Icon(Icons.search), - SizedBox(width: 12), + title: BlocBuilder( + builder: (context, state) { + if (state is SearchActive) { + return TextField( + autofocus: true, + decoration: const InputDecoration( + hintText: "Search", + hintStyle: TextStyle(color: Colors.white), + border: InputBorder.none, + ), + cursorColor: Colors.white, + style: const TextStyle(color: Colors.white), + onChanged: (value) { + context.read().setQuery(value); + }); + } + return const Text("Milkton Executive"); + }, + ), + actions: [ + BlocBuilder( + builder: (context, state) { + return IconButton( + onPressed: () { + if (state is SearchActive) { + context.read().setQuery(""); + context.read().closeSearch(); + } else { + context.read().activateSearch(); + } + }, + icon: Icon( + state is SearchActive ? Icons.close : Icons.search)); + }, + ), + const SizedBox(width: 12), ], ), drawer: const TopNavDrawer(), @@ -92,95 +126,125 @@ class HomeScreen extends StatelessWidget { } context.read().getOrders(orders); - return Padding( - padding: const EdgeInsets.all(12.0), - child: SingleChildScrollView( - child: BlocBuilder( - builder: (context, state) { - var filteredOrders = orders - .where((order) => - context.read().state.title == "ALL" - ? true - : context.read().state.title == - order['status']) - .toList(); - return Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: buttonStates - .map( - (buttonState) => Row( - children: [ - SecondaryButton( - isActive: buttonState["title"] == - context - .read() - .state - .title, - title: buttonState["title"], - count: buttonState["title"] == "ALL" - ? orders.length - : orders - .where((order) => - order['status'] == - buttonState["title"]) - .length, - onPressed: () { - context.read().setStatus( - buttonState["state"] - as StatusState); - }, - ), - const SizedBox(width: 12), - ], - ), - ) - .toList(), - ), - ), - filteredOrders.isEmpty - ? Padding( - padding: const EdgeInsets.all(36.0), - child: Column( - children: [ - SvgPicture.asset('assets/images/cart.svg'), - const Text("No orders here", - style: TextStyle(fontSize: 18)), - ], - )) - : Column( - children: [ - ...orders - .where((order) => context + return BlocBuilder( + builder: (context, queryState) { + return Padding( + padding: const EdgeInsets.all(12.0), + child: SingleChildScrollView( + child: BlocBuilder( + builder: (context, state) { + var filteredOrders = orders + .where((order) { + if (queryState.isEmpty) { + return true; + } else { + return order['customer']['firstName'] + .toString() + .toLowerCase() + .contains(queryState.toLowerCase()) || + order['customer']['lastName'] + .toString() + .toLowerCase() + .contains(queryState.toLowerCase()) || + order['customer']['phone'] + .toString() + .toLowerCase() + .contains(queryState.toLowerCase()) || + order['customer']['address'] + .toString() + .toLowerCase() + .contains(queryState.toLowerCase()); + } + }) + .where((order) => + context.read().state.title == "ALL" + ? true + : context.read().state.title == + order['status']) + .toList(); + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: buttonStates + .map( + (buttonState) => Row( + children: [ + SecondaryButton( + isActive: buttonState["title"] == + context + .read() + .state + .title, + title: buttonState["title"], + count: buttonState["title"] == "ALL" + ? filteredOrders.length + : filteredOrders + .where((order) => + order['status'] == + buttonState["title"]) + .length, + onPressed: () { + context .read() - .state - .title == - "ALL" - ? true - : context - .read() - .state - .title == - order['status']) - .map( - (order) => Column( - children: [ - const SizedBox(height: 12), - OrderCard( - order: Order.fromJson(order)), - ], - ), + .setStatus( + buttonState["state"] + as StatusState); + }, + ), + const SizedBox(width: 12), + ], ), - ], + ) + .toList(), ), - ], - ); - }, - ), - ), + ), + filteredOrders.isEmpty + ? Padding( + padding: const EdgeInsets.all(36.0), + child: Column( + children: [ + SvgPicture.asset( + 'assets/images/cart.svg'), + const Text("No orders here", + style: TextStyle(fontSize: 18)), + ], + )) + : Column( + children: [ + ...filteredOrders + .where((order) => context + .read() + .state + .title == + "ALL" + ? true + : context + .read() + .state + .title == + order['status']) + .map( + (order) => Column( + children: [ + const SizedBox(height: 12), + OrderCard( + order: + Order.fromJson(order)), + ], + ), + ), + ], + ), + ], + ); + }, + ), + ), + ); + }, ); }, ));