✨ feat(src/stores/auth.store.ts): обновляет логику получения пользователя после входа и регистрации
✨ feat(src/components/layout/TauriTitlebar.vue): изменяет название приложения с "Daiting" на "Dating" ✨ feat(src/components/layout/SideNav.vue): изменяет название приложения с "Daiting" на "Dating" ✨ fix(README.md): исправляет название приложения с "Daiting" на "Dating" ✨ fix(src/api/client.ts): обновляет базовый URL API с 'localhost:3000' на 'localhost:1337' ✨ fix(src/views/auth/LoginView.vue): изменяет название приложения с "Daiting" на "Dating" ✨ fix(src/views/auth/RegisterView.vue): изменяет название приложения с "Daiting" на "Dating" ✨ fix(src-tauri/Cargo.toml): исправляет описание приложения с "Daiting" на "Dating" ✨ fix(src-tauri/tauri.conf.json): изменяет имя продукта с "Daiting" на "Dating" ✨ fix(vite.config.ts): обновляет порт разработки с 1420 на 3000 ✨ fix(index.html): изменяет заголовок страницы с "Daiting" на "Dating" ✨ fix(dating-app-frontend-prompt.md): исправляет название приложения с "Daiting" на "Dating" ✨ fix(PRODUCT.md): изменяет название приложения с "Daiting" на "Dating"
This commit is contained in:
@@ -10,7 +10,7 @@ Young adults (18–35) in Russian-speaking markets looking for genuine human con
|
|||||||
|
|
||||||
## Product Purpose
|
## Product Purpose
|
||||||
|
|
||||||
Daiting is a dating app for meaningful connections. It replaces the swipe-factory aesthetic with an editorial, intentional experience. Success = users move from match to real-world date, and the app gets out of the way once that happens.
|
Dating is a dating app for meaningful connections. It replaces the swipe-factory aesthetic with an editorial, intentional experience. Success = users move from match to real-world date, and the app gets out of the way once that happens.
|
||||||
|
|
||||||
## Brand Personality
|
## Brand Personality
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Daiting — Frontend
|
# Dating — Frontend
|
||||||
|
|
||||||
Vue 3 + Vite + Tauri v2. Работает как PWA в браузере и как нативное десктопное приложение (Windows / macOS / Linux).
|
Vue 3 + Vite + Tauri v2. Работает как PWA в браузере и как нативное десктопное приложение (Windows / macOS / Linux).
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ cd dating-app-frontend
|
|||||||
# Установить зависимости
|
# Установить зависимости
|
||||||
pnpm install
|
pnpm install
|
||||||
|
|
||||||
# Запустить в браузере (порт 1420)
|
# Запустить в браузере (порт 3000) (old 1420)
|
||||||
pnpm dev
|
pnpm dev
|
||||||
|
|
||||||
# Запустить с Tauri (нативное окно)
|
# Запустить с Tauri (нативное окно)
|
||||||
@@ -272,7 +272,7 @@ const feed = await apiClient.api.feedControllerGetFeed({
|
|||||||
## Скрипты
|
## Скрипты
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm dev # Vite dev server, порт 1420
|
pnpm dev # Vite dev server, порт 3000
|
||||||
pnpm build # vue-tsc + vite build → dist/
|
pnpm build # vue-tsc + vite build → dist/
|
||||||
pnpm preview # Превью prod-сборки
|
pnpm preview # Превью prod-сборки
|
||||||
pnpm tauri dev # Tauri dev window (запускает pnpm dev внутри)
|
pnpm tauri dev # Tauri dev window (запускает pnpm dev внутри)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Context & Orientation
|
## Context & Orientation
|
||||||
|
|
||||||
You are building the complete frontend for a dating application called **Daiting**. The backend is already implemented. The generated API client lives at `src/api/api.ts` — use it as the source of truth for all endpoint shapes, DTOs, and types. Do not re-declare types that already exist in the API client; import them.
|
You are building the complete frontend for a dating application called **Dating**. The backend is already implemented. The generated API client lives at `src/api/api.ts` — use it as the source of truth for all endpoint shapes, DTOs, and types. Do not re-declare types that already exist in the API client; import them.
|
||||||
|
|
||||||
Project root: `C:\MyApps\dating-app-frontend`
|
Project root: `C:\MyApps\dating-app-frontend`
|
||||||
Package manager: **pnpm**
|
Package manager: **pnpm**
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Daiting</title>
|
<title>Dating</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link
|
<link
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "dating-app"
|
name = "dating-app"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Daiting — dating app frontend"
|
description = "Dating — dating app frontend"
|
||||||
authors = []
|
authors = []
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Daiting",
|
"productName": "Dating",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"identifier": "com.daiting.app",
|
"identifier": "com.dating.app",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "pnpm dev",
|
"beforeDevCommand": "pnpm dev",
|
||||||
"devUrl": "http://localhost:1420",
|
"devUrl": "http://localhost:3000",
|
||||||
"beforeBuildCommand": "pnpm build",
|
"beforeBuildCommand": "pnpm build",
|
||||||
"frontendDist": "../dist"
|
"frontendDist": "../dist"
|
||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
"title": "Daiting",
|
"title": "dating",
|
||||||
"width": 1280,
|
"width": 1280,
|
||||||
"height": 860,
|
"height": 860,
|
||||||
"minWidth": 375,
|
"minWidth": 375,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import axios from 'axios';
|
|||||||
import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios';
|
import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios';
|
||||||
import { Api, HttpClient } from './api';
|
import { Api, HttpClient } from './api';
|
||||||
|
|
||||||
const BASE_URL = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:3000';
|
const BASE_URL = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:1337';
|
||||||
|
|
||||||
// ─── Raw axios instance with interceptors ────────────────────────────────────
|
// ─── Raw axios instance with interceptors ────────────────────────────────────
|
||||||
|
|
||||||
@@ -36,7 +36,12 @@ function _processQueue(error: unknown, token: string | null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
axiosInstance.interceptors.response.use(
|
axiosInstance.interceptors.response.use(
|
||||||
(response) => response,
|
(response) => {
|
||||||
|
if (response.data !== null && typeof response.data === 'object' && 'data' in response.data) {
|
||||||
|
response.data = response.data.data;
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
},
|
||||||
async (error) => {
|
async (error) => {
|
||||||
const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };
|
const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };
|
||||||
|
|
||||||
@@ -62,11 +67,11 @@ axiosInstance.interceptors.response.use(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await axios.post<{ accessToken: string; refreshToken: string }>(
|
const res = await axios.post<{ data: { accessToken: string; refreshToken: string } }>(
|
||||||
`${BASE_URL}/api/v1/auth/refresh`,
|
`${BASE_URL}/api/v1/auth/refresh`,
|
||||||
{ refreshToken },
|
{ refreshToken },
|
||||||
);
|
);
|
||||||
const { accessToken, refreshToken: newRefresh } = res.data;
|
const { accessToken, refreshToken: newRefresh } = res.data.data;
|
||||||
_setAccessToken(accessToken);
|
_setAccessToken(accessToken);
|
||||||
localStorage.setItem('refreshToken', newRefresh);
|
localStorage.setItem('refreshToken', newRefresh);
|
||||||
_processQueue(null, accessToken);
|
_processQueue(null, accessToken);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ function toggle() {
|
|||||||
<div class="sidenav__header">
|
<div class="sidenav__header">
|
||||||
<span class="sidenav__logo">D</span>
|
<span class="sidenav__logo">D</span>
|
||||||
<Transition name="fade">
|
<Transition name="fade">
|
||||||
<span v-if="uiStore.sidebarExpanded" class="sidenav__brand">Daiting</span>
|
<span v-if="uiStore.sidebarExpanded" class="sidenav__brand">Dating</span>
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ async function closeWindow() {
|
|||||||
class="titlebar"
|
class="titlebar"
|
||||||
data-tauri-drag-region
|
data-tauri-drag-region
|
||||||
>
|
>
|
||||||
<span class="titlebar__brand">Daiting</span>
|
<span class="titlebar__brand">Dating</span>
|
||||||
<div class="titlebar__controls">
|
<div class="titlebar__controls">
|
||||||
<button class="titlebar__btn titlebar__btn--minimize" @click="minimize" aria-label="Свернуть" />
|
<button class="titlebar__btn titlebar__btn--minimize" @click="minimize" aria-label="Свернуть" />
|
||||||
<button class="titlebar__btn titlebar__btn--maximize" @click="maximize" aria-label="Развернуть" />
|
<button class="titlebar__btn titlebar__btn--maximize" @click="maximize" aria-label="Развернуть" />
|
||||||
|
|||||||
@@ -43,25 +43,20 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
const res = await apiClient.api.authControllerLogin(dto) as unknown as {
|
const res = await apiClient.api.authControllerLogin(dto) as unknown as {
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
user: AuthUser;
|
|
||||||
};
|
};
|
||||||
_setAccessToken(res.accessToken);
|
_setAccessToken(res.accessToken);
|
||||||
localStorage.setItem('refreshToken', res.refreshToken);
|
localStorage.setItem('refreshToken', res.refreshToken);
|
||||||
user.value = res.user;
|
await fetchMe();
|
||||||
if (res.user.profiles.length > 0) {
|
|
||||||
activeProfileId.value = res.user.profiles[0].id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function register(dto: RegisterDto) {
|
async function register(dto: RegisterDto) {
|
||||||
const res = await apiClient.api.authControllerRegister(dto) as unknown as {
|
const res = await apiClient.api.authControllerRegister(dto) as unknown as {
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
user: AuthUser;
|
|
||||||
};
|
};
|
||||||
_setAccessToken(res.accessToken);
|
_setAccessToken(res.accessToken);
|
||||||
localStorage.setItem('refreshToken', res.refreshToken);
|
localStorage.setItem('refreshToken', res.refreshToken);
|
||||||
user.value = res.user;
|
await fetchMe();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function logout() {
|
async function logout() {
|
||||||
@@ -78,7 +73,7 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
async function fetchMe() {
|
async function fetchMe() {
|
||||||
const res = await apiClient.api.usersControllerGetMe() as unknown as AuthUser;
|
const res = await apiClient.api.usersControllerGetMe() as unknown as AuthUser;
|
||||||
user.value = res;
|
user.value = res;
|
||||||
if (res.profiles.length > 0 && !activeProfileId.value) {
|
if (res.profiles?.length > 0 && !activeProfileId.value) {
|
||||||
activeProfileId.value = res.profiles[0].id;
|
activeProfileId.value = res.profiles[0].id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ async function submit() {
|
|||||||
<div class="auth-page__grain" aria-hidden="true" />
|
<div class="auth-page__grain" aria-hidden="true" />
|
||||||
|
|
||||||
<div class="auth-card">
|
<div class="auth-card">
|
||||||
<div class="auth-card__wordmark">Daiting</div>
|
<div class="auth-card__wordmark">Dating</div>
|
||||||
<h1 class="auth-card__heading">С возвращением</h1>
|
<h1 class="auth-card__heading">С возвращением</h1>
|
||||||
<p class="auth-card__sub">Войдите, чтобы продолжить</p>
|
<p class="auth-card__sub">Войдите, чтобы продолжить</p>
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ async function submit() {
|
|||||||
<div class="auth-page__grain" aria-hidden="true" />
|
<div class="auth-page__grain" aria-hidden="true" />
|
||||||
|
|
||||||
<div class="auth-card">
|
<div class="auth-card">
|
||||||
<div class="auth-card__wordmark">Daiting</div>
|
<div class="auth-card__wordmark">Dating</div>
|
||||||
<h1 class="auth-card__heading">Создать аккаунт</h1>
|
<h1 class="auth-card__heading">Создать аккаунт</h1>
|
||||||
<p class="auth-card__sub">Начните своё путешествие</p>
|
<p class="auth-card__sub">Начните своё путешествие</p>
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export default defineConfig(async () => ({
|
|||||||
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
||||||
clearScreen: false,
|
clearScreen: false,
|
||||||
server: {
|
server: {
|
||||||
port: 1420,
|
port: 3000,
|
||||||
strictPort: true,
|
strictPort: true,
|
||||||
host: host || false,
|
host: host || false,
|
||||||
hmr: host
|
hmr: host
|
||||||
|
|||||||
Reference in New Issue
Block a user