Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions front/src/pods/embalse-search/components/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './recent-searches';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./recent-searches.component"
export * from "./useRecentSearches.hook"
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Link from "next/link";
import { EmbalseSearchModel } from "../../embalse-search.vm";

interface Props {
searches: EmbalseSearchModel[];
}

export const RecentSearches: React.FC<Props> = (props) => {
const { searches } = props;

return (
<>
<h3>Búsquedas recientes</h3>
<ul>
{searches.map((item) => (
<li key={item.slug} className="mt-3">
<Link className="link-accessible" href={`/embalse/${item.slug}`}>{item.name} </Link>
</li>
))}
</ul>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useState, useEffect } from "react";
import { EmbalseSearchModel } from "../../embalse-search.vm";

export const useRecentSearches = () => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could simplify this, something like:

export const useRecentSearches = () => {
  const [recentSearches, setRecentSearches] = useState<EmbalseSearchModel[]>(
    [];

  useEffect(() => {
    const storedSearches = localStorage.getItem("recent-searches");
    if (storedSearches) {
      const parsedStoredSearches = JSON.parse(storedSearches);
      setRecentSearches(parsedStoredSearches);
    }
  }, []);

  const addNewEmbalseToRecentVisitedCollection(searchTerm: string) {
      const newSearchCollection = addNewSearchEntry = (searchTerm,recentSearches);

     setRecentSearches(newSearchCollection);
   }
}

const [newSearch, setNewSearch] = useState<EmbalseSearchModel>(null);
const [recentSearches, setRecentSearches] = useState<EmbalseSearchModel[]>(
[],
);

useEffect(() => {
const storedSearches = localStorage.getItem("recent-searches");
if (storedSearches) {
const parsedStoredSearches = JSON.parse(storedSearches);
setRecentSearches(parsedStoredSearches);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this to a business method as well, and ensure to cover edge cases here, What happens if we get an exception? localStorage may be disabled (e.g. in some browser in icognito mode), what happens if you we null or undefined, what happens if we get an string instead of an array, we should default it to empty array in that case

}, []);

useEffect(() => {
if (newSearch) {
setRecentSearches((prevSearches) => {
const filteredRecentSearches = prevSearches.filter(
(search) => search.slug !== newSearch.slug,
);
return [newSearch, ...filteredRecentSearches].slice(0, 5);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's create a recentSearches.bussiness.ts file and create a funciont like

const addNewSearchEntry = (newEntry: string,prevSearches: string[]) : string => {
          const filteredRecentSearches = prevSearches.filter(
          (search) => search.slug !== newSearch.slug,
        );

return [newSearch, ...filteredRecentSearches].slice(0, 5);
}

Then use that in this hook, and add unit test support.

});
}
}, [newSearch]);

useEffect(() => {
if (recentSearches.length > 0) {
const stringfiedRecentSearches = JSON.stringify(recentSearches);
localStorage.setItem("recent-searches", stringfiedRecentSearches);
}
}, [recentSearches]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmmm... why do we need this method? we are adding recent searches one by one, this could lead to issues if we are adding a new search this could lead to an infinite loop?


return {
newSearch,
setNewSearch,
recentSearches,
setRecentSearches,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think you don't need to expose newSearch, you can remove it and add just to the setNewsearch method passing a param

};
};
25 changes: 16 additions & 9 deletions front/src/pods/embalse-search/embalse-search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { EmbalseSearchModel } from "./embalse-search.vm";
import { getFilteredEmbalses as getFilteredEmbalsesBusiness } from "./embalse-search.business";
import { FilteredList } from "./components/filtered-list";
import { Input } from "./components/input";
import { RecentSearches, useRecentSearches } from "./components";

interface Props {
embalses: Embalse[];
Expand All @@ -22,6 +23,7 @@ export const EmbalseSearch: React.FC<Props> = (props) => {
>([]);
const [isNavigating, setIsNavigating] = useState<boolean>(false);
const [inputValue, setInputValue] = useState<string>("");
const { setNewSearch, recentSearches } = useRecentSearches();

const getFilteredEmbalses = (inputValue: string): EmbalseSearchModel[] => {
return getFilteredEmbalsesBusiness(inputValue, embalses);
Expand All @@ -42,12 +44,14 @@ export const EmbalseSearch: React.FC<Props> = (props) => {
onSelectedItemChange: ({ selectedItem }) => {
if (selectedItem) {
setIsNavigating(true);
setNewSearch(selectedItem);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's name this: `addNewEmbalseToLatestSearchCollection``

I think it's more meaninful

router.push(`/embalse/${selectedItem.slug}`);
}
},
});

const showNoResults = inputValue.length > 0 && filteredEmbalses.length === 0 && !isNavigating;
const showNoResults =
inputValue.length > 0 && filteredEmbalses.length === 0 && !isNavigating;

return (
<div className="relative flex flex-1 flex-col overflow-hidden p-8">
Expand All @@ -57,15 +61,19 @@ export const EmbalseSearch: React.FC<Props> = (props) => {
></div>
<div className="flex grow flex-col items-center justify-center">
<section
className="bg-base-100 absolute flex max-w-10/12 flex-col gap-8 rounded-xl p-8 shadow-lg"
className="bg-base-100 absolute flex max-w-10/12 flex-col gap-3 rounded-xl p-8 shadow-lg"
aria-labelledby="search-title"
>
<div className="text-center">
<h2 id="search-title" className="font-bold">
Embalses
</h2>
</div>

<div>
<p className="text-sm">
Encuentra toda la información disponible de los embalses de España
</p>
</div>
<div className="flex flex-col gap-4">
<div className="relative" role="search">
<Input getInputProps={getInputProps} />
Expand All @@ -78,13 +86,12 @@ export const EmbalseSearch: React.FC<Props> = (props) => {
/>
{showNoResults && <NoResult inputValue={inputValue} />}
</div>
<div>
<p className="text-sm">
Encuentra toda la información disponible de los embalses de
España
</p>
</div>
</div>
{recentSearches.length > 0 && (
<div className="mt-5">
<RecentSearches searches={recentSearches} />
</div>
)}
</section>
</div>
</div>
Expand Down
Loading