Compare commits

..

10 commits

Author SHA1 Message Date
Nikhil Nawgiri b42c9f1833 Improve styles - WIP 2024-10-27 13:36:15 +01:00
Nikhil Nawgiri f6b67cfbb2 Refactor 2024-10-27 13:20:58 +01:00
Nikhil Nawgiri 806d72e58a Improve styling 2024-10-27 13:19:08 +01:00
Nikhil Nawgiri 8cbb624f1f Add SearchResultItem component 2024-10-27 13:14:58 +01:00
Nikhil Nawgiri 512b258131 Rename SearchResults -> SearchResult 2024-10-27 12:59:18 +01:00
Nikhil Nawgiri 0a138375dc Improve variable naming 2024-10-27 12:54:44 +01:00
Nikhil Nawgiri a8064668b8 Fix broken styles 2024-10-27 12:53:28 +01:00
Nikhil Nawgiri 9773239b4f Implement SearchResults in App 2024-10-27 12:48:19 +01:00
Nikhil Nawgiri 1ab1d204af Add SearchResults parent component 2024-10-27 12:48:07 +01:00
Nikhil Nawgiri e47510f912 Add typing for search result state hook value 2024-10-27 12:47:53 +01:00
5 changed files with 119 additions and 11 deletions

View file

@ -32,11 +32,13 @@ header {
width: calc(100vw - 30px);
margin: 0 auto;
display: flex;
justify-content: space-between;
}
main {
flex-grow: 1;
background: linear-gradient(220deg, var(--jf-gradient-color-secondary-dark), var(--jf-gradient-color-primary-dark));
padding: 7px 15px;
}
h1 {
@ -103,3 +105,33 @@ h1:hover {
font-size: 17px;
}
}
.search-result-item {
display: flex;
margin-bottom: 10px;
img {
height: 48px;
}
section {
flex: 1;
padding: 8px 0 0 8px;
display: flex;
justify-content: space-evenly;text-align: left;
}
}
.search-result-item-interaction {
min-width: 20px;
}
.search-result-item-text {
flex: 1;
padding-left: 5px;
}
.search-result-item-action {
width: 48px;
height: 48px;
}

View file

@ -4,10 +4,11 @@ import Search from './components/search/Search'
import jellyfin from './assets/jellyfin.svg'
import './App.css'
import SearchResult from './components/search/SearchResult';
function App() {
const [searchString, setSearchString] = useState("");
const [searchResults, setSearchResults] = useState([]);
const [searchResult, setSearchResult] = useState<{}[]>([]);
const [itemChoiceByUser, setItemChoiceByUser] = useState({});
const [count, setCount] = useState(0)
@ -23,14 +24,16 @@ function App() {
Wishlist
</h1>
<Search
setSearchResults={setSearchResults}
setSearchResult={setSearchResult}
searchString={searchString}
setSearchString={setSearchString}
/>
</header>
<main>
<div>
content
<SearchResult
items={searchResult}
/>
</div>
</main>
<div className="mobile-keyboard-mock" />

View file

@ -7,37 +7,37 @@ import debounce from "lodash/debounce";
import searchApiCall from "../../helper/omdbHelper.ts";
interface SearchProps {
setSearchResults: Function,
setSearchResult: Function,
setSearchString: Function,
searchString: string,
}
const Search = ({ setSearchResults, setSearchString, searchString }: SearchProps) => {
const Search = ({ setSearchResult, setSearchString, searchString }: SearchProps) => {
const inputRef = useRef() as MutableRefObject<HTMLInputElement>;
const debouncedSearch = useMemo(
() => debounce(() => {
searchApiCall({ searchString: searchString, setter: setSearchResults });
searchApiCall({ searchString: searchString, setter: setSearchResult });
}, 300),
[searchString, setSearchResults]
[searchString, setSearchResult]
);
useEffect(() => {
if (searchString.length > 0) {
debouncedSearch();
} else {
setSearchResults([]);
setSearchResult([]);
}
}, [searchString, debouncedSearch, setSearchResults]);
}, [searchString, debouncedSearch, setSearchResult]);
const resetSearchTerm = () => {
inputRef.current.focus();
setSearchString("");
setSearchResults([]);
setSearchResult([]);
};
return (
<div className="search-area">
<div className="search-bar">
<input
value={searchString}
type="text"

View file

@ -0,0 +1,25 @@
import SearchResultItem from "./SearchResultItem";
interface SearchResultProps {
items: object[],
}
const SearchResult = ({ items }: SearchResultProps) => (
<div className="search-result-wrapper">
{items.length > 0 && items.map((item) => {
const { Title, Poster, imdbID, Year, Type } = item;
return (
<SearchResultItem
title={Title}
image={Poster}
imdbId={imdbID}
key={Poster}
year={Year}
type={Type}
/>
);
})}
</div>
);
export default SearchResult;

View file

@ -0,0 +1,48 @@
interface SearchResultItemProps {
title: string,
image: string,
imdbId: string,
year: string,
type: string,
clickHandler?: Function,
}
const itemStatusInLibrary = {
available: "✅",
requested: "⏳",
missing: " ",
}
// todo add link to movie if available
const SearchResultItem = ({
title,
image,
imdbId,
year,
type,
clickHandler,
}: SearchResultItemProps) => (
<div
className="search-result-item"
onClick={() => clickHandler({
title,
imdbId,
year,
})}
>
<img src={image} alt={title} />
<section>
<div className="search-result-item-interaction">
{Object.values(itemStatusInLibrary)[Math.floor(Math.random() * Object.values(itemStatusInLibrary).length)]}
</div>
<span className="search-result-item-text">
{year.substring(0, 4)} - {title}
</span>
<div className="search-result-item-action">
🔗
</div>
</section>
</div>
);
export default SearchResultItem;