🔍 Improvements to CV search results

This commit is contained in:
2024-04-09 17:38:14 -04:00
parent 9315ad7454
commit 8fe49f7034
4 changed files with 179 additions and 54 deletions

View File

@@ -7,7 +7,7 @@ import Card from "../shared/Carda";
import ellipsize from "ellipsize";
import { convert } from "html-to-text";
import dayjs from "dayjs";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
COMICVINE_SERVICE_URI,
LIBRARY_SERVICE_BASE_URI,
@@ -23,32 +23,31 @@ export const Search = ({}: ISearchProps): ReactElement => {
const queryClient = useQueryClient();
const [searchQuery, setSearchQuery] = useState("");
const [comicVineMetadata, setComicVineMetadata] = useState({});
const getCVSearchResults = (searchQuery) => {
setSearchQuery(searchQuery.search);
};
const {
mutate,
data: comicVineSearchResults,
isLoading,
isPending,
isSuccess,
} = useQuery({
queryFn: async () =>
await axios({
} = useMutation({
mutationFn: async (data: { search: string; resource: string }) => {
const { search, resource } = data;
console.log(data);
return await axios({
url: `${COMICVINE_SERVICE_URI}/search`,
method: "GET",
params: {
api_key: "a5fa0663683df8145a85d694b5da4b87e1c92c69",
query: searchQuery,
query: search,
format: "json",
limit: "10",
offset: "0",
field_list:
"id,name,deck,api_detail_url,image,description,volume,cover_date",
resources: "issue",
"id,name,deck,api_detail_url,image,description,volume,cover_date,count_of_issues",
resources: resource,
},
}),
queryKey: ["comicvineSearchResults", searchQuery],
enabled: !isNil(searchQuery),
});
},
});
// add to library
@@ -107,7 +106,7 @@ export const Search = ({}: ISearchProps): ReactElement => {
</header>
<div className="mx-auto max-w-screen-sm px-4 py-4 sm:px-6 sm:py-8 lg:px-8">
<Form
onSubmit={getCVSearchResults}
onSubmit={mutate}
initialValues={{
...formData,
}}
@@ -139,19 +138,62 @@ export const Search = ({}: ISearchProps): ReactElement => {
Search
</button>
</div>
{/* resource type selection: volume, issue etc. */}
<div className="flex flex-row gap-3 mt-4">
<Field name="resource" type="radio" value="volume">
{({ input: volumesInput, meta }) => (
<div className="w-fit rounded-xl">
<div>
<input
{...volumesInput}
type="radio"
id="volume"
className="peer hidden"
/>
<label
htmlFor="volume"
className="block cursor-pointer select-none rounded-xl p-2 text-center peer-checked:bg-blue-500 peer-checked:font-bold peer-checked:text-white"
>
Volumes
</label>
</div>
</div>
)}
</Field>
<Field name="resource" type="radio" value="issue">
{({ input: issuesInput, meta }) => (
<div className="w-fit rounded-xl">
<div>
<input
{...issuesInput}
type="radio"
id="issue"
className="peer hidden"
/>
<label
htmlFor="issue"
className="block cursor-pointer select-none rounded-xl p-2 text-center peer-checked:bg-blue-500 peer-checked:font-bold peer-checked:text-white"
>
Issues
</label>
</div>
</div>
)}
</Field>
</div>
</form>
)}
/>
</div>
{isLoading && <>Loading kaka...</>}
{!isNil(comicVineSearchResults?.data.results) &&
!isEmpty(comicVineSearchResults?.data.results) ? (
{isPending && <>Loading results...</>}
{!isEmpty(comicVineSearchResults?.data?.results) ? (
<div className="mx-auto max-w-screen-xl px-4 py-4 sm:px-6 sm:py-8 lg:px-8">
{comicVineSearchResults.data.results.map((result) => {
return isSuccess ? (
return result.resource_type === "issue" ? (
<div key={result.id} className="mb-5">
<div className="flex flex-row">
<div className="mr-5">
<div className="mr-5 min-w-[200px] max-w-[25%]">
<Card
key={result.id}
orientation={"cover-only"}
@@ -159,7 +201,7 @@ export const Search = ({}: ISearchProps): ReactElement => {
hasDetails={false}
/>
</div>
<div className="column">
<div className="w-3/4">
<div className="text-xl">
{!isEmpty(result.volume.name) ? (
result.volume.name
@@ -167,22 +209,14 @@ export const Search = ({}: ISearchProps): ReactElement => {
<span className="is-size-3">No Name</span>
)}
</div>
<div className="field is-grouped mt-1">
<div className="control">
<div className="tags has-addons">
<span className="tag is-light">Cover date</span>
<span className="tag is-info is-light">
{dayjs(result.cover_date).format("MMM D, YYYY")}
</span>
</div>
</div>
{result.cover_date && (
<p>
<span className="tag is-light">Cover date</span>
{dayjs(result.cover_date).format("MMM D, YYYY")}
</p>
)}
<div className="control">
<div className="tags has-addons">
<span className="tag is-warning">{result.id}</span>
</div>
</div>
</div>
<p className="tag is-warning">{result.id}</p>
<a href={result.api_detail_url}>
{result.api_detail_url}
@@ -210,7 +244,72 @@ export const Search = ({}: ISearchProps): ReactElement => {
</div>
</div>
) : (
<div>Loading</div>
result.resource_type === "volume" && (
<div key={result.id} className="mb-5">
<div className="flex flex-row">
<div className="mr-5">
<Card
key={result.id}
orientation={"cover-only"}
imageUrl={result.image.small_url}
hasDetails={false}
/>
</div>
<div className="column">
<div className="text-xl">
{!isEmpty(result.name) ? (
result.name
) : (
<span className="is-size-3">No Name</span>
)}
</div>
<div className="field is-grouped mt-1">
<div className="control">
<div className="tags has-addons">
<span className="tag is-light">
Number of issues
</span>
<span className="tag is-info is-light">
{result.count_of_issues}
</span>
</div>
</div>
<div className="control">
<div className="tags has-addons">
<span className="tag is-warning">
{result.id}
</span>
</div>
</div>
</div>
<a href={result.api_detail_url}>
{result.api_detail_url}
</a>
<p>
{ellipsize(
convert(result.description, {
baseElements: {
selectors: ["p", "div"],
},
}),
320,
)}
</p>
<div className="mt-2">
<button
className="flex space-x-1 sm:mt-0 sm:flex-row sm:items-center rounded-lg border border-green-400 dark:border-green-200 bg-green-200 px-2 py-2 text-gray-500 hover:bg-transparent hover:text-green-600 focus:outline-none focus:ring active:text-indigo-500"
onClick={() => addToLibrary("comicvine", result)}
>
<i className="icon-[solar--add-square-bold-duotone] w-6 h-6 mr-2"></i>{" "}
Mark as Wanted
</button>
</div>
</div>
</div>
</div>
)
);
})}
</div>

View File

@@ -48,13 +48,11 @@ export const SystemSettingsForm = (): ReactElement => {
</article>
<button
className={
isLoading ? "button is-danger is-loading" : "button is-danger"
}
className="flex space-x-1 sm:mt-0 sm:flex-row sm:items-center rounded-lg border border-red-400 dark:border-red-200 bg-red-200 px-4 py-2 text-gray-500 hover:bg-transparent hover:text-red-600 focus:outline-none focus:ring active:text-indigo-500"
onClick={() => flushDb()}
>
<span className="icon">
<i className="fas fa-eraser"></i>
<span className="pt-1 px-1">
<i className="icon-[solar--trash-bin-trash-bold-duotone] w-7 h-7"></i>
</span>
<span>Flush DB & Temporary Folders</span>
</button>

View File

@@ -61,7 +61,7 @@ const VolumeDetails = (props): ReactElement => {
}),
queryKey: ["comicObject"],
});
console.log(comicObject);
// get issues for a series
const {
data: issuesForSeries,
@@ -108,7 +108,6 @@ const VolumeDetails = (props): ReactElement => {
status,
} = useGetStoryArcs();
console.log("jihya", issuesForSeries);
const IssuesInVolume = () => (
<>
{!isUndefined(issuesForSeries) ? (
@@ -146,13 +145,42 @@ const VolumeDetails = (props): ReactElement => {
const Issues = () => (
<>
as
<ul>
<article
role="alert"
className="mt-4 rounded-lg text-sm max-w-screen-md border-s-4 border-blue-500 bg-blue-50 p-4 dark:border-s-4 dark:border-blue-600 dark:bg-blue-300 dark:text-slate-600"
>
<div>
You can add a single issue or the whole volume, and it will be added
to the list of `Wanted` items.
</div>
</article>
<div className="flex flex-wrap">
{isSuccess &&
issuesForSeries?.data.map((issue) => {
return <li>{JSON.stringify(issue, null, 2)}</li>;
return (
<div className="my-3 dark:bg-slate-400 bg-slate-300 p-4 rounded-lg w-3/4">
<div className="flex flex-row gap-4 mb-2">
<div className="w-fit">
<img
src={issue.image.thumb_url}
className="w-full rounded-md"
/>
</div>
<div className="w-3/4">
<p className="text-xl">{issue.name}</p>
<p className="text-sm">
{convert(issue.description, {
baseElements: {
selectors: ["p"],
},
})}
</p>
</div>
</div>
</div>
);
})}
</ul>
</div>
</>
);
@@ -265,9 +293,9 @@ const VolumeDetails = (props): ReactElement => {
/>
<div>
<div className="field is-grouped mt-2">
<div className="field is-grouped">
{/* Title */}
<span className="text-xl">
<span className="text-2xl">
{sourcedMetadata.comicvine.volumeInformation.name}
</span>
{/* Comicvine Id */}

View File

@@ -58,10 +58,10 @@ export const Volumes = (props): ReactElement => {
hasDetails={false}
/>
</Link>
<div className="dark:bg-[#647587] bg-slate-200 p-3 rounded-lg h-fit">
<span className="text-xl mb-1">
<div className="dark:bg-[#647587] bg-slate-200 rounded-lg w-3/4 h-fit p-3">
<div className="text-xl mb-1 w-fit">
{sourcedMetadata.comicvine.volumeInformation.name}
</span>
</div>
<p>
{ellipsize(
convert(
@@ -72,7 +72,7 @@ export const Volumes = (props): ReactElement => {
},
},
),
120,
180,
)}
</p>
</div>