diff --git a/scripts/prerender.js b/scripts/prerender.js index e947ec1..6452089 100644 --- a/scripts/prerender.js +++ b/scripts/prerender.js @@ -67,7 +67,7 @@ function generateHomePage(products) { const topProducts = products.slice(0, 6).map(product => `

${escapeHtml(product.full_name || `Товар ${product.id}`)}

- Подробнее + Подробнее
`).join(''); return ` @@ -88,7 +88,7 @@ function generateCatalogPage(products) {

${escapeHtml(product.full_name || `Товар ${product.id}`)}

${escapeHtml((product.description || '').slice(0, 150))}...

- Подробнее + Подробнее
`).join(''); return ` @@ -139,7 +139,7 @@ const routes = [ // Добавляем страницы товаров for (const product of products) { routes.push({ - path: `/product/${product.id}`, + path: `/product/${product.slug || product.id}`, title: product.full_name, description: (product.description || ''), getContent: () => generateProductPage(product) diff --git a/src/app/routes.tsx b/src/app/routes.tsx index 82bc8b7..07e3acb 100644 --- a/src/app/routes.tsx +++ b/src/app/routes.tsx @@ -15,7 +15,7 @@ function AppRoutes() { } /> } /> } /> - } /> + } /> ) diff --git a/src/features/catalog/ProductCard.tsx b/src/features/catalog/ProductCard.tsx index 1ec4939..6ace742 100644 --- a/src/features/catalog/ProductCard.tsx +++ b/src/features/catalog/ProductCard.tsx @@ -2,31 +2,34 @@ import React from "react"; import type { Product } from "../../types/product"; import styles from "./Catalog.module.css"; import { useNavigate } from "react-router-dom"; -import { setSelectedProducts } from "./productsSlice"; + interface Props { - product: Product; + product: Product; } const ProductCard: React.FC = ({ product }) => { const navigate = useNavigate(); - const onSelect = (prodId: number) => { - navigate(`/product/${product.id}`); - setSelectedProducts(prodId); - } + const onSelect = () => { + navigate(`/product/${product.slug}`); + }; return ( -
onSelect(product.id)} + onClick={() => onSelect()} >
- {product.name} + {product.name}
-

{product.name}

- +

{product.name}

+
); diff --git a/src/features/catalog/productsSlice.ts b/src/features/catalog/productsSlice.ts index dd25eb0..2281577 100644 --- a/src/features/catalog/productsSlice.ts +++ b/src/features/catalog/productsSlice.ts @@ -38,10 +38,10 @@ export const fetchProductsByCategory = createAsyncThunk( } ); -export const fetchProductById = createAsyncThunk( - "product/fetchById", - async (id: string) => { - const response = await client.get(`/products/${id}/`); +export const fetchProductBySlug = createAsyncThunk( + "product/fetchBySlug", + async (slug: string) => { + const response = await client.get(`/products/${slug}/`); return response.data; } ); @@ -54,7 +54,8 @@ interface ProductsState { loading: boolean; error: string | null; filtersApplied: Record; - selectedProductId: number | null; + selectedProduct: Product | null; + //selectedProductId: number | null; } const initialState: ProductsState = { @@ -65,16 +66,17 @@ const initialState: ProductsState = { loading: false, error: null, filtersApplied: {}, - selectedProductId: null + selectedProduct: null + //selectedProductId: null }; const slice = createSlice({ name: "products", initialState, reducers: { - setSelectedProducts(state, action: PayloadAction){ + /*setSelectedProducts(state, action: PayloadAction){ state.selectedProductId = action.payload; - }, + },*/ setPage(state, action: PayloadAction) { state.page = action.payload; }, @@ -84,10 +86,14 @@ const slice = createSlice({ setFilters(state, action: PayloadAction) { state.filtersApplied = action.payload; }, + setSelectedProduct(state, action: PayloadAction) { + state.selectedProduct = action.payload; + }, resetProducts(state) { state.items = []; state.total = 0; state.page = 1; + state.selectedProduct = null; } }, extraReducers: (builder) => { @@ -106,9 +112,22 @@ const slice = createSlice({ .addCase(fetchProductsByCategory.rejected, (s, a) => { s.loading = false; s.error = a.error.message ?? "Ошибка"; + }) + .addCase(fetchProductBySlug.pending, (s) => { + s.loading = true; + s.error = null; + }) + .addCase(fetchProductBySlug.fulfilled, (s, a) => { + s.loading = false; + s.selectedProduct = a.payload; + s.error = null; + }) + .addCase(fetchProductBySlug.rejected, (s, a) => { + s.loading = false; + s.error = a.error.message ?? "Ошибка"; }); } }); -export const { setPage, setLimit, setFilters, resetProducts, setSelectedProducts } = slice.actions; -export default slice.reducer; \ No newline at end of file +export const { setPage, setLimit, setFilters, resetProducts } = slice.actions; +export default slice.reducer; diff --git a/src/pages/ItemPage/ItemPage.tsx b/src/pages/ItemPage/ItemPage.tsx index 4d67a25..885c7bc 100644 --- a/src/pages/ItemPage/ItemPage.tsx +++ b/src/pages/ItemPage/ItemPage.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { useParams, useNavigate } from "react-router-dom"; import { ArrowLeftOutlined } from "@ant-design/icons"; import { useAppDispatch, useAppSelector } from "../../app/hooks"; -import { fetchProductById } from "../../features/catalog/productsSlice"; +import { fetchProductBySlug } from "../../features/catalog/productsSlice"; import styles from "./ItemPage.module.css"; import Button from "../../components/Button/Button"; import PriceLisForm from "../../components/PriceLisForm/PriceLisForm"; @@ -11,20 +11,20 @@ import Link from "antd/es/typography/Link"; import { setSelectedCategory } from "../../features/catalog/categoriesSlice"; const ItemPage = () => { - const { id } = useParams(); + const { slug } = useParams(); const dispatch = useAppDispatch(); const navigate = useNavigate(); - const { items, loading } = useAppSelector((state) => state.products); + const { loading } = useAppSelector((state) => state.products); const { items: cats, selectedCategoryId } = useAppSelector((s) => s.categories); const [activeTab, setActiveTab] = useState<"desc" | "chars">("desc"); const [open, setOpen] = useState(false); useEffect(() => { - if (id) dispatch(fetchProductById(id)); - }, [dispatch, id]); + if (slug) dispatch(fetchProductBySlug(slug)); + }, [dispatch, slug]); - const product = items.find((item) => item.id === Number(id)); + const product = useAppSelector((state) => state.products.selectedProduct); const category = cats.find((cat) => cat.id === Number(selectedCategoryId)); if (loading || !product) { diff --git a/src/types/product.ts b/src/types/product.ts index 611728d..c954702 100644 --- a/src/types/product.ts +++ b/src/types/product.ts @@ -9,4 +9,5 @@ export interface Product { categoryId?: number; created_at: string; full_name: string; + slug:string; } \ No newline at end of file