feat: add Vue 3 personal site for valitovgaziz in main_dc/my_site
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Valitov Gaziz | Технологический предприниматель</title>
|
||||||
|
<meta name="description" content="Валитов Газиз — технологический предприниматель и fullstack-разработчик. Создатель Yalarba.ru, EasySite102.ru." />
|
||||||
|
</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
+1395
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "my_site",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vue": "^3.5.22",
|
||||||
|
"vue-router": "^4.5.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-vue": "^6.0.1",
|
||||||
|
"vite": "^7.1.7"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<template>
|
||||||
|
<div id="app" :class="{ 'menu-open': mobileMenuOpen }">
|
||||||
|
<TheHeader @toggle-theme="toggleTheme" @toggle-menu="toggleMenu" :theme="theme" :menu-open="mobileMenuOpen" />
|
||||||
|
<main class="main-content">
|
||||||
|
<router-view />
|
||||||
|
</main>
|
||||||
|
<TheFooter />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import TheHeader from './components/TheHeader.vue'
|
||||||
|
import TheFooter from './components/TheFooter.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'App',
|
||||||
|
components: {
|
||||||
|
TheHeader,
|
||||||
|
TheFooter,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
theme: 'dark',
|
||||||
|
mobileMenuOpen: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
const saved = localStorage.getItem('theme')
|
||||||
|
if (saved) {
|
||||||
|
this.theme = saved
|
||||||
|
}
|
||||||
|
document.documentElement.setAttribute('data-theme', this.theme)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleTheme() {
|
||||||
|
this.theme = this.theme === 'dark' ? 'light' : 'dark'
|
||||||
|
localStorage.setItem('theme', this.theme)
|
||||||
|
document.documentElement.setAttribute('data-theme', this.theme)
|
||||||
|
},
|
||||||
|
toggleMenu() {
|
||||||
|
this.mobileMenuOpen = !this.mobileMenuOpen
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.main-content {
|
||||||
|
min-height: calc(100vh - 160px);
|
||||||
|
padding-top: 70px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
:root {
|
||||||
|
--bg: #ffffff;
|
||||||
|
--bg-secondary: #f5f7fa;
|
||||||
|
--text: #1a1a2e;
|
||||||
|
--text-secondary: #4a4a6a;
|
||||||
|
--accent: #2563eb;
|
||||||
|
--accent-hover: #1d4ed8;
|
||||||
|
--card-bg: #ffffff;
|
||||||
|
--border: #e2e8f0;
|
||||||
|
--header-bg: rgba(255, 255, 255, 0.9);
|
||||||
|
--skill-bg: #eef2ff;
|
||||||
|
--tag-bg: #e0e7ff;
|
||||||
|
--tag-text: #3730a3;
|
||||||
|
--shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
--shadow-lg: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||||
|
--gradient-hero: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
--max-width: 1100px;
|
||||||
|
--radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] {
|
||||||
|
--bg: #0f172a;
|
||||||
|
--bg-secondary: #1e293b;
|
||||||
|
--text: #e2e8f0;
|
||||||
|
--text-secondary: #94a3b8;
|
||||||
|
--accent: #60a5fa;
|
||||||
|
--accent-hover: #3b82f6;
|
||||||
|
--card-bg: #1e293b;
|
||||||
|
--border: #334155;
|
||||||
|
--header-bg: rgba(15, 23, 42, 0.9);
|
||||||
|
--skill-bg: #1e293b;
|
||||||
|
--tag-bg: #1e293b;
|
||||||
|
--tag-text: #93c5fd;
|
||||||
|
--shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||||
|
--shadow-lg: 0 10px 30px rgba(0, 0, 0, 0.4);
|
||||||
|
--gradient-hero: linear-gradient(135deg, #1e3a5f 0%, #2d1b69 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||||
|
background-color: var(--bg);
|
||||||
|
color: var(--text);
|
||||||
|
line-height: 1.6;
|
||||||
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--accent);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: var(--accent-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: var(--max-width);
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
padding: 80px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section:nth-child(even) {
|
||||||
|
background-color: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 48px;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 60px;
|
||||||
|
height: 4px;
|
||||||
|
background: var(--accent);
|
||||||
|
margin: 12px auto 0;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: var(--card-bg);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 24px;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 12px 28px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background: var(--accent);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background: var(--accent-hover);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline {
|
||||||
|
background: transparent;
|
||||||
|
border: 2px solid var(--accent);
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline:hover {
|
||||||
|
background: var(--accent);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-in {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
transition: opacity 0.6s ease, transform 0.6s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-in.visible {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.section {
|
||||||
|
padding: 48px 0;
|
||||||
|
}
|
||||||
|
.section-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="container footer-content">
|
||||||
|
<div class="footer-info">
|
||||||
|
<p>Уфа · Ufa · Өфө</p>
|
||||||
|
<p>© 2025 Valitov Gaziz</p>
|
||||||
|
</div>
|
||||||
|
<div class="footer-links">
|
||||||
|
<a href="https://t.me/valitovgaziz" target="_blank" rel="noopener noreferrer" class="footer-link">
|
||||||
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/></svg>
|
||||||
|
</a>
|
||||||
|
<a href="https://vk.com/valitovgaziz" target="_blank" rel="noopener noreferrer" class="footer-link">
|
||||||
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M15.684 0H8.316C2.879 0 0 2.879 0 8.316v7.368C0 21.121 2.879 24 8.316 24h7.368C21.121 24 24 21.121 24 15.684V8.316C24 2.879 21.121 0 15.684 0zm3.6 16.535h-1.651c-.849 0-1.08-.595-1.728-1.289-.566-.604-1.05-1.097-1.89-1.097-.97 0-1.4.513-1.4 1.316v1.07c0 .456-.178.72-1.076.72-1.583 0-3.308-1.088-4.33-2.539-1.443-1.875-1.83-3.36-1.83-3.636 0-.177.151-.343.448-.343h1.652c.468 0 .64.227.82.735.633 1.937 1.699 3.633 2.345 3.633.22 0 .306-.11.306-.576v-2.22c-.111-1.048-.672-1.124-.672-1.504 0-.242.168-.44.45-.44h2.578c.347 0 .46.196.46.573v2.176c0 .346.149.44.254.44.224 0 .38-.094.598-.317.604-.7 1.118-1.847 1.118-1.847.088-.215.224-.423.513-.423h1.651c.493 0 .597.252.493.619-.307.953-1.577 2.764-1.577 2.764-.168.257-.224.381 0 .638.168.224.739.672 1.126 1.09.392.423.672.747.784.985.196.44-.056.735-.54.735z"/></svg>
|
||||||
|
</a>
|
||||||
|
<a href="mailto:valitovgaziz@yandex.ru" class="footer-link">
|
||||||
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M22 4L12 13L2 4"/></svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'TheFooter',
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.footer {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
padding: 32px 0;
|
||||||
|
margin-top: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-info p {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-link {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
transition: color 0.2s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-link:hover {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.footer-content {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,178 @@
|
|||||||
|
<template>
|
||||||
|
<header class="header">
|
||||||
|
<div class="container header-container">
|
||||||
|
<router-link to="/" class="logo">Valitov<span>Gaziz</span></router-link>
|
||||||
|
<nav class="nav" :class="{ 'nav-open': menuOpen }">
|
||||||
|
<router-link to="/" class="nav-link" @click="$emit('toggle-menu')">Главная</router-link>
|
||||||
|
<a href="#about" class="nav-link" @click="closeMenu">Обо мне</a>
|
||||||
|
<a href="#projects" class="nav-link" @click="closeMenu">Проекты</a>
|
||||||
|
<a href="#experience" class="nav-link" @click="closeMenu">Опыт</a>
|
||||||
|
<a href="#skills" class="nav-link" @click="closeMenu">Навыки</a>
|
||||||
|
<a href="#contact" class="nav-link" @click="closeMenu">Контакты</a>
|
||||||
|
<router-link to="/blog" class="nav-link" @click="$emit('toggle-menu')">Блог</router-link>
|
||||||
|
</nav>
|
||||||
|
<div class="header-actions">
|
||||||
|
<button class="theme-toggle" @click="$emit('toggle-theme')" :aria-label="theme === 'dark' ? 'Светлая тема' : 'Тёмная тема'">
|
||||||
|
<svg v-if="theme === 'dark'" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
|
||||||
|
<svg v-else width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
|
||||||
|
</button>
|
||||||
|
<button class="burger" @click="$emit('toggle-menu')" :aria-label="menuOpen ? 'Закрыть меню' : 'Открыть меню'">
|
||||||
|
<span></span><span></span><span></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'TheHeader',
|
||||||
|
props: {
|
||||||
|
theme: { type: String, required: true },
|
||||||
|
menuOpen: { type: Boolean, default: false },
|
||||||
|
},
|
||||||
|
emits: ['toggle-theme', 'toggle-menu'],
|
||||||
|
methods: {
|
||||||
|
closeMenu() {
|
||||||
|
if (this.menuOpen) {
|
||||||
|
this.$emit('toggle-menu')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.header {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
background: var(--header-bg);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
transition: background 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text);
|
||||||
|
letter-spacing: -0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo span {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link:hover,
|
||||||
|
.router-link-exact-active {
|
||||||
|
color: var(--accent);
|
||||||
|
background: var(--skill-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle {
|
||||||
|
background: none;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
color: var(--text);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle:hover {
|
||||||
|
border-color: var(--accent);
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.burger {
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.burger span {
|
||||||
|
display: block;
|
||||||
|
width: 24px;
|
||||||
|
height: 2px;
|
||||||
|
background: var(--text);
|
||||||
|
border-radius: 2px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-open .burger span:nth-child(1) {
|
||||||
|
transform: rotate(45deg) translate(5px, 5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-open .burger span:nth-child(2) {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-open .burger span:nth-child(3) {
|
||||||
|
transform: rotate(-45deg) translate(5px, -5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.nav {
|
||||||
|
position: fixed;
|
||||||
|
top: 70px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: var(--bg);
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
gap: 4px;
|
||||||
|
transform: translateY(-100%);
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: all 0.3s;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-open {
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.burger {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import './assets/main.css'
|
||||||
|
|
||||||
|
import { createApp } from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
import router from './router'
|
||||||
|
|
||||||
|
const app = createApp(App)
|
||||||
|
|
||||||
|
app.use(router)
|
||||||
|
|
||||||
|
app.mount('#app')
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
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: '/blog',
|
||||||
|
name: 'Blog',
|
||||||
|
component: () => import('../views/Blog.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
export default router
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
<template>
|
||||||
|
<div class="blog-page">
|
||||||
|
<section class="blog-hero">
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="blog-title">Блог</h1>
|
||||||
|
<p class="blog-subtitle">Мысли, идеи и заметки о разработке, технологиях и предпринимательстве</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<div class="blog-list">
|
||||||
|
<article v-for="(post, index) in posts" :key="index" class="blog-post card" :class="{ 'fade-in': true, 'visible': true }">
|
||||||
|
<div class="post-meta">
|
||||||
|
<span class="post-date">{{ post.date }}</span>
|
||||||
|
<span class="post-read-time">{{ post.readTime }}</span>
|
||||||
|
</div>
|
||||||
|
<h2 class="post-title">{{ post.title }}</h2>
|
||||||
|
<p class="post-excerpt">{{ post.excerpt }}</p>
|
||||||
|
<blockquote v-if="post.quote" class="post-quote">
|
||||||
|
{{ post.quote }}
|
||||||
|
</blockquote>
|
||||||
|
<p v-if="post.additional" class="post-excerpt">{{ post.additional }}</p>
|
||||||
|
<div class="post-tags">
|
||||||
|
<span v-for="(tag, tIndex) in post.tags" :key="tIndex" class="post-tag">{{ tag }}</span>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'BlogView',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
posts: [
|
||||||
|
{
|
||||||
|
date: '20 марта 2024',
|
||||||
|
readTime: '6 мин чтения',
|
||||||
|
title: 'EasySite & YalArba: текущее состояние и планы развития',
|
||||||
|
excerpt: 'EasySite (B2B) — конструктор сайтов для отелей, санаториев, ресторанов. YalArba (B2C) — агрегатор для туристов с поиском, отзывами и системой бронирования.',
|
||||||
|
additional: 'Уже работают: JWT-авторизация, Docker-инфраструктура, SSL (Let\'s Encrypt), базовая аналитика. В бете: easysite102.ru и yalarba.ru.',
|
||||||
|
tags: ['EasySite', 'YalArba', 'Туризм', 'Стартап'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '25 марта 2024',
|
||||||
|
readTime: '8 мин чтения',
|
||||||
|
title: 'Почему я создаю YalArba: история и миссия',
|
||||||
|
excerpt: 'История началась в 2017 году — работа на заводе и учёба не могли затмить желания создать что-то полезное. Не найдя бесплатных маршрутов для путешествий онлайн, решил сделать решение сам.',
|
||||||
|
additional: 'Большинство сервисов будут бесплатными — хочется предоставить доступные альтернативы для всех. Бизнес-модель строится на ценности от количества пользователей.',
|
||||||
|
quote: 'Технологии должны решать реальные проблемы людей, а не создавать новые.',
|
||||||
|
tags: ['История', 'Миссия', 'Социальный проект', 'Туризм'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '15 марта 2024',
|
||||||
|
readTime: '5 мин чтения',
|
||||||
|
title: 'Новый этап развития Yalarba.ru',
|
||||||
|
excerpt: 'Завершён переход на новую архитектуру. Реализованы: обновлённый интерфейс поиска маршрутов, интеграция картографических сервисов, улучшенная система рекомендаций, подготовка мобильного приложения.',
|
||||||
|
tags: ['Yalarba', 'TravelTech', 'Разработка'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '10 марта 2024',
|
||||||
|
readTime: '7 мин чтения',
|
||||||
|
title: 'Переход с Vue 2 на Vue 3: опыт и выводы',
|
||||||
|
excerpt: 'Ключевые преимущества: Composition API, улучшенная производительность, поддержка TypeScript, меньший размер бандла. Миграция прошла гладко, но потребовала внимания к деталям.',
|
||||||
|
tags: ['Vue3', 'Фронтенд', 'JavaScript'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '5 марта 2024',
|
||||||
|
readTime: '4 мин чтения',
|
||||||
|
title: 'О важности сообщества в разработке',
|
||||||
|
excerpt: 'Профессиональный рост через сообщество: обратная связь, совместное обучение, поддержка и вдохновение. Нетворкинг и обмен опытом — ключ к развитию.',
|
||||||
|
tags: ['Сообщество', 'Разработка', 'IT'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.blog-hero {
|
||||||
|
padding: 80px 0 40px;
|
||||||
|
text-align: center;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-title {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: 800;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-subtitle {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-list {
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-post {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-date {
|
||||||
|
color: var(--accent);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-read-time {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-title {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-excerpt {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.7;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-quote {
|
||||||
|
border-left: 3px solid var(--accent);
|
||||||
|
padding: 12px 20px;
|
||||||
|
margin: 16px 0;
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 0 8px 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-tag {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: var(--tag-bg);
|
||||||
|
color: var(--tag-text);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.blog-title {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,767 @@
|
|||||||
|
<template>
|
||||||
|
<div class="home">
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-bg"></div>
|
||||||
|
<div class="container hero-content">
|
||||||
|
<div class="hero-text">
|
||||||
|
<p class="hero-greeting">Привет, я</p>
|
||||||
|
<h1 class="hero-name">Валитов Газиз</h1>
|
||||||
|
<p class="hero-title">Технологический предприниматель & Fullstack-разработчик</p>
|
||||||
|
<p class="hero-desc">
|
||||||
|
Создаю цифровые продукты, которые меняют жизнь людей к лучшему.
|
||||||
|
Основатель проектов Yalarba.ru и EasySite102.ru.
|
||||||
|
</p>
|
||||||
|
<div class="hero-buttons">
|
||||||
|
<a href="https://t.me/valitovgaziz" target="_blank" rel="noopener noreferrer" class="btn btn-primary">
|
||||||
|
Написать в Telegram
|
||||||
|
</a>
|
||||||
|
<router-link to="/blog" class="btn btn-outline">
|
||||||
|
Читать блог
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
<div class="hero-social">
|
||||||
|
<a href="https://t.me/valitovgaziz" target="_blank" rel="noopener noreferrer" class="social-link" title="Telegram">@valitovgaziz</a>
|
||||||
|
<a href="https://vk.com/valitovgaziz" target="_blank" rel="noopener noreferrer" class="social-link" title="VK">vk.com/valitovgaziz</a>
|
||||||
|
<a href="mailto:valitovgaziz@yandex.ru" class="social-link" title="Email">valitovgaziz@yandex.ru</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hero-image">
|
||||||
|
<div class="hero-photo">
|
||||||
|
<div class="photo-placeholder">
|
||||||
|
<svg width="80" height="80" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="about" class="section">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="section-title">Обо мне</h2>
|
||||||
|
<div class="about-content">
|
||||||
|
<div class="about-text">
|
||||||
|
<p class="about-paragraph">
|
||||||
|
Родился в городе Кумертау в 1985 году. Окончил УГАТУ (Уфимский государственный авиационный технический университет), прошёл службу в армии, работал на производстве.
|
||||||
|
</p>
|
||||||
|
<p class="about-paragraph">
|
||||||
|
С 2015 года в IT — прошёл путь от техника до основателя собственного технологического проекта. За плечами опыт работы с Go, Vue 3, Nuxt.js, PostgreSQL, Docker и другими современными технологиями.
|
||||||
|
</p>
|
||||||
|
<p class="about-paragraph">
|
||||||
|
Моя миссия — создавать продукты, которые приносят реальную пользу людям и делают туризм в Башкортостане доступнее и удобнее.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="about-highlights">
|
||||||
|
<div class="highlight-card">
|
||||||
|
<div class="highlight-icon">
|
||||||
|
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
|
||||||
|
</div>
|
||||||
|
<h4>Техническое видение</h4>
|
||||||
|
<p>Создаю масштабируемую архитектуру, выбираю правильные инструменты под задачи</p>
|
||||||
|
</div>
|
||||||
|
<div class="highlight-card">
|
||||||
|
<div class="highlight-icon">
|
||||||
|
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
|
||||||
|
</div>
|
||||||
|
<h4>Бизнес-ориентация</h4>
|
||||||
|
<p>Фокус на пользовательской ценности и устойчивых бизнес-моделях</p>
|
||||||
|
</div>
|
||||||
|
<div class="highlight-card">
|
||||||
|
<div class="highlight-icon">
|
||||||
|
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
|
||||||
|
</div>
|
||||||
|
<h4>Практический подход</h4>
|
||||||
|
<p>От прототипа до продукта — быстрое тестирование гипотез и итеративное развитие</p>
|
||||||
|
</div>
|
||||||
|
<div class="highlight-card">
|
||||||
|
<div class="highlight-icon">
|
||||||
|
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>
|
||||||
|
</div>
|
||||||
|
<h4>Мотивация</h4>
|
||||||
|
<p>Создание проекта, который приносит пользу многим людям</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="projects" class="section">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="section-title">Проекты</h2>
|
||||||
|
<div class="projects-grid">
|
||||||
|
<div class="project-card card">
|
||||||
|
<div class="project-header">
|
||||||
|
<h3 class="project-name">Yalarba.ru</h3>
|
||||||
|
<span class="project-status">Активный</span>
|
||||||
|
</div>
|
||||||
|
<p class="project-desc">
|
||||||
|
Туристическая платформа для Республики Башкортостан. Помогает путешественникам открывать новые места, строить маршруты и планировать поездки.
|
||||||
|
</p>
|
||||||
|
<div class="project-tech">
|
||||||
|
<span class="tech-tag">Go</span>
|
||||||
|
<span class="tech-tag">Nuxt.js 4</span>
|
||||||
|
<span class="tech-tag">PostgreSQL</span>
|
||||||
|
<span class="tech-tag">Docker</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="project-card card">
|
||||||
|
<div class="project-header">
|
||||||
|
<h3 class="project-name">EasySite102.ru</h3>
|
||||||
|
<span class="project-status">Бета</span>
|
||||||
|
</div>
|
||||||
|
<p class="project-desc">
|
||||||
|
Конструктор сайтов для бизнеса в сфере туризма: отелей, санаториев, ресторанов. Часть экосистемы YalArba.
|
||||||
|
</p>
|
||||||
|
<div class="project-tech">
|
||||||
|
<span class="tech-tag">Vue 3</span>
|
||||||
|
<span class="tech-tag">Nuxt.js</span>
|
||||||
|
<span class="tech-tag">Go</span>
|
||||||
|
<span class="tech-tag">PostgreSQL</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="project-card card">
|
||||||
|
<div class="project-header">
|
||||||
|
<h3 class="project-name">BegushiyBashkir.ru</h3>
|
||||||
|
<span class="project-status">Активный</span>
|
||||||
|
</div>
|
||||||
|
<p class="project-desc">
|
||||||
|
Беговой клуб. Сайт для бегового сообщества, основанного другом и партнёром Аминевым Загиром.
|
||||||
|
</p>
|
||||||
|
<div class="project-tech">
|
||||||
|
<span class="tech-tag">Vue 3</span>
|
||||||
|
<span class="tech-tag">Go</span>
|
||||||
|
<span class="tech-tag">PostgreSQL</span>
|
||||||
|
<span class="tech-tag">Docker</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="experience" class="section">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="section-title">Опыт работы</h2>
|
||||||
|
<div class="timeline">
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-dot"></div>
|
||||||
|
<div class="timeline-content card">
|
||||||
|
<div class="timeline-period">2020 — настоящее время</div>
|
||||||
|
<h3 class="timeline-title">Основатель и Tech Lead</h3>
|
||||||
|
<p class="timeline-company">Yalarba.ru</p>
|
||||||
|
<ul class="timeline-duties">
|
||||||
|
<li>Микросервисы на Go + Nuxt.js 4</li>
|
||||||
|
<li>Проектирование и оптимизация PostgreSQL</li>
|
||||||
|
<li>Docker-инфраструктура, управление продуктом</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-dot"></div>
|
||||||
|
<div class="timeline-content card">
|
||||||
|
<div class="timeline-period">2017 — настоящее время</div>
|
||||||
|
<h3 class="timeline-title">Fullstack-разработчик (Контракты)</h3>
|
||||||
|
<p class="timeline-company">Фриланс / Проектная работа</p>
|
||||||
|
<ul class="timeline-duties">
|
||||||
|
<li>REST API на Go (GORM, Chi)</li>
|
||||||
|
<li>Фронтенд на Nuxt.js 4 / Vue 3</li>
|
||||||
|
<li>Посадочные страницы, интеграции</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="education" class="section">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="section-title">Образование</h2>
|
||||||
|
<div class="education-grid">
|
||||||
|
<div class="edu-card card">
|
||||||
|
<div class="edu-year">2025 — н.в.</div>
|
||||||
|
<h4>МТИ — Московский технологический институт</h4>
|
||||||
|
<p>Разработка программного обеспечения</p>
|
||||||
|
</div>
|
||||||
|
<div class="edu-card card">
|
||||||
|
<div class="edu-year">2021</div>
|
||||||
|
<h4>Университет Иннополис</h4>
|
||||||
|
<p>Java Enterprise Developer</p>
|
||||||
|
</div>
|
||||||
|
<div class="edu-card card">
|
||||||
|
<div class="edu-year">2016 — 2020</div>
|
||||||
|
<h4>Уфимский колледж статистики и информатики</h4>
|
||||||
|
<p>Техник по информационным системам</p>
|
||||||
|
</div>
|
||||||
|
<div class="edu-card card">
|
||||||
|
<div class="edu-year">2002 — 2005</div>
|
||||||
|
<h4>УГАТУ</h4>
|
||||||
|
<p>Технология сварочного производства</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="skills" class="section">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="section-title">Навыки</h2>
|
||||||
|
<div class="skills-grid">
|
||||||
|
<div class="skill-card card">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span class="skill-name">Golang</span>
|
||||||
|
<span class="skill-level">Продвинутый</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar"><div class="skill-fill" style="width: 90%"></div></div>
|
||||||
|
</div>
|
||||||
|
<div class="skill-card card">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span class="skill-name">JavaScript</span>
|
||||||
|
<span class="skill-level">Продвинутый</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar"><div class="skill-fill" style="width: 85%"></div></div>
|
||||||
|
</div>
|
||||||
|
<div class="skill-card card">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span class="skill-name">Vue 3</span>
|
||||||
|
<span class="skill-level">Средний</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar"><div class="skill-fill" style="width: 70%"></div></div>
|
||||||
|
</div>
|
||||||
|
<div class="skill-card card">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span class="skill-name">Nuxt.js</span>
|
||||||
|
<span class="skill-level">Средний</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar"><div class="skill-fill" style="width: 65%"></div></div>
|
||||||
|
</div>
|
||||||
|
<div class="skill-card card">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span class="skill-name">PostgreSQL</span>
|
||||||
|
<span class="skill-level">Средний</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar"><div class="skill-fill" style="width: 70%"></div></div>
|
||||||
|
</div>
|
||||||
|
<div class="skill-card card">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span class="skill-name">Docker</span>
|
||||||
|
<span class="skill-level">Средний</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar"><div class="skill-fill" style="width: 70%"></div></div>
|
||||||
|
</div>
|
||||||
|
<div class="skill-card card">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span class="skill-name">Java</span>
|
||||||
|
<span class="skill-level">Начальный</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar"><div class="skill-fill" style="width: 40%"></div></div>
|
||||||
|
</div>
|
||||||
|
<div class="skill-card card">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span class="skill-name">Spring Framework</span>
|
||||||
|
<span class="skill-level">Начальный</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar"><div class="skill-fill" style="width: 35%"></div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="contact" class="section">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="section-title">Контакты</h2>
|
||||||
|
<div class="contact-content">
|
||||||
|
<p class="contact-text">Открыт к общению, сотрудничеству и новым проектам. Пишите!</p>
|
||||||
|
<div class="contact-links">
|
||||||
|
<a href="https://t.me/valitovgaziz" target="_blank" rel="noopener noreferrer" class="contact-item">
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/></svg>
|
||||||
|
<span>@valitovgaziz</span>
|
||||||
|
</a>
|
||||||
|
<a href="mailto:valitovgaziz@yandex.ru" class="contact-item">
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M22 4L12 13L2 4"/></svg>
|
||||||
|
<span>valitovgaziz@yandex.ru</span>
|
||||||
|
</a>
|
||||||
|
<a href="tel:+79625439343" class="contact-item">
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
|
||||||
|
<span>+7 (962) 543-93-43</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'HomeView',
|
||||||
|
mounted() {
|
||||||
|
this.setupScrollObserver()
|
||||||
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
if (this.observer) {
|
||||||
|
this.observer.disconnect()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setupScrollObserver() {
|
||||||
|
this.observer = new IntersectionObserver(
|
||||||
|
(entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
entry.target.classList.add('visible')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{ threshold: 0.1 }
|
||||||
|
)
|
||||||
|
document.querySelectorAll('.fade-in').forEach((el) => {
|
||||||
|
this.observer.observe(el)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.hero {
|
||||||
|
position: relative;
|
||||||
|
min-height: 90vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-bg {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: var(--gradient-hero);
|
||||||
|
opacity: 0.05;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 60px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 40px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-greeting {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: var(--accent);
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-name {
|
||||||
|
font-size: 3.5rem;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-desc {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.7;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-social {
|
||||||
|
display: flex;
|
||||||
|
gap: 24px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-link {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-link:hover {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-image {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-photo {
|
||||||
|
width: 320px;
|
||||||
|
height: 320px;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 4px solid var(--accent);
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-placeholder {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
opacity: 0.4;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-content {
|
||||||
|
display: grid;
|
||||||
|
gap: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-paragraph {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
line-height: 1.8;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-highlights {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-card {
|
||||||
|
text-align: center;
|
||||||
|
padding: 32px 20px;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
background: var(--card-bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-card:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: var(--skill-bg);
|
||||||
|
color: var(--accent);
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-card h4 {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-card p {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projects-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-name {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-status {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: var(--tag-bg);
|
||||||
|
color: var(--tag-text);
|
||||||
|
font-weight: 600;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-desc {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-tech {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-tag {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: var(--skill-bg);
|
||||||
|
color: var(--accent);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline {
|
||||||
|
position: relative;
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 2px;
|
||||||
|
background: var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 56px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-dot {
|
||||||
|
position: absolute;
|
||||||
|
left: 12px;
|
||||||
|
top: 24px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--accent);
|
||||||
|
border: 4px solid var(--bg);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-period {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--accent);
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-title {
|
||||||
|
font-size: 1.15rem;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-company {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-duties {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-duties li {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 20px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-duties li::before {
|
||||||
|
content: '—';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.education-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 20px;
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edu-card {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edu-year {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--accent);
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edu-card h4 {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edu-card p {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skills-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skill-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skill-name {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skill-level {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skill-bar {
|
||||||
|
height: 8px;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skill-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: var(--gradient-hero);
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: width 1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-content {
|
||||||
|
text-align: center;
|
||||||
|
max-width: 500px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-text {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-links {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 16px 24px;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
background: var(--card-bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 1rem;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item:hover {
|
||||||
|
border-color: var(--accent);
|
||||||
|
color: var(--accent);
|
||||||
|
transform: translateX(4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item svg {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.hero-content {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
text-align: center;
|
||||||
|
gap: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-name {
|
||||||
|
font-size: 2.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-buttons {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-social {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-photo {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-highlights {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.projects-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.education-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skills-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.about-highlights {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-name {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-buttons {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
|
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
host: true,
|
||||||
|
port: 3002
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user