This commit is contained in:
Dmitry 2025-12-03 04:32:20 +03:00
parent bfa3d44146
commit 1ed7334995
6 changed files with 1324 additions and 18 deletions

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,8 @@
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
"preview": "vite preview",
"test": "vitest"
},
"dependencies": {
"@hookform/resolvers": "^5.2.2",
@ -39,6 +40,8 @@
},
"devDependencies": {
"@eslint/js": "^9.39.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0",
"@types/node": "^24.10.1",
"@types/react": "^19.2.5",
"@types/react-dom": "^19.2.3",
@ -47,8 +50,10 @@
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.24",
"globals": "^16.5.0",
"jsdom": "^27.0.1",
"typescript": "~5.9.3",
"typescript-eslint": "^8.46.4",
"vite": "^7.2.4"
"vite": "^7.2.4",
"vitest": "^3.2.4"
}
}

View file

@ -1,16 +1,16 @@
import { apiClient } from './client'
import { adminApiClient } from './client'
import type { AuthResponse } from '@/types/models'
export const authApi = {
// Request authentication code to be sent to all admin Telegram accounts
requestCode: async (): Promise<{ success: boolean; message: string }> => {
const response = await apiClient.post('/api/v2/admin/auth/request-code')
const response = await adminApiClient.post('/api/v2/admin/auth/request-code')
return response.data
},
// Verify authentication code
verifyCode: async (code: string): Promise<AuthResponse> => {
const response = await apiClient.post('/api/v2/admin/auth/verify-code', {
const response = await adminApiClient.post('/api/v2/admin/auth/verify-code', {
code,
})
return response.data
@ -18,7 +18,7 @@ export const authApi = {
// Get current admin info (for token validation)
getCurrentUser: async (): Promise<any> => {
const response = await apiClient.get('/api/v2/admin/auth/me')
const response = await adminApiClient.get('/api/v2/admin/auth/me')
return response.data
},
}

View file

@ -2,6 +2,10 @@ import axios from 'axios'
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'https://api.mnemo-cards.online'
// Admin API always uses production backend (admin auth requires production server)
const ADMIN_API_BASE_URL = 'https://api.mnemo-cards.online'
// Regular API client for non-admin endpoints
export const apiClient = axios.create({
baseURL: API_BASE_URL,
headers: {
@ -9,23 +13,35 @@ export const apiClient = axios.create({
},
})
// Admin API client - always uses production backend
export const adminApiClient = axios.create({
baseURL: ADMIN_API_BASE_URL,
headers: {
'Content-Type': 'application/json',
},
})
// Request interceptor to add auth token
apiClient.interceptors.request.use((config) => {
const addAuthToken = (config: any) => {
const token = localStorage.getItem('admin_token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
}
// Response interceptor for error handling
apiClient.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
localStorage.removeItem('admin_token')
window.location.href = '/login'
}
return Promise.reject(error)
const handleAuthError = (error: any) => {
if (error.response?.status === 401) {
localStorage.removeItem('admin_token')
window.location.href = '/login'
}
)
return Promise.reject(error)
}
// Apply interceptors to both clients
apiClient.interceptors.request.use(addAuthToken)
apiClient.interceptors.response.use((response) => response, handleAuthError)
adminApiClient.interceptors.request.use(addAuthToken)
adminApiClient.interceptors.response.use((response) => response, handleAuthError)

View file

@ -1,3 +1,4 @@
/// <reference types="vitest" />
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
@ -10,4 +11,9 @@ export default defineConfig({
"@": path.resolve(__dirname, "./src"),
},
},
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/test/setup.ts',
},
})

Binary file not shown.