Compare commits
3 Commits
feature/8-
...
98b9670661
Author | SHA1 | Date | |
---|---|---|---|
98b9670661 | |||
1353b0e65a | |||
2e3de70f56 |
18
.env
@ -1,18 +0,0 @@
|
||||
DB_USER=
|
||||
DB_HOST=
|
||||
DB_NAME=
|
||||
DB_PASSWORD=
|
||||
DB_PORT=
|
||||
|
||||
YOOKASSA_SHOP_ID=
|
||||
YOOKASSA_SECRET_KEY=
|
||||
|
||||
APP_URL=
|
||||
|
||||
|
||||
# SMTP Configuration for Yandex
|
||||
SMTP_USER=levishub@yandex.com
|
||||
SMTP_PASS=avhpihoudpyvibtx
|
||||
DEFAULT_TO_EMAIL=miduway@yandex.ru
|
||||
SMTP_HOST=smtp.yandex.ru
|
||||
SMTP_PORT=465
|
20
.env.example
@ -1,20 +0,0 @@
|
||||
DB_USER=
|
||||
DB_HOST=
|
||||
DB_NAME=
|
||||
DB_PASSWORD=
|
||||
DB_PORT=
|
||||
|
||||
YOOKASSA_SHOP_ID=
|
||||
YOOKASSA_SECRET_KEY=
|
||||
|
||||
APP_URL=
|
||||
|
||||
|
||||
|
||||
|
||||
# SMTP Configuration for Yandex
|
||||
SMTP_USER=levishub@yandex.ru
|
||||
SMTP_PASS=avhpihoudpyvibtx
|
||||
DEFAULT_TO_EMAIL=miduway@yandex.ru
|
||||
SMTP_HOST=smtp.yandex.ru
|
||||
SMTP_PORT=465
|
@ -1,4 +1,4 @@
|
||||
name: Deploy Nuxt App
|
||||
name: Deploy Application
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
@ -8,37 +8,27 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.TOKEN }}
|
||||
token: 0406afe7de6547e850dd62c84976c6def23a5193
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
- name: Install dependencies and build
|
||||
- name: Install curl
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
if command -v apt-get &> /dev/null; then
|
||||
apt-get update && apt-get install -y curl
|
||||
elif command -v apk &> /dev/null; then
|
||||
apk add --no-cache curl
|
||||
elif command -v yum &> /dev/null; then
|
||||
yum install -y curl
|
||||
fi
|
||||
|
||||
- name: Prepare deployment files
|
||||
run: |
|
||||
tar -czf deploy.tar.gz dist Dockerfile docker-compose.yml
|
||||
|
||||
- name: Upload files via Gitea API
|
||||
- name: Upload config files to server
|
||||
env:
|
||||
GITEA_API: "https://gitea.miduway.space/api/v1/repos/levis/ebook/raw/main"
|
||||
GITEA_TOKEN: ${{ secrets.TOKEN }}
|
||||
GITEA_API: 'https://gitea.miduway.space/api/v1/repos/levis/ebook/raw/main'
|
||||
GITEA_TOKEN: '0406afe7de6547e850dd62c84976c6def23a5193'
|
||||
run: |
|
||||
for file in Dockerfile docker-compose.yml; do
|
||||
for file in docker-compose.yml Dockerfile; do
|
||||
echo "Uploading $file"
|
||||
curl -X PUT \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: text/plain" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-T "$file" \
|
||||
"$GITEA_API/$file?branch=main"
|
||||
"$GITEA_API/$file"
|
||||
done
|
||||
|
||||
curl -X PUT \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/gzip" \
|
||||
-T "deploy.tar.gz" \
|
||||
"$GITEA_API/deploy.tar.gz?branch=main"
|
||||
|
11
.gitignore
vendored
@ -11,15 +11,7 @@ node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
.nuxt
|
||||
|
||||
.output
|
||||
.data
|
||||
.nuxt
|
||||
.nitro
|
||||
.cache
|
||||
dist
|
||||
.history
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
@ -30,5 +22,6 @@ dist
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
package-lock.json
|
||||
|
||||
|
||||
frontend.env
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": ["html-validate:recommended", "html-validate:standard"],
|
||||
"rules": {
|
||||
"heading-level": "error",
|
||||
"require-img-alt": "error",
|
||||
"element-permitted-content": "error",
|
||||
"require-meta-title": "error",
|
||||
"require-meta-description": "error",
|
||||
"no-duplicate-id": "error",
|
||||
"prefer-native-element": "error"
|
||||
}
|
||||
}
|
2
.husky/pre-commit
Normal file
@ -0,0 +1,2 @@
|
||||
npm run lint
|
||||
npm run format
|
3
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar"]
|
||||
}
|
12
Dockerfile
@ -1,7 +1,13 @@
|
||||
FROM node:22-slim
|
||||
WORKDIR /usr/src/app
|
||||
FROM node:20 as builder
|
||||
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
CMD ["node", "dist/server/index.mjs"]
|
||||
|
||||
FROM nginx:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY ebook.conf /etc/nginx/conf.d/default.conf
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
77
README.md
@ -1,76 +1,27 @@
|
||||
# Nuxt Minimal Starter
|
||||
# Проект сайт vino Galante
|
||||
|
||||
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||
## Описание проекта
|
||||
|
||||
## Setup
|
||||
Интернет сайт Vino Galente создан для продажи книг за авторством...
|
||||
|
||||
Make sure to install dependencies:
|
||||
### Установка, для разработки
|
||||
|
||||
```bash
|
||||
# npm
|
||||
Копируем env
|
||||
|
||||
npm install
|
||||
|
||||
# pnpm
|
||||
pnpm install
|
||||
|
||||
# yarn
|
||||
yarn install
|
||||
|
||||
# bun
|
||||
bun install
|
||||
```
|
||||
cp frontend.env frontend.env.example
|
||||
```
|
||||
|
||||
## Development Server
|
||||
Устанавливаем зависимости
|
||||
|
||||
Start the development server on `http://localhost:3000`:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
# pnpm
|
||||
pnpm dev
|
||||
|
||||
# yarn
|
||||
yarn dev
|
||||
|
||||
# bun
|
||||
bun run dev
|
||||
```
|
||||
yarn
|
||||
```
|
||||
|
||||
## Production
|
||||
Запуск dev
|
||||
|
||||
Build the application for production:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run build
|
||||
|
||||
# pnpm
|
||||
pnpm build
|
||||
|
||||
# yarn
|
||||
yarn build
|
||||
|
||||
# bun
|
||||
bun run build
|
||||
```
|
||||
vite
|
||||
```
|
||||
|
||||
Locally preview production build:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run preview
|
||||
|
||||
# pnpm
|
||||
pnpm preview
|
||||
|
||||
# yarn
|
||||
yarn preview
|
||||
|
||||
# bun
|
||||
bun run preview
|
||||
```
|
||||
|
||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||
Разворачивание, docker
|
||||
|
15
app.vue
@ -1,15 +0,0 @@
|
||||
<template>
|
||||
<NuxtLayout>
|
||||
<!-- <link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Russo+One&display=swap"
|
||||
rel="stylesheet"
|
||||
/> -->
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
</template>
|
@ -1,3 +0,0 @@
|
||||
<svg width="14" height="20" viewBox="0 0 14 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.9401 11.1109L2.9533 20L0.457031 17.7781L9.19574 10L0.457031 2.22187L2.9533 0L12.9401 8.88906C13.2711 9.18373 13.457 9.58334 13.457 10C13.457 10.4167 13.2711 10.8163 12.9401 11.1109Z" fill="white"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 354 B |
Before Width: | Height: | Size: 746 KiB |
Before Width: | Height: | Size: 142 KiB |
@ -1,71 +0,0 @@
|
||||
<template>
|
||||
<div class="max-w-md mx-auto p-6 rounded-lg shadow-md text-gray-900">
|
||||
<h2 class="text-2xl font-bold mb-6 text-primary text-center">Заполните контактные данные</h2>
|
||||
|
||||
<form @submit.prevent="onSubmit" class="space-y-4">
|
||||
<div>
|
||||
<label for="to" class="block text-sm font-medium text-primary mb-2"> Ваш e-mail: </label>
|
||||
<input
|
||||
id="to"
|
||||
v-model="to"
|
||||
type="email"
|
||||
required
|
||||
placeholder="email@example.com"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent text-gray-900"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<UiButton type="submit" :disabled="isLoading" class="w-[400px]">
|
||||
<span v-if="isLoading">Перехожу...</span>
|
||||
<span v-else>Перейти к оплате</span>
|
||||
</UiButton>
|
||||
</form>
|
||||
|
||||
<div v-if="status" class="mt-4 p-3 rounded-md" :class="statusClass">
|
||||
{{ status }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
const to = ref('')
|
||||
const status = ref('')
|
||||
const isLoading = ref(false)
|
||||
|
||||
const statusClass = computed(() => {
|
||||
if (status.value.includes('Ошибка')) {
|
||||
return 'bg-red-100 text-red-700 border border-red-200'
|
||||
}
|
||||
if (status.value.includes('Успех')) {
|
||||
return 'bg-green-100 text-green-700 border border-green-200'
|
||||
}
|
||||
return 'bg-blue-100 text-blue-700 border-blue-200'
|
||||
})
|
||||
|
||||
async function onSubmit() {
|
||||
if (!to.value) {
|
||||
status.value = 'Пожалуйста, введите ваш e-mail'
|
||||
return
|
||||
}
|
||||
|
||||
isLoading.value = true
|
||||
status.value = ''
|
||||
|
||||
try {
|
||||
await $fetch('/api/send-order', {
|
||||
method: 'POST',
|
||||
body: { to: to.value },
|
||||
})
|
||||
|
||||
status.value = 'Успех! Письмо с подтверждением отправлено на вашу почту.'
|
||||
to.value = ''
|
||||
} catch (error) {
|
||||
console.error('Ошибка отправки письма:', error)
|
||||
status.value = `Ошибка отправки: ${error?.data?.message || error.message || 'Неизвестная ошибка'}`
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,17 +0,0 @@
|
||||
export const colorVariants = {
|
||||
primary: [
|
||||
"bg-accent-50",
|
||||
"text-primary",
|
||||
"hover:bg-accent-100",
|
||||
"active:bg-accent-150",
|
||||
],
|
||||
secondary: [
|
||||
"bg-transparent",
|
||||
"text-primary",
|
||||
"hover:bg-accent-50",
|
||||
"border-accent-50",
|
||||
"border",
|
||||
"hover:bg-accent-100",
|
||||
"active:bg-accent-150",
|
||||
],
|
||||
};
|
@ -1,28 +0,0 @@
|
||||
export default {
|
||||
meta: [
|
||||
{ charset: "utf-8" },
|
||||
{
|
||||
name: "viewport",
|
||||
content:
|
||||
"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no",
|
||||
},
|
||||
],
|
||||
link: [
|
||||
{
|
||||
rel: "preconnect",
|
||||
href: "https://fonts.googleapis.com",
|
||||
},
|
||||
{
|
||||
rel: "preconnect",
|
||||
href: "https://fonts.gstatic.com",
|
||||
},
|
||||
{
|
||||
rel: "stylesheet",
|
||||
href: "https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap",
|
||||
},
|
||||
{
|
||||
rel: "stylesheet",
|
||||
href: "https://fonts.googleapis.com/css2?family=Russo+One&display=swap",
|
||||
},
|
||||
],
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
import modules from "./modules";
|
||||
import sitemap from "./sitemap";
|
||||
|
||||
export default {
|
||||
modules,
|
||||
sitemap,
|
||||
typescript: {
|
||||
strict: true,
|
||||
typeCheck: true,
|
||||
},
|
||||
};
|
@ -1,13 +0,0 @@
|
||||
export default [
|
||||
'@nuxt/eslint',
|
||||
'@nuxt/icon',
|
||||
'@nuxt/image',
|
||||
'@nuxt/content',
|
||||
// '@nuxt/fonts',
|
||||
'@pinia/nuxt',
|
||||
'@nuxtjs/tailwindcss',
|
||||
'@pinia/nuxt',
|
||||
'@nuxtjs/html-validator',
|
||||
// '@nuxtjs/robots',
|
||||
// '@nuxtjs/sitemap',
|
||||
]
|
@ -1,12 +0,0 @@
|
||||
// ./sitemap.config.ts
|
||||
export default {
|
||||
siteUrl: 'https://ebook.miduway.space',
|
||||
|
||||
// Примеры маршрутов, можно заменить на API-запрос
|
||||
urls: [
|
||||
{ loc: '/books/1' },
|
||||
{ loc: '/books/1/title-1' },
|
||||
{ loc: '/books/2/title-2' },
|
||||
{ loc: '/books/2' },
|
||||
],
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
import { defineContentConfig, defineCollection } from '@nuxt/content'
|
||||
|
||||
export default defineContentConfig({
|
||||
collections: {
|
||||
books: defineCollection({
|
||||
type: 'page',
|
||||
source: '/books/*.md',
|
||||
}),
|
||||
},
|
||||
})
|
@ -1,69 +0,0 @@
|
||||
<div style="color: #f54b7e; font-weight: bold; font-size: 1.5em;">Глава 1. Перезагрузка</div>
|
||||
|
||||
### Введение
|
||||
|
||||
  Название первой главы - “Перезагрузка”. Как ты думаешь, почему? Потому что всё начинается с твоей головы и только с твоей головы. Суть этой главы - выработать в тебе правильное отношение к мужчинам. Правильное значит такое, которое тебе позволит нами управлять, хотя и неявно. Если ты хочешь иметь успех у мужчин, тебе просто необходимо правильно к нам относиться. Тебе нужна правильная система взглядов. Ты должна знать, по каким законам функционирует система “мужчина”. В противном случае ты обречена на провал, независимо от внешних данных, финансовой ситуации и всего остального.<br/>
|
||||
Пример. С чего начинается обучение водительскому мастерству? Правильно, с теории. На курсах вождения тебе объясняют, по каким правилам и законам движутся автомобили. Зная эти правила, ты можешь безопасно передвигаться в мегаполисе. Т.е. используя машину, ты добираешься из пункта “А” в пункт “Б”. Т.е. ты достигаешь своей цели быть в пункте “Б”, приехать на работу, например.<br/>
|
||||
  То же самое и в соблазнении. Все те убеждения соблазнительницы, с которыми ты ознакомишься в этой главе, такие же правила безопасности дорожного движения. Если твои нынешние убеждения относительно парней сильно разнятся с истинными, то ты просто не можешь иметь настоящий успех у мужчин. Мне очень повезло в жизни - не знаю почему, но я встретился с одной очень хорошей правильной девушкой. Девушка очень красивая, но с парнями на тот момент у нее был явный недобор. Все, что ей мешало иметь колоссальный успех у парней - неправильное отношение к мужчинам. Например, она считала, что мужчина первым должен проявлять активность, а девушка при этом вообще ничего не должна делать. Прошло полгода, теперь она проводит в день по три свидания, ей дарят золото, за ней ухаживают очень классные парни, такие, от которых у обычной девушки текут слюнки. Ей уже поступило несколько предложений о замужестве.
|
||||
Что же позволило ей так возвыситься над обычными девушками? Ответ ты найдешь в этой главе.
|
||||
|
||||
### <span style="color: #f54b7e;">Убеждения соблазнительницы</span>
|
||||
|
||||
_"Мы формируем свои убеждения в детстве,_<br/>
|
||||
_а потом движемся по жизни, воссоздавая_<br/>
|
||||
_ситуации, которые подошли бы нашим убеждениям."_ <br/>
|
||||
_Луиза Хей_
|
||||
|
||||
  Ты наверно думаешь, что успешная соблазнительница - это такая очень красивая девушка, понимающая все тонкости в моде и умеющая соблазнительно кокетничать? У нее обязательно должны быть длинные красивые ноги и осиная талия? Вся такая Мэрилин Монро? Тогда я не завидую твоей способности общаться с мужчинами. Сейчас я разобью эти глупые убеждения, созданные рекламой и всей этой телевизионной шелухой. Но мне надо, чтобы ты сама думала, сама использовала свой самый главный актив - свой мозг. Поэтому ответь на вопрос - какова была личная жизнь Мэрилин Монро? Ответила? Спасибо. Теперь ответь на следующий вопрос - какова личная жизнь типичной очень красивой девушки? Ответила? Спасибо. А теперь правильные ответы.<br/>
|
||||
  Мэрилин Монро, эта актриса, певица и, самое главное, секс-символ Америки 50 ÷ 60 годов прошлого столетия, была 3 раза замужем и умерла в очень молодом возрасте (всего 36 лет) от передозировки снотворного. Мдаа.<br/>
|
||||
Первый муж - Джим Дагерти, то ли моряк, то ли еще не пойми кто. Мэрилин было всего 16 лет, когда они поженились. Совсем ребенок еще. Характеризовала брак как ошибку молодости. Второй брак. Какой-то Джо Ди Маджо, звезда бейсбола. Брак просуществовал всего 9 месяцев. Мужик был необычайно ревнив и ревновал Мэрилин даже к публике. Ему было сложно терпеть ее популярность. Если брак даже и год не продержался, значит это был изначально один большой косяк, а не брак. Ладно, кратко о последнем браке. Третий муж - Артур Миллер. Драматург. Вроде более-менее брак. Продержался 4.5 года. Ходят слухи о четвертом браке и о том, что на Мэрилин залезал президент США Кеннеди. И вроде как причина смерти Мэрилин - убийство, т.к. она начала заявлять свои права на президента, и тот, чтобы устранить проблему, устранил любовницу.
|
||||
Из этой истории, так напоминающей кальку современной жизни, делаем следующие выводы:
|
||||
|
||||
1. Сама по себе красота, даже если это дьявольски привлекательная красота, ничего не дает.
|
||||
2. Так, желаемая всеми популярность абсолютно не гарантирует счастья в личной жизни.<br/><br/>
|
||||
Пока остановимся на этих двух выводах.<br/>
|
||||
  Еще в недавнем прошлом моей слабостью были модели. Они такие красивые, утонченные, у них длинные изящные пальцы - не девушки, а сплошное загляденье. И главное, они недоступны для обычных парней. Сколько раз я видел, как мужики сворачивали головы, провожая взглядом мою очередную спутницу. Конечно! В школу моделей берут всех, в модели - единицы. Самое интересное - наблюдать за реакцией парней. Вначале они бросают взгляд на девушку, примерно через секунду на меня. Если я делаю морду кирпичом - убирают взгляд, если нет - снова смотрят на девушку. Их можно понять, ведь по-настоящему красивая девушка - это истинное произведение искусства. Сам Бог ваяет настоящих моделей. И, естественно, у меня было много моделей и не только из моего города. И как ты думаешь, что я тебе скажу о них? Многие из них несчастны в личной жизни. Это просто парадоксально! Как могут быть несчастны такие красавицы?!<br/>
|
||||
  Вначале я удивлялся, потом привык. Да ты хотя бы посмотри на мисс Вселенная Оксану Федорову. Полнейшая неразбериха в личной жизни. Она же мисс Вселенная! Представляешь?! Официально она самая красивая девушка планеты Земля в 2002-м году.<br/>
|
||||
  Она могла выбрать любого. А красавица Дениз Ричардс? В 2002-м в возрасте 31 года вышла замуж за актера Чарли Шина. Как можно было выходить замуж за такого дегенерата? Чарли Шин известен своими многочисленными скандалами в личной и общественной жизни, он наркоман. В 2011 году Шин был уволен компаниями CBS и Warner Bros. Television. Мдаа. С 2011 года этот актер живет с Бри Олсон. Бри Олсон -порноактриса. Кто такая порноактриса? Порноактриса это всего лишь помойное ведро, она отсосет у любого, на кого укажет режиссер. Надо иметь весьма убогий разум, чтобы жить со шлюхой. И вот Дениз, живое воплощение женской красоты, выбрала для себя такого недочеловека. Прожив четыре года, они разошлись. Дениз осталась с двумя детьми.<br/>
|
||||
  Во истину покажите мне красивую, нет, очень красивую девушку, и я покажу вам трагедию. К чему это я все? А к тому, что главное в тебе - это твои мозги. Главное в тебе - это твои установки и ценности, которыми ты руководствуешься в жизни, твои глубинные убеждения. И если ты будешь женственной, нежной девушкой и, самое главное, умной, ты стопроцентно найдешь себе достойного человека. В этом просто нет никаких сомнений.<br/>
|
||||
  Теперь посмотрим на жен успешных людей. На женщин, у которых в личной жизни все тип-топ. Кого же взять на рассмотрение? А давай-ка возьмем царицу нашей страны - Светлану Владимировну Медведеву (фотографии смотри в интернете). Это жена действующего президента нашей страны Дмитрия Анатольевича Медведева. Родилась 15-го марта 1965 года в Кронштадте, детство провела в деревне Коваши. По одним данным вышла замуж в 24 года, по другим в 28. Ну что тут сказать? Смотри фотографии и делай выводы сама. В жизни сплошь и рядом девушки с самой заурядной внешностью удачно выходят замуж. Почему? Читай дальше.
|
||||
|
||||
_  Задание. Найди информацию, например, биографии о пяти женщинах, успешных в личной жизни и о пяти женщинах, несчастных в личной жизни. Проанализируй их и сделай хотя бы по 5 выводов о том, что же объединяет женщин успешных и что объединяет женщин не успешных. Таким образом, в сумме ты получишь 10 выводов. Обращай внимание не только на убеждения или установки, но и на то, какое воспитание получили девочки в детстве, в каких семьях росли, какова судьба их матерей и т.д. После 10 общих выводов в тебе должна родиться одна главная мысль, один общий вывод. Сделай это, потом читай дальше._
|
||||
|
||||
<br/>
|
||||
  Я верю в тебя и поэтому знаю, что общий вывод, который ты сделаешь сама для себя, будет таким: 99% успеха в соблазнении зависит от твоих ценностей, доминантных мыслей, убеждений, отношения к жизни, к мужчинам, т.е. всего того, что находится в твоей голове. И почти не зависит от природных внешних данных, места рождения, текущей финансовой ситуации и т.п. Сейчас я приведу убеждения успешной соблазнительницы, которые ты должна выучить как Отче наш и которые ты обязана проверить на практике. Все до единого! Вот этот ключ, открывающей тебе дорогу в долину любых отношений, которые ты только захочешь иметь. Они позволят тебе играть с мужчинами как кошка с мышкой и брать от них то, о чем обычная девушка не может и мечтать. Вот они:
|
||||
|
||||
1. Всё всегда хорошо
|
||||
2. Другие девушки не помеха для меня
|
||||
3. Парней много, я одна
|
||||
4. Использовать мужчин естественно и приятно
|
||||
5. Отшивать мужчин - это естественно
|
||||
6. Ты имеешь ровно то, что заслужила
|
||||
7. Ты достойна гораздо большего
|
||||
8. Все мечты достижимы
|
||||
9. Проявлять активность девушке естественно
|
||||
10. Мужчины до замужества - тренажеры
|
||||
11. Мужчина должен относиться уважительно
|
||||
12. Среди мужчин есть идиоты
|
||||
13. Желание секса от мужчины - это нормально
|
||||
14. Мужчины общаются, когда им что-то нужно
|
||||
15. Пока не было секса - ты не проиграла
|
||||
16. Удовольствие от общения = всё по плану
|
||||
17. Ты ничего не должна мужчине
|
||||
18. Соблазнение - интересная игра
|
||||
19. Ахиллесовы пяты мужчин: эго и секс
|
||||
20. Мужчины - хорошие создания
|
||||
21. Мужчины не примитивны
|
||||
22. Мужчинам нужно не только секс
|
||||
23. Смысл жизни - развитие
|
||||
24. Запасной аэродром - это нормально
|
||||
25. Сексом мужчину не удержать
|
||||
26. Общение должно приносить радость
|
||||
27. Мужчины любят высокоранговых женщин
|
||||
28. Мир - отражение тебя самой
|
||||
|
||||
  А теперь остановимся подробнее на каждом из этих убеждений. Надо сказать, что ты можешь высечь все эти убеждения на камне и использовать этот камень у себя вместо спальной подушки. Ты должна на собственном опыте убедиться в правоте этих убеждений. Эти убеждения - не что-то волшебное. Они просто сама суть жизнь, реальное положение вещей. Всё перечисленное - факты. Зная настоящие правила игры, ты получаешь шанс выиграть в этой игре. Только так, а руководствуясь ложными убеждениями ты всегда будешь оставаться в дурах.<br/>
|
||||
  Если ты хочешь достичь определенной цели - тебе нужны истинные знания. Только истинные знания позволят достичь цели. Все неистинные знания (ложь) забирают твое время, силы и уводят от нужного результата. Если бы ты могла жить вечно и при этом сохранить свою привлекательность, тебе не понадобилась бы эта книга. Просто экспериментируя и набивая себе шишки, исследовав все ложные тропы, ты нашла бы одну истинную и достигла бы нужного тебе результата. Но в жизни не так. У успешных спортсменов - выдающиеся тренера. У успешных бизнесменов - выдающиеся наставники. Человек даже писать и читать без учителя не научится. И в соблазнении у тебя есть учителя, только это слабые и некомпетентные учителя, поэтому учась у них, ты останешься такой же некомпетентной. Кто твои учителя? Правильно, это те люди, с которыми ты общаешься на темы соблазнения, т.е. твои подруги. Возможно, мама. Это уже лучше. Потому что она-то уж точно желает тебе добра, а насчет подруг - большой вопрос. В общем, послушай человека, достигшего определенных успехов в этом вопросе, т.е. меня. Даже если ты просто прочитаешь эту книгу, тебе станет гораздо легче. А уж если ты и задания будешь выполнять, а потом изучишь и вторую мою книгу… Истинно тебе говорю - ты будешь смеяться над своим текущим уровнем в общении с парнями.<br/>
|
||||
  Ты что-нибудь знаешь про метод тотальной бомбежки? Есть такой метод. Сделай себе шпаргалку с этими убеждениями, заглядывай в нее каждые полчаса и размышляй над тем убеждением, которое первым бросится тебе в глаза. Думай и думай - задавай себе вопросы - “А почему так? Какая мне польза от этого убеждения? Какие истории из моей жизни или жизни моих подруг подтверждают правильность этих убеждений?” Твой мозг должен вскипеть от такой работы. Думай и думай над этими убеждениями. Выучи их наизусть так, чтобы они от зубов твоих отлетали. После этого ты должна “вылизать”, “обсосать” каждое из этих убеждений, обсмаковать, понять в тончайших деталях, а это уже делается только на практике и только с помощью практики. Обязательно проверь их на практике, впитай в себя, а не то грош цена всем твоим стараниям.<br/>
|
||||
  Многие из этих убеждений очень глубокие, глубже и мощнее наших океанов, и для того, чтобы они стали частью тебя, тебе потребуется много практики и несколько лет жизни. Но это стоит того. Всё, что ты тратишь на улучшение - это только время и старания. Больше ничего. И это ничтожная цена за то, кем ты станешь. После всего пары лет упорной работы ты настолько изменишься в лучшую сторону, что будешь смотреть на себя теперешнюю как на слепого котенка. Тебе будет смешно. Ты будешь смотреть на своих сверстниц и ощущать огромнейшую разницу между тобой и ними. Тебе захочется им помочь, ты будешь смотреть на них, как на слепых котят, которые бьются головой об ножку стула и не могут ее обойти. Ты также будешь насквозь видеть мужчин, ты будешь чувствовать, на каком этапе игра, все будет под твоим контролем. Ты выйдешь на недостижимый для миллионов девушек уровень. У тебя откроются глаза. Ты ни за что не захочешь возвращаться в свое текущее состояние. Но для этого тебе надо начать действовать, да, черт подери, тупо начать действовать! Первый этап работы - перепрошивка мозга.<br/>
|
||||
  Итак, убеждения.
|
@ -1,37 +0,0 @@
|
||||
<div style="color: #f54b7e; font-weight: bold; font-size: 1.5em;">Глава 2. Ближний бой</div>
|
||||
|
||||
### <span style="color: #f54b7e;">Введение</span>
|
||||
|
||||
  Эта глава — самая важная глава в моей второй книге. Умение калибровать, несомненно, тоже важно. Но калибровать — природный дар девушек, вы очень быстро этому и обучаетесь, и изначально почти умеете. Именно поэтому во второй книге я сделал акцент не на калибровке, а именно на умении так влюбить в себя парня, что он будет помнить тебя даже перед лицом смерти. Техники влюбления… здесь я рассказываю далеко не очевидные вещи. Но они очень важны, очень. Крутую соблазнительницу от неопытной девушки отличают действия. Если они обе одинаково красивы, одинаково стильны, одинаково умны и приветливы, то всё, что их отличает, это действия. Соблазнительница просто действует по-другому, она делает другие вещи. Вот и всё. И я еще раз повторяю, ты не сможешь сама догадаться до тех фишек, которые проворачивает соблазнительница. Те фишки, о которых ты узнаешь из моей книги, я смог синтезировать, только на основе моего опыта и природной склонности к анализу. Физико-математический лицей и 4 года аспирантуры сделали свое дело. У меня есть природная склонность анализировать, я люблю думать. Мне нравится сам процесс мышления. Чтобы начать думать в правильном русле, нужны правильные знания, правильный опыт. На приобретение этого пресловутого опыта в лучшем случае может уйти год. У меня ушло больше, не было наставника. Приходилось до многих вещей доходить самому[1] .
|
||||
Но видимо у тебя хорошая карма, если в своих руках ты держишь эту книгу. Поэтому я не буду тебе рассказывать всякую чушь, которую пишут авторы-женщины в своих псевдо-учебниках по скрытому управлению мужчинами, соблазнению и т.д. Я пишу самую суть правды. Хотя, может это и не так уж плохо, что в теме соблазнения мужчин, все авторы — сплошные лохушки, пишущие о ширине твоего каблука, который должен быть на первом свидании. Что тебе идет, то и носи. Вот и вся правда про одежду. На фоне авторов, ничего не смыслящих в соблазнении, я выгляжу круче. Я удовлетворяю свой эгоизм, свою самовлюбленность и прочие черные стороны своей личности. Мой уровень, то качество материала, который я выдаю, становятся еще выше и качественнее на фоне псевдоспециалистов. Обычные авторы, которые пишут про соблазнение — это псевдоспециалисты. Спасибо вам, авторы-лохи, вы позволяете ощутить мне свою исключительность. А любому мужчине это очень приятно.
|
||||
|
||||
### <span style="color: #f54b7e;">Техника влюбления</span>
|
||||
|
||||
_Здесь даются реальные знания._<br/>
|
||||
_Гарвард_
|
||||
|
||||
  Механизм мужской и женской влюбленностей<br/>
|
||||
Механизмы мужской и женской влюбленностей несколько разнятся. Т.е. мужчины и женщины, парни и девушки влюбляются по-разному. У девушек крышу сразу не сносит, а у парней крышу сносит именно сразу. В этом и заключается принципиальное различие в механизмах. Безусловно, эта разница — классика, поэтому на этот счет есть вариации. Однако, по своей сути, так оно и есть. На первых порах отношений девушка способна трезво оценивать парня. Она еще не влюбилась, она оценивает, присматривается, приценивается к парню. Он ей нравится, но она может трезво мыслить. Видишь эти два графика ниже по тексту[2]? Теперь ты понимаешь различие в механизмах.
|
||||
Когда отношения с девушкой только начинаются, когда еще не было секса, парень испытывает некое подобие эйфории и одновременной зависимости от девушки. Я опять же говорю о классическом случае. Парень пытается быть максимально хорошим для нее. Она ему нравится, он запал на нее. Все его мысли — о ней. Девушка же влюбляется с задержкой по времени, когда парень пройдет ее фильтры. Когда у нее “щелкнет” в голове, тогда она и влюбляется.
|
||||
|
||||
<div style="display:flex; flex-direction: column; justify-content: center; align-items: center;">
|
||||

|
||||
Рисунок 5 — Различия между мужской и женской схемами влюбления<br/>
|
||||
_Иллюстрация создана автором книги_
|
||||
</div>
|
||||
|
||||
  Смотри, как выгодно для тебя устроила природа. Ты еще ничего не сделала в плане развития отношений, но уже имеешь бонус. Красота!! Спасибо матери-природе. Такой механизм — следствие заботы о выживании рода, вида. Вид должен выжить. Поэтому тебе дается время на фильтрацию самцов, чтобы ты могла выбрать лучшего и получить его семя. Самый живучий самец, самец, обошедший своих сородичей, самый жизнеспобный, способен дать тебе лучшее семя среди своих представителей. Так ты сможешь родить наиболее жизнеспособного ребенка, самого живучего. Забеременев же от слабого самца, ты родишь слабое потомство. Именно из-за такого механизма выживания вида парень сразу испытывает влечение к девушке, но после первого секса сразу же остывает к ней. Его задача выполнена, он оплодотворил самку. Его следующая задача — найти новую самку и оплодотворить ее. Поэтому он также быстро “западает” на следующую, трахает ее, остывает к ней и ищет новую. Парень выполняет задачу продолжения рода: совокупляется с максимальным количеством девушек.
|
||||
Но для нас с тобой сейчас самое важное — работать в зоне t — фильтрации. Как раз в период, который тебе подарила мать-природа, ты должна работать над отношениями. Тебе дали бонус в виде времени, не просри его. Те фишки, которые я тебе даю, имеют максимальную эффективность как раз в период фильтрации самцов. Как только вы переспите, период фильтрации закончится. И эффективность любых манипулятивных фишек, даже от Вино Галанте, упадет в разы. Это же так просто!! Ты пропустила парня через свои фильтры. Мать-природа позаботилась о том, чтобы сразу после этого ему захотелось другую самку. Как только ему захотелось другую, тебе становится архисложно влиять на парня. Природа, природа, против нее не поспоришь.
|
||||
Сколько времени длится период фильтрации самцов? Запомни, в соблазнении отсутствует время как таковое, в соблазнении присутствует качество. Поэтому период фильтрации может длиться один час, а может год или два. Здесь все зависит от твоего уровня. Но период фильтрации заканчивается первым сексом. Потому что ты уже отфильтровала парня. Раз ты его отфильтровала, как же может продолжаться фильтрация? Правильно, никак. А начинается период первой коммуникацией, считай, что словом “Привет”. Видишь, никаких времен, только условия.
|
||||
|
||||
### <span style="color: #f54b7e;">Главный секрет влюбления</span>
|
||||
|
||||
  Для того, чтобы парень влюбился в тебя, необходимо и достаточно выполнения всего четырех условий. На самом деле, когда ты работаешь по влюблению в себя парня, ты действуешь согласно всего четырем правилам. Все эти четыре правила или условия являются необходимыми и достаточными. Необходимые, значит, требуется выполнение всех четырех условий, чтобы в тебя влюбились. Достаточные, значит, требуется выполнение только этих четырех условий и никаких больше.
|
||||
Для влюбления парня **необходимы и достаточны 4 условия**:
|
||||
|
||||
- **Подстройка ментальная** — совпадение мышления.
|
||||
- **Подстройка по ценностям** — общие принципы жизни.
|
||||
- **Поведение** — действия, которые цепляют.
|
||||
- **Достаточное качество девушки** — внешность, интеллект, харизма.
|
||||
|
||||
  Выбей этот секрет влюбления на огромном камне и используй этот камень вместо подушки. Только что я рассказал тебе главный секрет влюбления в себя мужчины. Или девушки, здесь нет никакой разницы, кстати. Есть всего четыре вещи: ментальная подстройка, подстройка по ценностям, твое качество и твое поведение. Всё, больше ничего нет. Больше ничего не требуется, чтобы влюбить в себя абсолютно любого парня. Самое сложное, над чем приходится работать обычной девушке — ее качество. Если же ты родилась с внешностью Адрианы Лимы или Миранды Керр, да еще и с головой на плечах. Тогда тебе крупно повезло, работать придется не так уж и много. Ты — девушка высокого качества. Четвертый пункт удовлетворен.
|
Before Width: | Height: | Size: 38 KiB |
@ -1,7 +1,10 @@
|
||||
import { globalIgnores } from 'eslint/config'
|
||||
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
|
||||
import pluginVue from 'eslint-plugin-vue'
|
||||
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
|
||||
import { globalIgnores } from "eslint/config";
|
||||
import {
|
||||
defineConfigWithVueTs,
|
||||
vueTsConfigs,
|
||||
} from "@vue/eslint-config-typescript";
|
||||
import pluginVue from "eslint-plugin-vue";
|
||||
import skipFormatting from "@vue/eslint-config-prettier/skip-formatting";
|
||||
|
||||
// To allow more languages other than `ts` in `.vue` files, uncomment the following lines:
|
||||
// import { configureVueProject } from '@vue/eslint-config-typescript'
|
||||
@ -10,19 +13,18 @@ import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
|
||||
|
||||
export default defineConfigWithVueTs(
|
||||
{
|
||||
name: 'app/files-to-lint',
|
||||
files: ['**/*.{ts,mts,tsx,vue}'],
|
||||
name: "app/files-to-lint",
|
||||
files: ["**/*.{ts,mts,tsx,vue}"],
|
||||
},
|
||||
|
||||
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**', './src/generated/**']),
|
||||
globalIgnores([
|
||||
"**/dist/**",
|
||||
"**/dist-ssr/**",
|
||||
"**/coverage/**",
|
||||
"./src/generated/**",
|
||||
]),
|
||||
|
||||
pluginVue.configs['flat/essential'],
|
||||
pluginVue.configs["flat/essential"],
|
||||
vueTsConfigs.recommended,
|
||||
skipFormatting,
|
||||
{
|
||||
rules: {
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
|
||||
},
|
||||
},
|
||||
)
|
||||
skipFormatting
|
||||
);
|
||||
|
2
frontend.env.example
Normal file
@ -0,0 +1,2 @@
|
||||
VITE_MODE=DEVELOP
|
||||
VITE_API_BASE_PATH=http://localhost:5173/
|
21
index.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link href="/src/style.css" rel="stylesheet" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Russo+One&display=swap" rel="stylesheet" />
|
||||
<title>e-book</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,3 +0,0 @@
|
||||
export { default as footerNavigation } from '@/layouts/UiFooter/_data/footer-navigation.data'
|
||||
|
||||
export { default as refLitres } from '@/layouts/UiFooter/_data/ref-litres.data'
|
@ -1 +0,0 @@
|
||||
export { default as headerNavigation } from '@/layouts/UiHeader/_data/header-navigation.data'
|
@ -1,53 +0,0 @@
|
||||
import config from './config'
|
||||
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
import head from './config/head'
|
||||
// import sitemap from "./config/sitemap";
|
||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: '2025-05-15',
|
||||
devtools: { enabled: true },
|
||||
|
||||
devServer: {
|
||||
host: 'localhost',
|
||||
port: 4002,
|
||||
},
|
||||
|
||||
nitro: {
|
||||
output: {
|
||||
dir: './dist',
|
||||
},
|
||||
},
|
||||
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./', import.meta.url)),
|
||||
},
|
||||
|
||||
css: ['@/assets/css/tailwind.css'],
|
||||
...config,
|
||||
|
||||
htmlValidator: {
|
||||
usePrettier: true,
|
||||
logLevel: 'error',
|
||||
failOnError: false,
|
||||
},
|
||||
|
||||
app: {
|
||||
head: {
|
||||
title: 'Vino Galante',
|
||||
htmlAttrs: {
|
||||
lang: 'ru',
|
||||
},
|
||||
...head,
|
||||
},
|
||||
},
|
||||
|
||||
runtimeConfig: {
|
||||
smtpHost: process.env.SMTP_HOST,
|
||||
smtpPort: process.env.SMTP_PORT,
|
||||
smtpUser: process.env.SMTP_USER,
|
||||
smtpPass: process.env.SMTP_PASS,
|
||||
},
|
||||
|
||||
modules: [...config.modules],
|
||||
})
|
5918
package-lock.json
generated
Normal file
63
package.json
@ -1,56 +1,43 @@
|
||||
{
|
||||
"name": "e-book",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare",
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc -b && vite build",
|
||||
"preview": "vite preview",
|
||||
"prepare": "husky",
|
||||
"lint": "node_modules/.bin/eslint . --fix",
|
||||
"format": "node_modules/.bin/prettier --write ./"
|
||||
"format": "node_modules/.bin/prettier --write ./src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@a2seven/yoo-checkout": "^1.1.4",
|
||||
"@nuxt/content": "^3.6.0",
|
||||
"@nuxt/fonts": "^0.11.4",
|
||||
"@nuxt/icon": "^1.13.0",
|
||||
"@nuxt/image": "^1.10.0",
|
||||
"@nuxtjs/html-validator": "^2.1.0",
|
||||
"@nuxtjs/robots": "^5.2.10",
|
||||
"@nuxtjs/sitemap": "^7.4.0",
|
||||
"@pinia/nuxt": "^0.5.5",
|
||||
"@tailwindcss/postcss": "^4.1.10",
|
||||
"better-sqlite3": "^12",
|
||||
"crypto-js": "^4.2.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"husky": "^9.1.7",
|
||||
"nodemailer": "^7.0.3",
|
||||
"nuxt": "^3.17.5",
|
||||
"nuxt-schema-org": "^5.0.5",
|
||||
"pg": "^8.16.2",
|
||||
"postgres": "^3.4.7",
|
||||
"@tailwindcss/vite": "^4.1.8",
|
||||
"@vueuse/head": "^2.0.0",
|
||||
"pinia": "^3.0.3",
|
||||
"swiper": "^11.2.8",
|
||||
"vue": "^3.5.16"
|
||||
"tailwindcss": "^4.1.8",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/eslint": "^1.4.1",
|
||||
"@nuxt/test-utils": "^3.11.3",
|
||||
"@nuxtjs/tailwindcss": "^6.11.4",
|
||||
"@types/node": "^22.0.0",
|
||||
"@types/nodemailer": "^6.4.17",
|
||||
"@types/pg": "^8.15.4",
|
||||
"@tsconfig/node22": "^22.0.1",
|
||||
"@types/node": "^22.14.0",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"@vue/eslint-config-prettier": "^10.2.0",
|
||||
"@vue/eslint-config-typescript": "^14.5.0",
|
||||
"autoprefixer": "^10.4.18",
|
||||
"eslint": "^9.29.0",
|
||||
"eslint-plugin-vue": "^10.0.0",
|
||||
"postcss": "^8.5.6",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"eslint": "^9.22.0",
|
||||
"eslint-plugin-vue": "~10.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"jiti": "^2.4.2",
|
||||
"npm-run-all2": "^7.0.2",
|
||||
"playwright": "^1.52.0",
|
||||
"prettier": "3.5.3",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "~5.8.3",
|
||||
"vite": "^6.3.5",
|
||||
"vite-plugin-vue-devtools": "^7.7.2",
|
||||
"vue-tsc": "^2.2.8"
|
||||
}
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||
}
|
||||
|
@ -1,175 +0,0 @@
|
||||
<template>
|
||||
<div v-if="content" class="relative z-50 min-h-screen text-white mb-[208px] ml-4">
|
||||
<section class="flex flex-col relative z-40 mt-40 ml-18 mr-18">
|
||||
<div v-html="renderedContent" class="prose prose-invert max-w-none"></div>
|
||||
</section>
|
||||
</div>
|
||||
<div v-else class="text-white text-center py-20">Глава не найдена.</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Получаем параметры из URL
|
||||
const route = useRoute()
|
||||
const bookSlug = route.params.slug as string
|
||||
const chapterSlug = route.params.chapter as string
|
||||
|
||||
// Загружаем контент из markdown файла
|
||||
const { data: content } = await useAsyncData(`book-${bookSlug}-${chapterSlug}`, () => {
|
||||
return $fetch(`/api/content/books/${chapterSlug}`)
|
||||
})
|
||||
|
||||
// Конвертируем markdown в HTML (простая реализация)
|
||||
const renderedContent = computed(() => {
|
||||
if (!content.value?.content) return ''
|
||||
|
||||
let html = content.value.content
|
||||
|
||||
// Заменяем заголовки
|
||||
html = html.replace(
|
||||
/^### (.*$)/gim,
|
||||
'<h3 style="color: #f54b7e; font-weight: bold; margin-top: 1.5rem; margin-bottom: 0.5rem;">$1</h3>',
|
||||
)
|
||||
html = html.replace(
|
||||
/^## (.*$)/gim,
|
||||
'<h2 style="color: #f54b7e; font-weight: bold; margin-top: 2rem; margin-bottom: 1rem;">$1</h2>',
|
||||
)
|
||||
html = html.replace(
|
||||
/^# (.*$)/gim,
|
||||
'<h1 style="color: #f54b7e; font-weight: bold; font-size: 1.5em; margin-bottom: 1rem;">$1</h1>',
|
||||
)
|
||||
|
||||
// Заменяем параграфы
|
||||
html = html.replace(
|
||||
/^  (.*$)/gim,
|
||||
'<p style="margin-bottom: 1rem; line-height: 1.6;">$1</p>',
|
||||
)
|
||||
|
||||
// Заменяем жирный текст (двойные звездочки)
|
||||
html = html.replace(/\*\*(.*?)\*\*/g, '<strong style=" font-weight: bold;">$1</strong>')
|
||||
|
||||
// Заменяем курсив (звездочки)
|
||||
html = html.replace(/\*(.*?)\*/g, '<em style="font-style: italic;">$1</em>')
|
||||
|
||||
// Заменяем курсив (подчеркивания)
|
||||
html = html.replace(/\_(.*?)\_/g, '<em style="font-style: italic;">$1</em>')
|
||||
|
||||
// Заменяем изображения - исправляем пути
|
||||
html = html.replace(
|
||||
/!\[([^\]]*)\]\(([^)]+)\)/g,
|
||||
'<img src="/img/books/$2" alt="$1" style="max-width: 100%; height: auto; margin: 1rem 0; display: block;" />',
|
||||
)
|
||||
|
||||
// Заменяем списки
|
||||
html = html.replace(/^- (.*$)/gim, '<li style="margin-bottom: 0.5rem;">$1</li>')
|
||||
html = html.replace(/(<li.*<\/li>)/s, '<ul style="margin-bottom: 1rem;">$1</ul>')
|
||||
|
||||
// Заменяем <br/> теги на HTML <br>
|
||||
html = html.replace(/<br\/>/g, '<br>')
|
||||
|
||||
// Заменяем переносы строк
|
||||
html = html.replace(/\n/g, '<br>')
|
||||
|
||||
return html
|
||||
})
|
||||
|
||||
// Устанавливаем мета-теги
|
||||
useHead({
|
||||
title: `Глава ${chapterSlug} | Книга ${bookSlug} | Vino Galante`,
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content: `Читайте главу ${chapterSlug} из книги ${bookSlug} автора Vino Galante`,
|
||||
},
|
||||
],
|
||||
link: [
|
||||
{
|
||||
rel: 'canonical',
|
||||
href: `https://ebook.miduway.space/books/${bookSlug}/chapters/${chapterSlug}`,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
// Обработка ошибок, если файл не найден
|
||||
if (!content.value) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: 'Глава не найдена',
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* Дополнительные стили для контента */
|
||||
.prose {
|
||||
color: white;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.prose h1 {
|
||||
color: #f54b7e;
|
||||
font-weight: bold;
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.prose h2 {
|
||||
color: #f54b7e;
|
||||
font-weight: bold;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.prose h3 {
|
||||
color: #f54b7e;
|
||||
font-weight: bold;
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.prose p {
|
||||
margin-bottom: 1rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.prose ul {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.prose li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.prose strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.prose em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.prose blockquote {
|
||||
border-left: 4px solid #f54b7e;
|
||||
padding-left: 1rem;
|
||||
margin: 1rem 0;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.prose img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin: 1rem 0;
|
||||
display: block;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Стили для подписей к изображениям */
|
||||
.prose img + br + em {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
color: #f54b7e;
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
</style>
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Как влюбить в себя любого \n Книга I. \n Откровения бывшего Казановы",
|
||||
"src": "/img/books/book1.png",
|
||||
"buy": "добавить Книгу I",
|
||||
"price": 520,
|
||||
"message": "💡 Купи обе книги и получи \n скидку 10% - 936 за комплект"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Как влюбить в себя любого \n Книга II. \n Тонкая игра",
|
||||
"src": "/img/books/book2.png",
|
||||
"buy": "добавить Книгу II",
|
||||
"price": 520,
|
||||
"message": "💡 Купи обе книги и получи \n скидку 10% - 936 за комплект"
|
||||
}
|
||||
],
|
||||
"message": "💡 Купи обе книги и получи скидку 10% - 936 за комплект"
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
<template>
|
||||
<section class="relative z-50 ml-4">
|
||||
<UiHeading tag="h1" size="300" class="font-bold mb-16"> Корзина </UiHeading>
|
||||
<div class="-ml-6">
|
||||
<div
|
||||
v-for="({ name, src, price, message, buy, id }, index) in cartList.items"
|
||||
:key="index"
|
||||
class="flex items-start mb-24"
|
||||
>
|
||||
<div class="w-40 h-40 relative -top-5">
|
||||
<img :src="`${src}`" alt="book" />
|
||||
</div>
|
||||
<UiParagraph size="300" class="whitespace-pre mb-10 mr-12 w-80">{{ name }}</UiParagraph>
|
||||
<UiParagraph size="300" class="whitespace-pre mb-10 mr-20">{{ message }}</UiParagraph>
|
||||
<UiButton
|
||||
:id="id"
|
||||
class="mb-10"
|
||||
v-if="store.getQuantity(id) === 0"
|
||||
@click="handleAddToCart(id)"
|
||||
>{{ buy }}</UiButton
|
||||
>
|
||||
<template v-else>
|
||||
<div class="flex items-center gap-8 mr-20">
|
||||
<button
|
||||
class="w-8 h-8 flex items-center justify-center rounded-full border border-white text-white text-2xl"
|
||||
@click="handleRemove(id)"
|
||||
aria-label="Уменьшить количество"
|
||||
>
|
||||
−
|
||||
</button>
|
||||
<span class="text-white text-2xl">{{ store.getQuantity(id) }}</span>
|
||||
<button
|
||||
class="w-8 h-8 flex items-center justify-center rounded-full border border-white text-white text-2xl"
|
||||
@click="handleIncrement(id)"
|
||||
aria-label="Увеличить количество"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
<span class="text-white text-2xl font-bold mr-20 whitespace-nowrap">
|
||||
{{ Number(price) * store.getQuantity(id) }} ₽
|
||||
</span>
|
||||
<button
|
||||
class="w-8 h-8 flex items-center justify-center rounded-full border border-white text-white text-xl"
|
||||
@click="handleRemove(id)"
|
||||
aria-label="Удалить товар"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
<div class="flex items-center justify-end mt-8">
|
||||
<UiParagraph is="span" size="300">Общая стоимость</UiParagraph>
|
||||
<template v-if="isSpecialPrice">
|
||||
<span class="text-white text-2xl font-bold ml-4 line-through select-none">
|
||||
{{ regularTotalPrice }} ₽
|
||||
</span>
|
||||
<span class="text-primary text-3xl font-bold ml-4">
|
||||
{{ store.getTotalPrice(cartList.items) }} ₽
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="text-primary text-3xl font-bold ml-4">
|
||||
{{ store.getTotalPrice(cartList.items) }} ₽
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-10 flex flex-col items-center justify-center">
|
||||
<UiButton class="w-[660px]"> перейти к оформлению </UiButton>
|
||||
<UiParagraph is="span" size="300" class="mb-10 mt-5"
|
||||
>После оплаты книги сразу будут доступны для скачивания</UiParagraph
|
||||
>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import cartList from './_data/cart.json'
|
||||
import UiHeading from '~/components/Typography/UiHeading.vue'
|
||||
import UiParagraph from '~/components/Typography/UiParagraph.vue'
|
||||
import { useSelectedBook } from '@/store/useSelectedBook'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const store = useSelectedBook()
|
||||
|
||||
function handleIncrement(id: number) {
|
||||
store.increment(id)
|
||||
}
|
||||
|
||||
function handleDecrement(id: number) {
|
||||
store.decrement(id)
|
||||
}
|
||||
|
||||
function handleRemove(id: number) {
|
||||
store.reset(id)
|
||||
}
|
||||
|
||||
function handleAddToCart(id: number) {
|
||||
store.addToCart(id)
|
||||
}
|
||||
|
||||
const selectedBooksCount = computed(() => store.cartQuantities.filter((i) => i.quantity > 0).length)
|
||||
|
||||
const isSpecialPrice = computed(() => selectedBooksCount.value === 2)
|
||||
|
||||
const regularTotalPrice = computed(() => {
|
||||
// Сумма без скидки
|
||||
return store.cartQuantities.reduce((sum, item) => {
|
||||
const book = cartList.items.find((b: any) => b.id === item.id)
|
||||
return sum + (book ? Number(book.price) * item.quantity : 0)
|
||||
}, 0)
|
||||
})
|
||||
</script>
|
@ -1,19 +0,0 @@
|
||||
<template>
|
||||
<div class="relative z-50 text-black min-h-screen py-12">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-8">
|
||||
<UiHeading tag="h1" size="500" class="font-bold text-primary mb-4"
|
||||
>Контактные данные</UiHeading
|
||||
>
|
||||
</div>
|
||||
|
||||
<EmailForm />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import UiHeading from '~/components/Typography/UiHeading.vue'
|
||||
|
||||
// Страница использует компонент EmailForm
|
||||
</script>
|
@ -1,37 +0,0 @@
|
||||
<template>
|
||||
<section class="flex flex-row">
|
||||
<div
|
||||
class="lg:w-5/12 pl-5 pr-5 shadow-md bg-[url('/assets/img/png/shadow.png')]"
|
||||
>
|
||||
<UiHeading tag="h2" size="300" class="text-three mb-4 mt-5">
|
||||
💔 Ты не одна.
|
||||
<br />Я знаю, через что ты<br />
|
||||
проходишь.
|
||||
</UiHeading>
|
||||
<UiParagraph size="250" class="xl:max-w-[392px] mb-5"
|
||||
>Когда ты снова и снова отдаёшь сердце, а в ответ — тишина или игра, это
|
||||
ранит. Я знаю это чувство. Я был по ту сторону: манипулировал,
|
||||
очаровывал, уходил.
|
||||
|
||||
<br /><br />Я — бывший Казанова. И однажды я понял: больше так нельзя.
|
||||
|
||||
<br /><br />Эти книги — не теория. Это ключ к пониманию, как устроена
|
||||
мужская психология, чего на самом деле хочет мужчина, и как перестать
|
||||
теряться в отношениях.
|
||||
|
||||
<br /><br />Я написал их для тебя — чтобы ты могла быть счастливой, не
|
||||
прогибаясь, не умоляя, не теряя себя. Если ты устала «играть», если
|
||||
хочешь любви по-настоящему — начни с первой страницы. В этих книгах нет
|
||||
воды. Только правда.</UiParagraph
|
||||
>
|
||||
</div>
|
||||
<div class="lg:w-7/12">
|
||||
<NuxtImg src="/img/webp/meetingAlone.webp" alt="meeting" loading="lazy" />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import UiHeading from "@/components/Typography/UiHeading.vue";
|
||||
import UiParagraph from "@/components/Typography/UiParagraph.vue";
|
||||
</script>
|
@ -1,31 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<section class="relative z-50">
|
||||
<HeroBanner
|
||||
class="pt-28 bg-[url('/assets/img/png/bg.png')] z-40 bg-no-repeat bg-[400px] rounded-[50px] relative after:absolute after:bg-[url('/assets/img/webp/header-flowers-4.webp')] after:top-0 after:w-[418px] after:right-0 after:h-[230px] after:z-20 after:content-[''] after:bg-contain after:bg-no-repeat after:bg-right"
|
||||
/>
|
||||
<ForYouSection class="mt-40 pl-16 pr-24" />
|
||||
<YouNotAloneSection class="mt-40 pl-16 pr-24 mb-40" />
|
||||
<FeedbackSection class="mt-40 mb-52" />
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import FeedbackSection from "./_ui/feedbackSection/feedbackSection.vue";
|
||||
import ForYouSection from "./_ui/forYouSection/forYouSection.vue";
|
||||
import HeroBanner from "./_ui/heroBanner/heroBanner.vue";
|
||||
import YouNotAloneSection from "./_ui/youNotAloneSection/youNotAloneSection.vue";
|
||||
|
||||
useHead({
|
||||
title: "Vino Galante",
|
||||
meta: [
|
||||
{ name: "description", content: "Онлайн магазин книг автора Vino Galante" },
|
||||
],
|
||||
link: [
|
||||
{
|
||||
rel: "canonical",
|
||||
href: `https://ebook.miduway.space/`,
|
||||
},
|
||||
],
|
||||
});
|
||||
</script>
|
@ -1,104 +0,0 @@
|
||||
<template>
|
||||
<section class="relative z-50">
|
||||
<UiHeading size="300" tag="H1" class="mb-5">
|
||||
Политика конфиденциальности
|
||||
</UiHeading>
|
||||
<UiParagraph size="300" class="mb-5"
|
||||
>Настоящая политика конфиденциальности описывает, как мы собираем,
|
||||
используем и защищаем личную информацию, которую пользователи
|
||||
предоставляют при использовании нашего сайта.</UiParagraph
|
||||
>
|
||||
|
||||
<UiHeading size="300" tag="h2">1. Сбор информации</UiHeading>
|
||||
<UiParagraph size="300"
|
||||
>При оформлении заказа на сайте вы предоставляете персональные данные,
|
||||
которые включают:</UiParagraph
|
||||
>
|
||||
<ul class="list-disc pl-5 mb-3">
|
||||
<li><UiParagraph size="300">Адрес электронной почты</UiParagraph></li>
|
||||
<li><UiParagraph size="300">Имя (по желанию)</UiParagraph></li>
|
||||
</ul>
|
||||
|
||||
<UiHeading size="300" tag="h2">2. Использование информации</UiHeading>
|
||||
<UiParagraph size="300" class="mb-3"
|
||||
>Ваши личные данные используются исключительно для:</UiParagraph
|
||||
>
|
||||
<ul class="list-disc pl-5">
|
||||
<li>
|
||||
<UiParagraph size="300"
|
||||
>Обработки и выполнения вашего заказа.</UiParagraph
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<UiParagraph> Связи с вами по вопросам вашего заказа. </UiParagraph>
|
||||
</li>
|
||||
<li>
|
||||
<UiParagraph size="300" class="mb-3">
|
||||
Уведомления о важных обновлениях и новостях сайта (только если вы явно
|
||||
согласились на рассылку).</UiParagraph
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<UiHeading size="300" tag="h2">3. Защита личных данных</UiHeading>
|
||||
<UiParagraph size="300" class="mb-3">
|
||||
Мы предпринимаем необходимые меры для защиты ваших личных данных от
|
||||
несанкционированного доступа, изменения, разглашения или уничтожения.
|
||||
Доступ к личным данным имеют только сотрудники, непосредственно
|
||||
участвующие в обработке заказов.
|
||||
</UiParagraph>
|
||||
|
||||
<UiHeading size="300" tag="h2"
|
||||
>4. Передача информации третьим лицам</UiHeading
|
||||
>
|
||||
<UiParagraph size="300" class="mb-3">
|
||||
Мы не передаём ваши личные данные третьим лицам, за исключением случаев,
|
||||
предусмотренных законодательством Российской Федерации.
|
||||
</UiParagraph>
|
||||
|
||||
<UiHeading size="300" tag="h2">5. Cookies (Куки-файлы)</UiHeading>
|
||||
<UiParagraph size="300" class="mb-3">
|
||||
Мы используем файлы cookie, чтобы улучшить ваш пользовательский опыт. Вы
|
||||
можете отключить файлы cookie в настройках вашего браузера, однако это
|
||||
может ограничить доступ к некоторым функциям сайта.
|
||||
</UiParagraph>
|
||||
|
||||
<UiHeading size="300" tag="h2"
|
||||
>6. Изменения в политике конфиденциальности</UiHeading
|
||||
>
|
||||
<UiParagraph size="300" class="mb-3">
|
||||
Мы можем периодически обновлять настоящую политику конфиденциальности. Об
|
||||
изменениях мы уведомим вас, разместив новую версию политики на данной
|
||||
странице.
|
||||
</UiParagraph>
|
||||
|
||||
<UiHeading size="300" tag="h2">7. Ваше согласие</UiHeading>
|
||||
<UiParagraph size="300"
|
||||
>Используя наш сайт, вы соглашаетесь с условиями данной политики
|
||||
конфиденциальности.</UiParagraph
|
||||
>
|
||||
<UiParagraph size="300">
|
||||
Если у вас возникнут вопросы или пожелания относительно обработки ваших
|
||||
персональных данных, пожалуйста, свяжитесь с нами по электронной почте:
|
||||
<a href="mailto:vinogalante@yandex.ru">vinogalante@yandex.ru</a>.
|
||||
</UiParagraph>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import UiHeading from "@/components/Typography/UiHeading.vue";
|
||||
import UiParagraph from "@/components/Typography/UiParagraph.vue";
|
||||
|
||||
useHead({
|
||||
title: "Поликита конфиденциальности | Vino Galante",
|
||||
meta: [
|
||||
{ name: "description", content: "Онлайн магазин книг автора Vino Galante" },
|
||||
],
|
||||
link: [
|
||||
{
|
||||
rel: "canonical",
|
||||
href: `https://ebook.miduway.space/privacy`,
|
||||
},
|
||||
],
|
||||
});
|
||||
</script>
|
@ -1,46 +0,0 @@
|
||||
[
|
||||
{
|
||||
"question": "1. Как купить книгу?",
|
||||
"answer": "Чтобы купить книгу, просто перейдите на страницу соответствующей книги и нажмите кнопку «Купить». Вы будете перенаправлены в корзину, где можно подтвердить заказ и выбрать способ оплаты."
|
||||
},
|
||||
{
|
||||
"question": "2. Какие способы оплаты доступны?",
|
||||
"answer": "На сайте доступны самые удобные и безопасные способы оплаты: банковские карты (Visa, Mastercard, Мир), Система Быстрых Платежей (СБП) и сервис SberPay. Вы можете выбрать любой из них при оформлении заказа."
|
||||
},
|
||||
{
|
||||
"question": "3. Можно ли скачать книгу сразу после покупки?",
|
||||
"answer": "Да, после подтверждения покупки, ссылка на скачивание книги будет доступна сразу. Вы получите файл на указанный при заказе email, либо сможете скачать книгу непосредственно с сайта."
|
||||
},
|
||||
{
|
||||
"question": "4. Что делать, если я не могу скачать книгу?",
|
||||
"answer": "Если у вас возникли проблемы с скачиванием книги, пожалуйста, свяжитесь с нами через контактный email vinogalante@yandex.ru, и мы постараемся решить ваш вопрос как можно скорее."
|
||||
},
|
||||
{
|
||||
"question": "5. Есть ли пробный отрывок книги?",
|
||||
"answer": "Да, на каждой странице книги есть возможность ознакомиться с аннотацией и скачать отрывок или читать его прямо на сайте. Это поможет вам оценить стиль и содержание книги перед покупкой."
|
||||
},
|
||||
{
|
||||
"question": "6. Как читать книгу на мобильном устройстве?",
|
||||
"answer": "Книги можно читать на мобильных устройствах в любом формате (например, PDF). Просто скачайте файл и откройте его с помощью подходящего приложения, например, Adobe Reader для PDF."
|
||||
},
|
||||
{
|
||||
"question": "7. Можно ли вернуть книгу, если она не понравилась?",
|
||||
"answer": "К сожалению, электронные книги не подлежат возврату, поскольку они могут быть скачаны сразу после покупки. Мы рекомендуем ознакомиться с отрывком книги перед покупкой, чтобы убедиться, что она соответствует вашим ожиданиям."
|
||||
},
|
||||
{
|
||||
"question": "8. Как связаться с автором?",
|
||||
"answer": "Вы можете связаться со мной по электронной почте vinogalante@yandex.ru. Я всегда рад услышать отзывы о книгах и ответить на вопросы."
|
||||
},
|
||||
{
|
||||
"question": "9. Как узнать, когда выйдет следующая книга?",
|
||||
"answer": "На данный момент автор не планирует продолжать писать книги по данной теме. Сейчас автор сосредоточен на других проектах."
|
||||
},
|
||||
{
|
||||
"question": "10. Есть ли скидки на книги?",
|
||||
"answer": "Да, при оплате двух книг сразу предоставляется скидка 10%. Просто добавьте обе книги в корзину, и скидка будет автоматически применена при оформлении заказа."
|
||||
},
|
||||
{
|
||||
"question": "11. Могу ли я получить книгу в другом формате?",
|
||||
"answer": "На данный момент книги доступны в формате PDF, ePub. Если вам нужен другой формат, пожалуйста, свяжитесь с нами, и мы постараемся помочь."
|
||||
}
|
||||
]
|
@ -1,43 +0,0 @@
|
||||
<template>
|
||||
<section class="relative z-50 ml-4">
|
||||
<div v-for="({ question, answer }, index) in questions" :key="index" class="mb-16">
|
||||
<button
|
||||
type="button"
|
||||
@click="toggleFAQ(index)"
|
||||
class="flex gap-12 mb-5 items-baseline font-bold"
|
||||
>
|
||||
<UiParagraph as="span" size="500">
|
||||
{{ question }}
|
||||
</UiParagraph>
|
||||
<img
|
||||
src="/assets/icon/arrow.svg"
|
||||
alt="question"
|
||||
class="duration-500"
|
||||
:class="activeIndex === index ? 'rotate-90' : 'rotate-0'"
|
||||
/>
|
||||
</button>
|
||||
<Transition name="slide">
|
||||
<div v-show="activeIndex === index">
|
||||
<UiParagraph size="300">
|
||||
{{ answer }}
|
||||
</UiParagraph>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import UiParagraph from '~/components/Typography/UiParagraph.vue'
|
||||
import questions from './_data/question-answer.json'
|
||||
|
||||
const activeIndex = ref<null | number>(null)
|
||||
|
||||
const toggleFAQ = (index: number) => {
|
||||
activeIndex.value = activeIndex.value === index ? null : index
|
||||
}
|
||||
|
||||
useHead({
|
||||
title: 'Вопрос - ответ | Vino Galante',
|
||||
})
|
||||
</script>
|
@ -1,5 +0,0 @@
|
||||
export default {
|
||||
plugins: {
|
||||
"@tailwindcss/postcss": {},
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 208 KiB |
Before Width: | Height: | Size: 218 KiB |
Before Width: | Height: | Size: 38 KiB |
@ -1,15 +0,0 @@
|
||||
<svg width="63" height="54" viewBox="0 0 63 54" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_984_377)">
|
||||
<path d="M4.60144 9.38058C8.04021 8.15329 12.9711 6.8298 17.7659 6.41849C22.9338 5.97401 27.3168 6.62746 29.858 8.91288V41.2405C26.2249 39.4825 21.6205 39.2404 17.3735 39.6052C12.7884 40.0033 8.16455 41.1344 4.60144 42.2953V9.38058ZM33.7436 8.91288C36.2848 6.62746 40.6678 5.97401 45.8356 6.41849C50.6305 6.8298 55.5613 8.15329 59.0001 9.38058V42.2953C55.4331 41.1344 50.8131 40 46.2281 39.6086C41.9772 39.2404 37.3766 39.4792 33.7436 41.2405V8.91288ZM31.8008 5.9143C27.9734 3.10479 22.4248 2.68684 17.3735 3.11806C11.4906 3.62556 5.55342 5.34709 1.85431 6.78336C1.51489 6.91514 1.22707 7.12751 1.0252 7.39513C0.823323 7.66274 0.715924 7.9743 0.71582 8.2926V44.7798C0.71591 45.0573 0.797563 45.3303 0.953298 45.5739C1.10903 45.8175 1.33387 46.0238 1.60722 46.174C1.88057 46.3242 2.19369 46.4134 2.51791 46.4335C2.84212 46.4536 3.16705 46.4039 3.46295 46.289C6.89007 44.9622 12.4115 43.3667 17.762 42.9057C23.2369 42.4347 27.8258 43.1942 30.2854 45.8147C30.4674 46.0084 30.6981 46.1647 30.9604 46.2721C31.2227 46.3796 31.5099 46.4353 31.8008 46.4353C32.0917 46.4353 32.3789 46.3796 32.6412 46.2721C32.9034 46.1647 33.1341 46.0084 33.3162 45.8147C35.7758 43.1942 40.3647 42.4347 45.8356 42.9057C51.19 43.3667 56.7154 44.9622 60.1386 46.289C60.4345 46.4039 60.7594 46.4536 61.0836 46.4335C61.4079 46.4134 61.721 46.3242 61.9943 46.174C62.2677 46.0238 62.4925 45.8175 62.6483 45.5739C62.804 45.3303 62.8856 45.0573 62.8857 44.7798V8.2926C62.8856 7.9743 62.7782 7.66274 62.5764 7.39513C62.3745 7.12751 62.0867 6.91514 61.7472 6.78336C58.0481 5.34709 52.1109 3.62556 46.2281 3.11806C41.1768 2.68353 35.6281 3.10479 31.8008 5.9143Z" fill="white"/>
|
||||
<path d="M4.60144 9.38058C8.04021 8.15329 12.9711 6.8298 17.7659 6.41849C22.9338 5.97401 27.3168 6.62746 29.858 8.91288V41.2405C26.2249 39.4825 21.6205 39.2404 17.3735 39.6052C12.7884 40.0033 8.16455 41.1344 4.60144 42.2953V9.38058ZM33.7436 8.91288C36.2848 6.62746 40.6678 5.97401 45.8356 6.41849C50.6305 6.8298 55.5613 8.15329 59.0001 9.38058V42.2953C55.4331 41.1344 50.8131 40 46.2281 39.6086C41.9772 39.2404 37.3766 39.4792 33.7436 41.2405V8.91288ZM31.8008 5.9143C27.9734 3.10479 22.4248 2.68684 17.3735 3.11806C11.4906 3.62556 5.55342 5.34709 1.85431 6.78336C1.51489 6.91514 1.22707 7.12751 1.0252 7.39513C0.823323 7.66274 0.715924 7.9743 0.71582 8.2926V44.7798C0.71591 45.0573 0.797563 45.3303 0.953298 45.5739C1.10903 45.8175 1.33387 46.0238 1.60722 46.174C1.88057 46.3242 2.19369 46.4134 2.51791 46.4335C2.84212 46.4536 3.16705 46.4039 3.46295 46.289C6.89007 44.9622 12.4115 43.3667 17.762 42.9057C23.2369 42.4347 27.8258 43.1942 30.2854 45.8147C30.4674 46.0084 30.6981 46.1647 30.9604 46.2721C31.2227 46.3796 31.5099 46.4353 31.8008 46.4353C32.0917 46.4353 32.3789 46.3796 32.6412 46.2721C32.9034 46.1647 33.1341 46.0084 33.3162 45.8147C35.7758 43.1942 40.3647 42.4347 45.8356 42.9057C51.19 43.3667 56.7154 44.9622 60.1386 46.289C60.4345 46.4039 60.7594 46.4536 61.0836 46.4335C61.4079 46.4134 61.721 46.3242 61.9943 46.174C62.2677 46.0238 62.4925 45.8175 62.6483 45.5739C62.804 45.3303 62.8856 45.0573 62.8857 44.7798V8.2926C62.8856 7.9743 62.7782 7.66274 62.5764 7.39513C62.3745 7.12751 62.0867 6.91514 61.7472 6.78336C58.0481 5.34709 52.1109 3.62556 46.2281 3.11806C41.1768 2.68353 35.6281 3.10479 31.8008 5.9143Z" fill="url(#paint0_radial_984_377)" fill-opacity="0.2"/>
|
||||
</g>
|
||||
<defs>
|
||||
<radialGradient id="paint0_radial_984_377" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(31.8008 24.7048) rotate(41.336) scale(32.9053 273.844)">
|
||||
<stop stop-color="#EE70A4"/>
|
||||
<stop offset="1" stop-color="#FF33AD"/>
|
||||
</radialGradient>
|
||||
<clipPath id="clip0_984_377">
|
||||
<rect width="62.1699" height="53.0723" fill="white" transform="translate(0.71582)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.8 KiB |
@ -1,4 +1,4 @@
|
||||
<svg width="24" height="26" viewBox="0 0 24 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.19223 13.3786H4.30762V11.7148H5.19223C5.42685 11.7148 5.65185 11.8025 5.81775 11.9585C5.98365 12.1145 6.07685 12.3261 6.07685 12.5467C6.07685 12.7674 5.98365 12.979 5.81775 13.135C5.65185 13.291 5.42685 13.3786 5.19223 13.3786ZM11.3845 16.7062V11.7148H12.2692C12.5038 11.7148 12.7288 11.8025 12.8947 11.9585C13.0606 12.1145 13.1538 12.3261 13.1538 12.5467V15.8743C13.1538 16.0949 13.0606 16.3065 12.8947 16.4625C12.7288 16.6185 12.5038 16.7062 12.2692 16.7062H11.3845Z" fill="#C01F64"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.769531 2.56306C0.769531 1.90116 1.04913 1.26638 1.54682 0.798349C2.04452 0.330319 2.71953 0.0673828 3.42338 0.0673828L17.9435 0.0673828L23.7695 5.54622V22.5285C23.7695 23.1903 23.4899 23.8251 22.9922 24.2932C22.4945 24.7612 21.8195 25.0241 21.1157 25.0241H3.42338C2.71953 25.0241 2.04452 24.7612 1.54682 24.2932C1.04913 23.8251 0.769531 23.1903 0.769531 22.5285V2.56306ZM5.19261 10.0501H2.53876V18.369H4.30799V15.0414H5.19261C5.89645 15.0414 6.57147 14.7785 7.06916 14.3105C7.56685 13.8424 7.84645 13.2076 7.84645 12.5458C7.84645 11.8839 7.56685 11.2491 7.06916 10.781C6.57147 10.313 5.89645 10.0501 5.19261 10.0501ZM12.2695 10.0501H9.61568V18.369H12.2695C12.9734 18.369 13.6484 18.1061 14.1461 17.638C14.6438 17.17 14.9234 16.5352 14.9234 15.8733V12.5458C14.9234 11.8839 14.6438 11.2491 14.1461 10.781C13.6484 10.313 12.9734 10.0501 12.2695 10.0501ZM16.6926 18.369V10.0501H22.0003V11.7139H18.4618V13.3776H20.2311V15.0414H18.4618V18.369H16.6926Z" fill="#C01F64"/>
|
||||
<svg width="24" height="33" viewBox="0 0 24 33" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.19223 17.578H4.30762V15.3809H5.19223C5.42685 15.3809 5.65185 15.4966 5.81775 15.7026C5.98365 15.9086 6.07685 16.1881 6.07685 16.4794C6.07685 16.7708 5.98365 17.0502 5.81775 17.2562C5.65185 17.4622 5.42685 17.578 5.19223 17.578ZM11.3845 21.9722V15.3809H12.2692C12.5038 15.3809 12.7288 15.4966 12.8947 15.7026C13.0606 15.9086 13.1538 16.1881 13.1538 16.4794V20.8737C13.1538 21.165 13.0606 21.4444 12.8947 21.6504C12.7288 21.8565 12.5038 21.9722 12.2692 21.9722H11.3845Z" fill="#C01F64"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.769531 3.29567C0.769531 2.42161 1.04913 1.58334 1.54682 0.965281C2.04452 0.347222 2.71953 0 3.42338 0L17.9435 0L23.7695 7.2351V29.6611C23.7695 30.5351 23.4899 31.3734 22.9922 31.9915C22.4945 32.6095 21.8195 32.9567 21.1157 32.9567H3.42338C2.71953 32.9567 2.04452 32.6095 1.54682 31.9915C1.04913 31.3734 0.769531 30.5351 0.769531 29.6611V3.29567ZM5.19261 13.1827H2.53876V24.1683H4.30799V19.774H5.19261C5.89645 19.774 6.57147 19.4268 7.06916 18.8088C7.56685 18.1907 7.84645 17.3524 7.84645 16.4784C7.84645 15.6043 7.56685 14.766 7.06916 14.148C6.57147 13.5299 5.89645 13.1827 5.19261 13.1827ZM12.2695 13.1827H9.61568V24.1683H12.2695C12.9734 24.1683 13.6484 23.8211 14.1461 23.203C14.6438 22.5849 14.9234 21.7467 14.9234 20.8726V16.4784C14.9234 15.6043 14.6438 14.766 14.1461 14.148C13.6484 13.5299 12.9734 13.1827 12.2695 13.1827ZM16.6926 24.1683V13.1827H22.0003V15.3798H18.4618V17.5769H20.2311V19.774H18.4618V24.1683H16.6926Z" fill="#C01F64"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@ -1,3 +1,3 @@
|
||||
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.862 1.09623C10.4118 0.726207 9.85883 0.532441 9.29362 0.546625H3.26314C2.93561 0.546382 2.61125 0.616003 2.30861 0.751506C2.00597 0.88701 1.73099 1.08574 1.49939 1.33632C1.26779 1.58691 1.08412 1.88443 0.958888 2.21189C0.833653 2.53934 0.769307 2.89029 0.769532 3.24467V21.8479C0.770437 22.5631 1.03345 23.2488 1.50089 23.7546C1.96834 24.2603 2.60207 24.5449 3.26314 24.5459H21.2759C21.937 24.5449 22.5707 24.2603 23.0382 23.7546C23.5056 23.2488 23.7686 22.5631 23.7695 21.8479V6.79025C23.7686 6.07498 23.5056 5.38929 23.0382 4.88352C22.5707 4.37775 21.937 4.09318 21.2759 4.0922H12.119L11.7735 2.59884C11.6367 2.00076 11.3151 1.46938 10.862 1.09623ZM17.161 13.5927C16.4806 13.5927 15.828 13.3003 15.3469 12.7797C14.8658 12.2592 14.5955 11.5531 14.5955 10.817C14.5955 10.0808 14.8658 9.37475 15.3469 8.8542C15.828 8.33364 16.4806 8.04119 17.161 8.04119C17.8414 8.04119 18.4939 8.33364 18.975 8.8542C19.4561 9.37475 19.7264 10.0808 19.7264 10.817C19.7264 11.5531 19.4561 12.2592 18.975 12.7797C18.4939 13.3003 17.8414 13.5927 17.161 13.5927ZM9.81013 12.9432L19.1586 22.2328H3.26314C3.16906 22.2318 3.0791 22.1909 3.01258 22.119C2.94605 22.047 2.90829 21.9496 2.9074 21.8479V17.2271L8.52399 12.9432C8.7056 12.783 8.93274 12.6955 9.16706 12.6955C9.40139 12.6955 9.62853 12.783 9.81013 12.9432Z" fill="#C01F64"/>
|
||||
<svg width="24" height="31" viewBox="0 0 24 31" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.862 1.01361C10.4118 0.54615 9.85883 0.301357 9.29362 0.319278H3.26314C2.93561 0.31897 2.61125 0.406925 2.30861 0.578112C2.00597 0.749299 1.73099 1.00036 1.49939 1.31693C1.26779 1.63351 1.08412 2.00939 0.958888 2.42307C0.833653 2.83675 0.769307 3.28013 0.769532 3.72783V27.23C0.770437 28.1336 1.03345 28.9999 1.50089 29.6389C1.96834 30.2778 2.60207 30.6373 3.26314 30.6386H21.2759C21.937 30.6373 22.5707 30.2778 23.0382 29.6389C23.5056 28.9999 23.7686 28.1336 23.7695 27.23V8.20711C23.7686 7.30348 23.5056 6.43722 23.0382 5.79826C22.5707 5.1593 21.937 4.79979 21.2759 4.79856H12.119L11.7735 2.91193C11.6367 2.15634 11.3151 1.48504 10.862 1.01361ZM17.161 16.801C16.4806 16.801 15.828 16.4315 15.3469 15.7739C14.8658 15.1162 14.5955 14.2243 14.5955 13.2942C14.5955 12.3642 14.8658 11.4722 15.3469 10.8146C15.828 10.1569 16.4806 9.78748 17.161 9.78748C17.8414 9.78748 18.4939 10.1569 18.975 10.8146C19.4561 11.4722 19.7264 12.3642 19.7264 13.2942C19.7264 14.2243 19.4561 15.1162 18.975 15.7739C18.4939 16.4315 17.8414 16.801 17.161 16.801ZM9.81013 15.9804L19.1586 27.7163H3.26314C3.16906 27.7151 3.0791 27.6634 3.01258 27.5725C2.94605 27.4816 2.90829 27.3586 2.9074 27.23V21.3925L8.52399 15.9804C8.7056 15.778 8.93274 15.6674 9.16706 15.6674C9.40139 15.6674 9.62853 15.778 9.81013 15.9804Z" fill="#C01F64"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@ -1,12 +1,12 @@
|
||||
<svg width="24" height="23" viewBox="0 0 24 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M21.3585 0.232422H4.69186C3.1457 0.232422 0.845703 1.12416 0.845703 3.58064V19.2056C0.845703 21.6621 3.1457 22.5539 4.69186 22.5539H23.9226V20.3217H4.70724C4.11493 20.3083 3.40981 20.1052 3.40981 19.2056C3.40981 19.0929 3.42134 18.9925 3.44058 18.9009C3.58416 18.2581 4.18929 18.1007 4.70724 18.0896H23.9226V2.46456C23.9226 1.87256 23.6525 1.30481 23.1716 0.886201C22.6908 0.467593 22.0386 0.232422 21.3585 0.232422ZM21.3585 10.2771L18.7944 9.16099L16.2303 10.2771V2.46456H21.3585V10.2771Z" fill="url(#paint0_linear_868_365)"/>
|
||||
<path d="M21.3585 0.232422H4.69186C3.1457 0.232422 0.845703 1.12416 0.845703 3.58064V19.2056C0.845703 21.6621 3.1457 22.5539 4.69186 22.5539H23.9226V20.3217H4.70724C4.11493 20.3083 3.40981 20.1052 3.40981 19.2056C3.40981 19.0929 3.42134 18.9925 3.44058 18.9009C3.58416 18.2581 4.18929 18.1007 4.70724 18.0896H23.9226V2.46456C23.9226 1.87256 23.6525 1.30481 23.1716 0.886201C22.6908 0.467593 22.0386 0.232422 21.3585 0.232422ZM21.3585 10.2771L18.7944 9.16099L16.2303 10.2771V2.46456H21.3585V10.2771Z" fill="url(#paint1_radial_868_365)" fill-opacity="0.2"/>
|
||||
<svg width="31" height="28" viewBox="0 0 31 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24.3585 3.16504H7.69186C6.1457 3.16504 3.8457 4.05678 3.8457 6.51325V22.1383C3.8457 24.5947 6.1457 25.4865 7.69186 25.4865H26.9226V23.2543H7.70724C7.11493 23.2409 6.40981 23.0378 6.40981 22.1383C6.40981 22.0255 6.42134 21.9251 6.44058 21.8336C6.58416 21.1907 7.18929 21.0333 7.70724 21.0222H26.9226V5.39718C26.9226 4.80518 26.6525 4.23743 26.1716 3.81882C25.6908 3.40021 25.0386 3.16504 24.3585 3.16504ZM24.3585 13.2097L21.7944 12.0936L19.2303 13.2097V5.39718H24.3585V13.2097Z" fill="url(#paint0_linear_868_364)"/>
|
||||
<path d="M24.3585 3.16504H7.69186C6.1457 3.16504 3.8457 4.05678 3.8457 6.51325V22.1383C3.8457 24.5947 6.1457 25.4865 7.69186 25.4865H26.9226V23.2543H7.70724C7.11493 23.2409 6.40981 23.0378 6.40981 22.1383C6.40981 22.0255 6.42134 21.9251 6.44058 21.8336C6.58416 21.1907 7.18929 21.0333 7.70724 21.0222H26.9226V5.39718C26.9226 4.80518 26.6525 4.23743 26.1716 3.81882C25.6908 3.40021 25.0386 3.16504 24.3585 3.16504ZM24.3585 13.2097L21.7944 12.0936L19.2303 13.2097V5.39718H24.3585V13.2097Z" fill="url(#paint1_radial_868_364)" fill-opacity="0.2"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_868_365" x1="12.3842" y1="31.3428" x2="12.3842" y2="-28.1054" gradientUnits="userSpaceOnUse">
|
||||
<linearGradient id="paint0_linear_868_364" x1="15.3842" y1="34.2754" x2="15.3842" y2="-25.1728" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#E20C66"/>
|
||||
<stop offset="1" stop-color="#E20C66" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="paint1_radial_868_365" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(12.3842 11.3931) rotate(50.5894) scale(14.4454 118.907)">
|
||||
<radialGradient id="paint1_radial_868_364" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(15.3842 14.3258) rotate(50.5894) scale(14.4454 118.907)">
|
||||
<stop stop-color="#EE70A4"/>
|
||||
<stop offset="1" stop-color="#FF33AD"/>
|
||||
</radialGradient>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
1
public/vite.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -1,29 +0,0 @@
|
||||
import { readFile } from 'node:fs/promises'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const slug = getRouterParam(event, 'slug')
|
||||
|
||||
if (!slug) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: 'Slug is required'
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
// Читаем markdown файл из папки content/books
|
||||
// slug теперь представляет номер главы (1, 2, 3, etc.)
|
||||
const content = await readFile(`content/books/${slug}.md`, 'utf-8')
|
||||
|
||||
return {
|
||||
content,
|
||||
slug,
|
||||
chapter: slug
|
||||
}
|
||||
} catch (error) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: 'Глава не найдена'
|
||||
})
|
||||
}
|
||||
})
|
@ -1,53 +0,0 @@
|
||||
import nodemailer from 'nodemailer'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const { to } = await readBody(event)
|
||||
|
||||
if (!to) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: 'Bad Request: "to" field is required',
|
||||
})
|
||||
}
|
||||
|
||||
const config = useRuntimeConfig(event)
|
||||
|
||||
// Убедимся, что все переменные окружения на месте
|
||||
if (!config.smtpHost || !config.smtpPort || !config.smtpUser || !config.smtpPass) {
|
||||
console.error('SMTP configuration is missing in runtime config.')
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage: 'Internal Server Error: SMTP configuration is incomplete.',
|
||||
})
|
||||
}
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: config.smtpHost,
|
||||
port: parseInt(config.smtpPort, 10),
|
||||
secure: parseInt(config.smtpPort, 10) === 465, // true for 465, false for other ports
|
||||
auth: {
|
||||
user: config.smtpUser,
|
||||
pass: config.smtpPass,
|
||||
},
|
||||
})
|
||||
|
||||
const mailOptions = {
|
||||
from: `"Vino Galante" <${config.smtpUser}>`,
|
||||
to: to, // Отправляем на email, полученный от клиента
|
||||
bcc: config.smtpUser, // Отправляем скрытую копию самому себе для сохранения в "Отправленных"
|
||||
subject: 'Ваш заказ принят!',
|
||||
text: 'Спасибо за ваш заказ! Мы скоро свяжемся с вами для уточнения деталей.',
|
||||
html: '<b>Спасибо за ваш заказ!</b><p>Мы скоро свяжемся с вами для уточнения деталей.</p>',
|
||||
}
|
||||
|
||||
try {
|
||||
await transporter.sendMail(mailOptions)
|
||||
return { success: true, message: 'Email sent' }
|
||||
} catch (error) {
|
||||
console.error('Error sending email:', error)
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage: `Failed to send email: ${(error as Error).message || 'Unknown error'}`,
|
||||
})
|
||||
}
|
||||
})
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": "../.nuxt/tsconfig.server.json"
|
||||
}
|
10
src/App.vue
Normal file
@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<UiLayout>
|
||||
<RouterView />
|
||||
</UiLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import UiLayout from './layout/UiLayout.vue'
|
||||
import { RouterView } from 'vue-router'
|
||||
</script>
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 206 KiB |
Before Width: | Height: | Size: 251 KiB After Width: | Height: | Size: 251 KiB |
Before Width: | Height: | Size: 409 KiB After Width: | Height: | Size: 409 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 613 KiB After Width: | Height: | Size: 613 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 496 B After Width: | Height: | Size: 496 B |
13
src/components/UiButton/UiButton.params.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export const colorVariants = {
|
||||
primary: ['bg-accent-50', 'text-primary', 'hover:bg-accent-100', 'active:bg-accent-150'],
|
||||
secondary: [
|
||||
'bg-transparent',
|
||||
'text-primary',
|
||||
'hover:bg-accent-50',
|
||||
'border-accent-50',
|
||||
'border',
|
||||
'hover:bg-accent-100',
|
||||
'active:bg-accent-150',
|
||||
'cursor-pointer',
|
||||
],
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
<template>
|
||||
<component
|
||||
:is="tag"
|
||||
:type="tag === 'button' ? 'button' : ''"
|
||||
:to="path"
|
||||
:href="path"
|
||||
class="px-14 py-4 rounded-[20px] text-[30px] cursor-pointer shadow-[0px_16px_50px_-16px_rgba(229,30,125,1)]"
|
||||
:class="[baseStyle, size]"
|
||||
data-ui="ui-button"
|
||||
@ -14,7 +11,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRefs, computed } from 'vue'
|
||||
import { colorVariants } from './UiButton.params.js'
|
||||
import { colorVariants } from './UiButton.params.ts'
|
||||
|
||||
const props = defineProps({
|
||||
tag: {
|
||||
@ -32,10 +29,6 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: 'font-bold',
|
||||
},
|
||||
path: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const { tag, variants, size } = toRefs(props)
|
9
src/config/router/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import routes from './routes'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.VITE_URL),
|
||||
routes,
|
||||
})
|
||||
|
||||
export default router
|
43
src/config/router/routes.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import type { Component } from 'vue'
|
||||
|
||||
interface ChlidrenRoute {
|
||||
path: string
|
||||
name: string
|
||||
component: () => Promise<Component>
|
||||
props?: boolean
|
||||
}
|
||||
interface Route {
|
||||
path: string
|
||||
name: string
|
||||
component: () => Promise<Component>
|
||||
props?: boolean
|
||||
children?: ChlidrenRoute[]
|
||||
}
|
||||
|
||||
const routes: Route[] = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: () => import('@/pages/mainPage/indexPage.vue'),
|
||||
},
|
||||
{
|
||||
path: '/books/:slug',
|
||||
name: 'book-detail',
|
||||
component: () => import('@/pages/books/_slug/indexBookPage.vue'),
|
||||
props: true,
|
||||
children: [
|
||||
{
|
||||
path: ':titlesSlug',
|
||||
name: 'book-titles',
|
||||
component: () => import('@/pages/books/_slug/_titlesSlug/indexTitlesPage.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/privacy',
|
||||
name: 'privacy',
|
||||
component: () => import('@/pages/privacy/privacyPage.vue'),
|
||||
},
|
||||
]
|
||||
|
||||
export default routes
|
@ -25,7 +25,7 @@
|
||||
<script setup lang="ts">
|
||||
import UiParagraph from '@/components/Typography/UiParagraph.vue'
|
||||
import UiNav from '@/components/UiNav/UiNav.vue'
|
||||
import { footerNavigation, refLitres } from '@/layouts/UiFooter/_data'
|
||||
import { footerNavigation, refLitres } from '@/layout/UiFooter/_data'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
3
src/layout/UiFooter/_data/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export { default as footerNavigation } from '@/layout/UiFooter/_data/footer-navigation.data'
|
||||
|
||||
export { default as refLitres } from '@/layout/UiFooter/_data/ref-litres.data'
|
@ -13,7 +13,7 @@ const headerNavigation = [
|
||||
},
|
||||
{
|
||||
name: 'Купить',
|
||||
path: '/cart',
|
||||
path: '/buy',
|
||||
},
|
||||
{
|
||||
name: 'Отзывы',
|
1
src/layout/UiHeader/_data/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default as headerNavigation } from '@/layout/UiHeader/_data/header-navigation.data'
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
class="min-h-svh overflow-x-hidden lato-regular relative overflow-visible before:content-[''] before:absolute before:bottom-0 before:h-full before:w-full before:bg-[url(/assets/img/png/footer-flowers-2.png)] before:bg-no-repeat before:bg-bottom before:bg-contain 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 === '/books/1' || route.path === '/books/2'
|
||||
? 'bg-[linear-gradient(135deg,rgba(17,17,30,1)_10%,rgba(183,32,76,1)_170%)]'
|
||||
@ -9,15 +9,15 @@
|
||||
>
|
||||
<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(/assets/img/webp/gradient.webp)] after:bg-no-repeat after:bg-[right_top] after:bg-contain"
|
||||
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(/assets/img/webp/group-flowers.webp)] after:bg-no-repeat after:bg-[right_top] after:bg-cover"
|
||||
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(/assets/img/webp/hero-flowers.webp)] before:bg-no-repeat before:bg-left before:bg-contain"
|
||||
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-[1200px] text-primary relative">
|
16
src/main.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import { createHead } from '@vueuse/head'
|
||||
|
||||
import './style.css'
|
||||
import App from './App.vue'
|
||||
import router from '@/config/router/index'
|
||||
|
||||
const app = createApp(App)
|
||||
const head = createHead()
|
||||
|
||||
app.use(head)
|
||||
app.use(createPinia())
|
||||
app.use(router)
|
||||
|
||||
app.mount('#app')
|
@ -35,6 +35,5 @@
|
||||
}
|
||||
],
|
||||
"href": "https://www.litres.ru/58125553/",
|
||||
"hrefTitles": "title-1",
|
||||
"download": "/files/Otryvok_1.pdf"
|
||||
"hrefTitles": "title-1"
|
||||
}
|
@ -35,6 +35,5 @@
|
||||
}
|
||||
],
|
||||
"href": "https://www.litres.ru/vino-galante/kak-vlubit-v-sebya-lubogo-tonkaya-igra/",
|
||||
"hrefTitles": "title-2",
|
||||
"download": "/files/Otryvok_2.pdf"
|
||||
"hrefTitles": "title-2"
|
||||
}
|
@ -3,21 +3,11 @@
|
||||
"title": "Оглавление",
|
||||
"titleMeta": "Оглавление - Книга I",
|
||||
"sections": [
|
||||
{
|
||||
"subsections": [
|
||||
{
|
||||
"title": "Благодарности"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"subsections": [
|
||||
{
|
||||
"title": "Введение"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Введение",
|
||||
"subsections": [
|
||||
{
|
||||
"title": "Работа с любым печатным материалом"
|
||||
@ -84,29 +74,26 @@
|
||||
"title": {
|
||||
"text": "Поля-тараканы",
|
||||
"img": "/img/svg/books/1/titles-1/simple-icons_cockroachlabs.svg"
|
||||
},
|
||||
"subsections": [
|
||||
{
|
||||
"text": "Техника безопасности при работе в полях"
|
||||
},
|
||||
{
|
||||
"text": "Восстановление сил"
|
||||
},
|
||||
{
|
||||
"text": "Главный принцип развития"
|
||||
},
|
||||
{
|
||||
"text": "Техники выхода в аптайм"
|
||||
},
|
||||
{
|
||||
"text": "Действия"
|
||||
},
|
||||
{
|
||||
"text": "Результат"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"title": "Техника безопасности при работе в полях"
|
||||
},
|
||||
{
|
||||
"title": "Восстановление сил"
|
||||
},
|
||||
{
|
||||
"title": "Главный принцип развития"
|
||||
},
|
||||
{
|
||||
"title": "Техники выхода в аптайм"
|
||||
},
|
||||
{
|
||||
"title": "Действия"
|
||||
},
|
||||
{
|
||||
"title": "Результат"
|
||||
},
|
||||
{
|
||||
"title": {
|
||||
"text": "Калибровка",
|
||||
@ -128,19 +115,19 @@
|
||||
},
|
||||
"subsections": [
|
||||
{
|
||||
"text": "Определение и классификация"
|
||||
"title": "Определение и классификация"
|
||||
},
|
||||
{
|
||||
"text": "Псевдопассивная. Этап первый"
|
||||
"title": "Псевдопассивная. Этап первый"
|
||||
},
|
||||
{
|
||||
"text": "Псевдопассивная. Этап второй"
|
||||
"title": "Псевдопассивная. Этап второй"
|
||||
},
|
||||
{
|
||||
"text": "Активный тип стратегии"
|
||||
"title": "Активный тип стратегии"
|
||||
},
|
||||
{
|
||||
"text": "Третий этап. Степени кокетства"
|
||||
"title": "Третий этап. Степени кокетства"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -160,36 +147,35 @@
|
||||
"subsections": [
|
||||
{
|
||||
"title": "Введение"
|
||||
},
|
||||
{
|
||||
"text": "Физическое здоровье"
|
||||
},
|
||||
{
|
||||
"text": "Ментальный посыл. Стильность"
|
||||
},
|
||||
{
|
||||
"text": "Ментальный посыл. Внутреннее ощущение мира"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"title": "Физическое здоровье"
|
||||
},
|
||||
{
|
||||
"title": "Ментальный посыл. Стильность"
|
||||
},
|
||||
{
|
||||
"title": "Ментальный посыл. Внутреннее ощущение мира"
|
||||
},
|
||||
{
|
||||
"title": {
|
||||
"text": "Ошибки резидента",
|
||||
"img": "/img/svg/books/1/titles-1/si_error-line.svg"
|
||||
},
|
||||
"items": [
|
||||
"Косяк 1",
|
||||
"Косяк 2",
|
||||
"Полукосяк 3",
|
||||
"Косяк 4",
|
||||
"МегаКосяк 5 – опасный",
|
||||
"МегаКосяк 6 – опасный",
|
||||
"Косяк 7",
|
||||
"МегаКосяк 8 – крайне опасно",
|
||||
"МегаКосяк 9 – опасно",
|
||||
"Косяк 10",
|
||||
"Косяк 11"
|
||||
"Косак 1",
|
||||
"Косак 2",
|
||||
"Полукосак 3",
|
||||
"Косак 4",
|
||||
"МетаКосак 5 – опасный",
|
||||
"МетаКосак 6 – опасный",
|
||||
"Косак 7",
|
||||
"МетаКосак 8 – крайне опасно",
|
||||
"МетаКосак 9 – опасно",
|
||||
"Косак 10",
|
||||
"Косак 11"
|
||||
]
|
||||
},
|
||||
{
|
@ -22,16 +22,16 @@
|
||||
},
|
||||
"subsections": [
|
||||
{
|
||||
"text": "Экскурс в историю"
|
||||
"title": "Экскурс в историю"
|
||||
},
|
||||
{
|
||||
"text": "Правила формирования запасного аэродрома"
|
||||
"title": "Правила формирования запасного аэродрома"
|
||||
},
|
||||
{
|
||||
"text": "Подробнее о пятом пункте или как не врать"
|
||||
"title": "Подробнее о пятом пункте или как не врать"
|
||||
},
|
||||
{
|
||||
"text": "Следствия наличия запасного аэродрома"
|
||||
"title": "Следствия наличия запасного аэродрома"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -42,13 +42,13 @@
|
||||
},
|
||||
"subsections": [
|
||||
{
|
||||
"text": "Одежда"
|
||||
"title": "Одежда"
|
||||
},
|
||||
{
|
||||
"text": "Правильные места для свиданий"
|
||||
"title": "Правильные места для свиданий"
|
||||
},
|
||||
{
|
||||
"text": "Самое важное в свиданиях"
|
||||
"title": "Самое важное в свиданиях"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -66,6 +66,7 @@
|
||||
"img": "/img/svg/books/2/titles-2/Vector (4).svg"
|
||||
},
|
||||
"items": [
|
||||
"Механизм мужской и женской влюбленностей",
|
||||
"Главный секрет влюбления",
|
||||
"Ментальная подстройка",
|
||||
"Подстройка по ценностям",
|
||||
@ -101,13 +102,13 @@
|
||||
},
|
||||
"subsections": [
|
||||
{
|
||||
"text": "Введение"
|
||||
"title": "Введение"
|
||||
},
|
||||
{
|
||||
"text": "Оральные ласки"
|
||||
"title": "Оральные ласки"
|
||||
},
|
||||
{
|
||||
"text": "Минет"
|
||||
"title": "Минет"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -118,13 +119,13 @@
|
||||
},
|
||||
"subsections": [
|
||||
{
|
||||
"text": "Российские школы соблазнения"
|
||||
"title": "Российские школы соблазнения"
|
||||
},
|
||||
{
|
||||
"text": "Как найти соблазнителя"
|
||||
"title": "Как найти соблазнителя"
|
||||
},
|
||||
{
|
||||
"text": "История рождения одного термина"
|
||||
"title": "История рождения одного термина"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -135,22 +136,22 @@
|
||||
},
|
||||
"subsections": [
|
||||
{
|
||||
"text": "Как парни воспринимают секс"
|
||||
"title": "Как парни воспринимают секс"
|
||||
},
|
||||
{
|
||||
"text": "Девичья невинность"
|
||||
"title": "Девичья невинность"
|
||||
},
|
||||
{
|
||||
"text": "Прожим девственницы. Метод Галанте."
|
||||
"title": "Прожим девственницы. Метод Галанте."
|
||||
},
|
||||
{
|
||||
"text": "Прожим девственницы. Классический метод."
|
||||
"title": "Прожим девственницы. Классический метод."
|
||||
},
|
||||
{
|
||||
"text": "Прожим девственницы. Метод пикапера."
|
||||
"title": "Прожим девственницы. Метод пикапера."
|
||||
},
|
||||
{
|
||||
"text": "Вместо эпилога"
|
||||
"title": "Вместо эпилога"
|
||||
}
|
||||
]
|
||||
},
|
@ -1,23 +1,19 @@
|
||||
<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 !text-[24px]"
|
||||
size="500"
|
||||
>
|
||||
<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-[#E20C66] !text-[24px] [&]:font-normal">
|
||||
<UiHeading tag="H2" size="300" class="text-three [&]:font-normal">
|
||||
{{ section.title }}
|
||||
</UiHeading>
|
||||
|
||||
<!-- Subsections -->
|
||||
<div v-if="section.subsections" class="ml-10 flex flex-col gap-4">
|
||||
<div v-if="section.subsections" class="ml-6 flex flex-col gap-4">
|
||||
<div
|
||||
v-for="(subsection, subIndex) in section.subsections"
|
||||
:key="subIndex"
|
||||
@ -34,28 +30,19 @@
|
||||
:alt="subsection.title.text"
|
||||
class="w-6 h-6"
|
||||
/>
|
||||
<UiHeading
|
||||
tag="H3"
|
||||
size="300"
|
||||
class="[&]:text-[#FFFFFF] !text-[22px] [&]:font-normal"
|
||||
>
|
||||
<UiHeading tag="H3" size="300" class="[&]:font-normal">
|
||||
{{ subsection.title.text }}
|
||||
</UiHeading>
|
||||
</div>
|
||||
<!-- Regular subsection -->
|
||||
<UiHeading
|
||||
v-else
|
||||
tag="H3"
|
||||
size="300"
|
||||
class="[&]:text-[#FFFFFF] ml-1 !text-[22px] [&]:font-normal"
|
||||
>
|
||||
<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-10 flex flex-col gap-2 list-decimal">
|
||||
<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-[#CDCDCD] [&]:font-normal"
|
||||
<UiParagraph size="300" class="[&]:text-gray-200 [&]:font-normal"
|
||||
> {{ item }}</UiParagraph
|
||||
>
|
||||
</li>
|
||||
@ -64,11 +51,8 @@
|
||||
<!-- 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"
|
||||
class="[&]:text-[#CDCDCD] [&]:font-normal ml-4 [&]:text-[20px]"
|
||||
>
|
||||
{{ nestedSub.text }}
|
||||
<UiHeading tag="H4" size="300" class="[&]:text-gray-200 [&]:font-normal">
|
||||
{{ nestedSub.title }}
|
||||
</UiHeading>
|
||||
</div>
|
||||
</div>
|
||||
@ -86,6 +70,7 @@ 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 { useHead } from '@vueuse/head'
|
||||
|
||||
interface SubsectionTitle {
|
||||
text: string
|
||||
@ -96,8 +81,7 @@ interface Subsection {
|
||||
title: string | SubsectionTitle
|
||||
items?: string[]
|
||||
subsections?: Array<{
|
||||
title?: string
|
||||
text?: string
|
||||
title: string
|
||||
}>
|
||||
}
|
||||
|
||||
@ -131,6 +115,8 @@ const loadTitlesData = async (slug: string) => {
|
||||
watch(
|
||||
() => route.params.titlesSlug,
|
||||
async (newSlug) => {
|
||||
console.log('Route params changed:', route.params)
|
||||
console.log('New titlesSlug:', newSlug)
|
||||
if (newSlug) {
|
||||
await loadTitlesData(newSlug as string)
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<template v-if="book">
|
||||
<div class="relative z-50 min-h-screen text-white mb-[208px]">
|
||||
<template v-if="!route.params.chapter && !route.params.titlesSlug">
|
||||
<template v-if="!route.params.titlesSlug">
|
||||
<!--верхний блок-->
|
||||
<section
|
||||
class="flex min-h-[600px] flex-row relative z-40 before:content-[''] before:absolute before:top-[-140px] before:bg-top before:left-0 before:w-[1280px] before:h-[1000px] before:bg-[url(/assets/img/webp/vino-galante.webp)] before:bg-no-repeat before:bg-contain mt-40"
|
||||
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-[-30px] min-w-[570px]">
|
||||
<div class="flex flex-col items-center h-[600px]">
|
||||
<img :src="book.img" :alt="book.buttonText" />
|
||||
<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>
|
||||
<!--правый блок контента-->
|
||||
@ -33,20 +33,15 @@
|
||||
</section>
|
||||
</section>
|
||||
<!--средний блок-->
|
||||
<section class="flex flex-row items-center ml-12 gap-24 relative z-50">
|
||||
<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 }} </UiParagraph>
|
||||
<img src="/img/svg/books/ruble.svg" alt="ruble" />
|
||||
</div>
|
||||
<div class="flex items-center flex-col gap-3">
|
||||
<UiButton
|
||||
@click="handleSelect"
|
||||
:id="book.id"
|
||||
variants="primary"
|
||||
class="max-w-[440px] !font-normal !px-2 !py-4 mt-16"
|
||||
>
|
||||
<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">
|
||||
@ -55,29 +50,39 @@
|
||||
</div>
|
||||
</div>
|
||||
<!--правый-->
|
||||
<div class="min-h-[310px] pt-6">
|
||||
<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="24" height="24" />
|
||||
<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 shrink-0">
|
||||
<li class="flex flex-row mr-14 gap-3 items-center">
|
||||
<img
|
||||
src="/img/svg/books/book-illustrations.svg"
|
||||
alt="иллюстраций"
|
||||
width="24"
|
||||
height="24"
|
||||
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="24" height="24" />
|
||||
<img
|
||||
src="/img/svg/books/book-formats.svg"
|
||||
alt="формат"
|
||||
width="100%"
|
||||
height="100%"
|
||||
/>
|
||||
<UiParagraph size="250" as="span">
|
||||
{{ book.format }}
|
||||
</UiParagraph>
|
||||
@ -86,60 +91,51 @@
|
||||
</div>
|
||||
|
||||
<!--навигация по книге-->
|
||||
<div class="mt-28">
|
||||
<ul class="flex flex-row mr-32 items-baseline justify-between lg:whitespace-nowrap">
|
||||
<li class="flex flex-row items-center">
|
||||
<NuxtLink
|
||||
:to="`/books/${route.params.slug}/chapters/${route.params.slug}/`"
|
||||
class="flex flex-col gap-8 items-center cursor-pointer"
|
||||
>
|
||||
<img
|
||||
src="/img/svg/books/bi_book.svg"
|
||||
alt="Читай отрывок"
|
||||
width="62"
|
||||
height="53"
|
||||
/>
|
||||
|
||||
<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="50" height="50" />
|
||||
<UiParagraph size="250" as="span"> Читай отрывок </UiParagraph>
|
||||
</NuxtLink>
|
||||
</RouterLink>
|
||||
</li>
|
||||
<li class="flex flex-row items-center">
|
||||
<a
|
||||
download
|
||||
:href="book.download"
|
||||
class="flex flex-col items-center gap-8 cursor-pointer"
|
||||
>
|
||||
<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="62"
|
||||
height="53"
|
||||
width="50"
|
||||
height="50"
|
||||
/>
|
||||
|
||||
<UiParagraph size="250" as="span"> Скачай отрывок </UiParagraph>
|
||||
</a>
|
||||
</RouterLink>
|
||||
</li>
|
||||
<li class="flex flex-row items-center">
|
||||
<NuxtLink
|
||||
:to="`/books/${route.params.slug}/${book.hrefTitles}`"
|
||||
class="flex flex-col items-center gap-8 cursor-pointer"
|
||||
<li class="flex flex-row gap-3 items-center">
|
||||
<RouterLink
|
||||
:to="{
|
||||
name: 'book-titles',
|
||||
params: {
|
||||
slug: route.params.slug,
|
||||
titlesSlug: book.hrefTitles,
|
||||
},
|
||||
}"
|
||||
class="flex flex-col items-center gap-3 cursor-pointer"
|
||||
>
|
||||
<img src="/img/svg/books/down2.svg" alt="Содержание" width="62" height="53" />
|
||||
|
||||
<img src="/img/svg/books/titles.svg" alt="Содержание" width="50" height="50" />
|
||||
<UiParagraph size="250" as="span"> Содержание </UiParagraph>
|
||||
</NuxtLink>
|
||||
</RouterLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!--нижний блок-->
|
||||
<section class="ml-20 mt-32">
|
||||
<section class="ml-18 mt-32">
|
||||
<div>
|
||||
<UiHeading tag="h2" size="300" class="text-three"> Что ты узнаешь </UiHeading>
|
||||
<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-32 gap-4 h-64 items-center transition-transform transform hover:scale-110"
|
||||
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"
|
||||
>
|
||||
@ -159,7 +155,7 @@
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
<NuxtPage />
|
||||
<RouterView />
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="text-white text-center py-20">Книга не найдена.</div>
|
||||
@ -167,10 +163,11 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useRoute, useRouter } from '#app'
|
||||
import { useRoute, RouterView } 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
|
||||
@ -192,13 +189,10 @@ interface BookDetail {
|
||||
}>
|
||||
href: string
|
||||
hrefTitles: string
|
||||
download: string
|
||||
}
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const currentBookData = ref<BookDetail | null>(null)
|
||||
|
||||
const book = computed(() => currentBookData.value)
|
||||
@ -213,10 +207,6 @@ const loadBookData = async (slug: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleSelect = () => {
|
||||
router.push('/cart/')
|
||||
}
|
||||
|
||||
watch(
|
||||
() => route.params.slug,
|
||||
async (newSlug) => {
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<section class="feedback-section">
|
||||
<UiHeading tag="h2" size="300" class="text-three mb-4 pl-16 pr-24">
|
||||
<UiHeading tag="H2" size="300" class="text-three mb-4 pl-16 pr-24">
|
||||
Что говорят читатели
|
||||
</UiHeading>
|
||||
|
||||
@ -30,13 +30,13 @@
|
||||
Это поможет другим и вдохновит на новые главы. <br />
|
||||
Спасибо!
|
||||
</UiParagraph>
|
||||
<UiButton class="mt-10" variants="secondary">Написать отзыв</UiButton>
|
||||
<UiButton @click="console.log(1)" class="mt-10" variants="secondary">Написать отзыв</UiButton>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { onMounted } from 'vue' // Добавляем onMounted
|
||||
import Swiper from 'swiper'
|
||||
import { Pagination, Autoplay } from 'swiper/modules'
|
||||
import UiHeading from '@/components/Typography/UiHeading.vue'
|
||||
@ -86,7 +86,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.feedback-card {
|
||||
background-color: #171b27;
|
||||
background-color: #1a1a1a;
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
color: #fff;
|
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<section>
|
||||
<UiHeading tag="h1" size="300" class="text-three">
|
||||
<UiHeading tag="H2" size="300" class="text-three">
|
||||
Книги для тебя, если ты не знаешь...
|
||||
</UiHeading>
|
||||
<ul class="flex mt-20 flex-row items-center justify-between gap-10">
|
||||
<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="({ img, text }, index) in questions.data"
|
@ -1,14 +1,12 @@
|
||||
import UiParagraph from '@/components/Typography/UiParagraph.vue';
|
||||
<template>
|
||||
<div
|
||||
v-for="({ topContent, button, botContent, path }, index) in content.data"
|
||||
v-for="({ topContent, button, botContent }, index) in content.data"
|
||||
:key="index"
|
||||
class="flex flex-col items-center max-w-96"
|
||||
>
|
||||
<UiParagraph size="300" class="mb-12 h-32">{{ topContent }} </UiParagraph>
|
||||
<UiButton tag="RouterLink" :to="path" variants="primary" class="mb-3 w-full"
|
||||
>{{ button }}
|
||||
</UiButton>
|
||||
<UiButton variants="primary" class="mb-3 w-full">{{ button }} </UiButton>
|
||||
<UiParagraph as="span" size="200"> {{ botContent }}</UiParagraph>
|
||||
</div>
|
||||
</template>
|
||||
@ -25,14 +23,12 @@ const content = reactive({
|
||||
'💡 Узнай, как думает мужчина, что его действительно цепляет, и что делает женщину незабываемой.',
|
||||
button: 'КУПИТЬ КНИГУ I',
|
||||
botContent: 'PDF + EPUB сразу после оплаты',
|
||||
path: '/books/1',
|
||||
},
|
||||
{
|
||||
topContent:
|
||||
'💡 Продолжение для тех, кто готов перейти от флирта к глубокому контакту. Как строить притяжение, не теряя себя.',
|
||||
button: 'КУПИТЬ КНИГУ II',
|
||||
botContent: 'PDF + EPUB сразу после оплаты',
|
||||
path: '/books/2',
|
||||
},
|
||||
],
|
||||
})
|
@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<section>
|
||||
<div class="relative z-50">
|
||||
<img src="/assets/img/webp/hero-banner-content.webp" alt="Книги" />
|
||||
<img
|
||||
src="/src/assets/img/webp/hero-banner-content.webp"
|
||||
alt="Книги"
|
||||
width="100%"
|
||||
height="100%"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-row justify-between pl-16 pr-24">
|
||||
<BuyContent />
|
||||
@ -9,5 +14,5 @@
|
||||
</section>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BuyContent from "./_ui/buyContent.vue";
|
||||
import BuyContent from './_ui/buyContent.vue'
|
||||
</script>
|
@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<section class="flex flex-row">
|
||||
<div class="lg:w-5/12 pl-5 pr-5 shadow-md bg-[url('/src/assets/img/png/shadow.png')]">
|
||||
<UiHeading tag="H2" size="300" class="text-three mb-4 mt-5">
|
||||
💔 Ты не одна.
|
||||
<br />Я знаю, через что ты<br />
|
||||
проходишь.
|
||||
</UiHeading>
|
||||
<UiParagraph size="250" class="xl:max-w-[392px] mb-5"
|
||||
>Когда ты снова и снова отдаёшь сердце, а в ответ — тишина или игра, это ранит. Я знаю это
|
||||
чувство. Я был по ту сторону: манипулировал, очаровывал, уходил.
|
||||
|
||||
<br /><br />Я — бывший Казанова. И однажды я понял: больше так нельзя.
|
||||
|
||||
<br /><br />Эти книги — не теория. Это ключ к пониманию, как устроена мужская психология,
|
||||
чего на самом деле хочет мужчина, и как перестать теряться в отношениях.
|
||||
|
||||
<br /><br />Я написал их для тебя — чтобы ты могла быть счастливой, не прогибаясь, не
|
||||
умоляя, не теряя себя. Если ты устала «играть», если хочешь любви по-настоящему — начни с
|
||||
первой страницы. В этих книгах нет воды. Только правда.</UiParagraph
|
||||
>
|
||||
</div>
|
||||
<div class="lg:w-7/12">
|
||||
<img alt="meeting" width="100%" height="100%" src="/img/webp/meetingAlone.webp" />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import UiHeading from '@/components/Typography/UiHeading.vue'
|
||||
import UiParagraph from '@/components/Typography/UiParagraph.vue'
|
||||
</script>
|
31
src/pages/mainPage/indexPage.vue
Normal file
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div>
|
||||
<section class="relative z-50">
|
||||
<HeroBanner
|
||||
class="pt-28 bg-[url('/src/assets/img/png/bg.png')] z-40 bg-no-repeat bg-[400px] rounded-[50px] relative after:absolute after:bg-[url('/src/assets/img/webp/header-flowers-4.webp')] after:top-0 after:w-[418px] after:right-0 after:h-[230px] after:z-20 after:content-[''] after:bg-contain after:bg-no-repeat after:bg-right"
|
||||
/>
|
||||
<ForYouSection class="mt-40 pl-16 pr-24" />
|
||||
<YouNotAloneSection class="mt-40 pl-16 pr-24 mb-40" />
|
||||
<FeedbackSection class="mt-40 mb-52" />
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import FeedbackSection from './_ui/feedbackSection/feedbackSection.vue'
|
||||
import ForYouSection from './_ui/forYouSection/forYouSection.vue'
|
||||
import HeroBanner from './_ui/heroBanner/heroBanner.vue'
|
||||
import YouNotAloneSection from './_ui/youNotAloneSection/youNotAloneSection.vue'
|
||||
|
||||
import { useHead } from '@vueuse/head'
|
||||
|
||||
useHead({
|
||||
title: 'Vino Galante',
|
||||
meta: [{ name: 'description', content: 'Онлайн магазин книг автора Vino Galante' }],
|
||||
link: [
|
||||
{
|
||||
rel: 'canonical',
|
||||
href: `https://ebook.miduway.space/`,
|
||||
},
|
||||
],
|
||||
})
|
||||
</script>
|