feat books pages
All checks were successful
Deploy Application / deploy (push) Successful in 6s

This commit is contained in:
2025-06-14 18:14:50 +04:00
parent 991a8e0197
commit 615a89a1c6
26 changed files with 393 additions and 3 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -4,14 +4,21 @@ interface Route {
path: string
name: string
component: () => Promise<Component>
props?: boolean
}
const routes: Route[] = [
{
path: '/',
name: '/',
name: 'home',
component: () => import('@/pages/mainPage/indexPage.vue'),
},
{
path: '/books/:slug',
name: 'book-detail',
component: () => import('@/pages/books/_slug/indexBookPage.vue'),
props: true,
},
]
export default routes

View File

@ -1,18 +1,26 @@
<template>
<div
class="min-h-svh overflow-x-hidden bg-black-50 lato-regular relative overflow-visible before:content-[''] before:absolute before:bottom-0 before:h-[520px] before:w-full before:bg-[url(/src/assets/img/webp/footer-flowers.webp)] before:bg-no-repeat before:bg-bottom before:bg-cover before:z-40"
class="min-h-svh overflow-x-hidden lato-regular relative overflow-visible before:content-[''] before:absolute before:bottom-0 before:h-[520px] before:w-full before:bg-[url(/src/assets/img/webp/footer-flowers.webp)] before:bg-no-repeat before:bg-bottom before:bg-cover before:z-40"
:class="
route.path === '/'
? 'bg-black-50'
: 'bg-[linear-gradient(135deg,rgba(17,17,30,1)_10%,rgba(183,32,76,1)_170%)]'
"
>
<div
v-if="route.path === '/'"
class="relative z-10 after:content-[''] after:absolute after:top-0 after:right-0 after:w-[820px] after:h-[535px] after:bg-[url(/src/assets/img/webp/gradient.webp)] after:bg-no-repeat after:bg-[right_top] after:bg-contain"
/>
<div
v-if="route.path === '/'"
class="relative z-20 after:content-[''] after:absolute after:top-0 after:right-0 after:w-[1120px] after:h-[1800px] after:bg-[url(/src/assets/img/webp/group-flowers.webp)] after:bg-no-repeat after:bg-[right_top] after:bg-cover"
/>
<div
v-if="route.path === '/'"
class="relative z-40 before:content-[''] before:absolute before:top-0 before:left-0 before:w-[1120px] before:h-[1000px] before:bg-[url(/src/assets/img/webp/hero-flowers.webp)] before:bg-no-repeat before:bg-left before:bg-contain"
/>
<UiHeader class="relative z-50" />
<UiMain class="!min-h-[1800px] text-primary relative">
<UiMain class="!min-h-[1200px] text-primary relative">
<slot />
</UiMain>
<UiFooter />
@ -23,4 +31,7 @@
import UiFooter from './UiFooter/UiFooter.vue'
import UiHeader from './UiHeader/UiHeader.vue'
import UiMain from './UiMain/UiMain.vue'
import { useRoute } from 'vue-router'
const route = useRoute()
</script>

View File

@ -0,0 +1,38 @@
{
"id": 1,
"title": "Как влюбить в себя любого\nКнига I",
"metaTitle": "Как влюбить в себя любого - Книга I",
"subtitle": "ОТКРОВЕНИЯ БЫВШЕГО КАЗАНОВЫ",
"subdesc": "💡 Ты красивая, умная, но он не пишет? Эта книга покажет, как влюбить в себя любого — без игр и унижений",
"description": "Думаешь Vino Galante - правнук легендарного Джакомо Казановы? Да, такие слухи ходят. Но здесь дело не в итальянской крови. Просто Galante - очень «тонкий» соблазнитель. Зная все тонкости этого искусства, он филигранно работает «кончиками пальцев».\n\nА эту книгу (ты не поверишь!!) он написал специально для девушек. Однажды влюбившись, Vino перестал соблазнять. Так у тебя появилась возможность узнать основы тонкого искусства соблазнения из легендарного первоисточника.",
"img": "/img/webp/books/1.webp",
"price": "520 ",
"buttonText": "Хочу знать, как работает мужская психология",
"buttonFormat": "PDF + EPUB сразу после оплаты",
"pages": "210 страниц",
"illust": "11 иллюстраций",
"format": "PDF + EPUB",
"whoUKnows": [
{
"text": "Как устроено мужское влечение на самом деле",
"svg": "/img/svg/books/1/mdi_heart-outline.svg"
},
{
"text": "Почему красивые девушки часто одиноки — и что с этим делать",
"svg": "/img/svg/books/1/f7_exclamationmark.svg"
},
{
"text": "Как флиртовать тонко, не теряя себя",
"svg": "/img/svg/books/1/meteor-icons_message.svg"
},
{
"text": "Что делает девушку запоминающейся",
"svg": "/img/svg/books/1/lucide_star.svg"
},
{
"text": "Как не попадать в «запас» и быть единственной",
"svg": "/img/svg/books/1/stash_target.svg"
}
],
"href": "https://www.litres.ru/58125553/"
}

View File

@ -0,0 +1,38 @@
{
"id": 2,
"title": "Как влюбить в себя любого\nКнига II",
"metaTitle": "Как влюбить в себя любого - Книга II",
"subtitle": "ТОНКАЯ ИГРА",
"subdesc": "💡 Если ты устала от “не готов к отношениям” — начни играть по своим правилам",
"description": "Ты бывала свидетелем такого, что у красивой девушки личная жизнь не складывается, а у, казалось бы, дурнушки и семья хорошая, и муж и любит, и обеспечивает? Да такое сплошь и рядом!\n\nХочешь узнать, как построить отношения с любым парнем в наш век, когда вокруг полно красавиц, а все мужчины/парни избалованы?\nОтветы ты найдешь в этой книге.",
"img": "/img/webp/books/2.webp",
"price": "520 ",
"buttonText": "Скачать сейчас — и начать менять игру",
"buttonFormat": "PDF + EPUB сразу после оплаты",
"pages": "210 страниц",
"illust": "11 иллюстраций",
"format": "PDF + EPUB",
"whoUKnows": [
{
"text": "Как выстроить притяжение с любым мужчиной",
"svg": "/img/svg/books/1/mdi_heart-outline.svg"
},
{
"text": "Как включить его чувства, а не просто понравиться",
"svg": "/img/svg/books/1/f7_exclamationmark.svg"
},
{
"text": "Какие фишки работают — и почему",
"svg": "/img/svg/books/1/meteor-icons_message.svg"
},
{
"text": "Почему мужчины уходят от «идеальных» и возвращаются к «опасным»",
"svg": "/img/svg/books/1/lucide_star.svg"
},
{
"text": "Как говорить и вести себя, чтобы остаться в его сердце",
"svg": "/img/svg/books/1/stash_target.svg"
}
],
"href": "https://www.litres.ru/vino-galante/kak-vlubit-v-sebya-lubogo-tonkaya-igra/"
}

View File

@ -0,0 +1,214 @@
<template>
<div v-if="book" class="relative z-50 min-h-screen text-white mb-[208px]">
<!--верхний блок-->
<section
class="flex flex-row relative z-40 before:content-[''] before:absolute before:top-[-140px] before:bg-top before:left-0 before:w-[1200px] before:h-[1000px] before:bg-[url(/src/assets/img/webp/vino-galante.webp)] before:bg-no-repeat before:bg-contain mt-40"
>
<!--левый блок контента-->
<section class="relative top-[-20px] min-w-[570px]">
<div class="flex flex-col items-center">
<img :src="book.img" :alt="book.buttonText" width="100%" height="100%" />
</div>
</section>
<!--правый блок контента-->
<section>
<div class="w-11/12 h-full flex flex-col justify-start">
<div>
<UiHeading tag="H1" class="whitespace-pre-line [&]:font-bold" size="300">
{{ book.title }}
</UiHeading>
<UiParagraph class="mb-10" size="250">
{{ book.subtitle }}
</UiParagraph>
<UiParagraph size="250" class="mb-20">
{{ book.subdesc }}
</UiParagraph>
<UiParagraph size="250" class="whitespace-pre-line min-h-62">
{{ book.description }}
</UiParagraph>
</div>
</div>
</section>
</section>
<!--средний блок-->
<section class="flex flex-row items-center ml-18 justify-between">
<!--левый-->
<div class="flex flex-col items-center min-h-[310px]">
<div class="flex flex-row">
<UiParagraph class="[&]:text-6xl">{{ book.price }}&nbsp;</UiParagraph>
<img src="/img/svg/books/ruble.svg" />
</div>
<div class="mr-10 flex items-center flex-col gap-3">
<UiButton class="max-w-[380px] !font-normal !px-2 !py-4 mt-24">
{{ book.buttonText }}
</UiButton>
<UiParagraph size="200">
{{ book.buttonFormat }}
</UiParagraph>
</div>
</div>
<!--правый-->
<div class="min-h-[310px]">
<!--о книге-->
<div>
<ul class="flex flex-row mr-14 items-center justify-between lg:whitespace-nowrap">
<li class="flex flex-row mr-14 gap-3 items-center">
<img src="/img/svg/books/book-pages.svg" alt="страниц" width="100%" height="100%" />
<UiParagraph size="250" as="span">
{{ book.pages }}
</UiParagraph>
</li>
<li class="flex flex-row mr-14 gap-3 items-center">
<img
src="/img/svg/books/book-illustrations.svg"
alt="иллюстраций"
width="100%"
height="100%"
/>
<UiParagraph size="250" as="span">
{{ book.illust }}
</UiParagraph>
</li>
<li class="flex flex-row mr-14 gap-3 items-center">
<img src="/img/svg/books/book-formats.svg" alt="формат" width="100%" height="100%" />
<UiParagraph size="250" as="span">
{{ book.format }}
</UiParagraph>
</li>
</ul>
</div>
<!--навигация по книге-->
<div class="mt-24">
<ul class="flex flex-row mr-32 items-end justify-between lg:whitespace-nowrap">
<li class="flex flex-row gap-3 items-center">
<RouterLink to="#" class="flex flex-col items-center gap-3 cursor-pointer">
<img src="/img/svg/books/read.svg" alt="Читай отрывок" width="100%" height="100%" />
<UiParagraph size="250" as="span"> Читай отрывок </UiParagraph>
</RouterLink>
</li>
<li class="flex flex-row gap-3 items-center">
<RouterLink to="#" class="flex flex-col items-center gap-3 cursor-pointer">
<img
src="/img/svg/books/download.svg"
alt="Скачай отрывок"
width="100%"
height="100%"
/>
<UiParagraph size="250" as="span"> Скачай отрывок </UiParagraph>
</RouterLink>
</li>
<li class="flex flex-row gap-3 items-center">
<RouterLink to="#" class="flex flex-col items-center gap-3 cursor-pointer">
<img src="/img/svg/books/titles.svg" alt="Содержание" width="100%" height="100%" />
<UiParagraph size="250" as="span"> Содержание </UiParagraph>
</RouterLink>
</li>
</ul>
</div>
</div>
</section>
<!--нижний блок-->
<section class="ml-18 mt-32">
<div>
<UiHeading tag="H2" size="300" class="text-three"> Что ты узнаешь </UiHeading>
<ul class="flex mt-20 flex-row items-center justify-between">
<li
class="flex flex-col-reverse justify-end w-38 gap-4 h-64 items-center transition-transform transform hover:scale-110"
v-for="({ svg, text }, index) in book.whoUKnows"
:key="index"
>
<UiParagraph class="text-center" size="250">
{{ text }}
</UiParagraph>
<img :src="`${svg}`" alt="Вопрос" width="101" height="101" />
</li>
</ul>
</div>
<div class="flex justify-center text-center mt-36">
<UiParagraph>
Или купи на ЛитРес - <br /><a class="text-three" :href="book.href" target="_blank"
>Реферальная ссылка для поддержки автора</a
>
</UiParagraph>
</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'
import UiButton from '@/components/UiButton/UiButton.vue'
import { useHead } from '@vueuse/head'
interface BookDetail {
id: number
title: string
metaTitle: string
subtitle: string
subdesc: string
description: string
img: string
price: string
buttonText: string
buttonFormat: string
pages: string
illust: string
format: string
whoUKnows: Array<{
text: string
svg: string
}>
href: string
}
const route = useRoute()
const currentBookData = ref<BookDetail | null>(null)
const book = computed(() => currentBookData.value)
const loadBookData = async (slug: string) => {
try {
const module = await import(`./_data/${slug}.json`)
currentBookData.value = module.default as BookDetail
} catch (error) {
console.error(`Ошибка при загрузке книги с slug '${slug}':`, error)
currentBookData.value = null
}
}
watch(
() => route.params.slug,
async (newSlug) => {
if (newSlug) {
await loadBookData(newSlug as string)
}
},
{ immediate: true },
)
watch(book, (newBook) => {
if (newBook) {
useHead({
title: `${newBook.metaTitle} | Vino Galante`,
meta: [
{
name: 'description',
content: 'Онлайн магазин книг автора Vino Galante',
},
],
link: [
{
rel: 'canonical',
href: `https://ebook.miduway.space/books/${route.params.slug}`,
},
],
})
}
})
</script>

View File

@ -21,5 +21,11 @@ import { useHead } from '@vueuse/head'
useHead({
title: 'Vino Galante',
meta: [{ name: 'description', content: 'Онлайн магазин книг автора Vino Galante' }],
link: [
{
rel: 'canonical',
href: `https://ebook.miduway.space/`,
},
],
})
</script>