From 50400ae4656730a03917dcb9bfe4d5b3306b2d11 Mon Sep 17 00:00:00 2001 From: David Melanson Jr <david427@live.com> Date: Wed, 9 Mar 2022 21:13:56 -0500 Subject: [PATCH 1/5] Updated navbar --- .../src/features/layout/FooterNav.tsx | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 dart-cart-client/src/features/layout/FooterNav.tsx diff --git a/dart-cart-client/src/features/layout/FooterNav.tsx b/dart-cart-client/src/features/layout/FooterNav.tsx new file mode 100644 index 00000000..65f029f8 --- /dev/null +++ b/dart-cart-client/src/features/layout/FooterNav.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import { Link } from "react-router-dom"; + +const FooterNav = () => { + const links = { + Home: "/", + Categoriees: "#", + Deals: "#", + "Top Items": "#" + }; + + const navLinks = Object.keys(links).map((link) => { + return ( + <p key={link}> + <Link to={links[link]} className="text-reset"> + {link} + </Link> + </p> + ); + }); + + return <>{navLinks}</>; +}; + +export default FooterNav; From 89451a9683330c837810aa2ab530cc6680324c03 Mon Sep 17 00:00:00 2001 From: David Melanson Jr <david427@live.com> Date: Wed, 9 Mar 2022 21:15:16 -0500 Subject: [PATCH 2/5] Merged dev --- dart-cart-client/src/App.tsx | 7 +- dart-cart-client/src/common/models.ts | 4 +- .../src/common/slices/cartSlice.ts | 72 +-- .../src/common/slices/competitorsSlice.ts | 15 +- .../src/common/slices/shopProductSlice.ts | 44 +- .../src/features/authentication/Login.jsx | 1 - .../src/features/checkout/CheckoutButton.tsx | 24 +- .../src/features/checkout/CheckoutDisplay.css | 9 - .../competing-sellers/CompetingSellers.tsx | 53 +- .../src/features/display/Display.tsx | 53 +- .../src/features/layout/Categories.tsx | 16 +- .../src/features/layout/FooterNav.tsx | 25 + .../src/features/layout/Header.tsx | 12 +- .../src/features/layout/Navbar.tsx | 129 +++-- .../src/features/layout/Searchbar.tsx | 61 ++- .../src/features/list-item/ListItem.tsx | 5 +- .../product-details/ShopProductCard.tsx | 58 +-- .../product-details/ShopProductDisplay.tsx | 131 ++--- .../src/features/search/SearchDisplay.tsx | 45 -- .../seller-homepage/SellerHomepage.tsx | 3 +- .../features/user-register/UserRegister.tsx | 477 +++++++++--------- 21 files changed, 656 insertions(+), 588 deletions(-) create mode 100644 dart-cart-client/src/features/layout/FooterNav.tsx delete mode 100644 dart-cart-client/src/features/search/SearchDisplay.tsx diff --git a/dart-cart-client/src/App.tsx b/dart-cart-client/src/App.tsx index 609cb517..4dc814f9 100644 --- a/dart-cart-client/src/App.tsx +++ b/dart-cart-client/src/App.tsx @@ -19,11 +19,11 @@ import Checkout from "./features/checkout/CheckoutDisplay"; import ListItem from "./features/list-item/ListItem"; import ShopPage from "./features/shop-page/ShopPage"; import SellerHomepage from "./features/seller-homepage/SellerHomepage"; -import SearchDisplay from "./features/search/SearchDisplay"; function App() { useEffect(() => { document.title = "DartCart"; + // }); return ( @@ -32,7 +32,7 @@ function App() { <Provider store={store}> <Header /> <Routes> - <Route path="/" element={<Home />}></Route> + <Route path="/" element={<Display />}></Route> <Route path="/sellers/:seller_homepage" element={<SellerHomepage />} @@ -46,9 +46,8 @@ function App() { <Route path="/orders" element={<PreviousOrders />}></Route> <Route path="/checkout" element={<Checkout />}></Route> <Route path="/display" element={<Display />}></Route> - <Route path="/search" element={<SearchDisplay />}></Route> <Route - path="/shop/:product_id" + path="/shop-product/:shop_product_id" element={<ShopProductDisplay />} ></Route> <Route path="/*" element={<Error404Page />}></Route> diff --git a/dart-cart-client/src/common/models.ts b/dart-cart-client/src/common/models.ts index a41f53d2..7660e19b 100644 --- a/dart-cart-client/src/common/models.ts +++ b/dart-cart-client/src/common/models.ts @@ -2,12 +2,14 @@ import { Shop } from "./types"; export class Product { product_id: number; + id: number; name: string; description: string; categories: string[]; - constructor(product_id: number, name: string, description: string, categories: string[]) { + constructor(product_id: number, id: number, name: string, description: string, categories: string[]) { this.product_id = product_id; + this.id = id; this.name = name; this.description = description; this.categories = categories; diff --git a/dart-cart-client/src/common/slices/cartSlice.ts b/dart-cart-client/src/common/slices/cartSlice.ts index 5c5e3366..5fea7a1f 100644 --- a/dart-cart-client/src/common/slices/cartSlice.ts +++ b/dart-cart-client/src/common/slices/cartSlice.ts @@ -17,47 +17,47 @@ export const fetchCart = createAsyncThunk("cart/fetchCart", async () => { }); export const addToCart = createAsyncThunk('cart/addToCart', async (shop_product_id: number) => { - const username = localStorage.getItem("username") - const response = await axios.post(API_URL + "carts", { - quantity: 1, - saved: false, - customer: { - username: username - }, - shopProduct: { - shop_product_id: shop_product_id - } - }, { headers: authHeader() }) + const username = localStorage.getItem("username") + const response = await axios.post(API_URL + "carts", { + quantity: 1, + saved: false, + customer: { + username: username + }, + shopProduct: { + id: shop_product_id + } + }, { headers: authHeader() }) return response.data; }); export const updateCart = createAsyncThunk('cart/updateCart', async (cartItem: CartItem) => { - const response = await axios.put(API_URL + "carts/" + cartItem.id, { - quantity: cartItem.quantity - }, { headers: authHeader() }) + const response = await axios.put(API_URL + "carts/" + cartItem.id, { + quantity: cartItem.quantity + }, { headers: authHeader() }) return response.data; }); export const addInvoice = createAsyncThunk( "checkout/addInvoice", - async ({user, shippingAddress, currentCart}: CheckoutProps) => { - const response = await axios.post(API_URL + "checkout", { - id: user.id, - username: user.username, - password: user.password, - firstName: user.firstName, - lastName: user.lastName, - email: user.email, - phone: user.phone, - location: shippingAddress, - registrationDate: user.registrationDate, - itemList: currentCart - }, { - headers: authHeader() - }); - return response.data; + async ({ user, shippingAddress, currentCart }: CheckoutProps) => { + const response = await axios.post(API_URL + "checkout", { + id: user.id, + username: user.username, + password: user.password, + firstName: user.firstName, + lastName: user.lastName, + email: user.email, + phone: user.phone, + location: shippingAddress, + registrationDate: user.registrationDate, + itemList: currentCart + }, { + headers: authHeader() + }); + return response.data; } ); @@ -74,6 +74,12 @@ export const cartSlice = createSlice({ cartAdapater.updateOne(state, action); } }, + clearCart(state) { + cartAdapater.removeMany(state, state.ids) + }, + resetStatus(state) { + state.status = "idle" + } }, extraReducers: (builder) => { builder @@ -96,12 +102,12 @@ export const cartSlice = createSlice({ } }); -export const { updateCartItem } = cartSlice.actions; +export const { clearCart, updateCartItem, resetStatus } = cartSlice.actions; export default cartSlice.reducer; -export const { selectAll: selectAllCartItems, selectById: selectCartItemById} = cartAdapater.getSelectors((state: RootState) => state.cart) +export const { selectAll: selectAllCartItems, selectById: selectCartItemById } = cartAdapater.getSelectors((state: RootState) => state.cart) export const selectStatus = createSelector( (state: RootState) => state.cart, (cart) => cart.status - ); +); \ No newline at end of file diff --git a/dart-cart-client/src/common/slices/competitorsSlice.ts b/dart-cart-client/src/common/slices/competitorsSlice.ts index be183c90..458534da 100644 --- a/dart-cart-client/src/common/slices/competitorsSlice.ts +++ b/dart-cart-client/src/common/slices/competitorsSlice.ts @@ -4,6 +4,7 @@ import { createAsyncThunk, } from "@reduxjs/toolkit"; import axios from "axios"; +import authHeader from "../../features/authentication/AuthHeader"; import { ShopProduct } from "../models"; const MOCK_SERVER = process.env.REACT_APP_API_URL; @@ -14,10 +15,11 @@ const CPAdapter = createEntityAdapter<ShopProduct>(); // Entity is mapped to our export const fetchCompetitorProducts = createAsyncThunk( "CompetitorProducts/fetchCompetitorProducts", - async (productId: number) => { - const response = await axios.get(MOCK_SERVER + "/ShopProducts", { - params: { product_id: `${productId}` }, + async (shopProductId: number) => { + const response = await axios.get(MOCK_SERVER + "sellers/" + shopProductId, { + headers: authHeader(), }); + return response.data; } ); @@ -39,10 +41,11 @@ const CPSlice = createSlice({ }) .addCase(fetchCompetitorProducts.fulfilled, (state, action) => { const newEntities = {}; + var i = 0; + state.ids = []; action.payload.forEach((CompetitorProduct) => { - state.ids[CompetitorProduct.shop_product_id - 1] = - CompetitorProduct.shop_product_id; - newEntities[CompetitorProduct.shop_product_id] = CompetitorProduct; + state.ids[i++] = CompetitorProduct.id; + newEntities[CompetitorProduct.id] = CompetitorProduct; }); state.entities = newEntities; state.status = "idle"; diff --git a/dart-cart-client/src/common/slices/shopProductSlice.ts b/dart-cart-client/src/common/slices/shopProductSlice.ts index e2664333..3efc2e13 100644 --- a/dart-cart-client/src/common/slices/shopProductSlice.ts +++ b/dart-cart-client/src/common/slices/shopProductSlice.ts @@ -6,19 +6,21 @@ import { } from "@reduxjs/toolkit"; import axios from "axios"; import authHeader from "../../features/authentication/AuthHeader"; -import { ShopProduct } from "../models"; +import { Product } from "../models"; import { RootState } from "../types"; const MOCK_SERVER = process.env.REACT_APP_API_URL; -const SPAdapter = createEntityAdapter<ShopProduct>(); // Entity is mapped to our Model. Create Entity Adapter provides REDUCERS +const SPAdapter = createEntityAdapter<Product>(); // Entity is mapped to our Model. Create Entity Adapter provides REDUCERS export const fetchShopProducts = createAsyncThunk( "ShopProducts/fetchShopProducts", - async () => { - const response = await axios.get(MOCK_SERVER + "shop_products", { + async (name: string) => { + const response = await axios.get(MOCK_SERVER + "shop_products/search", { headers: authHeader(), + params: { name }, }); + return response.data; } ); @@ -33,6 +35,11 @@ const SPSlice = createSlice({ name: "ShopProducts", initialState: intitialState, //format is identical to getInitialState(), but we added a "status" field to the js Object reducers: { + clearSlice(state, action) { + state.status = "idle"; + state.ids = []; + state.entities = {}; + }, updatedSearchString(state, action) { state.searchString = action.payload; }, @@ -43,28 +50,41 @@ const SPSlice = createSlice({ state.status = "Loading"; }) .addCase(fetchShopProducts.fulfilled, (state, action) => { - const newEntities = {}; const newProducts = new Array(); + state.ids = [] + state.entities = {} action.payload.forEach((ShopProduct) => { - state.ids[ShopProduct.shop_product_id - 1] = - ShopProduct.shop_product_id; - newEntities[ShopProduct.shop_product_id] = ShopProduct; - newProducts[ShopProduct.shop_product_id - 1] = ShopProduct.product; + state.ids.push(ShopProduct.id); + state.entities[ShopProduct.id] = ShopProduct; + newProducts[ShopProduct.id - 1] = ShopProduct.product; }); state.items = newProducts; - state.entities = newEntities; - state.status = "idle"; + state.status = "success"; }); }, }); -export const { updatedSearchString } = SPSlice.actions; +export const { updatedSearchString, clearSlice } = SPSlice.actions; export const { selectAll: selectShopProducts, selectById: selectShopProductById, } = SPAdapter.getSelectors((state: any) => state.ShopProducts); +export const getSearchString = createSelector( + (state: RootState) => state.ShopProducts.searchString, + (search) => { + return search; + } +); + +export const getStatus = createSelector( + (state: RootState) => state.ShopProducts.status, + (status) => { + return status; + } +); + export const selectFilteredProducts = createSelector( (state: RootState) => state.ShopProducts, (state: RootState) => state.ShopProducts.searchString, diff --git a/dart-cart-client/src/features/authentication/Login.jsx b/dart-cart-client/src/features/authentication/Login.jsx index e4b7461e..c9738556 100644 --- a/dart-cart-client/src/features/authentication/Login.jsx +++ b/dart-cart-client/src/features/authentication/Login.jsx @@ -27,7 +27,6 @@ export const Login = () => { const handleLogin = async () => { await dispatch(loginUser({ username, password })); setError(""); - dispatch(fetchCart()); setShowModal(true); }; diff --git a/dart-cart-client/src/features/checkout/CheckoutButton.tsx b/dart-cart-client/src/features/checkout/CheckoutButton.tsx index bf59670c..ba490000 100644 --- a/dart-cart-client/src/features/checkout/CheckoutButton.tsx +++ b/dart-cart-client/src/features/checkout/CheckoutButton.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react"; import { useSelector, useDispatch } from "react-redux"; import { RootState } from "../../common/types"; -import { addInvoice, selectAllCartItems, selectStatus } from "../../common/slices/cartSlice"; +import { addInvoice, selectAllCartItems, selectStatus, resetStatus } from "../../common/slices/cartSlice"; import { Modal, Button } from "react-bootstrap"; import { selectUser } from "../../common/slices/authSlice"; import { useNavigate } from "react-router-dom"; @@ -28,12 +28,23 @@ export function CheckoutButton() { zip: "" }; - const handleShow = () => setShow(true); + useEffect(() => { + if(status === "fulfilled") { + setSuccess(true) + setShow(true) + } else if(status === "rejected") { + setSuccess(false) + setShow(true) + } + }, [status]) + const handleClose = () => { setShow(false); if(status === "fulfilled"){ + dispatch(resetStatus()) nav("/"); }else{ + dispatch(resetStatus()) nav("/cart"); } } @@ -43,14 +54,7 @@ export function CheckoutButton() { if(currentUser && currentCart){ let shippingAddress = streetAddress + ", " + city + " " + state + ", " + zip; - await dispatch(addInvoice({user: JSON.parse(currentUser), currentCart: currentCart, shippingAddress: shippingAddress})); - if(status === "fulfilled"){ - setSuccess(true); - handleShow(); - }else if(status === "rejected") { - setSuccess(false); - handleShow(); - } + dispatch(addInvoice({user: JSON.parse(currentUser), currentCart: currentCart, shippingAddress: shippingAddress})); } } diff --git a/dart-cart-client/src/features/checkout/CheckoutDisplay.css b/dart-cart-client/src/features/checkout/CheckoutDisplay.css index a96934c6..cab3f815 100644 --- a/dart-cart-client/src/features/checkout/CheckoutDisplay.css +++ b/dart-cart-client/src/features/checkout/CheckoutDisplay.css @@ -1,10 +1 @@ @import url('https://fonts.googleapis.com/css?family=Montserrat:400,700&display=swap'); - -/* body { - display: flex; - justify-content: center; - align-items: center; - min-height: 100vh; - background-color: #0C4160; - padding: 30px 10px -} */ \ No newline at end of file diff --git a/dart-cart-client/src/features/competing-sellers/CompetingSellers.tsx b/dart-cart-client/src/features/competing-sellers/CompetingSellers.tsx index 593265ac..9daa6aa5 100644 --- a/dart-cart-client/src/features/competing-sellers/CompetingSellers.tsx +++ b/dart-cart-client/src/features/competing-sellers/CompetingSellers.tsx @@ -1,30 +1,73 @@ import { useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; +import { Product, ShopProduct } from "../../common/models"; +import { addToCart } from "../../common/slices/cartSlice"; import { fetchCompetitorProducts, selectCompetitorProductById, + selectCompetitorProducts, } from "../../common/slices/competitorsSlice"; +import Logo from "../layout/Logo"; import "./competingSellers.css"; interface SellerProduct { - Seller: number; //product ID + Seller: number; } export function CompetingSellers({ Seller }: SellerProduct) { const dispatch = useDispatch(); - const ReduxCompetitorProducts = useSelector((state) => - selectCompetitorProductById(state, 1) + const ReduxCompetitorProducts: ShopProduct[] = useSelector( + selectCompetitorProducts ); useEffect(() => { dispatch(fetchCompetitorProducts(Seller)); // places return value into REDUX global state }, []); + function handleAddtoCart(e) { + dispatch(addToCart(e.target.value)); + } + return ( <div className="Competitors"> - {ReduxCompetitorProducts && ReduxCompetitorProducts?.product.product_id} - <button className="btn btn-success" >Add to Cart</button> + {(ReduxCompetitorProducts && + ReduxCompetitorProducts.map((competitors) => { + return ( + <div className="SellerContainer"> + <div className="SellerWindow"></div> + + <div className="SellerPocket"> + <div className="SellerInfo"> + <span>{competitors.product.name}</span> + <br /> + <span>Price: {competitors.price}.99</span> + <br /> + {competitors.discount > 0 && ( + <span className="SellerDiscount"> + Discount: {competitors.discount}.00 + </span> + )} + </div> + <div className="SellerInfo"> + <span>Location: {competitors.shop.location}</span> + <br /> + <span>In Stock: {competitors.quantity}</span> + <br /> + </div> + </div> + + <button + className="btn btn-primary" + value={competitors.id} + onClick={(e) => handleAddtoCart(e)} + > + Add to cart + </button> + </div> + ); + })) || + ""} </div> ); } diff --git a/dart-cart-client/src/features/display/Display.tsx b/dart-cart-client/src/features/display/Display.tsx index bab0c957..fcf1d9b8 100644 --- a/dart-cart-client/src/features/display/Display.tsx +++ b/dart-cart-client/src/features/display/Display.tsx @@ -1,41 +1,22 @@ -import { ShopProduct } from "../../common/models"; +import { Product } from "../../common/models"; import { ShopProductCard } from "../product-details/ShopProductCard"; import "./display.css"; import { useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import { fetchShopProducts, + getStatus, selectShopProducts, + clearSlice, } from "../../common/slices/shopProductSlice"; const Display = () => { const dispatch = useDispatch(); - const ReduxShopProducts = useSelector(selectShopProducts); - - function findCheapest(list: ShopProduct[]) { - let productMap: Map<number, number> = new Map<number, number>(); - let finalList: ShopProduct[] = []; - - for (let i = 0; i < list.length; i++) { - if (productMap[list[i].product.product_id]) { - if (list[i].price < productMap[list[i].product.product_id]) { - productMap[list[i].product.product_id] = list[i].price; - } - } else { - productMap[list[i].product.product_id] = list[i].price; - } - } - - list.forEach((Sproduct) => { - if (Sproduct.price === productMap[Sproduct.product.product_id]) { - finalList.push(Sproduct); - } - }); - return finalList; - } + const ReduxShopProducts: Product[] = useSelector(selectShopProducts); + const status = useSelector(getStatus); useEffect(() => { - dispatch(fetchShopProducts()); // places return value into REDUX global state + if (status === "idle") dispatch(fetchShopProducts("")); // places return value into REDUX global state }, []); return ( @@ -43,14 +24,20 @@ const Display = () => { <div className=""></div> <div className="ProductCardContainer"> - {ReduxShopProducts.length > 0 ? ( - findCheapest(ReduxShopProducts).map((ShopProduct) => { - return ( - <ShopProductCard ShopProduct={ShopProduct}></ShopProductCard> - ); - }) + {status === "success" ? ( + (ReduxShopProducts.length && + ReduxShopProducts.map((Product) => { + return <ShopProductCard Product={Product}></ShopProductCard>; + })) || ( + <> + <h1 style={{ color: "white" }}>No Items Found</h1> + </> + ) ) : ( - <div className="text-light fs-1 p-5 text-uppercase" style = {{textAlign: "center"}}> + <div + className="text-light fs-1 p-5 text-uppercase" + style={{ textAlign: "center" }} + > Fetching Products... </div> )} @@ -59,4 +46,4 @@ const Display = () => { ); }; -export default Display; \ No newline at end of file +export default Display; diff --git a/dart-cart-client/src/features/layout/Categories.tsx b/dart-cart-client/src/features/layout/Categories.tsx index 34c9055b..0eb004bb 100644 --- a/dart-cart-client/src/features/layout/Categories.tsx +++ b/dart-cart-client/src/features/layout/Categories.tsx @@ -1,20 +1,24 @@ import React from "react"; -import { Navbar } from "react-bootstrap"; import { Dropdown } from "react-bootstrap"; const Categories = () => { return ( - <Dropdown style={{ flex: "auto"}}> + <Dropdown style={{ flex: "auto" }}> <Dropdown.Toggle variant="success" id="dropdown-basic"> Categories </Dropdown.Toggle> <Dropdown.Menu> - <Dropdown.Item href="#/action-1">Action</Dropdown.Item> - <Dropdown.Item href="#/action-2">Another action</Dropdown.Item> - <Dropdown.Item href="#/action-3">Something else</Dropdown.Item> + <Dropdown.Item href="#/action-1">Toys</Dropdown.Item> + <Dropdown.Item href="#/action-2">Clothing</Dropdown.Item> + <Dropdown.Item href="#/action-3">Furniture</Dropdown.Item> + <Dropdown.Item href="#/action-3">Entertainment</Dropdown.Item> + <Dropdown.Item href="#/action-3">Automotive</Dropdown.Item> + <Dropdown.Item href="#/action-3">Home Goods</Dropdown.Item> + <Dropdown.Item href="#/action-3">School and Office</Dropdown.Item> + <Dropdown.Item href="#/action-3">Personal Care</Dropdown.Item> </Dropdown.Menu> </Dropdown> ); }; -export default Categories; \ No newline at end of file +export default Categories; diff --git a/dart-cart-client/src/features/layout/FooterNav.tsx b/dart-cart-client/src/features/layout/FooterNav.tsx new file mode 100644 index 00000000..65f029f8 --- /dev/null +++ b/dart-cart-client/src/features/layout/FooterNav.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import { Link } from "react-router-dom"; + +const FooterNav = () => { + const links = { + Home: "/", + Categoriees: "#", + Deals: "#", + "Top Items": "#" + }; + + const navLinks = Object.keys(links).map((link) => { + return ( + <p key={link}> + <Link to={links[link]} className="text-reset"> + {link} + </Link> + </p> + ); + }); + + return <>{navLinks}</>; +}; + +export default FooterNav; diff --git a/dart-cart-client/src/features/layout/Header.tsx b/dart-cart-client/src/features/layout/Header.tsx index d27ec297..aa9779a8 100644 --- a/dart-cart-client/src/features/layout/Header.tsx +++ b/dart-cart-client/src/features/layout/Header.tsx @@ -2,19 +2,19 @@ import "../styles.css"; import Logo from "./Logo"; import Searchbar from "./Searchbar"; import Nav from "./Navbar"; -import Categories from "./Categories"; -import { Navbar } from 'react-bootstrap'; - +import { Navbar } from "react-bootstrap"; const Header = () => { return ( <Navbar> - <header className="navbar navbar-expand-lg navbar-fixed-top navbar-custom" style= {{width: '100%'}}> + <header + className="navbar navbar-expand-lg navbar-fixed-top navbar-custom" + style={{ width: "100%" }} + > <Logo /> <Searchbar /> - <Categories /> <Nav /> - </header> + </header> </Navbar> ); }; diff --git a/dart-cart-client/src/features/layout/Navbar.tsx b/dart-cart-client/src/features/layout/Navbar.tsx index 18178367..cfd5031a 100644 --- a/dart-cart-client/src/features/layout/Navbar.tsx +++ b/dart-cart-client/src/features/layout/Navbar.tsx @@ -2,64 +2,97 @@ import React, { useEffect, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { Link } from "react-router-dom"; import { logout } from "../../common/slices/authSlice"; +import { clearCart } from "../../common/slices/cartSlice"; import { RootState } from "../../common/types"; - const Nav = (props) => { - - const dispatch = useDispatch() - const [name, setName] = useState("") - const user = useSelector((state: RootState) => state.authentication.user) || "" + const dispatch = useDispatch(); + const [name, setName] = useState(""); + const user = + useSelector((state: RootState) => state.authentication.user) || ""; useEffect(() => { - if(user) { - const u = JSON.parse(user) - setName(u.firstName) + if (user) { + const u = JSON.parse(user); + setName(u.firstName); } - }, [user]) + }, [user]); const handleLogout = () => { - dispatch(logout(null)) - } + dispatch(logout(null)); + dispatch(clearCart()); + }; return ( - <nav className="navbar-header"> - <ul - className="navbar-nav mr-auto link-container" - style={!props.footer ? { textAlign: "center" } : {}} - > - { - user ? (<> - <li className="nav-item-mb-3 nav-item"> - <h3>Welcome {name}</h3> - </li> - <li className="nav-item-mb-3 nav-item"> - <Link to="/" className="text-reset nav-link">Home</Link> - </li> - <li className="nav-item-mb-3 nav-item"> - <Link to="/" className="text-reset nav-link" onClick={handleLogout}>Logout</Link> - </li> - <li className="nav-item-mb-3 nav-item"> - <Link to="/cart" type="button" className="btn btn-success"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-cart" viewBox="0 0 16 16"> - <path d="M0 1.5A.5.5 0 0 1 .5 1H2a.5.5 0 0 1 .485.379L2.89 3H14.5a.5.5 0 0 1 .491.592l-1.5 8A.5.5 0 0 1 13 12H4a.5.5 0 0 1-.491-.408L2.01 3.607 1.61 2H.5a.5.5 0 0 1-.5-.5zM3.102 4l1.313 7h8.17l1.313-7H3.102zM5 12a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm7 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm-7 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm7 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"></path> - </svg> - </Link> - </li> - </>) : (<> - <li className="nav-item-mb-3 nav-item"> - <Link to="/" className="text-reset nav-link">Home</Link> - </li> - <li className="nav-item-mb-3 nav-item"> - <Link to="/login" className="text-reset nav-link">Login</Link> - </li> - <li className="nav-item-mb-3 nav-item"> - <Link to="/register" className="text-reset nav-link">Register</Link> - </li> - </>) - } - </ul> - </nav> + <nav className="navbar-header"> + <ul + className="navbar-nav mr-auto link-container" + style={!props.footer ? { textAlign: "center" } : {}} + > + {user ? ( + <> + <li className="nav-item-mb-3 nav-item"> + <h3>Welcome {name}</h3> + </li> + <li className="nav-item-mb-3 nav-item"> + <Link to="/" className="text-reset nav-link"> + Home + </Link> + </li> + <li className="nav-item-mb-3 nav-item"> + <Link to="/signup" className="text-reset nav-link"> + Create a Shop + </Link> + </li> + <li className="nav-item-mb-3 nav-item"> + <Link + to="/" + className="text-reset nav-link" + onClick={handleLogout} + > + Logout + </Link> + </li> + {!props.footer ? ( + <li className="nav-item-mb-3 nav-item"> + <Link to="/cart" type="button" className="btn btn-success"> + <svg + xmlns="http://www.w3.org/2000/svg" + width="16" + height="16" + fill="currentColor" + className="bi bi-cart" + viewBox="0 0 16 16" + > + <path d="M0 1.5A.5.5 0 0 1 .5 1H2a.5.5 0 0 1 .485.379L2.89 3H14.5a.5.5 0 0 1 .491.592l-1.5 8A.5.5 0 0 1 13 12H4a.5.5 0 0 1-.491-.408L2.01 3.607 1.61 2H.5a.5.5 0 0 1-.5-.5zM3.102 4l1.313 7h8.17l1.313-7H3.102zM5 12a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm7 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm-7 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm7 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"></path> + </svg> + </Link> + </li> + ) : ( + "" + )} + </> + ) : ( + <> + <li className="nav-item-mb-3 nav-item"> + <Link to="/" className="text-reset nav-link"> + Home + </Link> + </li> + <li className="nav-item-mb-3 nav-item"> + <Link to="/login" className="text-reset nav-link"> + Login + </Link> + </li> + <li className="nav-item-mb-3 nav-item"> + <Link to="/register" className="text-reset nav-link"> + Register + </Link> + </li> + </> + )} + </ul> + </nav> ); }; diff --git a/dart-cart-client/src/features/layout/Searchbar.tsx b/dart-cart-client/src/features/layout/Searchbar.tsx index 50e44fb5..2542b290 100644 --- a/dart-cart-client/src/features/layout/Searchbar.tsx +++ b/dart-cart-client/src/features/layout/Searchbar.tsx @@ -1,45 +1,58 @@ import React, { useRef } from "react"; -import { useDispatch } from "react-redux"; -import { updatedSearchString } from "../../common/slices/shopProductSlice"; +import { useDispatch, useSelector } from "react-redux"; +import { + fetchShopProducts, + getSearchString, + updatedSearchString, +} from "../../common/slices/shopProductSlice"; +import { useNavigate } from "react-router-dom"; const Searchbar = () => { - - const dispatch = useDispatch(); const string = useRef<HTMLInputElement>(null); + const search: string = useSelector(getSearchString); + const nav = useNavigate(); const handleSearch = (e: any) => { - if(e.code !== "Enter") { - console.log(string.current?.value) - dispatch(updatedSearchString(string.current?.value)) - } - } - - const buttonHandler = (e: any) => { - dispatch(updatedSearchString(string.current?.value)) - } - - + dispatch(fetchShopProducts(search)); + nav("/display"); + }; + const onChangeHandler = (e: any) => { + dispatch(updatedSearchString(string.current?.value)); + }; return ( - - <div className="navbar-brand" style={{width:" 60%", marginLeft: "20px" }}> + <div className="navbar-brand" style={{ width: " 60%", marginLeft: "20px" }}> <div className="form-inline my-2 my-lg-0"> - <input - type="submit" - onClick={e => buttonHandler(e)} + <button + onClick={(e) => handleSearch(e)} className="btn btn-success" value="Search" style={{ float: "right", backgroundColor: "#198754" }} - /> + > + Search{" "} + </button> <div style={{ overflow: "hidden", paddingRight: ".5em" }}> - <input type="text" placeholder="Search" style={{ width: "100%" }} ref={string} onChange={(e) => {handleSearch(e)}}/> + <input + type="text" + placeholder="Search" + style={{ width: "100%" }} + ref={string} + onKeyUp={(e) => { + // Check if keypress is enter button + if (e.key === "Enter") { + handleSearch(e); + } + }} + onBlur={(e) => handleSearch(e)} + onChange={(e) => { + onChangeHandler(e); + }} + /> </div> </div> </div> - - ); }; diff --git a/dart-cart-client/src/features/list-item/ListItem.tsx b/dart-cart-client/src/features/list-item/ListItem.tsx index ff52578d..d9c66849 100644 --- a/dart-cart-client/src/features/list-item/ListItem.tsx +++ b/dart-cart-client/src/features/list-item/ListItem.tsx @@ -77,7 +77,6 @@ export function ListItem() { }; const handleOnClick = () => { - console.log(chosenProduct); shopProduct.quantity = productQuantity; const rawPrice = productPrice.slice(1); @@ -88,6 +87,10 @@ export function ListItem() { if (!validateInput()) { return; } + + dispatch(createShopProduct(shopProduct)).unwrap().then(originalPromiseResult => setShowModal(true)).catch(rejectValueOrSerializedError => { + setError("Something went wrong...") + }) }; const handleClose = () => { diff --git a/dart-cart-client/src/features/product-details/ShopProductCard.tsx b/dart-cart-client/src/features/product-details/ShopProductCard.tsx index a291d21e..f2b5409e 100644 --- a/dart-cart-client/src/features/product-details/ShopProductCard.tsx +++ b/dart-cart-client/src/features/product-details/ShopProductCard.tsx @@ -1,45 +1,35 @@ -import { ShopProduct } from "../../common/models"; +import { Product } from "../../common/models"; import { Link } from "react-router-dom"; -import { useSelector, useDispatch } from "react-redux"; -import { addToCart } from "../../common/slices/cartSlice"; import "bootstrap/dist/css/bootstrap.min.css"; interface IShopProductCard { - ShopProduct: ShopProduct; + Product: Product; } const ComputerUrl = - "https://images.unsplash.com/photo-1587831990711-23ca6441447b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8ZGVza3RvcCUyMGNvbXB1dGVyfGVufDB8fDB8fA%3D%3D&w=1000&q=80"; + "https://images.unsplash.com/photo-1587831990711-23ca6441447b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8ZGVza3RvcCUyMGNvbXB1dGVyfGVufDB8fDB8fA%3D%3D&w=1000&q=80"; -export function ShopProductCard({ ShopProduct }: IShopProductCard) { - const dispatch = useDispatch(); +export function ShopProductCard({ Product }: IShopProductCard) { + return ( + <> + <div className=" card bg-black text-warning" style={{ width: "18rem" }}> + <img + className="card-img-top" + src={ComputerUrl} + alt="Card image cap" + ></img> + <div className="card-body"> + <h1>{Product?.name || ""}</h1> - function handleAddtoCart() { - dispatch(addToCart(ShopProduct.id)); - } + <p className="card-text">{`${Product?.description || ""}`}</p> - return ( - <> - <div className=" card bg-black text-warning" style={{ width: "18rem" }}> - <img className="card-img-top" src={ComputerUrl} alt="Card image cap"></img> - <div className="card-body"> - <h1>{ShopProduct.product.name}</h1> - <h4>$ {ShopProduct.price}</h4> - - <p className="card-text">{`${ShopProduct.product.description}`}</p> - - <Link - id="Chosen Shop Product" - className="btn stretched-link" - to={`/shop-product/${ShopProduct.id}`} - ></Link> - </div> - </div> - <div> - <button className="btn btn-primary" value={ShopProduct.id} onClick={handleAddtoCart}> - Add to card - </button> - </div> - </> - ); + <Link + id="Chosen Shop Product" + className="btn stretched-link" + to={`/shop-product/${Product?.id}` || ""} + ></Link> + </div> + </div> + </> + ); } diff --git a/dart-cart-client/src/features/product-details/ShopProductDisplay.tsx b/dart-cart-client/src/features/product-details/ShopProductDisplay.tsx index 60c32f6d..974e8289 100644 --- a/dart-cart-client/src/features/product-details/ShopProductDisplay.tsx +++ b/dart-cart-client/src/features/product-details/ShopProductDisplay.tsx @@ -1,10 +1,7 @@ -import { Fragment, useEffect } from "react"; import { useParams } from "react-router-dom"; -import Header from "../layout/Header"; -import Footer from "../layout/Footer"; import "./shopProduct.css"; -import { useDispatch, useSelector } from "react-redux"; -import { fetchShopProducts, selectShopProductById } from "../../common/slices/shopProductSlice"; +import { useSelector } from "react-redux"; +import { selectShopProductById } from "../../common/slices/shopProductSlice"; import { CompetingSellers } from "../competing-sellers/CompetingSellers"; //imgs @@ -17,71 +14,75 @@ import cartoonMeds from "../../imgs/Free-medica.png"; import cartoonShoes from "../../imgs/Sneaker-tennis-shoes.png"; const ShopProductDisplay = () => { - const product_id = useParams()?.product_id || ""; - const dispatch = useDispatch(); + const { shop_product_id } = useParams(); - const ReduxShopProducts = useSelector((state) => selectShopProductById(state, product_id)); + const id: number = parseInt(shop_product_id!); - useEffect(() => { - dispatch(fetchShopProducts()); // places return value into REDUX global state - }, []); + const ReduxShopProducts = useSelector((state) => + selectShopProductById(state, id) + ); - const ImgStyleBase = { - backgroundImage: "", - backgroundSize: "contain", - backgroundPosition: "center", - backgroundRepeat: "no-repeat", - width: "40%" - }; + const ImgStyleBase = { + backgroundImage: "", + backgroundSize: "contain", + backgroundPosition: "center", + backgroundRepeat: "no-repeat", + width: "40%", + }; - function ImgSplice(catagories: String[]) { - let newImg = Object.assign({}, ImgStyleBase); - catagories.forEach((catagory) => { - switch (catagory) { - case "Perishable": - newImg.backgroundImage = `url('${cartoonSteak}')`; - break; - case "Electronics": - newImg.backgroundImage = `url('${cartoonComputer}')`; - break; - case "Clothing": - newImg.backgroundImage = `url('${cartoonClothing}')`; - break; - case "Luxury": - newImg.backgroundImage = `url('${cartoonDiamond}')`; - break; - case "Entertainment": - newImg.backgroundImage = `url('${cartoonBat}')`; - break; - case "Medical": - newImg.backgroundImage = `url('${cartoonMeds}')`; - break; - case "Footware": - newImg.backgroundImage = `url('${cartoonShoes}')`; - break; - } - }); - return newImg; - } + function ImgSplice(catagories: String[]) { + let newImg = Object.assign({}, ImgStyleBase); + catagories.forEach((catagory) => { + switch (catagory) { + case "perishable": + newImg.backgroundImage = `url('${cartoonSteak}')`; + break; + case "furniture": + newImg.backgroundImage = `url('${cartoonComputer}')`; + break; + case "entertainment": + newImg.backgroundImage = `url('${cartoonComputer}')`; + break; + case "clothing": + newImg.backgroundImage = `url('${cartoonClothing}')`; + break; + case "toys": + newImg.backgroundImage = `url('${cartoonDiamond}')`; + break; + case "homegoods": + newImg.backgroundImage = `url('${cartoonBat}')`; + break; + case "automotive": + newImg.backgroundImage = `url('${cartoonBat}')`; + break; + case "personal-care": + newImg.backgroundImage = `url('${cartoonMeds}')`; + break; + case "school&office": + newImg.backgroundImage = `url('${cartoonShoes}')`; + break; + } + }); + return newImg; + } - console.log(ReduxShopProducts); - - return ( - <> - <div className="ProductInfoPocket"> - <h2>{ReduxShopProducts?.product.name?.toUpperCase()}</h2> - <br /> - <h3>Price: $ {ReduxShopProducts?.price}</h3> - <h3>In Stock: {ReduxShopProducts?.quantity}</h3> - <h3>Seller: {ReduxShopProducts?.shop}</h3> - </div> - - <div className="ProductDescriptionPocket"> - <p>{ReduxShopProducts?.product.description}</p> - </div> - <CompetingSellers Seller={1}></CompetingSellers> - </> - ); + return ( + <div className="ProductContainer"> + <div className="InnerProduct"> + <div className="ProductInfoContainer"> + {ReduxShopProducts && <div style={ImgStyleBase}></div>} + <div className="ProductInfoPocket"> + <h2>{ReduxShopProducts?.name?.toUpperCase()}</h2> + <br /> + </div> + </div> + <div className="ProductDescriptionPocket"> + <p>{ReduxShopProducts?.description}</p> + </div> + </div> + <CompetingSellers Seller={ReduxShopProducts?.id!}></CompetingSellers> + </div> + ); }; export default ShopProductDisplay; diff --git a/dart-cart-client/src/features/search/SearchDisplay.tsx b/dart-cart-client/src/features/search/SearchDisplay.tsx deleted file mode 100644 index 16277823..00000000 --- a/dart-cart-client/src/features/search/SearchDisplay.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import "../display/display.css" -import { useEffect, useRef, useState } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import { fetchShopProducts } from "../../common/slices/shopProductSlice"; -import { selectFilteredProducts } from '../../common/slices/shopProductSlice' -import { RootState } from "../../common/types"; -import { ProductCard } from "../product-details/ProductCard"; -import { ShopProduct } from "../../common/models"; -import { ShopProductCard } from "../product-details/ShopProductCard"; - -const SearchDisplay = () => { - - const dispatch = useDispatch() - const filteredProducts = useSelector( (state: RootState) => selectFilteredProducts(state)) - - - - useEffect(() => { - dispatch(fetchShopProducts()); - }, []) - - return ( - - <> - <div className=""> - - </div> - <div className="ProductCardContainer"> - { - filteredProducts.length > 0 ? - filteredProducts.map(Product => { - return <ShopProductCard ShopProduct={Product}></ShopProductCard> }) - : "" - } - - - - - </div> - </> - - ) -} - -export default SearchDisplay; \ No newline at end of file diff --git a/dart-cart-client/src/features/seller-homepage/SellerHomepage.tsx b/dart-cart-client/src/features/seller-homepage/SellerHomepage.tsx index 613e3b4e..db89529b 100644 --- a/dart-cart-client/src/features/seller-homepage/SellerHomepage.tsx +++ b/dart-cart-client/src/features/seller-homepage/SellerHomepage.tsx @@ -14,8 +14,7 @@ export const SellerHomepage = () => { const nav = useNavigate(); useEffect(() => { - console.log(seller); - dispatch(fetchShop(seller.id)); + dispatch(fetchShop(seller[0].id)); }, []); const handleOnClick = () => { diff --git a/dart-cart-client/src/features/user-register/UserRegister.tsx b/dart-cart-client/src/features/user-register/UserRegister.tsx index d9df5f08..b5642313 100644 --- a/dart-cart-client/src/features/user-register/UserRegister.tsx +++ b/dart-cart-client/src/features/user-register/UserRegister.tsx @@ -7,265 +7,256 @@ import { useAppDispatch } from "../../common/hooks"; import { loginUser } from "../../common/slices/authSlice"; export function UserRegister() { - const currentDate = Date.now(); - const [username, setUsername] = useState(""); - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - const [rePassword, setRePassword] = useState(""); - const [firstName, setFirstName] = useState(""); - const [lastName, setLastName] = useState(""); - const [location, setLocation] = useState(""); - const [phone, setPhone] = useState(""); - const [error, setError] = useState(""); - const [showModal, setShowModal] = useState(false); + const currentDate = Date.now(); + const [username, setUsername] = useState(""); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [rePassword, setRePassword] = useState(""); + const [firstName, setFirstName] = useState(""); + const [lastName, setLastName] = useState(""); + const [location, setLocation] = useState(""); + const [phone, setPhone] = useState(""); + const [error, setError] = useState(""); + const [showModal, setShowModal] = useState(false); - const dispatch = useAppDispatch(); - const nav = useNavigate(); + const dispatch = useAppDispatch(); + const nav = useNavigate(); - const user: User = { - id: 0, - username: "", - password: "", - firstName: "", - lastName: "", - email: "", - phone: "", - location: "", - registrationDate: 0 - }; + const user: User = { + id: 0, + username: "", + password: "", + firstName: "", + lastName: "", + email: "", + phone: "", + location: "", + registrationDate: 0, + }; - // BASIC input validation: no empty fields, passwords must match, formatting requirements - // Possible TODO: Password complexity requirements - // Possible TODO: Enforcing username requirements, address formatting - const validateInput = () => { - if (username === "") { - setError("Please enter a username."); - } else if (email === "") { - setError("Please enter an email address."); - } else if (!email.includes("@") || !email.includes(".")) { - setError("Invalid email address."); - } else if (password === "") { - setError("Please enter a password."); - } else if (password !== rePassword) { - setError("Passwords do not match. Please confirm your password."); - } else if (firstName === "") { - setError("Please enter your first name."); - } else if (lastName === "") { - setError("Please enter your last name."); - } else if (location === "") { - setError("Please enter your home address."); - } else if (phone === "") { - setError("Please enter your phone number."); - } else if (!phone.match(/^\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})$/)) { - setError("Invalid phone number."); - } else { - return true; - } - }; - - const createUser = async () => { - user.username = username; - user.email = email; - user.password = password; - user.firstName = firstName; - user.lastName = lastName; - user.location = location; - user.phone = phone; - user.registrationDate = currentDate; - - if (!validateInput()) { - return; - } + // BASIC input validation: no empty fields, passwords must match, formatting requirements + // Possible TODO: Password complexity requirements + // Possible TODO: Enforcing username requirements, address formatting + const validateInput = () => { + if (username === "") { + setError("Please enter a username."); + } else if (email === "") { + setError("Please enter an email address."); + } else if (!email.includes("@") || !email.includes(".")) { + setError("Invalid email address."); + } else if (password === "") { + setError("Please enter a password."); + } else if (password !== rePassword) { + setError("Passwords do not match. Please confirm your password."); + } else if (firstName === "") { + setError("Please enter your first name."); + } else if (lastName === "") { + setError("Please enter your last name."); + } else if (location === "") { + setError("Please enter your home address."); + } else if (phone === "") { + setError("Please enter your phone number."); + } else if ( + !phone.match(/^\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})$/) + ) { + setError("Invalid phone number."); + } else { + return true; + } + }; - await dispatch(saveUser(user)) - .unwrap() - .then((originalPromiseResult) => { - setShowModal(true); - dispatch(loginUser({ username: user.username, password: user.password })); - }) - .catch((rejectedValueOrSerializedError) => { - setError("That username is unavailable."); - clearInputs(); - }); - }; + const createUser = async () => { + user.username = username; + user.email = email; + user.password = password; + user.firstName = firstName; + user.lastName = lastName; + user.location = location; + user.phone = phone; + user.registrationDate = currentDate; - function clearInputs() { - setUsername(""); + if (!validateInput()) { + return; } - // Redirect upon modal close - function handleClose() { - setShowModal(false); - dispatch(homeRedirect(null)); - nav("/"); - } + await dispatch(saveUser(user)) + .unwrap() + .then((originalPromiseResult) => { + setShowModal(true); + dispatch( + loginUser({ username: user.username, password: user.password }) + ); + }) + .catch((rejectedValueOrSerializedError) => { + setError("That username is unavailable."); + clearInputs(); + }); + }; - return ( - <> - <section className="vh-200"> - <div className="container py-5 h-100"> - <div className="row d-flex justify-content-center align-items-center h-100"> - <div className="col-10"> - <div className="card shadow-2-strong" style={{ borderRadius: "1rem" }}> - <div className="card-header card text-center bg-success text-white"> - <h3 className="mb-0">Create Your Account</h3> - </div> - <div className="card-body p-3 text-center" style={{ backgroundColor: "#a6a6a6" }}> - {error ? <Alert variant="danger">{error}</Alert> : null} + function clearInputs() { + setUsername(""); + } - <div className="row"> - <div className="form-outline mb-0"> - <h4>Username</h4> - </div> - <div className="form-outline mb-4"> - <input - type="text" - placeholder="DartTheCart" - id="typeEmailX-2" - className="form-control form-control-lg" - value={username} - onChange={(e) => { - setUsername(e.target.value); - }} - /> - </div> - <div className="form-outline mb-0"> - <h4>Email</h4> - </div> - <div className="form-outline mb-4"> - <input - type="email" - placeholder="dartcart@email.com" - id="typePasswordX-2" - className="form-control form-control-lg" - value={email} - onChange={(e) => { - setEmail(e.target.value); - }} - /> - </div> - </div> + // Redirect upon modal close + function handleClose() { + setShowModal(false); + dispatch(homeRedirect(null)); + nav("/"); + } - <div className="row"> - <div className="form-outline mb-0"> - <h4>Password</h4> - </div> - <div className="form-outline mb-4"> - <input - type="password" - placeholder="P@S5W0RD!" - id="typePasswordX-2" - className="form-control form-control-lg" - value={password} - onChange={(e) => { - setPassword(e.target.value); - }} - /> - </div> - <div className="form-outline mb-0"> - <h4>Confirm Password</h4> - </div> - <div className="form-outline mb-4"> - <input - type="password" - placeholder="P@S5W0RD!" - id="typePasswordX-2" - className="form-control form-control-lg" - value={rePassword} - onChange={(e) => { - setRePassword(e.target.value); - }} - /> - </div> - </div> + return ( + <> + <section className="vh-200"> + <div className="container py-5 h-100"> + <div className="row d-flex justify-content-center align-items-center h-100"> + <div className="col col-lg-10 col-sm-12"> + <div + className="card shadow-2-strong" + style={{ borderRadius: "1rem" }} + > + <div className="card-header card text-center bg-success text-white"> + <h3 className="mb-0">Create Your Account</h3> + </div> + <div + className="card-body p-5 text-center" + style={{ backgroundColor: "#a6a6a6" }} + > + {error ? <Alert variant="danger">{error}</Alert> : null} - <div className="row"> - <div className="form-outline mb-0"> - <h4>First Name</h4> - </div> - <div className="form-outline mb-4"> - <input - type="text" - placeholder="John" - id="typePasswordX-2" - className="form-control form-control-lg" - value={firstName} - onChange={(e) => { - setFirstName(e.target.value); - }} - /> - </div> - <div className="form-outline mb-0"> - <h4>Last Name</h4> - </div> - <div className="form-outline mb-4"> - <input - type="text" - placeholder="Doe" - id="typePasswordX-2" - className="form-control form-control-lg" - value={lastName} - onChange={(e) => { - setLastName(e.target.value); - }} - /> - </div> - </div> + <div className="row align-items-center"> + <div className="form-outline mb-4"> + <input + type="text" + placeholder="Username" + id="typeEmailX-2" + className="form-control form-control-lg" + value={username} + onChange={(e) => { + setUsername(e.target.value); + }} + /> + </div> + <div className="form-outline mb-4"> + <input + type="email" + placeholder="Email Address" + id="typePasswordX-2" + className="form-control form-control-lg" + value={email} + onChange={(e) => { + setEmail(e.target.value); + }} + /> + </div> + </div> - <div className="row"> - <div className="form-outline mb-0"> - <h4>Address</h4> - </div> - <div className="form-outline mb-4"> - <input - type="text" - placeholder="1 Main St, Anytown, CA 12345" - id="typePasswordX-2" - className="form-control form-control-lg" - value={location} - onChange={(e) => { - setLocation(e.target.value); - }} - /> - </div> - <div className="form-outline mb-0"> - <h4>Phone Number</h4> - </div> - <div className="form-outline mb-4"> - <input - type="phone" - placeholder="(555) 555-5555" - id="typePasswordX-2" - className="form-control form-control-lg" - value={phone} - onChange={(e) => { - setPhone(e.target.value); - }} - /> - </div> - </div> + <div className="row"> + <div className="form-outline mb-4 col-6"> + <input + type="password" + placeholder="Password" + id="typePasswordX-2" + className="form-control form-control-lg" + value={password} + onChange={(e) => { + setPassword(e.target.value); + }} + /> + </div> + <div className="form-outline mb-4 col-6"> + <input + type="password" + placeholder="Retype Password" + id="typePasswordX-2" + className="form-control form-control-lg" + value={rePassword} + onChange={(e) => { + setRePassword(e.target.value); + }} + /> + </div> + </div> - <button className="btn btn-success btn-lg btn-block" onClick={createUser}> - Register - </button> + <div className="row"> + <div className="form-outline mb-4 col-6"> + <input + type="text" + placeholder="First Name" + id="typePasswordX-2" + className="form-control form-control-lg" + value={firstName} + onChange={(e) => { + setFirstName(e.target.value); + }} + /> + </div> + <div className="form-outline mb-4 col-6"> + <input + type="text" + placeholder="Last Name" + id="typePasswordX-2" + className="form-control form-control-lg" + value={lastName} + onChange={(e) => { + setLastName(e.target.value); + }} + /> + </div> + </div> - <Modal show={showModal}> - <Modal.Header closeButton> - <Modal.Title>Registration</Modal.Title> - </Modal.Header> - <Modal.Body>Account created. Welcome to DartCart!</Modal.Body> - <Modal.Footer> - <Button onClick={handleClose}>Close</Button> - </Modal.Footer> - </Modal> - </div> - </div> - </div> + <div className="row"> + <div className="form-outline mb-4"> + <input + type="text" + placeholder="Home Address" + id="typePasswordX-2" + className="form-control form-control-lg" + value={location} + onChange={(e) => { + setLocation(e.target.value); + }} + /> </div> + <div className="form-outline mb-4"> + <input + type="phone" + placeholder="Phone Number" + id="typePasswordX-2" + className="form-control form-control-lg" + value={phone} + onChange={(e) => { + setPhone(e.target.value); + }} + /> + </div> + </div> + + <button + className="btn btn-success btn-lg btn-block" + onClick={createUser} + > + Register + </button> + + <Modal show={showModal}> + <Modal.Header closeButton> + <Modal.Title>Registration</Modal.Title> + </Modal.Header> + <Modal.Body> + Account created. Welcome to DartCart! + </Modal.Body> + <Modal.Footer> + <Button onClick={handleClose}>Close</Button> + </Modal.Footer> + </Modal> </div> - </section> - </> - ); + </div> + </div> + </div> + </div> + </section> + </> + ); } export default UserRegister; From 6065c90a491710f7e43420eb21139016f03f631d Mon Sep 17 00:00:00 2001 From: David Melanson Jr <david427@live.com> Date: Wed, 9 Mar 2022 21:30:32 -0500 Subject: [PATCH 3/5] Updated navbar --- dart-cart-client/src/App.css | 33 ++++ .../features/authentication/SellerAccess.tsx | 0 dart-cart-client/src/features/layout/Logo.tsx | 39 ++--- .../src/features/layout/Navbar.tsx | 157 ++++++++---------- .../src/features/layout/Searchbar.tsx | 90 +++++----- 5 files changed, 165 insertions(+), 154 deletions(-) create mode 100644 dart-cart-client/src/features/authentication/SellerAccess.tsx diff --git a/dart-cart-client/src/App.css b/dart-cart-client/src/App.css index 6ab2ca1d..809749aa 100644 --- a/dart-cart-client/src/App.css +++ b/dart-cart-client/src/App.css @@ -44,3 +44,36 @@ .fa { color: rgb(25, 135, 84); } + +.ProductCardContainer { + margin: 2%; + display: flex; + flex-wrap: wrap; + background-color: #1b1b1b; + border-style: solid; + border-width: 0.5rem; + border-color: #5f5f5f; +} + +.navbar-brand { + display: flex; + justify-content: center; + width: 40%; + margin: auto; +} + +.navbar-header { + display: flex; + justify-content: flex-end; + width: 30%; + margin: auto; +} + +.nav-item { + margin: auto; +} + +.navbar-custom { + padding: 1rem; + margin-top: -10px; +} diff --git a/dart-cart-client/src/features/authentication/SellerAccess.tsx b/dart-cart-client/src/features/authentication/SellerAccess.tsx new file mode 100644 index 00000000..e69de29b diff --git a/dart-cart-client/src/features/layout/Logo.tsx b/dart-cart-client/src/features/layout/Logo.tsx index eb09894a..88d08974 100644 --- a/dart-cart-client/src/features/layout/Logo.tsx +++ b/dart-cart-client/src/features/layout/Logo.tsx @@ -4,31 +4,26 @@ import { Navbar } from "react-bootstrap"; import { Link } from "react-router-dom"; const logoStyle = { - height: "15%", - width: "15%", - marginLeft: "3%", + height: "50px", + width: "75px", + marginLeft: "5%" }; const Logo = () => { - return ( - <> - <Navbar> - <Link to="/" style={{ textDecoration: "none", color: "black" }}> - <h2>DartCart</h2> - </Link> - <Link to="/" style={{ textDecoration: "none", color: "black" }}> - <div style={{ textAlign: "left" }}> - <img - className="logo-img" - style={logoStyle} - src={logo} - alt="logo" - ></img> - </div> - </Link> - </Navbar> - </> - ); + return ( + <> + <Navbar style={{ width: "30%" }}> + <Link to="/" style={{ textDecoration: "none", color: "black" }}> + <h2>DartCart</h2> + </Link> + <Link to="/" style={{ textDecoration: "none", color: "black" }}> + <div style={{ textAlign: "left" }}> + <img className="logo-img" style={logoStyle} src={logo} alt="logo"></img> + </div> + </Link> + </Navbar> + </> + ); }; export default Logo; diff --git a/dart-cart-client/src/features/layout/Navbar.tsx b/dart-cart-client/src/features/layout/Navbar.tsx index cfd5031a..8269a30c 100644 --- a/dart-cart-client/src/features/layout/Navbar.tsx +++ b/dart-cart-client/src/features/layout/Navbar.tsx @@ -6,94 +6,81 @@ import { clearCart } from "../../common/slices/cartSlice"; import { RootState } from "../../common/types"; const Nav = (props) => { - const dispatch = useDispatch(); - const [name, setName] = useState(""); - const user = - useSelector((state: RootState) => state.authentication.user) || ""; + const dispatch = useDispatch(); + const [name, setName] = useState(""); + const user = useSelector((state: RootState) => state.authentication.user) || ""; - useEffect(() => { - if (user) { - const u = JSON.parse(user); - setName(u.firstName); - } - }, [user]); + useEffect(() => { + if (user) { + const u = JSON.parse(user); + setName(u.firstName); + } + }, [user]); - const handleLogout = () => { - dispatch(logout(null)); - dispatch(clearCart()); - }; + const handleLogout = () => { + dispatch(logout(null)); + dispatch(clearCart()); + }; - return ( - <nav className="navbar-header"> - <ul - className="navbar-nav mr-auto link-container" - style={!props.footer ? { textAlign: "center" } : {}} - > - {user ? ( - <> - <li className="nav-item-mb-3 nav-item"> - <h3>Welcome {name}</h3> - </li> - <li className="nav-item-mb-3 nav-item"> - <Link to="/" className="text-reset nav-link"> - Home - </Link> - </li> - <li className="nav-item-mb-3 nav-item"> - <Link to="/signup" className="text-reset nav-link"> - Create a Shop - </Link> - </li> - <li className="nav-item-mb-3 nav-item"> - <Link - to="/" - className="text-reset nav-link" - onClick={handleLogout} - > - Logout - </Link> - </li> - {!props.footer ? ( - <li className="nav-item-mb-3 nav-item"> - <Link to="/cart" type="button" className="btn btn-success"> - <svg - xmlns="http://www.w3.org/2000/svg" - width="16" - height="16" - fill="currentColor" - className="bi bi-cart" - viewBox="0 0 16 16" - > - <path d="M0 1.5A.5.5 0 0 1 .5 1H2a.5.5 0 0 1 .485.379L2.89 3H14.5a.5.5 0 0 1 .491.592l-1.5 8A.5.5 0 0 1 13 12H4a.5.5 0 0 1-.491-.408L2.01 3.607 1.61 2H.5a.5.5 0 0 1-.5-.5zM3.102 4l1.313 7h8.17l1.313-7H3.102zM5 12a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm7 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm-7 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm7 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"></path> - </svg> - </Link> - </li> - ) : ( - "" - )} - </> - ) : ( - <> - <li className="nav-item-mb-3 nav-item"> - <Link to="/" className="text-reset nav-link"> - Home - </Link> - </li> - <li className="nav-item-mb-3 nav-item"> - <Link to="/login" className="text-reset nav-link"> - Login - </Link> - </li> - <li className="nav-item-mb-3 nav-item"> - <Link to="/register" className="text-reset nav-link"> - Register - </Link> - </li> - </> - )} - </ul> - </nav> - ); + return ( + <nav className="navbar-header"> + <ul className="navbar-nav mr-auto link-container" style={!props.footer ? { textAlign: "center" } : {}}> + {user ? ( + <> + <li className="nav-item-mb-3 nav-item"> + <span style={{ fontWeight: "bold" }}>Welcome, {name} |</span> + </li> + <li className="nav-item-mb-3 nav-item"> + <Link to="/signup" className="text-reset nav-link"> + Sell + </Link> + </li> + <li className="nav-item-mb-3 nav-item"> + <Link to="/" className="text-reset nav-link" onClick={handleLogout}> + Logout + </Link> + </li> + {!props.footer ? ( + <li className="nav-item-mb-3 nav-item"> + <Link to="/cart" type="button" className="btn btn-success"> + <svg + xmlns="http://www.w3.org/2000/svg" + width="16" + height="16" + fill="currentColor" + className="bi bi-cart" + viewBox="0 0 16 16" + > + <path d="M0 1.5A.5.5 0 0 1 .5 1H2a.5.5 0 0 1 .485.379L2.89 3H14.5a.5.5 0 0 1 .491.592l-1.5 8A.5.5 0 0 1 13 12H4a.5.5 0 0 1-.491-.408L2.01 3.607 1.61 2H.5a.5.5 0 0 1-.5-.5zM3.102 4l1.313 7h8.17l1.313-7H3.102zM5 12a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm7 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm-7 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm7 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"></path> + </svg> + </Link> + </li> + ) : ( + "" + )} + </> + ) : ( + <> + <li className="nav-item-mb-3 nav-item"> + <Link to="/" className="text-reset nav-link"> + Home + </Link> + </li> + <li className="nav-item-mb-3 nav-item"> + <Link to="/login" className="text-reset nav-link"> + Login + </Link> + </li> + <li className="nav-item-mb-3 nav-item"> + <Link to="/register" className="text-reset nav-link"> + Register + </Link> + </li> + </> + )} + </ul> + </nav> + ); }; export default Nav; diff --git a/dart-cart-client/src/features/layout/Searchbar.tsx b/dart-cart-client/src/features/layout/Searchbar.tsx index 2542b290..2567d08f 100644 --- a/dart-cart-client/src/features/layout/Searchbar.tsx +++ b/dart-cart-client/src/features/layout/Searchbar.tsx @@ -1,59 +1,55 @@ import React, { useRef } from "react"; import { useDispatch, useSelector } from "react-redux"; -import { - fetchShopProducts, - getSearchString, - updatedSearchString, -} from "../../common/slices/shopProductSlice"; +import { fetchShopProducts, getSearchString, updatedSearchString } from "../../common/slices/shopProductSlice"; import { useNavigate } from "react-router-dom"; const Searchbar = () => { - const dispatch = useDispatch(); - const string = useRef<HTMLInputElement>(null); - const search: string = useSelector(getSearchString); + const dispatch = useDispatch(); + const string = useRef<HTMLInputElement>(null); + const search: string = useSelector(getSearchString); - const nav = useNavigate(); - const handleSearch = (e: any) => { - dispatch(fetchShopProducts(search)); - nav("/display"); - }; + const nav = useNavigate(); + const handleSearch = (e: any) => { + dispatch(fetchShopProducts(search)); + nav("/display"); + }; - const onChangeHandler = (e: any) => { - dispatch(updatedSearchString(string.current?.value)); - }; + const onChangeHandler = (e: any) => { + dispatch(updatedSearchString(string.current?.value)); + }; - return ( - <div className="navbar-brand" style={{ width: " 60%", marginLeft: "20px" }}> - <div className="form-inline my-2 my-lg-0"> - <button - onClick={(e) => handleSearch(e)} - className="btn btn-success" - value="Search" - style={{ float: "right", backgroundColor: "#198754" }} - > - Search{" "} - </button> - <div style={{ overflow: "hidden", paddingRight: ".5em" }}> - <input - type="text" - placeholder="Search" - style={{ width: "100%" }} - ref={string} - onKeyUp={(e) => { - // Check if keypress is enter button - if (e.key === "Enter") { - handleSearch(e); - } - }} - onBlur={(e) => handleSearch(e)} - onChange={(e) => { - onChangeHandler(e); - }} - /> + return ( + <div className="navbar-brand"> + <div className="form-inline my-2 my-lg-0" style={{ width: "100%" }}> + <button + onClick={(e) => handleSearch(e)} + className="btn btn-success" + value="Search" + style={{ float: "right", backgroundColor: "#198754" }} + > + Search{" "} + </button> + <div style={{ overflow: "hidden", paddingRight: ".5em" }}> + <input + type="text" + placeholder="Search" + style={{ width: "100%" }} + ref={string} + onKeyUp={(e) => { + // Check if keypress is enter button + if (e.key === "Enter") { + handleSearch(e); + } + }} + onBlur={(e) => handleSearch(e)} + onChange={(e) => { + onChangeHandler(e); + }} + /> + </div> + </div> </div> - </div> - </div> - ); + ); }; export default Searchbar; From 87e9134e8e18548ba3604741a6d79dd2a97cd7f7 Mon Sep 17 00:00:00 2001 From: David Melanson Jr <david427@live.com> Date: Wed, 9 Mar 2022 21:31:31 -0500 Subject: [PATCH 4/5] Update footer links --- .../features/authentication/SellerAccess.tsx | 7 +++ .../src/features/layout/Footer.tsx | 60 +++++++++---------- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/dart-cart-client/src/features/authentication/SellerAccess.tsx b/dart-cart-client/src/features/authentication/SellerAccess.tsx index e69de29b..7c09449d 100644 --- a/dart-cart-client/src/features/authentication/SellerAccess.tsx +++ b/dart-cart-client/src/features/authentication/SellerAccess.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +const SellerAccess = () => { + return <div>SellerAccess</div>; +}; + +export default SellerAccess; diff --git a/dart-cart-client/src/features/layout/Footer.tsx b/dart-cart-client/src/features/layout/Footer.tsx index f5e58711..f00764df 100644 --- a/dart-cart-client/src/features/layout/Footer.tsx +++ b/dart-cart-client/src/features/layout/Footer.tsx @@ -2,42 +2,40 @@ import Navbar from "./Navbar"; import About from "./About"; import SocialMedia from "./SocialMedia"; import UsefulLinks from "./UsefulLinks"; +import FooterNav from "./FooterNav"; export default function Footer() { - // divs dealing with managing columns were not abstracted away so this area can focus on applying styles correctly + // divs dealing with managing columns were not abstracted away so this area can focus on applying styles correctly - return ( - <footer className="text-center text-lg-start bg-black"> - <section className="footer-info"> - <div className="container text-center text-md-start mt-5"> - <div className="row mt-3"> - <div className="col-md-3 col-lg-4 col-xl-3 mx-auto mb-4"> - <SocialMedia /> - </div> + return ( + <footer className="text-center text-lg-start bg-black"> + <section className="footer-info"> + <div className="container text-center text-md-start mt-5"> + <div className="row mt-3"> + <div className="col-md-3 col-lg-4 col-xl-3 mx-auto mb-4"> + <SocialMedia /> + </div> - <div className="col-md-2 col-lg-2 col-xl-2 mx-auto mb-4"> - <h6 className="text-uppercase fw-bold mb-4">Navigation</h6> - <Navbar footer="true" /> - </div> + <div className="col-md-2 col-lg-2 col-xl-2 mx-auto mb-4"> + <h6 className="text-uppercase fw-bold mb-4">Navigation</h6> + <FooterNav /> + </div> - <div className="col-md-3 col-lg-2 col-xl-2 mx-auto mb-4"> - <h6 className="text-uppercase fw-bold mb-4">Useful links</h6> - <UsefulLinks /> - </div> + <div className="col-md-3 col-lg-2 col-xl-2 mx-auto mb-4"> + <h6 className="text-uppercase fw-bold mb-4">Useful links</h6> + <UsefulLinks /> + </div> - <div className="col-md-4 col-lg-3 col-xl-3 mx-auto mb-md-0 mb-4"> - <About /> - </div> - </div> - </div> - </section> + <div className="col-md-4 col-lg-3 col-xl-3 mx-auto mb-md-0 mb-4"> + <About /> + </div> + </div> + </div> + </section> - <div - className="text-center p-4" - style={{ backgroundColor: "rgba(0, 0, 0, 0.05)" }} - > - © 2022 Dart Cart - </div> - </footer> - ); + <div className="text-center p-4" style={{ backgroundColor: "rgba(0, 0, 0, 0.05)" }}> + © 2022 Dart Cart + </div> + </footer> + ); } From 46417621563711e4c77572e58a5b146f3fe0a249 Mon Sep 17 00:00:00 2001 From: David Melanson Jr <david427@live.com> Date: Wed, 9 Mar 2022 22:05:45 -0500 Subject: [PATCH 5/5] Added Sell button to combine homepage/signup --- dart-cart-client/src/App.tsx | 66 +++++++++---------- .../src/common/slices/authSlice.ts | 2 +- .../features/authentication/SellerAccess.tsx | 16 ++++- .../src/features/layout/Navbar.tsx | 7 +- .../seller-homepage/SellerHomepage.tsx | 2 +- .../src/features/shop-page/ShopPage.tsx | 55 ++++++++-------- 6 files changed, 76 insertions(+), 72 deletions(-) diff --git a/dart-cart-client/src/App.tsx b/dart-cart-client/src/App.tsx index 4dc814f9..5c8b8adb 100644 --- a/dart-cart-client/src/App.tsx +++ b/dart-cart-client/src/App.tsx @@ -19,44 +19,40 @@ import Checkout from "./features/checkout/CheckoutDisplay"; import ListItem from "./features/list-item/ListItem"; import ShopPage from "./features/shop-page/ShopPage"; import SellerHomepage from "./features/seller-homepage/SellerHomepage"; +import SellerAccess from "./features/authentication/SellerAccess"; function App() { - useEffect(() => { - document.title = "DartCart"; - // - }); + useEffect(() => { + document.title = "DartCart"; + // + }); - return ( - <div className="App"> - <BrowserRouter> - <Provider store={store}> - <Header /> - <Routes> - <Route path="/" element={<Display />}></Route> - <Route - path="/sellers/:seller_homepage" - element={<SellerHomepage />} - ></Route> - <Route path="/shops/:shop_id" element={<ShopPage />}></Route> - <Route path="/shops/:shop_id/list" element={<ListItem />}></Route> - <Route path="/cart" element={<Cart />}></Route> - <Route path="/register" element={<UserRegister />}></Route> - <Route path="/signup" element={<SellerRegister />}></Route> - <Route path="/login" element={<Login />}></Route> - <Route path="/orders" element={<PreviousOrders />}></Route> - <Route path="/checkout" element={<Checkout />}></Route> - <Route path="/display" element={<Display />}></Route> - <Route - path="/shop-product/:shop_product_id" - element={<ShopProductDisplay />} - ></Route> - <Route path="/*" element={<Error404Page />}></Route> - </Routes> - <Footer /> - </Provider> - </BrowserRouter> - </div> - ); + return ( + <div className="App"> + <BrowserRouter> + <Provider store={store}> + <Header /> + <Routes> + <Route path="/" element={<Display />}></Route> + <Route path="/sellers" element={<SellerAccess />}></Route> + <Route path="/sellers/:seller_homepage" element={<SellerHomepage />}></Route> + <Route path="/shops/:shop_id" element={<ShopPage />}></Route> + <Route path="/shops/:shop_id/list" element={<ListItem />}></Route> + <Route path="/cart" element={<Cart />}></Route> + <Route path="/register" element={<UserRegister />}></Route> + <Route path="/signup" element={<SellerRegister />}></Route> + <Route path="/login" element={<Login />}></Route> + <Route path="/orders" element={<PreviousOrders />}></Route> + <Route path="/checkout" element={<Checkout />}></Route> + <Route path="/display" element={<Display />}></Route> + <Route path="/shop-product/:shop_product_id" element={<ShopProductDisplay />}></Route> + <Route path="/*" element={<Error404Page />}></Route> + </Routes> + <Footer /> + </Provider> + </BrowserRouter> + </div> + ); } export default App; diff --git a/dart-cart-client/src/common/slices/authSlice.ts b/dart-cart-client/src/common/slices/authSlice.ts index 1bf69e26..297e04c0 100644 --- a/dart-cart-client/src/common/slices/authSlice.ts +++ b/dart-cart-client/src/common/slices/authSlice.ts @@ -131,7 +131,7 @@ export const loginUser = createAsyncThunk( ); export const fetchSeller = createAsyncThunk("authentication/fetchSeller", async (id: number) => { - return axios.get(`${API_URL}sellers/${id}`, { headers: authHeader() }).then((response) => { + return axios.get(`${API_URL}sellers/users/${id}`, { headers: authHeader() }).then((response) => { localStorage.setItem("seller", JSON.stringify(response.data)); }); }); diff --git a/dart-cart-client/src/features/authentication/SellerAccess.tsx b/dart-cart-client/src/features/authentication/SellerAccess.tsx index 7c09449d..4f697e88 100644 --- a/dart-cart-client/src/features/authentication/SellerAccess.tsx +++ b/dart-cart-client/src/features/authentication/SellerAccess.tsx @@ -1,7 +1,19 @@ -import React from "react"; +import React, { useEffect } from "react"; +import { useSelector } from "react-redux"; +import { useNavigate } from "react-router-dom"; +import { selectSeller } from "../../common/slices/authSlice"; +import { RootState } from "../../common/store"; const SellerAccess = () => { - return <div>SellerAccess</div>; + const stateSeller = useSelector(selectSeller); + const seller = JSON.parse(stateSeller); + const nav = useNavigate(); + + useEffect(() => { + seller ? nav(`${seller.homepage}`) : nav("/signup"); + }, []); + + return <></>; }; export default SellerAccess; diff --git a/dart-cart-client/src/features/layout/Navbar.tsx b/dart-cart-client/src/features/layout/Navbar.tsx index 8269a30c..edd13508 100644 --- a/dart-cart-client/src/features/layout/Navbar.tsx +++ b/dart-cart-client/src/features/layout/Navbar.tsx @@ -31,7 +31,7 @@ const Nav = (props) => { <span style={{ fontWeight: "bold" }}>Welcome, {name} |</span> </li> <li className="nav-item-mb-3 nav-item"> - <Link to="/signup" className="text-reset nav-link"> + <Link to="/sellers" className="text-reset nav-link"> Sell </Link> </li> @@ -61,11 +61,6 @@ const Nav = (props) => { </> ) : ( <> - <li className="nav-item-mb-3 nav-item"> - <Link to="/" className="text-reset nav-link"> - Home - </Link> - </li> <li className="nav-item-mb-3 nav-item"> <Link to="/login" className="text-reset nav-link"> Login diff --git a/dart-cart-client/src/features/seller-homepage/SellerHomepage.tsx b/dart-cart-client/src/features/seller-homepage/SellerHomepage.tsx index db89529b..60c062fb 100644 --- a/dart-cart-client/src/features/seller-homepage/SellerHomepage.tsx +++ b/dart-cart-client/src/features/seller-homepage/SellerHomepage.tsx @@ -14,7 +14,7 @@ export const SellerHomepage = () => { const nav = useNavigate(); useEffect(() => { - dispatch(fetchShop(seller[0].id)); + dispatch(fetchShop(seller.id)); }, []); const handleOnClick = () => { diff --git a/dart-cart-client/src/features/shop-page/ShopPage.tsx b/dart-cart-client/src/features/shop-page/ShopPage.tsx index 6680cba5..b2727307 100644 --- a/dart-cart-client/src/features/shop-page/ShopPage.tsx +++ b/dart-cart-client/src/features/shop-page/ShopPage.tsx @@ -4,41 +4,42 @@ import { useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { selectShop } from "../../common/slices/authSlice"; - const ShopPage = () => { - - const stateShop = useSelector(selectShop) - const shop = JSON.parse(stateShop) - const nav = useNavigate() + const stateShop = useSelector(selectShop); + const shop = JSON.parse(stateShop); + const nav = useNavigate(); const handleOnClick = () => { - nav(`/shops/${shop.id}/list`) - } + nav(`/shops/${shop.id}/list`); + }; return ( <> - <section className="vh-200"> - <div className="container py-5 h-100"> - <div className="row d-flex justify-content-center align-items-center h-100"> - <div className="col-10"> - <div className="card shadow-2-strong" style={{ borderRadius: "1rem" }}> - <div className="card-header card text-center bg-success text-white"> - <h3 className="mb-0">Shop #</h3> - </div> - <CardGroup> - <Card className="text-center" style={{ width: "18rem" }}> - <Card.Body> - <Card.Title>{`Shop location`}</Card.Title> + <section className="vh-200"> + <div className="container py-5 h-100"> + <div className="row d-flex justify-content-center align-items-center h-100"> + <div className="col-10"> + <div className="card shadow-2-strong" style={{ borderRadius: "1rem" }}> + <div className="card-header card text-center bg-success text-white"> + <h3 className="mb-0">{`Shop #${shop.id}`}</h3> + </div> + <CardGroup> + <Card className="text-center" style={{ width: "18rem" }}> + <Card.Body> + <Card.Title>{shop.location}</Card.Title> - <Button onClick={handleOnClick} variant="success">List Item</Button> - </Card.Body> - </Card> - </CardGroup> + <Button onClick={handleOnClick} variant="success"> + List Item + </Button> + </Card.Body> + </Card> + </CardGroup> + </div> </div> </div> </div> - </div> - </section> - </> - )}; + </section> + </> + ); +}; export default ShopPage;