diff --git a/src/App.tsx b/src/App.tsx
index 83e6d54..7b0af1c 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -2,8 +2,7 @@ import { useCallback } from "react";
import { ClubSelector } from "./components/GameSelector";
import type { IEventInfo } from "./types";
import { useNavigate } from "react-router";
-import { FloatButton, Typography } from "antd";
-import { SearchOutlined } from "@ant-design/icons";
+import { Typography } from "antd";
import "./index.css";
export function App() {
@@ -15,7 +14,6 @@ export function App() {
开球网比赛分组预测
- } onClick={() => navigate('/find')} />
);
}
diff --git a/src/components/FavButton.tsx b/src/components/FavButton.tsx
new file mode 100644
index 0000000..96bd29c
--- /dev/null
+++ b/src/components/FavButton.tsx
@@ -0,0 +1,38 @@
+import { Rate } from "antd";
+import { useCallback, useState } from "react";
+import { useFavPlayerStore, type FavPlayer } from "../store/useFavPlayerStore";
+import styled from "styled-components";
+
+interface Props {
+ user?: FavPlayer;
+}
+
+const StyledContainer = styled.div`
+ display: flex;
+ align-items: center;
+ .ant-rate {
+ margin: 0;
+ .ant-rate-star {
+ margin: 0;
+ }
+ }
+`;
+
+export function FavButton(props: Props) {
+ const favStore = useFavPlayerStore(state => state);
+ const [value, setValue] = useState(favStore.isFav(props.user?.uid) ? 1 : 0);
+ const handleFavClick = useCallback((value: number) => {
+ if (!props.user) return;
+ setValue(value);
+ if (value) {
+ favStore.fav(props.user);
+ } else {
+ favStore.unFav(props.user.uid);
+ }
+ }, [favStore]);
+ return (
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/MenuButtons.tsx b/src/components/MenuButtons.tsx
new file mode 100644
index 0000000..62bded1
--- /dev/null
+++ b/src/components/MenuButtons.tsx
@@ -0,0 +1,15 @@
+import { ArrowLeftOutlined, HeartOutlined, MenuOutlined, ScheduleOutlined, SearchOutlined } from "@ant-design/icons";
+import { FloatButton } from "antd";
+import { useNavigate } from "react-router";
+
+export function MenuButtons() {
+ const navigate = useNavigate();
+ return (
+ }>
+ } onClick={() => navigate('/')} />
+ } onClick={() => navigate('/fav-players')} />
+ } onClick={() => navigate('/find')} />
+ } onClick={() => navigate(-1)} />
+
+ );
+}
\ No newline at end of file
diff --git a/src/frontend.tsx b/src/frontend.tsx
index 70f1a9f..f4bae4e 100644
--- a/src/frontend.tsx
+++ b/src/frontend.tsx
@@ -15,6 +15,8 @@ import ProfilePage from "./page/ProfilePage";
import EventPage from "./page/EventPage";
import type { MatchInfo, XCXMember } from "./types";
import { FindUserPage } from "./page/FindUserPage";
+import { FavePlayersPage } from "./page/FavPlayersPage";
+import { MenuButtons } from "./components/MenuButtons";
const elem = document.getElementById("root")!;
@@ -26,9 +28,13 @@ const route = createBrowserRouter([
{
path: '',
index: true,
- element: ,
+ Component: App,
HydrateFallback: () =>
},
+ {
+ path: '/fav-players',
+ Component: FavePlayersPage,
+ },
{
path: 'event/:matchId',
loader: async ({ params }) => {
@@ -57,12 +63,12 @@ const route = createBrowserRouter([
Component: ProfilePage,
HydrateFallback: () =>
},
+ {
+ path: 'find',
+ Component: FindUserPage,
+ }
],
},
- {
- path: 'find',
- Component: FindUserPage,
- }
]);
function HydrateFallback() {
@@ -76,7 +82,10 @@ function HydrateFallback() {
function Layout() {
const navigation = useNavigation();
const loading = navigation.state === 'loading';
- return loading ? :
+ return loading ? : (<>
+
+
+ >);
}
const app = (
diff --git a/src/index.html b/src/index.html
index f4d5805..3d6c0a1 100644
--- a/src/index.html
+++ b/src/index.html
@@ -5,7 +5,7 @@
- 开球网比赛分组预测
+ 我的开球网
diff --git a/src/page/FavPlayersPage.tsx b/src/page/FavPlayersPage.tsx
new file mode 100644
index 0000000..91c5341
--- /dev/null
+++ b/src/page/FavPlayersPage.tsx
@@ -0,0 +1,72 @@
+import { Avatar, Card, Divider, Flex, Image, Segmented, Space, Typography } from "antd";
+import { useFavPlayerStore } from "../store/useFavPlayerStore";
+import { useNavigate } from "react-router";
+import { useMemo, useState } from "react";
+
+enum SortType {
+ DEFAULT = '默认排序',
+ SCORE_UP = '积分升序',
+ SCORE_DOWN = '积分降序',
+}
+
+export function FavePlayersPage() {
+ const { favMap } = useFavPlayerStore(state => state);
+ const [sortType, setSortType] = useState(SortType.SCORE_DOWN);
+ const list = useMemo(() => {
+ const l = Object.values(favMap);
+ switch (sortType) {
+ case SortType.DEFAULT: return l;
+ case SortType.SCORE_UP: return l.sort(({ score: a }, { score: b }) => +a - +b);
+ case SortType.SCORE_DOWN: return l.sort(({ score: b }, { score: a }) => +a - +b);
+ default: return l;
+ }
+ }, [favMap, sortType]);
+ const navigate = useNavigate();
+ return (
+
+
+ 收藏的球员
+
+ setSortType(e)}
+ options={[
+ SortType.SCORE_DOWN,
+ SortType.SCORE_UP,
+ ]}
+ />
+
+ {list.length === 0 ? (
+ 暂无收藏的球员
+ ) : (
+
+ {list.map(e => (
+
+
+ {e.avatar?.includes('noavatar') ? {e.name} : }
+ navigate(`/profile/${e.uid}`)}
+ >
+ {e.name}
+ {e.realname}
+
+
+
+ ))}
+
+ )}
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/page/ProfilePage.tsx b/src/page/ProfilePage.tsx
index caa1223..7a0e40a 100644
--- a/src/page/ProfilePage.tsx
+++ b/src/page/ProfilePage.tsx
@@ -9,6 +9,7 @@ import { ChangeBackground } from "../components/ChangeBackground";
import UserTags from "../components/Tags";
import { GameTable } from "../components/GameTable";
import { useTitle } from "ahooks";
+import { FavButton } from "../components/FavButton";
function Honor(props: { honors?: XCXProfile['honors'] }) {
if (!props.honors?.length) return null;
@@ -96,7 +97,20 @@ export default function ProfilePage() {
} onClick={() => navigate('/')} />
- {profile?.username}
+
+
+ {profile?.username}
+
+
+
姓名:{profile?.realname}
积分:{profile?.score}
diff --git a/src/store/useFavPlayerStore.ts b/src/store/useFavPlayerStore.ts
new file mode 100644
index 0000000..f0a33ff
--- /dev/null
+++ b/src/store/useFavPlayerStore.ts
@@ -0,0 +1,33 @@
+import { create } from 'zustand';
+import { persist, createJSONStorage } from 'zustand/middleware';
+import type { BasePlayer } from '../types';
+
+export interface FavPlayer extends BasePlayer {
+ realname?: string;
+ avatar?: string;
+}
+
+interface FavPlayerStore {
+ favMap: Record;
+ fav(player: FavPlayer): void;
+ unFav(uid: string): void;
+ isFav(uid?: string): boolean;
+}
+
+export const useFavPlayerStore = create(persist((set, get) => ({
+ favMap: {},
+ fav: user => {
+ const { favMap } = get();
+ favMap[user.uid] = user;
+ set({ favMap: { ...favMap } });
+ },
+ unFav: uid => {
+ const { favMap } = get();
+ delete favMap[uid];
+ set({ favMap: { ...favMap } });
+ },
+ isFav(uid) {
+ if (!uid) return false;
+ return !!get().favMap[uid];
+ },
+}), { name: 'fav-player-store', storage: createJSONStorage(() => localStorage) }));
\ No newline at end of file