mirror of
https://github.com/Radiquum/AniX.git
synced 2025-04-06 00:04:39 +00:00
frontend: add search & search history
This commit is contained in:
parent
6b88601417
commit
e3a79c6864
5 changed files with 145 additions and 17 deletions
|
@ -8,7 +8,7 @@ from modules.proxy import ENDPOINTS
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.post("", summary="Search for a release")
|
@router.get("", summary="Search for a release")
|
||||||
async def Search(request: Request, query: str, page: int = 0):
|
async def Search(request: Request, query: str, page: int = 0):
|
||||||
data = json.dumps({"query": query, "searchBy": 0})
|
data = json.dumps({"query": query, "searchBy": 0})
|
||||||
return await apiRequest(request, ENDPOINTS["search"], page, data=data)
|
return await apiRequest(request, ENDPOINTS["search"], page, data=data)
|
||||||
|
|
|
@ -3,10 +3,23 @@
|
||||||
import "beercss";
|
import "beercss";
|
||||||
import "material-dynamic-colors";
|
import "material-dynamic-colors";
|
||||||
import { NavigationRail } from "@/app/components/NavigationRail/NavigationRail";
|
import { NavigationRail } from "@/app/components/NavigationRail/NavigationRail";
|
||||||
import { setTheme, getTheme, setMode, getMode } from "./store/theme-store";
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { ColorPicker } from "@/app/components/ColorPicker/ColorPicker";
|
import { ColorPicker } from "@/app/components/ColorPicker/ColorPicker";
|
||||||
|
|
||||||
|
export function setMode(mode) {
|
||||||
|
localStorage.setItem("mode", mode);
|
||||||
|
}
|
||||||
|
export function getMode() {
|
||||||
|
return localStorage.getItem("mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setTheme(theme) {
|
||||||
|
localStorage.setItem("theme", theme);
|
||||||
|
}
|
||||||
|
export function getTheme() {
|
||||||
|
return localStorage.getItem("theme");
|
||||||
|
}
|
||||||
|
|
||||||
export const App = (props) => {
|
export const App = (props) => {
|
||||||
const [colorPicker, setColorPicker] = useState(false);
|
const [colorPicker, setColorPicker] = useState(false);
|
||||||
|
|
||||||
|
|
|
@ -7,4 +7,5 @@ export const endpoints = {
|
||||||
announce: `${API_URL}/index/announce`,
|
announce: `${API_URL}/index/announce`,
|
||||||
finished: `${API_URL}/index/finished`,
|
finished: `${API_URL}/index/finished`,
|
||||||
},
|
},
|
||||||
|
search: `${API_URL}/search`
|
||||||
};
|
};
|
129
frontend/app/search/page.js
Normal file
129
frontend/app/search/page.js
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { getData } from "@/app/api/api-utils";
|
||||||
|
import { endpoints } from "@/app/api/config";
|
||||||
|
import { useEffect, useState, useCallback } from "react";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { CardList } from "@/app/components/CardList/CardList";
|
||||||
|
import { useSearchParams } from "next/navigation";
|
||||||
|
|
||||||
|
export function saveSearches(search) {
|
||||||
|
localStorage.setItem("searches", search);
|
||||||
|
}
|
||||||
|
export function getSearches() {
|
||||||
|
return localStorage.getItem("searches");
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Search() {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const [releases, setReleases] = useState();
|
||||||
|
const [page, setPage] = useState(0);
|
||||||
|
const [query, setQuery] = useState("");
|
||||||
|
const [searches, setSearches] = useState(JSON.parse(getSearches()));
|
||||||
|
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const createQueryString = useCallback(
|
||||||
|
(name, value) => {
|
||||||
|
const params = new URLSearchParams(searchParams.toString());
|
||||||
|
params.set(name, value);
|
||||||
|
|
||||||
|
return params.toString();
|
||||||
|
},
|
||||||
|
[searchParams]
|
||||||
|
);
|
||||||
|
|
||||||
|
async function fetchData(query, page = 0) {
|
||||||
|
const url = `${endpoints.search}?query=${query}&page=${page}`;
|
||||||
|
const data = await getData(url);
|
||||||
|
|
||||||
|
// Handle initial load (page 0) or subsequent pagination
|
||||||
|
if (page === 0) {
|
||||||
|
setReleases(data.content);
|
||||||
|
} else {
|
||||||
|
setReleases([...releases, ...data.content]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (releases) {
|
||||||
|
fetchData(query, page); // Use fetchData for pagination
|
||||||
|
}
|
||||||
|
}, [page]);
|
||||||
|
|
||||||
|
const handleInput = (e) => {
|
||||||
|
setQuery(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
router.push(pathname + "?" + createQueryString("query", query));
|
||||||
|
setReleases(null);
|
||||||
|
setPage(0);
|
||||||
|
fetchData(query);
|
||||||
|
|
||||||
|
// save searches and update search history
|
||||||
|
if (!searches) {
|
||||||
|
setSearches([query]);
|
||||||
|
saveSearches(JSON.stringify([query]));
|
||||||
|
} else {
|
||||||
|
console.log(searches);
|
||||||
|
if (!searches.find((element) => element == query)) {
|
||||||
|
setSearches([query, ...searches.slice(0, 5)]);
|
||||||
|
saveSearches(JSON.stringify([query, ...searches.slice(0, 5)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<form className="field large prefix round fill" onSubmit={handleSubmit}>
|
||||||
|
<i className="front">search</i>
|
||||||
|
<input name="query" onInput={handleInput} value={query} />
|
||||||
|
<menu className="min" style={{ marginTop: "64px" }}>
|
||||||
|
{searches
|
||||||
|
? searches.map((item) => {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
key={item}
|
||||||
|
onClick={() => {
|
||||||
|
setQuery(item);
|
||||||
|
}}
|
||||||
|
className="row"
|
||||||
|
>
|
||||||
|
<i>history</i>
|
||||||
|
<div>{item}</div>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: ""}
|
||||||
|
</menu>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{releases ? (
|
||||||
|
<>
|
||||||
|
<div className="grid">
|
||||||
|
<CardList data={releases} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav className="large-margin center-align">
|
||||||
|
<button
|
||||||
|
className="large"
|
||||||
|
onClick={() => {
|
||||||
|
setPage(page + 1);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i>add</i>
|
||||||
|
<span>загрузить ещё</span>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
// <progress className="s1"></progress>
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
"use client";
|
|
||||||
export function setMode(mode) {
|
|
||||||
localStorage.setItem("mode", mode);
|
|
||||||
}
|
|
||||||
export function getMode() {
|
|
||||||
return localStorage.getItem("mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setTheme(theme) {
|
|
||||||
localStorage.setItem("theme", theme);
|
|
||||||
}
|
|
||||||
export function getTheme() {
|
|
||||||
return localStorage.getItem("theme");
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue