This commit is contained in:
Oscar
2026-06-24 17:43:45 +03:00
parent ed51218249
commit ffbfd772cb
28 changed files with 188 additions and 300 deletions

View File

@@ -1,13 +1,13 @@
---
name: project-daiting
description: "Daiting dating app frontend — Vue 3, Vite, Tauri v2, pnpm. Full scaffold built, actively iterated."
description: "JustUs dating app frontend — Vue 3, Vite, Tauri v2, pnpm. Full scaffold built, actively iterated."
metadata:
node_type: memory
type: project
originSessionId: 427527bf-bce1-4b1e-9bf1-b5f08ff29055
---
Vue 3 (Composition API + `<script setup>`) + Vite 6 + Tauri v2 + pnpm dating app called **Daiting**.
Vue 3 (Composition API + `<script setup>`) + Vite 6 + Tauri v2 + pnpm dating app called **JustUs**.
**Why:** User provided a comprehensive master prompt specifying full stack, aesthetic direction, and all features.

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dating</title>
<title>JustUs</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link

View File

@@ -6,7 +6,7 @@ const __dirname = fileURLToPath(new URL('.', import.meta.url))
const iconsDir = join(__dirname, '../src/assets/icons')
const svgFiles = readdirSync(iconsDir)
.filter(f => f.endsWith('.svg'))
.filter(f => f.endsWith('.svg') && f !== 'sprite.svg')
.sort()
if (!svgFiles.length) {

View File

@@ -1,12 +1,12 @@
[package]
name = "dating-app"
name = "justus-app"
version = "0.1.0"
description = "Dating — dating app frontend"
description = "JustUs — dating app frontend"
authors = []
edition = "2021"
[lib]
name = "dating_app_lib"
name = "justus_app_lib"
crate-type = [
"staticlib",
"cdylib",

View File

@@ -1,8 +1,8 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Dating",
"productName": "JustUs",
"version": "0.1.0",
"identifier": "com.dating.app",
"identifier": "com.justus.app",
"build": {
"beforeDevCommand": "pnpm dev",
"devUrl": "http://localhost:3000",
@@ -12,7 +12,7 @@
"app": {
"windows": [
{
"title": "dating",
"title": "JustUs",
"width": 1280,
"height": 860,
"minWidth": 375,

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M4 6h16M7 12h10M10 18h4"/>
</svg>

After

Width:  |  Height:  |  Size: 159 B

View File

@@ -6,6 +6,7 @@ export type IconName =
| 'chevron-left'
| 'chevron-right'
| 'edit'
| 'filter'
| 'flag'
| 'grid'
| 'heart'
@@ -15,6 +16,7 @@ export type IconName =
| 'plus'
| 'search'
| 'send'
| 'sprite'
| 'trash'
| 'view-list'
| 'view-stack'
| 'x'

View File

@@ -19,6 +19,9 @@
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
</symbol>
<symbol id="icon-filter" viewBox="0 0 24 24">
<path d="M4 6h16M7 12h10M10 18h4"/>
</symbol>
<symbol id="icon-flag" viewBox="0 0 24 24">
<path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1zM4 22v-7"/>
</symbol>
@@ -53,200 +56,18 @@
<path d="M22 2L11 13"/>
<path d="M22 2L15 22l-4-9-9-4 20-7z"/>
</symbol>
<symbol id="icon-sprite" viewBox="0 0 24 24">
<symbol id="icon-calendar" viewBox="0 0 24 24">
<path d="M8 2v4M16 2v4M3 10h18M3 6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
</symbol>
<symbol id="icon-chat" viewBox="0 0 24 24">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
</symbol>
<symbol id="icon-check" viewBox="0 0 24 24">
<path d="M20 6L9 17l-5-5"/>
</symbol>
<symbol id="icon-chevron-left" viewBox="0 0 24 24">
<path d="M15 18l-6-6 6-6"/>
</symbol>
<symbol id="icon-chevron-right" viewBox="0 0 24 24">
<path d="M9 18l6-6-6-6"/>
</symbol>
<symbol id="icon-edit" viewBox="0 0 24 24">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
</symbol>
<symbol id="icon-flag" viewBox="0 0 24 24">
<path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1zM4 22v-7"/>
</symbol>
<symbol id="icon-grid" viewBox="0 0 24 24">
<path d="M3 3h7v7H3zm11 0h7v7h-7zM3 14h7v7H3zm11 0h7v7h-7z"/>
</symbol>
<symbol id="icon-heart" viewBox="0 0 24 24">
<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"/>
</symbol>
<symbol id="icon-image" viewBox="0 0 24 24">
<rect x="3" y="3" width="18" height="18" rx="2"/>
<circle cx="8.5" cy="8.5" r="1.5"/>
<path d="M21 15l-5-5L5 21"/>
</symbol>
<symbol id="icon-mic" viewBox="0 0 24 24">
<rect x="9" y="1" width="6" height="11" rx="3"/>
<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
<path d="M12 19v4M8 23h8"/>
</symbol>
<symbol id="icon-person" viewBox="0 0 24 24">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
<circle cx="12" cy="7" r="4"/>
</symbol>
<symbol id="icon-plus" viewBox="0 0 24 24">
<path d="M12 5v14M5 12h14"/>
</symbol>
<symbol id="icon-search" viewBox="0 0 24 24">
<circle cx="11" cy="11" r="7"/>
<path d="M21 21l-4.35-4.35"/>
</symbol>
<symbol id="icon-send" viewBox="0 0 24 24">
<path d="M22 2L11 13"/>
<path d="M22 2L15 22l-4-9-9-4 20-7z"/>
</symbol>
<symbol id="icon-sprite" viewBox="0 0 24 24">
<symbol id="icon-calendar" viewBox="0 0 24 24">
<path d="M8 2v4M16 2v4M3 10h18M3 6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
</symbol>
<symbol id="icon-chat" viewBox="0 0 24 24">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
</symbol>
<symbol id="icon-check" viewBox="0 0 24 24">
<path d="M20 6L9 17l-5-5"/>
</symbol>
<symbol id="icon-chevron-left" viewBox="0 0 24 24">
<path d="M15 18l-6-6 6-6"/>
</symbol>
<symbol id="icon-chevron-right" viewBox="0 0 24 24">
<path d="M9 18l6-6-6-6"/>
</symbol>
<symbol id="icon-edit" viewBox="0 0 24 24">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
</symbol>
<symbol id="icon-flag" viewBox="0 0 24 24">
<path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1zM4 22v-7"/>
</symbol>
<symbol id="icon-grid" viewBox="0 0 24 24">
<path d="M3 3h7v7H3zm11 0h7v7h-7zM3 14h7v7H3zm11 0h7v7h-7z"/>
</symbol>
<symbol id="icon-heart" viewBox="0 0 24 24">
<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"/>
</symbol>
<symbol id="icon-image" viewBox="0 0 24 24">
<rect x="3" y="3" width="18" height="18" rx="2"/>
<circle cx="8.5" cy="8.5" r="1.5"/>
<path d="M21 15l-5-5L5 21"/>
</symbol>
<symbol id="icon-mic" viewBox="0 0 24 24">
<rect x="9" y="1" width="6" height="11" rx="3"/>
<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
<path d="M12 19v4M8 23h8"/>
</symbol>
<symbol id="icon-person" viewBox="0 0 24 24">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
<circle cx="12" cy="7" r="4"/>
</symbol>
<symbol id="icon-plus" viewBox="0 0 24 24">
<path d="M12 5v14M5 12h14"/>
</symbol>
<symbol id="icon-search" viewBox="0 0 24 24">
<circle cx="11" cy="11" r="7"/>
<path d="M21 21l-4.35-4.35"/>
</symbol>
<symbol id="icon-send" viewBox="0 0 24 24">
<path d="M22 2L11 13"/>
<path d="M22 2L15 22l-4-9-9-4 20-7z"/>
</symbol>
<symbol id="icon-sprite" viewBox="0 0 24 24">
<symbol id="icon-calendar" viewBox="0 0 24 24">
<path d="M8 2v4M16 2v4M3 10h18M3 6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
</symbol>
<symbol id="icon-chat" viewBox="0 0 24 24">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
</symbol>
<symbol id="icon-check" viewBox="0 0 24 24">
<path d="M20 6L9 17l-5-5"/>
</symbol>
<symbol id="icon-chevron-left" viewBox="0 0 24 24">
<path d="M15 18l-6-6 6-6"/>
</symbol>
<symbol id="icon-chevron-right" viewBox="0 0 24 24">
<path d="M9 18l6-6-6-6"/>
</symbol>
<symbol id="icon-edit" viewBox="0 0 24 24">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
</symbol>
<symbol id="icon-flag" viewBox="0 0 24 24">
<path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1zM4 22v-7"/>
</symbol>
<symbol id="icon-grid" viewBox="0 0 24 24">
<path d="M3 3h7v7H3zm11 0h7v7h-7zM3 14h7v7H3zm11 0h7v7h-7z"/>
</symbol>
<symbol id="icon-heart" viewBox="0 0 24 24">
<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"/>
</symbol>
<symbol id="icon-image" viewBox="0 0 24 24">
<rect x="3" y="3" width="18" height="18" rx="2"/>
<circle cx="8.5" cy="8.5" r="1.5"/>
<path d="M21 15l-5-5L5 21"/>
</symbol>
<symbol id="icon-mic" viewBox="0 0 24 24">
<rect x="9" y="1" width="6" height="11" rx="3"/>
<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
<path d="M12 19v4M8 23h8"/>
</symbol>
<symbol id="icon-person" viewBox="0 0 24 24">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
<circle cx="12" cy="7" r="4"/>
</symbol>
<symbol id="icon-plus" viewBox="0 0 24 24">
<path d="M12 5v14M5 12h14"/>
</symbol>
<symbol id="icon-search" viewBox="0 0 24 24">
<circle cx="11" cy="11" r="7"/>
<path d="M21 21l-4.35-4.35"/>
</symbol>
<symbol id="icon-send" viewBox="0 0 24 24">
<path d="M22 2L11 13"/>
<path d="M22 2L15 22l-4-9-9-4 20-7z"/>
</symbol>
<symbol id="icon-trash" viewBox="0 0 24 24">
<path d="M3 6h18"/>
<path d="M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/>
<path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>
</symbol>
<symbol id="icon-x" viewBox="0 0 24 24">
<path d="M18 6L6 18M6 6l12 12"/>
</symbol>
</symbol>
<symbol id="icon-trash" viewBox="0 0 24 24">
<path d="M3 6h18"/>
<path d="M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/>
<path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>
</symbol>
<symbol id="icon-x" viewBox="0 0 24 24">
<path d="M18 6L6 18M6 6l12 12"/>
</symbol>
</symbol>
<symbol id="icon-trash" viewBox="0 0 24 24">
<path d="M3 6h18"/>
<path d="M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/>
<path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>
</symbol>
<symbol id="icon-x" viewBox="0 0 24 24">
<path d="M18 6L6 18M6 6l12 12"/>
</symbol>
</symbol>
<symbol id="icon-trash" viewBox="0 0 24 24">
<path d="M3 6h18"/>
<path d="M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/>
<path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>
</symbol>
<symbol id="icon-view-list" viewBox="0 0 24 24">
<path d="M3 6h18M3 12h18M3 18h18"/>
</symbol>
<symbol id="icon-view-stack" viewBox="0 0 24 24">
<rect x="2" y="2" width="20" height="20" rx="3"/>
<rect x="6" y="6" width="12" height="12" rx="1" stroke-dasharray="2.5 1.5"/>
</symbol>
<symbol id="icon-x" viewBox="0 0 24 24">
<path d="M18 6L6 18M6 6l12 12"/>
</symbol>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M3 6h18M3 12h18M3 18h18"/>
</svg>

After

Width:  |  Height:  |  Size: 159 B

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="2" y="2" width="20" height="20" rx="3"/>
<rect x="6" y="6" width="12" height="12" rx="1" stroke-dasharray="2.5 1.5"/>
</svg>

After

Width:  |  Height:  |  Size: 252 B

View File

@@ -0,0 +1,5 @@
<svg width="120" height="28" viewBox="0 0 120 28" xmlns="http://www.w3.org/2000/svg">
<circle cx="14" cy="14" r="12" fill="#7F77DD"/>
<circle cx="23" cy="14" r="12" fill="#ED93B1" fill-opacity="0.85"/>
<text x="40" y="19" font-family="system-ui, -apple-system, sans-serif" font-size="15" font-weight="500" fill="#ffffff" letter-spacing="-0.3">Just<tspan fill="#AFA9EC">Us</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 400 B

View File

@@ -0,0 +1,5 @@
<svg width="120" height="28" viewBox="0 0 120 28" xmlns="http://www.w3.org/2000/svg">
<circle cx="14" cy="14" r="12" fill="#534AB7"/>
<circle cx="23" cy="14" r="12" fill="#D4537E" fill-opacity="0.85"/>
<text x="40" y="19" font-family="system-ui, -apple-system, sans-serif" font-size="15" font-weight="500" fill="#1a1a1a" letter-spacing="-0.3">Just<tspan fill="#534AB7">Us</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 400 B

View File

@@ -0,0 +1,5 @@
<svg width="180" height="40" viewBox="0 0 180 40" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="18" fill="#7F77DD"/>
<circle cx="34" cy="20" r="18" fill="#ED93B1" fill-opacity="0.85"/>
<text x="62" y="26" font-family="system-ui, -apple-system, sans-serif" font-size="22" font-weight="500" fill="#ffffff" letter-spacing="-0.5">Just<tspan fill="#AFA9EC">Us</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 400 B

View File

@@ -0,0 +1,5 @@
<svg width="180" height="40" viewBox="0 0 180 40" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="18" fill="#534AB7"/>
<circle cx="34" cy="20" r="18" fill="#D4537E" fill-opacity="0.85"/>
<text x="62" y="26" font-family="system-ui, -apple-system, sans-serif" font-size="22" font-weight="500" fill="#1a1a1a" letter-spacing="-0.5">Just<tspan fill="#534AB7">Us</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 400 B

View File

@@ -0,0 +1,5 @@
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<rect width="32" height="32" rx="8" fill="#534AB7"/>
<circle cx="13" cy="16" r="7" fill="#ffffff" fill-opacity="0.22"/>
<circle cx="19" cy="16" r="7" fill="#ED93B1" fill-opacity="0.8"/>
</svg>

After

Width:  |  Height:  |  Size: 283 B

View File

@@ -0,0 +1,6 @@
<svg width="48" height="48" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
<rect width="48" height="48" rx="12" fill="#534AB7"/>
<circle cx="20" cy="24" r="10" fill="#ffffff" fill-opacity="0.22"/>
<circle cx="29" cy="24" r="10" fill="#ED93B1" fill-opacity="0.8"/>
<text x="24" y="28" font-family="system-ui, -apple-system, sans-serif" font-size="11" font-weight="500" fill="#ffffff" text-anchor="middle">JU</text>
</svg>

After

Width:  |  Height:  |  Size: 438 B

View File

@@ -0,0 +1,6 @@
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<rect width="64" height="64" rx="16" fill="#534AB7"/>
<circle cx="26" cy="32" r="14" fill="#ffffff" fill-opacity="0.25"/>
<circle cx="38" cy="32" r="14" fill="#ED93B1" fill-opacity="0.8"/>
<text x="32" y="37" font-family="system-ui, -apple-system, sans-serif" font-size="14" font-weight="500" fill="#ffffff" text-anchor="middle">JU</text>
</svg>

After

Width:  |  Height:  |  Size: 438 B

View File

@@ -0,0 +1,5 @@
<svg width="96" height="96" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg">
<rect width="96" height="96" rx="48" fill="#534AB7"/>
<circle cx="38" cy="48" r="22" fill="#ffffff" fill-opacity="0.2"/>
<circle cx="58" cy="48" r="22" fill="#D4537E" fill-opacity="0.85"/>
</svg>

After

Width:  |  Height:  |  Size: 286 B

View File

@@ -0,0 +1,5 @@
<svg width="96" height="96" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg">
<rect width="96" height="96" rx="24" fill="#534AB7"/>
<circle cx="38" cy="48" r="22" fill="#ffffff" fill-opacity="0.2"/>
<circle cx="58" cy="48" r="22" fill="#D4537E" fill-opacity="0.85"/>
</svg>

After

Width:  |  Height:  |  Size: 286 B

View File

@@ -0,0 +1,5 @@
<svg width="180" height="40" viewBox="0 0 180 40" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="18" fill="#ffffff" fill-opacity="0.15"/>
<circle cx="34" cy="20" r="18" fill="#ffffff" fill-opacity="0.35"/>
<text x="62" y="26" font-family="system-ui, -apple-system, sans-serif" font-size="22" font-weight="500" fill="#ffffff" letter-spacing="-0.5">JustUs</text>
</svg>

After

Width:  |  Height:  |  Size: 390 B

View File

@@ -18,16 +18,16 @@
</template>
<script setup lang="ts">
import type { IconName } from '@/assets/icons/icon-names'
import { useRoute } from 'vue-router'
import AppIcon from '@/components/common/AppIcon.vue'
import type { IconName } from '@/assets/icons/icon-names'
const route = useRoute()
const navItems: { path: string, label: string, icon: IconName }[] = [
{ path: '/feed', label: 'Лента', icon: 'grid' },
{ path: '/matches', label: 'Совпадения', icon: 'heart' },
{ path: '/chats', label: 'Чаты', icon: 'chat' },
{ path: '/chats', label: 'Чат', icon: 'chat' },
{ path: '/dates', label: 'Встречи', icon: 'calendar' },
{ path: '/profile/me', label: 'Профиль', icon: 'person' },
]

View File

@@ -5,10 +5,11 @@
aria-label="Навигация"
>
<div class="sidenav__header">
<span class="sidenav__logo">D</span>
<Transition name="fade">
<span v-if="uiStore.sidebarExpanded" class="sidenav__brand">Dating</span>
</Transition>
<img src="@/assets/logo/justus-compact-dark.svg" alt="">
<!-- <span class="sidenav__logo">D</span> -->
<!-- <Transition name="fade"> -->
<!-- <span v-if="uiStore.sidebarExpanded" class="sidenav__brand">JustUs</span> -->
<!-- </Transition> -->
</div>
<ul class="sidenav__list" role="list">
@@ -31,15 +32,15 @@
</ul>
<div class="sidenav__footer">
<button
class="sidenav__toggle"
:aria-label="uiStore.sidebarExpanded ? 'Свернуть меню' : 'Развернуть меню'"
@click="toggle"
>
<span class="sidenav__icon">
<AppIcon :name="uiStore.sidebarExpanded ? 'chevron-left' : 'chevron-right'" :size="20" />
</span>
</button>
<!-- <button -->
<!-- class="sidenav__toggle" -->
<!-- :aria-label="uiStore.sidebarExpanded ? 'Свернуть меню' : 'Развернуть меню'" -->
<!-- @click="toggle" -->
<!-- > -->
<!-- <span class="sidenav__icon"> -->
<!-- <AppIcon :name="uiStore.sidebarExpanded ? 'chevron-left' : 'chevron-right'" :size="20" /> -->
<!-- </span> -->
<!-- </button> -->
</div>
</nav>
</template>
@@ -67,7 +68,7 @@ interface NavItem {
const navItems: NavItem[] = [
{ name: 'feed', path: '/feed', label: 'Лента', icon: 'grid' },
{ name: 'matches', path: '/matches', label: 'Совпадения', icon: 'heart' },
{ name: 'chats', path: '/chats', label: 'Чаты', icon: 'chat' },
{ name: 'chats', path: '/chats', label: 'Чат', icon: 'chat' },
// { name: 'dates', path: '/dates', label: 'Встречи', icon: 'calendar' },
{ name: 'profile', path: '/profile/me', label: 'Профиль', icon: 'person' },
]

View File

@@ -1,6 +1,6 @@
import type { MaybeRefOrGetter } from 'vue'
import { computed, toValue } from 'vue'
import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'
import { computed, toValue } from 'vue'
import { apiClient } from '@/api/client'
import { queryKeys } from './keys'

View File

@@ -1,25 +1,33 @@
// Design tokens — do not use directly in components; use CSS custom properties
:root {
// Surfaces
--color-base: #0d0d0d;
--color-surface: #161614;
--color-surface-2: #1e1e1b;
--color-surface-3: #242420;
--color-base: #0a0a0f;
--color-surface: #11111a;
--color-surface-2: #191926;
--color-surface-3: #1f1f30;
// Text
--color-cream: #f0ebe0;
--color-muted: #6b6860;
--color-dim: #3a3935;
--color-muted: #6b6878;
--color-dim: #35354a;
// Brand signal
--color-signal: #c45c3a;
--color-signal-dim: #7a3822;
--color-signal-bg: rgba(196, 92, 58, 0.12);
// Brand — primary (purple)
--color-signal: #7f77dd;
--color-signal-dim: #4e47a8;
--color-signal-bg: rgba(127, 119, 221, 0.12);
// Brand — accent (pink)
--color-accent: #ed93b1;
--color-accent-dim: #a85478;
--color-accent-bg: rgba(237, 147, 177, 0.12);
// Brand — secondary (light purple)
--color-secondary: #afa9ec;
// Utility
--color-border: rgba(240, 235, 224, 0.08);
--color-border-strong: rgba(240, 235, 224, 0.16);
--color-overlay: rgba(13, 13, 13, 0.72);
--color-border: rgba(175, 169, 236, 0.1);
--color-border-strong: rgba(175, 169, 236, 0.2);
--color-overlay: rgba(10, 10, 15, 0.76);
// Typography
--font-display: 'Instrument Serif', Georgia, serif;
@@ -34,9 +42,9 @@
--radius-full: 9999px;
// Shadows
--shadow-card: 0 2px 24px rgba(0, 0, 0, 0.6);
--shadow-modal: 0 8px 64px rgba(0, 0, 0, 0.8);
--shadow-signal: 0 0 20px rgba(196, 92, 58, 0.3);
--shadow-card: 0 2px 24px rgba(0, 0, 0, 0.7);
--shadow-modal: 0 8px 64px rgba(0, 0, 0, 0.85);
--shadow-signal: 0 0 24px rgba(127, 119, 221, 0.35);
// Transitions
--transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);

View File

@@ -4,7 +4,7 @@
<div class="auth-card">
<div class="auth-card__wordmark">
Dating
JustUs
</div>
<h1 class="auth-card__heading">
С возвращением

View File

@@ -4,7 +4,7 @@
<div class="auth-card">
<div class="auth-card__wordmark">
Dating
JustUs
</div>
<h1 class="auth-card__heading">
Создать аккаунт

View File

@@ -2,7 +2,7 @@
<div class="chats-list">
<header class="chats-list__header">
<h1 class="chats-list__title">
Чаты
Чат
</h1>
</header>
@@ -29,51 +29,51 @@
История
</li>
<li>
<RouterLink
:to="`/chats/${chat.id}`"
class="chat-item"
:class="{ 'chat-item--inactive': chat.status === 'closed', 'chat-item--active': chat.status === 'active' }"
>
<div class="chat-item__avatar-wrap">
<img
v-if="chat.partner?.avatarUrl"
:src="chat.partner.avatarUrl"
:alt="chat.partner?.name"
class="chat-item__avatar"
>
<div v-else class="chat-item__avatar chat-item__avatar--placeholder">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" width="24" height="24" opacity="0.3">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z" />
</svg>
<RouterLink
:to="`/chats/${chat.id}`"
class="chat-item"
:class="{ 'chat-item--inactive': chat.status === 'closed', 'chat-item--active': chat.status === 'active' }"
>
<div class="chat-item__avatar-wrap">
<img
v-if="chat.partner?.avatarUrl"
:src="chat.partner.avatarUrl"
:alt="chat.partner?.name"
class="chat-item__avatar"
>
<div v-else class="chat-item__avatar chat-item__avatar--placeholder">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" width="24" height="24" opacity="0.3">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z" />
</svg>
</div>
<!-- Lock icon for inactive chats -->
<div v-if="chat.status === 'closed'" class="chat-item__lock" aria-label="Чат неактивен">
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="12" height="12">
<rect x="3" y="7" width="10" height="8" rx="1" />
<path d="M5 7V5a3 3 0 0 1 6 0v2" />
</svg>
</div>
</div>
<!-- Lock icon for inactive chats -->
<div v-if="chat.status === 'closed'" class="chat-item__lock" aria-label="Чат неактивен">
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="12" height="12">
<rect x="3" y="7" width="10" height="8" rx="1" />
<path d="M5 7V5a3 3 0 0 1 6 0v2" />
</svg>
</div>
</div>
<div class="chat-item__content">
<div class="chat-item__top">
<span class="chat-item__name">{{ chat.partner?.name }}</span>
<span v-if="chat.lastMessage" class="chat-item__time meta">
{{ formatTime(chat.lastMessage.createdAt) }}
</span>
<div class="chat-item__content">
<div class="chat-item__top">
<span class="chat-item__name">{{ chat.partner?.name }}</span>
<span v-if="chat.lastMessage" class="chat-item__time meta">
{{ formatTime(chat.lastMessage.createdAt) }}
</span>
</div>
<p v-if="chat.lastMessage" class="chat-item__preview">
{{ chat.lastMessage.text || (chat.lastMessage.mediaType === 'photo' ? '📷 Фото' : chat.lastMessage.mediaType === 'voice' ? '🎤 Голосовое' : '🎬 Видео') }}
</p>
<p v-else class="chat-item__preview chat-item__preview--empty">
Начните переписку
</p>
</div>
<p v-if="chat.lastMessage" class="chat-item__preview">
{{ chat.lastMessage.text || (chat.lastMessage.mediaType === 'photo' ? '📷 Фото' : chat.lastMessage.mediaType === 'voice' ? '🎤 Голосовое' : '🎬 Видео') }}
</p>
<p v-else class="chat-item__preview chat-item__preview--empty">
Начните переписку
</p>
</div>
<div v-if="(chat.unreadCount ?? 0) > 0" class="chat-item__badge">
{{ chat.unreadCount }}
</div>
</RouterLink>
<div v-if="(chat.unreadCount ?? 0) > 0" class="chat-item__badge">
{{ chat.unreadCount }}
</div>
</RouterLink>
</li>
</template>
</ul>
@@ -95,8 +95,10 @@ const { query: { data: rawChats, isLoading: loading } } = useChatsQuery(profileI
const chats = computed(() => {
const list = rawChats.value ?? []
return [...list].sort((a, b) => {
if (a.status === 'active' && b.status !== 'active') return -1
if (a.status !== 'active' && b.status === 'active') return 1
if (a.status === 'active' && b.status !== 'active')
return -1
if (a.status !== 'active' && b.status === 'active')
return 1
return 0
})
})

View File

@@ -14,10 +14,7 @@
aria-label="Карточки"
@click="viewMode = 'stack'"
>
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" width="16" height="16">
<rect x="2" y="2" width="16" height="16" rx="2" />
<rect x="5" y="5" width="10" height="10" rx="1" stroke-dasharray="2 1" />
</svg>
<AppIcon name="view-stack" :size="16" />
</button>
<button
class="feed-header__toggle-btn"
@@ -25,16 +22,12 @@
aria-label="Лента"
@click="viewMode = 'scroll'"
>
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" width="16" height="16">
<path d="M2 5h16M2 10h16M2 15h16" />
</svg>
<AppIcon name="view-list" :size="16" />
</button>
</div>
<AppButton variant="secondary" size="sm" @click="filtersOpen = true">
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" width="14" height="14">
<path d="M3 5h14M6 10h8M9 15h2" />
</svg>
<AppIcon name="filter" :size="14" />
Фильтры
</AppButton>
</div>
@@ -45,9 +38,7 @@
<div v-if="activeMatchChatId" class="feed-locked" role="alertdialog" aria-modal="true">
<div class="feed-locked__inner">
<div class="feed-locked__icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" width="40" height="40">
<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>
<AppIcon name="heart" :size="40" />
</div>
<h2 class="feed-locked__title">
У вас активный матч
@@ -95,9 +86,7 @@
class="feed-grid__img"
>
<div v-else class="feed-grid__no-img">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" width="48" height="48" opacity="0.25">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z" />
</svg>
<AppIcon name="person" :size="48" class="feed-grid__no-img-icon" />
</div>
<div class="feed-grid__overlay">
<span class="feed-grid__name">{{ profile.name }}</span>
@@ -108,9 +97,7 @@
aria-label="Лайк"
@click.prevent.stop="handleScrollLike(profile.id)"
>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" width="18" height="18">
<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>
<AppIcon name="heart" :size="18" />
</button>
</RouterLink>
</article>
@@ -128,11 +115,12 @@
<script setup lang="ts">
import { computed, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { apiClient } from '@/api/client'
import AppButton from '@/components/common/AppButton.vue'
import AppIcon from '@/components/common/AppIcon.vue'
import EmptyState from '@/components/common/EmptyState.vue'
import FeedCardStack from '@/components/feed/FeedCardStack.vue'
import FeedFilters from '@/components/feed/FeedFilters.vue'
import { apiClient } from '@/api/client'
import { useAuth } from '@/composables/useAuth'
import { useFeed } from '@/composables/useFeed'
import { useUi } from '@/composables/useUi'
@@ -359,6 +347,10 @@ function goToChat() {
align-items: center;
justify-content: center;
background: var(--color-surface-3);
&-icon {
opacity: 0.25;
}
}
&__overlay {
@@ -408,7 +400,7 @@ function goToChat() {
opacity: 1;
background: var(--color-signal);
svg {
:deep(svg) {
fill: white;
stroke: white;
}