start new bb run club project on vue3
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}]
|
||||||
|
charset = utf-8
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
end_of_line = lf
|
||||||
|
max_line_length = 100
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
* text=auto eol=lf
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
coverage
|
||||||
|
*.local
|
||||||
|
|
||||||
|
/cypress/videos/
|
||||||
|
/cypress/screenshots/
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
*.tsbuildinfo
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/prettierrc",
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 100
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"Vue.volar",
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"EditorConfig.EditorConfig",
|
||||||
|
"esbenp.prettier-vscode"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# bbvue
|
||||||
|
|
||||||
|
This template should help get you started developing with Vue 3 in Vite.
|
||||||
|
|
||||||
|
## Recommended IDE Setup
|
||||||
|
|
||||||
|
[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
||||||
|
|
||||||
|
## Recommended Browser Setup
|
||||||
|
|
||||||
|
- Chromium-based browsers (Chrome, Edge, Brave, etc.):
|
||||||
|
- [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
|
||||||
|
- [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters)
|
||||||
|
- Firefox:
|
||||||
|
- [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/)
|
||||||
|
- [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/)
|
||||||
|
|
||||||
|
## Customize configuration
|
||||||
|
|
||||||
|
See [Vite Configuration Reference](https://vite.dev/config/).
|
||||||
|
|
||||||
|
## Project Setup
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compile and Hot-Reload for Development
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compile and Minify for Production
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lint with [ESLint](https://eslint.org/)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||||
|
import globals from 'globals'
|
||||||
|
import js from '@eslint/js'
|
||||||
|
import pluginVue from 'eslint-plugin-vue'
|
||||||
|
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
{
|
||||||
|
name: 'app/files-to-lint',
|
||||||
|
files: ['**/*.{js,mjs,jsx,vue}'],
|
||||||
|
},
|
||||||
|
|
||||||
|
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
|
||||||
|
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
js.configs.recommended,
|
||||||
|
...pluginVue.configs['flat/essential'],
|
||||||
|
skipFormatting,
|
||||||
|
])
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<link rel="icon" href="/favicon.ico">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Vite App</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
||||||
Generated
+4212
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "bbvue",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"engines": {
|
||||||
|
"node": "^20.19.0 || >=22.12.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"lint": "eslint . --fix",
|
||||||
|
"format": "prettier --write src/"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"pinia": "^3.0.3",
|
||||||
|
"vue": "^3.5.22",
|
||||||
|
"vue-router": "^4.5.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.33.0",
|
||||||
|
"@vitejs/plugin-vue": "^6.0.1",
|
||||||
|
"@vue/eslint-config-prettier": "^10.2.0",
|
||||||
|
"eslint": "^9.33.0",
|
||||||
|
"eslint-plugin-vue": "~10.4.0",
|
||||||
|
"globals": "^16.3.0",
|
||||||
|
"prettier": "3.6.2",
|
||||||
|
"vite": "^7.1.7",
|
||||||
|
"vite-plugin-vue-devtools": "^8.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,148 @@
|
|||||||
|
<template>
|
||||||
|
<div id="app">
|
||||||
|
<header class="app-header">
|
||||||
|
<div class="container">
|
||||||
|
<div class="logo">
|
||||||
|
<h1>🏃 Бегущий Башкир</h1>
|
||||||
|
</div>
|
||||||
|
<nav class="main-nav">
|
||||||
|
<router-link to="/" class="nav-link">Главная</router-link>
|
||||||
|
<router-link to="/about" class="nav-link">О нас</router-link>
|
||||||
|
<router-link to="/achievements" class="nav-link">Достижения</router-link>
|
||||||
|
<router-link to="/gallery" class="nav-link">Галерея</router-link>
|
||||||
|
<router-link to="/training" class="nav-link">Тренировки</router-link>
|
||||||
|
<router-link to="/news" class="nav-link">Новости</router-link>
|
||||||
|
<router-link to="/members" class="nav-link">Участники</router-link>
|
||||||
|
<router-link to="/reviews" class="nav-link">Отзывы</router-link>
|
||||||
|
<router-link to="/login" class="nav-link">Войти</router-link>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="main-content">
|
||||||
|
<router-view />
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="app-footer">
|
||||||
|
<div class="container">
|
||||||
|
<p>© 2025 Беговой клуб "Бегущий Башкир". Все права защищены.</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'App'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Arial', sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header {
|
||||||
|
background-color: #2e8b57;
|
||||||
|
color: white;
|
||||||
|
padding: 1rem 0;
|
||||||
|
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo h1 {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-nav {
|
||||||
|
display: flex;
|
||||||
|
gap: 1.5rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link:hover,
|
||||||
|
.nav-link.router-link-active {
|
||||||
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
min-height: calc(100vh - 140px);
|
||||||
|
padding: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-footer {
|
||||||
|
background-color: #1a3e23;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
padding: 1rem 0;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page h1 {
|
||||||
|
color: #2e8b57;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page p {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #ffd700;
|
||||||
|
color: #333;
|
||||||
|
padding: 12px 30px;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
background-color: #e6c200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background-color: #6c757d;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background-color: #545b62;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
@import './base.css';
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import './assets/main.css'
|
||||||
|
|
||||||
|
import { createApp } from 'vue'
|
||||||
|
import { createPinia } from 'pinia'
|
||||||
|
|
||||||
|
import App from './App.vue'
|
||||||
|
import router from './router'
|
||||||
|
|
||||||
|
const app = createApp(App)
|
||||||
|
|
||||||
|
app.use(createPinia())
|
||||||
|
app.use(router)
|
||||||
|
|
||||||
|
app.mount('#app')
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
import Home from '../views/Home.vue'
|
||||||
|
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
name: 'Home',
|
||||||
|
component: Home
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/about',
|
||||||
|
name: 'About',
|
||||||
|
component: () => import('../views/About.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/achievements',
|
||||||
|
name: 'Achievements',
|
||||||
|
component: () => import('../views/Achievements.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/gallery',
|
||||||
|
name: 'Gallery',
|
||||||
|
component: () => import('../views/Gallery.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/training',
|
||||||
|
name: 'Training',
|
||||||
|
component: () => import('../views/Training.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/news',
|
||||||
|
name: 'News',
|
||||||
|
component: () => import('../views/News.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/members',
|
||||||
|
name: 'Members',
|
||||||
|
component: () => import('../views/Members.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/reviews',
|
||||||
|
name: 'Reviews',
|
||||||
|
component: () => import('../views/Reviews.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/login',
|
||||||
|
name: 'Login',
|
||||||
|
component: () => import('../views/Login.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/profile',
|
||||||
|
name: 'Profile',
|
||||||
|
component: () => import('../views/Profile.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/register',
|
||||||
|
name: 'Register',
|
||||||
|
component: () => import('../views/Register.vue')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default router
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const useCounterStore = defineStore('counter', () => {
|
||||||
|
const count = ref(0)
|
||||||
|
const doubleCount = computed(() => count.value * 2)
|
||||||
|
function increment() {
|
||||||
|
count.value++
|
||||||
|
}
|
||||||
|
|
||||||
|
return { count, doubleCount, increment }
|
||||||
|
})
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<h1>👥 О нашем клубе</h1>
|
||||||
|
<p>Беговой клуб "Бегущий Башкир" - это сообщество единомышленников в Уфе</p>
|
||||||
|
|
||||||
|
<div class="content-section">
|
||||||
|
<h2>Наш тренер</h2>
|
||||||
|
<div class="coach-card">
|
||||||
|
<img src="https://via.placeholder.com/150/2e8b57/ffffff?text=ЗТ"
|
||||||
|
alt="Тренер"
|
||||||
|
style="border-radius: 50%; margin: 1rem 0;">
|
||||||
|
<h3>Аминев Загир</h3>
|
||||||
|
<p>Мастер спорта по полиатлону, КМС по скайраннингу</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<router-link to="/training" class="btn">Посмотреть расписание</router-link>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'About'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
<div class="about">
|
||||||
|
<h1>This is an about page</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.about {
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<h1>🏆 Наши достижения</h1>
|
||||||
|
<p>Лучшие результаты наших участников</p>
|
||||||
|
|
||||||
|
<div class="achievements-grid">
|
||||||
|
<div class="achievement-card">
|
||||||
|
<h3>🥇 Марафон 42.2 км</h3>
|
||||||
|
<p>Сергей - 3:27.49</p>
|
||||||
|
<p>Ғаяз - 3:34.33</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="achievement-card">
|
||||||
|
<h3>🥈 Полумарафон 21.1 км</h3>
|
||||||
|
<p>Ильгам - 1:23.33</p>
|
||||||
|
<p>Данил - 1:30.40</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="achievement-card">
|
||||||
|
<h3>🥉 Командные достижения</h3>
|
||||||
|
<p>III место в эстафете 4×400м (2024, 2025)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn" @click="$router.push('/members')">Посмотреть всех участников</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Achievements'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.achievements-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.achievement-card {
|
||||||
|
background: white;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
border-left: 4px solid #ffd700;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<h1>📸 Галерея</h1>
|
||||||
|
<p>Моменты из жизни нашего клуба</p>
|
||||||
|
|
||||||
|
<div class="gallery-grid">
|
||||||
|
<div v-for="n in 6" :key="n" class="gallery-item">
|
||||||
|
<img :src="`https://via.placeholder.com/300x200/2e8b57/ffffff?text=Фото+${n}`"
|
||||||
|
alt="Галерея"
|
||||||
|
style="width: 100%; border-radius: 8px;">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gallery-actions">
|
||||||
|
<button class="btn">📁 Альбомы</button>
|
||||||
|
<button class="btn">🎥 Видео</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Gallery'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.gallery-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-item {
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-item:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-actions {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="page home-page">
|
||||||
|
<h1>🏃 Добро пожаловать в Бегущий Башкир!</h1>
|
||||||
|
<p>Присоединяйтесь к нашему беговому сообществу в Уфе</p>
|
||||||
|
|
||||||
|
<div class="hero-section">
|
||||||
|
<img src="https://via.placeholder.com/800x400/2e8b57/ffffff?text=Бегущий+Башкир"
|
||||||
|
alt="Беговой клуб"
|
||||||
|
style="width: 100%; border-radius: 10px; margin: 2rem 0;">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="quick-links">
|
||||||
|
<h2>Быстрые ссылки</h2>
|
||||||
|
<div class="links-grid">
|
||||||
|
<router-link to="/training" class="btn">📅 Расписание тренировок</router-link>
|
||||||
|
<router-link to="/achievements" class="btn">🏆 Наши достижения</router-link>
|
||||||
|
<router-link to="/members" class="btn">👥 Участники клуба</router-link>
|
||||||
|
<router-link to="/gallery" class="btn">📸 Галерея</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Home'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.home-page {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-section {
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.links-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.links-grid .btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<script setup>
|
||||||
|
import TheWelcome from '../components/TheWelcome.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<main>
|
||||||
|
<TheWelcome />
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<h1>🔐 Вход в систему</h1>
|
||||||
|
<p>Войдите в свой личный кабинет</p>
|
||||||
|
|
||||||
|
<div class="login-form">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="email" placeholder="Email" class="form-input">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="password" placeholder="Пароль" class="form-input">
|
||||||
|
</div>
|
||||||
|
<button class="btn" @click="$router.push('/profile')">Войти</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="login-links">
|
||||||
|
<div class="register-link">
|
||||||
|
<p>Нет аккаунта? <router-link to="/register" class="link">Зарегистрируйтесь здесь</router-link></p>
|
||||||
|
</div>
|
||||||
|
<p><a href="#">Забыли пароль?</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary" @click="$router.push('/')">← На главную</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Login'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.login-form {
|
||||||
|
max-width: 300px;
|
||||||
|
margin: 2rem auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-links {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-links a {
|
||||||
|
color: #2e8b57;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-links a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<h1>👥 Участники клуба</h1>
|
||||||
|
<p>Наша дружная беговая семья</p>
|
||||||
|
|
||||||
|
<div class="members-grid">
|
||||||
|
<div v-for="member in members" :key="member.id" class="member-card">
|
||||||
|
<img :src="member.avatar"
|
||||||
|
:alt="member.name"
|
||||||
|
style="width: 80px; height: 80px; border-radius: 50%; margin-bottom: 1rem;">
|
||||||
|
<h3>{{ member.name }}</h3>
|
||||||
|
<p class="member-role">{{ member.role }}</p>
|
||||||
|
<p class="member-achievement">{{ member.achievement }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn" @click="$router.push('/achievements')">🏆 Посмотреть достижения</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Members',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
members: [
|
||||||
|
{ id: 1, name: 'Сергей', role: 'Марафонец', achievement: 'Лучший: 3:27.49', avatar: 'https://via.placeholder.com/80/2e8b57/ffffff?text=С' },
|
||||||
|
{ id: 2, name: 'Ильгам', role: 'Спринтер', achievement: '10км: 37:59', avatar: 'https://via.placeholder.com/80/2e8b57/ffffff?text=И' },
|
||||||
|
{ id: 3, name: 'Данил', role: 'Ультрамарафонец', achievement: 'Трейлы 120км', avatar: 'https://via.placeholder.com/80/2e8b57/ffffff?text=Д' },
|
||||||
|
{ id: 4, name: 'Ғаяз', role: 'Стайер', achievement: 'Марафон: 3:34.33', avatar: 'https://via.placeholder.com/80/2e8b57/ffffff?text=Ғ' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.members-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-card {
|
||||||
|
background: white;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
text-align: center;
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-card:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-role {
|
||||||
|
color: #2e8b57;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-achievement {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<h1>📰 Новости клуба</h1>
|
||||||
|
<p>Самые свежие события и анонсы</p>
|
||||||
|
|
||||||
|
<div class="news-list">
|
||||||
|
<div v-for="item in news" :key="item.id" class="news-card">
|
||||||
|
<h3>{{ item.title }}</h3>
|
||||||
|
<p class="news-date">{{ item.date }}</p>
|
||||||
|
<p>{{ item.excerpt }}</p>
|
||||||
|
<button class="btn btn-secondary">Читать далее</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn">📧 Подписаться на новости</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'News',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
news: [
|
||||||
|
{ id: 1, title: 'Новый набор в группу', date: '15.01.2025', excerpt: 'Открыт набор в группу для начинающих бегунов...' },
|
||||||
|
{ id: 2, title: 'Подготовка к весеннему марафону', date: '10.01.2025', excerpt: 'Стартует программа подготовки к Уфимскому марафону...' },
|
||||||
|
{ id: 3, title: 'Итоги забега РосХим', date: '05.01.2025', excerpt: 'Наши участники показали отличные результаты...' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.news-list {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 2rem auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.news-card {
|
||||||
|
background: white;
|
||||||
|
padding: 1.5rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.news-date {
|
||||||
|
color: #666;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<h1>👤 Личный кабинет</h1>
|
||||||
|
|
||||||
|
<div class="profile-header">
|
||||||
|
<img src="https://via.placeholder.com/100/2e8b57/ffffff?text=У"
|
||||||
|
alt="Аватар"
|
||||||
|
style="width: 100px; height: 100px; border-radius: 50%;">
|
||||||
|
<h2>Иван Иванов</h2>
|
||||||
|
<p>Участник с января 2024</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="profile-stats">
|
||||||
|
<h3>Моя статистика</h3>
|
||||||
|
<div class="stats-grid">
|
||||||
|
<div class="stat-card">
|
||||||
|
<h4>🏃 Всего пробег</h4>
|
||||||
|
<p>245 км</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<h4>⭐ Лучший результат</h4>
|
||||||
|
<p>10км - 48:15</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<h4>📅 Тренировок</h4>
|
||||||
|
<p>36</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="profile-actions">
|
||||||
|
<button class="btn">✏️ Редактировать профиль</button>
|
||||||
|
<button class="btn">📊 Подробная статистика</button>
|
||||||
|
<button class="btn" @click="$router.push('/training')">📅 Мой план тренировок</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary" @click="$router.push('/')">← На главную</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Profile'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.profile-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
background: white;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
max-width: 300px;
|
||||||
|
margin: 2rem auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,402 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<div class="register-container">
|
||||||
|
<h1>👤 Регистрация</h1>
|
||||||
|
<p>Присоединяйтесь к нашему беговому сообществу</p>
|
||||||
|
|
||||||
|
<form @submit.prevent="handleRegister" class="register-form">
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="firstName">Имя *</label>
|
||||||
|
<input
|
||||||
|
id="firstName"
|
||||||
|
v-model="formData.firstName"
|
||||||
|
type="text"
|
||||||
|
class="form-input"
|
||||||
|
placeholder="Введите ваше имя"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="lastName">Фамилия *</label>
|
||||||
|
<input
|
||||||
|
id="lastName"
|
||||||
|
v-model="formData.lastName"
|
||||||
|
type="text"
|
||||||
|
class="form-input"
|
||||||
|
placeholder="Введите вашу фамилию"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">Email *</label>
|
||||||
|
<input
|
||||||
|
id="email"
|
||||||
|
v-model="formData.email"
|
||||||
|
type="email"
|
||||||
|
class="form-input"
|
||||||
|
placeholder="example@mail.ru"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="phone">Телефон</label>
|
||||||
|
<input
|
||||||
|
id="phone"
|
||||||
|
v-model="formData.phone"
|
||||||
|
type="tel"
|
||||||
|
class="form-input"
|
||||||
|
placeholder="+7 (999) 123-45-67"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">Пароль *</label>
|
||||||
|
<input
|
||||||
|
id="password"
|
||||||
|
v-model="formData.password"
|
||||||
|
type="password"
|
||||||
|
class="form-input"
|
||||||
|
placeholder="Не менее 6 символов"
|
||||||
|
required
|
||||||
|
minlength="6"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="confirmPassword">Подтверждение пароля *</label>
|
||||||
|
<input
|
||||||
|
id="confirmPassword"
|
||||||
|
v-model="formData.confirmPassword"
|
||||||
|
type="password"
|
||||||
|
class="form-input"
|
||||||
|
placeholder="Повторите пароль"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="experience">Уровень подготовки</label>
|
||||||
|
<select
|
||||||
|
id="experience"
|
||||||
|
v-model="formData.experience"
|
||||||
|
class="form-input"
|
||||||
|
>
|
||||||
|
<option value="">Выберите уровень</option>
|
||||||
|
<option value="beginner">Начинающий (0-6 месяцев)</option>
|
||||||
|
<option value="intermediate">Любитель (6-24 месяцев)</option>
|
||||||
|
<option value="advanced">Опытный (2+ лет)</option>
|
||||||
|
<option value="professional">Профессионал</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="goals">Цели</label>
|
||||||
|
<select
|
||||||
|
id="goals"
|
||||||
|
v-model="formData.goals"
|
||||||
|
class="form-input"
|
||||||
|
>
|
||||||
|
<option value="">Выберите цель</option>
|
||||||
|
<option value="health">Улучшить здоровье</option>
|
||||||
|
<option value="weight">Сбросить вес</option>
|
||||||
|
<option value="first5k">Пробежать первые 5 км</option>
|
||||||
|
<option value="first10k">Пробежать первые 10 км</option>
|
||||||
|
<option value="halfMarathon">Подготовиться к полумарафону</option>
|
||||||
|
<option value="marathon">Подготовиться к марафону</option>
|
||||||
|
<option value="improve">Улучшить результаты</option>
|
||||||
|
<option value="social">Общение и компания</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group checkbox-group">
|
||||||
|
<label class="checkbox-label">
|
||||||
|
<input
|
||||||
|
v-model="formData.agreeTerms"
|
||||||
|
type="checkbox"
|
||||||
|
class="checkbox"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
Я соглашаюсь с
|
||||||
|
<a href="#" class="link">правилами клуба</a> и
|
||||||
|
<a href="#" class="link">политикой конфиденциальности</a> *
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group checkbox-group">
|
||||||
|
<label class="checkbox-label">
|
||||||
|
<input
|
||||||
|
v-model="formData.newsletter"
|
||||||
|
type="checkbox"
|
||||||
|
class="checkbox"
|
||||||
|
>
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
Хочу получать новости о тренировках и мероприятиях
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-primary"
|
||||||
|
:disabled="!formData.agreeTerms || loading"
|
||||||
|
>
|
||||||
|
{{ loading ? 'Регистрация...' : '🏃 Зарегистрироваться' }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div v-if="error" class="error-message">
|
||||||
|
{{ error }}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="login-link">
|
||||||
|
<p>Уже есть аккаунт? <router-link to="/login" class="link">Войдите здесь</router-link></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="benefits">
|
||||||
|
<h3>Что вы получите после регистрации:</h3>
|
||||||
|
<ul class="benefits-list">
|
||||||
|
<li>✅ Доступ к расписанию тренировок</li>
|
||||||
|
<li>✅ Персональный трекер прогресса</li>
|
||||||
|
<li>✅ Общение с тренером и участниками</li>
|
||||||
|
<li>✅ Участие в клубных мероприятиях</li>
|
||||||
|
<li>✅ Скидки на стартовые взносы</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary" @click="$router.push('/')">← На главную</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Register',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formData: {
|
||||||
|
firstName: '',
|
||||||
|
lastName: '',
|
||||||
|
email: '',
|
||||||
|
phone: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
|
experience: '',
|
||||||
|
goals: '',
|
||||||
|
agreeTerms: false,
|
||||||
|
newsletter: true
|
||||||
|
},
|
||||||
|
loading: false,
|
||||||
|
error: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async handleRegister() {
|
||||||
|
// Валидация
|
||||||
|
if (this.formData.password !== this.formData.confirmPassword) {
|
||||||
|
this.error = 'Пароли не совпадают'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.formData.password.length < 6) {
|
||||||
|
this.error = 'Пароль должен содержать не менее 6 символов'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.formData.agreeTerms) {
|
||||||
|
this.error = 'Необходимо согласие с правилами клуба'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loading = true
|
||||||
|
this.error = ''
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Здесь будет API call к backend
|
||||||
|
console.log('Регистрация:', this.formData)
|
||||||
|
|
||||||
|
// Имитация задержки сети
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1500))
|
||||||
|
|
||||||
|
// Успешная регистрация
|
||||||
|
this.$router.push('/login?message=registered')
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
this.error = 'Ошибка регистрации. Попробуйте еще раз.'
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.register-container {
|
||||||
|
max-width: 500px;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-form {
|
||||||
|
background: white;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 15px rgba(0,0,0,0.1);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
border: 2px solid #e1e5e9;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 1rem;
|
||||||
|
transition: border-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #2e8b57;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-group {
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkmark {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border: 2px solid #ddd;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-top: 2px;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox:checked + .checkmark {
|
||||||
|
background-color: #2e8b57;
|
||||||
|
border-color: #2e8b57;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox:checked + .checkmark::after {
|
||||||
|
content: '✓';
|
||||||
|
color: white;
|
||||||
|
position: absolute;
|
||||||
|
top: -2px;
|
||||||
|
left: 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #2e8b57;
|
||||||
|
color: white;
|
||||||
|
padding: 15px;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover:not(:disabled) {
|
||||||
|
background-color: #26734a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:disabled {
|
||||||
|
background-color: #ccc;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
background-color: #fee;
|
||||||
|
color: #c33;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-top: 1rem;
|
||||||
|
border-left: 4px solid #c33;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-link {
|
||||||
|
text-align: center;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: #2e8b57;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefits {
|
||||||
|
background-color: #f8fff8;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
border-left: 4px solid #2e8b57;
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefits h3 {
|
||||||
|
color: #2e8b57;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefits-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefits-list li {
|
||||||
|
padding: 0.3rem 0;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Адаптивность */
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.form-row {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-form {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<h1>⭐ Отзывы</h1>
|
||||||
|
<p>Что говорят наши участники</p>
|
||||||
|
|
||||||
|
<div class="reviews-list">
|
||||||
|
<div v-for="review in reviews" :key="review.id" class="review-card">
|
||||||
|
<div class="review-header">
|
||||||
|
<span class="review-author">{{ review.author }}</span>
|
||||||
|
<span class="review-rating">⭐ {{ review.rating }}/5</span>
|
||||||
|
</div>
|
||||||
|
<p class="review-text">{{ review.text }}</p>
|
||||||
|
<p class="review-date">{{ review.date }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="review-actions">
|
||||||
|
<button class="btn" @click="$router.push('/login')">✍️ Оставить отзыв</button>
|
||||||
|
<button class="btn btn-secondary">📊 Все отзывы</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Reviews',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
reviews: [
|
||||||
|
{ id: 1, author: 'Анна', rating: 5, text: 'Отличный клуб! За 3 месяца улучшила результат на 10км на 8 минут!', date: '15.01.2025' },
|
||||||
|
{ id: 2, author: 'Михаил', rating: 5, text: 'Профессиональный тренер и дружеская атмосфера. Рекомендую!', date: '12.01.2025' },
|
||||||
|
{ id: 3, author: 'Елена', rating: 4, text: 'Очень нравятся групповые тренировки, всегда есть с кем побегать', date: '10.01.2025' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.reviews-list {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 2rem auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-card {
|
||||||
|
background: white;
|
||||||
|
padding: 1.5rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-author {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #2e8b57;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-rating {
|
||||||
|
color: #ffd700;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-text {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-date {
|
||||||
|
color: #666;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-actions {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<h1>📅 Тренировки</h1>
|
||||||
|
<p>Расписание и программы тренировок</p>
|
||||||
|
|
||||||
|
<div class="schedule-section">
|
||||||
|
<h2>Расписание на неделю</h2>
|
||||||
|
<div class="schedule-grid">
|
||||||
|
<div v-for="day in schedule" :key="day.name" class="schedule-day">
|
||||||
|
<h4>{{ day.name }}</h4>
|
||||||
|
<p><strong>{{ day.time }}</strong></p>
|
||||||
|
<p>{{ day.activity }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="training-actions">
|
||||||
|
<button class="btn">📚 База знаний</button>
|
||||||
|
<button class="btn">💪 Программы тренировок</button>
|
||||||
|
<button class="btn" @click="$router.push('/members')">👥 Найти партнера для тренировок</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Training',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
schedule: [
|
||||||
|
{ name: 'Понедельник', time: '19:30', activity: 'Техника бега + ОФП' },
|
||||||
|
{ name: 'Вторник', time: '--:--', activity: 'Восстановление' },
|
||||||
|
{ name: 'Среда', time: '19:30', activity: 'Техника бега + СБУ' },
|
||||||
|
{ name: 'Четверг', time: '--:--', activity: 'Восстановление' },
|
||||||
|
{ name: 'Пятница', time: '--:--', activity: 'Восстановление' },
|
||||||
|
{ name: 'Суббота', time: '10:00', activity: 'Длительный кросс' },
|
||||||
|
{ name: 'Воскресенье', time: '--:--', activity: 'Восстановление' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.schedule-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.schedule-day {
|
||||||
|
background: white;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.training-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
|
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||||
|
|
||||||
|
// https://vite.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
vueDevTools(),
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
port: 3001,
|
||||||
|
host: true
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user