Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions public/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!-- <!DOCTYPE html>
<html lang="en">

<head>
Expand Down Expand Up @@ -55,4 +55,4 @@
crossorigin="anonymous"></script>
</body>

</html>
</html> -->
7 changes: 1 addition & 6 deletions src/components/Footer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@ const Footer = () => {
<footer className="mb-0 text-center">
<div className="d-flex align-items-center justify-content-center pb-5">
<div className="col-md-6">
<p className="mb-3 mb-md-0">Made with ❤️ by {" "}
<a href="https://sahibsingh.dev" className="text-decoration-underline text-dark fs-5" target="_blank" rel="noreferrer">Sahib Singh</a>
</p>
<a className="text-dark fs-4" href="https://github.com/ssahibsingh" target="_blank" rel="noreferrer">
<i className="fa fa-github"></i>
</a>
<p className="mb-3 mb-md-0">Made with ❤️ by Bikash </p>
</div>
</div>
</footer>
Expand Down
101 changes: 62 additions & 39 deletions src/components/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,66 @@
import React from 'react'
import { NavLink } from 'react-router-dom'
import { useSelector } from 'react-redux'
import React from "react";
import { NavLink } from "react-router-dom";
import { useSelector } from "react-redux";

const Navbar = () => {
const state = useSelector(state => state.handleCart)
return (
<nav className="navbar navbar-expand-lg navbar-light bg-light py-3 sticky-top">
<div className="container">
<NavLink className="navbar-brand fw-bold fs-4 px-2" to="/"> React Ecommerce</NavLink>
<button className="navbar-toggler mx-2" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
const state = useSelector((state) => state.handleCart);
return (
<nav className="navbar navbar-expand-lg navbar-light bg-light py-3 sticky-top">
<div className="container">
<NavLink className="navbar-brand fw-bold fs-4 px-2" to="/">
{" "}
Ecommerce MPilot{" "}
</NavLink>
<button
className="navbar-toggler mx-2"
type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span className="navbar-toggler-icon"></span>
</button>

<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav m-auto my-2 text-center">
<li className="nav-item">
<NavLink className="nav-link" to="/">Home </NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to="/product">Products</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to="/about">About</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to="/contact">Contact</NavLink>
</li>
</ul>
<div className="buttons text-center">
<NavLink to="/login" className="btn btn-outline-dark m-2"><i className="fa fa-sign-in-alt mr-1"></i> Login</NavLink>
<NavLink to="/register" className="btn btn-outline-dark m-2"><i className="fa fa-user-plus mr-1"></i> Register</NavLink>
<NavLink to="/cart" className="btn btn-outline-dark m-2"><i className="fa fa-cart-shopping mr-1"></i> Cart ({state.length}) </NavLink>
</div>
</div>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav m-auto my-2 text-center">
<li className="nav-item">
<NavLink className="nav-link" to="/">
Home{" "}
</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to="/product">
Products
</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to="/about">
About
</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to="/contact">
Contact
</NavLink>
</li>
</ul>
<div className="buttons text-center">
<NavLink to="/login" className="btn btn-outline-dark m-2">
<i className="fa fa-sign-in-alt mr-1"></i> Login
</NavLink>
<NavLink to="/register" className="btn btn-outline-dark m-2">
<i className="fa fa-user-plus mr-1"></i> Register
</NavLink>
<NavLink to="/cart" className="btn btn-outline-dark m-2">
<i className="fa fa-cart-shopping mr-1"></i> Cart ({state.length}){" "}
</NavLink>
</div>
</div>
</div>
</nav>
);
};


</div>
</nav>
)
}

export default Navbar
export default Navbar;
219 changes: 219 additions & 0 deletions src/components/forms/addProduct.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
import { Button, Label } from "flowbite-react";
import { Formik, Form, Field } from "formik";
import { object, string } from "zod";
import { toFormikValidationSchema } from "zod-formik-adapter";

const addProudctFormSchema = object({
title: string({
required_error: "*Please enter a title",
}),
price: string({
required_error: "*Please enter an price",
}),
description: string({
required_error: "*Please enter description",
}),
image: string({
required_error: "*Image is required",
}),
category: string({
required_error: "*Category is required",
}),
});

export type TProduct = {
id?: string,
title?: string,
price?: string,
description?: string,
image?: string,
category?: string,
};

const AddProductForm = ({
id,
title,
price,
description,
image,
category,
}: TProduct) => {
return (
<>
<Formik
initialValues={{
title: id ? title : "",
price: id ? price : "",
description: id ? description : "",
image: id ? image : "",
category: id ? category : "",
}}
onSubmit={async (values, { resetForm }) => {
alert("Form is submitted. Thank You !!");

try {
if (id) {
const productResponse = await fetch(
`https://fakestoreapi.com/products/${Number(id)}`,
{
method: "PUT",
body: JSON.stringify({
title: values.title,
price: Number(values.price),
description: values.description,
image: values.image,
category: values.category,
}),
}
);

if (productResponse.ok) {
const data = await productResponse.json();
console.log("Data updated successfully", data);
resetForm();
} else {
throw new Error("Error while updating product");
}
} else {
const productResponse = await fetch(
"https://fakestoreapi.com/products",
{
method: "POST",
body: JSON.stringify({
title: values.title,
price: Number(values.price),
description: values.description,
image: values.image,
category: values.category,
}),
}
);

if (productResponse.ok) {
const data = await productResponse.json();
console.log("Data added successfully", data);
resetForm();
} else {
throw new Error("Error while adding product");
}
}
} catch (error) {
console.log(error);
}
}}
validationSchema={toFormikValidationSchema(addProudctFormSchema)}
>
{(formikSate) => {
const errors = formikSate.errors;

return (
<Form>
<div>
<div>
<Label value="Title" className="text-md font-semibold" />
</div>

<div className="my-2">
<Field
type="text"
name="title"
placeholder="Enter title"
className="rounded-lg w-full"
/>
{!!errors.title && (
<div className="text-red-500 pt-2">{errors.title}</div>
)}
</div>
</div>

<div className="mt-4">
<div>
<Label value="Price" className="text-md font-semibold" />
</div>

<div className="my-2">
<Field
type="text"
name="price"
placeholder="Enter price"
className="rounded-lg w-full"
/>
{!!errors.price && (
<div className="text-red-500 pt-2">{errors.title}</div>
)}
</div>
</div>

<div className="mt-4">
<div>
<Label
value="Description"
className="text-md font-semibold"
/>
</div>

<div className="my-2">
<Field
type="text"
name="description"
placeholder="Enter description"
className="rounded-lg w-full"
/>
{!!errors.price && (
<div className="text-red-500 pt-2">
{errors.description}
</div>
)}
</div>
</div>

<div className="mt-4">
<div>
<Label value="Image" className="text-md font-semibold" />
</div>

<div className="my-2">
<Field
type="text"
name="image"
placeholder="Enter image"
className="rounded-lg w-full"
/>
{!!errors.image && (
<div className="text-red-500 pt-2">{errors.image}</div>
)}
</div>
</div>

<div className="mt-4">
<div>
<Label value="Category" className="text-md font-semibold" />
</div>

<div className="my-2">
<Field
type="text"
name="category"
placeholder="Enter category"
className="rounded-lg w-full"
/>
{!!errors.category && (
<div className="text-red-500 pt-2">{errors.category}</div>
)}
</div>
</div>

<div className="pt-6">
<Button color="dark" type="submit">
Submit
</Button>
</div>
</Form>
);
}}
</Formik>
</>
);
};

export default AddProductForm;
8 changes: 4 additions & 4 deletions src/components/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ const Home = () => {
/>
<div className="card-img-overlay d-flex align-items-center">
<div className="container">
<h5 className="card-title fs-1 text fw-lighter">New Season Arrivals</h5>
<h5 className="card-title fs-1 text fw-lighter">
New Season Arrivals
</h5>
<p className="card-text fs-5 d-none d-sm-block ">
This is a wider card with supporting text below as a natural
lead-in to additional content. This content is a little bit
longer.
Explore the men and women new collection available in the shops.
</p>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
Register,
Checkout,
PageNotFound,
addProduct,
} from "./pages";
import ScrollToTop from "./components/ScrollToTop";
import { Toaster } from "react-hot-toast";
Expand Down
Loading