Files
webMontime/src/views/app/AppHomeView.vue
T
2026-06-13 10:19:31 +03:30

142 lines
4.0 KiB
Vue

<template>
<DesktopLandingPage
v-if="showDesktopLanding"
:services="landingServices"
:loading-services="loadingLandingServices"
:services-error="landingServicesError"
:booking-enabled="canBookSingleBusiness"
/>
<WebAppLayout v-else-if="showMobileLanding">
<HomeHeroSection
:show-book-button="canBookSingleBusiness"
@book="goToBooking"
@browse="scrollToServices"
/>
<HomeServicesSection
:items="landingServices"
:loading="loadingLandingServices"
:error="landingServicesError"
:booking-enabled="canBookSingleBusiness"
/>
<HomeFeatureBar />
</WebAppLayout>
<div
v-else-if="!tenant.loaded && isDesktop"
class="flex min-h-dvh items-center justify-center bg-white dark:bg-[#0d1117]"
>
<BusinessCardSkeleton class="w-full max-w-5xl px-8" />
</div>
<DesktopDiscoveryPage v-else-if="tenant.loaded && isDesktop" />
<WebAppLayout v-else>
<BusinessCardSkeleton v-if="!tenant.loaded" class="py-2" />
<HomeDiscoveryContent v-else />
</WebAppLayout>
</template>
<script setup lang="ts">
import { useMediaQuery } from '@vueuse/core';
import { computed, onMounted, ref, watch } from 'vue';
import { useRouter } from 'vue-router';
import HomeDiscoveryContent from '@/components/home/HomeDiscoveryContent.vue';
import HomeFeatureBar from '@/components/home/HomeFeatureBar.vue';
import HomeHeroSection from '@/components/home/HomeHeroSection.vue';
import HomeServicesSection from '@/components/home/HomeServicesSection.vue';
import DesktopDiscoveryPage from '@/components/landing/DesktopDiscoveryPage.vue';
import DesktopLandingPage from '@/components/landing/DesktopLandingPage.vue';
import BusinessCardSkeleton from '@/components/ui/BusinessCardSkeleton.vue';
import WebAppLayout from '@/layouts/WebAppLayout.vue';
import { useOwnedBusiness } from '@/composables/useOwnedBusiness';
import { useAuthStore } from '@/stores/auth';
import { useTenantStore } from '@/stores/tenant';
import type { LandingServiceItem } from '@/types/landing';
import { fetchLandingServices } from '@/utils/landing-services';
const isDesktop = useMediaQuery('(min-width: 1024px)');
const router = useRouter();
const auth = useAuthStore();
const tenant = useTenantStore();
const { ensureLoaded, isOwnBusiness } = useOwnedBusiness();
const landingServices = ref<LandingServiceItem[]>([]);
const loadingLandingServices = ref(false);
const landingServicesError = ref('');
const showDesktopLanding = computed(
() => tenant.loaded && tenant.isSingleBusiness && isDesktop.value,
);
const showMobileLanding = computed(
() => tenant.loaded && tenant.isSingleBusiness && !isDesktop.value,
);
const showSingleBusinessLanding = computed(
() => showDesktopLanding.value || showMobileLanding.value,
);
const canBookSingleBusiness = computed(() => {
const businessId = tenant.singleBusinessId;
if (!businessId) return true;
return !isOwnBusiness(businessId);
});
async function loadLandingServices() {
if (!tenant.singleBusinessId) return;
loadingLandingServices.value = true;
landingServicesError.value = '';
try {
landingServices.value = await fetchLandingServices(tenant.singleBusinessId);
} catch {
landingServices.value = [];
} finally {
loadingLandingServices.value = false;
}
}
function scrollToServices() {
const el = document.getElementById('services');
el?.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
function goToBooking() {
if (!canBookSingleBusiness.value) {
void router.push({ name: 'app-owner' });
return;
}
const id = tenant.singleBusinessId;
if (!id) {
scrollToServices();
return;
}
void router.push({
name: 'app-business-detail',
params: { id },
});
}
watch(showSingleBusinessLanding, (show) => {
if (show) {
void loadLandingServices();
}
});
onMounted(async () => {
if (auth.isLoggedIn) {
await auth.loadUser();
await ensureLoaded();
}
await tenant.bootstrap();
if (showSingleBusinessLanding.value) {
await loadLandingServices();
}
});
</script>