diff --git a/src/app/me/page.tsx b/src/app/me/page.tsx index e89b226..c02bce9 100644 --- a/src/app/me/page.tsx +++ b/src/app/me/page.tsx @@ -12,7 +12,6 @@ import { Cookies, useCookies } from 'next-client-cookies'; import { Bandage, Role } from '@/app/interfaces'; import { Me } from '@/app/modules/components/me.module'; import Link from 'next/link'; -import axios from 'axios'; import { SimpleGrid } from '@/app/modules/components/adaptiveGrid.module'; import style_workshop from "@/app/styles/workshop/page.module.css"; @@ -116,11 +115,7 @@ const Login = () => { }) useEffect(() => { - axios.get(process.env.NEXT_PUBLIC_API_URL + `auth/roles`).then((response) => { - if (response.status === 200) { - setRoles(response.data); - } - }) + ApiManager.getRoles().then(setRoles); }, []) return ( diff --git a/src/app/modules/components/nick_search.module.tsx b/src/app/modules/components/nick_search.module.tsx index 41bb33a..23bec5b 100644 --- a/src/app/modules/components/nick_search.module.tsx +++ b/src/app/modules/components/nick_search.module.tsx @@ -1,10 +1,10 @@ import Select, { GroupBase } from 'react-select'; import * as Interfaces from "@/app/interfaces"; import { useState } from 'react'; -import axios from 'axios'; import Style from "@/app/styles/nick_search.module.css"; +import ApiManager from '../utils/apiManager'; -interface SearchResponse { +export interface SearchResponse { status: string; requestedFragment: string; data: { @@ -46,9 +46,10 @@ const Searcher = ({ onChange }: SearchProps) => { if (nickname.length > 2) { setLoading(true); - axios.get(process.env.NEXT_PUBLIC_API_URL + "minecraft/search/" + nickname).then(response => { - if (response.status == 200) { - const response_data = response.data as SearchResponse; + ApiManager.searchNicks(nickname) + .then(response_data => { + if (!response_data.data) return; + const data = response_data.data.map(nick => { const first_pos = nick.name.toLowerCase().indexOf(nickname.toLowerCase()); const first = nick.name.slice(0, first_pos); @@ -67,16 +68,16 @@ const Searcher = ({ onChange }: SearchProps) => { }) setNicknames([ { - value: response.data.requestedFragment, - label: {response.data.requestedFragment} + value: response_data.requestedFragment, + label: {response_data.requestedFragment} }, { label: <>Совпадения, options: data } ]); - } - }).finally(() => setLoading(false)) + }) + .finally(() => setLoading(false)); } } diff --git a/src/app/modules/utils/apiManager.ts b/src/app/modules/utils/apiManager.ts index 806458d..3b05f60 100644 --- a/src/app/modules/utils/apiManager.ts +++ b/src/app/modules/utils/apiManager.ts @@ -1,8 +1,9 @@ import * as Interfaces from "@/app/interfaces"; import { authApi } from "./api.module"; -import { AxiosResponse, Method } from "axios"; +import axios, { AxiosResponse, Method } from "axios"; import { Query } from "../components/header.module"; import { SettingsResponse } from "@/app/me/settings/page"; +import { SearchResponse } from "../components/nick_search.module"; type RequestProps = { url: string, @@ -30,9 +31,30 @@ class ApiManager { return response; } + /* Do HTTP simple */ + private static async doRequestSimple({ + url, + method, + data, + params + }: RequestProps): Promise> { + const response = await axios.request({ + url: process.env.NEXT_PUBLIC_API_URL.slice(0, -1) + url, + method, + data, + params, + withCredentials: true + }); + if (response.status >= 400) + throw response; + + return response; + } + + /* Get Categories */ static async getCategories(forEdit?: boolean): Promise { - return (await this.doRequest({ + return (await this.doRequestSimple({ url: '/categories', method: 'GET', params: { for_edit: forEdit ?? false } @@ -175,6 +197,22 @@ class ApiManager { }); } + /* Search Minecraft nicks */ + static async searchNicks(nickname: string): Promise { + return (await this.doRequestSimple({ + url: `/minecraft/search/${nickname}`, + method: 'GET' + })).data; + } + + /* Get Minecraft skin */ + static async getSkin(nickname: string): Promise { + return (await this.doRequestSimple({ + url: `/minecraft/skin/${nickname}?cape=true`, + method: 'GET' + })); + } + /* Get sessions */ static async getSessions(): Promise { return (await this.doRequest({ @@ -251,6 +289,32 @@ class ApiManager { data }); } + + + /* Get registration roles */ + static async getRoles(): Promise { + return (await this.doRequestSimple({ + url: `/auth/roles`, + method: 'GET' + })).data; + } + + /* Get registration roles */ + static async getWorkshop( + params: { + page: number, + take: number, + search: string, + filters: string, + sort: string + } + ): Promise { + return (await this.doRequestSimple({ + url: `/workshop`, + method: 'GET', + params + })).data; + } } export default ApiManager; \ No newline at end of file diff --git a/src/app/tutorials/page.tsx b/src/app/tutorials/page.tsx index d08eb2c..0f10d74 100644 --- a/src/app/tutorials/page.tsx +++ b/src/app/tutorials/page.tsx @@ -6,28 +6,23 @@ import React, { useEffect, useState } from "react"; import style from '@/app/styles/tutorials/common.module.css'; import ASide from "./header.module"; import InfoCard from "@/app/modules/components/info.module"; -import NextImage from "next/image"; import { CategoryEl } from "@/app/modules/components/card.module"; import { CustomLink } from "@/app/modules/components/search.module"; import styles from "@/app/styles/me/me.module.css"; import { Tooltip } from "@/app/modules/components/tooltip"; -import axios from "axios"; import { Role } from "@/app/interfaces"; import style_workshop from "@/app/styles/workshop/page.module.css"; import { IconInfoCircle, IconAlertTriangle, IconBulb } from '@tabler/icons-react'; import IconSvg from '@/app/resources/icon.svg'; import Link from "next/link"; +import ApiManager from "../modules/utils/apiManager"; export default function Home() { const [roles, setRoles] = useState([]); useEffect(() => { - axios.get(process.env.NEXT_PUBLIC_API_URL + `auth/roles`).then((response) => { - if (response.status === 200) { - setRoles(response.data); - } - }) + ApiManager.getRoles().then(setRoles); }, []) const roles_data = roles.map((role) => { diff --git a/src/app/workshop/[id]/bandage_engine.module.ts b/src/app/workshop/[id]/bandage_engine.module.ts index 69e812b..bbbcafe 100644 --- a/src/app/workshop/[id]/bandage_engine.module.ts +++ b/src/app/workshop/[id]/bandage_engine.module.ts @@ -1,4 +1,5 @@ import asyncImage from '@/app/modules/components/asyncImage.module'; +import ApiManager from '@/app/modules/utils/apiManager'; import axios from 'axios'; interface SkinResponse { @@ -82,13 +83,10 @@ class Client { async loadSkin(nickname: string): Promise { - if (!nickname) { - return; - } - const response = await axios.get(process.env.NEXT_PUBLIC_API_URL + `minecraft/skin/${nickname}?cape=true`, { validateStatus: () => true }); - if (response.status !== 200) { - return; - } + if (!nickname) return; + + const response = await ApiManager.getSkin(nickname); + if (response.status !== 200) return; const data = response.data as SkinResponse; this.slim = data.data.skin.slim; diff --git a/src/app/workshop/[id]/skinLoad.module.tsx b/src/app/workshop/[id]/skinLoad.module.tsx index 0e9a3b7..7120379 100644 --- a/src/app/workshop/[id]/skinLoad.module.tsx +++ b/src/app/workshop/[id]/skinLoad.module.tsx @@ -1,10 +1,10 @@ import { IconCheck, IconX } from "@tabler/icons-react"; -import axios from "axios"; import { useState } from "react"; import NextImage from 'next/image'; import style from "@/app/styles/editor/page.module.css"; import AsyncImage from "@/app/modules/components/asyncImage.module"; import Searcher from "@/app/modules/components/nick_search.module"; +import ApiManager from "@/app/modules/utils/apiManager"; const b64Prefix = "data:image/png;base64,"; @@ -39,7 +39,8 @@ const SkinLoad = ({ onChange }: SkinLoadProps) => { if (!nickname) { return; } - axios.get(process.env.NEXT_PUBLIC_API_URL + `minecraft/skin/${nickname}?cape=true`, { validateStatus: () => true }).then((response) => { + + ApiManager.getSkin(nickname).then(response => { if (response.status !== 200) { switch (response.status) { case 404: diff --git a/src/app/workshop/page.tsx b/src/app/workshop/page.tsx index ffe66e1..94f7057 100644 --- a/src/app/workshop/page.tsx +++ b/src/app/workshop/page.tsx @@ -5,7 +5,6 @@ import { useEffect, useState } from "react"; import Header from "@/app/modules/components/header.module"; import Style from "@/app/styles/workshop/page.module.css"; -import axios, { AxiosRequestConfig } from "axios"; import { Paginator } from "@/app/modules/components/paginator.module"; import { Search } from "@/app/modules/components/search.module"; import { BandageResponse, Category } from "@/app/interfaces"; @@ -30,11 +29,11 @@ export default function Home() { const [take, setTake] = useState(12); const [search, setSearch] = useState(''); - const [lastConfig, setLastConfig] = useState>(null); + const [lastConfig, setLastConfig] = useState(null); const [categories, setCategories] = useState([]); const [filters, setFilters] = useState([]); - const [sort, setSort] = useState('popular_up'); + const [sort, setSort] = useState('popular_up'); const [alertShown, setAlertShown] = useState(false); @@ -45,26 +44,22 @@ export default function Home() { useEffect(() => { const filters_str = filters.filter(filter => filter.enabled).map(filter => filter.id).toString(); - const config: AxiosRequestConfig = { - params: { - page: constrain(page, 0, Math.ceil(totalCount / take)), - take: take, - search: search || undefined, - filters: filters_str || undefined, - sort: sort || undefined - } + const config = { + page: constrain(page, 0, Math.ceil(totalCount / take)), + take: take, + search: search || undefined, + filters: filters_str || undefined, + sort: sort || undefined } if (JSON.stringify(config) === JSON.stringify(lastConfig)) { return; } - axios.get(process.env.NEXT_PUBLIC_API_URL + 'workshop', { withCredentials: true, ...config }).then((response) => { - if (response.status == 200) { - const data = response.data as BandageResponse; - setData(data); - setTotalCount(data.totalCount); - } + ApiManager.getWorkshop(config).then(data => { + setData(data); + setTotalCount(data.totalCount); }); + setLastConfig(config); }, [page, search, take, filters, sort])