Explorar el Código

+goods orderBy

ilya_shyian hace 2 años
padre
commit
9e3e4a5c7a

+ 2 - 2
src/actions/actionCatById.js

@@ -2,10 +2,10 @@ import { mock, query } from '../helpers';
 
 import { actionPromise } from '../reducers';
 
-export const actionCatById = ({ _id, promiseName = 'catById' }) =>
+export const actionCatById = ({ _id, promiseName = 'catById', orderBy = '', limit = 20, skip = 0 }) =>
     actionPromise(
         promiseName,
-        fetch(`/categories/${_id}/`, {
+        fetch(`/categories/${_id}/?limit=${limit}&skip=${skip}${orderBy && `&orderBy=` + orderBy}`, {
             method: 'GET',
             headers: {
                 'Content-Type': 'application/json',

+ 15 - 5
src/components/GoodsPage/index.js

@@ -1,21 +1,31 @@
 import { Grid, Stack, Typography, Divider } from '@mui/material';
 import { Box } from '@mui/system';
-import { connect } from 'react-redux';
+import { connect, useDispatch } from 'react-redux';
 import { useParams } from 'react-router-dom';
 import { GoodCard } from '../common/GoodCard';
 import { GoodList } from '../common/GoodList';
 import { SubCategories } from './SubCategories';
+import { SortOptions } from '../common/SortOptions';
+import { actionCatById } from '../../actions/actionCatById';
 
 const GoodsPage = ({ category = {} }) => {
     const { goods = [], name = '', subcategories = [] } = category || {};
-
+    const dispatch = useDispatch();
     return (
         <Box className="GoodsPage">
-            <Typography variant="h5" textAlign="center">
-                {name}
-            </Typography>
+            <Box>
+                <Typography variant="h5" textAlign="center">
+                    {name}
+                </Typography>
+            </Box>
+
             <Divider className="Divider" />
             <Stack>
+                <Box className="sortOptionsWrapper">
+                    <SortOptions
+                        onClick={(option) => dispatch(actionCatById({ _id: category._id, orderBy: option.value }))}
+                    />
+                </Box>
                 {!!subcategories.length ? (
                     <Box>
                         <Typography variant="h6" color="#79747E" textAlign="left">

+ 0 - 1
src/components/admin/AdminCategoriesPage/AdminCategoryList.js

@@ -18,7 +18,6 @@ const CSearchResults = connect((state) => ({ items: state.promise.adminCatsFind?
 const AdminCategoryList = ({ categories, orderBy = '_id' } = {}) => {
     const navigate = useNavigate();
     const location = useLocation();
-    console.log(orderBy);
 
     return (
         <Box className="AdminCategoryList">

+ 20 - 5
src/components/admin/AdminCategoriesPage/AdminCategoryListHeader.js

@@ -6,7 +6,7 @@ import { useNavigate } from 'react-router-dom';
 
 const AdminCategoryListHeader = ({ sort, onSortChange }) => {
     const navigate = useNavigate();
-    console.log(sort);
+
     return (
         <TableRow className="AdminCategoryListHeader">
             <TableCell scope="col">
@@ -15,12 +15,27 @@ const AdminCategoryListHeader = ({ sort, onSortChange }) => {
                     direction={sort === '_id' ? 'asc' : 'desc'}
                     onClick={() => onSortChange(sort === '_id' ? '-_id' : '_id')}
                 >
-                    NAME
+                    #
+                </TableSortLabel>
+            </TableCell>
+            <TableCell scope="col">
+                <TableSortLabel
+                    active={sort === 'name' || sort === '-name'}
+                    direction={sort === 'name' ? 'asc' : 'desc'}
+                    onClick={() => onSortChange(sort === 'name' ? '-name' : 'name')}
+                >
+                    Назва
+                </TableSortLabel>
+            </TableCell>
+            <TableCell scope="col">
+                <TableSortLabel
+                    active={sort === 'parent' || sort === '-parent'}
+                    direction={sort === 'parent' ? 'asc' : 'desc'}
+                    onClick={() => onSortChange(sort === 'parent' ? '-parent' : 'parent')}
+                >
+                    Батьківська категорія
                 </TableSortLabel>
-                #
             </TableCell>
-            <TableCell scope="col">Название</TableCell>
-            <TableCell scope="col">Родительская категория</TableCell>
             <TableCell scope="col">
                 <AddButton
                     onClick={() => {

+ 16 - 2
src/components/admin/AdminGoodsPage/AdminGoodList.js

@@ -7,6 +7,7 @@ import { SearchBar, SearchResults } from '../../common/SearchBar';
 import { actionGoodsFind } from '../../../actions/actionGoodsFind';
 import { actionPromiseClear } from '../../../reducers';
 import { Box, Table, TableBody, TableHead } from '@mui/material';
+import { createSearchParams, useLocation, useNavigate } from 'react-router-dom';
 
 const CSearchBar = connect(null, {
     onSearch: (text) => actionGoodsFind({ promiseName: 'adminGoodsFind', text, limit: 5 }),
@@ -15,7 +16,10 @@ const CSearchBar = connect(null, {
 
 const CSearchResults = connect((state) => ({ items: state.promise.adminGoodsFind?.payload || [] }))(SearchResults);
 
-const AdminGoodList = ({ goods }) => {
+const AdminGoodList = ({ goods, orderBy = '_id' }) => {
+    const navigate = useNavigate();
+    const location = useLocation();
+
     return (
         <Box className="AdminGoodList">
             <Box className="searchBarWrapper">
@@ -27,7 +31,17 @@ const AdminGoodList = ({ goods }) => {
             </Box>
             <Table>
                 <TableHead>
-                    <AdminGoodListHeader />
+                    <AdminGoodListHeader
+                        sort={orderBy}
+                        onSortChange={(orderBy) => {
+                            navigate({
+                                pathname: location.pathname,
+                                search: createSearchParams({
+                                    orderBy,
+                                }).toString(),
+                            });
+                        }}
+                    />
                 </TableHead>
                 <TableBody>
                     {(goods || []).map((good) => (

+ 38 - 5
src/components/admin/AdminGoodsPage/AdminGoodListHeader.js

@@ -4,15 +4,48 @@ import { AddButton } from '../../common/AddButton';
 import { TableCell, TableRow, TableSortLabel } from '@mui/material';
 import { useNavigate } from 'react-router-dom';
 
-const AdminGoodListHeader = ({ onSortChange, sort, sortReversed, onSortReverseChange }) => {
+const AdminGoodListHeader = ({ onSortChange, sort }) => {
     const navigate = useNavigate();
+    console.log(sort);
     return (
         <TableRow className="AdminGoodListHeader">
-            <TableCell scope="col">#</TableCell>
-            <TableCell scope="col">Назва</TableCell>
+            <TableCell scope="col">
+                <TableSortLabel
+                    active={sort === '_id' || sort === '-_id'}
+                    direction={sort === '_id' ? 'asc' : 'desc'}
+                    onClick={() => onSortChange(sort === '_id' ? '-_id' : '_id')}
+                >
+                    #
+                </TableSortLabel>
+            </TableCell>
+            <TableCell scope="col">
+                <TableSortLabel
+                    active={sort === 'name' || sort === '-name'}
+                    direction={sort === 'name' ? 'asc' : 'desc'}
+                    onClick={() => onSortChange(sort === 'name' ? '-name' : 'name')}
+                >
+                    Назва
+                </TableSortLabel>
+            </TableCell>
             <TableCell scope="col">Зображення</TableCell>
-            <TableCell scope="col">Ціна</TableCell>
-            <TableCell scope="col">Кількість</TableCell>
+            <TableCell scope="col">
+                <TableSortLabel
+                    active={sort === 'price' || sort === '-price'}
+                    direction={sort === 'price' ? 'asc' : 'desc'}
+                    onClick={() => onSortChange(sort === 'price' ? '-price' : 'price')}
+                >
+                    Ціна
+                </TableSortLabel>
+            </TableCell>
+            <TableCell scope="col">
+                <TableSortLabel
+                    active={sort === 'amount' || sort === '-amount'}
+                    direction={sort === 'amount' ? 'asc' : 'desc'}
+                    onClick={() => onSortChange(sort === 'amount' ? '-amount' : 'amount')}
+                >
+                    Кількість
+                </TableSortLabel>
+            </TableCell>
             <TableCell scope="col">Категорії</TableCell>
             <TableCell scope="col">
                 <AddButton

+ 2 - 2
src/components/admin/AdminGoodsPage/index.js

@@ -1,13 +1,13 @@
 import { Box, Typography } from '@mui/material';
 import { AdminGoodList, CAdminGoodList } from './AdminGoodList';
 
-export const AdminGoodsPage = () => {
+export const AdminGoodsPage = ({ orderBy }) => {
     return (
         <Box className="AdminGoodsPage">
             <Typography variant="h5" sx={{ marginBottom: '10px', marginTop: '10px' }}>
                 Товари
             </Typography>
-            <CAdminGoodList />
+            <CAdminGoodList orderBy={orderBy} />
         </Box>
     );
 };

+ 18 - 4
src/components/admin/AdminLayoutPage/index.js

@@ -52,7 +52,7 @@ const AdminCategoriesPageContainer = ({ cats }) => {
                     promise: { feedCatAll },
                 } = store.getState();
                 if (feedCatAll.status !== 'PENDING') {
-                    dispatch(actionFeedCats(feed.payload?.length || 0));
+                    dispatch(actionFeedCats(feed.payload?.length || 0, orderBy));
                 }
             }
         };
@@ -90,6 +90,13 @@ const AdminGoodsPageContainer = ({ goods }) => {
     const [searchParams] = useSearchParams();
     const orderBy = searchParams.get('orderBy') || '_id';
 
+    useEffect(() => {
+        dispatch(actionFeedClear());
+        dispatch(actionPromiseClear('feedGoodsAll'));
+        dispatch(actionPromiseClear('goodUpsert'));
+        dispatch(actionFeedGoods({ skip: 0, orderBy }));
+    }, [orderBy]);
+
     useEffect(() => {
         dispatch(actionFeedGoods({ skip: goods?.length || 0, orderBy }));
         window.onscroll = (e) => {
@@ -115,14 +122,21 @@ const AdminGoodsPageContainer = ({ goods }) => {
     useEffect(() => {
         if (goods?.length) store.dispatch(actionFeedAdd(goods));
     }, [goods]);
-    return <AdminGoodsPage />;
+    return <AdminGoodsPage orderBy={orderBy} />;
 };
 
 const AdminOrdersPageContainer = ({ orders }) => {
+    const dispatch = useDispatch();
     const [searchParams] = useSearchParams();
     const orderBy = searchParams.get('orderBy') || '_id';
 
-    const dispatch = useDispatch();
+    useEffect(() => {
+        dispatch(actionFeedClear());
+        dispatch(actionPromiseClear('feedOrdersAll'));
+        dispatch(actionPromiseClear('orderUpsert'));
+        dispatch(actionFeedOrders({ skip: 0, orderBy }));
+    }, [orderBy]);
+
     useEffect(() => {
         dispatch(actionFeedOrders({ skip: orders?.length || 0, orderBy }));
         window.onscroll = (e) => {
@@ -148,7 +162,7 @@ const AdminOrdersPageContainer = ({ orders }) => {
     useEffect(() => {
         if (orders?.length) store.dispatch(actionFeedAdd(orders));
     }, [orders]);
-    return <AdminOrdersPage />;
+    return <AdminOrdersPage orderBy={orderBy} />;
 };
 
 const AdminOrderPageContainer = () => {

+ 16 - 2
src/components/admin/AdminOrdersPage/AdminOrderList.js

@@ -6,6 +6,7 @@ import { actionOrdersFind } from '../../../actions/actionOrdersFind';
 import { actionPromiseClear } from '../../../reducers';
 import { Box, Table, TableBody, TableHead } from '@mui/material';
 import { AdminOrderItem } from './AdminOrderItem';
+import { createSearchParams, useLocation, useNavigate } from 'react-router-dom';
 
 const CSearchBar = connect(null, {
     onSearch: (text) => actionOrdersFind({ promiseName: 'adminOrdersFind', text, limit: 5 }),
@@ -14,7 +15,10 @@ const CSearchBar = connect(null, {
 
 const CSearchResults = connect((state) => ({ items: state.promise.adminOrdersFind?.payload || [] }))(SearchResults);
 
-const AdminOrderList = ({ orders }) => {
+const AdminOrderList = ({ orders, orderBy = '_id' }) => {
+    const navigate = useNavigate();
+    const location = useLocation();
+
     return (
         <Box className="AdminOrderList">
             <Box className="searchBarWrapper">
@@ -26,7 +30,17 @@ const AdminOrderList = ({ orders }) => {
             </Box>
             <Table>
                 <TableHead>
-                    <AdminOrderListHeader />
+                    <AdminOrderListHeader
+                        sort={orderBy}
+                        onSortChange={(orderBy) => {
+                            navigate({
+                                pathname: location.pathname,
+                                search: createSearchParams({
+                                    orderBy,
+                                }).toString(),
+                            });
+                        }}
+                    />
                 </TableHead>
                 <TableBody>
                     {(orders || []).map((order) => (

+ 28 - 4
src/components/admin/AdminOrdersPage/AdminOrderListHeader.js

@@ -4,16 +4,40 @@ import { AddButton } from '../../common/AddButton';
 import { TableCell, TableRow, TableSortLabel } from '@mui/material';
 import { useNavigate } from 'react-router-dom';
 
-const AdminOrderListHeader = ({ onSortChange, sort, sortReversed, onSortReverseChange }) => {
+const AdminOrderListHeader = ({ onSortChange, sort }) => {
     const navigate = useNavigate();
     return (
         <TableRow className="AdminOrderListHeader">
-            <TableCell scope="col">#</TableCell>
+            <TableCell scope="col">
+                <TableSortLabel
+                    active={sort === '_id' || sort === '-_id'}
+                    direction={sort === '_id' ? 'asc' : 'desc'}
+                    onClick={() => onSortChange(sort === '_id' ? '-_id' : '_id')}
+                >
+                    #
+                </TableSortLabel>
+            </TableCell>
             <TableCell scope="col">Email</TableCell>
             <TableCell scope="col">Номер</TableCell>
             <TableCell scope="col">Товари</TableCell>
-            <TableCell scope="col">Ціна</TableCell>
-            <TableCell scope="col">Статус</TableCell>
+            <TableCell scope="col">
+                <TableSortLabel
+                    active={sort === 'price' || sort === '-price'}
+                    direction={sort === 'price' ? 'asc' : 'desc'}
+                    onClick={() => onSortChange(sort === 'price' ? '-price' : 'price')}
+                >
+                    Ціна
+                </TableSortLabel>
+            </TableCell>
+            <TableCell scope="col">
+                <TableSortLabel
+                    active={sort === 'status' || sort === '-status'}
+                    direction={sort === 'status' ? 'asc' : 'desc'}
+                    onClick={() => onSortChange(sort === 'status' ? '-status' : 'status')}
+                >
+                    Статус
+                </TableSortLabel>
+            </TableCell>
             <TableCell scope="col">
                 <AddButton
                     onClick={() => {

+ 2 - 2
src/components/admin/AdminOrdersPage/index.js

@@ -1,13 +1,13 @@
 import { Box, Typography } from '@mui/material';
 import { CAdminOrderList } from './AdminOrderList';
 
-export const AdminOrdersPage = () => {
+export const AdminOrdersPage = ({ orderBy }) => {
     return (
         <Box className="AdminOrdersPage">
             <Typography variant="h5" sx={{ marginBottom: '10px', marginTop: '10px' }}>
                 Замовлення
             </Typography>
-            <CAdminOrderList />
+            <CAdminOrderList orderBy={orderBy} />
         </Box>
     );
 };

+ 58 - 0
src/components/common/SortOptions/index.js

@@ -0,0 +1,58 @@
+import { Box, Button, Menu, MenuItem } from '@mui/material';
+import { useEffect, useState } from 'react';
+import { sortOptions } from '../../../helpers/sortOptions';
+
+export const SortOptions = ({ onClick, options = sortOptions || [] } = {}) => {
+    const [anchorEl, setAnchorEl] = useState(null);
+    const [selectedOption, setSelectedOption] = useState(options[0] || null);
+    const open = Boolean(anchorEl);
+    const handleClick = (event) => {
+        setAnchorEl(event.currentTarget);
+    };
+
+    const handleSelect = (option) => {
+        option && setSelectedOption(option);
+        setAnchorEl(null);
+    };
+
+    useEffect(() => {
+        if (selectedOption) {
+            onClick(selectedOption);
+        }
+    }, [selectedOption]);
+
+    return (
+        <Box className="SortOptions">
+            <Button
+                id="demo-positioned-button"
+                aria-controls={open ? 'demo-positioned-menu' : undefined}
+                aria-haspopup="true"
+                aria-expanded={open ? 'true' : undefined}
+                onClick={handleClick}
+            >
+                {selectedOption.label}
+            </Button>
+            <Menu
+                id="demo-positioned-menu"
+                aria-labelledby="demo-positioned-button"
+                anchorEl={anchorEl}
+                open={open}
+                onClose={() => setAnchorEl(null)}
+                anchorOrigin={{
+                    vertical: 'top',
+                    horizontal: 'left',
+                }}
+                transformOrigin={{
+                    vertical: 'top',
+                    horizontal: 'left',
+                }}
+            >
+                {(options || []).map((option) => (
+                    <MenuItem key={option.value} onClick={(e) => handleSelect(option)}>
+                        {option.label}
+                    </MenuItem>
+                ))}
+            </Menu>
+        </Box>
+    );
+};

+ 18 - 0
src/helpers/sortOptions.js

@@ -0,0 +1,18 @@
+export const sortOptions = [
+    {
+        value: 'date',
+        label: 'Спочатку нові',
+    },
+    {
+        value: '-date',
+        label: 'Спочатку старі',
+    },
+    {
+        value: 'price',
+        label: 'Від дешевих до дорогих',
+    },
+    {
+        value: '-price',
+        label: 'Від дорогих до дешевих',
+    },
+];

+ 6 - 0
src/index.scss

@@ -305,6 +305,12 @@
 
     & .GoodsPage{
       padding:10px;
+      & .sortOptionsWrapper{
+        display: flex;
+        justify-content: right;
+        padding-right: 15px;
+
+      }
       & .Divider{
         margin-top: 10px;
         margin-bottom: 10px;