Files
mini-programs/src/components/GameManagePopup/index.tsx

239 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, {
useState,
forwardRef,
useImperativeHandle,
useRef,
} from "react";
import Taro from "@tarojs/taro";
import { View, Text, Input } from "@tarojs/components";
import CommonPopup from "../CommonPopup";
import styles from "./index.module.scss";
import detailService, { MATCH_STATUS } from "@/services/detailService";
import { useUserInfo } from "@/store/userStore";
import dayjs from "dayjs";
const CancelPopup = forwardRef((props, ref) => {
const { detail } = props;
const [visible, setVisible] = useState(false);
const [cancelReason, setCancelReason] = useState("");
const [inputFocus, setInputFocus] = useState(false);
const onFinish = useRef(null);
const { current_players, participants = [], publisher_id } = detail;
const realParticipants = participants
.filter((item) => item.status === "joined")
.map((item) => item.user.id);
const hasOtherJoin =
current_players > 1 ||
realParticipants.some((id) => id !== Number(publisher_id));
// const hasOtherJoin = true;
useImperativeHandle(ref, () => ({
show: (onAct) => {
onFinish.current = onAct;
setVisible(true);
// 使用 Taro.nextTick 确保在下一个渲染周期后聚焦
Taro.nextTick(() => {
setInputFocus(true);
});
},
}));
function onClose() {
setInputFocus(false);
setVisible(false);
setCancelReason("");
}
async function handleConfirm() {
if (!cancelReason && hasOtherJoin) {
Taro.showToast({ title: "请输入取消原因", icon: "none" });
return;
}
try {
await onFinish.current(hasOtherJoin ? cancelReason : "无责取消");
onClose();
} catch (e) {
console.log(e, 1221);
}
}
return (
<>
<CommonPopup
visible={visible}
showHeader={false}
hideFooter
zIndex={1002}
enableDragToClose={false}
onClose={onClose}
position="center"
style={{
width: hasOtherJoin ? "360px" : "300px",
borderRadius: "16px",
}}
>
<View className={styles.centerContainer}>
<View className={styles.title}></View>
<View className={styles.content}>
<Text className={styles.tips}>
{hasOtherJoin
? "已有球友报名,取消后将为他们自动退款"
: "有100+球友正在浏览您的球局哦~"}
</Text>
{hasOtherJoin && (
<View className={styles.cancelReason}>
<Input
className={styles.input}
placeholder="请输入取消理由"
focus={inputFocus}
value={cancelReason}
onInput={(e) => setCancelReason(e.detail.value)}
maxlength={100}
onBlur={() => setInputFocus(false)}
/>
</View>
)}
</View>
<View className={styles.actions}>
<View className={styles.confirm} onClick={handleConfirm}>
</View>
<View className={styles.cancel} onClick={onClose}>
</View>
</View>
</View>
</CommonPopup>
</>
);
});
export default forwardRef(function GameManagePopup(props, ref) {
const [visible, setVisible] = useState(false);
const [detail, setDetail] = useState({});
const onStatusChange = useRef(null);
const cancelRef = useRef(null);
const userInfo = useUserInfo();
useImperativeHandle(ref, () => ({
show: (gameDetail, onChange) => {
onStatusChange.current = onChange;
setDetail(gameDetail);
setVisible(true);
},
}));
function handleEditGame() {
Taro.navigateTo({
url: `/publish_pages/publishBall/index?gameId=${detail.id}&republish=0`,
});
onClose();
}
function handleRepubGame() {
Taro.navigateTo({
url: `/publish_pages/publishBall/index?gameId=${detail.id}&republish=1`,
});
onClose();
}
async function handleCancelGame() {
cancelRef.current.show(async (result) => {
if (result) {
try {
const res = await detailService.disbandGame({
game_id: detail.id,
settle_reason: result,
});
if (res.code === 0) {
Taro.showToast({ title: "活动取消成功" });
onStatusChange.current?.(true);
}
} catch (e) {
Taro.showToast({ title: e.message, icon: "error" });
return e;
}
}
});
onClose();
}
async function handleQuitGame() {
try {
const res = await detailService.organizerQuit({
game_id: detail.id,
quit_reason: "组织者主动退出",
});
if (res.code === 0) {
Taro.showToast({ title: "活动退出成功" });
onStatusChange.current?.(true);
}
} catch (e) {
Taro.showToast({ title: e.message, icon: "error" });
} finally {
onClose();
}
}
function onClose() {
setVisible(false);
}
const hasJoin = (detail.participants || [])
.filter((item) => item.status === "joined")
.some((item) => item.user.id === userInfo.id);
const finished = [MATCH_STATUS.FINISHED, MATCH_STATUS.CANCELED].includes(
detail.match_status,
);
// const inTwoHours = dayjs(detail.start_time).diff(dayjs(), "hour") < 2;
const beforeStart = dayjs(detail.start_time).isAfter(dayjs());
const hasOtherParticiappants = (detail.participants || [])
.filter((item) => item.status === "joined")
.some((item) => item.user.id !== userInfo.id);
return (
<>
<CommonPopup
visible={visible}
showHeader={false}
hideFooter
zIndex={1001}
enableDragToClose={false}
onClose={onClose}
style={{ minHeight: "unset" }}
>
<View className={styles.container}>
{!finished && !hasOtherParticiappants && beforeStart && (
<View className={styles.button} onClick={handleEditGame}>
</View>
)}
{finished && (
<View className={styles.button} onClick={handleRepubGame}>
</View>
)}
{!finished && beforeStart && (
<View className={styles.button} onClick={handleCancelGame}>
</View>
)}
{!finished && beforeStart && hasJoin && (
<View className={styles.button} onClick={handleQuitGame}>
退
</View>
)}
<View className={styles.button} onClick={onClose}>
</View>
</View>
</CommonPopup>
<CancelPopup ref={cancelRef} detail={detail} />
</>
);
});