Gennadysht 2 rokov pred
rodič
commit
4acebb78c4

+ 1 - 0
src/App.js

@@ -19,6 +19,7 @@ export const history = createBrowserHistory();
 //store.dispatch(actionRootCats());
 //store.dispatch(actionRestoreCart());
 
+
 const NotFound = () =>
   <div>
     <h1>404 not found</h1>

+ 7 - 19
src/Components/Category.js

@@ -1,4 +1,4 @@
-import { List, ListItem, ListItemButton, ListItemText, Breadcrumbs, Button } from "@mui/material"
+import { List, ListItem, ListItemButton, ListItemText, Button } from "@mui/material"
 import { Typography } from "@mui/material"
 import { Box, Container } from "@mui/system"
 import { useState } from "react"
@@ -8,7 +8,9 @@ import { useParams } from "react-router-dom"
 import { MyLink } from "."
 import { isCurrentUserAdmin, useGetCategoryByIdQuery } from "../reducers"
 import { actionSetCurrentEntity, frontEndNames, getCurrentEntity } from "../reducers/frontEndReducer"
+import { CategoryBreadcrumbs } from "./CategoryBreadcrumbs"
 import { CGoodsList } from "./GoodsList"
+import { LoadingState } from "./LoadingState"
 import { CatsList } from "./RootCats"
 
 const CSubCategories = connect(state => ({ cats: getCurrentEntity(frontEndNames.category, state)?.subCategories }),
@@ -22,31 +24,17 @@ const Category = () => {
     const dispatch = useDispatch();
     let state = useSelector(state => state);
     useEffect(() => {
-        if (getCurrentEntity(frontEndNames.category, state)?._id != _id) 
+        if (getCurrentEntity(frontEndNames.category, state)?._id != _id)
             dispatch(actionSetCurrentEntity(frontEndNames.category, { _id }));
         if (!isLoading)
             dispatch(actionSetCurrentEntity(frontEndNames.category, data.CategoryFindOne));
     }, [_id, isLoading, data]);
     let isAdmin = isCurrentUserAdmin(state);
-    return isLoading ? <Typography>Loading</Typography> : (
+    return isLoading ? <LoadingState /> : (
         <>
             <Container>
                 <Box>
-                    <Breadcrumbs aria-label="breadcrumb">
-                        <MyLink underline="hover" color="inherit" to="/">
-                            Home
-                        </MyLink>
-                        {cat.parent?._id && (
-                            <MyLink
-                                underline="hover"
-                                color="inherit"
-                                to={`/category/${cat.parent?._id}`}
-                            >
-                                {cat.parent?.name}
-                            </MyLink>
-                        )}
-                        <Typography color="text.primary">{cat.name}</Typography>
-                    </Breadcrumbs>
+                    <CategoryBreadcrumbs category={cat} />
                     {
                         isAdmin && (
                             <MyLink to="/editgood">
@@ -56,7 +44,7 @@ const Category = () => {
                             </MyLink>
                         )
                     }
-                    <Typography paragraph gutterBottom component={'h3'} variant={'h3'}>
+                    <Typography paragraph gutterBottom component={'h3'} variant={'h3'} sx={{marginTop: "1vh"} } >
                         {cat.name}
                     </Typography>
                     {csubCats && <CSubCategories />}

+ 1 - 1
src/Components/CategoryList.js

@@ -51,7 +51,7 @@ const CategoriesList = ({ entities, entitiesTypeName, fromPage, pageSize, isAdmi
     ]
     return (
         <>
-            <Container maxWidth="lg">
+            <Container maxWidth="lg" sx={{marginTop: "1vh"}}>
                 {
                     isAdmin && (
                         <MyLink to="/editcategory">

+ 6 - 3
src/Components/EditableGood.js

@@ -12,10 +12,11 @@ import { ModalContainer } from './ModalContainer';
 import { history } from "../App";
 import { LackPermissions } from './LackPermissions';
 import { CCategoryDropDownList } from './DropDownList';
+import { CategoryBreadcrumbs } from './CategoryBreadcrumbs';
 
 
 const EditableGood = ({ good: goodExt, maxWidth = 'md', saveGood }) => {
-    const copyGood = goodExt => ({ ...goodExt, images: [ ...(goodExt.images ?? []) ] });
+    const copyGood = goodExt => ({ ...goodExt, images: [...(goodExt.images ?? [])] });
     let [good, setGood] = useState(copyGood(goodExt));
     let [showPreview, setShowPreview] = useState(false);
     let [imagesContainer, setImagesContainer] = useState({ images: [...(goodExt.images ?? [])] });
@@ -58,9 +59,11 @@ const EditableGood = ({ good: goodExt, maxWidth = 'md', saveGood }) => {
     }
     if (good)
         good.categories ??= [];
+    const currentCategory = good.categories?.length > 0 ? good.categories[0] : undefined;
     return good && (
         <>
             <Container maxWidth={maxWidth}>
+                <CategoryBreadcrumbs category={currentCategory} showLeafAsLink={true} />
                 <Card variant='outlined'>
                     <Grid container spacing={maxWidth === 'xs' ? 7 : 5} rowSpacing={2}>
                         <Grid item xs={12}>
@@ -78,7 +81,7 @@ const EditableGood = ({ good: goodExt, maxWidth = 'md', saveGood }) => {
                                         <Grid container rowSpacing={2}>
                                             <Grid item width="100%">
                                                 {
-                                                    <CCategoryDropDownList currentCat={good.categories?.length > 0 ? good.categories[0] : undefined} onSetCategory={onSetCategory} />
+                                                    <CCategoryDropDownList currentCat={currentCategory} onSetCategory={onSetCategory} />
                                                 }
                                             </Grid>
                                             <Grid item width="100%">
@@ -166,7 +169,7 @@ const CEditableGood = ({ maxWidth = 'md' }) => {
         good = { _id: undefined, categories, images: [] };
     }
 
-    return !isLoading && 
+    return !isLoading &&
         (isAdmin ? <EditableGood good={good} saveGood={saveGoodMutation} maxWidth={maxWidth} /> : <LackPermissions name="good" />)
 }
 

+ 5 - 2
src/Components/Good.js

@@ -11,6 +11,8 @@ import { useGetGoodByIdQuery } from '../reducers';
 import { useParams } from 'react-router-dom';
 import { MyLink } from './MyLink';
 import { ModalContainer } from './ModalContainer';
+import { CategoryBreadcrumbs } from './CategoryBreadcrumbs';
+import { LoadingState } from './LoadingState';
 
 
 export const ExpandMore = styled(props => {
@@ -45,7 +47,7 @@ const Good = ({ good, maxWidth = 'md', isAdmin, showAddToCard = true, actionAddG
     let [expanded, setExpanded] = useState(true);
     let [previewMedia, setPreviewMedia] = useState(false);
     const handleExpandClick = () => setExpanded(!expanded);
-
+    const currentCategory = good?.categories?.length > 0 ? good.categories[0] : undefined;
     return good && (
         <>
             {
@@ -62,6 +64,7 @@ const Good = ({ good, maxWidth = 'md', isAdmin, showAddToCard = true, actionAddG
                     <></>
             }
             <Container maxWidth={maxWidth}>
+                <CategoryBreadcrumbs category={currentCategory} showLeafAsLink={true} />
                 <Card variant='outlined'>
                     <Grid container spacing={maxWidth === 'xs' ? 7 : 5}>
                         <Grid item xs={1}>
@@ -152,7 +155,7 @@ const CGood = ({ good, maxWidth = 'md', showAddToCard = true, editable = true })
         good = isLoading ? { name: 'loading', goods: [] } : data?.GoodFindOne;
     let state = useSelector(state => state);
     let isAdmin = isCurrentUserAdmin(state);
-    return <Good good={good} isAdmin={isAdmin} maxWidth={maxWidth} showAddToCard={showAddToCard} editable={editable} actionAddGoodToCart={() => dispatch(actionAddGoodToCart(good))} />
+    return isLoading ? <LoadingState /> : <Good good={good} isAdmin={isAdmin} maxWidth={maxWidth} showAddToCard={showAddToCard} editable={editable} actionAddGoodToCart={() => dispatch(actionAddGoodToCart(good))} />
 }
 let a = '';
 export { CGood };

+ 2 - 1
src/Components/Order.js

@@ -11,6 +11,7 @@ import { getCurrentUser } from '../reducers';
 import { UserEntity } from '../Entities';
 import { LackPermissions } from './LackPermissions';
 import { fixBackendDataError } from '../utills';
+import { LoadingState } from './LoadingState';
 
 const Order = ({ order = {} }) => {
     return (
@@ -49,7 +50,7 @@ const COrder = () => {
         order ?
         <Order order={order} />
         :
-        getOrderById.isLoading ? <Typography>Loading...</Typography> : <LackPermissions name="order"/>
+        getOrderById.isLoading ? <LoadingState /> : <LackPermissions name="order"/>
         ;
 }
 

+ 0 - 45
src/reducers/BAK/cartGoodsReducer.js

@@ -1,45 +0,0 @@
-/*import { gqlGoodFind } from "../gql";
-import { actionClearCartData } from "./cartReducer";
-import { actionPromiseGeneric, createPromiseReducerSlice } from "./promiseReducer";
-
-let actionCartGoodsFindInt = (dispatch, goods) => {
-    return dispatch(
-        actionGetCartGoods({ _id: { "$in": goods.map(g => g._id) } }));
-}
-
-const goodsData = "goodsData";
-const actionGetCartGoods = (goodsQuery) => 
-    actionPromiseCartGoods(goodsData, gqlGoodFind(undefined, undefined, null, goodsQuery));
-
-let actionLoadCart = () =>
-    async (dispatch, getState) => {
-        let state = getState();
-        let goods = state.cart.goods;
-        if (goods?.length > 0)
-            actionCartGoodsFindInt(dispatch, goods);
-        else
-            dispatch(actionClearCartData());
-    }
-
-let getCartData = state => {
-    var cartData = state.cartData;
-    if (!cartData)
-        return [];
-    return cartData[goodsData]?.payload ?? [];
-}
-let clearCartData = state => {
-    let res = false;
-    let cartData = getCartData(state);
-    if (cartData?.length > 0) {
-        state.cartData = { [goodsData]: { payload: [] } };
-        res = true;
-    }
-    return res;
-}
-
-const cartGoodsReducerSlice = createPromiseReducerSlice('cartData');
-const actionPromiseCartGoods = (name, promise) =>
-    actionPromiseGeneric(cartGoodsReducerSlice, name, promise);
-let cartGoodsReducer = cartGoodsReducerSlice.reducer;
-export { cartGoodsReducer, actionLoadCart, getCartData, clearCartData }
-*/

+ 0 - 282
src/reducers/BAK/example.js

@@ -1,282 +0,0 @@
-import logo from './logo.svg';
-import {useEffect, useState} from 'react';
-import './App.css';
-import { configureStore, createSlice, createAsyncThunk } from '@reduxjs/toolkit';
-
-import {  createApi } from '@reduxjs/toolkit/query/react'
-import { gql } from 'graphql-request' //npm install
-import {graphqlRequestBaseQuery} from '@rtk-query/graphql-request-base-query' //npm install
-
-import {Provider, useDispatch, useSelector} from 'react-redux';
-
-import storage from "redux-persist/lib/storage";
-import { combineReducers } from "redux";
-
-import {persistReducer , persistStore, FLUSH,
-  REHYDRATE,
-  PAUSE,
-  PERSIST,
-  PURGE,
-  REGISTER,} from 'redux-persist';
-
-
-const prepareHeaders =  (headers, { getState }) => {
-    // By default, if we have a token in the store, let's use that for authenticated requests
-    const token = getState().auth.token;
-    if (token) {
-        headers.set("Authorization", `Bearer ${token}`);
-    }
-    return headers;
-}
-
-
-export const api = createApi({
-    //reducerPath: 'api',
-    baseQuery: graphqlRequestBaseQuery({
-        url: '/graphql', 
-        prepareHeaders
-    }),
-    endpoints: (builder) => ({
-        getRootCategories: builder.query({
-            query: () => ({
-                document: gql`
-                query GetCategories{
-                    CategoryFind(query: "[{\\"parent\\": null}]") {
-                        _id name
-                        }
-                    }
-                `}),
-        }),
-        getCategoryById: builder.query({
-            query: (_id) => ({
-                document: gql`
-                    query GetCategory($q: String) {
-                        CategoryFindOne(query: $q) {
-                            _id
-                            name
-                            goods{_id name images{url} price}
-                        }
-                    }
-                    `,
-                variables: {q: JSON.stringify([{_id}])}
-            }),
-        }),
-    }),
-})
-
-const { useGetRootCategoriesQuery, useGetCategoryByIdQuery } = api
-console.log(api)
-
-export const loginApi = createApi({
-    reducerPath: 'loginApi',
-    baseQuery: graphqlRequestBaseQuery({
-        url: '/graphql', 
-        prepareHeaders
-    }),
-    endpoints: (builder) => ({
-        login: builder.mutation({
-            query: ({login, password}) => ({
-                document: gql`
-                    query login($login: String, $password: String) {
-                        login(login: $login, password: $password) 
-                    }
-                    `,
-                variables: {login, password}})
-        }),
-        userFind: builder.query({
-            query: (_id) => ({
-                document: gql`
-                    query UserFind($q: String) {
-                        UserFindOne(query: $q){
-                            _id login nick avatar {url} createdAt
-                        } 
-                    }
-                    `,
-                variables: {q: JSON.stringify([{_id}])}
-            }),
-            providesTags: (result, error, id) =>  ( [{ type: 'User', id}])
-        }),
-        setNick: builder.mutation({
-            query: ({_id, nick}) => ({
-                document: gql`
-                    mutation SetNick($_id:String, $nick: String){
-                        UserUpsert(user: {_id: $_id, nick: $nick}){
-                            _id, nick
-                        }
-                    }
-                `,
-                variables: {_id, nick}
-            }),
-            invalidatesTags: (result, error, arg) => ([{type: 'User', id: arg._id}])
-        })
-    }),
-})
-
-const mySetNick = (_id, nick) =>
-    async (dispatch, getState) => {
-        await dispatch(actionUpdateUser({_id, nick}))
-        await dispatch(actionAboutMe())
-    }
-
-const {useLoginMutation, useUserFindQuery, useSetNickMutation} = loginApi
-
-const actionAboutMe = () => 
-    async (dispatch, getState) => {
-        const auth = getState().auth
-        if (auth.token){
-            dispatch(loginApi.endpoints.userFind.initiate(auth.payload.sub.id))
-        }
-    }
-
-function jwtDecode(token) {                         // расщифровки токена авторизации
-    if (!token || typeof token != "string")
-        return undefined;
-    let tokenArr = token.split(".");
-    if (tokenArr.length != 3)
-        return undefined;
-    try {
-        let tokenJsonStr = atob(tokenArr[1]);
-        let tokenJson = JSON.parse(tokenJsonStr);
-        return tokenJson;
-    }
-    catch (error) {
-        return undefined;
-    }
-}
-
-const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
-
-const authSlice = createSlice({
-    name: 'auth',
-    initialState: {},
-    reducers: {
-        logout(state){ //type - auth/logout
-            // state.token = undefined
-            return {}
-        }
-    },
-    extraReducers: builder => 
-        builder.addMatcher(loginApi.endpoints.login.matchFulfilled,
-                          (state, {payload}) => {
-                              const tokenPayload = jwtDecode(payload.login)
-                              if (tokenPayload){
-                                  state.token = payload.login
-                                  state.payload = tokenPayload
-                              }
-                          })    
-})
-
-const {logout: actionLogout} = authSlice.actions
-
-const rootReducer = combineReducers({ //combineReducers(
-        auth: persistReducer({key: 'auth', storage}, authSlice.reducer),
-        [api.reducerPath]:api.reducer,
-        [loginApi.reducerPath]:loginApi.reducer
-})
-
-// const persistedReducer = 
-
-const store = configureStore({
-    middleware: (getDefaultMiddleware) => [
-        ...getDefaultMiddleware({serializableCheck: {ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER]}}),
-            api.middleware,
-            loginApi.middleware],
-    reducer: rootReducer
-})
-
-const persistor = persistStore(store)
-
-store.subscribe(() => console.log(store.getState()))
-
-const LoginStub = () => {
-    const [login, {data, isLoading}] = useLoginMutation()
-    const dispatch = useDispatch()
-    useEffect(() => {
-        login({login: 'admin', password: '123123'}).then(() => dispatch(actionAboutMe()))
-    },[])
-    
-    const myId = useSelector(state => state?.auth?.payload?.sub?.id)
-    const {data: aboutMeData} = useUserFindQuery(myId)
-
-    // setTimeout(() => login('admin', '123123'), 2000)
-    console.log(data, aboutMeData)
-    return (
-         <div>{isLoading ? 'грузим' : 'не грузим'}&nbsp;
-             {aboutMeData?.UserFindOne?.login} 
-             {aboutMeData?.UserFindOne?.nick} 
-         </div>   
-    )
-}
-
-const actionSetNick = (nick) => 
-    async (dispatch, getState) => {
-        const auth = getState().auth
-        if (auth.token){
-            dispatch(loginApi.endpoints.setNick.initiate({_id: auth.payload.sub.id, nick}))
-        }
-    }
-
-const SetNick = () => {
-    const [nick, setNickState] = useState('')
-    const dispatch = useDispatch()
-    return (
-        <div>
-            <input value={nick} onChange={e => setNickState(e.target.value)}/>
-            <button onClick={() => dispatch(actionSetNick(nick))}>Save</button>
-        </div>
-    )
-}
-
-const Aside = () => {
-
-    
-    const allCatsHookResult = useGetRootCategoriesQuery()
-    const {isLoading, data}       = allCatsHookResult
-    console.log(allCatsHookResult)
-    return (
-        <aside>
-            {isLoading && <strong>Loading...</strong>}
-            {data && data.CategoryFind && data.CategoryFind.map(cat => <div key={cat._id}>{cat.name}</div>)}
-        </aside>
-    )
-}
-
-const OneCat = () => {
-    const oneCatHookResult  = useGetCategoryByIdQuery("62c94990b74e1f5f2ec1a0dc")
-    const {isLoading, data}       = oneCatHookResult
-    console.log(oneCatHookResult)
-    return (
-        <div>
-            {isLoading && <strong>Loading...</strong>}
-            {data && data.CategoryFindOne && 
-                <>
-                    <h1>{data.CategoryFindOne.name}</h1>
-                    {data.CategoryFindOne.goods && data.CategoryFindOne.goods.map(good => <div key={good._id}>{good.name}</div>)}
-                </>}
-        </div>
-    )
-}
-
-const LogoutButton = () => {
-    const dispatch = useDispatch()
-    return (
-        <button onClick={() => dispatch(actionLogout())}>Logout</button>
-    )
-}
-
-function App() {
-
-    return (
-        <Provider store={store}>
-            <div className="App">
-                <LogoutButton />
-                <LoginStub />
-                <SetNick />
-                <Aside />
-                <OneCat />
-            </div>
-        </Provider>
-    );
-}
-
-export default App;