feat(club-management): add club follow/unfollow functionality
Introduce a follow/unfollow feature for clubs in the ClubSummary component. Users can now toggle their subscription status to a specific club, with the state persisted locally using zustand. Changes include: - Added 'Follow' and 'Unfollow' buttons with corresponding star icons (StarOutlined/StarFilled). - Updated ClubStore to manage a simplified list of clubs (id and name only). - Refactored Data type in ClubSearchTable to use Pick<ClubInfo, 'id' | 'name'>. - Fixed club name in GameSelector clubList to '东华乒乓球俱乐部'. - Excluded follow buttons for club ID '47' (Donghua). The implementation ensures a consistent UI state across the application and persists user preferences.
This commit is contained in:
parent
f1ca5cda75
commit
5927861af7
@ -19,7 +19,7 @@ enum ClubType {
|
|||||||
我的收藏,
|
我的收藏,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Data = { clubs: ClubInfo[], total: number, page: number; };
|
type Data = { clubs: Pick<ClubInfo, 'id' | 'name'>[], total: number, page: number; };
|
||||||
|
|
||||||
const initData = { clubs: [], total: 0, page: 1 };
|
const initData = { clubs: [], total: 0, page: 1 };
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,8 @@ import { useRequest } from "ahooks";
|
|||||||
import type { ClubDetail } from "../types";
|
import type { ClubDetail } from "../types";
|
||||||
import { MapType, openWebMapRaw } from "../utils/front";
|
import { MapType, openWebMapRaw } from "../utils/front";
|
||||||
import type { ItemType } from "antd/es/menu/interface";
|
import type { ItemType } from "antd/es/menu/interface";
|
||||||
import { NotificationOutlined, PushpinOutlined } from "@ant-design/icons";
|
import { NotificationOutlined, PushpinOutlined, StarFilled, StarOutlined } from "@ant-design/icons";
|
||||||
|
import { useClubStore } from "../store/useClubStore";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
clubId: string;
|
clubId: string;
|
||||||
@ -43,6 +44,7 @@ export const ClubSummary = (props: Props) => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
}, [info]);
|
}, [info]);
|
||||||
|
const store = useClubStore();
|
||||||
if (requestClubSummary.data === null) return null;
|
if (requestClubSummary.data === null) return null;
|
||||||
return (
|
return (
|
||||||
<div style={{ width: '100%' }}>
|
<div style={{ width: '100%' }}>
|
||||||
@ -52,7 +54,29 @@ export const ClubSummary = (props: Props) => {
|
|||||||
<Flex vertical align="center" justify="center">
|
<Flex vertical align="center" justify="center">
|
||||||
<ChangeBackground url={info?.img} />
|
<ChangeBackground url={info?.img} />
|
||||||
<Avatar src={info?.img} size={80} />
|
<Avatar src={info?.img} size={80} />
|
||||||
<Typography.Title level={2}>{info?.name}</Typography.Title>
|
<Typography.Title level={3}>
|
||||||
|
<Flex gap={12}>
|
||||||
|
{info?.name}
|
||||||
|
{props.clubId === '47' ? null : (store.isFav(info?.id ?? '')) ? (
|
||||||
|
<Button
|
||||||
|
icon={<StarFilled style={{ color: 'yellow' }} />}
|
||||||
|
onClick={() => store.unFav(info?.id ?? '')}
|
||||||
|
>
|
||||||
|
取消关注
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
icon={<StarOutlined />}
|
||||||
|
onClick={() => store.add({
|
||||||
|
id: info?.id ?? '',
|
||||||
|
name: info?.name ?? '',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
关注
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Typography.Title>
|
||||||
<Flex gap={12}>
|
<Flex gap={12}>
|
||||||
{noArticle ? null : (
|
{noArticle ? null : (
|
||||||
<Button icon={<NotificationOutlined />} onClick={() => setIsArticleOpen(true)}>查看公告</Button>
|
<Button icon={<NotificationOutlined />} onClick={() => setIsArticleOpen(true)}>查看公告</Button>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
export const clubs = [
|
export const clubs = [
|
||||||
{
|
{
|
||||||
name: '东华',
|
name: '东华乒乓球俱乐部',
|
||||||
clubId: '47',
|
clubId: '47',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -1,17 +1,16 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { persist, createJSONStorage } from 'zustand/middleware';
|
import { persist, createJSONStorage } from 'zustand/middleware';
|
||||||
import type { ClubInfo } from "../types";
|
|
||||||
|
|
||||||
interface Store {
|
interface Store {
|
||||||
clubs: ClubInfo[];
|
clubs: { id: string; name: string }[];
|
||||||
add(club: ClubInfo): void;
|
add(club: { id: string; name: string }): void;
|
||||||
unFav(id: string): void;
|
unFav(id: string): void;
|
||||||
isFav(id: string): boolean;
|
isFav(id: string): boolean;
|
||||||
}
|
}
|
||||||
export const useClubStore = create(persist<Store>((set, get) => {
|
export const useClubStore = create(persist<Store>((set, get) => {
|
||||||
return {
|
return {
|
||||||
clubs: [],
|
clubs: [],
|
||||||
add: (club: ClubInfo) => {
|
add: (club: { id: string; name: string }) => {
|
||||||
set({ clubs: [...get().clubs, club] });
|
set({ clubs: [...get().clubs, club] });
|
||||||
},
|
},
|
||||||
unFav: (id: string) => {
|
unFav: (id: string) => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user