From 1699873ea8912f4544145afd42953702cf6e98e0 Mon Sep 17 00:00:00 2001 From: Oleg Urin Date: Mon, 30 Mar 2026 22:56:01 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BA=D0=BB=D0=B8=D0=B5=D0=BD=D1=82,=20=D0=BF=D1=83?= =?UTF-8?q?=D1=82=D0=B8=20=D0=B2=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=D1=85,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D1=83=D1=8E=20?= =?UTF-8?q?=D0=BE=D0=BA=D1=80=D1=83=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + README.md | 2 - src/api/client.ts | 48 +++++++++++++++++--- src/components/PriceLisForm/PriceLisForm.tsx | 9 ++-- src/features/catalog/categoriesSlice.ts | 4 +- src/features/catalog/productsSlice.ts | 4 +- src/vite-env.d.ts | 8 ++++ tsconfig.app.json | 2 +- 8 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 src/vite-env.d.ts diff --git a/.gitignore b/.gitignore index a547bf3..dc2ec41 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ node_modules dist dist-ssr *.local +.env.production # Editor directories and files .vscode/* diff --git a/README.md b/README.md index 9b24cc2..0212a8b 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,6 @@ GET /products?categoryId=1&page=1&limit=9&size=110х2,2х500,110х2,2х1500&colo "id": 101, "name": "Труба ПВХ", "description": "бля бля", - "price": 799, "categoryId": 1, "images": ["/images/s23-1.jpg", "/images/s23-2.jpg"], "attributes": { @@ -148,7 +147,6 @@ GET /api/products/101 "id": 101, "name": "ПВХ труба", "description": "бля бля", - "price": 799, "categoryId": 1, "images": [ "/images/s23-1.jpg", diff --git a/src/api/client.ts b/src/api/client.ts index eb9f9fb..a1d33a0 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -1,9 +1,43 @@ -import axios from "axios"; +import axios, { AxiosInstance } from 'axios'; -export const API_BASE = ""; -const client = axios.create({ - baseURL: API_BASE, - headers: { "Content-Type": "application/json" }, -}); +class ApiClient { + private axiosInstance: AxiosInstance; -export default client; \ No newline at end of file + constructor(baseURL: string = import.meta.env.VITE_API_URL) { + this.axiosInstance = axios.create({ + baseURL, + timeout: 10000, + headers: { + 'Content-Type': 'application/json', + }, + }); + + // Интерцептор для обработки ошибок + this.axiosInstance.interceptors.response.use( + (response) => response, + (error) => { + if (error.response?.status === 404) { + console.error('Resource not found:', error.config?.url); + } else if (error.response?.status === 500) { + console.error('Server error:', error.response?.data); + } + return Promise.reject(error); + } + ); + } + + async get(url: string): Promise<{ data: T }> { + const response = await this.axiosInstance.get(url); + return { data: response.data }; + } + + async post( + url: string, + data?: any, + ): Promise<{ data: T }> { + const response = await this.axiosInstance.post(url, data); + return { data: response.data }; + } +} + +export const client = new ApiClient('/api'); \ No newline at end of file diff --git a/src/components/PriceLisForm/PriceLisForm.tsx b/src/components/PriceLisForm/PriceLisForm.tsx index 88518bc..a0837b0 100644 --- a/src/components/PriceLisForm/PriceLisForm.tsx +++ b/src/components/PriceLisForm/PriceLisForm.tsx @@ -7,10 +7,11 @@ import { yupResolver } from "@hookform/resolvers/yup"; import styles from "./ModalRequestForm.module.css"; import Button from "../Button/Button"; import axios from "axios"; +import { client } from "../../api/client"; // ✅ Схема валидации const schema = yup.object().shape({ - name: yup.string().required("Введите имя"), + name: yup.string().required("Введите ФИО"), email: yup.string().email("Некорректный Email").required("Введите Email"), phone: yup.string().min(18, "Введите корректный номер").required("Введите номер"), }); @@ -62,10 +63,8 @@ const PriceLisForm: React.FC = ({ open, onClose }) => { const sendToBackend = async (data: FormData): Promise => { try{ - const response = await axios.post("/api/requests", { + const response = await client.post<{success: boolean}>("/api/email", { ...data, - source: "website-form", - timestamp: new Date().toISOString(), }) return response.data.success; @@ -121,7 +120,7 @@ const PriceLisForm: React.FC = ({ open, onClose }) => {
diff --git a/src/features/catalog/categoriesSlice.ts b/src/features/catalog/categoriesSlice.ts index 4c0685c..f1b8a81 100644 --- a/src/features/catalog/categoriesSlice.ts +++ b/src/features/catalog/categoriesSlice.ts @@ -1,11 +1,11 @@ import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; import type { Category } from "../../types/categories"; -import axios from "axios"; +import {client} from "../../api/client"; export const fetchCategories = createAsyncThunk( "categories/fetchCategories", async () => { - const res = await axios.get("/api/categories"); + const res = await client.get("/categories"); return res.data; } ); diff --git a/src/features/catalog/productsSlice.ts b/src/features/catalog/productsSlice.ts index 45b9af2..a0b3f85 100644 --- a/src/features/catalog/productsSlice.ts +++ b/src/features/catalog/productsSlice.ts @@ -1,6 +1,6 @@ import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"; import type {PayloadAction} from "@reduxjs/toolkit"; -import client from "../../api/client"; +import {client} from "../../api/client"; import type { Product } from "../../types/product"; import axios from "axios"; @@ -42,7 +42,7 @@ export const fetchProductsByCategory = createAsyncThunk( export const fetchProductById = createAsyncThunk( "product/fetchById", async (id: string) => { - const response = await axios.get(`/api/products/${id}`); + const response = await client.get(`/products/${id}`); return response.data; } ); diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..2fb12b0 --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1,8 @@ +interface ImportMetaEnv { + readonly VITE_API_URL: string + readonly VITE_API_KEY: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} \ No newline at end of file diff --git a/tsconfig.app.json b/tsconfig.app.json index a9b5a59..7d68ebb 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -11,7 +11,7 @@ /* Bundler mode */ "moduleResolution": "bundler", "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, + "verbatimModuleSyntax": false, "moduleDetection": "force", "noEmit": true, "jsx": "react-jsx", From fd28afea41841b4d0153ed2ff60483188945f3d3 Mon Sep 17 00:00:00 2001 From: Oleg Urin Date: Tue, 31 Mar 2026 15:09:35 +0300 Subject: [PATCH 2/2] ... --- src/api/client.ts | 1 - vite.config.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/api/client.ts b/src/api/client.ts index a1d33a0..76e08df 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -12,7 +12,6 @@ class ApiClient { }, }); - // Интерцептор для обработки ошибок this.axiosInstance.interceptors.response.use( (response) => response, (error) => { diff --git a/vite.config.ts b/vite.config.ts index 13122b5..159db8d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,7 +7,7 @@ export default defineConfig({ server: { host: '0.0.0.0', // Слушаем все интерфейсы port: 5173, - allowedHosts: ['rustprogersteam.ru'], + allowedHosts: ['pvh.projects.rustprogersteam.ru'], strictPort: true, // Запрещаем автоматический выбор порта hmr: { clientPort: 5173, // Важно для HMR в Docker