- {resources.map(({ name, icon }) =>
+ {[{ name: "All", icon: faGlobeAsia }, ...resources].map(({ name, icon }) =>
handleTabChange(name)}
className={"cursor-pointer dark:text-gray-500 px-2 pt-1 border-primary-600 pb-1 text-center" + (name === resource ? " border-b-2 dark:text-primary-500 text-indigo-800" : "")}
@@ -91,7 +91,7 @@ const SearchField = ({ isFocus, onFocus, resource, setResource }) => {
value={searchText}
type="text"
className="p-4 pl-6 text-base md:text-xl transition-shadow duration-300 ease-in-out shadow-md hover:shadow-lg focus:shadow-xl placeholder-gray-600 dark:text-white rounded-xl z-10 outline-none w-full absolute top-0 left-0 bg-transparent"
- placeholder={`Search for ${resource} in States or Districts`}
+ placeholder={`Search for ${resource} resources in States or Districts`}
/>
{
!searchText &&
diff --git a/components/search/StateSearchField.jsx b/components/search/StateSearchField.jsx
new file mode 100644
index 000000000..6a2b3304d
--- /dev/null
+++ b/components/search/StateSearchField.jsx
@@ -0,0 +1,141 @@
+import React, { useState, createRef } from "react";
+import { isTrendingPlace, getSuggestedListByState, getSuggestedWordByState } from "@lib/search";
+import TrendingIcon from "@components/icons/TrendingIcon";
+import { useRouter } from "next/router";
+import { parametreize } from "@lib/utils";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faCog, faGlobeAsia, faTimes } from "@fortawesome/free-solid-svg-icons";
+import { resources } from "./SearchIntro";
+
+const StateSearchField = ({ resource, setResource, state }) => {
+ const [searchText, setSearchText] = useState("");
+ const [isLoading, setIsLoading] = useState(false);
+ const [isFocus, onFocus] = useState(false);
+ const suggestionText = getSuggestedWordByState(searchText, state);
+ const suggestedResults = getSuggestedListByState(searchText, state, resource);
+ const searchFieldRef = createRef();
+ const pageRouter = useRouter();
+
+ const handleSearchKeyDown = e => {
+ if (e.key === "Tab") {
+ e.preventDefault();
+ if (suggestionText.name) {
+ setSearchText(suggestionText.name);
+ }
+ } else if (e.key === "Escape") {
+ e.preventDefault();
+ searchFieldRef.current?.blur();
+ } else if (e.key === "Enter" && suggestionText?.name) {
+ handleGotoResource(suggestionText)
+ }
+ };
+
+ const handleGotoResource = (result) => {
+ setIsLoading(true);
+ setSearchText(result.name);
+ const { name, type, state } = result;
+ if (type === "District") {
+ pageRouter.push(
+ `/${parametreize(state)}/${parametreize(name)}/${parametreize(resource)}`
+ )
+ }
+ else if (type === "State") {
+ pageRouter.push(`/${parametreize(name)}/?resource=${resource}`)
+ }
+
+ }
+
+ const handleTabChange = (name) => {
+ setResource(name)
+ setTimeout(() => {
+ document.getElementById("searchField")?.focus();
+ }, 500)
+ }
+
+ return (
+
+
+ {[{ name: "All", icon: faGlobeAsia }, ...resources].map(({ name, icon }) =>
+
handleTabChange(name)}
+ className={"flex items-center cursor-pointer dark:text-gray-500 px-2 pt-1 border-primary-600 pb-1 text-center" + (name === resource ? " border-b-2 dark:text-primary-500 text-indigo-800" : "")}
+ key={name}>
+
+ {name}
+
+ )}
+
+
+
+ onFocus(true)}
+ onChange={({ target: { value } }) => setSearchText(value)}
+ onBlur={_ => {
+ setTimeout(() => {
+ onFocus(false);
+ }, 200)
+ }}
+ value={searchText}
+ type="text"
+ className="p-4 pl-6 text-base md:text-xl transition-shadow duration-300 ease-in-out shadow-md hover:shadow-lg focus:shadow-xl placeholder-gray-600 dark:text-white rounded-xl z-10 outline-none w-full absolute top-0 left-0 bg-transparent"
+ placeholder={`Search for districts with ${resource} resources`}
+ />
+ {/* I am using Custom Close Icon instead of input[type='search'] to use dark style */}
+ {
+ (searchText && !isLoading) &&
+ setSearchText("")}>
+
+
+ }
+ {/* Loading Icon when the user makes use of suggestions */}
+ {
+ isLoading &&
+ setSearchText("")}>
+
+
+ }
+
+ {isFocus && (
+
+
+ {!suggestedResults.length
+ ? "We couldn't find suggestions for you.. 💤"
+ : "Suggestions âš¡"}
+
+
+
+ )}
+
+ );
+};
+export default StateSearchField;
diff --git a/lib/search.js b/lib/search.js
index 4a730b9b8..8ba441af3 100644
--- a/lib/search.js
+++ b/lib/search.js
@@ -1,4 +1,5 @@
import states from '@data/states.json';
+import resourceStats from "@data/resource_stats_v2.json"
import topTenStatesAndDistricts from "@data/top_states_and_districts"
export const getAllStateNames = () => {
@@ -25,7 +26,7 @@ export const getAllDistrictNames = () => {
};
export const getSuggestedWord = searchText => {
- if (!searchText) return "";
+ if (!searchText) return { displayText: "" };
const states = getAllStateNames();
const districts = getAllDistrictNames();
const stateSuggestion = states.find(e => isExactMatch(e, searchText));
@@ -74,3 +75,44 @@ export const getSuggestedList = searchText => {
export const isTrendingPlace = name => {
return topTenStatesAndDistricts.find(e => e.name === name);
};
+
+export const getStatsByState = (state) => {
+ const data = resourceStats.states?.find(e => e.name === state && e.type === "State");
+ return data || {}
+}
+
+export const getSuggestedWordByState = (searchText, state) => {
+ if (!searchText) return { displayText: "" };
+ const allDistricts = resourceStats.districts.filter(e => e.state === state);
+ const districtSuggestion = allDistricts.find(e => isExactMatch(e, searchText));
+ if (districtSuggestion) {
+ const word = {
+ ...districtSuggestion,
+ displayText:
+ searchText +
+ districtSuggestion.name?.substring(
+ searchText.length,
+ districtSuggestion.length
+ )
+ };
+ return word;
+ }
+ return { displayText: "" };
+};
+
+export const getSuggestedListByState = (searchText, state, type) => {
+ const RESULT_LIMIT = 10;
+
+ const allDistricts = resourceStats.districts.filter(e => e.state === state);
+
+ type = type === "All" ? "total" : type?.toLowerCase()
+
+ if (!searchText)
+ return allDistricts?.sort((a, b) => a[type] > b[type]).slice(0, RESULT_LIMIT);
+
+ const districts = allDistricts.filter(e => isPartialMatch(e, searchText));
+
+ return districts
+ .sort((a, _) => (isTrendingPlace(a.name) || isExactMatch(a, searchText) ? -1 : 0))
+ .slice(0, RESULT_LIMIT);
+};
diff --git a/pages/[state]/index.js b/pages/[state]/index.js
index b71fe3cc7..dd0d88827 100644
--- a/pages/[state]/index.js
+++ b/pages/[state]/index.js
@@ -1,8 +1,8 @@
import React from 'react';
import { parametreize, statesStaticPaths, humanize } from '@lib/utils';
import { NextSeo } from 'next-seo';
-import DetailedHome from '@components/DetailedHome';
import { useRouter } from 'next/router';
+import StateHome from '@components/StateHome';
export default function State({ state }) {
const SEO = {
@@ -28,7 +28,7 @@ export default function State({ state }) {
return (
<>
-
+
>
);
}
diff --git a/pages/index.jsx b/pages/index.jsx
index 26cdc0b8c..20713d168 100644
--- a/pages/index.jsx
+++ b/pages/index.jsx
@@ -15,7 +15,7 @@ export default function Home() {
const { locale } = useLocaleContext();
const t = useLocale(locale, 'home');
- const [resource, setResource] = useState("Oxygen");
+ const [resource, setResource] = useState("All");
const [isToShowSuggestion, setIsToShowSuggestion] = useState(false);
return (