feat: add button to show collections containing the release on release page

feat: add release in list widget to release page
fix: redirecting if viewing not favorites collection for unauthorized user
This commit is contained in:
Kentai Radiquum 2024-08-18 14:40:59 +05:00
parent 723b620749
commit 501d3a1705
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
5 changed files with 117 additions and 61 deletions

View file

@ -1,13 +1,21 @@
import { Card } from "flowbite-react"; import { Card } from "flowbite-react";
export const CollectionInfoLists = (props: { export const InfoLists = (props: {
completed: number; completed: number;
planned: number; planned: number;
abandoned: number; abandoned: number;
delayed: number; delayed: number;
watching: number; watching: number;
total: number; total?: number;
}) => { }) => {
const total =
props.total ||
props.watching +
props.planned +
props.completed +
props.delayed +
props.abandoned;
return ( return (
<Card className="w-full h-fit "> <Card className="w-full h-fit ">
<div <div
@ -15,12 +23,19 @@ export const CollectionInfoLists = (props: {
style={ style={
{ {
"--width-of-one": "5", "--width-of-one": "5",
"--watching-percent": `calc(var(--width-of-one) * (${props.watching} / ${props.total} * 100%))`, "--watching-percent": `calc(var(--width-of-one) * (${props.watching} / ${total} * 100%))`,
"--planned-percent": `calc(var(--width-of-one) * (${props.planned} / ${props.total} * 100%))`, "--planned-percent": `calc(var(--width-of-one) * (${props.planned} / ${total} * 100%))`,
"--watched-percent": `calc(var(--width-of-one) * (${props.completed} / ${props.total} * 100%))`, "--watched-percent": `calc(var(--width-of-one) * (${props.completed} / ${total} * 100%))`,
"--delayed-percent": `calc(var(--width-of-one) * (${props.delayed} / ${props.total} * 100%))`, "--delayed-percent": `calc(var(--width-of-one) * (${props.delayed} / ${total} * 100%))`,
"--abandoned-percent": `calc(var(--width-of-one) * (${props.abandoned} / ${props.total} * 100%))`, "--abandoned-percent": `calc(var(--width-of-one) * (${props.abandoned} / ${total} * 100%))`,
"--no-list-percent": `calc(var(--width-of-one) * (${props.total - (props.watching + props.planned + props.completed + props.delayed + props.abandoned)} / ${props.total} * 100%))`, "--no-list-percent": `calc(var(--width-of-one) * (${
total -
(props.watching +
props.planned +
props.completed +
props.delayed +
props.abandoned)
} / ${total} * 100%))`,
} as React.CSSProperties } as React.CSSProperties
} }
> >

View file

@ -1,5 +1,6 @@
import { Card, Dropdown, Button } from "flowbite-react"; import { Card, Dropdown, Button } from "flowbite-react";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import Link from "next/link";
const lists = [ const lists = [
{ list: 0, name: "Не смотрю" }, { list: 0, name: "Не смотрю" },
@ -12,8 +13,7 @@ const lists = [
const DropdownTheme = { const DropdownTheme = {
floating: { floating: {
target: target: "flex-1",
"flex-1",
}, },
}; };
@ -24,6 +24,7 @@ export const ReleaseInfoUserList = (props: {
token: string | null; token: string | null;
setUserList: any; setUserList: any;
setIsFavorite: any; setIsFavorite: any;
collection_count: number;
}) => { }) => {
function _addToFavorite() { function _addToFavorite() {
if (props.token) { if (props.token) {
@ -51,39 +52,57 @@ export const ReleaseInfoUserList = (props: {
return ( return (
<Card className="h-full"> <Card className="h-full">
{props.token ? ( <div className="flex flex-wrap gap-1">
<div className="flex flex-wrap gap-2"> <Button color={"blue"} size="sm" className="w-full lg:w-auto ">
<Dropdown <Link href={`/release/${props.release_id}/collections`}>
label={lists[props.userList].name} Показать в коллекциях{" "}
dismissOnClick={true} <span className="p-1 ml-1 text-gray-500 rounded bg-gray-50">
theme={DropdownTheme} {props.collection_count}
color="blue" </span>
> </Link>
{lists.map((list) => ( </Button>
<Dropdown.Item {props.token && (
key={list.list} <Button color={"blue"} size="sm" className="w-full lg:w-auto lg:flex-1">
onClick={() => _addToList(list.list)} В коллекцию{" "}
> <span className="w-6 h-6 iconify mdi--bookmark-add "></span>
{list.name}
</Dropdown.Item>
))}
</Dropdown>
<Button
color="blue"
onClick={() => {
_addToFavorite();
}}
>
<span
className={`iconify w-6 h-6 ${
props.isFavorite ? "mdi--heart" : "mdi--heart-outline"
}`}
></span>
</Button> </Button>
</div> )}
) : ( {props.token ? (
<p>Войдите что-бы добавить в избранное или список</p> <>
)} <Dropdown
label={lists[props.userList].name}
dismissOnClick={true}
theme={DropdownTheme}
color="blue"
size="sm"
>
{lists.map((list) => (
<Dropdown.Item
key={list.list}
onClick={() => _addToList(list.list)}
>
{list.name}
</Dropdown.Item>
))}
</Dropdown>
<Button
color="blue"
onClick={() => {
_addToFavorite();
}}
size="sm"
>
<span
className={`iconify w-6 h-6 ${
props.isFavorite ? "mdi--heart" : "mdi--heart-outline"
}`}
></span>
</Button>
</>
) : (
<p>Войдите что-бы добавить список, избранное или коллекцию</p>
)}
</div>
</Card> </Card>
); );
}; };

View file

@ -35,15 +35,22 @@ export function CollectionsFullPage(props: {
const getKey = (pageIndex: number, previousPageData: any) => { const getKey = (pageIndex: number, previousPageData: any) => {
if (previousPageData && !previousPageData.content.length) return null; if (previousPageData && !previousPageData.content.length) return null;
if (userStore.token) {
if (props.type == "favorites") { let url;
return `${ENDPOINTS.collection.favoriteCollections}/all/${pageIndex}?token=${userStore.token}`;
} else if (props.type == "profile") { if (props.type == "favorites") {
return `${ENDPOINTS.collection.userCollections}/${props.profile_id}/${pageIndex}?token=${userStore.token}`; url = `${ENDPOINTS.collection.favoriteCollections}/all/${pageIndex}`;
} else if (props.type == "release") { } else if (props.type == "profile") {
return `${ENDPOINTS.collection.releaseInCollections}/${props.release_id}/${pageIndex}?token=${userStore.token}`; url = `${ENDPOINTS.collection.userCollections}/${props.profile_id}/${pageIndex}`;
} } else if (props.type == "release") {
url = `${ENDPOINTS.collection.releaseInCollections}/${props.release_id}/${pageIndex}`;
} }
if (userStore.token) {
url += `?token=${userStore.token}`;
}
return url;
}; };
const { data, error, isLoading, size, setSize } = useSWRInfinite( const { data, error, isLoading, size, setSize } = useSWRInfinite(
@ -72,7 +79,11 @@ export function CollectionsFullPage(props: {
}, [scrollPosition]); }, [scrollPosition]);
useEffect(() => { useEffect(() => {
if (userStore.state === "finished" && !userStore.token) { if (
userStore.state === "finished" &&
!userStore.token &&
props.type == "favorites"
) {
router.push(`/login?redirect=/collections/favorites`); router.push(`/login?redirect=/collections/favorites`);
} }
}, [userStore.state, userStore.token]); }, [userStore.state, userStore.token]);

View file

@ -15,6 +15,7 @@ import { ReleaseInfoRating } from "#/components/ReleaseInfo/ReleaseInfo.Rating";
import { ReleaseInfoRelated } from "#/components/ReleaseInfo/ReleaseInfo.Related"; import { ReleaseInfoRelated } from "#/components/ReleaseInfo/ReleaseInfo.Related";
import { ReleaseInfoScreenshots } from "#/components/ReleaseInfo/ReleaseInfo.Screenshots"; import { ReleaseInfoScreenshots } from "#/components/ReleaseInfo/ReleaseInfo.Screenshots";
import { CommentsMain } from "#/components/Comments/Comments.Main"; import { CommentsMain } from "#/components/Comments/Comments.Main";
import { InfoLists } from "#/components/InfoLists/InfoLists";
export const ReleasePage = (props: any) => { export const ReleasePage = (props: any) => {
const token = useUserStore((state) => state.token); const token = useUserStore((state) => state.token);
@ -68,7 +69,7 @@ export const ReleasePage = (props: any) => {
released: data.release.episodes_released, released: data.release.episodes_released,
}} }}
season={data.release.season} season={data.release.season}
status={data.release.status.name} status={data.release.status ? data.release.status.name : "Анонс"}
duration={data.release.duration} duration={data.release.duration}
category={data.release.category.name} category={data.release.category.name}
broadcast={data.release.broadcast} broadcast={data.release.broadcast}
@ -86,14 +87,15 @@ export const ReleasePage = (props: any) => {
token={token} token={token}
setUserList={setUserList} setUserList={setUserList}
setIsFavorite={setUserFavorite} setIsFavorite={setUserFavorite}
collection_count={data.release.collection_count}
/> />
</div> </div>
{data.release.status.name.toLowerCase() != "анонс" && ( {data.release.status && data.release.status.name.toLowerCase() != "анонс" && (
<div className="[grid-column:1] [grid-row:span_4]"> <div className="[grid-column:1] [grid-row:span_12]">
<ReleasePlayer id={props.id} /> <ReleasePlayer id={props.id} />
</div> </div>
)} )}
{data.release.status.name.toLowerCase() != "анонс" && ( {data.release.status && data.release.status.name.toLowerCase() != "анонс" && (
<div className="[grid-column:2]"> <div className="[grid-column:2]">
<ReleaseInfoRating <ReleaseInfoRating
release_id={props.id} release_id={props.id}
@ -111,14 +113,24 @@ export const ReleasePage = (props: any) => {
/> />
</div> </div>
)} )}
<div className="[grid-column:2] [grid-row:span_4]">
<InfoLists
completed={data.release.completed_count}
planned={data.release.plan_count}
abandoned={data.release.dropped_count}
delayed={data.release.hold_on_count}
watching={data.release.watching_count}
/>
</div>
{data.release.screenshot_images.length > 0 && ( {data.release.screenshot_images.length > 0 && (
<div className="[grid-column:2]"> <div className="[grid-column:2] [grid-row:span_11]">
<ReleaseInfoScreenshots images={data.release.screenshot_images} /> <ReleaseInfoScreenshots images={data.release.screenshot_images} />
</div> </div>
)} )}
{data.release.related_releases.length > 0 && ( {data.release.related_releases.length > 0 && (
<div className="[grid-column:2] [grid-row:span_4]"> <div className="[grid-column:2] [grid-row:span_2]">
<ReleaseInfoRelated <ReleaseInfoRelated
release_id={props.id} release_id={props.id}
related={data.release.related} related={data.release.related}
@ -127,7 +139,7 @@ export const ReleasePage = (props: any) => {
</div> </div>
)} )}
<div className="[grid-column:1] [grid-row:span_2]"> <div className="[grid-column:1] [grid-row:span_32]">
<CommentsMain <CommentsMain
release_id={props.id} release_id={props.id}
token={token} token={token}

View file

@ -5,13 +5,12 @@ import { Spinner } from "#/components/Spinner/Spinner";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useScrollPosition } from "#/hooks/useScrollPosition"; import { useScrollPosition } from "#/hooks/useScrollPosition";
import { useUserStore } from "../store/auth"; import { useUserStore } from "../store/auth";
import { Button, Card } from "flowbite-react";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { ReleaseSection } from "#/components/ReleaseSection/ReleaseSection"; import { ReleaseSection } from "#/components/ReleaseSection/ReleaseSection";
import { CollectionInfoBasics } from "#/components/CollectionInfo/CollectionInfo.Basics"; import { CollectionInfoBasics } from "#/components/CollectionInfo/CollectionInfo.Basics";
import { CollectionInfoLists } from "#/components/CollectionInfo/CollectionInfoLists"; import { InfoLists } from "#/components/InfoLists/InfoLists";
import { CollectionInfoControls } from "#/components/CollectionInfo/CollectionInfoControls"; import { CollectionInfoControls } from "#/components/CollectionInfo/CollectionInfoControls";
const fetcher = async (url: string) => { const fetcher = async (url: string) => {
@ -101,7 +100,7 @@ export const ViewCollectionPage = (props: { id: number }) => {
/> />
{userStore.token && !isLoading && ( {userStore.token && !isLoading && (
<div className="flex flex-col gap-4 w-full max-w-full lg:max-w-[48%]"> <div className="flex flex-col gap-4 w-full max-w-full lg:max-w-[48%]">
<CollectionInfoLists <InfoLists
completed={collectionInfo.completed_count} completed={collectionInfo.completed_count}
planned={collectionInfo.plan_count} planned={collectionInfo.plan_count}
abandoned={collectionInfo.dropped_count} abandoned={collectionInfo.dropped_count}