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",