Files
mini-programs/src/game_pages/detail/components/StickyBottom/index.tsx
2025-11-05 17:39:23 +08:00

311 lines
8.6 KiB
TypeScript

import { useEffect, useRef, useState } from "react";
import Taro from "@tarojs/taro";
import classnames from "classnames";
import dayjs from "dayjs";
import { Text, View, Image } from "@tarojs/components";
import OrderService from "@/services/orderService";
import { EvaluateCallback, EvaluateScene } from "@/store/evaluateStore";
import { MATCH_STATUS, IsSubstituteSupported } from "@/services/detailService";
import { GameManagePopup, NTRPEvaluatePopup } from "@/components";
import img from "@/config/images";
import RMB_ICON from "@/static/detail/rmb.svg";
import { toast, navto } from "../../utils/helper";
import styles from "./index.module.scss";
function isFull(counts) {
const {
max_players,
current_players,
max_substitute_players,
current_substitute_count,
is_substitute_supported,
} = counts;
if (max_players === current_players &&is_substitute_supported === IsSubstituteSupported.NOTSUPPORT) {
return true;
}
else if (max_players === current_players &&is_substitute_supported === IsSubstituteSupported.SUPPORT) {
return max_substitute_players === current_substitute_count;
}
return false;
}
// 底部操作栏
export default function StickyButton(props) {
const {
handleShare,
handleJoinGame,
detail,
onStatusChange,
handleAddComment,
getCommentCount,
} = props;
const [commentCount, setCommentCount] = useState(0);
const ntrpRef = useRef<{
show: (evaluateCallback: EvaluateCallback) => void;
}>({ show: () => {} });
const {
id,
price,
user_action_status,
match_status,
start_time,
end_time,
is_organizer,
} = detail || {};
const gameManageRef = useRef();
function handleSelfEvaluate() {
ntrpRef?.current?.show({
type: EvaluateScene.detail,
next: (flag) => {
if (flag) {
Taro.navigateTo({
url: `/order_pages/orderDetail/index?gameId=${id}`,
});
return;
}
Taro.redirectTo({ url: `/order_pages/orderDetail/index?gameId=${id}` });
},
onCancel: () => {
// Taro.redirectTo({ url: `/game_pages/detail/index?id=${id}` });
Taro.navigateBack();
},
});
}
useEffect(() => {
getCommentCount?.((count) => {
setCommentCount(count);
});
}, [getCommentCount]);
function generateTextAndAction(
user_action_status: null | { [key: string]: boolean }
):
| undefined
| { text: string | React.FC; action?: () => void; available?: boolean } {
if (!user_action_status) {
return;
}
const priceStrArr = price.toString().split(".");
const displayPrice = is_organizer ? (
<>
<Text className={styles.integer}>0</Text>
{/* <Text className={styles.decimalPart}>.00</Text> */}
</>
) : (
<>
<Text className={styles.integer}>{priceStrArr[0]}</Text>
<Text className={styles.decimalPart}>.{priceStrArr[1]}</Text>
</>
);
// user_action_status.can_assess = true;
// user_action_status.can_join = false;
// console.log(user_action_status, "user_action");
const {
can_assess,
can_join,
can_substitute,
can_pay,
is_substituting,
waiting_start,
} = user_action_status || {};
if (MATCH_STATUS.CANCELED === match_status) {
return {
text: "活动已取消",
available: false,
// action: () => toast("活动已取消"),
};
} else if (MATCH_STATUS.FINISHED === match_status) {
return {
text: "活动已结束",
available: false,
// action: () => toast("活动已取消"),
};
} else if (dayjs(end_time).isBefore(dayjs())) {
return {
text: "活动已结束",
available: false,
// action: () => toast("活动已结束"),
};
} else if (dayjs(start_time).isBefore(dayjs())) {
return {
text: "活动已开始",
available: false,
// action: () => toast("活动已开始"),
};
} else if (isFull(detail)) {
return {
text: "活动已满员",
available: false,
// action: () => toast("活动已满员"),
};
}
if (waiting_start) {
return {
text: () => (
<>
<Image className={styles.crrrencySymbol} src={RMB_ICON} />
{displayPrice}
<Text className={styles.btnText}></Text>
</>
),
action: () => toast("已加入"),
};
} else if (is_substituting) {
return {
text: () => (
<>
<Image className={styles.crrrencySymbol} src={RMB_ICON} />
{displayPrice}
<Text className={styles.btnText}></Text>
</>
),
action: () => toast("已加入候补"),
};
} else if (can_pay) {
return {
text: () => (
<>
<Image src={RMB_ICON} />
{price}
<Text className={styles.btnText}></Text>
</>
),
action: async () => {
const res = await OrderService.getUnpaidOrder(id);
if (res.code === 0) {
navto(
`/order_pages/orderDetail/index?id=${res.data.order_info.order_id}`
);
}
},
};
} else if (can_substitute) {
return {
text: () => (
<>
<Image className={styles.crrrencySymbol} src={RMB_ICON} />
{displayPrice}
<Text className={styles.btnText}></Text>
</>
),
action: handleJoinGame,
};
} else if (can_join) {
return {
text: () => {
return (
<>
<Image className={styles.crrrencySymbol} src={RMB_ICON} />
{displayPrice}
<Text className={styles.btnText}></Text>
</>
);
},
action: handleJoinGame,
};
} else if (can_assess) {
return {
text: () => (
<>
<Image className={styles.crrrencySymbol} src={RMB_ICON} />
{displayPrice}
<Text className={styles.btnText}></Text>
</>
),
action: handleSelfEvaluate,
};
}
return {
text: "球局无法加入",
available: false,
};
}
if (!user_action_status) {
return "";
}
const {
text,
available = true,
action = () => {},
} = generateTextAndAction(user_action_status)!;
let ActionText: React.FC | string = text;
if (typeof ActionText === "string") {
ActionText = () => {
return <Text className={styles.btnText}>{text as string}</Text>;
};
}
return (
<>
<View className={styles["sticky-bottom-bar"]}>
<View className={styles["sticky-bottom-bar-share-and-comment"]}>
<View
className={styles["sticky-bottom-bar-share"]}
onClick={() => handleShare()}
>
<Image
className={styles["sticky-bottom-bar-share-icon"]}
src={img.ICON_DETAIL_SHARE}
/>
<Text className={styles["sticky-bottom-bar-share-text"]}></Text>
</View>
<View
className={styles["sticky-bottom-bar-share-and-comment-separator"]}
/>
<View
className={styles["sticky-bottom-bar-comment"]}
onClick={() => {
// Taro.showToast({ title: "To be continued", icon: "none" });
handleAddComment();
}}
>
<Image
className={styles["sticky-bottom-bar-comment-icon"]}
src={img.ICON_DETAIL_COMMENT_LIGHT}
/>
<Text className={styles["sticky-bottom-bar-comment-text"]}>
{commentCount > 0 ? commentCount : "评论"}
</Text>
</View>
</View>
<View
className={classnames(
styles["detail-main-action"],
available ? "" : styles.disabled
)}
>
<View
style={is_organizer ? {} : { margin: "auto" }}
className={styles["sticky-bottom-bar-join-game"]}
onClick={action}
>
<ActionText />
</View>
{is_organizer && (
<View
className={styles.game_manage}
onClick={() => {
gameManageRef.current.show(detail, onStatusChange);
}}
>
</View>
)}
</View>
</View>
<GameManagePopup ref={gameManageRef} />
<NTRPEvaluatePopup type={EvaluateScene.detail} ref={ntrpRef} showGuide />
</>
);
}