Compare commits
20 Commits
develop
...
3cd6a975f9
Author | SHA1 | Date | |
---|---|---|---|
3cd6a975f9 | |||
15a7ffe120 | |||
b54de4ace0 | |||
7a283ababc | |||
eacb8a70d0 | |||
bc3d085c02 | |||
4112bca029 | |||
76aa42dc25 | |||
551f68a78a | |||
46a59c7b91 | |||
4cdb90eaf7 | |||
4934e8be67 | |||
886f21e0a2 | |||
495638c922 | |||
453376c024 | |||
4e35841df3 | |||
09edacf376 | |||
727fa976bd | |||
7634a3d616 | |||
a30c08c50c |
@ -1,4 +1,4 @@
|
||||
name: Deploy Application
|
||||
name: Deploy Nuxt App
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
@ -8,27 +8,37 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
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: |
|
||||
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
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
- 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:
|
||||
GITEA_API: 'https://gitea.miduway.space/api/v1/repos/levis/ebook/raw/main'
|
||||
GITEA_TOKEN: '0406afe7de6547e850dd62c84976c6def23a5193'
|
||||
GITEA_API: "https://gitea.miduway.space/api/v1/repos/levis/ebook/raw/production"
|
||||
GITEA_TOKEN: ${{ secrets.TOKEN }}
|
||||
run: |
|
||||
for file in docker-compose.yml Dockerfile; do
|
||||
echo "Uploading $file"
|
||||
for file in Dockerfile docker-compose.yml; do
|
||||
curl -X PUT \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: text/plain" \
|
||||
-T "$file" \
|
||||
"$GITEA_API/$file"
|
||||
"$GITEA_API/$file?branch=production"
|
||||
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
@ -11,6 +11,14 @@ node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
.nuxt
|
||||
|
||||
.output
|
||||
.data
|
||||
.nuxt
|
||||
.nitro
|
||||
.cache
|
||||
dist
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
@ -23,5 +31,4 @@ dist-ssr
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
|
||||
frontend.env
|
@ -1,2 +0,0 @@
|
||||
npm run lint
|
||||
npm run format
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100
|
||||
}
|
||||
|
3
.vscode/extensions.json
vendored
@ -1,3 +0,0 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar"]
|
||||
}
|
12
Dockerfile
@ -1,13 +1,7 @@
|
||||
FROM node:20 as builder
|
||||
|
||||
WORKDIR /app
|
||||
FROM node:22-alpine
|
||||
WORKDIR /usr/src/app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
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;"]
|
||||
CMD ["node", "dist/server/index.mjs"]
|
||||
|
77
README.md
@ -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:
|
||||
|
||||
```
|
||||
cp frontend.env frontend.env.example
|
||||
```bash
|
||||
# npm
|
||||
npm install
|
||||
|
||||
# pnpm
|
||||
pnpm install
|
||||
|
||||
# yarn
|
||||
yarn install
|
||||
|
||||
# bun
|
||||
bun install
|
||||
```
|
||||
|
||||
Устанавливаем зависимости
|
||||
## Development Server
|
||||
|
||||
```
|
||||
yarn
|
||||
Start the development server on `http://localhost:3000`:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
# pnpm
|
||||
pnpm dev
|
||||
|
||||
# yarn
|
||||
yarn dev
|
||||
|
||||
# bun
|
||||
bun run dev
|
||||
```
|
||||
|
||||
Запуск dev
|
||||
## Production
|
||||
|
||||
```
|
||||
vite
|
||||
Build the application for production:
|
||||
|
||||
```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
@ -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
@ -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;
|
||||
}
|
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 |
@ -11,7 +11,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRefs, computed } from 'vue'
|
||||
import { colorVariants } from './UiButton.params.ts'
|
||||
import { colorVariants } from './UiButton.params.js'
|
||||
|
||||
const props = defineProps({
|
||||
tag: {
|
11
config/index.ts
Normal 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
@ -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
@ -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' },
|
||||
],
|
||||
}
|
21
index.html
@ -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>
|
@ -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 '@/layout/UiFooter/_data'
|
||||
import { footerNavigation, refLitres } from '@/layouts/UiFooter/_data'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
3
layouts/UiFooter/_data/index.ts
Normal 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'
|
1
layouts/UiHeader/_data/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default as headerNavigation } from '@/layouts/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-[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="
|
||||
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(/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
|
||||
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
|
||||
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" />
|
||||
<UiMain class="!min-h-[1200px] text-primary relative">
|
25
nuxt.config.ts
Normal 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,
|
||||
});
|
15864
package-lock.json
generated
54
package.json
@ -1,43 +1,47 @@
|
||||
{
|
||||
"name": "e-book",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc -b && vite build",
|
||||
"preview": "vite preview",
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare",
|
||||
"prepare": "husky",
|
||||
"lint": "node_modules/.bin/eslint . --fix",
|
||||
"format": "node_modules/.bin/prettier --write ./src/"
|
||||
"format": "node_modules/.bin/prettier --write ./"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.1.8",
|
||||
"@vueuse/head": "^2.0.0",
|
||||
"pinia": "^3.0.3",
|
||||
"@nuxt/content": "^3.6.0",
|
||||
"@nuxt/fonts": "^0.11.4",
|
||||
"@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",
|
||||
"tailwindcss": "^4.1.8",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "4"
|
||||
"vue": "^3.5.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node22": "^22.0.1",
|
||||
"@types/node": "^22.14.0",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"@nuxt/eslint": "^1.4.1",
|
||||
"@nuxt/test-utils": "^3.11.3",
|
||||
"@nuxtjs/tailwindcss": "^6.11.4",
|
||||
"@types/node": "^22.0.0",
|
||||
"@vue/eslint-config-prettier": "^10.2.0",
|
||||
"@vue/eslint-config-typescript": "^14.5.0",
|
||||
"@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",
|
||||
"autoprefixer": "^10.4.18",
|
||||
"eslint": "^9.29.0",
|
||||
"eslint-plugin-vue": "^10.0.0",
|
||||
"postcss": "^8.5.6",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
@ -4,19 +4,28 @@
|
||||
<template v-if="!route.params.titlesSlug">
|
||||
<!--верхний блок-->
|
||||
<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]">
|
||||
<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>
|
||||
</section>
|
||||
<!--правый блок контента-->
|
||||
<section>
|
||||
<div class="w-11/12 h-full flex flex-col justify-start">
|
||||
<div>
|
||||
<UiHeading tag="H1" class="whitespace-pre-line [&]:font-bold" size="300">
|
||||
<UiHeading
|
||||
tag="H1"
|
||||
class="whitespace-pre-line [&]:font-bold"
|
||||
size="300"
|
||||
>
|
||||
{{ book.title }}
|
||||
</UiHeading>
|
||||
<UiParagraph class="mb-10" size="250">
|
||||
@ -33,11 +42,13 @@
|
||||
</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-row">
|
||||
<UiParagraph class="[&]:text-6xl">{{ book.price }} </UiParagraph>
|
||||
<UiParagraph class="[&]:text-6xl"
|
||||
>{{ book.price }} </UiParagraph
|
||||
>
|
||||
<img src="/img/svg/books/ruble.svg" alt="ruble" />
|
||||
</div>
|
||||
<div class="mr-10 flex items-center flex-col gap-3">
|
||||
@ -53,7 +64,9 @@
|
||||
<div class="min-h-[310px]">
|
||||
<!--о книге-->
|
||||
<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">
|
||||
<img
|
||||
src="/img/svg/books/book-pages.svg"
|
||||
@ -92,50 +105,77 @@
|
||||
|
||||
<!--навигация по книге-->
|
||||
<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>
|
||||
</RouterLink>
|
||||
<ul
|
||||
class="flex flex-row mr-32 items-end justify-between lg:whitespace-nowrap"
|
||||
>
|
||||
<li class="flex flex-row items-center">
|
||||
<NuxtLink
|
||||
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 class="flex flex-row gap-3 items-center">
|
||||
<RouterLink to="#" class="flex flex-col items-center gap-3 cursor-pointer">
|
||||
<NuxtLink
|
||||
to="#"
|
||||
class="flex flex-col items-center gap-4 cursor-pointer"
|
||||
>
|
||||
<div class="w-[62px] h-[53px]">
|
||||
<img
|
||||
src="/img/svg/books/download.svg"
|
||||
alt="Скачай отрывок"
|
||||
width="50"
|
||||
height="50"
|
||||
width="62"
|
||||
height="53"
|
||||
/>
|
||||
<UiParagraph size="250" as="span"> Скачай отрывок </UiParagraph>
|
||||
</RouterLink>
|
||||
</div>
|
||||
|
||||
<UiParagraph size="250" as="span">
|
||||
Скачай отрывок
|
||||
</UiParagraph>
|
||||
</NuxtLink>
|
||||
</li>
|
||||
<li class="flex flex-row gap-3 items-center">
|
||||
<RouterLink
|
||||
:to="{
|
||||
name: 'book-titles',
|
||||
params: {
|
||||
slug: route.params.slug,
|
||||
titlesSlug: book.hrefTitles,
|
||||
},
|
||||
}"
|
||||
<NuxtLink
|
||||
:to="`/books/${route.params.slug}/${book.hrefTitles}`"
|
||||
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>
|
||||
</RouterLink>
|
||||
</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!--нижний блок-->
|
||||
<section class="ml-18 mt-32">
|
||||
<section class="ml-20 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-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"
|
||||
:key="index"
|
||||
>
|
||||
@ -148,74 +188,76 @@
|
||||
</div>
|
||||
<div class="flex justify-center text-center mt-36">
|
||||
<UiParagraph>
|
||||
Или купи на ЛитРес - <br /><a class="text-three" :href="book.href" target="_blank"
|
||||
Или купи на ЛитРес - <br /><a
|
||||
class="text-three"
|
||||
:href="book.href"
|
||||
target="_blank"
|
||||
>Реферальная ссылка для поддержки автора</a
|
||||
>
|
||||
</UiParagraph>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
<RouterView />
|
||||
<NuxtPage />
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="text-white text-center py-20">Книга не найдена.</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
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'
|
||||
import { ref, computed, watch } from "vue";
|
||||
import { useRoute } from "#app";
|
||||
import UiHeading from "@/components/Typography/UiHeading.vue";
|
||||
import UiParagraph from "@/components/Typography/UiParagraph.vue";
|
||||
import UiButton from "@/components/UiButton/UiButton.vue";
|
||||
|
||||
interface BookDetail {
|
||||
id: number
|
||||
title: string
|
||||
metaTitle: string
|
||||
subtitle: string
|
||||
subdesc: string
|
||||
description: string
|
||||
img: string
|
||||
price: string
|
||||
buttonText: string
|
||||
buttonFormat: string
|
||||
pages: string
|
||||
illust: string
|
||||
format: string
|
||||
id: number;
|
||||
title: string;
|
||||
metaTitle: string;
|
||||
subtitle: string;
|
||||
subdesc: string;
|
||||
description: string;
|
||||
img: string;
|
||||
price: string;
|
||||
buttonText: string;
|
||||
buttonFormat: string;
|
||||
pages: string;
|
||||
illust: string;
|
||||
format: string;
|
||||
whoUKnows: Array<{
|
||||
text: string
|
||||
svg: string
|
||||
}>
|
||||
href: string
|
||||
hrefTitles: string
|
||||
text: string;
|
||||
svg: string;
|
||||
}>;
|
||||
href: 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) => {
|
||||
try {
|
||||
const module = await import(`./_data/${slug}.json`)
|
||||
currentBookData.value = module.default as BookDetail
|
||||
const module = await import(`./_data/${slug}.json`);
|
||||
currentBookData.value = module.default as BookDetail;
|
||||
} catch (error) {
|
||||
console.error(`Ошибка при загрузке книги с slug '${slug}':`, error)
|
||||
currentBookData.value = null
|
||||
console.error(`Ошибка при загрузке книги с slug '${slug}':`, error);
|
||||
currentBookData.value = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => route.params.slug,
|
||||
async (newSlug) => {
|
||||
if (newSlug) {
|
||||
await loadBookData(newSlug as string)
|
||||
await loadBookData(newSlug as string);
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(book, (newBook) => {
|
||||
if (newBook) {
|
||||
@ -223,17 +265,17 @@ watch(book, (newBook) => {
|
||||
title: `${newBook.metaTitle} | Vino Galante`,
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content: 'Онлайн магазин книг автора Vino Galante',
|
||||
name: "description",
|
||||
content: "Онлайн магазин книг автора Vino Galante",
|
||||
},
|
||||
],
|
||||
link: [
|
||||
{
|
||||
rel: 'canonical',
|
||||
rel: "canonical",
|
||||
href: `https://ebook.miduway.space/books/${route.params.slug}`,
|
||||
},
|
||||
],
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
@ -1,12 +1,20 @@
|
||||
<template>
|
||||
<div v-if="titles" class="relative z-50 min-h-screen text-white mb-[208px]">
|
||||
<section class="flex flex-col relative z-40 mt-40 ml-18">
|
||||
<UiHeading tag="H1" class="whitespace-pre-line [&]:font-normal mb-10 -ml-5" size="500">
|
||||
<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">
|
||||
<div
|
||||
v-for="(section, index) in titles.sections"
|
||||
:key="index"
|
||||
class="flex flex-col gap-4"
|
||||
>
|
||||
<!-- Main section title -->
|
||||
<UiHeading tag="H2" size="300" class="text-three [&]:font-normal">
|
||||
{{ section.title }}
|
||||
@ -35,14 +43,27 @@
|
||||
</UiHeading>
|
||||
</div>
|
||||
<!-- 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 }}
|
||||
</UiHeading>
|
||||
|
||||
<!-- Items list -->
|
||||
<ul v-if="subsection.items" class="ml-6 flex flex-col gap-2 list-decimal">
|
||||
<li v-for="(item, itemIndex) in subsection.items" :key="itemIndex">
|
||||
<UiParagraph size="300" class="[&]:text-gray-200 [&]:font-normal"
|
||||
<ul
|
||||
v-if="subsection.items"
|
||||
class="ml-6 flex flex-col gap-2 list-decimal"
|
||||
>
|
||||
<li
|
||||
v-for="(item, itemIndex) in subsection.items"
|
||||
:key="itemIndex"
|
||||
>
|
||||
<UiParagraph
|
||||
size="300"
|
||||
class="[&]:text-gray-200 [&]:font-normal"
|
||||
> {{ item }}</UiParagraph
|
||||
>
|
||||
</li>
|
||||
@ -50,8 +71,15 @@
|
||||
|
||||
<!-- Nested subsections -->
|
||||
<div v-if="subsection.subsections" class="flex flex-col gap-2">
|
||||
<div v-for="(nestedSub, nestedIndex) in subsection.subsections" :key="nestedIndex">
|
||||
<UiHeading tag="H4" size="300" class="[&]:text-gray-200 [&]:font-normal">
|
||||
<div
|
||||
v-for="(nestedSub, nestedIndex) in subsection.subsections"
|
||||
:key="nestedIndex"
|
||||
>
|
||||
<UiHeading
|
||||
tag="H4"
|
||||
size="300"
|
||||
class="[&]:text-gray-200 [&]:font-normal"
|
||||
>
|
||||
{{ nestedSub.title }}
|
||||
</UiHeading>
|
||||
</div>
|
||||
@ -66,63 +94,61 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import UiHeading from '@/components/Typography/UiHeading.vue'
|
||||
import UiParagraph from '@/components/Typography/UiParagraph.vue'
|
||||
import { useHead } from '@vueuse/head'
|
||||
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
|
||||
img?: string
|
||||
text: string;
|
||||
img?: string;
|
||||
}
|
||||
|
||||
interface Subsection {
|
||||
title: string | SubsectionTitle
|
||||
items?: string[]
|
||||
title: string | SubsectionTitle;
|
||||
items?: string[];
|
||||
subsections?: Array<{
|
||||
title: string
|
||||
}>
|
||||
title: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
interface Section {
|
||||
title: string
|
||||
subsections?: Subsection[]
|
||||
title: string;
|
||||
subsections?: Subsection[];
|
||||
}
|
||||
|
||||
interface TitlesData {
|
||||
title: string
|
||||
titleMeta: string
|
||||
sections: Section[]
|
||||
title: string;
|
||||
titleMeta: string;
|
||||
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) => {
|
||||
try {
|
||||
const module = await import(`./_data/${slug}.json`)
|
||||
currentTitlesData.value = module.default as TitlesData
|
||||
const module = await import(`./_data/${slug}.json`);
|
||||
currentTitlesData.value = module.default as TitlesData;
|
||||
} catch (error) {
|
||||
console.error(`Ошибка при загрузке содержания с slug '${slug}':`, error)
|
||||
currentTitlesData.value = null
|
||||
console.error(`Ошибка при загрузке содержания с slug '${slug}':`, error);
|
||||
currentTitlesData.value = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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)
|
||||
await loadTitlesData(newSlug as string);
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(titles, (newTitles) => {
|
||||
if (newTitles) {
|
||||
@ -130,17 +156,17 @@ watch(titles, (newTitles) => {
|
||||
title: `${newTitles.titleMeta} | Vino Galante`,
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content: 'Содержание книги Vino Galante',
|
||||
name: "description",
|
||||
content: "Содержание книги Vino Galante",
|
||||
},
|
||||
],
|
||||
link: [
|
||||
{
|
||||
rel: 'canonical',
|
||||
rel: "canonical",
|
||||
href: `https://ebook.miduway.space/books/${route.params.slug}/${route.params.titlesSlug}`,
|
||||
},
|
||||
],
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
@ -30,13 +30,13 @@
|
||||
Это поможет другим и вдохновит на новые главы. <br />
|
||||
Спасибо!
|
||||
</UiParagraph>
|
||||
<UiButton @click="console.log(1)" class="mt-10" variants="secondary">Написать отзыв</UiButton>
|
||||
<UiButton class="mt-10" variants="secondary">Написать отзыв</UiButton>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue' // Добавляем onMounted
|
||||
import { onMounted } from 'vue'
|
||||
import Swiper from 'swiper'
|
||||
import { Pagination, Autoplay } from 'swiper/modules'
|
||||
import UiHeading from '@/components/Typography/UiHeading.vue'
|
@ -2,7 +2,7 @@
|
||||
<section>
|
||||
<div class="relative z-50">
|
||||
<img
|
||||
src="/src/assets/img/webp/hero-banner-content.webp"
|
||||
src="/assets/img/webp/hero-banner-content.webp"
|
||||
alt="Книги"
|
||||
width="100%"
|
||||
height="100%"
|
@ -1,6 +1,6 @@
|
||||
<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')]">
|
||||
<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 />
|
||||
@ -21,7 +21,13 @@
|
||||
>
|
||||
</div>
|
||||
<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>
|
||||
</section>
|
||||
</template>
|
31
pages/index/index.vue
Normal 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
@ -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
@ -0,0 +1,5 @@
|
||||
export default {
|
||||
plugins: {
|
||||
"@tailwindcss/postcss": {},
|
||||
}
|
||||
}
|
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@ -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
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../.nuxt/tsconfig.server.json"
|
||||
}
|
10
src/App.vue
@ -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>
|
@ -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
|
@ -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
|
@ -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'
|
@ -1 +0,0 @@
|
||||
export { default as headerNavigation } from '@/layout/UiHeader/_data/header-navigation.data'
|
16
src/main.ts
@ -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')
|
@ -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>
|
@ -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>
|
@ -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
@ -1 +0,0 @@
|
||||
/// <reference types="vite/client" />
|
38
tailwind.config.ts
Normal 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: [],
|
||||
}
|
@ -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/*"]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
// https://nuxt.com/docs/guide/concepts/typescript
|
||||
"extends": "./.nuxt/tsconfig.json"
|
||||
}
|
||||
|
@ -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"]
|
||||
}
|
||||
}
|
@ -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)),
|
||||
},
|
||||
},
|
||||
})
|