Files
mareike/app/Views/Components/TabbedPage.vue

116 lines
2.7 KiB
Vue

<script setup>
import { ref, shallowRef, onMounted } from "vue"
const props = defineProps({
tabs: {
type: Array,
required: true,
// [{ title: "Titel", component: Component, endpoint: "/wp-json/..." }]
}
})
const activeTab = ref(null) // aktuell ausgewählter Tab
const tabData = ref({}) // Daten für jeden Tab
const tabComponent = shallowRef(null) // Komponente für aktuellen Tab
const loading = ref(false)
const error = ref(null)
async function selectTab(index) {
const tab = props.tabs[index]
activeTab.value = index
tabComponent.value = null
error.value = null
loading.value = true
try {
const csrfToken = document
.querySelector('meta[name="csrf-token"]')
?.getAttribute('content')
const response = await fetch(tab.endpoint, {
method: 'GET', // oder POST, PUT, DELETE …
headers: {
'Accept': 'application/json',
'X-CSRF-TOKEN': csrfToken,
'X-Requested-With': 'XMLHttpRequest',
},
credentials: 'same-origin', // wichtig für Session/Auth
})
if (!response.ok) throw new Error("Fehler: " + response.status)
const json = await response.json()
tabData.value[index] = json
tabComponent.value = tab.component
} catch (err) {
error.value = err.message
} finally {
loading.value = false
}
}
// ersten Tab automatisch laden
onMounted(() => {
if (props.tabs.length > 0) {
selectTab(0)
}
})
</script>
<template>
<div class="tabs">
<!-- Tab Header -->
<div class="tab-header">
<button
v-for="(tab, index) in tabs"
:key="index"
:class="['tab-button', { active: activeTab === index }]"
@click="selectTab(index)"
>
{{ tab.title }}
</button>
</div>
<!-- Tab Content -->
<div class="tab-content" id="tab-content">
<div v-if="loading"> Lädt...</div>
<div v-else-if="error"> {{ error }}</div>
<component
v-else-if="tabComponent"
:is="tabComponent"
:data="tabData[activeTab]"
:deep_jump_id="tabs[activeTab].deep_jump_id"
:deep_jump_id_sub="tabs[activeTab].deep_jump_id_sub"
/>
</div>
</div>
</template>
<style scoped>
.tabs {
border: 1px solid #ddd;
border-radius: 8px;
}
.tab-header {
display: flex;
border-bottom: 1px solid #ddd;
}
.tab-button {
padding: 0.5rem 1rem;
cursor: pointer;
border: none;
background: #f8f8f8;
}
.tab-button.active {
font-weight: bold;
background: white;
border-bottom: 2px solid #0073aa;
}
.tab-content {
padding: 1rem;
width: 100%;
}
</style>