initial: bootstrap from BukidBountyApp base
This commit is contained in:
177
resources/js/Pages/Fragments/Home/HomePublic.vue
Normal file
177
resources/js/Pages/Fragments/Home/HomePublic.vue
Normal file
@@ -0,0 +1,177 @@
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import axios from 'axios';
|
||||
import { useNavigate } from '../../../composables/Core/useNavigate.js';
|
||||
|
||||
// Core Components
|
||||
import ServiceButtonGrid from '../../../Components/Core/Services/ServiceButtonGrid.vue';
|
||||
import SideTextButtonList from '../../../Components/Core/Services/SideTextButtonList.vue';
|
||||
import CardSimple from '../../../Components/Core/CardSimple.vue';
|
||||
import GlobalAnnouncement from '../../../Components/GlobalAnnouncement.vue';
|
||||
|
||||
import { useUIStore } from '../../../stores/ui';
|
||||
|
||||
const { navigate } = useNavigate();
|
||||
const uiStore = useUIStore();
|
||||
|
||||
const landingPageHtml = ref(null);
|
||||
const hasLandingPage = ref(false);
|
||||
const loadingLanding = ref(true);
|
||||
|
||||
// Fetch the active landing page
|
||||
const fetchLandingPage = async () => {
|
||||
loadingLanding.value = true;
|
||||
try {
|
||||
const res = await axios.get('/api/public/landing-page');
|
||||
if (res.data.success && res.data.has_landing_page && res.data.data) {
|
||||
landingPageHtml.value = res.data.data.html_content;
|
||||
hasLandingPage.value = true;
|
||||
uiStore.setFullWidth(true);
|
||||
|
||||
// Hide global app UI for a clean landing page experience
|
||||
uiStore.setHeaderVisibility(false);
|
||||
uiStore.setBottomNavVisibility(false);
|
||||
} else {
|
||||
hasLandingPage.value = false;
|
||||
uiStore.setFullWidth(false);
|
||||
uiStore.setHeaderVisibility(true);
|
||||
uiStore.setBottomNavVisibility(true);
|
||||
}
|
||||
} catch (err) {
|
||||
hasLandingPage.value = false;
|
||||
uiStore.setFullWidth(false);
|
||||
uiStore.setHeaderVisibility(true);
|
||||
uiStore.setBottomNavVisibility(true);
|
||||
} finally {
|
||||
loadingLanding.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Also ensure we reset full width if this fragment is unmounted
|
||||
import { onUnmounted, watch } from 'vue';
|
||||
onUnmounted(() => {
|
||||
uiStore.setFullWidth(false);
|
||||
uiStore.setHeaderVisibility(true);
|
||||
uiStore.setBottomNavVisibility(true);
|
||||
});
|
||||
|
||||
// Watch for changes in hasLandingPage to update UI store
|
||||
watch(hasLandingPage, (newVal) => {
|
||||
uiStore.setFullWidth(newVal);
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
fetchLandingPage();
|
||||
});
|
||||
|
||||
// Services for public users (no auth required)
|
||||
const services = computed(() => [
|
||||
{ icon: 'https://cdn.jsdelivr.net/gh/telemagnadon/obj-vault-3a@v2026.05.14-vendor-2/a/938032617d05.bin', title: 'Market', pagename: 'ListProductsMarket' },
|
||||
{ icon: 'https://cdn.jsdelivr.net/gh/telemagnadon/obj-vault-3a@v2026.05.14-vendor-2/a/85605eacd4c8.bin', title: 'Stores', pagename: 'ListStores' },
|
||||
]);
|
||||
|
||||
// Quick actions for public users
|
||||
const quickActionsItems = computed(() => [
|
||||
{ text: 'Browse Products', pagename: 'ListProductsMarket', icon: 'https://cdn.jsdelivr.net/gh/telemagnadon/obj-vault-3a@v2026.05.14-vendor-2/a/f0a0193d728e.bin' },
|
||||
{ text: 'View Available Stores', pagename: 'ListStores', icon: 'https://cdn.jsdelivr.net/gh/telemagnadon/obj-vault-3a@v2026.05.14-vendor-2/a/85605eacd4c8.bin' },
|
||||
]);
|
||||
|
||||
const handleItemClick = (item) => {
|
||||
if (item.pagename) {
|
||||
navigate({ page: item.pagename, props: { data: item.pagestring || '' } });
|
||||
}
|
||||
};
|
||||
|
||||
const goToLogin = () => {
|
||||
navigate({ page: 'Auth.Login' });
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="home-public-fragment">
|
||||
<!-- Loading state -->
|
||||
<div v-if="loadingLanding" class="text-center py-5">
|
||||
<div class="spinner-border text-primary" role="status"></div>
|
||||
</div>
|
||||
|
||||
<!-- Custom Landing Page (from DB) -->
|
||||
<div v-else-if="hasLandingPage && landingPageHtml" class="landing-page-container">
|
||||
<div class="landing-page-content" v-html="landingPageHtml"></div>
|
||||
</div>
|
||||
|
||||
<!-- Default Public Homepage (fallback) -->
|
||||
<div v-else class="pb-5">
|
||||
<!-- Global Announcements -->
|
||||
<GlobalAnnouncement />
|
||||
|
||||
<!-- Services Grid -->
|
||||
<div class="mt-4">
|
||||
<h5 class="tf-container fw_6 mb-3">Featured Services</h5>
|
||||
<ServiceButtonGrid :items="services" @item-click="handleItemClick" />
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions -->
|
||||
<div class="tf-container mt-4">
|
||||
<h5 class="fw_6 mb-3">Quick Links</h5>
|
||||
<SideTextButtonList :items="quickActionsItems" @item-click="handleItemClick" />
|
||||
</div>
|
||||
|
||||
<!-- Login CTA -->
|
||||
<div class="tf-container mt-5">
|
||||
<div class="login-cta-box text-center p-4">
|
||||
<h4 class="fw_6 mb-2">Ready to trade?</h4>
|
||||
<p class="mb-4 text-muted">Join the {{ uiStore.appName }} community today.</p>
|
||||
<button @click="goToLogin" class="btn btn-primary w-100 py-3 rounded-pill fw_6">
|
||||
Login / Sign Up
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.announcement-img {
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.announcement-text {
|
||||
line-height: 1.6;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.login-cta-box {
|
||||
background: #f8f9fa;
|
||||
border-radius: 15px;
|
||||
border: 1px dashed #dee2e6;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #42b983;
|
||||
border: none;
|
||||
font-size: 1.1rem;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.btn-primary:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* Landing page container - allow full-width custom content */
|
||||
.landing-page-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.landing-page-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Ensure dark mode compatibility */
|
||||
:global(.dark-mode) .login-cta-box {
|
||||
background: var(--bg-card, #1e1e2e);
|
||||
border-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user