181 lines
6.6 KiB
Vue
181 lines
6.6 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from "vue";
|
|
import { storeToRefs } from "pinia";
|
|
import { useMarketStore } from "../stores/market";
|
|
|
|
defineEmits<{
|
|
refresh: [];
|
|
}>();
|
|
|
|
const marketStore = useMarketStore();
|
|
const { userBets } = storeToRefs(marketStore);
|
|
const loading = computed(() => marketStore.isLoading);
|
|
|
|
const totalBetAmount = computed(() => {
|
|
return userBets.value.reduce((sum, bet) => sum + bet.amount, 0);
|
|
});
|
|
|
|
const winningBets = computed(() => {
|
|
return userBets.value.filter(bet => {
|
|
const market = bet.market;
|
|
return market?.status === "resolved" && market?.winning_option?.uuid === bet.option.uuid;
|
|
}).reverse();
|
|
});
|
|
|
|
const losingBets = computed(() => {
|
|
return userBets.value.filter(bet => {
|
|
const market = bet.market;
|
|
return market?.status === "resolved" && market?.winning_option?.uuid !== bet.option.uuid;
|
|
});
|
|
});
|
|
|
|
const openBets = computed(() => {
|
|
return userBets.value.filter(bet => bet.market?.status === "open");
|
|
});
|
|
|
|
const totalWinnings = computed(() => {
|
|
return winningBets.value.reduce((sum, bet) => sum + bet.amount, 0);
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="space-y-6">
|
|
<!-- Loading -->
|
|
<div v-if="loading" class="flex justify-center py-20">
|
|
<span class="loading loading-spinner loading-lg"></span>
|
|
</div>
|
|
|
|
<!-- Empty State -->
|
|
<div v-else-if="userBets.length === 0" class="alert">
|
|
<i class="mdi mdi-information mr-2"></i>
|
|
<span>You haven't placed any bets yet</span>
|
|
</div>
|
|
|
|
<!-- Content -->
|
|
<template v-else>
|
|
<!-- Stats -->
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
<div class="stat bg-base-100 rounded-lg shadow">
|
|
<div class="stat-title text-sm">Total Bets</div>
|
|
<div class="stat-value text-2xl">{{ userBets.length }}</div>
|
|
<div class="stat-desc text-xs">{{ totalBetAmount }} points</div>
|
|
</div>
|
|
|
|
<div class="stat bg-base-100 rounded-lg shadow">
|
|
<div class="stat-title text-sm">Active</div>
|
|
<div class="stat-value text-2xl text-info">{{ openBets.length }}</div>
|
|
<div class="stat-desc text-xs">Waiting for result</div>
|
|
</div>
|
|
|
|
<div class="stat bg-base-100 rounded-lg shadow">
|
|
<div class="stat-title text-sm">Won</div>
|
|
<div class="stat-value text-2xl text-success">{{ winningBets.length }}</div>
|
|
<div class="stat-desc text-xs text-success">+{{ totalWinnings }} points</div>
|
|
</div>
|
|
|
|
<div class="stat bg-base-100 rounded-lg shadow">
|
|
<div class="stat-title text-sm">Lost</div>
|
|
<div class="stat-value text-2xl text-error">{{ losingBets.length }}</div>
|
|
<div class="stat-desc text-xs">Better luck next time</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bets Sections -->
|
|
<div class="space-y-6">
|
|
<!-- Open Bets -->
|
|
<div v-if="openBets.length > 0">
|
|
<h3 class="text-xl font-bold mb-4 flex items-center gap-2">
|
|
<i class="mdi mdi-progress-clock text-info"></i>
|
|
Active Bets ({{ openBets.length }})
|
|
</h3>
|
|
<div class="space-y-4">
|
|
<div
|
|
v-for="bet in openBets"
|
|
:key="bet.uuid"
|
|
class="card bg-base-100 shadow hover:shadow-lg transition-shadow"
|
|
>
|
|
<div class="card-body py-4">
|
|
<div class="flex justify-between items-start">
|
|
<div class="flex-1">
|
|
<h4 class="font-semibold text-lg">{{ bet.market?.title }}</h4>
|
|
<p class="text-sm text-base-content/70">
|
|
Bet on: <span class="font-medium">{{ bet.option.text }}</span>
|
|
</p>
|
|
</div>
|
|
<div class="text-right">
|
|
<div class="text-lg font-bold">{{ bet.amount }} pts</div>
|
|
<div class="text-xs text-base-content/60 mt-1">
|
|
Status: <span class="badge badge-info badge-sm">{{ bet.market?.status }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Winning Bets -->
|
|
<div v-if="winningBets.length > 0">
|
|
<h3 class="text-xl font-bold mb-4 flex items-center gap-2">
|
|
<i class="mdi mdi-check-circle text-success"></i>
|
|
Won Bets ({{ winningBets.length }})
|
|
</h3>
|
|
<div class="space-y-4">
|
|
<div
|
|
v-for="bet in winningBets"
|
|
:key="bet.uuid"
|
|
class="card bg-success/10 border border-success shadow"
|
|
>
|
|
<div class="card-body py-4">
|
|
<div class="flex justify-between items-start">
|
|
<div class="flex-1">
|
|
<h4 class="font-semibold text-lg">{{ bet.market?.title }}</h4>
|
|
<p class="text-sm text-base-content/70">
|
|
Correct! You bet on: <span class="font-medium text-success">{{ bet.option.text }}</span>
|
|
</p>
|
|
</div>
|
|
<div class="text-right">
|
|
<div class="text-lg font-bold text-success">+{{ bet.amount }} pts</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Losing Bets -->
|
|
<div v-if="losingBets.length > 0">
|
|
<h3 class="text-xl font-bold mb-4 flex items-center gap-2">
|
|
<i class="mdi mdi-close-circle text-error"></i>
|
|
Lost Bets ({{ losingBets.length }})
|
|
</h3>
|
|
<div class="space-y-4">
|
|
<div
|
|
v-for="bet in losingBets"
|
|
:key="bet.uuid"
|
|
class="card bg-error/10 border border-error shadow"
|
|
>
|
|
<div class="card-body py-4">
|
|
<div class="flex justify-between items-start">
|
|
<div class="flex-1">
|
|
<h4 class="font-semibold text-lg">{{ bet.market?.title }}</h4>
|
|
<p class="text-sm text-base-content/70">
|
|
You bet on: <span class="font-medium">{{ bet.option.text }}</span>
|
|
</p>
|
|
<p class="text-sm text-base-content/60 mt-1">
|
|
Winner: <span class="font-medium">{{ bet.market?.winning_option?.text }}</span>
|
|
</p>
|
|
</div>
|
|
<div class="text-right">
|
|
<div class="text-lg font-bold text-error">-{{ bet.amount }} pts</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|