UI/src/components/lottery/LotteryGame.vue
2024-06-19 19:18:05 +07:00

482 lines
13 KiB
Vue
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.

<script setup>
import { ref, reactive, computed, watch, onUnmounted } from "vue";
import socket from "@/socket";
import { useRoute, useRouter } from "vue-router";
import CountDown from "@/helpers/CountDown";
import { formatNumber } from "@/helpers/format";
import { useUserStore } from "@/store/user";
import { storeToRefs } from "pinia";
import { showFailToast } from "vant";
import { Popup } from "vant";
import axios from "@/axios";
import API from "@/api";
import { handleRequest } from "@/helpers/request";
const route = useRoute();
const router = useRouter();
const userStore = useUserStore();
const { userInfo } = storeToRefs(userStore);
const id = route.query.id;
if (!id) {
router.push("/Game");
}
const amount = ref("");
const isShowOrder = ref(false);
const isShowConfirmOrder = ref(false);
const showResult = ref(false);
const gameHistory = ref([]);
const showPopupRs = () => {
showResult.value = !showResult.value;
};
const countDown = reactive({
hh: 0,
mm: 0,
ss: 0,
t: 0,
});
const gameInfo = reactive({
name: "",
session: "",
end: 0,
});
const choices = ref([
// { id: "1", name: "IDOL 1", active: false },
// { id: "2", name: "IDOL 2", active: false },
// { id: "3", name: "IDOL 3", active: false },
// { id: "4", name: "IDOL 4", active: false },
]);
const choicesSelected = computed(() => {
return choices.value.filter((e) => e.active);
});
const hhmmss = computed(() => {
return `${String(countDown.hh).padStart(2, "0")}:${String(
countDown.mm
).padStart(2, "0")}:${String(countDown.ss).padStart(2, "0")}`;
});
const countDownTime = new CountDown(0, (hh, mm, ss, t) => {
Object.assign(countDown, { hh, mm, ss, t });
});
const io = socket();
io.emit("join", id, (data) => {
if (data.success == 0) {
router.push("/Game");
}
});
io.on("game-info", (data) => {
const { name, session, countdown } = data;
const end = Date.now() + countdown * 1000
Object.assign(gameInfo, { session, end });
countDownTime.restart(end);
getGameHistory();
});
onUnmounted(() => {
io.disconnect();
});
const toggleChoice = (id) => {
const idx = choices.value.findIndex((e) => e.id === id);
if (idx === -1) return;
choices.value[idx].active = !choices.value[idx].active;
if (!choices.value[idx].active) {
choices.value[idx].amount = 0;
}
};
const getGameHistory = () => {
const params = { page: 1, size: 20 };
handleRequest(axios.get(API.GAME_HISTORY + "/" + id, { params })).then(
(res) => {
if (res.success) {
gameHistory.value = res.data;
}
}
);
};
const GameInfo = () => {
handleRequest(axios.get(API.GAME_INFO + "/" + id)).then(
(res) => {
if (res.success) {
choices.value = res.data.info?.betOptions ?? []
gameInfo.name = res.data.info.name
console.log(res.data.info)
}
}
)
};
const confirmOrder = () => {
if (choicesSelected.value.length === 0) {
return showFailToast("Hãy chọn 1 con số");
}
if (!amount.value) {
return showFailToast("Vui lòng nhập số điểm.");
}
isShowConfirmOrder.value = true;
};
const cancelOrder = () => {
choices.value.forEach((c) => {
c.active = false;
});
amount.value = "";
};
const submit = () => {
const data = {
id,
choices: choicesSelected.value.map((e) => {
return {
id: e.id,
amount: Number(amount.value),
};
}),
};
handleRequest(axios.post(API.ORDER, data)).then((res) => {
if (res.success) {
showFailToast("Thành công");
amount.value = 0;
choices.value.forEach((e) => (e.active = 0));
isShowConfirmOrder.value = false;
} else {
showFailToast(res.message ?? "Lỗi bình chọn");
}
});
};
const countChoices = computed(() => {
return choicesSelected.value.length;
});
const totalAmount = computed(() => {
return choicesSelected.value.reduce((prev, curr) => {
return prev + amount.value;
}, 0);
});
const choicesText = computed(() => {
if (choicesSelected.value.length) {
return choicesSelected.value.map((e) => e.name).join(",");
}
return "Không được chọn";
});
watch(amount, (value) => {
choices.value.forEach((c) => {
c.amount = value;
});
});
watch(countChoices, (newVal, oldVal) => {
if (newVal > 0 && oldVal == 0) {
isShowOrder.value = true;
} else if (newVal == 0 && oldVal > 0) {
isShowOrder.value = false;
isShowConfirmOrder.value = false;
}
});
const formatResultText1 = (r) => {
const s = r.split(",").reduce((prev, curr) => {
return prev + (curr >> 0);
}, 0);
return s > 10 ? "IDOL 1" : "IDOL 2";
};
const formatResultText2 = (r) => {
const s = r.split(",").reduce((prev, curr) => {
return prev + (curr >> 0);
}, 0);
return s % 2 ? "IDOL 3" : "IDOL 4";
};
GameInfo();
</script>
<template>
<div class="container page">
<div class="nav-bar van-nav-bar van-hairline--bottom">
<div class="van-nav-bar__content">
<div @click="$router.push('/Game')" class="van-nav-bar__left">
<i
class="van-icon van-icon-arrow-left"
style="color: rgb(255, 255, 255)"
>
</i>
</div>
<div class="van-nav-bar__title van-ellipsis">{{ gameInfo.name }}</div>
</div>
</div>
<div class="record">
<div class="period">
<div class="cover van-image">
<img class="van-image__img" src="@/assets/images/common/bgGirl.png" />
</div>
<span class="period-number">{{ gameInfo.session }}</span>
<div class="next-number">
<div class="van-count-down">{{ hhmmss }}</div>
</div>
</div>
<div
class="linear-gradient"
style="
background: linear-gradient(
to right,
rgba(126, 86, 120, 0),
rgb(230, 195, 161),
rgba(126, 86, 120, 0)
);
"
></div>
<div class="recent" @click="showPopupRs">
<div class="kuaisan-ball left" v-if="gameHistory[0]">
<span class="res-des middle" v-for="r, i in gameHistory[0].resultText ?? []" :key="i">{{
r
}}</span
>
</div>
<i
class="van-icon van-icon-arrow-down down"
:class="showResult ? 'up' : ''"
></i>
</div>
</div>
<div class="history_popup"></div>
<div class="wrapper">
<div class="options-bar">
<div class="game">
<div
class="linear-gradient"
style="
background: linear-gradient(
to right,
rgba(126, 86, 120, 0),
rgb(230, 195, 161),
rgba(126, 86, 120, 0)
);
"
></div>
<div class="sumValueTwoSides">
<div
class="rectangle large"
:class="{ active: c.active }"
v-for="(c, idx) in choices"
:key="idx"
@click="toggleChoice(c.id)"
>
<div class="wrapper">
<div class="content">
<p class="name-text large">{{ c.name }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottom-bar">
<div class="bar">
<div class="left" @click="isShowOrder = !isShowOrder">
<div class="item">
<i class="jixuanico van-icon van-icon-cart-o"> </i
><span class="text">Bình chọn</span>
</div>
<div class="line"></div>
</div>
<div class="mid">
<div>
<span class="text">Số dư khả dụng</span>
</div>
<div>
<span class="text num">{{ formatNumber(userInfo.money) }}</span
><span class="text">Đ</span>
</div>
</div>
<div class="right" @click="confirmOrder">Xác nhận</div>
</div>
<div class="wrapper" :class="isShowOrder === true ? 'active' : ''">
<div class="item">
<span class="label">Hiện tại số đã chọn</span>
<div class="bet-number">{{ choicesText }}</div>
<i
class="van-icon van-icon-arrow-down down"
:class="isShowOrder ? '' : 'up'"
@click="isShowOrder = !isShowOrder"
>
</i>
</div>
<div class="item">
<span class="label">Điểm xếp hạng</span>
<div class="amount-wrapper">
<div class="van-cell van-field">
<div
class="van-cell__value van-cell__value--alone van-field__value"
>
<div class="van-field__body">
<input
v-model.number="amount"
type="number"
inputmode="numeric"
placeholder="Vui lòng nhập số điểm"
class="van-field__control"
/>
</div>
</div>
</div>
<span class="label">Đ</span>
</div>
</div>
<div class="item">
<div class="part">
<span> Tổng cộng</span
><span class="number">{{ countChoices }}</span
><span>Đặt</span>
</div>
<div class="part">
<span> Tổng cộng</span
><span class="number">{{ totalAmount }} </span><span>Đ</span>
</div>
</div>
</div>
</div>
<van-popup
v-model:show="showResult"
position="top"
:style="{ height: '70%' }"
>
<div class="van-pull-refresh">
<div class="van-pull-refresh__track" style="transition-duration: 0ms">
<div class="van-pull-refresh__head"></div>
<div class="wrapper">
<div class="item">
<div class="left font-weight">Mã xếp hạng</div>
<div class="right font-weight">Kết quả xếp hạng</div>
</div>
<div
class="item"
v-for="(item, index) in gameHistory"
:key="index"
>
<div class="left font-weight">{{ item.session }}</div>
<div class="right font-weight">
<div
class="kuaisan-ball left"
style="
justify-content: center;
width: 100%;
margin-left: 40%;
"
>
<span class="res-des middle" v-for="r, i in item.resultText ?? []" :key="i"
>{{ r }} </span
>
</div>
</div>
</div>
</div>
</div>
</div>
</van-popup>
</div>
</div>
<van-popup v-model:show="isShowConfirmOrder">
<div class="confirm-order-modal">
<div class="head van-hairline--bottom">
<p class="text" style="margin: 1em">Bình chọn</p>
</div>
<ul class="list">
<li
class="lise-item van-hairline--bottom"
v-for="(item, index) in choicesSelected"
:key="index"
>
<div class="main">
<p class="bet-name">{{ item.name }}</p>
<p class="detail-text">
1ĐặtX{{ item.amount }}Đ={{ item.amount }}Đ
</p>
</div>
<van-icon name="close" @click="toggleChoice(item.id)" />
</li>
</ul>
<div class="sub-bar">
<van-button
type="default"
class="item cancel-btn"
color="#979799"
plain
@click="cancelOrder"
>Hủy bình chọn</van-button
>
<van-button
type="default"
class="item"
color="linear-gradient(270deg, #c24491, #775fd9)"
@click="submit"
>Xác nhận</van-button
>
</div>
</div>
</van-popup>
</template>
<style scoped>
.van-cell {
font-size: 4vw !important;
line-height: 6.667vw !important;
}
.van-cell {
position: relative;
display: -webkit-box;
display: -webkit-flex;
display: flex;
box-sizing: border-box;
width: 100%;
padding: 1.333vw 2.133vw;
overflow: hidden;
color: #323233;
font-size: 1.867vw;
line-height: 3.2vw;
background-color: #fff;
}
.wrapper .item {
display: flex;
flex-direction: row;
align-items: center;
padding: 1.333vw 0;
}
.wrapper .item .kuaisan-ball .res-des.middle {
width: auto;
}
.rectangle.active .content {
background: transparent;
}
.lise-item .main p {
margin: 1em 0;
}
.cancel-btn :deep(.van-button__text) {
color: currentColor !important;
}
</style>