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 };
|
||||
|
||||
|
||||
@ -5,7 +5,8 @@ import { useRequest } from "ahooks";
|
||||
import type { ClubDetail } from "../types";
|
||||
import { MapType, openWebMapRaw } from "../utils/front";
|
||||
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 {
|
||||
clubId: string;
|
||||
@ -43,6 +44,7 @@ export const ClubSummary = (props: Props) => {
|
||||
},
|
||||
]
|
||||
}, [info]);
|
||||
const store = useClubStore();
|
||||
if (requestClubSummary.data === null) return null;
|
||||
return (
|
||||
<div style={{ width: '100%' }}>
|
||||
@ -52,7 +54,29 @@ export const ClubSummary = (props: Props) => {
|
||||
<Flex vertical align="center" justify="center">
|
||||
<ChangeBackground url={info?.img} />
|
||||
<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}>
|
||||
{noArticle ? null : (
|
||||
<Button icon={<NotificationOutlined />} onClick={() => setIsArticleOpen(true)}>查看公告</Button>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
export const clubs = [
|
||||
{
|
||||
name: '东华',
|
||||
name: '东华乒乓球俱乐部',
|
||||
clubId: '47',
|
||||
},
|
||||
];
|
||||
@ -1,17 +1,16 @@
|
||||
import { create } from "zustand";
|
||||
import { persist, createJSONStorage } from 'zustand/middleware';
|
||||
import type { ClubInfo } from "../types";
|
||||
|
||||
interface Store {
|
||||
clubs: ClubInfo[];
|
||||
add(club: ClubInfo): void;
|
||||
clubs: { id: string; name: string }[];
|
||||
add(club: { id: string; name: string }): void;
|
||||
unFav(id: string): void;
|
||||
isFav(id: string): boolean;
|
||||
}
|
||||
export const useClubStore = create(persist<Store>((set, get) => {
|
||||
return {
|
||||
clubs: [],
|
||||
add: (club: ClubInfo) => {
|
||||
add: (club: { id: string; name: string }) => {
|
||||
set({ clubs: [...get().clubs, club] });
|
||||
},
|
||||
unFav: (id: string) => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user