Changeset a2e5735


Ignore:
Timestamp:
12/13/22 22:38:11 (17 months ago)
Author:
Nace Gjorgjievski <nace.gorgievski123@…>
Branches:
master
Parents:
113029b
Message:

Final Version

Files:
19 added
12 edited

Legend:

Unmodified
Added
Removed
  • backend/models/productModel.js

    r113029b ra2e5735  
    55    name: { type: String, required: true, unique: true },
    66    slug: { type: String, required: true, unique: true },
     7    height: { type: Number, required: true },
     8    width: { type: Number, required: true },
     9    length: { type: Number, required: true },
    710    image: { type: String, required: true },
    811    sideImage: { type: String, required: true },
  • backend/routes/productRoutes.js

    r113029b ra2e5735  
    4242      priceMontaza: req.body.priceMontaza,
    4343      countInStock: req.body.countInStock,
     44      height: req.body.H,
     45      width: req.body.W,
     46      length: req.body.L,
    4447    });
    4548
     
    5255
    5356const PAGE_SIZE = 7;
     57
     58productRouter.get(
     59  "/search",
     60  expressAsyncHandler(async (req, res) => {
     61    const { query } = req;
     62    const pageSize = query.pageSize || PAGE_SIZE;
     63    const page = query.page || 1;
     64    const searchQuery = query.text;
     65    console.log("HEEEY: " + searchQuery);
     66    const queryFilter =
     67      searchQuery && searchQuery !== "all"
     68        ? { name: { $regex: searchQuery, $options: "i" } }
     69        : {};
     70    const descriptionFilter =
     71      searchQuery && searchQuery !== "all"
     72        ? { description: { $regex: searchQuery, $options: "i" } }
     73        : {};
     74    const slug =
     75      searchQuery && searchQuery !== "all"
     76        ? { slug: { $regex: searchQuery, $options: "i" } }
     77        : {};
     78    const products = await Product.find({
     79      $or: [
     80        { name: { $regex: searchQuery, $options: "i" } },
     81        { slug: { $regex: searchQuery, $options: "i" } },
     82        { description: { $regex: searchQuery, $options: "i" } },
     83      ],
     84    })
     85      .skip(pageSize * (page - 1))
     86      .limit(pageSize);
     87    const countProducts = await Product.countDocuments({
     88      $or: [
     89        { name: { $regex: searchQuery, $options: "i" } },
     90        { slug: { $regex: searchQuery, $options: "i" } },
     91        { description: { $regex: searchQuery, $options: "i" } },
     92      ],
     93    });
     94    res.send({
     95      products,
     96      countProducts,
     97      page,
     98      pages: Math.ceil(countProducts / pageSize),
     99    });
     100  })
     101);
     102
    54103productRouter.get(
    55104  "/",
     
    62111    const order = query.order || "";
    63112    const searchQuery = query.query || "";
     113    const HF = query.HF || 0;
     114    const HT = query.HT || 1000;
     115    const WF = query.WF || 0;
     116    const WT = query.WT || 1000;
     117    const LF = query.LF || 0;
     118    const LT = query.LT || 1000;
    64119
    65120    const queryFilter =
     
    80135      ...categoryFilter,
    81136      ...subCategoryFilter,
     137      $and: [
     138        { height: { $gte: HF } },
     139        { height: { $lte: HT } },
     140        { width: { $gte: WF } },
     141        { width: { $lte: WT } },
     142        { length: { $gte: LF } },
     143        { length: { $lte: LT } },
     144      ],
    82145    })
    83146      .sort(sortOrder)
  • backend/server.js

    r113029b ra2e5735  
    77import userRouter from "./routes/userRoutes.js";
    88import orderRouter from "./routes/orderRoutes.js";
     9import categoryRouter from "./routes/categoryRoutes.js";
    910
    1011dotenv.config();
     
    2829app.use("/api/users", userRouter);
    2930app.use("/api/orders", orderRouter);
     31app.use("/api/category", categoryRouter);
    3032
    3133app.use((err, req, res, next) => {
  • frontend/src/App.js

    r113029b ra2e5735  
    2828import AdminOrdersScreen from "./screens/AdminOrdersScreen";
    2929import AdminOrderScreen from "./screens/AdminOrderScreen";
     30import AdminAddCategoryScreen from "./screens/AdminAddCategoryScreen";
     31import SearchScreen from "./screens/SearchScreen";
    3032function App() {
    3133  const { state } = useContext(Store);
     
    5456          element={<CategoryScreen />}
    5557        />
     58        <Route path="/products/search" element={<SearchScreen />} />
    5659        <Route path="/admin/dashboard" element={<AdminDashboardScreen />} />
    5760        <Route path="/admin/addProduct" element={<AdminAddProductScreen />} />
     61        <Route
     62          path="/admin/addCategory"
     63          element={<AdminAddCategoryScreen />}
     64        ></Route>
    5865        <Route path="/admin/products" element={<AdminProductsScreen />} />
    5966        <Route path="/admin/orders" element={<AdminOrdersScreen />} />
  • frontend/src/components/Header.js

    r113029b ra2e5735  
    1 import React from "react";
     1import React, { useEffect, useState } from "react";
    22import logo from "../Images/logo.png";
    33import "../styles/Header.css";
     
    2424import NavDropdown from "react-bootstrap/NavDropdown";
    2525import { height } from "@mui/system";
     26import Axios from "axios";
     27import CategoryMenu from "./CategoryMenu";
    2628
    2729const toggleMenu = (event) => {
     
    7678  const navigate = useNavigate();
    7779
     80  const [categories, setCategories] = useState([]);
     81  //const []
     82
    7883  const signoutHandler = () => {
    7984    ctxDispatch({ type: "USER_SIGNOUT" });
     
    8388    window.location.href = "/signin";
    8489  };
     90
     91  const searchHandler = () => {
     92    let text = document.querySelector(".header__searchInput").value;
     93    console.log(text);
     94    navigate(`/products/search?text=${text}`);
     95  };
     96
     97  useEffect(() => {
     98    const fetchData = async () => {
     99      const cat = await Axios.get(`/api/category/getCategories`);
     100      categories.splice(0, categories.length);
     101      for (let i = 0; i < cat.data.length; i++) {
     102        categories.push(cat.data[i]);
     103      }
     104      console.log(categories[0]);
     105    };
     106    fetchData();
     107  }, [categories]);
     108  const results = [];
     109  const results1 = [];
     110  const results2 = [];
     111  const results3 = [];
     112  if (categories) createMenu(categories);
     113  function createMenu(categories) {
     114    /*
     115    let ul = document.getElementById("category-ul-1");
     116    for(let i=0;i<categories.length;i++){
     117      ul.appendChild()
     118    }*/
     119    results.splice(0, results.length);
     120    categories.forEach((category) => {
     121      results.push(<CategoryMenu category={category} />);
     122    });
     123    for (let i = 0; i < categories.length; i++) {
     124      if (i < 3) {
     125        results1.push(<CategoryMenu category={categories[i]} />);
     126      } else if (i < 5) {
     127        results2.push(<CategoryMenu category={categories[i]} />);
     128      } else {
     129        results3.push(<CategoryMenu category={categories[i]} />);
     130      }
     131    }
     132    console.log("Results:");
     133    console.log(categories);
     134  }
    85135
    86136  return (
     
    839889          <div className="header__dropdown">
    840890            <div className="header__dropdownColumn">
    841               <ul>
     891              <ul id="category-ul-1">
     892                <li>{categories[0] && results1}</li>
     893                {/*
    842894                <li>
    843895                  <Link to="/products/dnevna/all">
     
    916968                    </li>
    917969                  </ul>
    918                 </li>
     970                        </li>*/}
    919971              </ul>
    920972            </div>
    921973            <div className="header__dropdownColumn">
    922974              <ul>
     975                <li>{categories[0] && results2}</li>
     976                {/*
    923977                <li>
    924978                  <Link to="/products/spalna/all">
     
    9981052                  </ul>
    9991053                </li>
     1054                      */}
    10001055              </ul>
    10011056            </div>
    10021057            <div className="header__dropdownColumn">
    10031058              <ul>
     1059                <li>{categories[0] && results3}</li>
     1060                {/*
    10041061                <li>
    10051062                  <Link to="/products/kancelarija/all">
     
    10831140                  </ul>
    10841141                </li>
     1142                */}
    10851143              </ul>
    10861144            </div>
     
    12011259        </div>
    12021260        <div className="header__search">
    1203           <input className="header__searchInput" type="text" />
    1204           <SearchIcon className="header__searchIcon" fontSize="large" />
     1261          <input className="header__searchInput" type="text" name="text" />
     1262          <button onClick={searchHandler}>
     1263            <SearchIcon className="header__searchIcon" fontSize="large" />
     1264          </button>
    12051265        </div>
    12061266      </div>
  • frontend/src/components/Product.js

    r113029b ra2e5735  
    5454      <div
    5555        style={{
    56           width: "100%",
    5756          display: "flex",
    58           justifyContent: "center",
     57          justifyContent: "space-around",
    5958          alignItems: "center",
    6059        }}
    6160      >
    62         {product.countInStock > 0 ? (
    63           <span style={{ color: "green" }}>
    64             <CheckIcon></CheckIcon>Залиха
    65           </span>
    66         ) : (
    67           <span style={{ color: "red" }}>
    68             <ClearIcon></ClearIcon>Залиха
    69           </span>
    70         )}
     61        <h5>H: {product.height}</h5>
     62        <h5>W: {product.width}</h5>
     63        <h5>L: {product.length}</h5>
    7164      </div>
    72       <div className="product__addToCart" style={{ marginTop: "15px" }}>
     65      <div
     66        className="product__addToCart"
     67        style={{ marginTop: "15px", display: "flex", justifyContent: "center" }}
     68      >
    7369        <button onClick={addToCartHandler}>
    7470          <ShoppingBasketIcon />
    7571        </button>
     72        <div
     73          style={{
     74            //width: "100%",
     75            display: "flex",
     76            justifyContent: "center",
     77            alignItems: "center",
     78            marginLeft: "10px",
     79          }}
     80        >
     81          {product.countInStock > 0 ? (
     82            <span style={{ color: "green" }}>
     83              <CheckIcon></CheckIcon>Залиха
     84            </span>
     85          ) : (
     86            <span style={{ color: "red" }}>
     87              <ClearIcon></ClearIcon>Залиха
     88            </span>
     89          )}
     90        </div>
    7691      </div>
    7792    </div>
  • frontend/src/screens/AdminAddProductScreen.js

    r113029b ra2e5735  
    2020  const [dimension, setDimension] = useState("");
    2121  const [scheme, setScheme] = useState("");
     22  const [H, setH] = useState("");
     23  const [W, setW] = useState("");
     24  const [L, setL] = useState("");
    2225  const [message, setMessage] = useState("");
    2326
     
    5659    formData.append("dimension", dimension);
    5760    formData.append("scheme", scheme);
    58 
     61    formData.append("H", H);
     62    formData.append("W", W);
     63    formData.append("L", L);
    5964    try {
    6065      const result = await axios.post("/api/products/add", formData);
     
    7681            Додади нов производ
    7782          </div>
     83        </Link>
     84        <Link
     85          to={"/admin/addCategory"}
     86          style={{ textDecoration: "none", width: "100%" }}
     87        >
     88          <div className="dashboard-btn">Додади категорија</div>
    7889        </Link>
    7990        <Link
     
    351362              </div>
    352363              <div>
     364                <Form.Group
     365                  style={{ display: "flex", justifyContent: "space-around" }}
     366                >
     367                  <div
     368                    style={{
     369                      display: "flex",
     370                      flexDirection: "row",
     371                      alignItems: "center",
     372                    }}
     373                  >
     374                    <Form.Label>H:</Form.Label>
     375                    <Form.Control
     376                      type="text"
     377                      name="dimension"
     378                      style={{ width: "60px" }}
     379                      value={H}
     380                      onChange={(e) => setH(e.target.value)}
     381                      required
     382                    ></Form.Control>
     383                  </div>
     384                  <div
     385                    style={{
     386                      display: "flex",
     387                      flexDirection: "row",
     388                      alignItems: "center",
     389                    }}
     390                  >
     391                    <Form.Label>W:</Form.Label>
     392                    <Form.Control
     393                      type="text"
     394                      name="dimension"
     395                      value={W}
     396                      onChange={(e) => setW(e.target.value)}
     397                      style={{ width: "60px" }}
     398                      required
     399                    ></Form.Control>
     400                  </div>
     401                  <div
     402                    style={{
     403                      display: "flex",
     404                      flexDirection: "row",
     405                      alignItems: "center",
     406                    }}
     407                  >
     408                    <Form.Label>L:</Form.Label>
     409                    <Form.Control
     410                      type="text"
     411                      name="dimension"
     412                      style={{ width: "60px" }}
     413                      value={L}
     414                      onChange={(e) => setL(e.target.value)}
     415                      required
     416                    ></Form.Control>
     417                  </div>
     418                </Form.Group>
    353419                <Form.Group>
    354420                  <Form.Label>Слика со димензии</Form.Label>
  • frontend/src/screens/AdminDashboardScreen.js

    r113029b ra2e5735  
    66import { useNavigate, Link } from "react-router-dom";
    77import ListProducts from "../components/ListProducts";
     8import { Helmet } from "react-helmet-async";
    89
    910function AdminDashboardScreen() {
     
    1920  return (
    2021    <div id="pgContainer">
     22      <Helmet>
     23        <title>Dashboard</title>
     24      </Helmet>
    2125      <div id="sidebarMenu">
    2226        <Link
     
    2731            Додади нов производ
    2832          </div>
     33        </Link>
     34        <Link
     35          to={"/admin/addCategory"}
     36          style={{ textDecoration: "none", width: "100%" }}
     37        >
     38          <div className="dashboard-btn">Додади категорија</div>
    2939        </Link>
    3040        <Link
  • frontend/src/screens/AdminEditProductScreen.js

    r113029b ra2e5735  
    8383            Додади нов производ
    8484          </div>
     85        </Link>
     86        <Link
     87          to={"/admin/addCategory"}
     88          style={{ textDecoration: "none", width: "100%" }}
     89        >
     90          <div className="dashboard-btn">Додади категорија</div>
    8591        </Link>
    8692        <Link
  • frontend/src/screens/AdminOrdersScreen.js

    r113029b ra2e5735  
    8282            Додади нов производ
    8383          </div>
     84        </Link>
     85        <Link
     86          to={"/admin/addCategory"}
     87          style={{ textDecoration: "none", width: "100%" }}
     88        >
     89          <div className="dashboard-btn">Додади категорија</div>
    8490        </Link>
    8591        <Link
  • frontend/src/screens/AdminProductsScreen.js

    r113029b ra2e5735  
    9696                Додади нов производ
    9797              </div>
     98            </Link>
     99            <Link
     100              to={"/admin/addCategory"}
     101              style={{ textDecoration: "none", width: "100%" }}
     102            >
     103              <div className="dashboard-btn">Додади категорија</div>
    98104            </Link>
    99105            <Link
  • frontend/src/screens/CategoryScreen.js

    r113029b ra2e5735  
    1 import React, { useEffect, useReducer } from "react";
     1import React, { useEffect, useReducer, useState } from "react";
    22import "../styles/Home.css";
    33// import data from "./data";
     
    3434  const params = useParams();
    3535  const { category, subCategory } = params;
     36  var HF = 0;
     37  var HT = 1000;
     38  var WF = 0;
     39  var WT = 1000;
     40  var LF = 0;
     41  var LT = 1000;
     42  //const [HT, setHT] = useState(1000);
     43  //const [WF, setWF] = useState(0);
     44  //const [WT, setWT] = useState(1000);
     45  //const [LF, setLF] = useState(0);
     46  //const [LT, setLT] = useState(1000);
    3647  const navigate = useNavigate();
    3748  const { search } = useLocation();
     
    4354  const order = sp.get("order") || "newest";
    4455  const page = sp.get("page") || 1;
    45 
    4656  const [{ loading, error, products, pages, countProducts }, dispatch] =
    4757    useReducer(reducer, { loading: true, error: "" });
     
    5666        );*/
    5767        const { data } = await axios.get(
    58           `/api/products?page=${page}&query=${query}&category=${category}&subCategory=${subCategory}&order=${order}`
     68          `/api/products?page=${page}&query=${query}&category=${category}&subCategory=${subCategory}&order=${order}&HF=${HF}&HT=${HT}&WF=${WF}&WT=${WT}&LF=${LF}&LT=${LT}`
    5969        );
    6070        dispatch({ type: "FETCH_SUCCESS", payload: data });
     
    6474    };
    6575    fetchData();
    66   }, [category, page, query, order, subCategory, error]);
     76  }, [
     77    category,
     78    page,
     79    query,
     80    order,
     81    subCategory,
     82    error,
     83    HF,
     84    HT,
     85    WF,
     86    WT,
     87    LF,
     88    LT,
     89  ]);
    6790
    6891  const getFilterUrl = (filter) => {
     
    7295    const filterSubCategory = filter.subCategory || subCategory;
    7396    const sortOrder = filter.order || order;
    74     return `?category=${filterCategorry}&query=${filterQuery}&subCategory=${filterSubCategory}&page=${filterPage}&order=${sortOrder}`;
     97    const filterHF = filter.HF || HF;
     98    const filterHT = filter.HT || HT;
     99    const filterWF = filter.WF || WF;
     100    const filterWT = filter.WT || WT;
     101    const filterLF = filter.LF || LF;
     102    const filterLT = filter.LT || LT;
     103    return `?category=${filterCategorry}&query=${filterQuery}&subCategory=${filterSubCategory}&page=${filterPage}&order=${sortOrder}&HF=${filterHF}&HT=${filterHT}&WF=${filterWF}&WT=${filterWT}&LF=${filterLF}&LT=${filterLT}`;
     104  };
     105
     106  const filterHandler = (e) => {
     107    e.preventDefault();
     108    HF = document.getElementById("HF").value;
     109    HT = document.getElementById("HT").value;
     110    WF = document.getElementById("WF").value;
     111    WT = document.getElementById("WT").value;
     112    LF = document.getElementById("LF").value;
     113    LT = document.getElementById("LT").value;
     114    console.log(HT);
     115    const fetchData = async () => {
     116      try {
     117        dispatch({ type: "FETCH_REQUEST" });
     118        /*
     119        const { data } = await axios.get(
     120          `/api/products/search?page=${page}&query=${query}&category=${category}&subCategory=${subCategory}&order=${order}`
     121        );*/
     122        const { data } = await axios.get(
     123          `/api/products?page=${page}&query=${query}&category=${category}&subCategory=${subCategory}&order=${order}&HF=${HF}&HT=${HT}&WF=${WF}&WT=${WT}&LF=${LF}&LT=${LT}`
     124        );
     125        dispatch({ type: "FETCH_SUCCESS", payload: data });
     126      } catch (err) {
     127        dispatch({ type: "FETCH_FAIL", payload: getError(err) });
     128      }
     129    };
     130    fetchData();
    75131  };
    76132
     
    124180            >
    125181              <Form
     182                onSubmit={filterHandler}
    126183                style={{
    127184                  width: "100%",
    128185                  display: "flex",
    129                   justifyContent: "end",
     186                  justifyContent: "space-around",
    130187                  marginRight: "40px",
    131188                  alignItems: "center",
    132189                }}
    133190              >
     191                <Form.Group style={{ display: "flex", alignItems: "center" }}>
     192                  <Form.Label style={{ margin: "0px" }}>H:</Form.Label>
     193                  <Form.Control
     194                    style={{ width: "60px" }}
     195                    id="HF"
     196                    //onChange={(e) => setHF(e.target.value)}
     197                  />
     198                  <Form.Label style={{ margin: "0px" }}>-</Form.Label>
     199                  <Form.Control
     200                    style={{ width: "60px" }}
     201                    id="HT"
     202                    //onChange={(e) => setHT(e.target.value)}
     203                  />
     204                </Form.Group>
     205                <Form.Group style={{ display: "flex", alignItems: "center" }}>
     206                  <Form.Label style={{ margin: "0px" }}>W:</Form.Label>
     207                  <Form.Control
     208                    style={{ width: "60px" }}
     209                    id="WF"
     210                    //onChange={(e) => setWF(e.target.value)}
     211                  />
     212                  <Form.Label style={{ margin: "0px" }}>-</Form.Label>
     213                  <Form.Control
     214                    style={{ width: "60px" }}
     215                    id="WT"
     216                    //onChange={(e) => setWT(e.target.value)}
     217                  />
     218                </Form.Group>
     219                <Form.Group style={{ display: "flex", alignItems: "center" }}>
     220                  <Form.Label style={{ margin: "0px" }}>L:</Form.Label>
     221                  <Form.Control
     222                    id="LF"
     223                    style={{ width: "60px" }}
     224                    //onChange={(e) => setLF(e.target.value)}
     225                  />
     226                  <Form.Label style={{ margin: "0px" }}>-</Form.Label>
     227                  <Form.Control
     228                    id="LT"
     229                    style={{ width: "60px" }}
     230                    //onChange={(e) => setLT(e.target.value)}
     231                  />
     232                </Form.Group>
    134233                {/*}
    135234                <Form.Group>
     
    292391                    <option value={"highFirst"}>Од висока кон ниска</option>
    293392                  </Form.Select>
     393                </Form.Group>
     394                <Form.Group>
     395                  <Button variant="danger" size="lg" type="submit">
     396                    Филтрирај
     397                  </Button>
    294398                </Form.Group>
    295399              </Form>
Note: See TracChangeset for help on using the changeset viewer.