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

240 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 onFinish = useRef(null);
const inputRef = 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);
// 使用 requestAnimationFrame 替代 setTimeout(0),性能更好
requestAnimationFrame(() => {
requestAnimationFrame(() => {
inputRef.current && inputRef.current.focus();
});
});
},
}));
function onClose() {
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
ref={inputRef}
className={styles.input}
placeholder="请输入取消理由"
focus
value={cancelReason}
onInput={(e) => setCancelReason(e.detail.value)}
maxlength={100}
/>
</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} />
</>
);
});