20 Commits

Author SHA1 Message Date
3cd6a975f9 Merge branch 'production' of https://gitea.miduway.space/levis/ebook into production
Some checks failed
Deploy Nuxt App / deploy (push) Has been cancelled
2025-06-19 21:39:01 +04:00
15a7ffe120 fix
Some checks failed
Deploy Nuxt App / deploy (push) Has been cancelled
2025-06-19 17:37:47 +00:00
b54de4ace0 update deploy.yml
All checks were successful
Deploy Nuxt App / deploy (push) Successful in 1m46s
2025-06-19 17:25:32 +00:00
7a283ababc remove .nuxt and .data
All checks were successful
Deploy Nuxt App / deploy (push) Successful in 1m44s
2025-06-19 21:17:07 +04:00
eacb8a70d0 fix
All checks were successful
Deploy Nuxt App / deploy (push) Successful in 1m41s
2025-06-19 21:14:28 +04:00
bc3d085c02 fix
All checks were successful
Deploy Nuxt App / deploy (push) Successful in 1m45s
2025-06-19 21:11:08 +04:00
4112bca029 Merge branch 'production' of https://gitea.miduway.space/levis/ebook into production
All checks were successful
Deploy Nuxt App / deploy (push) Successful in 1m53s
2025-06-19 21:07:57 +04:00
76aa42dc25 fix DockerFile
All checks were successful
Deploy Nuxt App / deploy (push) Successful in 2m39s
2025-06-19 16:59:26 +00:00
551f68a78a fix DockerFile 2025-06-19 16:08:21 +00:00
46a59c7b91 fix 2025-06-18 10:04:01 +04:00
4cdb90eaf7 fix
All checks were successful
Deploy Application / deploy (push) Successful in 8s
2025-06-18 08:41:39 +04:00
4934e8be67 fix
All checks were successful
Deploy Application / deploy (push) Successful in 7s
2025-06-18 08:40:17 +04:00
886f21e0a2 fix
All checks were successful
Deploy Application / deploy (push) Successful in 7s
2025-06-18 08:35:55 +04:00
495638c922 fix
All checks were successful
Deploy Application / deploy (push) Successful in 7s
2025-06-18 08:33:33 +04:00
453376c024 Update config
All checks were successful
Deploy Application / deploy (push) Successful in 8s
2025-06-18 07:50:52 +04:00
4e35841df3 fix deploy
All checks were successful
Deploy Application / deploy (push) Successful in 8s
2025-06-17 17:52:41 +04:00
09edacf376 Merge pull request 'migrate on nuxt3' (#7) from migration-to-nuxt into production
Reviewed-on: #7
2025-06-17 13:49:35 +00:00
727fa976bd migrate on nuxt3 2025-06-17 17:46:03 +04:00
7634a3d616 fix
All checks were successful
Deploy Application / deploy (push) Successful in 6s
2025-06-17 11:27:13 +04:00
a30c08c50c del clg
All checks were successful
Deploy Application / deploy (push) Successful in 5s
2025-06-15 19:23:58 +04:00
77 changed files with 15279 additions and 1813 deletions

View File

@ -1,4 +1,4 @@
name: Deploy Application name: Deploy Nuxt App
on: [push] on: [push]
jobs: jobs:
@ -8,27 +8,37 @@ jobs:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
token: 0406afe7de6547e850dd62c84976c6def23a5193 token: ${{ secrets.TOKEN }}
- name: Install curl - name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '22'
- name: Install dependencies and build
run: | run: |
if command -v apt-get &> /dev/null; then npm install
apt-get update && apt-get install -y curl npm run build
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: Upload config files to server - name: Prepare deployment files
run: |
tar -czf deploy.tar.gz dist Dockerfile docker-compose.yml
- name: Upload files via Gitea API
env: env:
GITEA_API: 'https://gitea.miduway.space/api/v1/repos/levis/ebook/raw/main' GITEA_API: "https://gitea.miduway.space/api/v1/repos/levis/ebook/raw/production"
GITEA_TOKEN: '0406afe7de6547e850dd62c84976c6def23a5193' GITEA_TOKEN: ${{ secrets.TOKEN }}
run: | run: |
for file in docker-compose.yml Dockerfile; do for file in Dockerfile docker-compose.yml; do
echo "Uploading $file"
curl -X PUT \ curl -X PUT \
-H "Authorization: token $GITEA_TOKEN" \ -H "Authorization: token $TOKEN" \
-H "Content-Type: text/plain" \
-T "$file" \ -T "$file" \
"$GITEA_API/$file" "$GITEA_API/$file?branch=production"
done done
curl -X PUT \
-H "Authorization: token $TOKEN" \
-H "Content-Type: application/gzip" \
-T "deploy.tar.gz" \
"$GITEA_API/deploy.tar.gz?branch=production"

9
.gitignore vendored
View File

@ -11,6 +11,14 @@ node_modules
dist dist
dist-ssr dist-ssr
*.local *.local
.nuxt
.output
.data
.nuxt
.nitro
.cache
dist
# Editor directories and files # Editor directories and files
.vscode/* .vscode/*
@ -23,5 +31,4 @@ dist-ssr
*.sln *.sln
*.sw? *.sw?
frontend.env frontend.env

View File

@ -1,2 +0,0 @@
npm run lint
npm run format

View File

@ -1,7 +0,0 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"singleQuote": true,
"printWidth": 100
}

View File

@ -1,3 +0,0 @@
{
"recommendations": ["Vue.volar"]
}

View File

@ -1,13 +1,7 @@
FROM node:20 as builder FROM node:22-alpine
WORKDIR /usr/src/app
WORKDIR /app
COPY package*.json ./ COPY package*.json ./
RUN npm install RUN npm install
COPY . . COPY . .
RUN npm run build 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;"]

View File

@ -1,27 +1,76 @@
# Проект сайт vino Galante # Nuxt Minimal Starter
## Описание проекта Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
Интернет сайт Vino Galente создан для продажи книг за авторством... ## Setup
### Установка, для разработки
Копируем env Make sure to install dependencies:
``` ```bash
cp frontend.env frontend.env.example # npm
npm install
# pnpm
pnpm install
# yarn
yarn install
# bun
bun install
``` ```
Устанавливаем зависимости ## Development Server
``` Start the development server on `http://localhost:3000`:
yarn
```bash
# npm
npm run dev
# pnpm
pnpm dev
# yarn
yarn dev
# bun
bun run dev
``` ```
Запуск dev ## Production
``` Build the application for production:
vite
```bash
# npm
npm run build
# pnpm
pnpm build
# yarn
yarn build
# bun
bun run build
``` ```
Разворачивание, docker 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.

15
app.vue Normal file
View File

@ -0,0 +1,15 @@
<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>

42
assets/css/tailwind.css Normal file
View File

@ -0,0 +1,42 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--color-primary: rgba(255, 255, 255, 1);
--color-secondary: rgba(229, 30, 125, 1);
--color-three: rgba(245, 75, 126, 1);
--color-accent-50: #f54378;
--color-accent-100: #e51e7d;
--color-accent-150: #c4035f;
--color-black-50: #0c1018;
/* system colors */
--color-error: oklch(57.7% 0.245 27.325);
--color-warning: oklch(76.9% 0.188 70.08);
/* disabled */
--color-text-disabled: oklch(55.1% 0.027 264.364);
--color-bg-disabled: oklch(92.8% 0.006 264.531);
}
/* Кастомные классы шрифтов */
.lato-thin { font-family: 'Lato', sans-serif; font-weight: 100; font-style: normal; }
.lato-light { font-family: 'Lato', sans-serif; font-weight: 300; font-style: normal; }
.lato-regular { font-family: 'Lato', sans-serif; font-weight: 400; font-style: normal; }
.lato-bold { font-family: 'Lato', sans-serif; font-weight: 700; font-style: normal; }
.lato-black { font-family: 'Lato', sans-serif; font-weight: 900; font-style: normal; }
.lato-thin-italic { font-family: 'Lato', sans-serif; font-weight: 100; font-style: italic; }
.lato-light-italic { font-family: 'Lato', sans-serif; font-weight: 300; font-style: italic; }
.lato-regular-italic { font-family: 'Lato', sans-serif; font-weight: 400; font-style: italic; }
.lato-bold-italic { font-family: 'Lato', sans-serif; font-weight: 700; font-style: italic; }
.lato-black-italic { font-family: 'Lato', sans-serif; font-weight: 900; font-style: italic; }
.russo-one-regular {
font-family: 'Russo One', sans-serif;
font-weight: 700;
font-style: normal;
}

View File

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 206 KiB

After

Width:  |  Height:  |  Size: 206 KiB

View File

Before

Width:  |  Height:  |  Size: 251 KiB

After

Width:  |  Height:  |  Size: 251 KiB

View File

Before

Width:  |  Height:  |  Size: 409 KiB

After

Width:  |  Height:  |  Size: 409 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

Before

Width:  |  Height:  |  Size: 613 KiB

After

Width:  |  Height:  |  Size: 613 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 496 B

After

Width:  |  Height:  |  Size: 496 B

View File

@ -11,7 +11,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { toRefs, computed } from 'vue' import { toRefs, computed } from 'vue'
import { colorVariants } from './UiButton.params.ts' import { colorVariants } from './UiButton.params.js'
const props = defineProps({ const props = defineProps({
tag: { tag: {

11
config/index.ts Normal file
View File

@ -0,0 +1,11 @@
import modules from './modules'
import sitemap from './sitemap'
export default {
modules,
sitemap,
typescript: {
strict: true,
typeCheck: true,
},
}

12
config/modules.ts Normal file
View File

@ -0,0 +1,12 @@
export default [
"@nuxt/eslint",
"@nuxt/icon",
"@nuxt/image",
// '@nuxt/content',
// '@nuxt/fonts',
"@pinia/nuxt",
"@nuxtjs/tailwindcss",
"@pinia/nuxt",
// '@nuxtjs/robots',
// '@nuxtjs/sitemap',
];

12
config/sitemap.ts Normal file
View File

@ -0,0 +1,12 @@
// ./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' },
],
}

View File

@ -1,21 +0,0 @@
<!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>

View File

@ -25,7 +25,7 @@
<script setup lang="ts"> <script setup lang="ts">
import UiParagraph from '@/components/Typography/UiParagraph.vue' import UiParagraph from '@/components/Typography/UiParagraph.vue'
import UiNav from '@/components/UiNav/UiNav.vue' import UiNav from '@/components/UiNav/UiNav.vue'
import { footerNavigation, refLitres } from '@/layout/UiFooter/_data' import { footerNavigation, refLitres } from '@/layouts/UiFooter/_data'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
const route = useRoute() const route = useRoute()

View File

@ -0,0 +1,3 @@
export { default as footerNavigation } from '@/layouts/UiFooter/_data/footer-navigation.data'
export { default as refLitres } from '@/layouts/UiFooter/_data/ref-litres.data'

View File

@ -0,0 +1 @@
export { default as headerNavigation } from '@/layouts/UiHeader/_data/header-navigation.data'

View File

@ -1,6 +1,6 @@
<template> <template>
<div <div
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="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/webp/footer-flowers.webp)] before:bg-no-repeat before:bg-bottom before:bg-contain before:z-40"
:class=" :class="
route.path === '/books/1' || route.path === '/books/2' route.path === '/books/1' || route.path === '/books/2'
? 'bg-[linear-gradient(135deg,rgba(17,17,30,1)_10%,rgba(183,32,76,1)_170%)]' ? 'bg-[linear-gradient(135deg,rgba(17,17,30,1)_10%,rgba(183,32,76,1)_170%)]'
@ -9,15 +9,15 @@
> >
<div <div
v-if="route.path === '/'" v-if="route.path === '/'"
class="relative z-10 after:content-[''] after:absolute after:top-0 after:right-0 after:w-[820px] after:h-[535px] after:bg-[url(/src/assets/img/webp/gradient.webp)] after:bg-no-repeat after:bg-[right_top] after:bg-contain" 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"
/> />
<div <div
v-if="route.path === '/'" v-if="route.path === '/'"
class="relative z-20 after:content-[''] after:absolute after:top-0 after:right-0 after:w-[1120px] after:h-[1800px] after:bg-[url(/src/assets/img/webp/group-flowers.webp)] after:bg-no-repeat after:bg-[right_top] after:bg-cover" 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"
/> />
<div <div
v-if="route.path === '/'" v-if="route.path === '/'"
class="relative z-40 before:content-[''] before:absolute before:top-0 before:left-0 before:w-[1120px] before:h-[1000px] before:bg-[url(/src/assets/img/webp/hero-flowers.webp)] before:bg-no-repeat before:bg-left before:bg-contain" 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"
/> />
<UiHeader class="relative z-50" /> <UiHeader class="relative z-50" />
<UiMain class="!min-h-[1200px] text-primary relative"> <UiMain class="!min-h-[1200px] text-primary relative">

25
nuxt.config.ts Normal file
View File

@ -0,0 +1,25 @@
import config from "./config";
import { fileURLToPath, URL } from "node:url";
// 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,
});

15870
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,43 +1,47 @@
{ {
"name": "e-book", "name": "e-book",
"private": true, "private": true,
"version": "0.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "build": "nuxt build",
"build": "vue-tsc -b && vite build", "dev": "nuxt dev",
"preview": "vite preview", "generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
"prepare": "husky", "prepare": "husky",
"lint": "node_modules/.bin/eslint . --fix", "lint": "node_modules/.bin/eslint . --fix",
"format": "node_modules/.bin/prettier --write ./src/" "format": "node_modules/.bin/prettier --write ./"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/vite": "^4.1.8", "@nuxt/content": "^3.6.0",
"@vueuse/head": "^2.0.0", "@nuxt/fonts": "^0.11.4",
"pinia": "^3.0.3", "@nuxt/icon": "^1.13.0",
"@nuxt/image": "^1.10.0",
"@nuxtjs/robots": "^5.2.10",
"@nuxtjs/sitemap": "^7.4.0",
"@pinia/nuxt": "^0.5.5",
"@tailwindcss/postcss": "^4.1.10",
"better-sqlite3": "^11.10.0",
"husky": "^9.1.7",
"nuxt": "^3.17.5",
"nuxt-schema-org": "^5.0.5",
"swiper": "^11.2.8", "swiper": "^11.2.8",
"tailwindcss": "^4.1.8", "vue": "^3.5.16"
"vue": "^3.5.13",
"vue-router": "4"
}, },
"devDependencies": { "devDependencies": {
"@tsconfig/node22": "^22.0.1", "@nuxt/eslint": "^1.4.1",
"@types/node": "^22.14.0", "@nuxt/test-utils": "^3.11.3",
"@vitejs/plugin-vue": "^5.2.3", "@nuxtjs/tailwindcss": "^6.11.4",
"@types/node": "^22.0.0",
"@vue/eslint-config-prettier": "^10.2.0", "@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.5.0", "@vue/eslint-config-typescript": "^14.5.0",
"@vue/tsconfig": "^0.7.0", "autoprefixer": "^10.4.18",
"eslint": "^9.22.0", "eslint": "^9.29.0",
"eslint-plugin-vue": "~10.0.0", "eslint-plugin-vue": "^10.0.0",
"husky": "^9.1.7", "postcss": "^8.5.6",
"jiti": "^2.4.2",
"npm-run-all2": "^7.0.2",
"playwright": "^1.52.0",
"prettier": "3.5.3", "prettier": "3.5.3",
"tailwindcss": "^3.4.17",
"typescript": "~5.8.3", "typescript": "~5.8.3",
"vite": "^6.3.5",
"vite-plugin-vue-devtools": "^7.7.2",
"vue-tsc": "^2.2.8" "vue-tsc": "^2.2.8"
}, }
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
} }

View File

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

View File

@ -1,12 +1,20 @@
<template> <template>
<div v-if="titles" class="relative z-50 min-h-screen text-white mb-[208px]"> <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"> <section class="flex flex-col relative z-40 mt-40 ml-18">
<UiHeading tag="H1" class="whitespace-pre-line [&]:font-normal mb-10 -ml-5" size="500"> <UiHeading
tag="H1"
class="whitespace-pre-line [&]:font-normal mb-10 -ml-5"
size="500"
>
{{ titles.title }} {{ titles.title }}
</UiHeading> </UiHeading>
<div class="flex flex-col gap-6"> <div class="flex flex-col gap-6">
<div v-for="(section, index) in titles.sections" :key="index" class="flex flex-col gap-4"> <div
v-for="(section, index) in titles.sections"
:key="index"
class="flex flex-col gap-4"
>
<!-- Main section title --> <!-- Main section title -->
<UiHeading tag="H2" size="300" class="text-three [&]:font-normal"> <UiHeading tag="H2" size="300" class="text-three [&]:font-normal">
{{ section.title }} {{ section.title }}
@ -35,14 +43,27 @@
</UiHeading> </UiHeading>
</div> </div>
<!-- Regular subsection --> <!-- Regular subsection -->
<UiHeading v-else tag="H3" size="300" class="[&]:text-gray-200 [&]:font-normal"> <UiHeading
v-else
tag="H3"
size="300"
class="[&]:text-gray-200 [&]:font-normal"
>
{{ subsection.title }} {{ subsection.title }}
</UiHeading> </UiHeading>
<!-- Items list --> <!-- Items list -->
<ul v-if="subsection.items" class="ml-6 flex flex-col gap-2 list-decimal"> <ul
<li v-for="(item, itemIndex) in subsection.items" :key="itemIndex"> v-if="subsection.items"
<UiParagraph size="300" class="[&]:text-gray-200 [&]:font-normal" class="ml-6 flex flex-col gap-2 list-decimal"
>
<li
v-for="(item, itemIndex) in subsection.items"
:key="itemIndex"
>
<UiParagraph
size="300"
class="[&]:text-gray-200 [&]:font-normal"
>&nbsp;{{ item }}</UiParagraph >&nbsp;{{ item }}</UiParagraph
> >
</li> </li>
@ -50,8 +71,15 @@
<!-- Nested subsections --> <!-- Nested subsections -->
<div v-if="subsection.subsections" class="flex flex-col gap-2"> <div v-if="subsection.subsections" class="flex flex-col gap-2">
<div v-for="(nestedSub, nestedIndex) in subsection.subsections" :key="nestedIndex"> <div
<UiHeading tag="H4" size="300" class="[&]:text-gray-200 [&]:font-normal"> v-for="(nestedSub, nestedIndex) in subsection.subsections"
:key="nestedIndex"
>
<UiHeading
tag="H4"
size="300"
class="[&]:text-gray-200 [&]:font-normal"
>
{{ nestedSub.title }} {{ nestedSub.title }}
</UiHeading> </UiHeading>
</div> </div>
@ -66,63 +94,61 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, watch } from 'vue' import { ref, computed, watch } from "vue";
import { useRoute } from 'vue-router' import { useRoute } from "vue-router";
import UiHeading from '@/components/Typography/UiHeading.vue' import UiHeading from "@/components/Typography/UiHeading.vue";
import UiParagraph from '@/components/Typography/UiParagraph.vue' import UiParagraph from "@/components/Typography/UiParagraph.vue";
import { useHead } from '@vueuse/head' // import { useHead } from '@vueuse/head'
interface SubsectionTitle { interface SubsectionTitle {
text: string text: string;
img?: string img?: string;
} }
interface Subsection { interface Subsection {
title: string | SubsectionTitle title: string | SubsectionTitle;
items?: string[] items?: string[];
subsections?: Array<{ subsections?: Array<{
title: string title: string;
}> }>;
} }
interface Section { interface Section {
title: string title: string;
subsections?: Subsection[] subsections?: Subsection[];
} }
interface TitlesData { interface TitlesData {
title: string title: string;
titleMeta: string titleMeta: string;
sections: Section[] sections: Section[];
} }
const route = useRoute() const route = useRoute();
const currentTitlesData = ref<TitlesData | null>(null) const currentTitlesData = ref<TitlesData | null>(null);
const titles = computed(() => currentTitlesData.value) const titles = computed(() => currentTitlesData.value);
const loadTitlesData = async (slug: string) => { const loadTitlesData = async (slug: string) => {
try { try {
const module = await import(`./_data/${slug}.json`) const module = await import(`./_data/${slug}.json`);
currentTitlesData.value = module.default as TitlesData currentTitlesData.value = module.default as TitlesData;
} catch (error) { } catch (error) {
console.error(`Ошибка при загрузке содержания с slug '${slug}':`, error) console.error(`Ошибка при загрузке содержания с slug '${slug}':`, error);
currentTitlesData.value = null currentTitlesData.value = null;
} }
} };
watch( watch(
() => route.params.titlesSlug, () => route.params.titlesSlug,
async (newSlug) => { async (newSlug) => {
console.log('Route params changed:', route.params)
console.log('New titlesSlug:', newSlug)
if (newSlug) { if (newSlug) {
await loadTitlesData(newSlug as string) await loadTitlesData(newSlug as string);
} }
}, },
{ immediate: true }, { immediate: true }
) );
watch(titles, (newTitles) => { watch(titles, (newTitles) => {
if (newTitles) { if (newTitles) {
@ -130,17 +156,17 @@ watch(titles, (newTitles) => {
title: `${newTitles.titleMeta} | Vino Galante`, title: `${newTitles.titleMeta} | Vino Galante`,
meta: [ meta: [
{ {
name: 'description', name: "description",
content: 'Содержание книги Vino Galante', content: "Содержание книги Vino Galante",
}, },
], ],
link: [ link: [
{ {
rel: 'canonical', rel: "canonical",
href: `https://ebook.miduway.space/books/${route.params.slug}/${route.params.titlesSlug}`, href: `https://ebook.miduway.space/books/${route.params.slug}/${route.params.titlesSlug}`,
}, },
], ],
}) });
} }
}) });
</script> </script>

View File

@ -30,13 +30,13 @@
Это поможет другим и вдохновит на новые главы. <br /> Это поможет другим и вдохновит на новые главы. <br />
Спасибо! Спасибо!
</UiParagraph> </UiParagraph>
<UiButton @click="console.log(1)" class="mt-10" variants="secondary">Написать отзыв</UiButton> <UiButton class="mt-10" variants="secondary">Написать отзыв</UiButton>
</div> </div>
</section> </section>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from 'vue' // Добавляем onMounted import { onMounted } from 'vue'
import Swiper from 'swiper' import Swiper from 'swiper'
import { Pagination, Autoplay } from 'swiper/modules' import { Pagination, Autoplay } from 'swiper/modules'
import UiHeading from '@/components/Typography/UiHeading.vue' import UiHeading from '@/components/Typography/UiHeading.vue'

View File

@ -2,7 +2,7 @@
<section> <section>
<div class="relative z-50"> <div class="relative z-50">
<img <img
src="/src/assets/img/webp/hero-banner-content.webp" src="/assets/img/webp/hero-banner-content.webp"
alt="Книги" alt="Книги"
width="100%" width="100%"
height="100%" height="100%"

View File

@ -1,6 +1,6 @@
<template> <template>
<section class="flex flex-row"> <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')]"> <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"> <UiHeading tag="H2" size="300" class="text-three mb-4 mt-5">
💔 Ты не одна. 💔 Ты не одна.
<br />Я знаю, через что ты<br /> <br />Я знаю, через что ты<br />
@ -21,7 +21,13 @@
> >
</div> </div>
<div class="lg:w-7/12"> <div class="lg:w-7/12">
<img alt="meeting" width="100%" height="100%" src="/img/webp/meetingAlone.webp" /> <NuxtImg
src="/img/webp/meetingAlone.webp"
alt="meeting"
width="100%"
height="100%"
loading="lazy"
/>
</div> </div>
</section> </section>
</template> </template>

31
pages/index/index.vue Normal file
View File

@ -0,0 +1,31 @@
<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>

104
pages/privacy/index.vue Normal file
View File

@ -0,0 +1,104 @@
<template>
<section>
<UiHeading size="300" tag="H1" class="mb-5">
Политика конфиденциальности
</UiHeading>
<UiParagraph size="300" class="mb-3"
>Настоящая политика конфиденциальности описывает, как мы собираем,
используем и защищаем личную информацию, которую пользователи
предоставляют при использовании нашего сайта.</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>

5
postcss.config.mjs Normal file
View File

@ -0,0 +1,5 @@
export default {
plugins: {
"@tailwindcss/postcss": {},
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 1.5 KiB

3
server/tsconfig.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": "../.nuxt/tsconfig.server.json"
}

View File

@ -1,10 +0,0 @@
<template>
<UiLayout>
<RouterView />
</UiLayout>
</template>
<script setup lang="ts">
import UiLayout from './layout/UiLayout.vue'
import { RouterView } from 'vue-router'
</script>

View File

@ -1,9 +0,0 @@
import { createRouter, createWebHistory } from 'vue-router'
import routes from './routes'
const router = createRouter({
history: createWebHistory(import.meta.env.VITE_URL),
routes,
})
export default router

View File

@ -1,43 +0,0 @@
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

View File

@ -1,3 +0,0 @@
export { default as footerNavigation } from '@/layout/UiFooter/_data/footer-navigation.data'
export { default as refLitres } from '@/layout/UiFooter/_data/ref-litres.data'

View File

@ -1 +0,0 @@
export { default as headerNavigation } from '@/layout/UiHeader/_data/header-navigation.data'

View File

@ -1,16 +0,0 @@
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')

View File

@ -1,31 +0,0 @@
<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>

View File

@ -1,87 +0,0 @@
<template>
<section>
<UiHeading size="300" tag="H1" class="mb-5"> Политика конфиденциальности </UiHeading>
<UiParagraph size="300"
>Настоящая политика конфиденциальности описывает, как мы собираем, используем и защищаем
личную информацию, которую пользователи предоставляют при использовании нашего
сайта.</UiParagraph
>
<UiHeading size="300" tag="H2">1. Сбор информации</UiHeading>
<UiParagraph size="300"
>При оформлении заказа на сайте вы предоставляете персональные данные, которые
включают:</UiParagraph
>
<ul class="list-disc pl-5">
<li><UiParagraph size="300">Адрес электронной почты</UiParagraph></li>
<li><UiParagraph size="300">Имя (по желанию)</UiParagraph></li>
</ul>
<UiHeading size="300" tag="H2">2. Использование информации</UiHeading>
<UiParagraph size="300">Ваши личные данные используются исключительно для:</UiParagraph>
<ul class="list-disc pl-5">
<li><UiParagraph size="300">Обработки и выполнения вашего заказа.</UiParagraph></li>
<li><UiParagraph> Связи с вами по вопросам вашего заказа. </UiParagraph></li>
<li>
<UiParagraph size="300">
Уведомления о важных обновлениях и новостях сайта (только если вы явно согласились на
рассылку).</UiParagraph
>
</li>
</ul>
<UiHeading size="300" tag="H2">3. Защита личных данных</UiHeading>
<UiParagraph size="300">
Мы предпринимаем необходимые меры для защиты ваших личных данных от несанкционированного
доступа, изменения, разглашения или уничтожения. Доступ к личным данным имеют только
сотрудники, непосредственно участвующие в обработке заказов.
</UiParagraph>
<UiHeading size="300" tag="H2">4. Передача информации третьим лицам</UiHeading>
<UiParagraph size="300">
Мы не передаём ваши личные данные третьим лицам, за исключением случаев, предусмотренных
законодательством Российской Федерации.
</UiParagraph>
<UiHeading size="300" tag="H2">5. Cookies (Куки-файлы)</UiHeading>
<UiParagraph size="300">
Мы используем файлы cookie, чтобы улучшить ваш пользовательский опыт. Вы можете отключить
файлы cookie в настройках вашего браузера, однако это может ограничить доступ к некоторым
функциям сайта.
</UiParagraph>
<UiHeading size="300" tag="H2">6. Изменения в политике конфиденциальности</UiHeading>
<UiParagraph size="300">
Мы можем периодически обновлять настоящую политику конфиденциальности. Об изменениях мы
уведомим вас, разместив новую версию политики на данной странице.
</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'
import { useHead } from '@vueuse/head'
useHead({
title: 'Поликита конфиденциальности | Vino Galante',
meta: [{ name: 'description', content: 'Онлайн магазин книг автора Vino Galante' }],
link: [
{
rel: 'canonical',
href: `https://ebook.miduway.space/privacy`,
},
],
})
</script>

View File

@ -1,87 +0,0 @@
@import 'tailwindcss';
@theme {
--color-primary: rgba(255, 255, 255, 1);
--color-secondary: rgba(229, 30, 125, 1);
--color-three: rgba(245, 75, 126, 1);
--color-accent-50: #f54378;
--color-accent-100: #e51e7d;
--color-accent-150: #c4035f;
--color-black-50: #0c1018;
/*system colors*/
--color-error: oklch(57.7% 0.245 27.325);
--color-warning: oklch(76.9% 0.188 70.08);
/*disabled*/
--color-text-disabled: oklch(55.1% 0.027 264.364);
--color-bg-disabled: oklch(92.8% 0.006 264.531);
}
.lato-thin {
font-family: 'Lato', sans-serif;
font-weight: 100;
font-style: normal;
}
.lato-light {
font-family: 'Lato', sans-serif;
font-weight: 300;
font-style: normal;
}
.lato-regular {
font-family: 'Lato', sans-serif;
font-weight: 400;
font-style: normal;
}
.lato-bold {
font-family: 'Lato', sans-serif;
font-weight: 700;
font-style: normal;
}
.lato-black {
font-family: 'Lato', sans-serif;
font-weight: 900;
font-style: normal;
}
.lato-thin-italic {
font-family: 'Lato', sans-serif;
font-weight: 100;
font-style: italic;
}
.lato-light-italic {
font-family: 'Lato', sans-serif;
font-weight: 300;
font-style: italic;
}
.lato-regular-italic {
font-family: 'Lato', sans-serif;
font-weight: 400;
font-style: italic;
}
.lato-bold-italic {
font-family: 'Lato', sans-serif;
font-weight: 700;
font-style: italic;
}
.lato-black-italic {
font-family: 'Lato', sans-serif;
font-weight: 900;
font-style: italic;
}
.russo-one-regular {
font-family: 'Russo One', sans-serif;
font-weight: 700;
font-style: normal;
}

1
src/vite-env.d.ts vendored
View File

@ -1 +0,0 @@
/// <reference types="vite/client" />

38
tailwind.config.ts Normal file
View File

@ -0,0 +1,38 @@
// tailwind.config.js
const { fontFamily } = require('tailwindcss/defaultTheme')
module.exports = {
content: [
'./components/**/*.{vue,js}',
'./layouts/**/*.vue',
'./pages/**/*.vue',
'./app.vue',
'./nuxt.config.{js,ts}',
],
theme: {
extend: {
colors: {
primary: 'var(--color-primary)',
secondary: 'var(--color-secondary)',
three: 'var(--color-three)',
accent: {
50: 'var(--color-accent-50)',
100: 'var(--color-accent-100)',
150: 'var(--color-accent-150)',
},
black: {
50: 'var(--color-black-50)',
},
error: 'var(--color-error)',
warning: 'var(--color-warning)',
'text-disabled': 'var(--color-text-disabled)',
'bg-disabled': 'var(--color-bg-disabled)',
},
fontFamily: {
lato: ['Lato', ...fontFamily.sans],
russo: ['"Russo One"', ...fontFamily.sans],
},
},
},
plugins: [],
}

View File

@ -1,12 +0,0 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["./src/**/*", "./src/**/*.vue"],
"exclude": ["./src/**/__tests__/*"],
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"paths": {
"@/*": ["./src/*"]
}
}
}

View File

@ -1,11 +1,4 @@
{ {
"files": [], // https://nuxt.com/docs/guide/concepts/typescript
"references": [ "extends": "./.nuxt/tsconfig.json"
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
}
]
} }

View File

@ -1,19 +0,0 @@
{
"extends": "@tsconfig/node22/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*",
"eslint.config.*"
],
"compilerOptions": {
"noEmit": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}

View File

@ -1,24 +0,0 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import tailwindcss from '@tailwindcss/vite'
import vueDevTools from 'vite-plugin-vue-devtools'
import path from 'path'
export default defineConfig({
root: path.resolve(__dirname, '.'),
plugins: [vue(), vueDevTools(), tailwindcss()],
build: {
outDir: './dist', // Output to Nginx served directory
emptyOutDir: true,
},
server: {
host: '0.0.0.0', // Allow Docker container access
port: 4002,
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
})