refactor: fetcher -> useSWRfetcher (Search, CreateCollection Search Modal)

This commit is contained in:
Kentai Radiquum 2025-03-20 22:35:28 +05:00
parent 92f6725b21
commit f9ba62d525
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
2 changed files with 79 additions and 97 deletions

View file

@ -18,19 +18,8 @@ import { ReleaseLink } from "#/components/ReleaseLink/ReleaseLink";
import { CropModal } from "#/components/CropModal/CropModal";
import { b64toBlob } from "#/api/utils";
const fetcher = async (url: string) => {
const res = await fetch(url);
if (!res.ok) {
const error = new Error(
`An error occurred while fetching the data. status: ${res.status}`
);
error.message = await res.json();
throw error;
}
return res.json();
};
import { useSWRfetcher } from "#/api/utils";
import { Spinner } from "#/components/Spinner/Spinner";
export const CreateCollectionPage = () => {
const userStore = useUserStore();
@ -150,9 +139,9 @@ export const CreateCollectionPage = () => {
async function _createCollection() {
const url =
mode === "edit"
? `${ENDPOINTS.collection.edit}/${collection_id}?token=${userStore.token}`
: `${ENDPOINTS.collection.create}?token=${userStore.token}`;
mode === "edit" ?
`${ENDPOINTS.collection.edit}/${collection_id}?token=${userStore.token}`
: `${ENDPOINTS.collection.create}?token=${userStore.token}`;
const res = await fetch(url, {
method: "POST",
@ -239,39 +228,42 @@ export const CreateCollectionPage = () => {
className="flex flex-col items-center w-full sm:max-w-[600px] h-[337px] border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 dark:border-gray-600 dark:bg-gray-700 dark:hover:border-gray-500 dark:hover:bg-gray-600"
>
<div className="flex flex-col items-center justify-center max-w-[595px] h-[inherit] rounded-[inherit] pt-5 pb-6 overflow-hidden">
{!imageUrl ? (
<>
<svg
className="w-8 h-8 mb-4 text-gray-500 dark:text-gray-400"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 20 16"
>
<path
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2"
/>
</svg>
<p className="mb-2 text-sm text-gray-500 dark:text-gray-400">
<span className="font-semibold">Нажмите для загрузки</span>{" "}
или перетащите файл
</p>
<p className="text-xs text-gray-500 dark:text-gray-400">
PNG или JPG (Макс. 600x337 пикселей)
</p>
</>
) : (
// eslint-disable-next-line @next/next/no-img-element
<img
src={imageUrl}
className="object-cover w-[inherit] h-[inherit]"
alt=""
/>
)}
{
!imageUrl ?
<>
<svg
className="w-8 h-8 mb-4 text-gray-500 dark:text-gray-400"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 20 16"
>
<path
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2"
/>
</svg>
<p className="mb-2 text-sm text-gray-500 dark:text-gray-400">
<span className="font-semibold">
Нажмите для загрузки
</span>{" "}
или перетащите файл
</p>
<p className="text-xs text-gray-500 dark:text-gray-400">
PNG или JPG (Макс. 600x337 пикселей)
</p>
</>
// eslint-disable-next-line @next/next/no-img-element
: <img
src={imageUrl}
className="object-cover w-[inherit] h-[inherit]"
alt=""
/>
}
</div>
<FileInput
id="dropzone-file"
@ -428,7 +420,7 @@ export const ReleasesEditModal = (props: {
const { data, error, isLoading, size, setSize } = useSWRInfinite(
getKey,
fetcher,
useSWRfetcher,
{ initialSize: 2, revalidateFirstPage: false }
);
@ -554,6 +546,8 @@ export const ReleasesEditModal = (props: {
{content.length == 1 && <div></div>}
</div>
</div>
{isLoading && <Spinner />}
{error && <div>Произошла ошибка</div>}
</Modal>
);
};

View file

@ -11,20 +11,7 @@ import { useUserStore } from "../store/auth";
import { Button, Dropdown, Modal } from "flowbite-react";
import { CollectionsSection } from "#/components/CollectionsSection/CollectionsSection";
import { UserSection } from "#/components/UserSection/UserSection";
const fetcher = async (url: string) => {
const res = await fetch(url);
if (!res.ok) {
const error = new Error(
`An error occurred while fetching the data. status: ${res.status}`
);
error.message = await res.json();
throw error;
}
return res.json();
};
import { useSWRfetcher } from "#/api/utils";
const ListsMapping = {
watching: {
@ -128,7 +115,7 @@ export function SearchPage() {
const { data, error, isLoading, size, setSize } = useSWRInfinite(
getKey,
fetcher,
useSWRfetcher,
{ initialSize: 2, revalidateFirstPage: false }
);
@ -174,7 +161,18 @@ export function SearchPage() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchVal]);
if (error) return <div>failed to load: {error.message}</div>;
if (error)
return (
<main className="flex items-center justify-center min-h-screen">
<div className="flex flex-col gap-2">
<h1 className="text-2xl font-bold">Ошибка</h1>
<p className="text-lg">
Произошла ошибка поиска. Попробуйте обновить страницу или зайдите
позже.
</p>
</div>
</main>
);
return (
<>
@ -237,39 +235,35 @@ export function SearchPage() {
</div>
<div className="mt-2">
{data && data[0].related && <RelatedSection {...data[0].related} />}
{content ? (
content.length > 0 ? (
{content ?
content.length > 0 ?
<>
{where == "collections" ? (
{where == "collections" ?
<CollectionsSection
sectionTitle="Найденные Коллекции"
content={content}
/>
) : where == "profiles" ? (
: where == "profiles" ?
<UserSection
sectionTitle="Найденные Пользователи"
content={content}
/>
) : (
<ReleaseSection
: <ReleaseSection
sectionTitle="Найденные релизы"
content={content}
/>
)}
}
</>
) : (
<div className="flex flex-col items-center justify-center min-w-full gap-4 mt-12 text-xl">
: <div className="flex flex-col items-center justify-center min-w-full gap-4 mt-12 text-xl">
<span className="w-24 h-24 iconify-color twemoji--crying-cat"></span>
<p>Странно, аниме не найдено, попробуйте другой запрос...</p>
</div>
)
) : (
isLoading && (
: isLoading && (
<div className="flex items-center justify-center min-w-full min-h-screen">
<Spinner />
</div>
)
)}
}
{!content && !isLoading && !query && (
<div className="flex flex-col items-center justify-center min-w-full gap-2 mt-12 text-xl">
<span className="w-16 h-16 iconify mdi--arrow-up animate-bounce"></span>
@ -277,11 +271,13 @@ export function SearchPage() {
</div>
)}
</div>
{data &&
data.length > 1 &&
(where == "releases"
? data[data.length - 1].releases.length == 25
: data[data.length - 1].content.length == 25) ? (
{(
data &&
data.length > 1 &&
(where == "releases" ?
data[data.length - 1].releases.length == 25
: data[data.length - 1].content.length == 25)
) ?
<Button
className="w-full"
color={"light"}
@ -292,9 +288,7 @@ export function SearchPage() {
<span className="text-lg">Загрузить ещё</span>
</div>
</Button>
) : (
""
)}
: ""}
<FiltersModal
isOpen={filtersModalOpen}
setIsOpen={setFiltersModalOpen}
@ -394,9 +388,7 @@ const FiltersModal = (props: {
</Dropdown>
</div>
</div>
{props.isAuth &&
where == "list" &&
ListsMapping.hasOwnProperty(list) ? (
{props.isAuth && where == "list" && ListsMapping.hasOwnProperty(list) ?
<div className="my-4">
<div className="flex items-center justify-between">
<p className="font-bold dark:text-white">Список</p>
@ -414,10 +406,8 @@ const FiltersModal = (props: {
</Dropdown>
</div>
</div>
) : (
""
)}
{!["profiles", "collections"].includes(where) ? (
: ""}
{!["profiles", "collections"].includes(where) ?
<div className="my-4">
<div className="flex items-center justify-between">
<p className="font-bold dark:text-white">Искать по</p>
@ -435,9 +425,7 @@ const FiltersModal = (props: {
</Dropdown>
</div>
</div>
) : (
""
)}
: ""}
</Modal.Body>
<Modal.Footer>
<div className="flex justify-end w-full gap-2">