diff --git a/app/api/bookmarks/route.js b/app/api/bookmarks/route.js index 4a3537d..d53f467 100644 --- a/app/api/bookmarks/route.js +++ b/app/api/bookmarks/route.js @@ -1,6 +1,7 @@ import { NextResponse } from "next/server"; import { fetchDataViaGet } from "../utils"; import { ENDPOINTS } from "../config"; +import { sort } from "../common"; const list = { watching: 1, @@ -10,20 +11,12 @@ const list = { abandoned: 5, }; -const sort = { - adding_descending: 1, - adding_ascending: 2, - // year_descending: 3, - // year_ascending: 4, - alphabet_descending: 5, - alphabet_ascending: 6, -}; - export async function GET(request) { const page = parseInt(request.nextUrl.searchParams.get(["page"])) || 0; const listName = request.nextUrl.searchParams.get(["list"]) || null; const token = request.nextUrl.searchParams.get(["token"]) || null; - const sortName = request.nextUrl.searchParams.get(["sort"]) || "adding_descending"; + const sortName = + request.nextUrl.searchParams.get(["sort"]) || "adding_descending"; if (!token || token == "null") { return NextResponse.json({ message: "No token provided" }, { status: 403 }); diff --git a/app/api/common.js b/app/api/common.js new file mode 100644 index 0000000..c0ad6ad --- /dev/null +++ b/app/api/common.js @@ -0,0 +1,8 @@ +export const sort = { + adding_descending: 1, + adding_ascending: 2, + // year_descending: 3, + // year_ascending: 4, + alphabet_descending: 5, + alphabet_ascending: 6, +}; diff --git a/app/api/config.js b/app/api/config.js index 5348d98..6e65034 100644 --- a/app/api/config.js +++ b/app/api/config.js @@ -11,7 +11,7 @@ export const ENDPOINTS = { profile: `${API_URL}/profile`, bookmark: `${API_URL}/profile/list/all`, history: `${API_URL}/history`, - favorite: `${API_URL}/favorite`, + favorite: `${API_URL}/favorite/all`, }, filter: `${API_URL}/filter`, auth: `${API_URL}/auth/signIn`, diff --git a/app/api/favorites/route.js b/app/api/favorites/route.js new file mode 100644 index 0000000..b241b82 --- /dev/null +++ b/app/api/favorites/route.js @@ -0,0 +1,26 @@ +import { NextResponse } from "next/server"; +import { fetchDataViaGet } from "../utils"; +import { ENDPOINTS } from "../config"; +import { sort } from "../common"; + + +export async function GET(request) { + const page = parseInt(request.nextUrl.searchParams.get(["page"])) || 0; + const token = request.nextUrl.searchParams.get(["token"]) || null; + const sortName = request.nextUrl.searchParams.get(["sort"]) || "adding_descending"; + + if (!token || token == "null") { + return NextResponse.json({ message: "No token provided" }, { status: 403 }); + } + + if (!sort[sortName]) { + return NextResponse.json({ message: "Unknown sort" }, { status: 400 }); + } + + let url = new URL(`${ENDPOINTS.user.favorite}/${page}`); + url.searchParams.set("token", token); + url.searchParams.set("sort", sort[sortName]); + + const response = await fetchDataViaGet(url.toString()); + return NextResponse.json(response); +} diff --git a/app/api/mappings.js b/app/api/mappings.js deleted file mode 100644 index e69de29..0000000 diff --git a/app/bookmarks/page.js b/app/bookmarks/page.js index 5ed0070..dea39e9 100644 --- a/app/bookmarks/page.js +++ b/app/bookmarks/page.js @@ -1,5 +1,5 @@ export const metadata = { - title: "AniX | Закладки", + title: "Закладки", }; import { BookmarksPage } from "@/app/pages/Bookmarks"; diff --git a/app/favorites/page.js b/app/favorites/page.js new file mode 100644 index 0000000..a86a845 --- /dev/null +++ b/app/favorites/page.js @@ -0,0 +1,9 @@ +export const metadata = { + title: "Избранное", +}; + +import { FavoritesPage } from "@/app/pages/Favorites"; + +export default function Index() { + return ; +} diff --git a/app/pages/BookmarksCategory.jsx b/app/pages/BookmarksCategory.jsx index f6a5b9a..7161054 100644 --- a/app/pages/BookmarksCategory.jsx +++ b/app/pages/BookmarksCategory.jsx @@ -6,6 +6,7 @@ import { useState, useEffect } from "react"; import { useScrollPosition } from "@/app/hooks/useScrollPosition"; import { useUserStore } from "../store/auth"; import { Dropdown } from "flowbite-react"; +import { sort } from "./common"; const fetcher = async (url) => { const res = await fetch(url); @@ -20,29 +21,6 @@ const fetcher = async (url) => { return res.json(); }; -const sort = { - descendingIcon: "material-symbols--sort", - ascendingIcon: "[transform:rotateX(180deg)] material-symbols--sort", - values: [ - { - name: "Сначала новые", - value: "adding_descending", - }, - { - name: "Сначала старые", - value: "adding_ascending", - }, - { - name: "А-Я", - value: "alphabet_descending", - }, - { - name: "Я-А", - value: "alphabet_ascending", - }, - ], -}; - export function BookmarksCategoryPage(props) { const token = useUserStore((state) => state.token); const [selectedSort, setSelectedSort] = useState(0); @@ -56,7 +34,7 @@ export function BookmarksCategoryPage(props) { const { data, error, isLoading, size, setSize } = useSWRInfinite( getKey, fetcher, - { initialSize: 2, revalidateFirstPage: false } + { initialSize: 2 } ); const [content, setContent] = useState(null); diff --git a/app/pages/Favorites.jsx b/app/pages/Favorites.jsx new file mode 100644 index 0000000..b57807d --- /dev/null +++ b/app/pages/Favorites.jsx @@ -0,0 +1,105 @@ +"use client"; +import useSWRInfinite from "swr/infinite"; +import { ReleaseSection } from "@/app/components/ReleaseSection/ReleaseSection"; +import { Spinner } from "@/app/components/Spinner/Spinner"; +import { useState, useEffect } from "react"; +import { useScrollPosition } from "@/app/hooks/useScrollPosition"; +import { useUserStore } from "../store/auth"; +import { Dropdown } from "flowbite-react"; +import { sort } from "./common"; + +const fetcher = async (url) => { + const res = await fetch(url); + + if (!res.ok) { + const error = new Error("An error occurred while fetching the data."); + error.info = await res.json(); + error.status = res.status; + throw error; + } + + return res.json(); +}; + +export function FavoritesPage() { + const token = useUserStore((state) => state.token); + const [selectedSort, setSelectedSort] = useState(0); + const [isLoadingEnd, setIsLoadingEnd] = useState(false); + + const getKey = (pageIndex, previousPageData) => { + if (previousPageData && !previousPageData.content.length) return null; + return `/api/favorites?page=${pageIndex}&token=${token}&sort=${sort.values[selectedSort].value}`; + }; + + const { data, error, isLoading, size, setSize } = useSWRInfinite( + getKey, + fetcher, + { initialSize: 2 } + ); + + const [content, setContent] = useState(null); + useEffect(() => { + if (data) { + let allReleases = []; + for (let i = 0; i < data.length; i++) { + allReleases.push(...data[i].content); + } + setContent(allReleases); + setIsLoadingEnd(true); + } + }, [data]); + + const scrollPosition = useScrollPosition(); + useEffect(() => { + if (scrollPosition >= 98 && scrollPosition <= 99) { + setSize(size + 1); + } + }, [scrollPosition]); + + return ( + + + + Избранное + + + {sort.values.map((item, index) => ( + setSelectedSort(index)}> + + {item.name} + + ))} + + + {content && content.length > 0 ? ( + + ) : !isLoadingEnd || isLoading ? ( + + + + ) : ( + + + В избранном пока ничего нет... + + )} + {data && + data[data.length - 1].current_page < + data[data.length - 1].total_page_count && ( + setSize(size + 1)} + > + + Загрузить ещё + + )} + + ); +} diff --git a/app/pages/common.js b/app/pages/common.js new file mode 100644 index 0000000..e4245f9 --- /dev/null +++ b/app/pages/common.js @@ -0,0 +1,22 @@ +export const sort = { + descendingIcon: "material-symbols--sort", + ascendingIcon: "[transform:rotateX(180deg)] material-symbols--sort", + values: [ + { + name: "Сначала новые", + value: "adding_descending", + }, + { + name: "Сначала старые", + value: "adding_ascending", + }, + { + name: "А-Я", + value: "alphabet_descending", + }, + { + name: "Я-А", + value: "alphabet_ascending", + }, + ], +};
В избранном пока ничего нет...