* 🌊 qBittorrent settings scaffold * 🔧 Added scaffold for the qBittorrent connection form * 🔧 Some refactoring * 🔧 Cleaned up folder structure * 🔧 Fixed broken paths * 🔧 Cleaned up Search and Import component hierarchy * 🔧 More path fixes * 🔧 Tooling changes * 📝 Qbittorrent form scaffold * ⬆️ Bumped @dnd-kit deps * 🧑🏼🔧 Fixed the hostname regex * 🏗️ Adding fields to the settings form * 🔧 Formatting and more layout changes * 🔧 Added Prowlarr settings items in JSON * 📝 Purified Card Component * 📝 Abstracted connection form into a component * 🏗️ Reorganized tabs * Migrating from Redux to RTK-query * ⬇️ Fetched qBittorrent settings * 🏗️ Trying out react-query * 🧩 Added react-query query to qBittorrentSettings page * 📝 qbittorrent form RU actions first draft * 🏗️ Added loading state check * 🏗 Added error check state * 🏗️ Refactored AirDCPP context using react-query * 🏗️ Refactoring AirDCPP Settings Form with react-query * 🔧 Removed context * 🔧 Removing context from AirDCPP settings page * 🔧 Fixed early init error on the store * 🐛 Debugging AirDCPP Settings Form page * 🧸 Zustand-ified AirDCPP Form * ❌ AirDCPP code cleaned up from App.tsx * ➕ Re-added yarn.lock
83 lines
2.1 KiB
TypeScript
83 lines
2.1 KiB
TypeScript
import { debounce, isEmpty, map } from "lodash";
|
|
import React, { ReactElement, useCallback, useState } from "react";
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
import Card from "../shared/Carda";
|
|
|
|
import { searchIssue } from "../../actions/fileops.actions";
|
|
import MetadataPanel from "../shared/MetadataPanel";
|
|
|
|
interface ISearchBarProps {
|
|
data: any;
|
|
}
|
|
|
|
export const SearchBar = (data: ISearchBarProps): ReactElement => {
|
|
const dispatch = useDispatch();
|
|
const searchResults = useSelector(
|
|
(state: RootState) => state.fileOps.librarySearchResultsFormatted,
|
|
);
|
|
|
|
const performSearch = useCallback(
|
|
debounce((e) => {
|
|
dispatch(
|
|
searchIssue(
|
|
{
|
|
query: {
|
|
volumeName: e.target.value,
|
|
},
|
|
},
|
|
{
|
|
pagination: {
|
|
size: 25,
|
|
from: 0,
|
|
},
|
|
type: "volumeName",
|
|
trigger: "globalSearchBar",
|
|
},
|
|
),
|
|
);
|
|
}, 500),
|
|
[data],
|
|
);
|
|
return (
|
|
<>
|
|
<div className="control has-icons-right">
|
|
<input
|
|
className="input mt-2"
|
|
placeholder="Search Library"
|
|
onChange={(e) => performSearch(e)}
|
|
/>
|
|
|
|
<span className="icon is-right mt-2">
|
|
<i className="fa-solid fa-magnifying-glass"></i>
|
|
</span>
|
|
</div>
|
|
{!isEmpty(searchResults) ? (
|
|
<div
|
|
className="columns box is-multiline"
|
|
style={{
|
|
padding: 4,
|
|
position: "absolute",
|
|
width: 360,
|
|
margin: "60px 0 0 350px",
|
|
}}
|
|
>
|
|
{map(searchResults, (result, idx) => (
|
|
<MetadataPanel
|
|
data={result}
|
|
key={idx}
|
|
imageStyle={{ maxWidth: 70 }}
|
|
titleStyle={{ fontSize: "0.8rem" }}
|
|
tagsStyle={{ fontSize: "0.7rem" }}
|
|
containerStyle={{
|
|
width: "100vw",
|
|
padding: 0,
|
|
margin: "0 0 8px 0",
|
|
}}
|
|
/>
|
|
))}
|
|
</div>
|
|
) : null}
|
|
</>
|
|
);
|
|
};
|