144 lines
4.3 KiB
Vue
144 lines
4.3 KiB
Vue
<template>
|
||
<div v-if="titles" class="relative z-50 min-h-screen text-white mb-[208px]">
|
||
<section class="flex flex-col relative z-40 mt-40 ml-18">
|
||
<UiHeading tag="H1" class="whitespace-pre-line [&]:font-normal mb-10 -ml-5" size="500">
|
||
{{ titles.title }}
|
||
</UiHeading>
|
||
|
||
<div class="flex flex-col gap-6">
|
||
<div v-for="(section, index) in titles.sections" :key="index" class="flex flex-col gap-4">
|
||
<!-- Main section title -->
|
||
<UiHeading tag="h2" size="300" class="text-three [&]:font-normal">
|
||
{{ section.title }}
|
||
</UiHeading>
|
||
|
||
<!-- Subsections -->
|
||
<div v-if="section.subsections" class="ml-6 flex flex-col gap-4">
|
||
<div
|
||
v-for="(subsection, subIndex) in section.subsections"
|
||
:key="subIndex"
|
||
class="flex flex-col gap-2"
|
||
>
|
||
<!-- Subsection with image -->
|
||
<div
|
||
v-if="typeof subsection.title === 'object'"
|
||
class="flex items-center gap-3 -ml-10"
|
||
>
|
||
<img
|
||
v-if="subsection.title.img"
|
||
:src="subsection.title.img"
|
||
:alt="subsection.title.text"
|
||
class="w-6 h-6"
|
||
/>
|
||
<UiHeading tag="H3" size="300" class="[&]:font-normal">
|
||
{{ subsection.title.text }}
|
||
</UiHeading>
|
||
</div>
|
||
<!-- Regular subsection -->
|
||
<UiHeading v-else tag="H3" size="300" class="[&]:text-gray-200 [&]:font-normal">
|
||
{{ subsection.title }}
|
||
</UiHeading>
|
||
|
||
<!-- Items list -->
|
||
<ul v-if="subsection.items" class="ml-6 flex flex-col gap-2 list-decimal">
|
||
<li v-for="(item, itemIndex) in subsection.items" :key="itemIndex">
|
||
<UiParagraph size="300" class="[&]:text-gray-200 [&]:font-normal"
|
||
> {{ item }}</UiParagraph
|
||
>
|
||
</li>
|
||
</ul>
|
||
|
||
<!-- Nested subsections -->
|
||
<div v-if="subsection.subsections" class="flex flex-col gap-2">
|
||
<div v-for="(nestedSub, nestedIndex) in subsection.subsections" :key="nestedIndex">
|
||
<UiHeading tag="H4" size="300" class="[&]:text-gray-200 [&]:font-normal">
|
||
{{ nestedSub.title }}
|
||
</UiHeading>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div v-else class="text-white text-center py-20">Содержание не найдено.</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, computed, watch } from 'vue'
|
||
import { useRoute } from 'vue-router'
|
||
import UiHeading from '@/components/Typography/UiHeading.vue'
|
||
import UiParagraph from '@/components/Typography/UiParagraph.vue'
|
||
|
||
interface SubsectionTitle {
|
||
text: string
|
||
img?: string
|
||
}
|
||
|
||
interface Subsection {
|
||
title: string | SubsectionTitle
|
||
items?: string[]
|
||
subsections?: Array<{
|
||
title: string
|
||
}>
|
||
}
|
||
|
||
interface Section {
|
||
title: string
|
||
subsections?: Subsection[]
|
||
}
|
||
|
||
interface TitlesData {
|
||
title: string
|
||
titleMeta: string
|
||
sections: Section[]
|
||
}
|
||
|
||
const route = useRoute()
|
||
|
||
const currentTitlesData = ref<TitlesData | null>(null)
|
||
|
||
const titles = computed(() => currentTitlesData.value)
|
||
|
||
const loadTitlesData = async (slug: string) => {
|
||
try {
|
||
const module = await import(`./_data/${slug}.json`)
|
||
currentTitlesData.value = module.default as TitlesData
|
||
} catch (error) {
|
||
console.error(`Ошибка при загрузке содержания с slug '${slug}':`, error)
|
||
currentTitlesData.value = null
|
||
}
|
||
}
|
||
|
||
watch(
|
||
() => route.params.titlesSlug,
|
||
async (newSlug) => {
|
||
if (newSlug) {
|
||
await loadTitlesData(newSlug as string)
|
||
}
|
||
},
|
||
{ immediate: true },
|
||
)
|
||
|
||
watch(titles, (newTitles) => {
|
||
if (newTitles) {
|
||
useHead({
|
||
title: `${newTitles.titleMeta} | Vino Galante`,
|
||
meta: [
|
||
{
|
||
name: 'description',
|
||
content: 'Содержание книги Vino Galante',
|
||
},
|
||
],
|
||
link: [
|
||
{
|
||
rel: 'canonical',
|
||
href: `https://ebook.miduway.space/books/${route.params.slug}/${route.params.titlesSlug}`,
|
||
},
|
||
],
|
||
})
|
||
}
|
||
})
|
||
</script>
|