refact(app): FindUserPage

This commit is contained in:
kyuuseiryuu 2026-02-10 18:14:55 +09:00
parent 5d668b2078
commit b300d874d2
4 changed files with 23 additions and 27 deletions

View File

@ -2,20 +2,20 @@ import { useCallback } from "react";
import { ClubSelector } from "./components/GameSelector"; import { ClubSelector } from "./components/GameSelector";
import type { IEventInfo } from "./types"; import type { IEventInfo } from "./types";
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
import { FloatButton, Typography } from "antd";
import { SearchOutlined } from "@ant-design/icons";
import "./index.css"; import "./index.css";
import { FindUserButton } from "./components/FindUser";
export function App() { export function App() {
const navigate = useNavigate(); const navigate = useNavigate();
const handleGameClick = useCallback(async (game: IEventInfo) => { const handleGameClick = useCallback(async (game: IEventInfo) => {
navigate(`/event/${game.matchId}`); navigate(`/event/${game.matchId}`);
}, []); }, []);
return ( return (
<div className="app"> <div className="app">
<h1></h1> <Typography.Title level={1}></Typography.Title>
<ClubSelector onGameClick={handleGameClick} /> <ClubSelector onGameClick={handleGameClick} />
<FindUserButton /> <FloatButton icon={<SearchOutlined />} onClick={() => navigate('/find')} />
</div> </div>
); );
} }

View File

@ -14,6 +14,7 @@ import { createBrowserRouter, RouterProvider, Outlet, useNavigation } from "reac
import ProfilePage from "./page/ProfilePage"; import ProfilePage from "./page/ProfilePage";
import EventPage from "./page/EventPage"; import EventPage from "./page/EventPage";
import type { MatchInfo, XCXMember } from "./types"; import type { MatchInfo, XCXMember } from "./types";
import { FindUserPage } from "./page/FindUserPage";
const elem = document.getElementById("root")!; const elem = document.getElementById("root")!;
@ -58,6 +59,10 @@ const route = createBrowserRouter([
}, },
], ],
}, },
{
path: 'find',
Component: FindUserPage,
}
]); ]);
function HydrateFallback() { function HydrateFallback() {

View File

@ -1,32 +1,21 @@
import { SearchOutlined } from "@ant-design/icons";
import { useLocalStorageState, useRequest } from "ahooks"; import { useLocalStorageState, useRequest } from "ahooks";
import { FloatButton, Drawer, Input, Table } from "antd"; import { Input, Table, Spin, Typography, Flex, Space } from "antd";
import { useState } from "react"; import type { XCXFindUser, XCXFindUserResp } from "../types";
import type { XCXFindUser, XCXFindUserResp } from "../../types"; import User from "../components/User";
import User from "../User"; import { SEX } from "../utils";
import { SEX } from "../../utils";
import dayjs from "dayjs"; import dayjs from "dayjs";
export function FindUserButton() { export function FindUserPage() {
const [open, setOpen] = useState(false);
const [searchKey, setSearchKey] = useLocalStorageState<string>('findUser:searchKey'); const [searchKey, setSearchKey] = useLocalStorageState<string>('findUser:searchKey');
const findUserReq = useRequest(async (page: number = 1) => { const findUserReq = useRequest(async (page: number = 1) => {
const findOutUsers: XCXFindUserResp = await (await fetch(`/api/user/find?page=${page}&key=${searchKey}`)).json(); const findOutUsers: XCXFindUserResp = await (await fetch(`/api/user/find?page=${page}&key=${searchKey}`)).json();
return findOutUsers; return findOutUsers;
}, { manual: true, refreshDeps: [searchKey], cacheKey: 'findUser:result' }); }, { manual: true, refreshDeps: [searchKey], cacheKey: 'findUser:result' });
return ( return (
<> <div className="app">
<FloatButton <Typography.Title level={1}></Typography.Title>
icon={<SearchOutlined />} <Spin spinning={findUserReq.loading}>
onClick={() => setOpen(true)} <Flex vertical gap={48} align="center">
/>
<Drawer
placement="bottom"
open={open}
onClose={() => setOpen(false)}
loading={findUserReq.loading}
size="80vh"
>
<Input.Search <Input.Search
allowClear allowClear
size="large" size="large"
@ -37,6 +26,7 @@ export function FindUserButton() {
/> />
<Table <Table
size="small" size="small"
style={{ width: '100%' }}
rowKey={e => e.uid} rowKey={e => e.uid}
dataSource={findUserReq.data?.data} dataSource={findUserReq.data?.data}
pagination={{ pagination={{
@ -64,7 +54,8 @@ export function FindUserButton() {
<Table.Column align="center" title="性别" dataIndex={'sex'} render={sex => SEX[sex]} /> <Table.Column align="center" title="性别" dataIndex={'sex'} render={sex => SEX[sex]} />
<Table.Column align="center" title="年龄" dataIndex={'birthyear'} render={year => year !== '0' ? dayjs().diff(dayjs(year), 'year') : '-'} /> <Table.Column align="center" title="年龄" dataIndex={'birthyear'} render={year => year !== '0' ? dayjs().diff(dayjs(year), 'year') : '-'} />
</Table> </Table>
</Drawer> </Flex>
</> </Spin>
</div>
); );
} }

View File

@ -52,7 +52,7 @@ export class XCXAPI {
return (await this.#fetch<{ data: GamesData[] }>(url))?.data; return (await this.#fetch<{ data: GamesData[] }>(url))?.data;
} }
async findUser(key: string = '', page: number = 1) { async findUser(key: string = '', page: number = 1) {
if (!key) return; if (!key) return null;
const url = `/api/user/lists?page=${page}&key=${key}`; const url = `/api/user/lists?page=${page}&key=${key}`;
return (await this.#fetch<XCXFindUserResp>(url)); return (await this.#fetch<XCXFindUserResp>(url));
} }