155 lines
5.1 KiB
Vue
155 lines
5.1 KiB
Vue
<script setup lang="ts">
|
|
import { computed, onMounted, watch } from 'vue';
|
|
import { useRoute, RouterView } from 'vue-router';
|
|
import { useI18n } from 'vue-i18n';
|
|
import DesktopTopNav from './DesktopTopNav.vue';
|
|
import DesktopOddsBetPopover from './DesktopOddsBetPopover.vue';
|
|
import SportsCategoryBar from './SportsCategoryBar.vue';
|
|
import LeagueSidebar from './LeagueSidebar.vue';
|
|
import MatchSidebar from './MatchSidebar.vue';
|
|
import DesktopBetSlipRail from './DesktopBetSlipRail.vue';
|
|
import FloatingMailbox from '../FloatingMailbox.vue';
|
|
import AnnouncementMarquee from '../AnnouncementMarquee.vue';
|
|
import { usePlayerHome } from '../../composables/usePlayerHome';
|
|
import { useAuthStore } from '../../stores/auth';
|
|
import { useBetSlipStore } from '../../stores/betSlip';
|
|
|
|
const route = useRoute();
|
|
const { locale } = useI18n();
|
|
const auth = useAuthStore();
|
|
const slip = useBetSlipStore();
|
|
const { load: loadPlayerHome, announcements } = usePlayerHome();
|
|
|
|
const layoutMode = computed<'betting' | 'account' | 'hub' | 'marketing'>(() => {
|
|
const p = route.path;
|
|
if (p === '/bet' || p.startsWith('/match/') || p.startsWith('/outright/')) {
|
|
return 'betting';
|
|
}
|
|
if (
|
|
p === '/bets' ||
|
|
p.startsWith('/bets/') ||
|
|
p.startsWith('/wallet') ||
|
|
p.startsWith('/profile')
|
|
) {
|
|
return 'account';
|
|
}
|
|
if (p.startsWith('/announcements')) {
|
|
return 'hub';
|
|
}
|
|
if (p.startsWith('/messages')) {
|
|
return 'hub';
|
|
}
|
|
return 'marketing';
|
|
});
|
|
|
|
const isMatchDetail = computed(() => route.path.startsWith('/match/'));
|
|
const isBettingDetail = computed(
|
|
() => route.path.startsWith('/match/') || route.path.startsWith('/outright/'),
|
|
);
|
|
|
|
const showBetSlipRail = computed(() => {
|
|
const p = route.path;
|
|
if (p === '/bets' || p.startsWith('/bets/')) return false;
|
|
if (p.startsWith('/wallet') || p.startsWith('/profile')) return false;
|
|
if (route.params.id && (p.startsWith('/announcements/') || p.startsWith('/messages/'))) {
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
|
|
onMounted(() => {
|
|
void loadPlayerHome(true);
|
|
});
|
|
|
|
watch(locale, (next, prev) => {
|
|
if (prev && next !== prev) void loadPlayerHome(true);
|
|
});
|
|
|
|
watch(
|
|
() => auth.token,
|
|
() => {
|
|
void loadPlayerHome(true);
|
|
},
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
class="desktop-shell"
|
|
:class="{
|
|
'betslip-collapsed': showBetSlipRail && !slip.panelExpanded,
|
|
'betslip-hidden': !showBetSlipRail,
|
|
}"
|
|
>
|
|
<div v-if="announcements && announcements.length" class="desktop-marquee-wrap">
|
|
<AnnouncementMarquee :items="announcements" embedded />
|
|
</div>
|
|
|
|
<header class="desktop-header-wrap">
|
|
<DesktopTopNav />
|
|
</header>
|
|
|
|
<div class="desktop-body">
|
|
<div class="desktop-main-container">
|
|
<!-- Betting Layout -->
|
|
<div v-if="layoutMode === 'betting'" class="desktop-layout-betting-wrap">
|
|
<div class="desktop-betting-sports-row">
|
|
<SportsCategoryBar />
|
|
</div>
|
|
<div class="desktop-layout-betting">
|
|
<aside class="desktop-betting-left">
|
|
<LeagueSidebar v-if="!isMatchDetail" />
|
|
<MatchSidebar v-else />
|
|
</aside>
|
|
<main class="desktop-betting-center" :class="{ 'is-betting-detail': isBettingDetail }">
|
|
<RouterView v-slot="{ Component, route: viewRoute }">
|
|
<KeepAlive v-if="viewRoute.meta.keepAlive" :max="10">
|
|
<component :is="Component" :key="viewRoute.path" />
|
|
</KeepAlive>
|
|
<component v-else :is="Component" :key="viewRoute.fullPath" />
|
|
</RouterView>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Account Layout -->
|
|
<div v-else-if="layoutMode === 'account'" class="desktop-layout-account">
|
|
<main class="desktop-account-center">
|
|
<RouterView v-slot="{ Component, route: viewRoute }">
|
|
<KeepAlive v-if="viewRoute.meta.keepAlive" :max="10">
|
|
<component :is="Component" :key="viewRoute.path" />
|
|
</KeepAlive>
|
|
<component v-else :is="Component" :key="viewRoute.fullPath" />
|
|
</RouterView>
|
|
</main>
|
|
</div>
|
|
|
|
<!-- Hub Layout: Messages / Announcements split pane -->
|
|
<div v-else-if="layoutMode === 'hub'" class="desktop-layout-hub-outer">
|
|
<RouterView v-slot="{ Component, route: viewRoute }">
|
|
<KeepAlive v-if="viewRoute.meta.keepAlive" :max="10">
|
|
<component :is="Component" :key="viewRoute.path" />
|
|
</KeepAlive>
|
|
<component v-else :is="Component" :key="viewRoute.fullPath" />
|
|
</RouterView>
|
|
</div>
|
|
|
|
<!-- Marketing/Single Column Layout -->
|
|
<div v-else class="desktop-layout-marketing no-scrollbar">
|
|
<main class="desktop-marketing-content">
|
|
<RouterView v-slot="{ Component, route: viewRoute }">
|
|
<KeepAlive v-if="viewRoute.meta.keepAlive" :max="10">
|
|
<component :is="Component" :key="viewRoute.path" />
|
|
</KeepAlive>
|
|
<component v-else :is="Component" :key="viewRoute.fullPath" />
|
|
</RouterView>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
<DesktopBetSlipRail v-if="showBetSlipRail" />
|
|
</div>
|
|
<FloatingMailbox />
|
|
<DesktopOddsBetPopover />
|
|
</div>
|
|
</template>
|