UI/src/components/lottery/LotteryGame.vue
2024-06-18 13:30:42 +07:00

384 lines
10 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 } from "vue-router";
import CountDown from "@/helpers/CountDown";
import { formatNumber } from "@/helpers/format";
import { showFailToast } from "vant";
import axios from "@/axios";
import API from "@/api";
import { handleRequest } from "@/helpers/request";
const route = useRoute();
const id = route.query.id;
const amount = ref("");
const isShowOrder = 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 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);
io.on("game-info", (data) => {
const { name, session, end } = data;
Object.assign(gameInfo, { name, session, end });
countDownTime.restart(end);
getGameHistory();
});
onUnmounted(() => {
io.disconnect();
})
const toggleChoice = (idx) => {
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 submit = () => {
const cs = choices.value.filter((e) => e.active);
if (cs.length === 0) return;
const data = {
id,
choices: cs.map((e) => {
return {
id: e.id,
amount: Number(amount.value),
};
}),
};
handleRequest(axios.post(API.ORDER, data)).then((res) => {
if (res.success) {
showFailToast("Bình chọn thành công.");
amount.value = 0;
choices.value.forEach((e) => (e.active = 0));
} else {
showFailToast(res.message ?? "Lỗi bình chọn");
}
});
};
const countChoices = computed(() => {
return choices.value.filter((e) => e.active).length;
});
const totalAmount = computed(() => {
return choices.value.reduce((prev, curr) => {
return prev + (curr.active ? amount.value : 0);
}, 0);
});
const choicesText = computed(() => {
const cs = choices.value.filter((e) => e.active);
if (cs.length) {
return cs.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;
}
});
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";
};
</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">{{
formatResultText1(gameHistory[0]?.result)
}}</span
><span class="res-des middle">{{
formatResultText2(gameHistory[0]?.result)
}}</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(idx)"
>
<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ố khả dụng</span>
</div>
<div>
<span class="text num">0</span><span class="text">Đ</span>
</div>
</div>
<div class="right" @click="submit">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ố tiền"
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"> 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"
>{{ formatResultText1(item.result) }} </span
><span class="res-des middle"
>{{ formatResultText2(item.result) }}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</van-popup>
</div>
</div>
</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;
}
</style>