feat(market): resolve for admin
This commit is contained in:
parent
a264336bd8
commit
79e7cef3ba
@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted } from "vue";
|
import { ref, computed, onMounted } from "vue";
|
||||||
import { polylanSubmitterApiGetUserInfo, marketApiCreateBet, marketApiListUserBets } from "../api";
|
import { polylanSubmitterApiGetUserInfo, marketApiCreateBet, marketApiListUserBets, marketApiCloseMarket, marketApiResolveMarket } from "../api";
|
||||||
import type { Market, MarketOption } from "../types";
|
import type { Market, MarketOption } from "../types";
|
||||||
import type { UserInfoOut, UserBetSchema } from "../api/types.gen";
|
import type { UserInfoOut, UserBetSchema } from "../api/types.gen";
|
||||||
|
|
||||||
@ -19,6 +19,9 @@ const error = ref<string>("");
|
|||||||
const userInfo = ref<UserInfoOut | undefined>();
|
const userInfo = ref<UserInfoOut | undefined>();
|
||||||
const userBets = ref<UserBetSchema[]>([]);
|
const userBets = ref<UserBetSchema[]>([]);
|
||||||
const existingBet = ref<UserBetSchema | null>(null);
|
const existingBet = ref<UserBetSchema | null>(null);
|
||||||
|
const showResolveModal = ref(false);
|
||||||
|
const selectedWinningOption = ref<string | null>(null);
|
||||||
|
const resolveLoading = ref(false);
|
||||||
|
|
||||||
const timeRemaining = computed(() => {
|
const timeRemaining = computed(() => {
|
||||||
const endDate = new Date(props.market.end_date).getTime();
|
const endDate = new Date(props.market.end_date).getTime();
|
||||||
@ -68,6 +71,53 @@ const getPotentialGain = (option: MarketOption) => {
|
|||||||
return Math.round(existingBet.value.amount * multiplier);
|
return Math.round(existingBet.value.amount * multiplier);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const closeMarket = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
error.value = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
await marketApiCloseMarket({
|
||||||
|
path: { market_uuid: props.market.uuid },
|
||||||
|
});
|
||||||
|
emit("refresh");
|
||||||
|
} catch (e) {
|
||||||
|
error.value = "Error closing market";
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resolveMarket = async () => {
|
||||||
|
if (!selectedWinningOption.value) {
|
||||||
|
error.value = "Please select a winning option";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveLoading.value = true;
|
||||||
|
error.value = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
await marketApiResolveMarket({
|
||||||
|
path: { market_uuid: props.market.uuid },
|
||||||
|
body: { winning_option_uuid: selectedWinningOption.value },
|
||||||
|
});
|
||||||
|
emit("refresh");
|
||||||
|
showResolveModal.value = false;
|
||||||
|
selectedWinningOption.value = null;
|
||||||
|
} catch (e) {
|
||||||
|
const err = e as any;
|
||||||
|
if (typeof err === 'object' && err?.detail) {
|
||||||
|
error.value = err.detail;
|
||||||
|
} else if (typeof err === 'string') {
|
||||||
|
error.value = err;
|
||||||
|
} else {
|
||||||
|
error.value = "Error resolving market";
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
resolveLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const placeBet = async () => {
|
const placeBet = async () => {
|
||||||
if (!selectedOption.value || !betAmount.value) return;
|
if (!selectedOption.value || !betAmount.value) return;
|
||||||
|
|
||||||
@ -147,7 +197,7 @@ onMounted(async () => {
|
|||||||
<div :class="['badge', statusColor, 'text-white']">
|
<div :class="['badge', statusColor, 'text-white']">
|
||||||
{{ market.status }}
|
{{ market.status }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm text-base-content/60 text-right">
|
<div v-if="market.status === 'open'" class="text-sm text-base-content/60 text-right">
|
||||||
<div>{{ timeRemaining }}</div>
|
<div>{{ timeRemaining }}</div>
|
||||||
<div class="text-xs">until close</div>
|
<div class="text-xs">until close</div>
|
||||||
</div>
|
</div>
|
||||||
@ -157,6 +207,51 @@ onMounted(async () => {
|
|||||||
|
|
||||||
<div class="divider my-0"></div>
|
<div class="divider my-0"></div>
|
||||||
|
|
||||||
|
<!-- Admin Actions -->
|
||||||
|
<div v-if="userInfo?.is_superuser" class="card-body py-4 bg-base-100">
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<button v-if="market.status === 'open'" @click="closeMarket" :disabled="loading" class="btn btn-sm btn-warning">
|
||||||
|
<span v-if="loading" class="loading loading-spinner loading-sm"></span>
|
||||||
|
<span v-else>Close Market</span>
|
||||||
|
</button>
|
||||||
|
<button v-if="market.status === 'closed'" @click="showResolveModal = true" class="btn btn-sm btn-success">
|
||||||
|
Resolve Market
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Resolve Modal -->
|
||||||
|
<dialog v-if="showResolveModal" class="modal modal-open">
|
||||||
|
<div class="modal-box">
|
||||||
|
<h3 class="font-bold text-lg mb-4">Resolve Market - Select Winner</h3>
|
||||||
|
|
||||||
|
<div class="space-y-2 mb-4">
|
||||||
|
<div v-for="option in market.options" :key="option.uuid" class="form-control">
|
||||||
|
<label class="label cursor-pointer border rounded-lg p-3 hover:bg-base-200 transition w-full flex justify-between">
|
||||||
|
<span class="label-text font-medium">{{ option.text }}</span>
|
||||||
|
<input type="radio" :value="option.uuid" v-model="selectedWinningOption" class="radio radio-primary" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="error" class="alert alert-error mb-4">
|
||||||
|
<i class="mdi mdi-alert-circle"></i>
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-action">
|
||||||
|
<button @click="showResolveModal = false" class="btn" :disabled="resolveLoading">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button @click="resolveMarket" :disabled="!selectedWinningOption || resolveLoading" class="btn btn-primary">
|
||||||
|
<span v-if="resolveLoading" class="loading loading-spinner loading-sm"></span>
|
||||||
|
<span v-else>Resolve & Distribute Points</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-backdrop" @click="showResolveModal = false"></div>
|
||||||
|
</dialog>
|
||||||
|
|
||||||
<!-- Options -->
|
<!-- Options -->
|
||||||
<div class="card-body py-4">
|
<div class="card-body py-4">
|
||||||
<div class="flex flex-col gap-3">
|
<div class="flex flex-col gap-3">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user