diff --git a/package.json b/package.json index 9c9f6e4..ab12438 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "react": "^18", "react-dom": "^18", "react-hook-form": "^7.50.1", + "react-image": "^4.1.0", "react-imask": "^7.5.0", "valtio": "^1.13.0", "zod": "^3.22.4" diff --git a/src/components/reusable/wrapper.tsx b/src/components/reusable/wrapper.tsx index 88d6bb9..823b30b 100644 --- a/src/components/reusable/wrapper.tsx +++ b/src/components/reusable/wrapper.tsx @@ -37,7 +37,7 @@ const Wrapper = (props: WrapperProps) => { } } -

{props.title}

+

{props.title}

{props.children} diff --git a/src/pages/catalog/[code].tsx b/src/pages/catalog/[code].tsx index 60ee6ac..efd58af 100644 --- a/src/pages/catalog/[code].tsx +++ b/src/pages/catalog/[code].tsx @@ -1,4 +1,4 @@ -import {BreadcrumbItem, Breadcrumbs, Button} from "@nextui-org/react"; +import {BreadcrumbItem, Breadcrumbs, Button, Skeleton, Spinner} from "@nextui-org/react"; import HomeIcon from "../../../public/home_icon.svg"; import Link from "next/link"; import axios from "axios"; @@ -11,6 +11,7 @@ import {useSnapshot} from "valtio"; import useClient from "@/hooks/useClient"; import LocalAPI from "@/service/localAPI"; import {useQuery, useQueryClient, useMutation} from "@tanstack/react-query"; +import {Img} from 'react-image' const OilCard = ({product}: InferGetStaticPropsType) => { const {favourites} = useSnapshot(favouritesStore) @@ -56,33 +57,32 @@ const OilCard = ({product}: InferGetStaticPropsType) => { {product.name} -
- {/*TODO image*/} - {product.properties.main_image && #} -
+
+ {isClient && product.properties.main_image && {product.name}}/>} +
Артикул: {product.properties.vendor_code} -

{product.name}

+ className={"text-sm md:text-xl text-[#E0E3E3] mb-7 block"}>Артикул: {product.properties.vendor_code} +

{product.name}

Категория: {product.properties.category} + className={"text-base md:text-xl block mb-7 text-[#E0E3E3]"}>Категория: {product.properties.category} Вязкость: {product.properties.viscosity} + className={"text-base md:text-xl block mb-7 text-[#E0E3E3]"}>Вязкость: {product.properties.viscosity} Тип: {product.properties.oil_type} + className={"text-base md:text-xl block mb-7 text-[#E0E3E3]"}>Тип: {product.properties.oil_type}
- -
+
- - {product.price.BASE} ₽ + + {`${product.price.BASE}`.replace(/\B(?=(\d{3})+(?!\d))/g, ' ')} ₽ 1 шт {isClient && - } { isClient && - } diff --git a/src/pages/catalog/index.tsx b/src/pages/catalog/index.tsx index 22b272f..5c734af 100644 --- a/src/pages/catalog/index.tsx +++ b/src/pages/catalog/index.tsx @@ -1,15 +1,12 @@ import { - Breadcrumbs, - BreadcrumbItem, CheckboxGroup, Checkbox, - Button, Skeleton + Button, Skeleton, Accordion, AccordionItem } from "@nextui-org/react"; import Link from "next/link"; -import axios from "axios"; + import {InferGetStaticPropsType} from "next"; import FavouriteIcon from "@/../public/favourites_icon.svg"; -import {Dispatch, SetStateAction, useEffect, useState} from "react"; import {toggleFavourite} from "@/store/favourites"; import {useSnapshot} from "valtio"; @@ -18,89 +15,103 @@ import useClient from "@/hooks/useClient"; import Wrapper from "@/components/reusable/wrapper"; import {useMutation, useQuery, useQueryClient} from "@tanstack/react-query"; import LocalAPI from "@/service/localAPI"; +import {Img} from "react-image"; +const CheckboxUI = (obj: {id: number, name: string, values: {id: number, value: string}[]}) => { + return ( + + + + {obj.values && obj.values.map(val => ( + {val.value} + ))} + + + + + ) +} const FilterGenerator = ({filterPropertiesData}: Pick, "filterPropertiesData">) => { return ( -
-

Фильтры

- - {filterPropertiesData.map( obj => ( - - {obj.values && obj.values.map(val => ( - {val.value} + + + {filterPropertiesData.map(obj => ( + ))} - - - ))} -
+ + ) } -type CardProps = InferGetStaticPropsType['catalog'][0] & {isFavourite?: boolean} +type CardProps = InferGetStaticPropsType['catalog'][0] & { isFavourite?: boolean } const CatalogCard = (product: CardProps) => { const isClient = useClient() - const cartItems = useQuery({queryKey: ['cart'], queryFn: async () => { - const service = new LocalAPI() - return await service.getCartItems() - }}) - - const [imageIsLoading, setImageIsLoading] = useState(true); - const qs = useQueryClient() - - const toggleCart = useMutation({ - mutationFn: async ({productId, quantity}: { productId: number, quantity: number }) => { - const service = new LocalAPI() - if (cartItems.data!.find(({id}) => id === productId)) { - return await service.deleteCartItem(productId) - } - return await service.addCartItem(productId, quantity) - }, - onSuccess: () => { - qs.invalidateQueries({queryKey: ["cart"]}) + const cartItems = useQuery({ + queryKey: ['cart'], queryFn: async () => { + const service = new LocalAPI() + return await service.getCartItems() } }) - const onImageLoad = () => { - setImageIsLoading(false); - } + + const qs = useQueryClient() + + const toggleCart = useMutation({ + mutationFn: async ({productId, quantity}: { productId: number, quantity: number }) => { + const service = new LocalAPI() + if (cartItems.data!.find(({id}) => id === productId)) { + return await service.deleteCartItem(productId) + } + return await service.addCartItem(productId, quantity) + }, + onSuccess: () => { + qs.invalidateQueries({queryKey: ["cart"]}) + } + }) return ( -
+
{ - imageIsLoading && - } - { - product.properties.main_image && {product.name} + isClient && product.properties.main_image && + {product.name}}/> }
- Стандарт API: {product.properties.api_standart} Тип: {product.properties.oil_type} + Стандарт API: {product.properties.api_standart} Тип: {product.properties.oil_type}

{product.name}

{ isClient ? - toggleFavourite(product.id)} className={`transition-colors absolute z-20 top-0 right-0 ${product.isFavourite ? "fill-primary" : "fill-[#E0E3E3]"}`}/> : null + toggleFavourite(product.id)} + className={`transition-colors absolute z-20 top-0 right-0 ${product.isFavourite ? "fill-primary" : "fill-[#E0E3E3]"}`}/> : null } -
+
- {product.price.BASE} ₽ + {`${product.price.BASE}`.replace(/\B(?=(\d{3})+(?!\d))/g, ' ')} ₽ { isClient ? - : null + : null } - +
@@ -113,20 +124,21 @@ const Catalog = (props: InferGetStaticPropsType) => { const {favourites} = useSnapshot(favouritesStore) return ( -
- +
+ -
+
- { - props.catalog.map(product => - <> - - - ) - } -
-
+ { + props.catalog.map(product => + <> + + + ) + } +
+
) } @@ -135,7 +147,11 @@ export default Catalog; export const getStaticProps = async () => { const service = new LocalAPI() - const filterData = await service.getFilters() as {id: number, name: string, values: {id: number, value: string}[]}[] + const filterData = await service.getFilters() as { + id: number, + name: string, + values: { id: number, value: string }[] + }[] const catalogData = await service.getCatalogItems() as { id: number code: string, diff --git a/src/styles/globals.css b/src/styles/globals.css index d3d6ab9..00d2fa6 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -19,7 +19,7 @@ } .wrapper { - @apply 2xl:max-w-[1440px] max-w-full sm:max-w-[540px] md:max-w-[720px] lg:max-w-[960px] xl:max-w-[1140px] mx-auto; + @apply 2xl:max-w-[1440px] max-w-[90%] sm:max-w-[540px] md:max-w-[720px] lg:max-w-[960px] xl:max-w-[1140px] mx-auto; } } diff --git a/yarn.lock b/yarn.lock index ddece8e..1c9d28b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5497,6 +5497,11 @@ react-hook-form@^7.50.1: resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.50.1.tgz#f6aeb17a863327e5a0252de8b35b4fc8990377ed" integrity sha512-3PCY82oE0WgeOgUtIr3nYNNtNvqtJ7BZjsbxh6TnYNbXButaD5WpjOmTjdxZfheuHKR68qfeFnEDVYoSSFPMTQ== +react-image@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/react-image/-/react-image-4.1.0.tgz#92f2d4a809a178b3bf69acd7bad7da7aa5e7364c" + integrity sha512-qwPNlelQe9Zy14K2pGWSwoL+vHsAwmJKS6gkotekDgRpcnRuzXNap00GfibD3eEPYu3WCPlyIUUNzcyHOrLHjw== + react-imask@^7.5.0: version "7.5.0" resolved "https://registry.yarnpkg.com/react-imask/-/react-imask-7.5.0.tgz#ba751c3b29c263fc47293e49755a5f0a369a12f8"