Kaynağa Gözat

rtk_deploy build

Gennadysht 1 yıl önce
ebeveyn
işleme
e3fe697611

+ 19 - 6
src/Components/Category.js

@@ -1,5 +1,5 @@
 import { List, ListItem, ListItemButton, ListItemText, Button } from "@mui/material"
-import { Typography } from "@mui/material"
+import { Typography, Grid } from "@mui/material"
 import { Box, Container } from "@mui/system"
 import { useEffect } from "react"
 import { connect, useDispatch, useSelector } from "react-redux"
@@ -36,11 +36,24 @@ const Category = () => {
                     <CategoryBreadcrumbs category={cat} />
                     {
                         isAdmin && (
-                            <MyLink to="/editgood">
-                                <Button size='small' variant="contained" >
-                                    Add Good
-                                </Button>
-                            </MyLink>
+                            <>
+                                <Grid container spacing={2} justifyContent="center">
+                                    <Grid item>
+                                        <MyLink to="/editgood">
+                                            <Button size='small' variant="contained" >
+                                                Add Good
+                                            </Button>
+                                        </MyLink>
+                                    </Grid>
+                                    <Grid item>
+                                        <MyLink to={`/editcategory/${cat._id}`}>
+                                            <Button size='small' variant="contained" >
+                                                Edit Category
+                                            </Button>
+                                        </MyLink>
+                                    </Grid>
+                                </Grid>
+                            </>
                         )
                     }
                     <Typography paragraph gutterBottom component={'h3'} variant={'h3'} sx={{ marginTop: "1vh" }} >

+ 5 - 4
src/Components/CategoryTree.js

@@ -5,7 +5,7 @@ import {
     MultiBackend,
     getBackendOptions
 } from "@minoru/react-dnd-treeview";
-import { useGetRootCategoriesQuery, useSaveCategoryMutation } from "../reducers";
+import { DefaultSubCategoriesTreeDepth, useGetRootCategoriesQuery, useSaveCategoryMutation } from "../reducers";
 import { CategoryTreeItem } from "./CategoryTreeItem";
 import { ThemeProvider, CssBaseline } from "@mui/material";
 import { createTheme } from "@mui/material/styles";
@@ -53,7 +53,7 @@ const CategoryTree = ({ elements, saveCategory }) => {
             if (!params.dropTarget.subCategories)
                 params.dropTarget.subCategories = [];
             params.dropTarget.subCategories.push(params.dragSource);
-            sourceCat.parentCat = params.dropTarget;
+            params.dragSource.parentCat = params.dropTarget;
 
             sourceCat.parent = targetCat ?? null;
             saveCategory(sourceCat);
@@ -85,7 +85,7 @@ const CategoryTree = ({ elements, saveCategory }) => {
                             />
                         )}
                         dragPreviewRender={(monitorProps) => (
-                            <div>{monitorProps.item.text}</div>
+                            <CategoryTreeItem node={monitorProps.item} depth={0} isOpen={false}/>
                         )}
                         onDrop={handleDrop}
                         classes={{
@@ -111,6 +111,7 @@ function wrapToTreeItems(cats, parentCat = null, catTreeItems = undefined) {
                 "parentCat": parentCat,
                 "droppable": true,
                 "text": cat.name,
+                "image": cat.image ?? {},
                 "cat": { _id: cat._id, name: cat.name, parent: parentCat?.cat ?? null },
             };
             if (!parentCat.subCategories)
@@ -124,7 +125,7 @@ function wrapToTreeItems(cats, parentCat = null, catTreeItems = undefined) {
 }
 
 const CCategoryTree = () => {
-    const { isLoading, data } = useGetRootCategoriesQuery(true);
+    const { isLoading, data } = useGetRootCategoriesQuery(DefaultSubCategoriesTreeDepth);
     let cats = data?.CategoryFind;
 
     let catTreeItems = [];

+ 11 - 4
src/Components/CategoryTreeItem.js

@@ -2,8 +2,10 @@ import React from "react";
 import { TextField } from "@mui/material";
 import ArrowRightIcon from "@mui/icons-material/ArrowRight";
 import styles from "./CategoryTreeItem.module.css";
-import ListAltIcon from "@mui/icons-material/ListAlt";
 import { useDragOver } from "@minoru/react-dnd-treeview";
+import { AvatarImage } from "./AvatarAnimated";
+import { getFullImageUrl } from "../utills";
+import CategoryIcon from '@mui/icons-material/Category';
 
 export const CategoryTreeItem = (props) => {
     const { id, droppable, data } = props.node;
@@ -33,7 +35,13 @@ export const CategoryTreeItem = (props) => {
                 )}
             </div>
             <div>
-                <ListAltIcon color="secondary" droppable={droppable} fileType={data?.fileType} />
+                {
+                    props.node.image?.url ?
+                        <AvatarImage variant='rounded' src={getFullImageUrl(props.node.image)} />
+                        :
+                        <AvatarImage variant='rounded' sx={{ bgcolor: "rgba(184, 200, 239, 0.63)" }}><CategoryIcon color="secondary"/></AvatarImage>
+                }
+
             </div>
             <div className={styles.labelGridItem}>
                 <TextField
@@ -49,12 +57,11 @@ export const CategoryTreeItem = (props) => {
                             }
                         },
                     }}
-                    id="filled-basic" defaultValue={props.node.text} variant="filled" size="small"
+                    id="filled-basic" defaultValue={props.node.text} size="small"
                     onBlur={e => props.saveCategoryName(props.node, e.target.value)}
                     onKeyUp={(e) => {
                         if (e.key === 'Escape') {
                             e.target.value = e.target.defaultValue;
-                            console.log('Enter key pressed');
                         }
                     }}
                 />

+ 2 - 2
src/Components/DropDownList.js

@@ -1,6 +1,6 @@
 import React, { useEffect } from 'react';
 import { Button, ButtonGroup, ClickAwayListener, Grow, Paper, Popper, MenuItem, MenuList, Typography } from "@mui/material";
-import { useGetRootCategoriesQuery } from '../reducers';
+import { DefaultSubCategoriesTreeDepth, useGetRootCategoriesQuery } from '../reducers';
 import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
 import { styled } from '@mui/material/styles';
 import { DeleteOutline } from '@mui/icons-material';
@@ -126,7 +126,7 @@ const wrapToTreeItems = (cats, parentCat = undefined, currentLevelPrefix = '', c
 }
 
 export const CCategoryDropDownListUnstyled = ({ currentCat, onSetCategory, showClearButton }) => {
-    const { isLoading, data } = useGetRootCategoriesQuery(true);
+    const { isLoading, data } = useGetRootCategoriesQuery(DefaultSubCategoriesTreeDepth);
     let cats = data?.CategoryFind;
     if (!isLoading && cats) {
         cats = wrapToTreeItems(cats);

+ 1 - 0
src/Components/MainAppBar.js

@@ -40,6 +40,7 @@ const MainAppBar = ({ token, openSidebar }) => {
                         aria-label="menu"
                         onClick={() => openSidebar(true)}
                         sx={{ mr: 2 }}
+                        id="burger"
                     >
                         <MenuIcon />
                     </IconButton>

+ 35 - 4
src/Components/RootCats.js

@@ -1,18 +1,48 @@
+import React from "react";
 import { List, ListItem, ListItemButton, ListItemText } from "@mui/material";
 import { MyLink } from ".";
 import { useGetRootCategoriesQuery } from "../reducers";
+import { AvatarImage } from "./AvatarAnimated";
+import ListItemAvatar from '@mui/material/ListItemAvatar';
+import CategoryIcon from '@mui/icons-material/Category';
+import { getFullImageUrl } from "../utills";
 
 export const CatsList = ({ cats = [] }) => {
+    const [selectedIndex, setSelectedIndex] = React.useState(-1);
+
+    const handleListItemClick = (event, index) => {
+        setSelectedIndex(index);
+    };
     return (
-        <List>
-            {cats && cats?.map(cat => (
-                <CatItem cat={cat} key={cat._id} />
+        <List sx={{ bgcolor: "" }}>
+            {cats && cats?.map((cat, index) => (
+                <CatItem cat={cat} key={cat._id} index={index} selectedIndex={selectedIndex} handleListItemClick={handleListItemClick} />
             ))}
         </List>
     )
 };
 
-const CatItem = ({ cat }) => {
+const CatItem = ({ cat, index, selectedIndex, handleListItemClick }) => {
+    return (
+        <MyLink to={`/category/${cat._id}`}>
+            <ListItemButton
+                selected={index === selectedIndex}
+                onClick={(event) => handleListItemClick(event, index)}
+            >
+                <ListItemAvatar>
+                    {
+                        cat.image?.url ?
+                            <AvatarImage variant='rounded' src={getFullImageUrl(cat.image)} />
+                            :
+                            <AvatarImage variant='rounded' sx={{ bgcolor: "rgba(184, 200, 239, 0.63)" }}><CategoryIcon color="secondary" /></AvatarImage>
+                    }
+                </ListItemAvatar>
+                <ListItemText
+                    primary={cat.name}
+                />
+            </ListItemButton>
+        </MyLink>
+    );
     return (
         <ListItem key={cat._id} disablePadding>
             <ListItemButton>
@@ -27,6 +57,7 @@ const CatItem = ({ cat }) => {
 const CRootCats = () => {
     const { isLoading, data } = useGetRootCategoriesQuery();
     let cats = data?.CategoryFind;
+
     return !isLoading && cats && <CatsList cats={cats} />
 }
 

+ 6 - 8
src/Components/Sidebar.js

@@ -19,13 +19,10 @@ function Sidebar(props) {
         openSidebar(false);
         setOpenedComp(undefined)
     };
-    const handleClickAwayListener = () => {
-        if (openedComp === undefined) {
-            setOpenedComp(true)
-        }
-        else if (openedComp === true)
-            handleDrawerClose();
-
+    const handleClickAwayListener = event => {
+        if (event.target.closest('#burger'))
+            return;
+        handleDrawerClose();
     };
     const DrawerHeader = styled('div')(({ theme }) => ({
         display: 'flex',
@@ -35,9 +32,10 @@ function Sidebar(props) {
         ...theme.mixins.toolbar,
         justifyContent: 'flex-end',
     }));
+
     return (
         <>
-            <ClickAwayListener onClickAway={handleClickAwayListener}>
+            <ClickAwayListener onClickAway={event => handleClickAwayListener(event)}>
                 <Drawer
                     sx={{
                         width: drawerWidth,

+ 23 - 8
src/reducers/categoryReducer.js

@@ -1,7 +1,7 @@
 import { createApi } from '@reduxjs/toolkit/query/react'
 import { graphqlRequestBaseQuery } from "@rtk-query/graphql-request-base-query"
 import { gql } from "graphql-request";
-import { createFullQuery, getFullBackendUrl } from '../utills';
+import { createFullQuery, getFullBackendUrl, repeatQuery } from '../utills';
 
 const getCategorySearchParams = (query, queryExt) => ({ searchStr: query, searchFieldNames: ["name"], queryExt });
 export const prepareHeaders = (headers, { getState }) => {
@@ -12,6 +12,7 @@ export const prepareHeaders = (headers, { getState }) => {
     return headers;
 }
 
+let placeHolder = '|--|';
 export const categoryApi = createApi({
     reducerPath: 'category',
     baseQuery: graphqlRequestBaseQuery({
@@ -21,19 +22,33 @@ export const categoryApi = createApi({
     tagTypes: ['Category', 'CategoryCount'],
     endpoints: (builder) => ({
         getRootCategories: builder.query({
-            query: (withChildren = false) => ({
-                document: gql`
-                query GetCategories{
-                    CategoryFind(query: "[{\\"parent\\": null}]") {
-                        _id name ${withChildren ? 'subCategories { _id name } ' : ''} image { _id url }
+            query: (childrenDepth = 0) => {
+                let params = createFullQuery({ queryExt: {parent: null } }, { sort: { name: 1 } });
+                return (
+                    {
+                        document: gql`
+                        query GetCategories($q: String){
+                            CategoryFind(query: $q) {
+                                _id name image { _id url }
+                                ${repeatQuery(childrenDepth, ` subCategories { _id name image { _id url } ${placeHolder} } `, placeHolder)}
+                            }
                         }
+                    `,
+                        variables: params
                     }
-                `}),
+                )
+            },
             providesTags: (result) => {
                 return result
                     ? [...result.CategoryFind.map(obj => ({ type: 'Category', _id: obj._id })), 'Category']
                     : ['Category'];
-            }
+            },
+            transformResponse: (response) => {
+                return response;
+            },
+            transformErrorResponse: (response, meta) => {
+                return response;
+            },
         }),
         getCategories: builder.query({
             query: ({ withOwner = false, withChildren = false, withParent = false, queryExt = {}, fromPage, pageSize, searchStr = '' }) => {

+ 1 - 0
src/reducers/index.js

@@ -4,5 +4,6 @@ export { frontEndSlice, frontEndNames, actionSetSidebar, actionSetPaging, action
 export { useGetRootCategoriesQuery, useGetCategoryByIdQuery, useGetCategoriesQuery, useGetCategoriesCountQuery, useSaveCategoryMutation } from './categoryReducer';
 export { ordersApi, useGetOrderByIdQuery, useGetOrdersCountQuery, useGetOrdersQuery, useAddOrderMutation } from './ordersReducer';
 export { goodsApi, useGetGoodByIdQuery, useGetGoodsCountQuery, useGetGoodsQuery, useGetGoodsByIdQuery, useSaveGoodMutation } from './goodsReducer';
+export let DefaultSubCategoriesTreeDepth = 3;
 
 

+ 11 - 0
src/utills/gqlUtils.js

@@ -28,3 +28,14 @@ const createQueryPaging = (fromPage, pageSize, sort) => {
 export const createFullQuery = ({ searchStr, searchFieldNames, queryExt = {} }, { fromPage, pageSize, sort } = {}) => {
     return { q: JSON.stringify([createQueryExt(createQuery(searchStr, searchFieldNames), queryExt), createQueryPaging(fromPage, pageSize, sort)]) };
 }
+
+export const repeatQuery = (depth, content, placeHolder, query = undefined) => {
+    query ||= placeHolder;
+    query = ` ${query} `
+    for (let i = 0; i < depth; i++) {
+        query = query.replace("|--|", content);
+    }
+    query = query.replace("|--|", "");
+    return query;
+}
+

+ 1 - 1
src/utills/index.js

@@ -1,2 +1,2 @@
 export {getFullImageUrl, findObjectIndexById, capitalize, fixBackendDataError, jwtDecode, getFullBackendUrl} from './utils';
-export {createFullQuery} from './gqlUtils';
+export {createFullQuery, repeatQuery} from './gqlUtils';

+ 1 - 1
src/utills/utils.js

@@ -14,7 +14,7 @@ function saveImage(image) {
     let formData = new FormData();
     formData.append('photo', image.data);
     let token = JSON.parse(JSON.parse(localStorage["persist:auth"]).token);
-    let res = fetch('/upload', {
+    let res = fetch(getFullBackendUrl('/upload'), {
         method: "POST",
         headers: token ? { Authorization: 'Bearer ' + token } : {},
         body: formData