🎠 Carousels on Wanted and Volumes
This commit is contained in:
@@ -4,6 +4,7 @@ import ellipsize from "ellipsize";
|
|||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import Card from "../shared/Carda";
|
import Card from "../shared/Carda";
|
||||||
import Header from "../shared/Header";
|
import Header from "../shared/Header";
|
||||||
|
import useEmblaCarousel from "embla-carousel-react";
|
||||||
|
|
||||||
export const VolumeGroups = (props): ReactElement => {
|
export const VolumeGroups = (props): ReactElement => {
|
||||||
// Till mongo gives us back the deduplicated results with the ObjectId
|
// Till mongo gives us back the deduplicated results with the ObjectId
|
||||||
@@ -13,50 +14,64 @@ export const VolumeGroups = (props): ReactElement => {
|
|||||||
navigate(`/volumes/all`);
|
navigate(`/volumes/all`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// embla carousel
|
||||||
|
const [emblaRef, emblaApi] = useEmblaCarousel({
|
||||||
|
loop: false,
|
||||||
|
align: "start",
|
||||||
|
containScroll: "trimSnaps",
|
||||||
|
slidesToScroll: 1,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section>
|
<div>
|
||||||
<Header
|
<Header
|
||||||
headerContent="Volumes"
|
headerContent="Volumes"
|
||||||
subHeaderContent="Based on ComicVine Volume information"
|
subHeaderContent={<>Based on ComicVine Volume information</>}
|
||||||
iconClassNames="fa-solid fa-binoculars mr-2"
|
iconClassNames="fa-solid fa-binoculars mr-2"
|
||||||
link={"/volumes"}
|
link={"/volumes"}
|
||||||
/>
|
/>
|
||||||
<div className="grid grid-cols-5 gap-6 mt-3">
|
<div className="-mr-10 sm:-mr-17 lg:-mr-29 xl:-mr-36 2xl:-mr-42 mt-3">
|
||||||
{map(deduplicatedGroups, (data) => {
|
<div className="overflow-hidden" ref={emblaRef}>
|
||||||
return (
|
<div className="flex">
|
||||||
<div className="max-w-sm mx-auto" key={data._id}>
|
{map(deduplicatedGroups, (data) => {
|
||||||
<Card
|
return (
|
||||||
orientation="vertical-2"
|
<div
|
||||||
key={data._id}
|
key={data._id}
|
||||||
imageUrl={data.volumes.image.small_url}
|
className="flex-[0_0_200px] min-w-0 sm:flex-[0_0_220px] md:flex-[0_0_240px] lg:flex-[0_0_260px] xl:flex-[0_0_280px] pr-[15px]"
|
||||||
hasDetails
|
>
|
||||||
>
|
<Card
|
||||||
<div className="py-3">
|
orientation="vertical-2"
|
||||||
<div className="text-sm">
|
imageUrl={data.volumes.image.small_url}
|
||||||
<Link to={`/volume/details/${data._id}`}>
|
hasDetails
|
||||||
{ellipsize(data.volumes.name, 48)}
|
>
|
||||||
</Link>
|
<div className="py-3">
|
||||||
</div>
|
<div className="text-sm">
|
||||||
{/* issue count */}
|
<Link to={`/volume/details/${data._id}`}>
|
||||||
<span className="inline-flex mt-1 items-center bg-slate-50 text-slate-800 text-xs font-medium px-2.5 py-0.5 rounded-md dark:text-slate-600 dark:bg-slate-400">
|
{ellipsize(data.volumes.name, 48)}
|
||||||
<span className="pr-1 pt-1">
|
</Link>
|
||||||
<i className="icon-[solar--documents-minimalistic-bold-duotone] w-5 h-5"></i>
|
</div>
|
||||||
</span>
|
{/* issue count */}
|
||||||
|
<span className="inline-flex mt-1 items-center bg-slate-50 text-slate-800 text-xs font-medium px-2.5 py-0.5 rounded-md dark:text-slate-600 dark:bg-slate-400">
|
||||||
|
<span className="pr-1 pt-1">
|
||||||
|
<i className="icon-[solar--documents-minimalistic-bold-duotone] w-5 h-5"></i>
|
||||||
|
</span>
|
||||||
|
|
||||||
<span className="text-md text-slate-500 dark:text-slate-900">
|
<span className="text-md text-slate-500 dark:text-slate-900">
|
||||||
{data.volumes.count_of_issues} issues
|
{data.volumes.count_of_issues} issues
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
<div className="w-11/12 h-2 mx-auto bg-slate-900 rounded-b opacity-75"></div>
|
||||||
|
<div className="w-10/12 h-2 mx-auto bg-slate-900 rounded-b opacity-50"></div>
|
||||||
|
<div className="w-9/12 h-2 mx-auto bg-slate-900 rounded-b opacity-25"></div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
);
|
||||||
<div className="w-11/12 h-2 mx-auto bg-slate-900 rounded-b opacity-75"></div>
|
})}
|
||||||
<div className="w-10/12 h-2 mx-auto bg-slate-900 rounded-b opacity-50"></div>
|
</div>
|
||||||
<div className="w-9/12 h-2 mx-auto bg-slate-900 rounded-b opacity-25"></div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { isEmpty, isNil, isUndefined, map } from "lodash";
|
|||||||
import { detectIssueTypes } from "../../shared/utils/tradepaperback.utils";
|
import { detectIssueTypes } from "../../shared/utils/tradepaperback.utils";
|
||||||
import { determineCoverFile } from "../../shared/utils/metadata.utils";
|
import { determineCoverFile } from "../../shared/utils/metadata.utils";
|
||||||
import Header from "../shared/Header";
|
import Header from "../shared/Header";
|
||||||
|
import useEmblaCarousel from "embla-carousel-react";
|
||||||
|
|
||||||
type WantedComicsListProps = {
|
type WantedComicsListProps = {
|
||||||
comics: any;
|
comics: any;
|
||||||
@@ -16,108 +17,124 @@ export const WantedComicsList = ({
|
|||||||
}: WantedComicsListProps): ReactElement => {
|
}: WantedComicsListProps): ReactElement => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// embla carousel
|
||||||
|
const [emblaRef, emblaApi] = useEmblaCarousel({
|
||||||
|
loop: false,
|
||||||
|
align: "start",
|
||||||
|
containScroll: "trimSnaps",
|
||||||
|
slidesToScroll: 1,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div>
|
||||||
<Header
|
<Header
|
||||||
headerContent="Wanted Comics"
|
headerContent="Wanted Comics"
|
||||||
subHeaderContent="Comics marked as wanted from various sources"
|
subHeaderContent={<>Comics marked as wanted from various sources</>}
|
||||||
iconClassNames="fa-solid fa-binoculars mr-2"
|
iconClassNames="fa-solid fa-binoculars mr-2"
|
||||||
link={"/wanted"}
|
link={"/wanted"}
|
||||||
/>
|
/>
|
||||||
<div className="grid grid-cols-5 gap-6 mt-3">
|
<div className="-mr-10 sm:-mr-17 lg:-mr-29 xl:-mr-36 2xl:-mr-42 mt-3">
|
||||||
{map(
|
<div className="overflow-hidden" ref={emblaRef}>
|
||||||
comics,
|
<div className="flex">
|
||||||
({
|
{map(
|
||||||
_id,
|
comics,
|
||||||
rawFileDetails,
|
({
|
||||||
sourcedMetadata: { comicvine, comicInfo, locg },
|
_id,
|
||||||
wanted,
|
rawFileDetails,
|
||||||
}) => {
|
sourcedMetadata: { comicvine, comicInfo, locg },
|
||||||
const isComicBookMetadataAvailable = !isUndefined(comicvine);
|
wanted,
|
||||||
const consolidatedComicMetadata = {
|
}) => {
|
||||||
rawFileDetails,
|
const isComicBookMetadataAvailable = !isUndefined(comicvine);
|
||||||
comicvine,
|
const consolidatedComicMetadata = {
|
||||||
comicInfo,
|
rawFileDetails,
|
||||||
locg,
|
comicvine,
|
||||||
};
|
comicInfo,
|
||||||
|
locg,
|
||||||
const {
|
};
|
||||||
issueName,
|
|
||||||
url,
|
const {
|
||||||
publisher = null,
|
issueName,
|
||||||
} = determineCoverFile(consolidatedComicMetadata);
|
url,
|
||||||
const titleElement = (
|
publisher = null,
|
||||||
<Link to={"/comic/details/" + _id}>
|
} = determineCoverFile(consolidatedComicMetadata);
|
||||||
{ellipsize(issueName, 20)}
|
const titleElement = (
|
||||||
<p>{publisher}</p>
|
<Link to={"/comic/details/" + _id}>
|
||||||
</Link>
|
{ellipsize(issueName, 20)}
|
||||||
);
|
<p>{publisher}</p>
|
||||||
return (
|
</Link>
|
||||||
<Card
|
);
|
||||||
key={_id}
|
return (
|
||||||
orientation={"vertical-2"}
|
<div
|
||||||
imageUrl={url}
|
key={_id}
|
||||||
hasDetails
|
className="flex-[0_0_200px] min-w-0 sm:flex-[0_0_220px] md:flex-[0_0_240px] lg:flex-[0_0_260px] xl:flex-[0_0_280px] pr-[15px]"
|
||||||
title={issueName ? titleElement : <span>No Name</span>}
|
>
|
||||||
cardState="wanted"
|
<Card
|
||||||
>
|
orientation={"vertical-2"}
|
||||||
<div className="pb-1">
|
imageUrl={url}
|
||||||
<div className="flex flex-row gap-2">
|
hasDetails
|
||||||
{/* Issue type */}
|
title={issueName ? titleElement : <span>No Name</span>}
|
||||||
{isComicBookMetadataAvailable &&
|
cardState="wanted"
|
||||||
!isNil(detectIssueTypes(comicvine.description)) ? (
|
>
|
||||||
<div className="my-2">
|
<div className="pb-1">
|
||||||
<span className="inline-flex items-center bg-slate-50 text-slate-800 text-xs font-medium px-2.5 py-0.5 rounded-md dark:text-slate-900 dark:bg-slate-400">
|
<div className="flex flex-row gap-2">
|
||||||
<span className="pr-1 pt-1">
|
{/* Issue type */}
|
||||||
<i className="icon-[solar--book-2-line-duotone] w-5 h-5"></i>
|
{isComicBookMetadataAvailable &&
|
||||||
</span>
|
!isNil(detectIssueTypes(comicvine.description)) ? (
|
||||||
|
<div className="my-2">
|
||||||
<span className="text-md text-slate-500 dark:text-slate-900">
|
<span className="inline-flex items-center bg-slate-50 text-slate-800 text-xs font-medium px-2.5 py-0.5 rounded-md dark:text-slate-900 dark:bg-slate-400">
|
||||||
{
|
<span className="pr-1 pt-1">
|
||||||
detectIssueTypes(comicvine.description)
|
<i className="icon-[solar--book-2-line-duotone] w-5 h-5"></i>
|
||||||
.displayName
|
</span>
|
||||||
}
|
|
||||||
</span>
|
<span className="text-md text-slate-500 dark:text-slate-900">
|
||||||
</span>
|
{
|
||||||
|
detectIssueTypes(comicvine.description)
|
||||||
|
.displayName
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
{/* issues marked as wanted, part of this volume */}
|
||||||
|
{wanted?.markEntireVolumeWanted ? (
|
||||||
|
<div className="text-sm">sagla volume pahije</div>
|
||||||
|
) : (
|
||||||
|
<div className="my-2">
|
||||||
|
<span className="inline-flex items-center bg-slate-50 text-slate-800 text-xs font-medium px-2.5 py-0.5 rounded-md dark:text-slate-900 dark:bg-slate-400">
|
||||||
|
<span className="pr-1 pt-1">
|
||||||
|
<i className="icon-[solar--documents-bold-duotone] w-5 h-5"></i>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span className="text-md text-slate-500 dark:text-slate-900">
|
||||||
|
{wanted.issues.length}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{/* comicVine metadata presence */}
|
||||||
|
{isComicBookMetadataAvailable && (
|
||||||
|
<img
|
||||||
|
src="/src/client/assets/img/cvlogo.svg"
|
||||||
|
alt={"ComicVine metadata detected."}
|
||||||
|
className="inline-block w-6 h-6 md:w-7 md:h-7 flex-shrink-0 object-contain"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!isEmpty(locg) && (
|
||||||
|
<img
|
||||||
|
src="/src/client/assets/img/locglogo.svg"
|
||||||
|
className="w-7 h-7"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
);
|
||||||
{/* issues marked as wanted, part of this volume */}
|
},
|
||||||
{wanted?.markEntireVolumeWanted ? (
|
)}
|
||||||
<div className="text-sm">sagla volume pahije</div>
|
</div>
|
||||||
) : (
|
</div>
|
||||||
<div className="my-2">
|
</div>
|
||||||
<span className="inline-flex items-center bg-slate-50 text-slate-800 text-xs font-medium px-2.5 py-0.5 rounded-md dark:text-slate-900 dark:bg-slate-400">
|
</div>
|
||||||
<span className="pr-1 pt-1">
|
|
||||||
<i className="icon-[solar--documents-bold-duotone] w-5 h-5"></i>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span className="text-md text-slate-500 dark:text-slate-900">
|
|
||||||
{wanted.issues.length}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{/* comicVine metadata presence */}
|
|
||||||
{isComicBookMetadataAvailable && (
|
|
||||||
<img
|
|
||||||
src="/src/client/assets/img/cvlogo.svg"
|
|
||||||
alt={"ComicVine metadata detected."}
|
|
||||||
className="inline-block w-6 h-6 md:w-7 md:h-7 flex-shrink-0 object-contain"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!isEmpty(locg) && (
|
|
||||||
<img
|
|
||||||
src="/src/client/assets/img/locglogo.svg"
|
|
||||||
className="w-7 h-7"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user