From 0c414a571a9edd240ff23204f91228bcd540bf1e Mon Sep 17 00:00:00 2001 From: Shihan Date: Mon, 8 May 2023 16:56:37 +0530 Subject: [PATCH 1/9] frontend fertilizer list, fertilizer form, fertilizer generator --- package.json | 21 ------ src/components/AddFertilizer.js | 0 src/components/FertilizerForm.css | 69 +++++++++++++++++ src/components/FertilizerForm.js | 100 +++++++++++++++++++++++++ src/components/FertilizerGenTable.js | 38 ++++++++++ src/components/FertilizerGenerator.css | 54 +++++++++++++ src/components/FertilizerGenerator.js | 51 +++++++++++++ src/components/FertilizerList.css | 40 ++++++++++ src/components/FertilizerList.js | 65 ++++++++++++++++ 9 files changed, 417 insertions(+), 21 deletions(-) delete mode 100644 package.json create mode 100644 src/components/AddFertilizer.js create mode 100644 src/components/FertilizerForm.css create mode 100644 src/components/FertilizerForm.js create mode 100644 src/components/FertilizerGenTable.js create mode 100644 src/components/FertilizerGenerator.css create mode 100644 src/components/FertilizerGenerator.js create mode 100644 src/components/FertilizerList.css create mode 100644 src/components/FertilizerList.js diff --git a/package.json b/package.json deleted file mode 100644 index a5f7a1d..0000000 --- a/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "greenstore", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" - }, - "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@types/react": "^18.0.28", - "@types/react-dom": "^18.0.11", - "@vitejs/plugin-react": "^3.1.0", - "vite": "^4.2.0" - } -} diff --git a/src/components/AddFertilizer.js b/src/components/AddFertilizer.js new file mode 100644 index 0000000..e69de29 diff --git a/src/components/FertilizerForm.css b/src/components/FertilizerForm.css new file mode 100644 index 0000000..54f2643 --- /dev/null +++ b/src/components/FertilizerForm.css @@ -0,0 +1,69 @@ +.fertilizer-form { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + width: 50%; + margin: 0 auto; + padding: 2rem; + border: 2px solid #ccc; + border-radius: 4px; + background-color: #F4FFF8; +} + +.form-group { + display: flex; + flex-direction: column; + width: calc(50% - 1rem); + margin-bottom: 1rem; +} + +label { + font-size: 1.2rem; + font-weight: bold; + margin-bottom: 0.5rem; + color: #2E8B57; +} + +input[type="text"] { + font-size: 1.2rem; + padding: 0.5rem; + border: none; + border-radius: 4px; + border-bottom: 2px solid #ccc; + outline: none; + background-color: white; + color: #2E8B57; + width: 100%; +} + +input[type="text"]:focus { + border-color: #4caf50; +} + +button[type="submit"] { + font-size: 1.2rem; + padding: 0.5rem 1rem; + background-color: #2E8B57; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.3s ease-in-out; + outline: none; +} + +button[type="submit"]:hover { + background-color: #228B22; +} + +.form-topic { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: bold; + font-size: 1.5rem; + margin-top: 0; + text-align: center; + width: 100%; + margin-bottom: 2rem; + color: #2E8B57; +} diff --git a/src/components/FertilizerForm.js b/src/components/FertilizerForm.js new file mode 100644 index 0000000..4a2f599 --- /dev/null +++ b/src/components/FertilizerForm.js @@ -0,0 +1,100 @@ +import React, { useState } from "react"; +import "./FertilizerForm.css"; + +const FertilizerForm = ({ onFertilizerSubmit }) => { + const [fertilizer, setFertilizer] = useState({ + name: "", + weight: "", + price: "", + manufacturingDate: "", + createdDate: "", + }); + + const handleInputChange = (event) => { + const { name, value } = event.target; + setFertilizer((prevFertilizer) => ({ + ...prevFertilizer, + [name]: value, + })); + }; + + const handleSubmit = (event) => { + event.preventDefault(); + onFertilizerSubmit(fertilizer); + setFertilizer({ + name: "", + weight: "", + price: "", + manufacturingDate: "", + createdDate: "", + }); + }; + + return ( +
+ +

ADD NEW FERTILIZER

+ +
+ + +
+ + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ ); +}; + +export default FertilizerForm; diff --git a/src/components/FertilizerGenTable.js b/src/components/FertilizerGenTable.js new file mode 100644 index 0000000..d6dcfb5 --- /dev/null +++ b/src/components/FertilizerGenTable.js @@ -0,0 +1,38 @@ +import React from "react"; +import "./FertilizerGenerator.css"; // import your CSS file + +const FertilizerTable = () => { + const data = [ + { plantName: "Tomato", growthStage: "Vegetative", time: "Morning", fertilizerType: "NPK 20-20-20" }, + { plantName: "Lettuce", growthStage: "Seedling", time: "Afternoon", fertilizerType: "NPK 10-10-10" }, + { plantName: "Pepper", growthStage: "Flowering", time: "Evening", fertilizerType: "NPK 15-15-15" }, + ]; + + return ( +
+

History Data

+ + + + + + + + + + + {data.map((item, index) => ( + + + + + + + ))} + +
Plant NameGrowth StageTimeFertilizer Type
{item.plantName}{item.growthStage}{item.time}{item.fertilizerType}
+
+ ); +}; + +export default FertilizerTable; diff --git a/src/components/FertilizerGenerator.css b/src/components/FertilizerGenerator.css new file mode 100644 index 0000000..66887cc --- /dev/null +++ b/src/components/FertilizerGenerator.css @@ -0,0 +1,54 @@ +form { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; + border: 2px solid #ccc; + padding: 1rem; + border-radius: 4px; + } + + label { + display: flex; + flex-direction: column; + align-items: flex-start; + margin-right: 1rem; + } + + input[type="text"] { + padding: 0.5rem; + margin-top: 0.5rem; + font-size: 1rem; + border: none; + border-radius: 4px; + border-bottom: 2px solid #ccc; + outline: none; + } + + input[type="text"]:focus { + border-color: #4caf50; + } + + button[type="submit"] { + padding: 0.5rem 1rem; + font-size: 1rem; + background-color: #4caf50; + color: #fff; + border: none; + border-radius: 4px; + cursor: pointer; + outline: none; + } + + button[type="submit"]:hover { + background-color: #388e3c; + } + .page-title { + text-align: center; + font-size: 2rem; + font-weight: bold; + margin-top: 2rem; + margin-bottom: 2rem; + } + \ No newline at end of file diff --git a/src/components/FertilizerGenerator.js b/src/components/FertilizerGenerator.js new file mode 100644 index 0000000..b95570f --- /dev/null +++ b/src/components/FertilizerGenerator.js @@ -0,0 +1,51 @@ +import React, { useState } from "react"; +import "./FertilizerGenerator.css"; // import your CSS file + +const FertilizerGeneratorForm = () => { + const [plantName, setPlantName] = useState(""); + const [growthStage, setGrowthStage] = useState(""); + const [time, setTime] = useState(""); + + const handleSubmit = (event) => { + event.preventDefault(); + // Call the FertilizerGenerator component with the input values + }; + + return ( +
+ +

Generate Fertilizer

+ + + + + +
+ ); +}; + +export default FertilizerGeneratorForm; diff --git a/src/components/FertilizerList.css b/src/components/FertilizerList.css new file mode 100644 index 0000000..49dc3a7 --- /dev/null +++ b/src/components/FertilizerList.css @@ -0,0 +1,40 @@ +table { + border-collapse: collapse; + width: 100%; + margin: 0 auto; + } + + th, + td { + padding: 0.5rem; + text-align: left; + border-bottom: 1px solid #ccc; + } + + th { + background-color: #4caf50; + color: #fff; + } + + tr:nth-child(even) { + background-color: #f2f2f2; + } + + tr:hover { + background-color: #e2e2e2; + } + + p { + text-align: center; + font-size: 1.5rem; + font-weight: bold; + } + + .page-title { + text-align: center; + font-size: 2rem; + font-weight: bold; + margin-top: 2rem; + margin-bottom: 2rem; + } + \ No newline at end of file diff --git a/src/components/FertilizerList.js b/src/components/FertilizerList.js new file mode 100644 index 0000000..fe54385 --- /dev/null +++ b/src/components/FertilizerList.js @@ -0,0 +1,65 @@ +import React from "react"; +import "./FertilizerList.css"; + +const dummyData = [ + { + id: 1, + name: "Phosphorus fertilizer", + weight: "1 kg", + price: "Rs. 480", + manufacturingDate: "2023-03-23", + createdDate: "2023-03-23", + }, + { + id: 2, + name: "Phosphorus fertilizer", + weight: "1 kg", + price: "Rs. 480 ", + manufacturingDate: "2023-03-23", + createdDate: "2023-03-23", + }, +]; + +const FertilizerList = ({ fertilizers = dummyData }) => { + if (!fertilizers.length) { + return ( +
+

No fertilizers found.

+
+ ); + } + + return ( +
+

Available Fertilizers

+ + + + + + + + + + + + + + {fertilizers.map((fertilizer) => ( + + + + + + + + ))} + +
NameWeightPriceManufacturing DateCreated Date
{fertilizer.name}{fertilizer.weight}{fertilizer.price}{fertilizer.manufacturingDate}{fertilizer.createdDate}
+ +
+ ); + +}; + +export default FertilizerList; From 79cdc9760679250800b01eb30df6cbea7f7a513f Mon Sep 17 00:00:00 2001 From: Shihan Date: Tue, 9 May 2023 22:31:30 +0530 Subject: [PATCH 2/9] report generater, add fertilizer --- src/App.jsx | 48 ++++----- src/components/FertilizerForm.css | 114 +++++++++++--------- src/components/FertilizerForm.js | 145 ++++++++++---------------- src/components/FertilizerGenTable.js | 93 ++++++++++------- src/components/FertilizerGenerator.js | 80 +++++++++++--- src/components/FertilizerList.css | 6 +- src/components/FertilizerList.js | 98 ++++++++--------- 7 files changed, 316 insertions(+), 268 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 2ba469d..0d45509 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,34 +1,32 @@ import { useState } from 'react' -import reactLogo from './assets/react.svg' -import viteLogo from '/vite.svg' -import './App.css' +import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +import FertilizerForm from "./components/FertilizerForm"; +import ViewFertilizers from "./components/FertilizerList"; +import FertilizerGenerator from "./components/FertilizerGenerator"; +import FertilizerTable from "./components/FertilizerGenTable"; function App() { - const [count, setCount] = useState(0) return ( -
-
- - Vite logo - - - React logo - -
-

Vite + React

-
- -

- Edit src/App.jsx and save to test HMR -

-
-

- Click on the Vite and React logos to learn more -

+
+ + } /> + + + + } /> + + + } /> + + + + +
+ ) } diff --git a/src/components/FertilizerForm.css b/src/components/FertilizerForm.css index 54f2643..6a2bd4a 100644 --- a/src/components/FertilizerForm.css +++ b/src/components/FertilizerForm.css @@ -1,69 +1,87 @@ -.fertilizer-form { +.fertilizer-form-container { display: flex; - flex-wrap: wrap; - justify-content: space-between; - align-items: center; - width: 50%; - margin: 0 auto; - padding: 2rem; - border: 2px solid #ccc; - border-radius: 4px; - background-color: #F4FFF8; + justify-content: center; +} + +.fertilizer-form { + border: 1px solid #ccc; + padding: 20px; + width: 400px; +} + +.form-topic { + text-align: center; } .form-group { - display: flex; - flex-direction: column; - width: calc(50% - 1rem); - margin-bottom: 1rem; + margin-bottom: 10px; } label { - font-size: 1.2rem; - font-weight: bold; - margin-bottom: 0.5rem; - color: #2E8B57; + display: block; + margin-bottom: 5px; } -input[type="text"] { - font-size: 1.2rem; - padding: 0.5rem; - border: none; - border-radius: 4px; - border-bottom: 2px solid #ccc; - outline: none; - background-color: white; - color: #2E8B57; +input { width: 100%; + padding: 10px; + border-radius: 5px; + border: 1px solid #ccc; + box-sizing: border-box; } -input[type="text"]:focus { - border-color: #4caf50; -} - -button[type="submit"] { - font-size: 1.2rem; - padding: 0.5rem 1rem; - background-color: #2E8B57; +button { + background-color: #4CAF50; color: white; + padding: 10px 20px; border: none; - border-radius: 4px; + border-radius: 5px; cursor: pointer; - transition: background-color 0.3s ease-in-out; - outline: none; + margin-top: 10px; + margin-bottom: 50px; } -button[type="submit"]:hover { - background-color: #228B22; +form { + display: flex; + flex-direction: column; + align-items: center; + margin: 50px auto; + width: 80%; + background-color: #F0FFF0; /* Change background color */ + border: 1px solid #008000; /* Add border */ + padding: 20px; } -.form-topic { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: bold; - font-size: 1.5rem; - margin-top: 0; - text-align: center; +label { + display: flex; + flex-direction: column; + margin: 20px 0; width: 100%; - margin-bottom: 2rem; - color: #2E8B57; + max-width: 500px; + color: #008000; /* Change label color */ +} + +select { + margin-top: 5px; + padding: 10px; + border: none; + border-radius: 5px; + font-size: 16px; + background-color: #FFFFFF; /* Change select background color */ + color: #008000; /* Change select color */ +} + +button { + margin-top: 30px; + padding: 10px 20px; + border: none; + border-radius: 5px; + font-size: 18px; + background-color: #008000; /* Change button background color */ + color: #FFFFFF; + cursor: pointer; +} + +button:hover { + background-color: #006400; /* Change button hover color */ } diff --git a/src/components/FertilizerForm.js b/src/components/FertilizerForm.js index 4a2f599..ef180ed 100644 --- a/src/components/FertilizerForm.js +++ b/src/components/FertilizerForm.js @@ -1,100 +1,67 @@ -import React, { useState } from "react"; +import React, { useState } from 'react'; +import axios from 'axios'; import "./FertilizerForm.css"; +import DatePicker from 'react-datepicker'; +import 'react-datepicker/dist/react-datepicker.css'; -const FertilizerForm = ({ onFertilizerSubmit }) => { - const [fertilizer, setFertilizer] = useState({ - name: "", - weight: "", - price: "", - manufacturingDate: "", - createdDate: "", - }); - const handleInputChange = (event) => { - const { name, value } = event.target; - setFertilizer((prevFertilizer) => ({ - ...prevFertilizer, - [name]: value, - })); - }; +function FertilizerForm() { + const [name, setName] = useState(''); + const [weight, setWeight] = useState(''); + const [price, setPrice] = useState(''); + const [manufacturingDate, setManufacturingDate] = useState(''); + const [createdDate, setCreatedDate] = useState(''); - const handleSubmit = (event) => { + const handleSubmit = async (event) => { event.preventDefault(); - onFertilizerSubmit(fertilizer); - setFertilizer({ - name: "", - weight: "", - price: "", - manufacturingDate: "", - createdDate: "", - }); - }; + try { + const fertilizer = { name, weight, price, manufacturingDate, createdDate }; + const response = await axios.post('http://localhost:8070/fertilizers/create', fertilizer); + console.log(response); + alert(`${fertilizer.name} Added`); + setName(""); + setWeight(""); + setPrice(""); + setManufacturingDate(""); + setCreatedDate(""); + - return ( -
- -

ADD NEW FERTILIZER

- -
- - -
+ } catch (error) { + console.log(error); + } + } + return ( +
+
+

Add Fertilizer

+ +
+ + setName(event.target.value)} required /> +
+
+ + setWeight(event.target.value)} required /> +
+
+ + setPrice(event.target.value)} required /> +
+
+ + setManufacturingDate(date)} dateFormat="dd/MM/yyyy" required/> -
- - -
-
- - -
-
- - -
-
- - +
+
+ + setCreatedDate(date)} dateFormat="dd/MM/yyyy" required/> +
+ +
- - - ); -}; +
+ ) +} export default FertilizerForm; diff --git a/src/components/FertilizerGenTable.js b/src/components/FertilizerGenTable.js index d6dcfb5..0f7c747 100644 --- a/src/components/FertilizerGenTable.js +++ b/src/components/FertilizerGenTable.js @@ -1,38 +1,61 @@ -import React from "react"; -import "./FertilizerGenerator.css"; // import your CSS file +const fertilizers = { + tomato: { + Seedling: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + Vegetative: { type: "Nitrogen", amount: "1", frequency: "Every 2 weeks" }, + Fruiting: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + }, + lettuce: { + Seedling: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + Vegetative: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + Heading: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + }, + cucumber: { + Seedling: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + Vegetative: { type: "Nitrogen", amount: "1", frequency: "Every 2 weeks" }, + Flowering: { type: "Phosphorus", amount: "1", frequency: "Every 2 weeks" }, + Fruiting: { type: "Potassium", amount: "1", frequency: "Every 2 weeks" }, + }, + bell_pepper: { + Seedling: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + Vegetative: { type: "Nitrogen", amount: "1", frequency: "Every 2 weeks" }, + Flowering: { type: "Phosphorus", amount: "1", frequency: "Every 2 weeks" }, + Fruiting: { type: "Potassium", amount: "1", frequency: "Every 2 weeks" }, + }, + zucchini: { + Seedling: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + Vegetative: { type: "Nitrogen", amount: "1", frequency: "Every 2 weeks" }, + Flowering: { type: "Phosphorus", amount: "1", frequency: "Every 2 weeks" }, + Fruiting: { type: "Potassium", amount: "1", frequency: "Every 2 weeks" }, + }, + carrot: { + Seedling: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + Vegetative: { type: "Phosphorus", amount: "1", frequency: "Every 2 weeks" }, + Rooting: { type: "Potassium", amount: "1", frequency: "Every 2 weeks" }, + }, + broccoli: { + Seedling: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + Vegetative: { type: "Nitrogen", amount: "1", frequency: "Every 2 weeks" }, + Flowering: { type: "Phosphorus", amount: "1", frequency: "Every 2 weeks" }, + }, + spinach: { + Seedling: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + Vegetative: { type: "Nitrogen", amount: "1", frequency: "Every 2 weeks" }, + Heading: { type: "Phosphorus", amount: "1", frequency: "Every 2 weeks" }, + }, + corn: { + Seedling: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + Vegetative: { type: "Nitrogen", amount: "1", frequency: "Every 2 weeks" }, + Tasseling: { type: "Phosphorus", amount: "1", frequency: "Every 2 weeks" }, + Pollinating: { type: "Potassium", amount: "1", frequency: "Every 2 weeks" }, + }, + pumpkin: { + Seedling: { type: "Nitrogen", amount: "0.5", frequency: "Every 2 weeks" }, + Vegetative: { type: "Nitrogen", amount: "1", frequency: "Every 2 weeks" }, + Flowering: { type: "Phosphorus", amount: "1", frequency: "Every 2 weeks" }, + Fruiting: { type: "Potassium", amount: "1", frequency: "Every 2 weeks" }, + } -const FertilizerTable = () => { - const data = [ - { plantName: "Tomato", growthStage: "Vegetative", time: "Morning", fertilizerType: "NPK 20-20-20" }, - { plantName: "Lettuce", growthStage: "Seedling", time: "Afternoon", fertilizerType: "NPK 10-10-10" }, - { plantName: "Pepper", growthStage: "Flowering", time: "Evening", fertilizerType: "NPK 15-15-15" }, - ]; - - return ( -
-

History Data

- - - - - - - - - - - {data.map((item, index) => ( - - - - - - - ))} - -
Plant NameGrowth StageTimeFertilizer Type
{item.plantName}{item.growthStage}{item.time}{item.fertilizerType}
-
- ); + // Add more plants and growth stages as needed }; -export default FertilizerTable; +export default fertilizers; diff --git a/src/components/FertilizerGenerator.js b/src/components/FertilizerGenerator.js index b95570f..dc27a6c 100644 --- a/src/components/FertilizerGenerator.js +++ b/src/components/FertilizerGenerator.js @@ -1,32 +1,63 @@ import React, { useState } from "react"; -import "./FertilizerGenerator.css"; // import your CSS file +import fertilizers from "../components/FertilizerGenTable"; + const FertilizerGeneratorForm = () => { const [plantName, setPlantName] = useState(""); const [growthStage, setGrowthStage] = useState(""); const [time, setTime] = useState(""); + const [fertilizerType, setFertilizerType] = useState(""); + const [fertilizerAmount, setFertilizerAmount] = useState(""); + const [fertilizerFrequency, setFertilizerFrequency] = useState(""); + const handleSubmit = (event) => { event.preventDefault(); - // Call the FertilizerGenerator component with the input values + + // Check if plantName and growthStage are valid before accessing fertilizers object + if (fertilizers[plantName] && fertilizers[plantName][growthStage]) { + let { type, amount, frequency } = fertilizers[plantName][growthStage]; + + if (time === "Morning") { + // Increase nitrogen by 25% + amount *= 1.25; + } else if (time === "Afternoon") { + // Decrease nitrogen by 25% + amount *= 0.75; + } + + setFertilizerType(type); + setFertilizerAmount(amount); + setFertilizerFrequency(frequency); + } else { + // Handle case where plantName or growthStage is invalid + setFertilizerType(""); + setFertilizerAmount(""); + setFertilizerFrequency(""); + } }; return (
+

Generate Fertilizer

+ -

Generate Fertilizer

- + + + + + + + + + + + + + + + + +
TypeAmountFrequency
{fertilizerType}{fertilizerAmount} pounds{fertilizerFrequency}
+ + +
+ + + + ); }; diff --git a/src/components/FertilizerList.css b/src/components/FertilizerList.css index 49dc3a7..7b096ce 100644 --- a/src/components/FertilizerList.css +++ b/src/components/FertilizerList.css @@ -1,4 +1,5 @@ table { + margin-bottom: 100px; border-collapse: collapse; width: 100%; margin: 0 auto; @@ -37,4 +38,7 @@ table { margin-top: 2rem; margin-bottom: 2rem; } - \ No newline at end of file + + h1 { + text-align: center; + } \ No newline at end of file diff --git a/src/components/FertilizerList.js b/src/components/FertilizerList.js index fe54385..5ea0c45 100644 --- a/src/components/FertilizerList.js +++ b/src/components/FertilizerList.js @@ -1,65 +1,49 @@ -import React from "react"; +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; import "./FertilizerList.css"; -const dummyData = [ - { - id: 1, - name: "Phosphorus fertilizer", - weight: "1 kg", - price: "Rs. 480", - manufacturingDate: "2023-03-23", - createdDate: "2023-03-23", - }, - { - id: 2, - name: "Phosphorus fertilizer", - weight: "1 kg", - price: "Rs. 480 ", - manufacturingDate: "2023-03-23", - createdDate: "2023-03-23", - }, -]; +function Fertilizers() { + const [fertilizers, setFertilizers] = useState([]); -const FertilizerList = ({ fertilizers = dummyData }) => { - if (!fertilizers.length) { - return ( -
-

No fertilizers found.

-
- ); - } + useEffect(() => { + axios.get('http://localhost:8070/fertilizers/') + .then(response => { + setFertilizers(response.data); + }) + .catch(error => { + console.log(error); + }) + }, []); return ( -
-

Available Fertilizers

- - - - - - - - - - - - - - {fertilizers.map((fertilizer) => ( - - - - - - +
+

Fertilizers

+
NameWeightPriceManufacturing DateCreated Date
{fertilizer.name}{fertilizer.weight}{fertilizer.price}{fertilizer.manufacturingDate}{fertilizer.createdDate}
+ + + + + + + - ))} - -
NameWeightPriceManufacturing DateCreated Date
- + + + {fertilizers.map(fertilizer => { + return ( + + {fertilizer.name} + {fertilizer.weight} + {fertilizer.price} + {fertilizer.manufacturingDate} + {fertilizer.createdDate} + + ) + })} + +
- ); - -}; + ) +} -export default FertilizerList; +export default Fertilizers; From 3b7f2681634436e7fc2b2d418bcb400e1a835257 Mon Sep 17 00:00:00 2001 From: Shihan Date: Sat, 13 May 2023 17:18:32 +0530 Subject: [PATCH 3/9] Commit route files --- src/routers/App.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/routers/App.js diff --git a/src/routers/App.js b/src/routers/App.js new file mode 100644 index 0000000..925784f --- /dev/null +++ b/src/routers/App.js @@ -0,0 +1,39 @@ +import React, { useState } from "react"; +import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +import FertilizerForm from "./components/FertilizerForm"; +import ViewFertilizers from "./components/FertilizerList"; +import FertilizerGenerator from "./components/FertilizerGenerator"; +import CustomerRegistrationForm from "./components/CustomerRegistrationForm"; +import Navbar from "./components/Navbar"; + +function App() { + + return ( + +
+ + } /> + + + + } /> + + + + } /> + + + + } /> + + + } /> + + +
+ +
+ ); +} + +export default App; From ff3c0c3be8e9434490026017afef83cac06b4add Mon Sep 17 00:00:00 2001 From: Shihan Date: Mon, 15 May 2023 12:26:03 +0530 Subject: [PATCH 4/9] Customer registration, fertilizer generator update, view customers, edit fertilizer, --- src/components/CustomerEdit.js | 83 ++++++++++++++++ src/components/CustomerList.js | 69 +++++++++++++ src/components/CustomerLogin.css | 0 src/components/CustomerLoginForm.js | 46 +++++++++ src/components/CustomerRegistrationForm.css | 37 +++++++ src/components/CustomerRegistrationForm.js | 67 +++++++++++++ src/components/FertilizerEdit.js | 85 ++++++++++++++++ src/components/FertilizerForm.css | 44 --------- src/components/FertilizerForm.js | 9 +- src/components/FertilizerGen.css | 45 +++++++++ src/components/FertilizerGenerator.js | 64 +++++++++--- src/components/FertilizerList.css | 2 +- src/components/FertilizerList.js | 35 ++++++- src/components/FertilizerView.js | 47 +++++++++ src/components/Navbar.css | 104 ++++++++++++++++++++ src/components/Navbar.js | 53 ++++++++++ src/routers/App.js | 43 +++++++- 17 files changed, 766 insertions(+), 67 deletions(-) create mode 100644 src/components/CustomerEdit.js create mode 100644 src/components/CustomerList.js create mode 100644 src/components/CustomerLogin.css create mode 100644 src/components/CustomerLoginForm.js create mode 100644 src/components/CustomerRegistrationForm.css create mode 100644 src/components/CustomerRegistrationForm.js create mode 100644 src/components/FertilizerEdit.js create mode 100644 src/components/FertilizerGen.css create mode 100644 src/components/FertilizerView.js create mode 100644 src/components/Navbar.css create mode 100644 src/components/Navbar.js diff --git a/src/components/CustomerEdit.js b/src/components/CustomerEdit.js new file mode 100644 index 0000000..dc077fe --- /dev/null +++ b/src/components/CustomerEdit.js @@ -0,0 +1,83 @@ +import { useEffect, useState } from 'react'; +import "./CustomerRegistrationForm.css"; +import axios from 'axios'; +import { Link, useParams } from 'react-router-dom'; + +export default function CustomerEditForm() { + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [city, setCity] = useState(''); + const [state, setState] = useState(''); + const [zipCode, setZipCode] = useState(''); + + const { id } = useParams(); + + useEffect(() => { + const fetchUserData = async () => { + try { + const response = await axios.get(`http://localhost:8070/customers/${id}`); + const userData = response.data; + setName(userData.name); + setEmail(userData.email); + setPassword(userData.password); + setCity(userData.city); + setState(userData.state); + setZipCode(userData.zipCode); + } catch (error) { + console.log(error); + } + }; + + fetchUserData(); + }, [id]); + + const handleSubmit = async (e) => { + e.preventDefault(); + try { + const updatedCustomer = { name, email, password, city, state, zipCode }; + const response = await axios.patch(`http://localhost:8070/customers/${id}`, updatedCustomer); + console.log(response); + alert(`${updatedCustomer.name} Updated`); + } catch (error) { + console.log(error); + } + }; + + + return ( +
+ View Customers + +

Update Data

+
+ + + + + + + + +
+
+ ); +} diff --git a/src/components/CustomerList.js b/src/components/CustomerList.js new file mode 100644 index 0000000..13bba76 --- /dev/null +++ b/src/components/CustomerList.js @@ -0,0 +1,69 @@ +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; +import { Link } from 'react-router-dom'; + +function CustomerList() { + const [customers, setCustomers] = useState([]); + + useEffect(() => { + axios.get('http://localhost:8070/customers/') + .then(response => { + setCustomers(response.data); + }) + .catch(error => { + console.log(error); + }) + }, []); + + const handleDelete = (id) => { + axios.delete(`http://localhost:8070/customers/${id}`) + .then(() => { + setCustomers(customers => customers.filter(customer => customer._id !== id)); + alert("Customer deleted successfully"); + }) + .catch(error => { + console.log(error); + }); + }; + + + return ( +
+

Customers

+ + + + + + + + + + + + + + {customers.map(customer => { + return ( + + + + + + + + + + ) + })} + +
NameEmailCityStateZip CodeAction
{customer.name}{customer.email}{customer.city}{customer.state}{customer.zipCode} + Show Details + + +
+
+ ) +} + +export default CustomerList; diff --git a/src/components/CustomerLogin.css b/src/components/CustomerLogin.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/CustomerLoginForm.js b/src/components/CustomerLoginForm.js new file mode 100644 index 0000000..a6c5b32 --- /dev/null +++ b/src/components/CustomerLoginForm.js @@ -0,0 +1,46 @@ +import React, { useState } from 'react'; +import './CustomerLogin.css'; + +function LoginForm() { + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + + const handleSubmit = (event) => { + event.preventDefault(); + console.log(`Submitted login form with username "${username}" and password "${password}"`); + // TODO: Send login request to server + }; + + return ( + +
+

Customer Login

+ +
+ + setUsername(event.target.value)} + required + /> + + + setPassword(event.target.value)} + required + /> + + +
+
+ ); +} + +export default LoginForm; diff --git a/src/components/CustomerRegistrationForm.css b/src/components/CustomerRegistrationForm.css new file mode 100644 index 0000000..91afa59 --- /dev/null +++ b/src/components/CustomerRegistrationForm.css @@ -0,0 +1,37 @@ +form { + display: flex; + flex-direction: column; + max-width: 400px; + margin: 0 auto; + } + + label { + margin-top: 10px; + font-size: 16px; + font-weight: bold; + } + + input { + width: 100%; + padding: 10px; + margin-top: 5px; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 16px; + } + + button[type="submit"] { + background-color: #8bc34a; + color: #fff; + border: none; + border-radius: 4px; + font-size: 16px; + padding: 10px; + margin-top: 10px; + cursor: pointer; + } + + button[type="submit"]:hover { + background-color: #689f38; + } + \ No newline at end of file diff --git a/src/components/CustomerRegistrationForm.js b/src/components/CustomerRegistrationForm.js new file mode 100644 index 0000000..099143b --- /dev/null +++ b/src/components/CustomerRegistrationForm.js @@ -0,0 +1,67 @@ +import { useState } from 'react'; +import "./CustomerRegistrationForm.css"; +import axios from 'axios'; +import { Link } from 'react-router-dom'; + +export default function CustomerRegistrationForm() { + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [city, setCity] = useState(''); + const [state, setState] = useState(''); + const [zipCode, setZipCode] = useState(''); + + const handleSubmit = async (e) => { + e.preventDefault(); + try { + const customer = { name, email, password, city, state, zipCode }; + const response = await axios.post('http://localhost:8070/customers/create', customer); + console.log(response); + alert(`${customer.name} Added`); + setName(""); + setEmail(""); + setPassword(""); + setCity(""); + setState(""); + setZipCode(""); + + + } catch (error) { + console.log(error); + } + }; + + return ( +
+ View Customers +

Customer Register Form

+
+ + + + + + + +
+
+ ); +} diff --git a/src/components/FertilizerEdit.js b/src/components/FertilizerEdit.js new file mode 100644 index 0000000..9df4e41 --- /dev/null +++ b/src/components/FertilizerEdit.js @@ -0,0 +1,85 @@ +import { useEffect, useState } from 'react'; +import axios from 'axios'; +import "./FertilizerForm.css"; +import DatePicker from 'react-datepicker'; +import 'react-datepicker/dist/react-datepicker.css'; +import { Link, useParams } from 'react-router-dom'; + +function FertilizerEditForm() { + const [name, setName] = useState(''); + const [weight, setWeight] = useState(''); + const [price, setPrice] = useState(''); + const [type, setType] = useState(''); + const [manufacturingDate, setManufacturingDate] = useState(''); + const [createdDate, setCreatedDate] = useState(''); + + const { id } = useParams(); + + useEffect(() => { + const fetchFertilizerData = async () => { + try { + const response = await axios.get(`http://localhost:8070/fertilizers/${id}`); + const fertilizerData = response.data; + setName(fertilizerData.name); + setWeight(fertilizerData.weight); + setPrice(fertilizerData.price); + setType(fertilizerData.type); + setManufacturingDate(new Date(fertilizerData.manufacturingDate)); + setCreatedDate(new Date(fertilizerData.createdDate)); + } catch (error) { + console.log(error); + } + }; + + fetchFertilizerData(); + }, [id]); + + const handleSubmit = async (event) => { + event.preventDefault(); + try { + const updatedFertilizer = { name, weight, price,type, manufacturingDate, createdDate }; + const response = await axios.patch(`http://localhost:8070/fertilizers/${id}`, updatedFertilizer); + console.log(response); + alert(`${updatedFertilizer.name} Updated`); + } catch (error) { + console.log(error); + } + }; + + return ( +
+ View Fertilizers + +

Update Fertilizer Data

+
+
+ + setName(event.target.value)} required /> +
+
+ + setWeight(event.target.value)} required /> +
+
+ + setPrice(event.target.value)} required /> +
+
+ + setType(event.target.value)} required /> +
+
+ + setManufacturingDate(date)} dateFormat="dd/MM/yyyy" required/> +
+
+ + setCreatedDate(date)} dateFormat="dd/MM/yyyy" required/> +
+ +
+
+ ) +} + +export default FertilizerEditForm; diff --git a/src/components/FertilizerForm.css b/src/components/FertilizerForm.css index 6a2bd4a..66c134c 100644 --- a/src/components/FertilizerForm.css +++ b/src/components/FertilizerForm.css @@ -41,47 +41,3 @@ button { margin-bottom: 50px; } -form { - display: flex; - flex-direction: column; - align-items: center; - margin: 50px auto; - width: 80%; - background-color: #F0FFF0; /* Change background color */ - border: 1px solid #008000; /* Add border */ - padding: 20px; -} - -label { - display: flex; - flex-direction: column; - margin: 20px 0; - width: 100%; - max-width: 500px; - color: #008000; /* Change label color */ -} - -select { - margin-top: 5px; - padding: 10px; - border: none; - border-radius: 5px; - font-size: 16px; - background-color: #FFFFFF; /* Change select background color */ - color: #008000; /* Change select color */ -} - -button { - margin-top: 30px; - padding: 10px 20px; - border: none; - border-radius: 5px; - font-size: 18px; - background-color: #008000; /* Change button background color */ - color: #FFFFFF; - cursor: pointer; -} - -button:hover { - background-color: #006400; /* Change button hover color */ -} diff --git a/src/components/FertilizerForm.js b/src/components/FertilizerForm.js index ef180ed..80e4292 100644 --- a/src/components/FertilizerForm.js +++ b/src/components/FertilizerForm.js @@ -9,19 +9,21 @@ function FertilizerForm() { const [name, setName] = useState(''); const [weight, setWeight] = useState(''); const [price, setPrice] = useState(''); + const [type, setType] = useState(''); const [manufacturingDate, setManufacturingDate] = useState(''); const [createdDate, setCreatedDate] = useState(''); const handleSubmit = async (event) => { event.preventDefault(); try { - const fertilizer = { name, weight, price, manufacturingDate, createdDate }; + const fertilizer = { name, weight, price, type, manufacturingDate, createdDate }; const response = await axios.post('http://localhost:8070/fertilizers/create', fertilizer); console.log(response); alert(`${fertilizer.name} Added`); setName(""); setWeight(""); setPrice(""); + setType(""); setManufacturingDate(""); setCreatedDate(""); @@ -48,6 +50,11 @@ function FertilizerForm() { setPrice(event.target.value)} required />
+
+ + setType(event.target.value)} required /> +
+
setManufacturingDate(date)} dateFormat="dd/MM/yyyy" required/> diff --git a/src/components/FertilizerGen.css b/src/components/FertilizerGen.css new file mode 100644 index 0000000..52afcd5 --- /dev/null +++ b/src/components/FertilizerGen.css @@ -0,0 +1,45 @@ +form { + display: flex; + flex-direction: column; + align-items: center; + margin: 50px auto; + width: 80%; + background-color: #F0FFF0; /* Change background color */ + border: 1px solid #008000; /* Add border */ + padding: 20px; + } + + label { + display: flex; + flex-direction: column; + margin: 20px 0; + width: 100%; + max-width: 500px; + color: #008000; /* Change label color */ + } + + select { + margin-top: 5px; + padding: 10px; + border: none; + border-radius: 5px; + font-size: 16px; + background-color: #FFFFFF; /* Change select background color */ + color: #008000; /* Change select color */ + } + + button { + margin-top: 30px; + padding: 10px 20px; + border: none; + border-radius: 5px; + font-size: 18px; + background-color: #008000; /* Change button background color */ + color: #FFFFFF; + cursor: pointer; + } + + button:hover { + background-color: #006400; /* Change button hover color */ + } + \ No newline at end of file diff --git a/src/components/FertilizerGenerator.js b/src/components/FertilizerGenerator.js index dc27a6c..f0e4581 100644 --- a/src/components/FertilizerGenerator.js +++ b/src/components/FertilizerGenerator.js @@ -1,6 +1,7 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; +import axios from "axios"; import fertilizers from "../components/FertilizerGenTable"; - +import "./FertilizerGen.css"; const FertilizerGeneratorForm = () => { const [plantName, setPlantName] = useState(""); @@ -9,28 +10,44 @@ const FertilizerGeneratorForm = () => { const [fertilizerType, setFertilizerType] = useState(""); const [fertilizerAmount, setFertilizerAmount] = useState(""); const [fertilizerFrequency, setFertilizerFrequency] = useState(""); - + const [filteredFertilizers, setFilteredFertilizers] = useState([]); + + + const fetchFertilizers = async (type) => { + try { + const response = await axios.get(`http://localhost:8070/fertilizers`); + const filteredData = response.data.filter((fertilizer) => + fertilizer.type.toLowerCase() === type.toLowerCase() + ); + setFilteredFertilizers(filteredData); + } catch (error) { + console.error(error); + } + }; + + const handleSubmit = (event) => { event.preventDefault(); - // Check if plantName and growthStage are valid before accessing fertilizers object if (fertilizers[plantName] && fertilizers[plantName][growthStage]) { let { type, amount, frequency } = fertilizers[plantName][growthStage]; if (time === "Morning") { - // Increase nitrogen by 25% + // Increase nitrogen in the morning because of the wet soil is good for absorption amount *= 1.25; } else if (time === "Afternoon") { - // Decrease nitrogen by 25% + // Decrease nitrogen amount *= 0.75; } setFertilizerType(type); setFertilizerAmount(amount); setFertilizerFrequency(frequency); + + fetchFertilizers(type); + } else { - // Handle case where plantName or growthStage is invalid setFertilizerType(""); setFertilizerAmount(""); setFertilizerFrequency(""); @@ -38,6 +55,8 @@ const FertilizerGeneratorForm = () => { }; return ( + +

Generate Fertilizer

diff --git a/src/components/FertilizerList.css b/src/components/FertilizerList.css index 7b096ce..b68d1e3 100644 --- a/src/components/FertilizerList.css +++ b/src/components/FertilizerList.css @@ -14,7 +14,7 @@ table { th { background-color: #4caf50; - color: #fff; + color: #271919; } tr:nth-child(even) { diff --git a/src/components/FertilizerList.js b/src/components/FertilizerList.js index 5ea0c45..4d622e9 100644 --- a/src/components/FertilizerList.js +++ b/src/components/FertilizerList.js @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import axios from 'axios'; import "./FertilizerList.css"; +import { Link } from 'react-router-dom'; function Fertilizers() { const [fertilizers, setFertilizers] = useState([]); @@ -15,8 +16,24 @@ function Fertilizers() { }) }, []); + + + const handleDelete = (id) => { + axios.delete(`http://localhost:8070/fertilizers/${id}`) + .then(() => { + setFertilizers(fertilizers => fertilizers.filter(fertilizer => fertilizer._id !== id)); + alert("Customer deleted successfully"); + }) + .catch(error => { + console.log(error); + }); + }; + return (
+
+ Go Back +

Fertilizers

@@ -24,8 +41,10 @@ function Fertilizers() { - - + + + + @@ -33,10 +52,16 @@ function Fertilizers() { return ( - - + + + - + + ) })} diff --git a/src/components/FertilizerView.js b/src/components/FertilizerView.js new file mode 100644 index 0000000..ba251df --- /dev/null +++ b/src/components/FertilizerView.js @@ -0,0 +1,47 @@ +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; +import './FertilizerList.css'; +import { Link } from 'react-router-dom'; + +function FertilizerList() { + const [fertilizers, setFertilizers] = useState([]); + + useEffect(() => { + axios.get('http://localhost:8070/fertilizers/') + .then(response => { + setFertilizers(response.data); + }) + .catch(error => { + console.log(error); + }) + }, []); + + + return ( +
+

Recommended Fertilizers

+
+ {fertilizers.map(fertilizer => ( +
+
+ + {fertilizer.name} + +
+
+

{fertilizer.name}

+

${fertilizer.price}

+
+ +
+
+
+ ))} +
+
+ ); +} + +export default FertilizerList; diff --git a/src/components/Navbar.css b/src/components/Navbar.css new file mode 100644 index 0000000..857562e --- /dev/null +++ b/src/components/Navbar.css @@ -0,0 +1,104 @@ +.navbar { + display: flex; + justify-content: space-between; + align-items: center; + background-color: #008CBA; + height: 60px; + padding: 0 20px; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); + font-family: 'Montserrat', sans-serif; + } + + .navbar__left { + display: flex; + align-items: center; + } + + .navbar__logo { + font-size: 24px; + font-weight: bold; + color: #fff; + text-decoration: none; + } + + .navbar__right { + display: flex; + align-items: center; + } + + .navbar__item { + margin-left: 20px; + } + + .navbar__link { + font-size: 16px; + color: #fff; + text-decoration: none; + transition: all 0.3s ease-in-out; + padding: 10px; + border-radius: 5px; + } + + .navbar__link:hover { + background-color: #fff; + color: #008CBA; + } + + + + + + .navbar__item:hover .dropdown-menu { + display: block; + } + + .dropdown-menu { + display: none; + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + border: 1px solid #ccc; + border-radius: 4px; + box-shadow: 0 6px 12px rgba(0,0,0,.175); + } + + .dropdown-menu li:hover { + background-color: #f5f5f5; + } + + .dropdown-menu li a:hover { + color: #333; + text-decoration: none; + } + + .dropdown-menu { + background-color: #fff; + border: 1px solid #ddd; + box-shadow: 0 2px 3px rgba(0, 0, 0, 0.15); + padding: 10px; + min-width: 150px; + } + + .dropdown-menu li { + margin-bottom: 10px; + text-align: center; + } + + .dropdown-menu li a { + color: #333; + text-decoration: none; + } + + .dropdown-menu li a:hover { + color: #007bff; + } + \ No newline at end of file diff --git a/src/components/Navbar.js b/src/components/Navbar.js new file mode 100644 index 0000000..3e75e34 --- /dev/null +++ b/src/components/Navbar.js @@ -0,0 +1,53 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import "./Navbar.css"; +import 'bootstrap/dist/css/bootstrap.min.css'; +import 'bootstrap/dist/js/bootstrap.min.js'; + + +function Navbar() { + return ( + + + ); +} + +export default Navbar; diff --git a/src/routers/App.js b/src/routers/App.js index 925784f..9f847c4 100644 --- a/src/routers/App.js +++ b/src/routers/App.js @@ -5,6 +5,11 @@ import ViewFertilizers from "./components/FertilizerList"; import FertilizerGenerator from "./components/FertilizerGenerator"; import CustomerRegistrationForm from "./components/CustomerRegistrationForm"; import Navbar from "./components/Navbar"; +import CustomerLoginForm from './components/CustomerLoginForm'; +import CustomerList from "./components/CustomerList"; +import CustomerEditForm from "./components/CustomerEdit"; +import FertilizerEditForm from "./components/FertilizerEdit"; +import FertilizerView from './components/FertilizerView'; function App() { @@ -14,15 +19,45 @@ function App() { } /> - - } /> + } /> + + + } /> + + + } /> + + + } /> + + + } /> + + + } /> + + + } /> + + + } /> + + + } /> + + + } /> + + + } /> - } /> - + + } /> + } /> From 450f76d2d6acaa4d6c508cf5bc5a8fc647c6a70a Mon Sep 17 00:00:00 2001 From: Shihan Date: Tue, 23 May 2023 14:43:32 +0530 Subject: [PATCH 5/9] add frontend code according to folder structure --- src/App.jsx | 32 +++-------- src/components/AddFertilizer.js | 0 src/components/FertilizerGenerator.css | 54 ------------------- src/components/{Navbar.js => Navbar.jsx} | 0 .../CustomerEdit.jsx} | 2 +- .../CustomerList.jsx} | 0 .../CustomerLoginForm.jsx} | 2 +- .../CustomerRegistrationForm.jsx} | 2 +- .../FertilizerEdit.jsx} | 2 +- .../FertilizerForm.jsx} | 2 +- .../FertilizerGenTable.jsx} | 0 .../FertilizerGenerator.jsx} | 40 +++++++++----- .../FertilizerList.jsx} | 3 +- .../FertilizerView.jsx} | 3 +- src/routers/.gitkeep | 0 src/{components => routes}/.gitkeep | 0 .../App.js => routes/FertilizerAppRoutes.jsx} | 20 +++---- .../customer}/CustomerLogin.css | 0 .../customer}/CustomerRegistrationForm.css | 0 .../fertilizer}/FertilizerForm.css | 0 .../fertilizer}/FertilizerGen.css | 22 ++++++++ .../fertilizer}/FertilizerList.css | 0 22 files changed, 74 insertions(+), 110 deletions(-) delete mode 100644 src/components/AddFertilizer.js delete mode 100644 src/components/FertilizerGenerator.css rename src/components/{Navbar.js => Navbar.jsx} (100%) rename src/components/{CustomerEdit.js => customer/CustomerEdit.jsx} (97%) rename src/components/{CustomerList.js => customer/CustomerList.jsx} (100%) rename src/components/{CustomerLoginForm.js => customer/CustomerLoginForm.jsx} (95%) rename src/components/{CustomerRegistrationForm.js => customer/CustomerRegistrationForm.jsx} (96%) rename src/components/{FertilizerEdit.js => fertilizers/FertilizerEdit.jsx} (98%) rename src/components/{FertilizerForm.js => fertilizers/FertilizerForm.jsx} (98%) rename src/components/{FertilizerGenTable.js => fertilizers/FertilizerGenTable.jsx} (100%) rename src/components/{FertilizerGenerator.js => fertilizers/FertilizerGenerator.jsx} (80%) rename src/components/{FertilizerList.js => fertilizers/FertilizerList.jsx} (97%) rename src/components/{FertilizerView.js => fertilizers/FertilizerView.jsx} (96%) delete mode 100644 src/routers/.gitkeep rename src/{components => routes}/.gitkeep (100%) rename src/{routers/App.js => routes/FertilizerAppRoutes.jsx} (71%) rename src/{components => styles/customer}/CustomerLogin.css (100%) rename src/{components => styles/customer}/CustomerRegistrationForm.css (100%) rename src/{components => styles/fertilizer}/FertilizerForm.css (100%) rename src/{components => styles/fertilizer}/FertilizerGen.css (71%) rename src/{components => styles/fertilizer}/FertilizerList.css (100%) diff --git a/src/App.jsx b/src/App.jsx index 0d45509..9e6bfb8 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,33 +1,13 @@ -import { useState } from 'react' -import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; -import FertilizerForm from "./components/FertilizerForm"; -import ViewFertilizers from "./components/FertilizerList"; -import FertilizerGenerator from "./components/FertilizerGenerator"; -import FertilizerTable from "./components/FertilizerGenTable"; +import FertilizerAppRoutes from "./routes/FertilizerAppRoutes"; +import './App.css'; function App() { return ( -
- - } /> - - - - } /> - - - } /> - - - - - +
+
- - ) + ); } -export default App +export default App; diff --git a/src/components/AddFertilizer.js b/src/components/AddFertilizer.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/FertilizerGenerator.css b/src/components/FertilizerGenerator.css deleted file mode 100644 index 66887cc..0000000 --- a/src/components/FertilizerGenerator.css +++ /dev/null @@ -1,54 +0,0 @@ -form { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - margin-bottom: 1rem; - border: 2px solid #ccc; - padding: 1rem; - border-radius: 4px; - } - - label { - display: flex; - flex-direction: column; - align-items: flex-start; - margin-right: 1rem; - } - - input[type="text"] { - padding: 0.5rem; - margin-top: 0.5rem; - font-size: 1rem; - border: none; - border-radius: 4px; - border-bottom: 2px solid #ccc; - outline: none; - } - - input[type="text"]:focus { - border-color: #4caf50; - } - - button[type="submit"] { - padding: 0.5rem 1rem; - font-size: 1rem; - background-color: #4caf50; - color: #fff; - border: none; - border-radius: 4px; - cursor: pointer; - outline: none; - } - - button[type="submit"]:hover { - background-color: #388e3c; - } - .page-title { - text-align: center; - font-size: 2rem; - font-weight: bold; - margin-top: 2rem; - margin-bottom: 2rem; - } - \ No newline at end of file diff --git a/src/components/Navbar.js b/src/components/Navbar.jsx similarity index 100% rename from src/components/Navbar.js rename to src/components/Navbar.jsx diff --git a/src/components/CustomerEdit.js b/src/components/customer/CustomerEdit.jsx similarity index 97% rename from src/components/CustomerEdit.js rename to src/components/customer/CustomerEdit.jsx index dc077fe..eab3d59 100644 --- a/src/components/CustomerEdit.js +++ b/src/components/customer/CustomerEdit.jsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import "./CustomerRegistrationForm.css"; +import "../../styles/customer/CustomerRegistrationForm.css"; import axios from 'axios'; import { Link, useParams } from 'react-router-dom'; diff --git a/src/components/CustomerList.js b/src/components/customer/CustomerList.jsx similarity index 100% rename from src/components/CustomerList.js rename to src/components/customer/CustomerList.jsx diff --git a/src/components/CustomerLoginForm.js b/src/components/customer/CustomerLoginForm.jsx similarity index 95% rename from src/components/CustomerLoginForm.js rename to src/components/customer/CustomerLoginForm.jsx index a6c5b32..db89cb0 100644 --- a/src/components/CustomerLoginForm.js +++ b/src/components/customer/CustomerLoginForm.jsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import './CustomerLogin.css'; +import "../../styles/customer/CustomerLogin.css"; function LoginForm() { const [username, setUsername] = useState(''); diff --git a/src/components/CustomerRegistrationForm.js b/src/components/customer/CustomerRegistrationForm.jsx similarity index 96% rename from src/components/CustomerRegistrationForm.js rename to src/components/customer/CustomerRegistrationForm.jsx index 099143b..44f4ae9 100644 --- a/src/components/CustomerRegistrationForm.js +++ b/src/components/customer/CustomerRegistrationForm.jsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import "./CustomerRegistrationForm.css"; +import "../../styles/customer/CustomerRegistrationForm.css"; import axios from 'axios'; import { Link } from 'react-router-dom'; diff --git a/src/components/FertilizerEdit.js b/src/components/fertilizers/FertilizerEdit.jsx similarity index 98% rename from src/components/FertilizerEdit.js rename to src/components/fertilizers/FertilizerEdit.jsx index 9df4e41..ab7b8e5 100644 --- a/src/components/FertilizerEdit.js +++ b/src/components/fertilizers/FertilizerEdit.jsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; import axios from 'axios'; -import "./FertilizerForm.css"; +import "../../styles/fertilizer/FertilizerForm.css"; import DatePicker from 'react-datepicker'; import 'react-datepicker/dist/react-datepicker.css'; import { Link, useParams } from 'react-router-dom'; diff --git a/src/components/FertilizerForm.js b/src/components/fertilizers/FertilizerForm.jsx similarity index 98% rename from src/components/FertilizerForm.js rename to src/components/fertilizers/FertilizerForm.jsx index 80e4292..20b6c13 100644 --- a/src/components/FertilizerForm.js +++ b/src/components/fertilizers/FertilizerForm.jsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import axios from 'axios'; -import "./FertilizerForm.css"; +import "../../styles/fertilizer/FertilizerForm.css"; import DatePicker from 'react-datepicker'; import 'react-datepicker/dist/react-datepicker.css'; diff --git a/src/components/FertilizerGenTable.js b/src/components/fertilizers/FertilizerGenTable.jsx similarity index 100% rename from src/components/FertilizerGenTable.js rename to src/components/fertilizers/FertilizerGenTable.jsx diff --git a/src/components/FertilizerGenerator.js b/src/components/fertilizers/FertilizerGenerator.jsx similarity index 80% rename from src/components/FertilizerGenerator.js rename to src/components/fertilizers/FertilizerGenerator.jsx index f0e4581..1d7f340 100644 --- a/src/components/FertilizerGenerator.js +++ b/src/components/fertilizers/FertilizerGenerator.jsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import axios from "axios"; -import fertilizers from "../components/FertilizerGenTable"; -import "./FertilizerGen.css"; +import fertilizers from "./FertilizerGenTable"; +import "../../styles/fertilizer/FertilizerGen.css"; const FertilizerGeneratorForm = () => { const [plantName, setPlantName] = useState(""); @@ -45,8 +45,9 @@ const FertilizerGeneratorForm = () => { setFertilizerAmount(amount); setFertilizerFrequency(frequency); - fetchFertilizers(type); + fetchFertilizers(type); + } else { setFertilizerType(""); setFertilizerAmount(""); @@ -54,6 +55,7 @@ const FertilizerGeneratorForm = () => { } }; + return (
@@ -111,7 +113,7 @@ const FertilizerGeneratorForm = () => {
Name Weight PriceManufacturing DateCreated DateTypeMFDAction
{fertilizer.name}{fertilizer.weight}{fertilizer.price}{fertilizer.weight} KGLKR {fertilizer.price}{fertilizer.type} {fertilizer.manufacturingDate}{fertilizer.createdDate} + Show Details + + +
-

Filtered Fertilizers

+

Find the most suitable fertilizer from the below

@@ -120,18 +122,30 @@ const FertilizerGeneratorForm = () => { + - {filteredFertilizers.map((fertilizer) => ( - - - - - - - - ))} + {filteredFertilizers.length === 0 ? ( + + + + ) : ( + filteredFertilizers.map((fertilizer) => ( + + + + + + + + + + )) + )}
Price Type Manufacturing Date
{fertilizer.name}{fertilizer.weight} KGLKR {fertilizer.price}{fertilizer.type}{fertilizer.manufacturingDate}
No values to display
{fertilizer.name}{fertilizer.weight} KGLKR {fertilizer.price}{fertilizer.type}{fertilizer.manufacturingDate} + + +
diff --git a/src/components/FertilizerList.js b/src/components/fertilizers/FertilizerList.jsx similarity index 97% rename from src/components/FertilizerList.js rename to src/components/fertilizers/FertilizerList.jsx index 4d622e9..0344421 100644 --- a/src/components/FertilizerList.js +++ b/src/components/fertilizers/FertilizerList.jsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import axios from 'axios'; -import "./FertilizerList.css"; +import "../../styles/fertilizer/FertilizerList.css"; + import { Link } from 'react-router-dom'; function Fertilizers() { diff --git a/src/components/FertilizerView.js b/src/components/fertilizers/FertilizerView.jsx similarity index 96% rename from src/components/FertilizerView.js rename to src/components/fertilizers/FertilizerView.jsx index ba251df..9759965 100644 --- a/src/components/FertilizerView.js +++ b/src/components/fertilizers/FertilizerView.jsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import axios from 'axios'; -import './FertilizerList.css'; +import "../../styles/fertilizer/FertilizerList.css"; + import { Link } from 'react-router-dom'; function FertilizerList() { diff --git a/src/routers/.gitkeep b/src/routers/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/.gitkeep b/src/routes/.gitkeep similarity index 100% rename from src/components/.gitkeep rename to src/routes/.gitkeep diff --git a/src/routers/App.js b/src/routes/FertilizerAppRoutes.jsx similarity index 71% rename from src/routers/App.js rename to src/routes/FertilizerAppRoutes.jsx index 9f847c4..7c10ab8 100644 --- a/src/routers/App.js +++ b/src/routes/FertilizerAppRoutes.jsx @@ -1,15 +1,15 @@ import React, { useState } from "react"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; -import FertilizerForm from "./components/FertilizerForm"; -import ViewFertilizers from "./components/FertilizerList"; -import FertilizerGenerator from "./components/FertilizerGenerator"; -import CustomerRegistrationForm from "./components/CustomerRegistrationForm"; -import Navbar from "./components/Navbar"; -import CustomerLoginForm from './components/CustomerLoginForm'; -import CustomerList from "./components/CustomerList"; -import CustomerEditForm from "./components/CustomerEdit"; -import FertilizerEditForm from "./components/FertilizerEdit"; -import FertilizerView from './components/FertilizerView'; +import FertilizerForm from "../components/fertilizers/FertilizerForm"; +import ViewFertilizers from "../components/fertilizers/FertilizerList"; +import FertilizerGenerator from "../components/fertilizers/FertilizerGenerator"; +import FertilizerEditForm from "../components/fertilizers/FertilizerEdit"; +import CustomerRegistrationForm from "../components/customer/CustomerRegistrationForm"; +import Navbar from "../components/Navbar"; +import CustomerLoginForm from '../components/customer/CustomerLoginForm'; +import CustomerList from "../components/customer/CustomerList"; +import CustomerEditForm from "../components/customer/CustomerEdit"; + function App() { diff --git a/src/components/CustomerLogin.css b/src/styles/customer/CustomerLogin.css similarity index 100% rename from src/components/CustomerLogin.css rename to src/styles/customer/CustomerLogin.css diff --git a/src/components/CustomerRegistrationForm.css b/src/styles/customer/CustomerRegistrationForm.css similarity index 100% rename from src/components/CustomerRegistrationForm.css rename to src/styles/customer/CustomerRegistrationForm.css diff --git a/src/components/FertilizerForm.css b/src/styles/fertilizer/FertilizerForm.css similarity index 100% rename from src/components/FertilizerForm.css rename to src/styles/fertilizer/FertilizerForm.css diff --git a/src/components/FertilizerGen.css b/src/styles/fertilizer/FertilizerGen.css similarity index 71% rename from src/components/FertilizerGen.css rename to src/styles/fertilizer/FertilizerGen.css index 52afcd5..ef54121 100644 --- a/src/components/FertilizerGen.css +++ b/src/styles/fertilizer/FertilizerGen.css @@ -42,4 +42,26 @@ form { button:hover { background-color: #006400; /* Change button hover color */ } + + + .buy-button { + background-color: #4caf50; + color: white; + border: none; + padding: 10px 20px; + font-size: 16px; + border-radius: 4px; + cursor: pointer; + } + + .add-to-cart-button { + background-color: #008cba; + color: white; + border: none; + padding: 10px 20px; + font-size: 16px; + border-radius: 4px; + cursor: pointer; + margin-top: 10px; + } \ No newline at end of file diff --git a/src/components/FertilizerList.css b/src/styles/fertilizer/FertilizerList.css similarity index 100% rename from src/components/FertilizerList.css rename to src/styles/fertilizer/FertilizerList.css From 47d6704796c371418aa0cf14b20ac59542eb1892 Mon Sep 17 00:00:00 2001 From: Shihan Date: Tue, 23 May 2023 19:54:32 +0530 Subject: [PATCH 6/9] review changes --- src/App.jsx | 4 ++-- src/routes/{FertilizerAppRoutes.jsx => AppRoutes.jsx} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename src/routes/{FertilizerAppRoutes.jsx => AppRoutes.jsx} (100%) diff --git a/src/App.jsx b/src/App.jsx index 9e6bfb8..8625b79 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,11 +1,11 @@ -import FertilizerAppRoutes from "./routes/FertilizerAppRoutes"; +import AppRoutes from "./routes/AppRoutes"; import './App.css'; function App() { return (
- +
); } diff --git a/src/routes/FertilizerAppRoutes.jsx b/src/routes/AppRoutes.jsx similarity index 100% rename from src/routes/FertilizerAppRoutes.jsx rename to src/routes/AppRoutes.jsx From 34afd6dd95de52745f3f06726c9bab402e84229d Mon Sep 17 00:00:00 2001 From: Shihan Date: Tue, 23 May 2023 20:06:40 +0530 Subject: [PATCH 7/9] remove bootstrap --- src/components/Navbar.jsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 3e75e34..6f76ec2 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -1,8 +1,6 @@ import React from 'react'; import { Link } from 'react-router-dom'; import "./Navbar.css"; -import 'bootstrap/dist/css/bootstrap.min.css'; -import 'bootstrap/dist/js/bootstrap.min.js'; function Navbar() { From 423afe39ba7c5891fd0f72fd30bde057a3e3e1c3 Mon Sep 17 00:00:00 2001 From: Shihan Date: Wed, 24 May 2023 09:53:39 +0530 Subject: [PATCH 8/9] resolve conflict --- src/App.jsx | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 src/App.jsx diff --git a/src/App.jsx b/src/App.jsx deleted file mode 100644 index 8625b79..0000000 --- a/src/App.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import AppRoutes from "./routes/AppRoutes"; -import './App.css'; - -function App() { - - return ( -
- -
- ); -} - -export default App; From 5eee5b186553d37b4c2edff56bb93b91647e62d8 Mon Sep 17 00:00:00 2001 From: Shihan Date: Fri, 26 May 2023 21:40:17 +0530 Subject: [PATCH 9/9] add cart frontend --- src/components/Navbar.css | 160 +++++-------- src/components/Navbar.jsx | 137 +++++++---- src/components/cart/CartPage.jsx | 175 ++++++++++++++ src/components/customer/CustomerEdit.jsx | 1 + src/components/customer/CustomerList.jsx | 1 + src/components/customer/CustomerLoginForm.jsx | 98 +++++--- .../fertilizers/FertilizerGenerator.jsx | 215 ++++++++++-------- src/routes/AppRoutes.jsx | 15 +- src/styles/cart/Cart.css | 75 ++++++ 9 files changed, 598 insertions(+), 279 deletions(-) create mode 100644 src/components/cart/CartPage.jsx create mode 100644 src/styles/cart/Cart.css diff --git a/src/components/Navbar.css b/src/components/Navbar.css index 857562e..961dd3c 100644 --- a/src/components/Navbar.css +++ b/src/components/Navbar.css @@ -1,104 +1,66 @@ .navbar { - display: flex; - justify-content: space-between; - align-items: center; - background-color: #008CBA; - height: 60px; - padding: 0 20px; - box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); - font-family: 'Montserrat', sans-serif; - } - - .navbar__left { - display: flex; - align-items: center; - } - - .navbar__logo { - font-size: 24px; - font-weight: bold; - color: #fff; - text-decoration: none; - } - - .navbar__right { - display: flex; - align-items: center; - } - - .navbar__item { - margin-left: 20px; - } - - .navbar__link { - font-size: 16px; - color: #fff; - text-decoration: none; - transition: all 0.3s ease-in-out; - padding: 10px; - border-radius: 5px; - } - - .navbar__link:hover { - background-color: #fff; - color: #008CBA; - } - + background-color: #f0f0f0; + padding: 10px; +} +.navbar__left { + display: flex; + align-items: center; +} +.navbar__logo { + font-size: 1.5rem; + color: #333; + text-decoration: none; +} +.navbar__right { + list-style: none; + display: flex; + align-items: center; + margin-left: auto; +} - .navbar__item:hover .dropdown-menu { - display: block; - } - - .dropdown-menu { - display: none; - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - text-align: left; - list-style: none; - background-color: #fff; - border: 1px solid #ccc; - border-radius: 4px; - box-shadow: 0 6px 12px rgba(0,0,0,.175); - } - - .dropdown-menu li:hover { - background-color: #f5f5f5; - } - - .dropdown-menu li a:hover { - color: #333; - text-decoration: none; - } - - .dropdown-menu { - background-color: #fff; - border: 1px solid #ddd; - box-shadow: 0 2px 3px rgba(0, 0, 0, 0.15); - padding: 10px; - min-width: 150px; - } - - .dropdown-menu li { - margin-bottom: 10px; - text-align: center; - } - - .dropdown-menu li a { - color: #333; - text-decoration: none; - } - - .dropdown-menu li a:hover { - color: #007bff; - } - \ No newline at end of file +.navbar__item { + position: relative; + margin-right: 10px; +} + +.navbar__link { + color: #333; + text-decoration: none; + padding: 10px; +} + +.dropdown-toggle { + cursor: pointer; +} + +.dropdown-menu { + display: none; + position: absolute; + top: 100%; + left: 0; + background-color: #fff; + padding: 10px; + list-style: none; + z-index: 1; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-menu li { + margin-bottom: 5px; +} + +.dropdown-menu li a { + color: #333; + text-decoration: none; + padding: 5px; +} + +.dropdown-menu li a:hover { + background-color: #f0f0f0; +} diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 6f76ec2..bb99f79 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -1,50 +1,103 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; -import "./Navbar.css"; - +import React, { useState } from 'react'; +import { Link, useNavigate } from 'react-router-dom'; +import { FaShoppingCart } from 'react-icons/fa'; +import './Navbar.css'; function Navbar() { + const [isDropdownOpen, setDropdownOpen] = useState(false); + const navigate = useNavigate(); + + const toggleDropdown = () => { + setDropdownOpen(!isDropdownOpen); + }; + + const closeDropdown = () => { + setDropdownOpen(false); + }; + + const handleCartClick = () => { + navigate('/cart'); + }; + + const handleLogout = () => { + // Perform logout logic here + // Example: Clear authentication token, reset user state, etc. + localStorage.removeItem('token'); // Remove authentication token from localStorage + // Reset any user-related state or perform additional logout actions + + navigate('/'); // Navigate to the homepage or any desired route after logout + }; + return ( - + ); } diff --git a/src/components/cart/CartPage.jsx b/src/components/cart/CartPage.jsx new file mode 100644 index 0000000..38f52ae --- /dev/null +++ b/src/components/cart/CartPage.jsx @@ -0,0 +1,175 @@ +import { useEffect, useState } from 'react'; +import axios from 'axios'; +import jwtDecode from 'jwt-decode'; +import { useNavigate } from 'react-router'; +import '../../styles/cart/Cart.css'; + + + +const Cart = () => { + const [cart, setCart] = useState(null); + const [token, setToken] = useState(''); + const [id, setId] = useState(''); + + const navigate = useNavigate(); + + useEffect(() => { + const loginWithToken = async () => { + try { + const storedToken = localStorage.getItem('token'); + if (storedToken) { + setToken(storedToken); + } + } catch (error) { + console.error(error); + } + }; + + loginWithToken(); + }, []); + + useEffect(() => { + const getCartFromToken = async () => { + try { + if (token) { + const decodedToken = jwtDecode(token); + const customerId = decodedToken.customer._id; + + setId(customerId); + // Make the API request to fetch the cart data + const response = await axios.get(`http://localhost:8070/cart/${customerId}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + + setCart(response.data); + } + } catch (error) { + console.error(error); + } + }; + + getCartFromToken(); + }, [token]); + + const updateCartItemQuantity = async (itemId, newQuantity) => { + try { + // Make the API request to update the quantity of an item in the cart + const response = await axios.patch( + `http://localhost:8070/cart/${cart._id}/items/${itemId}`, + { quantity: newQuantity }, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + + // Update the cart object with the updated item + const updatedCart = { ...cart }; + const updatedItemIndex = updatedCart.items.findIndex((item) => item._id === itemId); + if (updatedItemIndex !== -1) { + updatedCart.items[updatedItemIndex].quantity = newQuantity; + setCart(updatedCart); + } + } catch (error) { + console.error(error); + } + }; + + const handleInputChange = (itemId, e) => { + const newQuantity = e.target.value; + updateCartItemQuantity(itemId, newQuantity); + }; + + const removeCartItem = async (itemId) => { + try { + // Make the API request to remove an item from the cart + await axios.delete(`http://localhost:8070/cart/${id}/items/${itemId}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + + // Fetch the updated cart data after removing the item + const response = await axios.get(`http://localhost:8070/cart/${id}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + + setCart(response.data); + } catch (error) { + console.error(error); + } + }; + + const calculateTotalPrice = () => { + if (cart && cart.items) { + return cart.items.reduce((total, item) => total + item.product.price * item.quantity, 0).toFixed(2); + } + return '0.00'; + }; + + const handleBackClick = () => { + // Perform any necessary actions when the back button is clicked + console.log('Back button clicked'); + navigate('/report'); + }; + + const handleProceedPayment = () => { + // Perform any necessary actions when the proceed to payment button is clicked + console.log('Proceed to payment button clicked'); + }; + + if (cart === null) { + return
Loading...
; + } + + return ( +
+ +

Cart

+ {cart.items && cart.items.length === 0 ? ( +

Your cart is empty.

+ ) : ( +
+ + + + + + + + + + + {cart.items.map((item) => ( + + + + + + + ))} + +
ProductQuantityPriceAction
{item.product.name} + handleInputChange(item._id, e)} + /> + ${(item.product.price * item.quantity).toFixed(2)} + +
+

Total Price: ${calculateTotalPrice()}

+ + +
+ )} +
+ ); +}; + +export default Cart; diff --git a/src/components/customer/CustomerEdit.jsx b/src/components/customer/CustomerEdit.jsx index eab3d59..ad01589 100644 --- a/src/components/customer/CustomerEdit.jsx +++ b/src/components/customer/CustomerEdit.jsx @@ -24,6 +24,7 @@ export default function CustomerEditForm() { setCity(userData.city); setState(userData.state); setZipCode(userData.zipCode); + console.log(userData); } catch (error) { console.log(error); } diff --git a/src/components/customer/CustomerList.jsx b/src/components/customer/CustomerList.jsx index 13bba76..4914914 100644 --- a/src/components/customer/CustomerList.jsx +++ b/src/components/customer/CustomerList.jsx @@ -9,6 +9,7 @@ function CustomerList() { axios.get('http://localhost:8070/customers/') .then(response => { setCustomers(response.data); + console.log(customers); }) .catch(error => { console.log(error); diff --git a/src/components/customer/CustomerLoginForm.jsx b/src/components/customer/CustomerLoginForm.jsx index db89cb0..cf43fdf 100644 --- a/src/components/customer/CustomerLoginForm.jsx +++ b/src/components/customer/CustomerLoginForm.jsx @@ -1,46 +1,76 @@ -import React, { useState } from 'react'; -import "../../styles/customer/CustomerLogin.css"; +import { useState } from 'react'; +import axios from 'axios'; +import { useNavigate } from 'react-router-dom'; -function LoginForm() { - const [username, setUsername] = useState(''); +export default function CustomerLoginForm() { + const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); + const [userType, setUserType] = useState('Customer'); + const [error, setError] = useState(''); + const navigate = useNavigate(); const handleSubmit = (event) => { event.preventDefault(); - console.log(`Submitted login form with username "${username}" and password "${password}"`); - // TODO: Send login request to server + + // Perform client-side validation + if (!email || !password) { + setError('Please enter your email and password.'); + return; + } + + // Send login request to the server + axios + .post('http://localhost:8070/login/', { email, password, userType }) + .then((response) => { + console.log(response.data); // Handle the successful login here + if (response.data.message === 'Login successful') { + setError(''); + + localStorage.setItem('token', response.data.token); // Set the token in localStorage + navigate('/report'); + } else { + setError('Invalid email or password. Please try again.'); + } + }) + .catch((error) => { + setError('Invalid email or password. Please try again.'); // Handle the login error here + }); }; return ( -
-

Customer Login

- -
- - setUsername(event.target.value)} - required - /> - - - setPassword(event.target.value)} - required - /> - - -
+

Customer Login

+
+ +
+ + +
+ +
+ + setEmail(event.target.value)} + /> +
+
+ + setPassword(event.target.value)} + /> +
+
+ +
+ {error &&
{error}
} +
); } - -export default LoginForm; diff --git a/src/components/fertilizers/FertilizerGenerator.jsx b/src/components/fertilizers/FertilizerGenerator.jsx index 1d7f340..2396939 100644 --- a/src/components/fertilizers/FertilizerGenerator.jsx +++ b/src/components/fertilizers/FertilizerGenerator.jsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react"; import axios from "axios"; import fertilizers from "./FertilizerGenTable"; import "../../styles/fertilizer/FertilizerGen.css"; +import jwt_decode from "jwt-decode"; const FertilizerGeneratorForm = () => { const [plantName, setPlantName] = useState(""); @@ -12,7 +13,7 @@ const FertilizerGeneratorForm = () => { const [fertilizerFrequency, setFertilizerFrequency] = useState(""); const [filteredFertilizers, setFilteredFertilizers] = useState([]); - + const fetchFertilizers = async (type) => { try { const response = await axios.get(`http://localhost:8070/fertilizers`); @@ -24,8 +25,31 @@ const FertilizerGeneratorForm = () => { console.error(error); } }; - - + + const addToCart = async (fertilizerId) => { + try { + const token = localStorage.getItem("token"); + + if (token) { + const decodedToken = jwt_decode(token); + const customerId = decodedToken.customer._id; + + console.log(customerId); + + const response = await axios.post( + `http://localhost:8070/cart/${customerId}/add`, + { + customerId, + fertilizerId, + quantity: 1, + } + ); + console.log("Item added to cart:", response.data); + } + } catch (error) { + console.error(error); + } + }; const handleSubmit = (event) => { event.preventDefault(); @@ -34,10 +58,8 @@ const FertilizerGeneratorForm = () => { let { type, amount, frequency } = fertilizers[plantName][growthStage]; if (time === "Morning") { - // Increase nitrogen in the morning because of the wet soil is good for absorption amount *= 1.25; } else if (time === "Afternoon") { - // Decrease nitrogen amount *= 0.75; } @@ -45,9 +67,7 @@ const FertilizerGeneratorForm = () => { setFertilizerAmount(amount); setFertilizerFrequency(frequency); - fetchFertilizers(type); - } else { setFertilizerType(""); setFertilizerAmount(""); @@ -55,104 +75,111 @@ const FertilizerGeneratorForm = () => { } }; - return ( -
-
-

Generate Fertilizer

- - - - - - - + +

Generate Fertilizer

+ + + + + + + + + + + + + + + + + + + + + +
TypeAmountFrequency
{fertilizerType}{fertilizerAmount} pounds{fertilizerFrequency}
+
+

+ Find the most suitable fertilizer from the below +

+ + + - - + + - - - - - + {filteredFertilizers.length === 0 ? ( + + + + ) : ( + filteredFertilizers.map((fertilizer) => ( + + + + + + + + + )) + )} -
NameWeightPrice TypeAmountFrequencyManufacturing Date
{fertilizerType}{fertilizerAmount} pounds{fertilizerFrequency}
+ No values to display +
{fertilizer.name}{fertilizer.weight} KGLKR {fertilizer.price}{fertilizer.type}{fertilizer.manufacturingDate} + + +
- -

Find the most suitable fertilizer from the below

- - - - - - - - - - - - - {filteredFertilizers.length === 0 ? ( - - - - ) : ( - filteredFertilizers.map((fertilizer) => ( - - - - - - - - - - )) - )} - -
NameWeightPriceTypeManufacturing Date
No values to display
{fertilizer.name}{fertilizer.weight} KGLKR {fertilizer.price}{fertilizer.type}{fertilizer.manufacturingDate} - - -
- +
- - - ); }; diff --git a/src/routes/AppRoutes.jsx b/src/routes/AppRoutes.jsx index 7c10ab8..d3e42c1 100644 --- a/src/routes/AppRoutes.jsx +++ b/src/routes/AppRoutes.jsx @@ -9,6 +9,7 @@ import Navbar from "../components/Navbar"; import CustomerLoginForm from '../components/customer/CustomerLoginForm'; import CustomerList from "../components/customer/CustomerList"; import CustomerEditForm from "../components/customer/CustomerEdit"; +import CartPage from "../components/cart/CartPage"; function App() { @@ -16,9 +17,6 @@ function App() { return (
- - } /> - } /> @@ -28,12 +26,6 @@ function App() { } /> - - } /> - - - } /> - } /> @@ -41,7 +33,7 @@ function App() { } /> - } /> + } /> } /> @@ -64,6 +56,9 @@ function App() { } /> + + } /> +
diff --git a/src/styles/cart/Cart.css b/src/styles/cart/Cart.css new file mode 100644 index 0000000..187216f --- /dev/null +++ b/src/styles/cart/Cart.css @@ -0,0 +1,75 @@ +.cart-container { + width: 400px; + margin: 0 auto; + padding: 20px; + background-color: #f5f5f5; + border: 1px solid #ddd; + border-radius: 4px; + } + + .cart-header { + font-size: 24px; + font-weight: bold; + margin-bottom: 20px; + } + + .cart-table { + width: 100%; + border-collapse: collapse; + } + + .cart-table th, + .cart-table td { + padding: 10px; + border-bottom: 1px solid #ddd; + text-align: left; + } + + .cart-table th { + background-color: #f9f9f9; + } + + .cart-table td input[type="number"] { + width: 50px; + padding: 5px; + } + + .cart-total { + margin-top: 20px; + text-align: right; + } + + .cart-buttons { + margin-top: 20px; + text-align: right; + } + + .cart-buttons button { + padding: 10px 20px; + background-color: #007bff; + color: #fff; + border: none; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.3s; + } + + .cart-buttons button:hover { + background-color: #0056b3; + } + + .cart-empty-message { + font-style: italic; + margin-top: 20px; + } + + .cart-loading { + text-align: center; + margin-top: 50px; + } + + .cart-error { + color: red; + margin-top: 20px; + } + \ No newline at end of file