Merged all the changes from bhakti's branch for Frontend/ and Backend/ directory up to commit 3d79d69640

This commit is contained in:
K
2025-06-21 00:12:28 +05:30
111 changed files with 143053 additions and 738 deletions
+60
View File
@@ -1,6 +1,7 @@
const Crop = require("../Models/crop.model.js"); const Crop = require("../Models/crop.model.js");
const Farm = require("../Models/farm.model.js"); const Farm = require("../Models/farm.model.js");
const { uploadOnCloudinary } = require("../Utils/cloudinary.js"); const { uploadOnCloudinary } = require("../Utils/cloudinary.js");
const { run } = require("../Utils/model.js");
// Create a new crop // Create a new crop
const createCrop = async (req, res) => { const createCrop = async (req, res) => {
@@ -145,6 +146,61 @@ const updateHealthStatus = async (req, res) => {
} }
}; };
const cropHarvest = async (req, res) => {
try {
const crop = await Crop.findById(req.params.cropId).populate("farm");
console.log(crop);
const message = `My crop is ${crop.name}, given that I have planted it on ${crop.plantedDate}, suggest me a date as to when it will be harvested. Give output in the form: ${crop.name} will take .. months to harvest around (give month name and year).`; // for harvest expectation
const result = await run(message);
res.status(200).json({ message: result });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const suggestNextCrop = async (req, res) => {
try {
const crop = await Crop.findById(req.params.cropId).populate("farm");
console.log(crop);
const message = `Currently I have ${crop.name} in my field. Considering the best optimal time for its harvestation give my location, ${crop.farm.location} and water content of my field is ${crop.farm.waterContent}. Suggest next crop I should grow and give more suggestions around it. Don't tell me when to harvest ${crop.name}, only tell me next best crop to plant in my field and give suggestions around it.`; // for next sowing suggestion
const result = await run(message);
res.status(200).json({ message: result });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const suggestPesticides = async (req, res) => {
try {
const crop = await Crop.findById(req.params.cropId).populate("farm");
console.log(crop);
const message = `Considering I have grown ${crop.name} in my field located in ${crop.farm.location} and has water content of ${crop.farm.waterContent}. Suggest pesticides I should use on the crop and when to use it considering my sow date is ${crop.sowDate}. Give precautionary measures and suggestions around it.`; // for pesticides
const result = await run(message);
res.status(200).json({ message: result });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const suggestFertilizers = async (req, res) => {
try {
const crop = await Crop.findById(req.params.cropId).populate("farm");
console.log(crop);
const message = `Considering I have grown ${crop.name} in my field located in ${crop.farm.location} and has water content of ${crop.farm.waterContent}. Suggest fertilizers I should use on the crop and when to use it, i.e. after how many months after sowing considering sowing date is ${crop.sowDate} considering my sow date is ${crop.sowDate}. Give me precautionary measures.`; // for fertilizers
const result = await run(message);
res.status(200).json({ message: result });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
module.exports = { module.exports = {
createCrop, createCrop,
@@ -154,4 +210,8 @@ module.exports = {
deleteCrop, deleteCrop,
updateGrowthStage, updateGrowthStage,
updateHealthStatus, updateHealthStatus,
cropHarvest,
suggestNextCrop,
suggestPesticides,
suggestFertilizers,
}; };
+1
View File
@@ -39,6 +39,7 @@ const getUserFarms = async (req, res) => {
// Get a single farm by ID // Get a single farm by ID
const getFarmById = async (req, res) => { const getFarmById = async (req, res) => {
try { try {
console.log("also i am clla ing", "My farm id is : ", req.params.farmId);
const farm = await Farm.findById(req.params.farmId) const farm = await Farm.findById(req.params.farmId)
.populate("crops") .populate("crops")
.populate("finances"); .populate("finances");
+47 -1
View File
@@ -2,15 +2,55 @@ const Finance = require("../Models/finance.model.js");
const Farm = require("../Models/farm.model.js"); const Farm = require("../Models/farm.model.js");
// Create finance record for a farm // Create finance record for a farm
// const createFinance = async (req, res) => {
// try {
// const { farm } = req.body;
// console.log("My farm id is which is going to be created : ", req.body);
// // Check if the farm exists
// const existingFarm = await Farm.findById(farm);
// if (!existingFarm)
// return res.status(404).json({ message: "Farm not found" });
// const finance = new Finance({
// farm,
// transactions: [],
// totalExpenses: 0,
// totalRevenue: 0,
// });
// await finance.save();
// // Link finance to farm
// existingFarm.finances = finance._id;
// await existingFarm.save();
// res.status(201).json(finance);
// } catch (error) {
// res.status(500).json({ message: error.message });
// }
// };
const createFinance = async (req, res) => { const createFinance = async (req, res) => {
try { try {
const { farm } = req.body; const { farm } = req.body;
console.log("My farm id is which is going to be created : ", farm);
// Check if the farm exists // Check if the farm exists
const existingFarm = await Farm.findById(farm); const existingFarm = await Farm.findById(farm);
if (!existingFarm) if (!existingFarm) {
return res.status(404).json({ message: "Farm not found" }); return res.status(404).json({ message: "Farm not found" });
}
// Check if finance already exists for this farm
if (existingFarm.finances) {
return res
.status(400)
.json({ message: "Finance already exists for this farm" });
}
// Create finance entry
const finance = new Finance({ const finance = new Finance({
farm, farm,
transactions: [], transactions: [],
@@ -50,6 +90,12 @@ const addTransaction = async (req, res) => {
try { try {
const { type, amount, description } = req.body; const { type, amount, description } = req.body;
console.log("My type is : ", type);
console.log("My amount is : ", amount);
console.log("My description is : ", description);
console.log("My finance id is : ", req.params.financeId);
const finance = await Finance.findById(req.params.financeId); const finance = await Finance.findById(req.params.financeId);
if (!finance) if (!finance)
return res.status(404).json({ message: "Finance record not found" }); return res.status(404).json({ message: "Finance record not found" });
+5 -7
View File
@@ -65,12 +65,12 @@ const loginUser = catchAsyncErrors(async (req, res) => {
return res return res
.status(200) .status(200)
.cookie(process.env.TOKEN_NAME, token, { .cookie("uid", token, {
httpOnly: true, // Prevent access from JavaScript (recommended for security)
secure: false, // ⚠️ Set to `false` for localhost
sameSite: "Lax", // Use "Lax" instead of "None" for better compatibility
path: "/", path: "/",
sameSite: "None", expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
secure: process.env.NODE_ENV === "production",
httpOnly: true,
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
}) })
.json({ .json({
success: true, success: true,
@@ -260,8 +260,6 @@ const resetPassword = catchAsyncErrors(async (req, res) => {
// get user personal details // get user personal details
const getUserDetails = catchAsyncErrors(async (req, res) => { const getUserDetails = catchAsyncErrors(async (req, res) => {
const user = await User.findById(req.user._id); const user = await User.findById(req.user._id);
if (!user) { if (!user) {
+9
View File
@@ -7,6 +7,10 @@ const {
deleteCrop, deleteCrop,
updateHealthStatus, updateHealthStatus,
updateGrowthStage, updateGrowthStage,
cropHarvest,
suggestNextCrop,
suggestPesticides,
suggestFertilizers,
} = require("../Controllers/crop.controller.js"); } = require("../Controllers/crop.controller.js");
const { checkAuthenticated } = require("../Middlewares/authentication.js"); const { checkAuthenticated } = require("../Middlewares/authentication.js");
const upload = require("../Middlewares/multer.js"); const upload = require("../Middlewares/multer.js");
@@ -22,4 +26,9 @@ router.delete("/:cropId", checkAuthenticated, deleteCrop); // Delete a crop
router.put("/health/:cropId", checkAuthenticated, updateHealthStatus); router.put("/health/:cropId", checkAuthenticated, updateHealthStatus);
router.put("/growth/:cropId", checkAuthenticated, updateGrowthStage); router.put("/growth/:cropId", checkAuthenticated, updateGrowthStage);
router.get("/harvest/:cropId", checkAuthenticated, cropHarvest);
router.get("/nextCrop/:cropId", checkAuthenticated, suggestNextCrop);
router.get("/pesticides/:cropId", checkAuthenticated, suggestPesticides);
router.get("/fertilizers/:cropId", checkAuthenticated, suggestFertilizers);
module.exports = router; module.exports = router;
+99
View File
@@ -272,6 +272,88 @@
// console.log(result.response.text()); // console.log(result.response.text());
// } // }
// const {
// GoogleGenerativeAI,
// HarmCategory,
// HarmBlockThreshold,
// } = require("@google/generative-ai");
// const apiKey = "AIzaSyDsXug23r4umgcJpj77KeqNyYW0hQnYDgg";
// const genAI = new GoogleGenerativeAI(apiKey);
// const model = genAI.getGenerativeModel({
// model: "gemini-2.0-flash",
// });
// const generationConfig = {
// temperature: 1,
// topP: 0.95,
// topK: 40,
// maxOutputTokens: 8192,
// responseMimeType: "text/plain",
// };
// async function run(message) {
// const chatSession = model.startChat({
// generationConfig,
// history: [
// {
// role: "user",
// parts: [
// {
// text: "AI Guidelines:\n- The AI must only provide answers related to farming, including crops, sowing, irrigation, harvesting, fertilizers, pesticides, soil health, and climate conditions. \n- The AI must not answer anything outside farming. \n- If asked an unrelated question, the AI must not respond. \n- If the query is unclear, the AI must default to farming-related guidance. \n- The AI must provide only one-line responses without extra details. \n- No harmful, hurtful, or controversial responses. \n- No advice on illegal, unsafe, or unethical farming practices.\n",
// },
// ],
// },
// {
// role: "model",
// parts: [
// {
// text: "Understood. I will only provide one-line responses directly related to farming.\n",
// },
// ],
// },
// {
// role: "user",
// parts: [
// {
// text: "you can also receive json or javascript object as an input ",
// },
// ],
// },
// {
// role: "model",
// parts: [
// {
// text: "Understood. I will process the JSON or JavaScript object only if it pertains to farming and respond with a single line.\n",
// },
// ],
// },
// {
// role: "user",
// parts: [
// {
// text: "Answer everything which falls under the farming and agriculture even if the prompt does not include any farm or agriculture word in it",
// },
// ],
// },
// {
// role: "model",
// parts: [
// {
// text: "Understood. I will assume all queries are related to farming and provide a one-line farming-related response.\n",
// },
// ],
// },
// ],
// });
// const result = await chatSession.sendMessage(message);
// console.log(result.response.text());
// return result.response.text();
// }
const { const {
GoogleGenerativeAI, GoogleGenerativeAI,
HarmCategory, HarmCategory,
@@ -345,11 +427,28 @@ async function run(message) {
}, },
], ],
}, },
{
role: "user",
parts: [
{
text: "Give me a percise answer no matter what, dont give useless or incomplete answer \n",
},
],
},
{
role: "model",
parts: [
{
text: "Understood. I will strive to provide precise and complete one-line farming-related answers.\n",
},
],
},
], ],
}); });
const result = await chatSession.sendMessage(message); const result = await chatSession.sendMessage(message);
console.log(result.response.text()); console.log(result.response.text());
return result.response.text();
} }
module.exports = { run }; module.exports = { run };
+1 -3
View File
@@ -30,7 +30,7 @@ app.use(express.static("public"));
app.use(cookieParser()); app.use(cookieParser());
app.get("/", (req, res) => { app.get("/", (req, res) => {
return res.send("Hiddskpkpk..."); return res.send("Server is running...");
}); });
app.use("/api/v1", userRoute); app.use("/api/v1", userRoute);
@@ -43,6 +43,4 @@ app.use("/api/v1/finance", financeRoute);
app.use("/api/v1/task", taskRoute); app.use("/api/v1/task", taskRoute);
module.exports = app; module.exports = app;
+1
View File
@@ -0,0 +1 @@
VITE_API_URL=http://localhost:8000
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+142
View File
@@ -0,0 +1,142 @@
{
"hash": "2bafedf9",
"configHash": "7e00041b",
"lockfileHash": "a954eb91",
"browserHash": "c3bc7b53",
"optimized": {
"react": {
"src": "../../node_modules/react/index.js",
"file": "react.js",
"fileHash": "902ee93a",
"needsInterop": true
},
"react-dom/client": {
"src": "../../node_modules/react-dom/client.js",
"file": "react-dom_client.js",
"fileHash": "cfbeda6d",
"needsInterop": true
},
"react-router-dom": {
"src": "../../node_modules/react-router-dom/dist/index.js",
"file": "react-router-dom.js",
"fileHash": "216229fd",
"needsInterop": false
},
"react-redux": {
"src": "../../node_modules/react-redux/dist/react-redux.mjs",
"file": "react-redux.js",
"fileHash": "b9f679da",
"needsInterop": false
},
"@reduxjs/toolkit": {
"src": "../../node_modules/@reduxjs/toolkit/dist/redux-toolkit.modern.mjs",
"file": "@reduxjs_toolkit.js",
"fileHash": "13da79f3",
"needsInterop": false
},
"socket.io-client": {
"src": "../../node_modules/socket.io-client/build/esm/index.js",
"file": "socket__io-client.js",
"fileHash": "ab2fcae8",
"needsInterop": false
},
"react-icons/io": {
"src": "../../node_modules/react-icons/io/index.mjs",
"file": "react-icons_io.js",
"fileHash": "fb80952c",
"needsInterop": false
},
"react-icons/fa6": {
"src": "../../node_modules/react-icons/fa6/index.mjs",
"file": "react-icons_fa6.js",
"fileHash": "da456fb8",
"needsInterop": false
},
"react-icons/ri": {
"src": "../../node_modules/react-icons/ri/index.mjs",
"file": "react-icons_ri.js",
"fileHash": "6e092d47",
"needsInterop": false
},
"react-icons/bs": {
"src": "../../node_modules/react-icons/bs/index.mjs",
"file": "react-icons_bs.js",
"fileHash": "c070a6ed",
"needsInterop": false
},
"react-icons/fa": {
"src": "../../node_modules/react-icons/fa/index.mjs",
"file": "react-icons_fa.js",
"fileHash": "aa81607f",
"needsInterop": false
},
"react-icons/md": {
"src": "../../node_modules/react-icons/md/index.mjs",
"file": "react-icons_md.js",
"fileHash": "60d442c6",
"needsInterop": false
},
"react-icons/io5": {
"src": "../../node_modules/react-icons/io5/index.mjs",
"file": "react-icons_io5.js",
"fileHash": "5d65fe60",
"needsInterop": false
},
"framer-motion": {
"src": "../../node_modules/framer-motion/dist/es/index.mjs",
"file": "framer-motion.js",
"fileHash": "05223771",
"needsInterop": false
},
"react-intersection-observer": {
"src": "../../node_modules/react-intersection-observer/dist/index.mjs",
"file": "react-intersection-observer.js",
"fileHash": "575187c6",
"needsInterop": false
},
"react-chartjs-2": {
"src": "../../node_modules/react-chartjs-2/dist/index.js",
"file": "react-chartjs-2.js",
"fileHash": "07d12b80",
"needsInterop": false
},
"chart.js": {
"src": "../../node_modules/chart.js/dist/chart.js",
"file": "chart__js.js",
"fileHash": "39dbe037",
"needsInterop": false
},
"react-apexcharts": {
"src": "../../node_modules/react-apexcharts/dist/react-apexcharts.min.js",
"file": "react-apexcharts.js",
"fileHash": "2bdb7b94",
"needsInterop": true
},
"react-typewriter-effect": {
"src": "../../node_modules/react-typewriter-effect/dist/index.js",
"file": "react-typewriter-effect.js",
"fileHash": "574603a4",
"needsInterop": true
}
},
"chunks": {
"chunk-UU7TO5PY": {
"file": "chunk-UU7TO5PY.js"
},
"chunk-2YIK36WJ": {
"file": "chunk-2YIK36WJ.js"
},
"chunk-UHINIFCJ": {
"file": "chunk-UHINIFCJ.js"
},
"chunk-SD42HLFO": {
"file": "chunk-SD42HLFO.js"
},
"chunk-W4EHDCLL": {
"file": "chunk-W4EHDCLL.js"
},
"chunk-EWTE5DHJ": {
"file": "chunk-EWTE5DHJ.js"
}
}
}
+100
View File
@@ -0,0 +1,100 @@
import {
Animation,
Animations,
ArcElement,
BarController,
BarElement,
BasePlatform,
BasicPlatform,
BubbleController,
CategoryScale,
Chart,
DatasetController,
DomPlatform,
DoughnutController,
Element,
Interaction,
LineController,
LineElement,
LinearScale,
LogarithmicScale,
PieController,
PointElement,
PolarAreaController,
RadarController,
RadialLinearScale,
Scale,
ScatterController,
Ticks,
TimeScale,
TimeSeriesScale,
_detectPlatform,
adapters,
animator,
controllers,
defaults,
elements,
index,
layouts,
plugin_colors,
plugin_decimation,
plugin_legend,
plugin_subtitle,
plugin_title,
plugin_tooltip,
plugins,
registerables,
registry,
scales
} from "./chunk-2YIK36WJ.js";
import "./chunk-EWTE5DHJ.js";
export {
Animation,
Animations,
ArcElement,
BarController,
BarElement,
BasePlatform,
BasicPlatform,
BubbleController,
CategoryScale,
Chart,
plugin_colors as Colors,
DatasetController,
plugin_decimation as Decimation,
DomPlatform,
DoughnutController,
Element,
index as Filler,
Interaction,
plugin_legend as Legend,
LineController,
LineElement,
LinearScale,
LogarithmicScale,
PieController,
PointElement,
PolarAreaController,
RadarController,
RadialLinearScale,
Scale,
ScatterController,
plugin_subtitle as SubTitle,
Ticks,
TimeScale,
TimeSeriesScale,
plugin_title as Title,
plugin_tooltip as Tooltip,
adapters as _adapters,
_detectPlatform,
animator,
controllers,
defaults,
elements,
layouts,
plugins,
registerables,
registry,
scales
};
//# sourceMappingURL=chart__js.js.map
+7
View File
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+45
View File
@@ -0,0 +1,45 @@
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __esm = (fn, res) => function __init() {
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
export {
__esm,
__commonJS,
__export,
__toESM,
__toCommonJS,
__publicField
};
//# sourceMappingURL=chunk-EWTE5DHJ.js.map
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
+149
View File
@@ -0,0 +1,149 @@
import {
require_react
} from "./chunk-W4EHDCLL.js";
import {
__toESM
} from "./chunk-EWTE5DHJ.js";
// node_modules/react-icons/lib/iconBase.mjs
var import_react2 = __toESM(require_react(), 1);
// node_modules/react-icons/lib/iconContext.mjs
var import_react = __toESM(require_react(), 1);
var DefaultContext = {
color: void 0,
size: void 0,
className: void 0,
style: void 0,
attr: void 0
};
var IconContext = import_react.default.createContext && import_react.default.createContext(DefaultContext);
// node_modules/react-icons/lib/iconBase.mjs
var _excluded = ["attr", "size", "title"];
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
}
return target;
}
function _extends() {
_extends = Object.assign ? Object.assign.bind() : function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function ownKeys(e, r) {
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r && (o = o.filter(function(r2) {
return Object.getOwnPropertyDescriptor(e, r2).enumerable;
})), t.push.apply(t, o);
}
return t;
}
function _objectSpread(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
_defineProperty(e, r2, t[r2]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
});
}
return e;
}
function _defineProperty(obj, key, value) {
key = _toPropertyKey(key);
if (key in obj) {
Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true });
} else {
obj[key] = value;
}
return obj;
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function Tree2Element(tree) {
return tree && tree.map((node, i) => import_react2.default.createElement(node.tag, _objectSpread({
key: i
}, node.attr), Tree2Element(node.child)));
}
function GenIcon(data) {
return (props) => import_react2.default.createElement(IconBase, _extends({
attr: _objectSpread({}, data.attr)
}, props), Tree2Element(data.child));
}
function IconBase(props) {
var elem = (conf) => {
var {
attr,
size,
title
} = props, svgProps = _objectWithoutProperties(props, _excluded);
var computedSize = size || conf.size || "1em";
var className;
if (conf.className) className = conf.className;
if (props.className) className = (className ? className + " " : "") + props.className;
return import_react2.default.createElement("svg", _extends({
stroke: "currentColor",
fill: "currentColor",
strokeWidth: "0"
}, conf.attr, attr, svgProps, {
className,
style: _objectSpread(_objectSpread({
color: props.color || conf.color
}, conf.style), props.style),
height: computedSize,
width: computedSize,
xmlns: "http://www.w3.org/2000/svg"
}), title && import_react2.default.createElement("title", null, title), props.children);
};
return IconContext !== void 0 ? import_react2.default.createElement(IconContext.Consumer, null, (conf) => elem(conf)) : elem(DefaultContext);
}
export {
GenIcon
};
//# sourceMappingURL=chunk-SD42HLFO.js.map
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../node_modules/react-icons/lib/iconBase.mjs", "../../node_modules/react-icons/lib/iconContext.mjs"],
"sourcesContent": ["var _excluded = [\"attr\", \"size\", \"title\"];\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } } return target; }\nfunction _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport React from \"react\";\nimport { IconContext, DefaultContext } from \"./iconContext.mjs\";\nfunction Tree2Element(tree) {\n return tree && tree.map((node, i) => /*#__PURE__*/React.createElement(node.tag, _objectSpread({\n key: i\n }, node.attr), Tree2Element(node.child)));\n}\nexport function GenIcon(data) {\n return props => /*#__PURE__*/React.createElement(IconBase, _extends({\n attr: _objectSpread({}, data.attr)\n }, props), Tree2Element(data.child));\n}\nexport function IconBase(props) {\n var elem = conf => {\n var {\n attr,\n size,\n title\n } = props,\n svgProps = _objectWithoutProperties(props, _excluded);\n var computedSize = size || conf.size || \"1em\";\n var className;\n if (conf.className) className = conf.className;\n if (props.className) className = (className ? className + \" \" : \"\") + props.className;\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n stroke: \"currentColor\",\n fill: \"currentColor\",\n strokeWidth: \"0\"\n }, conf.attr, attr, svgProps, {\n className: className,\n style: _objectSpread(_objectSpread({\n color: props.color || conf.color\n }, conf.style), props.style),\n height: computedSize,\n width: computedSize,\n xmlns: \"http://www.w3.org/2000/svg\"\n }), title && /*#__PURE__*/React.createElement(\"title\", null, title), props.children);\n };\n return IconContext !== undefined ? /*#__PURE__*/React.createElement(IconContext.Consumer, null, conf => elem(conf)) : elem(DefaultContext);\n}", "import React from \"react\";\nexport var DefaultContext = {\n color: undefined,\n size: undefined,\n className: undefined,\n style: undefined,\n attr: undefined\n};\nexport var IconContext = React.createContext && /*#__PURE__*/React.createContext(DefaultContext);"],
"mappings": ";;;;;;;;AASA,IAAAA,gBAAkB;;;ACTlB,mBAAkB;AACX,IAAI,iBAAiB;AAAA,EAC1B,OAAO;AAAA,EACP,MAAM;AAAA,EACN,WAAW;AAAA,EACX,OAAO;AAAA,EACP,MAAM;AACR;AACO,IAAI,cAAc,aAAAC,QAAM,iBAA8B,aAAAA,QAAM,cAAc,cAAc;;;ADR/F,IAAI,YAAY,CAAC,QAAQ,QAAQ,OAAO;AACxC,SAAS,yBAAyB,QAAQ,UAAU;AAAE,MAAI,UAAU,KAAM,QAAO,CAAC;AAAG,MAAI,SAAS,8BAA8B,QAAQ,QAAQ;AAAG,MAAI,KAAK;AAAG,MAAI,OAAO,uBAAuB;AAAE,QAAI,mBAAmB,OAAO,sBAAsB,MAAM;AAAG,SAAK,IAAI,GAAG,IAAI,iBAAiB,QAAQ,KAAK;AAAE,YAAM,iBAAiB,CAAC;AAAG,UAAI,SAAS,QAAQ,GAAG,KAAK,EAAG;AAAU,UAAI,CAAC,OAAO,UAAU,qBAAqB,KAAK,QAAQ,GAAG,EAAG;AAAU,aAAO,GAAG,IAAI,OAAO,GAAG;AAAA,IAAG;AAAA,EAAE;AAAE,SAAO;AAAQ;AAC3e,SAAS,8BAA8B,QAAQ,UAAU;AAAE,MAAI,UAAU,KAAM,QAAO,CAAC;AAAG,MAAI,SAAS,CAAC;AAAG,WAAS,OAAO,QAAQ;AAAE,QAAI,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,GAAG;AAAE,UAAI,SAAS,QAAQ,GAAG,KAAK,EAAG;AAAU,aAAO,GAAG,IAAI,OAAO,GAAG;AAAA,IAAG;AAAA,EAAE;AAAE,SAAO;AAAQ;AACtR,SAAS,WAAW;AAAE,aAAW,OAAO,SAAS,OAAO,OAAO,KAAK,IAAI,SAAU,QAAQ;AAAE,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AAAE,UAAI,SAAS,UAAU,CAAC;AAAG,eAAS,OAAO,QAAQ;AAAE,YAAI,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,GAAG;AAAE,iBAAO,GAAG,IAAI,OAAO,GAAG;AAAA,QAAG;AAAA,MAAE;AAAA,IAAE;AAAE,WAAO;AAAA,EAAQ;AAAG,SAAO,SAAS,MAAM,MAAM,SAAS;AAAG;AAClV,SAAS,QAAQ,GAAG,GAAG;AAAE,MAAI,IAAI,OAAO,KAAK,CAAC;AAAG,MAAI,OAAO,uBAAuB;AAAE,QAAI,IAAI,OAAO,sBAAsB,CAAC;AAAG,UAAM,IAAI,EAAE,OAAO,SAAUC,IAAG;AAAE,aAAO,OAAO,yBAAyB,GAAGA,EAAC,EAAE;AAAA,IAAY,CAAC,IAAI,EAAE,KAAK,MAAM,GAAG,CAAC;AAAA,EAAG;AAAE,SAAO;AAAG;AAC9P,SAAS,cAAc,GAAG;AAAE,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AAAE,QAAI,IAAI,QAAQ,UAAU,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC;AAAG,QAAI,IAAI,QAAQ,OAAO,CAAC,GAAG,IAAE,EAAE,QAAQ,SAAUA,IAAG;AAAE,sBAAgB,GAAGA,IAAG,EAAEA,EAAC,CAAC;AAAA,IAAG,CAAC,IAAI,OAAO,4BAA4B,OAAO,iBAAiB,GAAG,OAAO,0BAA0B,CAAC,CAAC,IAAI,QAAQ,OAAO,CAAC,CAAC,EAAE,QAAQ,SAAUA,IAAG;AAAE,aAAO,eAAe,GAAGA,IAAG,OAAO,yBAAyB,GAAGA,EAAC,CAAC;AAAA,IAAG,CAAC;AAAA,EAAG;AAAE,SAAO;AAAG;AACtb,SAAS,gBAAgB,KAAK,KAAK,OAAO;AAAE,QAAM,eAAe,GAAG;AAAG,MAAI,OAAO,KAAK;AAAE,WAAO,eAAe,KAAK,KAAK,EAAE,OAAc,YAAY,MAAM,cAAc,MAAM,UAAU,KAAK,CAAC;AAAA,EAAG,OAAO;AAAE,QAAI,GAAG,IAAI;AAAA,EAAO;AAAE,SAAO;AAAK;AAC3O,SAAS,eAAe,GAAG;AAAE,MAAI,IAAI,aAAa,GAAG,QAAQ;AAAG,SAAO,YAAY,OAAO,IAAI,IAAI,IAAI;AAAI;AAC1G,SAAS,aAAa,GAAG,GAAG;AAAE,MAAI,YAAY,OAAO,KAAK,CAAC,EAAG,QAAO;AAAG,MAAI,IAAI,EAAE,OAAO,WAAW;AAAG,MAAI,WAAW,GAAG;AAAE,QAAI,IAAI,EAAE,KAAK,GAAG,KAAK,SAAS;AAAG,QAAI,YAAY,OAAO,EAAG,QAAO;AAAG,UAAM,IAAI,UAAU,8CAA8C;AAAA,EAAG;AAAE,UAAQ,aAAa,IAAI,SAAS,QAAQ,CAAC;AAAG;AAGvT,SAAS,aAAa,MAAM;AAC1B,SAAO,QAAQ,KAAK,IAAI,CAAC,MAAM,MAAmB,cAAAC,QAAM,cAAc,KAAK,KAAK,cAAc;AAAA,IAC5F,KAAK;AAAA,EACP,GAAG,KAAK,IAAI,GAAG,aAAa,KAAK,KAAK,CAAC,CAAC;AAC1C;AACO,SAAS,QAAQ,MAAM;AAC5B,SAAO,WAAsB,cAAAA,QAAM,cAAc,UAAU,SAAS;AAAA,IAClE,MAAM,cAAc,CAAC,GAAG,KAAK,IAAI;AAAA,EACnC,GAAG,KAAK,GAAG,aAAa,KAAK,KAAK,CAAC;AACrC;AACO,SAAS,SAAS,OAAO;AAC9B,MAAI,OAAO,UAAQ;AACjB,QAAI;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,OACJ,WAAW,yBAAyB,OAAO,SAAS;AACtD,QAAI,eAAe,QAAQ,KAAK,QAAQ;AACxC,QAAI;AACJ,QAAI,KAAK,UAAW,aAAY,KAAK;AACrC,QAAI,MAAM,UAAW,cAAa,YAAY,YAAY,MAAM,MAAM,MAAM;AAC5E,WAAoB,cAAAA,QAAM,cAAc,OAAO,SAAS;AAAA,MACtD,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,aAAa;AAAA,IACf,GAAG,KAAK,MAAM,MAAM,UAAU;AAAA,MAC5B;AAAA,MACA,OAAO,cAAc,cAAc;AAAA,QACjC,OAAO,MAAM,SAAS,KAAK;AAAA,MAC7B,GAAG,KAAK,KAAK,GAAG,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,IACT,CAAC,GAAG,SAAsB,cAAAA,QAAM,cAAc,SAAS,MAAM,KAAK,GAAG,MAAM,QAAQ;AAAA,EACrF;AACA,SAAO,gBAAgB,SAAyB,cAAAA,QAAM,cAAc,YAAY,UAAU,MAAM,UAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,cAAc;AAC3I;",
"names": ["import_react", "React", "r", "React"]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+172
View File
@@ -0,0 +1,172 @@
import {
__commonJS
} from "./chunk-EWTE5DHJ.js";
// node_modules/object-assign/index.js
var require_object_assign = __commonJS({
"node_modules/object-assign/index.js"(exports, module) {
"use strict";
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
function toObject(val) {
if (val === null || val === void 0) {
throw new TypeError("Object.assign cannot be called with null or undefined");
}
return Object(val);
}
function shouldUseNative() {
try {
if (!Object.assign) {
return false;
}
var test1 = new String("abc");
test1[5] = "de";
if (Object.getOwnPropertyNames(test1)[0] === "5") {
return false;
}
var test2 = {};
for (var i = 0; i < 10; i++) {
test2["_" + String.fromCharCode(i)] = i;
}
var order2 = Object.getOwnPropertyNames(test2).map(function(n) {
return test2[n];
});
if (order2.join("") !== "0123456789") {
return false;
}
var test3 = {};
"abcdefghijklmnopqrst".split("").forEach(function(letter) {
test3[letter] = letter;
});
if (Object.keys(Object.assign({}, test3)).join("") !== "abcdefghijklmnopqrst") {
return false;
}
return true;
} catch (err) {
return false;
}
}
module.exports = shouldUseNative() ? Object.assign : function(target, source) {
var from;
var to = toObject(target);
var symbols;
for (var s = 1; s < arguments.length; s++) {
from = Object(arguments[s]);
for (var key in from) {
if (hasOwnProperty.call(from, key)) {
to[key] = from[key];
}
}
if (getOwnPropertySymbols) {
symbols = getOwnPropertySymbols(from);
for (var i = 0; i < symbols.length; i++) {
if (propIsEnumerable.call(from, symbols[i])) {
to[symbols[i]] = from[symbols[i]];
}
}
}
}
return to;
};
}
});
// node_modules/prop-types/lib/ReactPropTypesSecret.js
var require_ReactPropTypesSecret = __commonJS({
"node_modules/prop-types/lib/ReactPropTypesSecret.js"(exports, module) {
"use strict";
var ReactPropTypesSecret = "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";
module.exports = ReactPropTypesSecret;
}
});
// node_modules/prop-types/lib/has.js
var require_has = __commonJS({
"node_modules/prop-types/lib/has.js"(exports, module) {
module.exports = Function.call.bind(Object.prototype.hasOwnProperty);
}
});
// node_modules/prop-types/checkPropTypes.js
var require_checkPropTypes = __commonJS({
"node_modules/prop-types/checkPropTypes.js"(exports, module) {
"use strict";
var printWarning = function() {
};
if (true) {
ReactPropTypesSecret = require_ReactPropTypesSecret();
loggedTypeFailures = {};
has = require_has();
printWarning = function(text) {
var message = "Warning: " + text;
if (typeof console !== "undefined") {
console.error(message);
}
try {
throw new Error(message);
} catch (x) {
}
};
}
var ReactPropTypesSecret;
var loggedTypeFailures;
var has;
function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
if (true) {
for (var typeSpecName in typeSpecs) {
if (has(typeSpecs, typeSpecName)) {
var error;
try {
if (typeof typeSpecs[typeSpecName] !== "function") {
var err = Error(
(componentName || "React class") + ": " + location + " type `" + typeSpecName + "` is invalid; it must be a function, usually from the `prop-types` package, but received `" + typeof typeSpecs[typeSpecName] + "`.This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`."
);
err.name = "Invariant Violation";
throw err;
}
error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
} catch (ex) {
error = ex;
}
if (error && !(error instanceof Error)) {
printWarning(
(componentName || "React class") + ": type specification of " + location + " `" + typeSpecName + "` is invalid; the type checker function must return `null` or an `Error` but returned a " + typeof error + ". You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument)."
);
}
if (error instanceof Error && !(error.message in loggedTypeFailures)) {
loggedTypeFailures[error.message] = true;
var stack = getStack ? getStack() : "";
printWarning(
"Failed " + location + " type: " + error.message + (stack != null ? stack : "")
);
}
}
}
}
}
checkPropTypes.resetWarningCache = function() {
if (true) {
loggedTypeFailures = {};
}
};
module.exports = checkPropTypes;
}
});
export {
require_object_assign,
require_ReactPropTypesSecret,
require_has,
require_checkPropTypes
};
/*! Bundled license information:
object-assign/index.js:
(*
object-assign
(c) Sindre Sorhus
@license MIT
*)
*/
//# sourceMappingURL=chunk-UU7TO5PY.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
{
"type": "module"
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+190
View File
@@ -0,0 +1,190 @@
import {
BarController,
BubbleController,
Chart,
DoughnutController,
LineController,
PieController,
PolarAreaController,
RadarController,
ScatterController
} from "./chunk-2YIK36WJ.js";
import {
require_react
} from "./chunk-W4EHDCLL.js";
import {
__toESM
} from "./chunk-EWTE5DHJ.js";
// node_modules/react-chartjs-2/dist/index.js
var import_react = __toESM(require_react());
var defaultDatasetIdKey = "label";
function reforwardRef(ref, value) {
if (typeof ref === "function") {
ref(value);
} else if (ref) {
ref.current = value;
}
}
function setOptions(chart, nextOptions) {
const options = chart.options;
if (options && nextOptions) {
Object.assign(options, nextOptions);
}
}
function setLabels(currentData, nextLabels) {
currentData.labels = nextLabels;
}
function setDatasets(currentData, nextDatasets) {
let datasetIdKey = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : defaultDatasetIdKey;
const addedDatasets = [];
currentData.datasets = nextDatasets.map((nextDataset) => {
const currentDataset = currentData.datasets.find((dataset) => dataset[datasetIdKey] === nextDataset[datasetIdKey]);
if (!currentDataset || !nextDataset.data || addedDatasets.includes(currentDataset)) {
return {
...nextDataset
};
}
addedDatasets.push(currentDataset);
Object.assign(currentDataset, nextDataset);
return currentDataset;
});
}
function cloneData(data) {
let datasetIdKey = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : defaultDatasetIdKey;
const nextData = {
labels: [],
datasets: []
};
setLabels(nextData, data.labels);
setDatasets(nextData, data.datasets, datasetIdKey);
return nextData;
}
function getDatasetAtEvent(chart, event) {
return chart.getElementsAtEventForMode(event.nativeEvent, "dataset", {
intersect: true
}, false);
}
function getElementAtEvent(chart, event) {
return chart.getElementsAtEventForMode(event.nativeEvent, "nearest", {
intersect: true
}, false);
}
function getElementsAtEvent(chart, event) {
return chart.getElementsAtEventForMode(event.nativeEvent, "index", {
intersect: true
}, false);
}
function ChartComponent(props, ref) {
const { height = 150, width = 300, redraw = false, datasetIdKey, type, data, options, plugins = [], fallbackContent, updateMode, ...canvasProps } = props;
const canvasRef = (0, import_react.useRef)(null);
const chartRef = (0, import_react.useRef)(null);
const renderChart = () => {
if (!canvasRef.current) return;
chartRef.current = new Chart(canvasRef.current, {
type,
data: cloneData(data, datasetIdKey),
options: options && {
...options
},
plugins
});
reforwardRef(ref, chartRef.current);
};
const destroyChart = () => {
reforwardRef(ref, null);
if (chartRef.current) {
chartRef.current.destroy();
chartRef.current = null;
}
};
(0, import_react.useEffect)(() => {
if (!redraw && chartRef.current && options) {
setOptions(chartRef.current, options);
}
}, [
redraw,
options
]);
(0, import_react.useEffect)(() => {
if (!redraw && chartRef.current) {
setLabels(chartRef.current.config.data, data.labels);
}
}, [
redraw,
data.labels
]);
(0, import_react.useEffect)(() => {
if (!redraw && chartRef.current && data.datasets) {
setDatasets(chartRef.current.config.data, data.datasets, datasetIdKey);
}
}, [
redraw,
data.datasets
]);
(0, import_react.useEffect)(() => {
if (!chartRef.current) return;
if (redraw) {
destroyChart();
setTimeout(renderChart);
} else {
chartRef.current.update(updateMode);
}
}, [
redraw,
options,
data.labels,
data.datasets,
updateMode
]);
(0, import_react.useEffect)(() => {
if (!chartRef.current) return;
destroyChart();
setTimeout(renderChart);
}, [
type
]);
(0, import_react.useEffect)(() => {
renderChart();
return () => destroyChart();
}, []);
return import_react.default.createElement("canvas", {
ref: canvasRef,
role: "img",
height,
width,
...canvasProps
}, fallbackContent);
}
var Chart2 = (0, import_react.forwardRef)(ChartComponent);
function createTypedChart(type, registerables) {
Chart.register(registerables);
return (0, import_react.forwardRef)((props, ref) => import_react.default.createElement(Chart2, {
...props,
ref,
type
}));
}
var Line = createTypedChart("line", LineController);
var Bar = createTypedChart("bar", BarController);
var Radar = createTypedChart("radar", RadarController);
var Doughnut = createTypedChart("doughnut", DoughnutController);
var PolarArea = createTypedChart("polarArea", PolarAreaController);
var Bubble = createTypedChart("bubble", BubbleController);
var Pie = createTypedChart("pie", PieController);
var Scatter = createTypedChart("scatter", ScatterController);
export {
Bar,
Bubble,
Chart2 as Chart,
Doughnut,
Line,
Pie,
PolarArea,
Radar,
Scatter,
getDatasetAtEvent,
getElementAtEvent,
getElementsAtEvent
};
//# sourceMappingURL=react-chartjs-2.js.map
File diff suppressed because one or more lines are too long
+39
View File
@@ -0,0 +1,39 @@
import {
require_react_dom
} from "./chunk-UHINIFCJ.js";
import "./chunk-W4EHDCLL.js";
import {
__commonJS
} from "./chunk-EWTE5DHJ.js";
// node_modules/react-dom/client.js
var require_client = __commonJS({
"node_modules/react-dom/client.js"(exports) {
var m = require_react_dom();
if (false) {
exports.createRoot = m.createRoot;
exports.hydrateRoot = m.hydrateRoot;
} else {
i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
exports.createRoot = function(c, o) {
i.usingClientEntryPoint = true;
try {
return m.createRoot(c, o);
} finally {
i.usingClientEntryPoint = false;
}
};
exports.hydrateRoot = function(c, h, o) {
i.usingClientEntryPoint = true;
try {
return m.hydrateRoot(c, h, o);
} finally {
i.usingClientEntryPoint = false;
}
};
}
var i;
}
});
export default require_client();
//# sourceMappingURL=react-dom_client.js.map
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../node_modules/react-dom/client.js"],
"sourcesContent": ["'use strict';\n\nvar m = require('react-dom');\nif (process.env.NODE_ENV === 'production') {\n exports.createRoot = m.createRoot;\n exports.hydrateRoot = m.hydrateRoot;\n} else {\n var i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n exports.createRoot = function(c, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.createRoot(c, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n exports.hydrateRoot = function(c, h, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.hydrateRoot(c, h, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n}\n"],
"mappings": ";;;;;;;;;AAAA;AAAA;AAEA,QAAI,IAAI;AACR,QAAI,OAAuC;AACzC,cAAQ,aAAa,EAAE;AACvB,cAAQ,cAAc,EAAE;AAAA,IAC1B,OAAO;AACD,UAAI,EAAE;AACV,cAAQ,aAAa,SAAS,GAAG,GAAG;AAClC,UAAE,wBAAwB;AAC1B,YAAI;AACF,iBAAO,EAAE,WAAW,GAAG,CAAC;AAAA,QAC1B,UAAE;AACA,YAAE,wBAAwB;AAAA,QAC5B;AAAA,MACF;AACA,cAAQ,cAAc,SAAS,GAAG,GAAG,GAAG;AACtC,UAAE,wBAAwB;AAC1B,YAAI;AACF,iBAAO,EAAE,YAAY,GAAG,GAAG,CAAC;AAAA,QAC9B,UAAE;AACA,YAAE,wBAAwB;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAjBM;AAAA;AAAA;",
"names": []
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+293
View File
@@ -0,0 +1,293 @@
"use client";
import {
require_react
} from "./chunk-W4EHDCLL.js";
import {
__toESM
} from "./chunk-EWTE5DHJ.js";
// node_modules/react-intersection-observer/dist/index.mjs
var React = __toESM(require_react(), 1);
var React2 = __toESM(require_react(), 1);
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
var observerMap = /* @__PURE__ */ new Map();
var RootIds = /* @__PURE__ */ new WeakMap();
var rootId = 0;
var unsupportedValue = void 0;
function defaultFallbackInView(inView) {
unsupportedValue = inView;
}
function getRootId(root) {
if (!root) return "0";
if (RootIds.has(root)) return RootIds.get(root);
rootId += 1;
RootIds.set(root, rootId.toString());
return RootIds.get(root);
}
function optionsToId(options) {
return Object.keys(options).sort().filter(
(key) => options[key] !== void 0
).map((key) => {
return `${key}_${key === "root" ? getRootId(options.root) : options[key]}`;
}).toString();
}
function createObserver(options) {
const id = optionsToId(options);
let instance = observerMap.get(id);
if (!instance) {
const elements = /* @__PURE__ */ new Map();
let thresholds;
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
var _a;
const inView = entry.isIntersecting && thresholds.some((threshold) => entry.intersectionRatio >= threshold);
if (options.trackVisibility && typeof entry.isVisible === "undefined") {
entry.isVisible = inView;
}
(_a = elements.get(entry.target)) == null ? void 0 : _a.forEach((callback) => {
callback(inView, entry);
});
});
}, options);
thresholds = observer.thresholds || (Array.isArray(options.threshold) ? options.threshold : [options.threshold || 0]);
instance = {
id,
observer,
elements
};
observerMap.set(id, instance);
}
return instance;
}
function observe(element, callback, options = {}, fallbackInView = unsupportedValue) {
if (typeof window.IntersectionObserver === "undefined" && fallbackInView !== void 0) {
const bounds = element.getBoundingClientRect();
callback(fallbackInView, {
isIntersecting: fallbackInView,
target: element,
intersectionRatio: typeof options.threshold === "number" ? options.threshold : 0,
time: 0,
boundingClientRect: bounds,
intersectionRect: bounds,
rootBounds: bounds
});
return () => {
};
}
const { id, observer, elements } = createObserver(options);
const callbacks = elements.get(element) || [];
if (!elements.has(element)) {
elements.set(element, callbacks);
}
callbacks.push(callback);
observer.observe(element);
return function unobserve() {
callbacks.splice(callbacks.indexOf(callback), 1);
if (callbacks.length === 0) {
elements.delete(element);
observer.unobserve(element);
}
if (elements.size === 0) {
observer.disconnect();
observerMap.delete(id);
}
};
}
function isPlainChildren(props) {
return typeof props.children !== "function";
}
var InView = class extends React.Component {
constructor(props) {
super(props);
__publicField(this, "node", null);
__publicField(this, "_unobserveCb", null);
__publicField(this, "handleNode", (node) => {
if (this.node) {
this.unobserve();
if (!node && !this.props.triggerOnce && !this.props.skip) {
this.setState({ inView: !!this.props.initialInView, entry: void 0 });
}
}
this.node = node ? node : null;
this.observeNode();
});
__publicField(this, "handleChange", (inView, entry) => {
if (inView && this.props.triggerOnce) {
this.unobserve();
}
if (!isPlainChildren(this.props)) {
this.setState({ inView, entry });
}
if (this.props.onChange) {
this.props.onChange(inView, entry);
}
});
this.state = {
inView: !!props.initialInView,
entry: void 0
};
}
componentDidMount() {
this.unobserve();
this.observeNode();
}
componentDidUpdate(prevProps) {
if (prevProps.rootMargin !== this.props.rootMargin || prevProps.root !== this.props.root || prevProps.threshold !== this.props.threshold || prevProps.skip !== this.props.skip || prevProps.trackVisibility !== this.props.trackVisibility || prevProps.delay !== this.props.delay) {
this.unobserve();
this.observeNode();
}
}
componentWillUnmount() {
this.unobserve();
}
observeNode() {
if (!this.node || this.props.skip) return;
const {
threshold,
root,
rootMargin,
trackVisibility,
delay,
fallbackInView
} = this.props;
this._unobserveCb = observe(
this.node,
this.handleChange,
{
threshold,
root,
rootMargin,
// @ts-ignore
trackVisibility,
// @ts-ignore
delay
},
fallbackInView
);
}
unobserve() {
if (this._unobserveCb) {
this._unobserveCb();
this._unobserveCb = null;
}
}
render() {
const { children } = this.props;
if (typeof children === "function") {
const { inView, entry } = this.state;
return children({ inView, entry, ref: this.handleNode });
}
const {
as,
triggerOnce,
threshold,
root,
rootMargin,
onChange,
skip,
trackVisibility,
delay,
initialInView,
fallbackInView,
...props
} = this.props;
return React.createElement(
as || "div",
{ ref: this.handleNode, ...props },
children
);
}
};
function useInView({
threshold,
delay,
trackVisibility,
rootMargin,
root,
triggerOnce,
skip,
initialInView,
fallbackInView,
onChange
} = {}) {
var _a;
const [ref, setRef] = React2.useState(null);
const callback = React2.useRef(onChange);
const [state, setState] = React2.useState({
inView: !!initialInView,
entry: void 0
});
callback.current = onChange;
React2.useEffect(
() => {
if (skip || !ref) return;
let unobserve;
unobserve = observe(
ref,
(inView, entry) => {
setState({
inView,
entry
});
if (callback.current) callback.current(inView, entry);
if (entry.isIntersecting && triggerOnce && unobserve) {
unobserve();
unobserve = void 0;
}
},
{
root,
rootMargin,
threshold,
// @ts-ignore
trackVisibility,
// @ts-ignore
delay
},
fallbackInView
);
return () => {
if (unobserve) {
unobserve();
}
};
},
// We break the rule here, because we aren't including the actual `threshold` variable
// eslint-disable-next-line react-hooks/exhaustive-deps
[
// If the threshold is an array, convert it to a string, so it won't change between renders.
Array.isArray(threshold) ? threshold.toString() : threshold,
ref,
root,
rootMargin,
triggerOnce,
skip,
trackVisibility,
fallbackInView,
delay
]
);
const entryTarget = (_a = state.entry) == null ? void 0 : _a.target;
const previousEntryTarget = React2.useRef(void 0);
if (!ref && entryTarget && !triggerOnce && !skip && previousEntryTarget.current !== entryTarget) {
previousEntryTarget.current = entryTarget;
setState({
inView: !!initialInView,
entry: void 0
});
}
const result = [setRef, state.inView, state.entry];
result.ref = result[0];
result.inView = result[1];
result.entry = result[2];
return result;
}
export {
InView,
defaultFallbackInView,
observe,
useInView
};
//# sourceMappingURL=react-intersection-observer.js.map
File diff suppressed because one or more lines are too long
+1119
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
import {
require_react
} from "./chunk-W4EHDCLL.js";
import "./chunk-EWTE5DHJ.js";
export default require_react();
//# sourceMappingURL=react.js.map
+7
View File
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

+2 -2
View File
@@ -37,8 +37,8 @@ function App() {
return ( return (
<> <>
<div className="w-full h-auto flex-col relative"> <div className="w-full h-auto flex-col relative">
<Navbar2 />
<div className="pt-20"></div>
<Outlet /> <Outlet />
<div <div
className={`${ className={`${
+1 -1
View File
@@ -3,7 +3,7 @@ import React from "react";
const Container = ({ children }) => { const Container = ({ children }) => {
return ( return (
<> <>
<div className="w-full h-auto">{children}</div> <div className="w-full max-h-screen">{children}</div>
</> </>
); );
}; };
+23 -18
View File
@@ -1,25 +1,30 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import Td from "./Td"; import Td from "./Td";
import Laoder from "./Laoder"; import Loader from "./Loader";
import { useGetFarmsQuery } from "../store/api/farmApi";
const FarmList = () => { const FarmList = () => {
const [data, setData] = useState([]); // const [data, setData] = useState([]);
const [loading, setLoading] = useState(true); // const [loading, setLoading] = useState(true);
useEffect(() => {
fetch("http://localhost:8000/api/v1/farm", { const { data: farms, error, isLoading } = useGetFarmsQuery();
credentials: "include",
method: "GET", console.log(farms);
headers: { "Content-Type": "application/json" }, // useEffect(() => {
}) // fetch("http://localhost:8000/api/v1/farm", {
.then((response) => response.json()) // credentials: "include",
.then((data) => setData(data)) // method: "GET",
.then(setLoading(false)) // headers: { "Content-Type": "application/json" },
.catch((error) => console.error(error)); // })
}, []); // .then((response) => response.json())
// .then((data) => setData(data))
// .then(setLoading(false))
// .catch((error) => console.error(error));
// }, []);
return ( return (
<div className="relative overflow-x-auto shadow-md sm:rounded-lg"> <div className="relative overflow-x-auto shadow-md sm:rounded-lg">
{loading ? ( {isLoading ? (
<Laoder></Laoder> <Loader></Loader>
) : ( ) : (
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400"> <table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400"> <thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
@@ -42,8 +47,8 @@ const FarmList = () => {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{data.length > 0 ? ( {farms && farms.length > 0 ? (
data.map((item) => <Td key={item.id} children={item} />) farms.map((item) => <Td key={item.id} children={item} />)
) : ( ) : (
<tr> <tr>
<td colSpan={5} className="text-center"> <td colSpan={5} className="text-center">
+38
View File
@@ -0,0 +1,38 @@
import React from 'react'
function FileInput() {
const handleFileChange= () => {
const fileInput = document.getElementById("file_input");
const file = fileInput.files[0];
if (!file) {
alert("Please select a file!");
return;
}
const formData = new FormData();
formData.append("file", file);
// Send to backend
fetch("http://your-backend-url.com/upload", {
method: "POST",
body: formData,
})
.then((response) => response.json())
.then((data) => console.log("File uploaded successfully:", data))
.catch((error) => console.error("Upload failed:", error));
}
return (
<div className=' pt-24'>
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white" for="file_input">Upload file</label>
<input class="block w-full text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400"
id="file_input"
type="file"
onChange={handleFileChange} />
</div>
)
}
export default FileInput
@@ -1,4 +1,4 @@
const Laoder = () => { const Loader = () => {
return ( return (
<div className="w-full bg-white rounded-lg shadow p-4"> <div className="w-full bg-white rounded-lg shadow p-4">
<div class="flex items-center justify-center w-full h-56 border border-gray-200 rounded-lg bg-gray-50 dark:bg-gray-800 dark:border-gray-700"> <div class="flex items-center justify-center w-full h-56 border border-gray-200 rounded-lg bg-gray-50 dark:bg-gray-800 dark:border-gray-700">
@@ -26,4 +26,4 @@ const Laoder = () => {
); );
}; };
export default Laoder; export default Loader;
+2 -2
View File
@@ -6,7 +6,7 @@ import { BACKEND_URL } from "../constants";
const Navbar = () => { const Navbar = () => {
const user = useSelector((store) => store.user); const user = useSelector((store) => store.user);
//console.log("User is : ", user);
const navigate = useNavigate(); const navigate = useNavigate();
@@ -18,7 +18,7 @@ const Navbar = () => {
const data = await responce.json(); const data = await responce.json();
//console.log("User Logged out data is : ", data);
if (data.success == true) { if (data.success == true) {
navigate("/user/login"); navigate("/user/login");
+34 -22
View File
@@ -1,24 +1,38 @@
import { useState } from "react"; import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
const Navbar2 = () => { const Navbar2 = () => {
const user = useSelector((store) => store.user);
const [isLoggedIn, setLoggedIn] = useState(false) const [isLoggedIn, setLoggedIn] = useState(false);
return (
<div className=" flex justify-center rounded-full"> useEffect(() => {
<nav className=" h-18 mt-3 mb-3 w-[97.5%] mx-5 fixed z-20 dark:bg-gray-800/30 backdrop-blur-md rounded-full"> if (user.name !== "Unloggedin User") {
setLoggedIn(true);
}
}, [user]);
const handleUserSession = async (event) => {
event.preventDefault();
const responce = await fetch(`http://localhost:8000/api/v1/me`, {
credentials: "include",
});
const user = await responce.json();
dispatch(userSliceActions.addUser(user.data));
};
return (
<div className=" flex justify-center w-full">
<nav className=" h-18 mt-3 mb-3 w-4/12 mx-5 fixed z-20 dark:bg-gray-800/30 backdrop-blur-md rounded-full">
<div className="absolute inset-0 bg-gradient-to-r from-gray-100/10 to-gray-500/20 pointer-events-none rounded-full"></div> <div className="absolute inset-0 bg-gradient-to-r from-gray-100/10 to-gray-500/20 pointer-events-none rounded-full"></div>
<div className="relative h-full flex items-center justify-between p-4"> <div className="relative h-full flex items-center justify-between p-4">
<a <a
href="/" href="/"
className="flex items-center space-x-3 rtl:space-x-reverse" className="flex items-center space-x-3 rtl:space-x-reverse"
> >
<img <img src="/images/logo.png" className="size-10" alt="Logo" />
src="/images/logo.png"
className="size-10"
alt="Logo"
/>
<span className="self-center text-2xl text-white font-semibold whitespace-nowrap dark:text-white"> <span className="self-center text-2xl text-white font-semibold whitespace-nowrap dark:text-white">
Crop Compass Crop Compass
</span> </span>
@@ -26,18 +40,17 @@ const Navbar2 = () => {
<div className="flex md:order-2 space-x-3 md:space-x-0 rtl:space-x-reverse"> <div className="flex md:order-2 space-x-3 md:space-x-0 rtl:space-x-reverse">
<button <button
type="button" type="button"
className="text-black bg-white hover:bg-purple-200 font-medium rounded-full text-sm py-2 px-4 text-center" className="text-black bg-white hover:bg-purple-200 font-medium rounded-full text-sm py-2 px-4 text-center"
> >
{isLoggedIn? ( {isLoggedIn ? (
<Link to={"/user/dashboard/addfarm"}>Get Started</Link> <Link to={"/user/dashboard"}>Get Started</Link>
) : ( ) : (
<Link to={"/user/login"}>Log In</Link> <Link to={"/user/login"}>Log In</Link>
)} )}
</button> </button>
</div> </div>
<div {/* <div
className="items-center justify-between hidden w-full md:flex md:w-auto md:order-1" className="items-center justify-between hidden w-full md:flex md:w-auto md:order-1"
id="navbar-sticky" id="navbar-sticky"
> >
@@ -76,12 +89,11 @@ const Navbar2 = () => {
</a> </a>
</li> </li>
</ul> </ul>
</div> </div> */}
</div> </div>
</nav> </nav>
</div> </div>
); );
}; };
export default Navbar2; export default Navbar2;
+2 -2
View File
@@ -6,7 +6,7 @@ const Notification = ({ notification }) => {
// const dateStr = "2024-09-26T04:31:50.646+00:00"; // const dateStr = "2024-09-26T04:31:50.646+00:00";
const date = new Date(dateStr); const date = new Date(dateStr);
const dayName = date.toLocaleDateString("en-US", { weekday: "long" }); const dayName = date.toLocaleDateString("en-US", { weekday: "long" });
//console.log(dayName);
return dayName; return dayName;
}; };
@@ -27,7 +27,7 @@ const Notification = ({ notification }) => {
}; };
const istDate = date.toLocaleString("en-US", options); const istDate = date.toLocaleString("en-US", options);
//console.log(istDate); // Output: "September 26, 2024, 10:01:50 AM"
return istDate; return istDate;
}; };
+25 -1
View File
@@ -1,4 +1,28 @@
import { useEffect, useState } from "react";
import { useGetFarmsQuery } from "../store/api/farmApi";
const calculateSpend = (farmList) => {
let totalSpend = 0;
for (let i = 0; i < farmList.length; i++) {
if (!farmList[i]) continue;
if (!farmList[i]?.finances) continue;
if (!farmList[i]?.finances?.totalExpenses) continue;
totalSpend += farmList[i]?.finances?.totalExpenses;
}
return totalSpend;
};
const TotalSpent = () => { const TotalSpent = () => {
const [totalSpend, setTotalSpend] = useState(0);
const { data: farmList, isLoading, error } = useGetFarmsQuery();
useEffect(() => {
if (!isLoading && !error && farmList) {
setTotalSpend(calculateSpend(farmList));
}
}, [farmList]);
return ( return (
<div className="h-full"> <div className="h-full">
<a <a
@@ -6,7 +30,7 @@ const TotalSpent = () => {
className="h-full block max-w-sm p-6 bg-no-repeat bg-center bg-cover border border-gray-200 rounded-lg shadow-sm hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700" className="h-full block max-w-sm p-6 bg-no-repeat bg-center bg-cover border border-gray-200 rounded-lg shadow-sm hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700"
> >
<h5 className="mb-2 text-4xl font-bold tracking-tight text-gray-900 dark:text-white"> <h5 className="mb-2 text-4xl font-bold tracking-tight text-gray-900 dark:text-white">
100,000 {totalSpend && totalSpend}
</h5> </h5>
<p className="font-normal text-gray-700 dark:text-gray-400"> <p className="font-normal text-gray-700 dark:text-gray-400">
This is the total cost which you spent on this farm This is the total cost which you spent on this farm
@@ -1,5 +1,5 @@
// PerformanceChart.jsx // PerformanceChart.jsx
import React from "react"; import React, { useEffect, useState } from "react";
import { Line } from "react-chartjs-2"; import { Line } from "react-chartjs-2";
import { import {
Chart as ChartJS, Chart as ChartJS,
@@ -11,6 +11,7 @@ import {
Tooltip, Tooltip,
Legend, Legend,
} from "chart.js"; } from "chart.js";
import { useGetFarmsQuery } from "../../store/api/farmApi";
ChartJS.register( ChartJS.register(
CategoryScale, CategoryScale,
@@ -22,7 +23,35 @@ ChartJS.register(
Legend Legend
); );
const calculateSpend = (farmList) => {
let totalSpend = [];
for (let i = 0; i < farmList.length; i++) {
if (!farmList[i]) continue;
if (!farmList[i]?.finances) continue;
if (!farmList[i]?.finances?.transactions) continue;
for (let j = 0; j < farmList[i]?.finances?.transactions.length; j++) {
if (!farmList[i]?.finances?.transactions[j]) continue;
if (!farmList[i]?.finances?.transactions[j]?.amount) continue;
if (farmList[i]?.finances?.transactions[j]?.type == "Revenue") continue;
totalSpend.push(farmList[i]?.finances?.transactions[j]?.amount);
}
}
return totalSpend;
};
const PerformanceChart = () => { const PerformanceChart = () => {
const [totalSpend, setTotalSpend] = useState(0);
const [spentList, setSpentList] = useState([]);
const { data: farmList, isLoading, error } = useGetFarmsQuery();
useEffect(() => {
if (!isLoading && !error && farmList) {
setTotalSpend(calculateSpend(farmList));
setSpentList(calculateSpend(farmList));
}
}, [farmList]);
const data = { const data = {
labels: [ labels: [
"Jan", "Jan",
@@ -40,8 +69,8 @@ const PerformanceChart = () => {
], ],
datasets: [ datasets: [
{ {
label: "Yield", label: "Expences",
data: [75, 68, 85, 88, 60, 62, 78, 90, 95, 92, 88, 80], // slightly improved values data: spentList, // slightly improved values
fill: false, fill: false,
backgroundColor: "rgb(75, 192, 192)", backgroundColor: "rgb(75, 192, 192)",
borderColor: "rgba(75, 192, 192, 0.2)", borderColor: "rgba(75, 192, 192, 0.2)",
@@ -53,7 +82,7 @@ const PerformanceChart = () => {
responsive: true, responsive: true,
plugins: { plugins: {
legend: { position: "top" }, legend: { position: "top" },
title: { display: true, text: "Performance Trend" }, title: { display: true, text: "Expences Tracking " },
}, },
}; };
@@ -0,0 +1,96 @@
// PerformanceChart.jsx
import React, { useEffect, useState } from "react";
import { Line } from "react-chartjs-2";
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
} from "chart.js";
import { useGetFarmsQuery } from "../../store/api/farmApi";
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
);
const calculateSpend = (farmList) => {
let totalSpend = [];
for (let i = 0; i < farmList.length; i++) {
if (!farmList[i]) continue;
if (!farmList[i]?.finances) continue;
if (!farmList[i]?.finances?.transactions) continue;
for (let j = 0; j < farmList[i]?.finances?.transactions.length; j++) {
if (!farmList[i]?.finances?.transactions[j]) continue;
if (!farmList[i]?.finances?.transactions[j]?.amount) continue;
if (farmList[i]?.finances?.transactions[j]?.type == "Expense") continue;
totalSpend.push(farmList[i]?.finances?.transactions[j]?.amount);
}
}
return totalSpend;
};
const PerformanceChart2 = () => {
const [totalSpend, setTotalSpend] = useState(0);
const [spentList, setSpentList] = useState([]);
const { data: farmList, isLoading, error } = useGetFarmsQuery();
useEffect(() => {
if (!isLoading && !error && farmList) {
setTotalSpend(calculateSpend(farmList));
setSpentList(calculateSpend(farmList));
}
}, [farmList]);
const data = {
labels: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
],
datasets: [
{
label: "Expences",
data: spentList, // slightly improved values
fill: false,
backgroundColor: "rgb(75, 192, 192)",
borderColor: "rgba(75, 192, 192, 0.2)",
},
],
};
const options = {
responsive: true,
plugins: {
legend: { position: "top" },
title: { display: true, text: "Expences Tracking " },
},
};
return <Line data={data} options={options} />;
};
export default PerformanceChart2;
@@ -36,7 +36,7 @@ const Piechart = () => {
return ( return (
<div className="bg-white md:p-6 block max-w-sm p-6 bg-no-repeat bg-center bg-cover border border-gray-200 rounded-lg shadow-sm hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700"> <div className="bg-white md:p-6 block max-w-sm p-6 bg-no-repeat bg-center bg-cover border border-gray-200 rounded-lg shadow-sm hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
<h5 className="text-xl font-bold text-gray-900 dark:text-white mb-4 "> <h5 className="text-xl font-bold text-gray-900 dark:text-white mb-4 ">
Cost Analysis Farm Info
</h5> </h5>
<Chart options={chartOptions} series={series} type="donut" height={320} /> <Chart options={chartOptions} series={series} type="donut" height={320} />
</div> </div>
+4
View File
@@ -26,11 +26,14 @@ import Monitoring from "./pages/UserPanel/Monitoring.jsx";
import AddFarm from "./pages/UserPanel/Farm/AddFarm.jsx"; import AddFarm from "./pages/UserPanel/Farm/AddFarm.jsx";
import UpdateFarm from "./pages/UserPanel/Farm/UpdateForm.jsx"; import UpdateFarm from "./pages/UserPanel/Farm/UpdateForm.jsx";
import FarmPage from "./pages/UserPanel/Farm/FarmPage.jsx"; import FarmPage from "./pages/UserPanel/Farm/FarmPage.jsx";
import Ai from "./pages/UserPanel/Ai.jsx";
import CropPage from "./pages/UserPanel/Farm/CropPage.jsx";
createRoot(document.getElementById("root")).render( createRoot(document.getElementById("root")).render(
<StrictMode> <StrictMode>
<Provider store={MentifyStore}> <Provider store={MentifyStore}>
<BrowserRouter> <BrowserRouter>
<Routes> <Routes>
<Route path="/ai" element={<Ai />} />
{/* Routes for the main App */} {/* Routes for the main App */}
<Route path="/" element={<App />}> <Route path="/" element={<App />}>
<Route index element={<HomePage />} /> <Route index element={<HomePage />} />
@@ -59,6 +62,7 @@ createRoot(document.getElementById("root")).render(
<Route path="addfarm" element={<AddFarm />} /> <Route path="addfarm" element={<AddFarm />} />
<Route path="updatefarm" element={<UpdateFarm />} /> <Route path="updatefarm" element={<UpdateFarm />} />
<Route path="farmpage/:farmId" element={<FarmPage />} /> <Route path="farmpage/:farmId" element={<FarmPage />} />
<Route path="croppage/:cropId" element={<CropPage />} />
</Route> </Route>
</Route> </Route>
</Routes> </Routes>
+37 -11
View File
@@ -1,18 +1,47 @@
import React from "react"; import React, { useState } from "react";
import { useSelector } from "react-redux";
import { useEffect } from "react";
import { Link } from "react-router-dom";
export const HeroSecn = () => { export const HeroSecn = () => {
const user = useSelector((store) => store.user);
const [isLoggedIn, setLoggedIn] = useState(false);
useEffect(() => {
if (user.name !== "Unloggedin User") {
setLoggedIn(true);
}
}, [user]);
const handleUserSession = async (event) => {
event.preventDefault();
const responce = await fetch(`http://localhost:8000/api/v1/me`, {
credentials: "include",
});
const user = await responce.json();
dispatch(userSliceActions.addUser(user.data));
};
return ( return (
<section className=" py-40 w-full flex justify-center text-gray-100"> <section className=" py-40 w-full flex justify-center text-gray-100">
<div className="flex flex-col-reverse md:flex-row justify-between w-10/12 h-auto"> <div className="flex flex-col-reverse md:flex-row justify-between w-10/12 h-auto">
<div className="container mx-auto flex flex-col justify-between h-full w-full"> <div className="container mx-auto flex flex-col justify-between h-full w-full">
<div className="text-center md:text-start flex flex-col justify-around h-full"> <div className="text-center md:text-start flex flex-col justify-around h-full">
<h1 className="text-6xl md:text-6xl md:w-2/3 md:font-extrabold font-bold"> <h1 className="text-6xl md:text-6xl md:w-2/3 md:font-extrabold font-bold ">
Anything and Everything you Need to know About One stop solution for every farmer's need.
</h1> </h1>
<p className="text-2xl font-semibold mb-8 ">
Your crops and their Health!
</p>
</div> </div>
<button
type="button"
className="text-black w-auto max-w-lg bg-white hover:bg-purple-200 font-medium rounded-full text-sm py-2 px-4 text-center"
></button>
</div> </div>
<div className="w-full md:w-4/5 object-contain flex justify-center items-center"> <div className="w-full md:w-4/5 object-contain flex justify-center items-center">
<img <img
@@ -28,7 +57,7 @@ export const HeroSecn = () => {
export const CardWithImage = () => { export const CardWithImage = () => {
return ( return (
<div className="max-w-sm rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700"> <div className="max-w-sm rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700">
<a href="#"> <a href="#">
<img <img
className="rounded-t-lg" className="rounded-t-lg"
@@ -99,10 +128,7 @@ export const CardOnlyText = (props) => {
export const CardWithButton = () => { export const CardWithButton = () => {
return ( return (
<div className="max-w-sm p-6 backdrop-blur-md rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700"> <div className="max-w-sm p-6 backdrop-blur-md rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700">
<a <a target="_blank">
href="https://www.reuters.com/sustainability/land-use-biodiversity/comment-how-empowering-smallholder-farmers-with-ai-tools-can-bolster-global-food-2025-01-10/"
target="_blank"
>
<h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-50 dark:text-white"> <h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-50 dark:text-white">
Empowering smallholder farmers with AI tools can bolster global food Empowering smallholder farmers with AI tools can bolster global food
security security
+1 -156
View File
@@ -18,171 +18,16 @@ const Footer = () => {
</span> </span>
</a> </a>
</div> </div>
<div className="grid grid-cols-2 gap-8 sm:gap-6 sm:grid-cols-3">
<div>
<h2 className="mb-6 text-sm font-semibold text-gray-50 uppercase dark:text-white">
Resources
</h2>
<ul className="text-gray-50 dark:text-gray-400 font-medium">
<li className="mb-4">
<a href="https://flowbite.com/" className="hover:underline">
Flowbite
</a>
</li>
<li>
<a
href="https://tailwindcss.com/"
className="hover:underline"
>
Tailwind CSS
</a>
</li>
</ul>
</div>
<div>
<h2 className="mb-6 text-sm font-semibold text-gray-50 uppercase dark:text-white">
Follow us
</h2>
<ul className="text-gray-50 dark:text-gray-400 font-medium">
<li className="mb-4">
<a
href="https://github.com/themesberg/flowbite"
className="hover:underline"
>
Github
</a>
</li>
<li>
<a
href="https://discord.gg/4eeurUVvTy"
className="hover:underline"
>
Discord
</a>
</li>
</ul>
</div>
<div>
<h2 className="mb-6 text-sm font-semibold text-gray-50 uppercase dark:text-white">
Legal
</h2>
<ul className="text-gray-50 dark:text-gray-400 font-medium">
<li className="mb-4">
<a href="#" className="hover:underline">
Privacy Policy
</a>
</li>
<li>
<a href="#" className="hover:underline">
Terms &amp; Conditions
</a>
</li>
</ul>
</div>
</div>
</div> </div>
<hr className="my-6 border-gray-50 sm:mx-auto dark:border-gray-700 lg:my-8" /> <hr className="my-6 border-gray-50 sm:mx-auto dark:border-gray-700 lg:my-8" />
<div className="sm:flex sm:items-center sm:justify-between"> <div className="sm:flex sm:items-center sm:justify-between">
<span className="text-sm text-gray-50 sm:text-center dark:text-gray-400"> <span className="text-sm text-gray-50 sm:text-center dark:text-gray-400">
© 2024{" "} © 2025{" "}
<a href="/" className="hover:underline"> <a href="/" className="hover:underline">
Crop Compass Crop Compass
</a> </a>
. All Rights Reserved. . All Rights Reserved.
</span> </span>
<div className="flex mt-4 sm:justify-center sm:mt-0">
<a
href="#"
className="text-gray-50 hover:text-gray-900 dark:hover:text-white"
>
<svg
className="w-4 h-4"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 8 19"
>
<path
fillRule="evenodd"
d="M6.135 3H8V0H6.135a4.147 4.147 0 0 0-4.142 4.142V6H0v3h2v9.938h3V9h2.021l.592-3H5V3.591A.6.6 0 0 1 5.592 3h.543Z"
clipRule="evenodd"
/>
</svg>
<span className="sr-only">Facebook page</span>
</a>
<a
href="#"
className="text-gray-50 hover:text-gray-900 dark:hover:text-white ms-5"
>
<svg
className="w-4 h-4"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 21 16"
>
<path d="M16.942 1.556a16.3 16.3 0 0 0-4.126-1.3 12.04 12.04 0 0 0-.529 1.1 15.175 15.175 0 0 0-4.573 0 11.585 11.585 0 0 0-.535-1.1 16.274 16.274 0 0 0-4.129 1.3A17.392 17.392 0 0 0 .182 13.218a15.785 15.785 0 0 0 4.963 2.521c.41-.564.773-1.16 1.084-1.785a10.63 10.63 0 0 1-1.706-.83c.143-.106.283-.217.418-.33a11.664 11.664 0 0 0 10.118 0c.137.113.277.224.418.33-.544.328-1.116.606-1.71.832a12.52 12.52 0 0 0 1.084 1.785 16.46 16.46 0 0 0 5.064-2.595 17.286 17.286 0 0 0-2.973-11.59ZM6.678 10.813a1.941 1.941 0 0 1-1.8-2.045 1.93 1.93 0 0 1 1.8-2.047 1.919 1.919 0 0 1 1.8 2.047 1.93 1.93 0 0 1-1.8 2.045Zm6.644 0a1.94 1.94 0 0 1-1.8-2.045 1.93 1.93 0 0 1 1.8-2.047 1.918 1.918 0 0 1 1.8 2.047 1.93 1.93 0 0 1-1.8 2.045Z" />
</svg>
<span className="sr-only">Discord community</span>
</a>
<a
href="#"
className="text-gray-50 hover:text-gray-900 dark:hover:text-white ms-5"
>
<svg
className="w-4 h-4"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 20 17"
>
<path
fillRule="evenodd"
d="M20 1.892a8.178 8.178 0 0 1-2.355.635 4.074 4.074 0 0 0 1.8-2.235 8.344 8.344 0 0 1-2.605.98A4.13 4.13 0 0 0 13.85 0a4.068 4.068 0 0 0-4.1 4.038 4 4 0 0 0 .105.919A11.705 11.705 0 0 1 1.4.734a4.006 4.006 0 0 0 1.268 5.392 4.165 4.165 0 0 1-1.859-.5v.05A4.057 4.057 0 0 0 4.1 9.635a4.19 4.19 0 0 1-1.856.07 4.108 4.108 0 0 0 3.831 2.807A8.36 8.36 0 0 1 0 14.184 11.732 11.732 0 0 0 6.291 16 11.502 11.502 0 0 0 17.964 4.5c0-.177 0-.35-.012-.523A8.143 8.143 0 0 0 20 1.892Z"
clipRule="evenodd"
/>
</svg>
<span className="sr-only">Twitter page</span>
</a>
<a
href="#"
className="text-gray-50 hover:text-gray-900 dark:hover:text-white ms-5"
>
<svg
className="w-4 h-4"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M10 .333A9.911 9.911 0 0 0 6.866 19.65c.5.092.678-.215.678-.477 0-.237-.01-1.017-.014-1.845-2.757.6-3.338-1.169-3.338-1.169a2.627 2.627 0 0 0-1.1-1.451c-.9-.615.07-.6.07-.6a2.084 2.084 0 0 1 1.518 1.021 2.11 2.11 0 0 0 2.884.823c.044-.503.268-.973.63-1.325-2.2-.25-4.516-1.1-4.516-4.9A3.832 3.832 0 0 1 4.7 7.068a3.56 3.56 0 0 1 .095-2.623s.832-.266 2.726 1.016a9.409 9.409 0 0 1 4.962 0c1.89-1.282 2.717-1.016 2.717-1.016.366.83.402 1.768.1 2.623a3.827 3.827 0 0 1 1.02 2.659c0 3.807-2.319 4.644-4.525 4.889a2.366 2.366 0 0 1 .673 1.834c0 1.326-.012 2.394-.012 2.72 0 .263.18.572.681.475A9.911 9.911 0 0 0 10 .333Z"
clipRule="evenodd"
/>
</svg>
<span className="sr-only">GitHub account</span>
</a>
<a
href="#"
className="text-gray-50 hover:text-gray-900 dark:hover:text-white ms-5"
>
<svg
className="w-4 h-4"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M10 0a10 10 0 1 0 10 10A10.009 10.009 0 0 0 10 0Zm6.613 4.614a8.523 8.523 0 0 1 1.93 5.32 20.094 20.094 0 0 0-5.949-.274c-.059-.149-.122-.292-.184-.441a23.879 23.879 0 0 0-.566-1.239 11.41 11.41 0 0 0 4.769-3.366ZM8 1.707a8.821 8.821 0 0 1 2-.238 8.5 8.5 0 0 1 5.664 2.152 9.608 9.608 0 0 1-4.476 3.087A45.758 45.758 0 0 0 8 1.707ZM1.642 8.262a8.57 8.57 0 0 1 4.73-5.981A53.998 53.998 0 0 1 9.54 7.222a32.078 32.078 0 0 1-7.9 1.04h.002Zm2.01 7.46a8.51 8.51 0 0 1-2.2-5.707v-.262a31.64 31.64 0 0 0 8.777-1.219c.243.477.477.964.692 1.449-.114.032-.227.067-.336.1a13.569 13.569 0 0 0-6.942 5.636l.009.003ZM10 18.556a8.508 8.508 0 0 1-5.243-1.8 11.717 11.717 0 0 1 6.7-5.332.509.509 0 0 1 .055-.02 35.65 35.65 0 0 1 1.819 6.476 8.476 8.476 0 0 1-3.331.676Zm4.772-1.462A37.232 37.232 0 0 0 13.113 11a12.513 12.513 0 0 1 5.321.364 8.56 8.56 0 0 1-3.66 5.73h-.002Z"
clipRule="evenodd"
/>
</svg>
<span className="sr-only">Dribbble account</span>
</a>
</div>
</div> </div>
</div> </div>
</footer> </footer>
+56 -17
View File
@@ -1,7 +1,15 @@
import React from 'react' import React from "react";
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { useInView } from "react-intersection-observer"; import { useInView } from "react-intersection-observer";
import { CardOnlyText, CardWithButton, CardWithImage, CardWithOnlyImage, HeroSecn, } from "./Cards"; import {
CardOnlyText,
CardWithButton,
CardWithImage,
CardWithOnlyImage,
HeroSecn,
} from "./Cards";
import Testimonial from "./Testimonial";
import Navbar2 from "../../components/Navbar2";
const ScrollReveal = ({ children, direction = "left" }) => { const ScrollReveal = ({ children, direction = "left" }) => {
const { ref, inView } = useInView({ triggerOnce: true, threshold: 0.2 }); const { ref, inView } = useInView({ triggerOnce: true, threshold: 0.2 });
@@ -26,33 +34,64 @@ const ScrollReveal = ({ children, direction = "left" }) => {
}; };
function Hero2() { function Hero2() {
const myRef = document.querySelector('.scrollable-div') const myRef = document.querySelector(".scrollable-div");
return ( return (
<div> <div>
<ScrollReveal direction='up'> <Navbar2 />
<ScrollReveal direction="up">
<HeroSecn /> <HeroSecn />
</ScrollReveal> </ScrollReveal>
<Testimonial />
<div className=" flex justify-center"> <div className=" flex justify-center">
<div className=" flex justify-between py-8 w-5/6 "> <div className=" flex justify-between py-8 w-5/6 ">
<ScrollReveal direction="up">
<ScrollReveal direction='up'>
<CardWithImage /> <CardWithImage />
</ScrollReveal> </ScrollReveal>
<div className="flex flex-col gap-10 justify-between ">
<ScrollReveal direction='up' > <CardOnlyText headingText = {"AI for agriculture: How Indian farmers are harvesting innovation"} bodyText={"Farmers participating in the programme saw a 21% increase in chili yields per acre, a 9% reduction in pesticide use, a 5% decrease in fertilizer usage, and an 8% improvement in unit prices due to quality enhancements."} href={"https://www.weforum.org/impact/ai-for-agriculture-in-india/ "} /> </ScrollReveal>
<ScrollReveal direction='up'> <CardWithButton /> </ScrollReveal>
</div>
<div className=" flex flex-col justify-between"> <div className="flex flex-col gap-10 justify-between ">
<ScrollReveal direction='up'> <CardOnlyText headingText={"SugarChain: Blockchain technology meets Agriculture"} bodyText={"The use of blockchain technology can help farmers automate processes with high trust, addressing issues like middlemen involvement and ensuring accurate compensation for their products"} href={"https://arxiv.org/abs/2301.08405"} /> </ScrollReveal> <ScrollReveal direction="up">
<ScrollReveal direction='up'> <CardWithOnlyImage /> </ScrollReveal> {" "}
</div> <CardOnlyText
headingText={
"AI for agriculture: How Indian farmers are harvesting innovation"
}
bodyText={
"Farmers participating in the programme saw a 21% increase in chili yields per acre, a 9% reduction in pesticide use, a 5% decrease in fertilizer usage, and an 8% improvement in unit prices due to quality enhancements."
}
href={
"https://www.weforum.org/impact/ai-for-agriculture-in-india/ "
}
/>{" "}
</ScrollReveal>
<ScrollReveal direction="up">
{" "}
<CardWithButton />{" "}
</ScrollReveal>
</div>
<div className=" flex flex-col justify-between">
<ScrollReveal direction="up">
{" "}
<CardOnlyText
headingText={
"SugarChain: Blockchain technology meets Agriculture"
}
bodyText={
"The use of blockchain technology can help farmers automate processes with high trust, addressing issues like middlemen involvement and ensuring accurate compensation for their products"
}
href={"https://arxiv.org/abs/2301.08405"}
/>{" "}
</ScrollReveal>
<ScrollReveal direction="up">
{" "}
<CardWithOnlyImage />{" "}
</ScrollReveal>
</div>
</div> </div>
</div> </div>
</div> </div>
) );
} }
export default Hero2 export default Hero2;
+1 -1
View File
@@ -10,7 +10,7 @@ const HomePage = () => {
<> <>
<div className=" bg-[url(/images/bgphoto.png)] bg-no-repeat bg-cover"> <div className=" bg-[url(/images/bgphoto.png)] bg-no-repeat bg-cover">
<Hero2 /> <Hero2 />
<Testimonial />
<Footer /> <Footer />
</div> </div>
</> </>
+18 -38
View File
@@ -35,8 +35,8 @@ const Testimonial = () => {
return ( return (
<> <>
<section className=" py-12 px-2 md:px-32 text-white"> <section className=" py-12 px-2 md:px-32 text-white">
<div className="container mx-auto "> <div className="container mx-auto min-h-[20]">
<div className="text-center flex-col justify-center align-middle "> <div className="text-center flex-col justify-center align-middle min-h-full">
<ScrollReveal direction="up"> <ScrollReveal direction="up">
<h2 className="text-xl sm:text-4xl font-bold mb-4 drop-shadow-md"> <h2 className="text-xl sm:text-4xl font-bold mb-4 drop-shadow-md">
WHY CHOOSE US? WHY CHOOSE US?
@@ -50,33 +50,29 @@ const Testimonial = () => {
scrollArea={myRef} scrollArea={myRef}
startDelay={100} startDelay={100}
cursorColor="white" cursorColor="white"
text="Record breaking features like never before!" text="Unparalled management for crops & farms."
typeSpeed={100} typeSpeed={100}
/> />
</h1> </h1>
</ScrollReveal> </ScrollReveal>
</div> </div>
<div className="flex flex-col sm:flex-row justify-around mt-8 h-auto"> <div className="flex flex-col sm:flex-row justify-around mt-8 h-auto min-h-[50]">
<ScrollReveal direction="up"> <ScrollReveal direction="up">
<div className="max-w-sm p-6 backdrop-blur-md rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700"> <div className="max-w-sm p-6 backdrop-blur-md rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700">
<svg <img
className="w-7 h-7 text-gray-200 dark:text-gray-400 mb-3" src="/images/dashboard.png"
aria-hidden="true" alt="dashboard"
xmlns="http://www.w3.org/2000/svg" className="w-7 h-7"
fill="currentColor" ></img>
viewBox="0 0 20 20" <a href="/user/dashboard/">
>
<path d="M18 5h-.7c.229-.467.349-.98.351-1.5a3.5 3.5 0 0 0-3.5-3.5c-1.717 0-3.215 1.2-4.331 2.481C8.4.842 6.949 0 5.5 0A3.5 3.5 0 0 0 2 3.5c.003.52.123 1.033.351 1.5H2a2 2 0 0 0-2 2v3a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1V7a2 2 0 0 0-2-2ZM8.058 5H5.5a1.5 1.5 0 0 1 0-3c.9 0 2 .754 3.092 2.122-.219.337-.392.635-.534.878Zm6.1 0h-3.742c.933-1.368 2.371-3 3.739-3a1.5 1.5 0 0 1 0 3h.003ZM11 13H9v7h2v-7Zm-4 0H2v5a2 2 0 0 0 2 2h3v-7Zm6 0v7h3a2 2 0 0 0 2-2v-5h-5Z" />
</svg>
<a href="#">
<h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-50 dark:text-white"> <h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-50 dark:text-white">
Excellent Dashboards Excellent Dashboards
</h5> </h5>
</a> </a>
<p className="mb-3 font-normal text-gray-50 dark:text-gray-400"> <p className="mb-3 font-normal text-gray-50 dark:text-gray-400">
Our descriptive dashboards give insights into your crop's Our descriptive dashboards give insights into your crop's
health and keeps track of your burning expenses health and keeps track of your burning expenses.
</p> </p>
<a <a
href="#" href="#"
@@ -103,16 +99,8 @@ const Testimonial = () => {
</ScrollReveal> </ScrollReveal>
<ScrollReveal direction="up"> <ScrollReveal direction="up">
<div className="max-w-sm p-6 backdrop-blur-md rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700"> <div className="max-w-sm p-6 backdrop-blur-md rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700 pb-13">
<svg <img src="/images/crops.png" className="w-7 h-7" alt="" />
className="w-7 h-7 text-gray-200 dark:text-gray-400 mb-3"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 20 20"
>
<path d="M18 5h-.7c.229-.467.349-.98.351-1.5a3.5 3.5 0 0 0-3.5-3.5c-1.717 0-3.215 1.2-4.331 2.481C8.4.842 6.949 0 5.5 0A3.5 3.5 0 0 0 2 3.5c.003.52.123 1.033.351 1.5H2a2 2 0 0 0-2 2v3a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1V7a2 2 0 0 0-2-2ZM8.058 5H5.5a1.5 1.5 0 0 1 0-3c.9 0 2 .754 3.092 2.122-.219.337-.392.635-.534.878Zm6.1 0h-3.742c.933-1.368 2.371-3 3.739-3a1.5 1.5 0 0 1 0 3h.003ZM11 13H9v7h2v-7Zm-4 0H2v5a2 2 0 0 0 2 2h3v-7Zm6 0v7h3a2 2 0 0 0 2-2v-5h-5Z" />
</svg>
<a href="#"> <a href="#">
<h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-50 dark:text-white"> <h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-50 dark:text-white">
{" "} {" "}
@@ -121,10 +109,10 @@ const Testimonial = () => {
</a> </a>
<p className="mb-3 font-normal text-gray-50 dark:text-gray-400"> <p className="mb-3 font-normal text-gray-50 dark:text-gray-400">
Predict the possible crop diseases based on their shown Predict the possible crop diseases based on their shown
symptoms symptoms.
</p> </p>
<a <a
href="#" href="/ai"
className="inline-flex font-medium items-center text-blue-600 hover:underline" className="inline-flex font-medium items-center text-blue-600 hover:underline"
> >
Check Out Check Out
@@ -149,16 +137,8 @@ const Testimonial = () => {
<ScrollReveal direction="up"> <ScrollReveal direction="up">
<div className="max-w-sm p-6 backdrop-blur-md rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700"> <div className="max-w-sm p-6 backdrop-blur-md rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700">
<svg <img src="/images/planner.png" className="w-7 h-7" alt="" />
className="w-7 h-7 text-gray-200 dark:text-gray-400 mb-3" <a href="/user/dashboard/monitoring">
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 20 20"
>
<path d="M18 5h-.7c.229-.467.349-.98.351-1.5a3.5 3.5 0 0 0-3.5-3.5c-1.717 0-3.215 1.2-4.331 2.481C8.4.842 6.949 0 5.5 0A3.5 3.5 0 0 0 2 3.5c.003.52.123 1.033.351 1.5H2a2 2 0 0 0-2 2v3a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1V7a2 2 0 0 0-2-2ZM8.058 5H5.5a1.5 1.5 0 0 1 0-3c.9 0 2 .754 3.092 2.122-.219.337-.392.635-.534.878Zm6.1 0h-3.742c.933-1.368 2.371-3 3.739-3a1.5 1.5 0 0 1 0 3h.003ZM11 13H9v7h2v-7Zm-4 0H2v5a2 2 0 0 0 2 2h3v-7Zm6 0v7h3a2 2 0 0 0 2-2v-5h-5Z" />
</svg>
<a href="#">
<h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-50 dark:text-white"> <h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-50 dark:text-white">
Crop Planner Crop Planner
</h5> </h5>
@@ -166,7 +146,7 @@ const Testimonial = () => {
<p className="mb-3 font-normal text-gray-50 dark:text-gray-400"> <p className="mb-3 font-normal text-gray-50 dark:text-gray-400">
Based on previous season's crop and used pertilizers and Based on previous season's crop and used pertilizers and
pesticides, plan what crops would best suit the present state pesticides, plan what crops would best suit the present state
of your soil of your soil.
</p> </p>
<a <a
href="#" href="#"
+85 -90
View File
@@ -28,8 +28,6 @@ const LoginPage = () => {
const user = await responce.json(); const user = await responce.json();
//console.log("User Login Data is here : ", user);
dispatch(userSliceActions.addUser(user.data)); dispatch(userSliceActions.addUser(user.data));
emailElement.current.value = ""; emailElement.current.value = "";
@@ -40,97 +38,94 @@ const LoginPage = () => {
} }
}; };
return ( return (
<section className="bg-[url(/images/loginBG.png)] bg-cover font-sans flex flex-col justify-center md:p-5 "> <section className="bg-[url(/images/loginBG.png)] bg-cover font-sans flex flex-col justify-center md:p-5 w-full min-h-screen max-h-screen">
<div className="container mx-auto "> <div className="flex justify-between items-center h-full">
<div className="flex justify-between pt-24"> <div className=" rounded-lg shadow-md ">
<div className=" rounded-lg shadow-md "> <div className="flex flex-col items-center justify-center h-full ">
<div className="flex flex-col items-center justify-center h-full "> <h1 className="text-6xl font-bold text-white mb-4 md:text-6xl lg:text-9xl ml-8">
<h1 className="text-6xl font-bold text-white mb-4 md:text-6xl lg:text-9xl ml-8"> Welcome Back!
Welcome Back! </h1>
</h1> </div>
</div>
<div className=" backdrop-blur-md bg-gradient-to-tr from-slate-300/10 to-slate-200/30 rounded-lg shadow-md lg:p-36">
<h1 className="text-2xl font-bold text-gray-50 mb-4">Login</h1>
<p className="text-gray-100 mb-6">
Welcome back! Please login to your account.
</p>
<form className="space-y-6" onSubmit={handleLogin}>
<div>
<label
for="username"
className="block mb-2 text-sm font-medium text-gray-100 dark:text-white"
>
Email
</label>
<input
type="email"
id="username"
ref={emailElement}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="username@gmail.com"
required
/>
</div> </div>
</div> <div>
<div className=" backdrop-blur-md bg-gradient-to-tr from-slate-300/10 to-slate-200/30 rounded-lg shadow-md lg:p-36"> <label
<h1 className="text-2xl font-bold text-gray-50 mb-4">Login</h1> for="password"
<p className="text-gray-100 mb-6"> className="block mb-2 text-sm font-medium text-gray-100 dark:text-white"
Welcome back! Please login to your account. >
Password
</label>
<input
type="password"
id="password"
ref={passwordElement}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="********"
required
/>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center">
<input
id="remember_me"
type="checkbox"
value=""
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label
for="remember_me"
className="ml-2 text-sm font-medium text-gray-100 dark:text-gray-300"
>
Remember Me
</label>
</div>
<Link
to={"/user/forgetpassword"}
className="text-sm font-medium text-blue-600 hover:underline dark:text-blue-500"
>
Forgot Password?
</Link>
</div>
<div className=" flex justify-center">
<button
type="submit"
className="text-white w-1/2 backdrop-blur-lg bg-gradient-to-tr from-slate-100/15 to-slate-200/15 shadow-lg hover:backdrop-blur-lg focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Login
</button>
</div>
<p className="text-gray-100 text-center mt-4">
New User?{" "}
<Link
to={"/user/signup"}
className="text-blue-600 hover:underline"
>
Signup
</Link>
</p> </p>
<form className="space-y-6" onSubmit={handleLogin}> </form>
<div>
<label
for="username"
className="block mb-2 text-sm font-medium text-gray-100 dark:text-white"
>
Email
</label>
<input
type="email"
id="username"
ref={emailElement}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="username@gmail.com"
required
/>
</div>
<div>
<label
for="password"
className="block mb-2 text-sm font-medium text-gray-100 dark:text-white"
>
Password
</label>
<input
type="password"
id="password"
ref={passwordElement}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="********"
required
/>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center">
<input
id="remember_me"
type="checkbox"
value=""
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label
for="remember_me"
className="ml-2 text-sm font-medium text-gray-100 dark:text-gray-300"
>
Remember Me
</label>
</div>
<Link
to={"/user/forgetpassword"}
className="text-sm font-medium text-blue-600 hover:underline dark:text-blue-500"
>
Forgot Password?
</Link>
</div>
<div className=" flex justify-center">
<button
type="submit"
className="text-white w-1/2 backdrop-blur-lg bg-gradient-to-tr from-slate-100/15 to-slate-200/15 shadow-lg hover:backdrop-blur-lg focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Login
</button>
</div>
<p className="text-gray-100 text-center mt-4">
New User?{" "}
<Link
to={"/user/signup"}
className="text-blue-600 hover:underline"
>
Signup
</Link>
</p>
</form>
</div>
</div> </div>
</div> </div>
</section> </section>
+127 -133
View File
@@ -13,18 +13,12 @@ const SignupPage = () => {
const handleRegisteration = async (event) => { const handleRegisteration = async (event) => {
event.preventDefault(); event.preventDefault();
let userRole;
if (roleElement.current.value == "Student") {
userRole = "user";
} else {
userRole = "mentor";
}
const user = { const user = {
name: name:
firstNameElement.current.value + " " + lastNameElement.current.value, firstNameElement.current.value + " " + lastNameElement.current.value,
email: emailElement.current.value, email: emailElement.current.value,
password: passwordElement.current.value, password: passwordElement.current.value,
role: userRole,
}; };
event.preventDefault(); event.preventDefault();
@@ -39,13 +33,10 @@ const SignupPage = () => {
}); });
const data = await responce.json(); const data = await responce.json();
//console.log("Our user data is : ", data);
firstNameElement.current.value = ""; firstNameElement.current.value = "";
lastNameElement.current.value = ""; lastNameElement.current.value = "";
emailElement.current.value = ""; emailElement.current.value = "";
passwordElement.current.value = ""; passwordElement.current.value = "";
roleElement.current.value = "";
if (data.success == true) { if (data.success == true) {
navigate("/user/login"); navigate("/user/login");
@@ -53,143 +44,147 @@ const SignupPage = () => {
}; };
return ( return (
<section className="bg-[url(https://i.pinimg.com/736x/6c/d2/cc/6cd2cc05a7e464a78bdf1124b4ad30f1.jpg)] bg-cover font-sans flex flex-col justify-center md:p-5 "> <section className="bg-[url(https://i.pinimg.com/736x/6c/d2/cc/6cd2cc05a7e464a78bdf1124b4ad30f1.jpg)] bg-cover font-sans flex flex-col justify-center min-h-screen max-h-screen">
<div className="container mx-auto p-4 pt-24 sm:mt-32 md:mt-0"> <div className="flex justify-between items-center w-full h-full p-5">
<div className="grid grid-cols-1 md:grid-cols-2 gap-8"> {/* <div className="bg-gradient-to-br from-purple-300 to-pink-200 rounded-lg shadow-md min-h-40 object-center md:hidden">
<div className="bg-gradient-to-br from-purple-300 to-pink-200 rounded-lg shadow-md min-h-40 object-center md:hidden"> <div className="flex flex-col items-center justify-center h-full relative">
<div className="flex flex-col items-center justify-center h-full relative"> <img
<img src="/images/background1.jpg"
src="/images/background1.jpg" alt=""
alt="" className="absolute order-3 w-full h-full"
className="absolute order-3 w-full h-full" />
/> <h1 className="text-6xl font-bold text-white mb-4 md:text-6xl lg:text-9xl relative ml-8">
<h1 className="text-6xl font-bold text-white mb-4 md:text-6xl lg:text-9xl relative ml-8"> Welcome to Crop Compass
Welcome to Crop Compass
</h1>
</div>
</div>
<div className="backdrop-blur-md bg-gradient-to-tr from-slate-300/10 to-slate-200/30 rounded-lg shadow-md lg:p-36">
<h1 className="text-2xl font-bold text-gray-50 mb-4">
Register Your account
</h1> </h1>
<p className="text-gray-100"> </div>
Welcome to Crop Compass. </div> */}
</p> <div className="backdrop-blur-md bg-gradient-to-tr from-slate-300/10 to-slate-200/30 rounded-lg shadow-md lg:p-36 h-[95vh]">
<p className="text-gray-100 mb-6"> <h1 className="text-2xl font-bold text-gray-50 mb-4">
Please register your new account. Register Your account
</p> </h1>
<form <p className="text-gray-100">Welcome to Crop Compass.</p>
action="#" <p className="text-gray-100 mb-6">
className="space-y-6" Please register your new account.
onSubmit={handleRegisteration} </p>
> <form action="#" className="space-y-6" onSubmit={handleRegisteration}>
<div className="flex flex-col gap-5 sm:flex-row"> <div className="flex flex-col gap-5 sm:flex-row">
<div className="w-full"> <div className="w-full">
<label
htmlFor="username"
className="block mb-2 text-sm font-medium text-gray-100 dark:text-white"
>
First Name
</label>
<input
type="text"
id="firstName"
ref={firstNameElement}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="John"
required
/>
</div>
<div className="w-full">
<label
htmlFor="username"
className="block mb-2 text-sm font-medium text-gray-100 dark:text-white"
>
Last Name
</label>
<input
type="text"
id="LastName"
ref={lastNameElement}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Doe"
required
/>
</div>
</div>
<div>
<label <label
htmlFor="username" htmlFor="username"
className="block mb-2 text-sm font-medium text-gray-100 dark:text-white" className="block mb-2 text-sm font-medium text-gray-100 dark:text-white"
> >
Email First Name
</label> </label>
<input <input
type="email" type="text"
id="email" id="firstName"
ref={emailElement} ref={firstNameElement}
className="bg-gray-50 border border-gray-300 text-gray-100 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="user@mail.com"
required
/>
</div>
<div>
<label
htmlFor="password"
className="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>
Password
</label>
<input
type="password"
id="password"
ref={passwordElement}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="At least 6 unique Characters.. " placeholder="John"
required required
/> />
</div> </div>
<div className="flex items-center justify-between"> <div className="w-full">
<div className="flex items-center"> <label
<input htmlFor="username"
id="remember_me" className="block mb-2 text-sm font-medium text-gray-100 dark:text-white"
type="checkbox"
value=""
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label
htmlFor="remember_me"
className="ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"
>
Remember Me
</label>
</div>
<a
href="#"
className="text-sm font-medium text-blue-600 hover:underline dark:text-blue-500"
></a>
</div>
<div className=" flex justify-center">
<button
type="submit"
className="text-white w-1/2 backdrop-blur-lg bg-gradient-to-tr from-slate-100/15 to-slate-200/15 shadow-lg hover:backdrop-blur-lg focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
> >
Register your Account Last Name
</button> </label>
<input
type="text"
id="LastName"
ref={lastNameElement}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Doe"
required
/>
</div> </div>
<p className="text-gray-600 text-center mt-4"> </div>
Already have an Account ?{" "}
<Link <div>
to={"/user/login"} <label
className="text-blue-600 hover:underline" htmlFor="username"
className="block mb-2 text-sm font-medium text-gray-100 dark:text-white"
>
Email
</label>
<input
type="email"
id="email"
ref={emailElement}
className="bg-gray-50 border border-gray-300 text-black text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="user@mail.com"
required
/>
</div>
<div>
<label
htmlFor="password"
className="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>
Password
</label>
<input
type="password"
id="password"
ref={passwordElement}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="At least 6 unique Characters.. "
required
/>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center">
<input
id="remember_me"
type="checkbox"
value=""
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label
htmlFor="remember_me"
className="ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"
> >
Login Remember Me
</Link> </label>
</p> </div>
</form> <a
href="#"
className="text-sm font-medium text-blue-600 hover:underline dark:text-blue-500"
></a>
</div>
<div className=" flex justify-center">
<button
type="submit"
className="text-white w-1/2 backdrop-blur-lg bg-gradient-to-tr from-slate-100/15 to-slate-200/15 shadow-lg hover:backdrop-blur-lg focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Register your Account
</button>
</div>
<p className="text-gray-600 text-center mt-4">
Already have an Account ?{" "}
<Link
to={"/user/login"}
className="text-blue-600 hover:underline"
>
Login
</Link>
</p>
</form>
</div>
<div className="rounded-lg shadow-md text-center w-auto">
<div className="flex flex-col items-center justify-center h-full ">
<h1 className="text-6xl font-bold text-white mb-4 md:text-6xl lg:text-9xl ml-8">
Start your Journey
<br />
with <br />
Crop Compass
</h1>
</div> </div>
{/* <div className=" backdrop-blur-sm rounded-lg shadow-md md:block"> </div>
{/* <div className=" backdrop-blur-sm rounded-lg shadow-md md:block">
<div className="flex flex-col items-center justify-center h-full relative text-center"> <div className="flex flex-col items-center justify-center h-full relative text-center">
<img <img
src="/images/background1.jpg" src="/images/background1.jpg"
@@ -201,7 +196,6 @@ const SignupPage = () => {
</h1> </h1>
</div> </div>
</div> */} </div> */}
</div>
</div> </div>
</section> </section>
); );
@@ -14,7 +14,7 @@ const ResetPassword = () => {
const { token } = useParams(); const { token } = useParams();
// console.log("So our Token is : ", token);
const handleResetPassword = async (event) => { const handleResetPassword = async (event) => {
event.preventDefault(); event.preventDefault();
@@ -41,7 +41,7 @@ const ResetPassword = () => {
const data = await responce.json(); const data = await responce.json();
//console.log("Status of the Reset password", data);
if (data.success === true) { if (data.success === true) {
navigate("/user/login"); navigate("/user/login");
+80
View File
@@ -0,0 +1,80 @@
import React, { useState } from "react";
const Ai = () => {
const [selectedFile, setSelectedFile] = useState(null);
const [prediction, setPrediction] = useState("");
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const handleFileChange = (e) => {
if (e.target.files && e.target.files[0]) {
setSelectedFile(e.target.files[0]);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!selectedFile) return;
setLoading(true);
setPrediction("");
setError("");
try {
const formData = new FormData();
formData.append("image", selectedFile);
const response = await fetch("http://localhost:3000/predict", {
method: "POST",
body: formData,
});
if (!response.ok) {
throw new Error("Prediction request failed");
}
const result = await response.json();
// Assuming the API returns a JSON object with an "output" field.
setPrediction(result.data || "No prediction returned");
} catch (err) {
console.error("Error during prediction:", err);
setError(err.message);
} finally {
setLoading(false);
}
};
return (
<div className="min-h-screen w-full flex items-center justify-center max-h-screen">
<div className="max-w-md mx-auto p-6 bg-white shadow rounded-lg">
<h2 className="text-2xl font-bold mb-4 text-center">
Plant disease prediction
</h2>
<form onSubmit={handleSubmit} className="space-y-4">
<input
type="file"
accept="image/*"
onChange={handleFileChange}
className="block w-full text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 p-2"
/>
<button
type="submit"
disabled={loading || !selectedFile}
className="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
>
{loading ? "Predicting..." : "Predict"}
</button>
</form>
{error && <p className="mt-4 text-center text-red-600">{error}</p>}
{prediction && (
<div className="mt-4 p-4 bg-green-100 border border-green-300 rounded">
<h3 className="text-lg font-semibold">Prediction:</h3>
<p>{prediction}</p>
</div>
)}
</div>
</div>
);
};
export default Ai;
+1 -1
View File
@@ -12,7 +12,7 @@ const Dashboard = () => {
<AddFarm /> <AddFarm />
</div> </div>
<div className="mb-4 flex space-x-4"> <div className="mb-4 flex space-x-10">
<Piechart /> <Piechart />
<TotalSpent /> <TotalSpent />
</div> </div>
+15 -9
View File
@@ -1,4 +1,5 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useCreateCropMutation } from "../../../store/api/cropApi";
const AddCrop = ({ farmId }) => { const AddCrop = ({ farmId }) => {
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
@@ -12,6 +13,7 @@ const AddCrop = ({ farmId }) => {
const [uploading, setUploading] = useState(false); const [uploading, setUploading] = useState(false);
const [error, setError] = useState(""); const [error, setError] = useState("");
const [success, setSuccess] = useState(""); const [success, setSuccess] = useState("");
const [createCrop] = useCreateCropMutation();
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
e.preventDefault(); e.preventDefault();
@@ -28,16 +30,19 @@ const AddCrop = ({ farmId }) => {
if (image) { if (image) {
formData.append("image", image); formData.append("image", image);
} }
console.log(formData);
try { try {
const response = await fetch(`http://localhost:8000/api/v1/crop`, { const response = await createCrop(formData);
method: "POST", // const response = await fetch(`http://localhost:8000/api/v1/crop`, {
credentials: "include", // method: "POST",
body: formData, // credentials: "include",
}); // body: formData,
if (!response.ok) { // });
throw new Error("Failed to create crop"); // if (!response.ok) {
} // throw new Error("Failed to create crop");
// }
setSuccess("Crop created successfully!"); setSuccess("Crop created successfully!");
// Reset form fields // Reset form fields
setName(""); setName("");
@@ -46,6 +51,7 @@ const AddCrop = ({ farmId }) => {
setGrowthStage(""); setGrowthStage("");
setHealthStatus(""); setHealthStatus("");
setImage(null); setImage(null);
setIsModalOpen(false);
} catch (err) { } catch (err) {
setError(err.message); setError(err.message);
} finally { } finally {
+8 -16
View File
@@ -1,5 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useCreateFarmMutation } from "../../../store/api/farmApi";
const AddFarm = () => { const AddFarm = () => {
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
@@ -11,6 +12,8 @@ const AddFarm = () => {
const [error, setError] = useState(null); const [error, setError] = useState(null);
const [success, setSuccess] = useState(false); const [success, setSuccess] = useState(false);
const navigator = useNavigate(); const navigator = useNavigate();
const [createFarm] = useCreateFarmMutation();
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
e.preventDefault(); e.preventDefault();
const farmData = { const farmData = {
@@ -21,30 +24,19 @@ const AddFarm = () => {
size: sizeContent, size: sizeContent,
}; };
console.log(farmData);
try { try {
const response = await fetch("http://localhost:8000/api/v1/farm", { const res = await createFarm(farmData);
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(farmData),
});
const data = await response.json(); if (res.error) {
console.log(data); return null;
if (!response.ok) {
throw new Error("Failed to add farm");
} }
navigator("farmpage");
setSuccess(true); setSuccess(true);
setError(null); setError(null);
setIsModalOpen(false); setIsModalOpen(false);
window.location.reload();
} catch (err) { } catch (err) {
setError(err.message); setError(err.message);
setSuccess(false); setSuccess(false);
@@ -0,0 +1,177 @@
import React, { useState } from "react";
import Loader from "../../../components/Loader";
import { useAddTransactionMutation } from "../../../store/api/financeApi";
const AddTransaction = ({ farmId, financeId }) => {
const [modalOpen, setModalOpen] = useState(false);
const [type, setType] = useState("Expense");
const [amount, setAmount] = useState("");
const [description, setDescription] = useState("");
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState("");
const [addTransaction] = useAddTransactionMutation();
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
setMessage("");
const transactionData = {
type,
amount: parseFloat(amount),
description,
};
try {
const response = await addTransaction({ financeId, transactionData });
// const response = await fetch(
// `http://localhost:8000/api/v1/finance/${farmId}/transaction`,
// {
// method: "POST",
// credentials: "include",
// headers: {
// "Content-Type": "application/json",
// },
// body: JSON.stringify({
// type,
// amount: parseFloat(amount),
// description,
// }),
// }
// );
// if (!response.ok) {
// throw new Error("Failed to create transaction");
// }
// const data = await response.json();
setMessage("Transaction created successfully!");
// Optionally clear the form
setType("Expense");
setAmount("");
setDescription("");
} catch (error) {
console.error("Error creating transaction:", error);
setMessage("Error creating transaction.");
} finally {
setLoading(false);
}
};
return (
<>
<button
onClick={() => setModalOpen(true)}
className="block text-white bg-green-600 hover:bg-green-700 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center"
type="button"
>
Add Transaction
</button>
{modalOpen && (
<div className="fixed inset-0 z-50 flex justify-center items-center overflow-y-auto overflow-x-hidden bg-black bg-opacity-50">
<div className="relative p-4 w-full max-w-md">
<div className="relative bg-white rounded-lg shadow dark:bg-gray-700">
{/* Modal Header */}
<div className="flex justify-between items-center p-4 border-b rounded-t dark:border-gray-600">
<h3 className="text-xl font-semibold text-gray-900 dark:text-white">
Add Transaction
</h3>
<button
onClick={() => setModalOpen(false)}
type="button"
className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white"
>
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M6 18L18 6M6 6l12 12"
></path>
</svg>
</button>
</div>
{/* Modal Body */}
<div className="p-4">
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label
htmlFor="transaction-type"
className="block text-sm font-medium text-gray-700"
>
Type
</label>
<select
id="transaction-type"
value={type}
onChange={(e) => setType(e.target.value)}
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
required
>
<option value="Expense">Expense</option>
<option value="Revenue">Revenue</option>
</select>
</div>
<div>
<label
htmlFor="transaction-amount"
className="block text-sm font-medium text-gray-700"
>
Amount
</label>
<input
type="number"
id="transaction-amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
required
/>
</div>
<div>
<label
htmlFor="transaction-description"
className="block text-sm font-medium text-gray-700"
>
Description
</label>
<textarea
id="transaction-description"
value={description}
onChange={(e) => setDescription(e.target.value)}
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
required
></textarea>
</div>
<button
type="submit"
disabled={loading}
className="w-full inline-flex items-center justify-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
>
{loading ? <Loader></Loader> : "Add Transaction"}
</button>
</form>
{message && (
<p className="mt-4 text-sm text-center text-green-600">
{message}
</p>
)}
</div>
</div>
</div>
</div>
)}
</>
);
};
export default AddTransaction;
@@ -0,0 +1,180 @@
import React, { useState } from "react";
import { useCreateTaskMutation } from "../../../store/api/taskApi";
const CreateTask = ({ farmId, onTaskCreated }) => {
const [farm, setFarm] = useState(farmId);
const [taskType, setTaskType] = useState("Sowing");
const [description, setDescription] = useState("Started Sowing the seeds");
const [assignedDate, setAssignedDate] = useState("2025-04-15");
const [status, setStatus] = useState("Pending");
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState("");
const [modalOpen, setModalOpen] = useState(false);
const [createTask] = useCreateTaskMutation();
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
setMessage("");
// In a real app, you might also fetch or choose a crop.
// For now, we assume crop is provided.
const crop = "67ba388f9c4979463e64a39a";
const taskData = {
farm,
crop,
taskType,
description,
assignedDate,
status,
};
try {
const res = await createTask(taskData).unwrap();
setMessage("Task created successfully!");
setModalOpen(false);
// Call the parent's callback with the newly created task
if (onTaskCreated) onTaskCreated(data);
} catch (error) {
console.error("Error creating task:", error);
setMessage("Error creating task.");
} finally {
setLoading(false);
}
};
return (
<>
<button
onClick={() => setModalOpen(true)}
className="block text-white bg-green-600 hover:bg-green-700 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center"
type="button"
>
Create Task
</button>
{modalOpen && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-75">
<div className="relative w-full max-w-2xl p-6 bg-white rounded-lg shadow-xl">
<div className="flex justify-between items-center border-b pb-3">
<h2 className="text-2xl font-bold text-gray-800">Create Task</h2>
<button
onClick={() => setModalOpen(false)}
type="button"
className="text-gray-600 hover:text-gray-800"
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<div className="mt-4">
<form onSubmit={handleSubmit} className="space-y-5">
<div>
<label
htmlFor="task-type"
className="block text-sm font-medium text-gray-700"
>
Task Type
</label>
<select
id="task-type"
value={taskType}
onChange={(e) => setTaskType(e.target.value)}
className="mt-2 block w-full rounded-md border-gray-300 shadow-sm p-3 focus:ring-2 focus:ring-green-400"
required
>
<option value="Sowing">Sowing</option>
<option value="Watering">Watering</option>
<option value="Fertilization">Fertilization</option>
<option value="Pest Control">Pest Control</option>
<option value="Harvesting">Harvesting</option>
</select>
</div>
<div>
<label
htmlFor="description"
className="block text-sm font-medium text-gray-700"
>
Description
</label>
<textarea
id="description"
value={description}
onChange={(e) => setDescription(e.target.value)}
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm p-2 focus:ring-2 focus:ring-green-400"
required
></textarea>
</div>
<div>
<label
htmlFor="assignedDate"
className="block text-sm font-medium text-gray-700"
>
Assigned Date
</label>
<input
type="date"
id="assignedDate"
value={assignedDate}
onChange={(e) => setAssignedDate(e.target.value)}
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm p-2 focus:ring-2 focus:ring-green-400"
required
/>
</div>
<div>
<label
htmlFor="status"
className="block text-sm font-medium text-gray-700"
>
Status
</label>
<select
id="status"
value={status}
onChange={(e) => setStatus(e.target.value)}
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm p-2 focus:ring-2 focus:ring-green-400"
required
>
<option value="Pending">Pending</option>
<option value="Completed">Completed</option>
</select>
</div>
<button
type="submit"
disabled={loading}
className="w-full inline-flex justify-center py-2 px-4 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
>
{loading ? "Creating Task..." : "Create Task"}
</button>
</form>
{message && (
<p className="mt-4 text-center text-sm text-green-600">
{message}
</p>
)}
</div>
</div>
</div>
)}
</>
);
};
export default CreateTask;
@@ -1,29 +1,47 @@
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import Laoder from "../../../components/Laoder"; import Loader from "../../../components/Loader";
import { useParams } from "react-router-dom";
import { useCreateFinanceMutation } from "../../../store/api/financeApi";
import { useGetFarmByIdQuery } from "../../../store/api/farmApi";
const CreateFinance = () => { const CreateFinance = () => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [message, setMessage] = useState(""); const [message, setMessage] = useState("");
// Hardcoded farm ID from your example
const farmId = "67b9e6829c4979463e64a0fc";
const [farm, setFarm] = useState("");
// Hardcoded farm ID from your example
const { farmId } = useParams();
const [createFinance] = useCreateFinanceMutation();
const { data: farmData, isLoading, error } = useGetFarmByIdQuery(farmId);
useEffect(() => {
if (!isLoading && !error && farmData) {
setFarm(farmData);
}
}, [farmData]);
const handleCreateFinance = async () => { const handleCreateFinance = async () => {
setLoading(true); setLoading(true);
setMessage(""); setMessage("");
try { try {
const response = await fetch("http://localhost:8000/api/v1/finance", { const responce = await createFinance({ farm: farmId });
method: "POST", // const response = await fetch("http://localhost:8000/api/v1/finance", {
credentials: "include", // method: "POST",
headers: { // credentials: "include",
"Content-Type": "application/json", // headers: {
}, // "Content-Type": "application/json",
body: JSON.stringify({ farm: farmId }), // },
}); // body: JSON.stringify({ farm: farmId }),
// });
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to create finance"); throw new Error("Failed to create finance");
} }
const data = await response.json(); const data = await response.json();
console.log("Finance response:", data);
setMessage("Finance created successfully!"); setMessage("Finance created successfully!");
} catch (error) { } catch (error) {
console.error("Error creating finance:", error); console.error("Error creating finance:", error);
@@ -34,17 +52,13 @@ const CreateFinance = () => {
}; };
return ( return (
<div className="max-w-md mx-auto p-4 border rounded shadow"> <button
<h2 className="text-xl font-bold mb-4">Create Finance</h2> onClick={handleCreateFinance}
<button disabled={loading}
onClick={handleCreateFinance} className="mt-4 w-30 inline-flex items-center justify-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
disabled={loading} >
className="mt-4 w-full inline-flex items-center justify-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500" Create Finance
> </button>
{loading ? <Laoder></Laoder> : "Create Finance"}
</button>
{message && <p className="mt-4 text-sm text-green-600">{message}</p>}
</div>
); );
}; };
@@ -0,0 +1,260 @@
import React, { useEffect, useState } from "react";
import { useParams, useNavigate } from "react-router-dom";
import Farm from "./Farm";
import CropTable from "./CropTable";
import Transactions from "./Transactions";
import CreateTransactions from "./CreateTransactions";
import Loader from "../../../components/Loader";
import AddTransaction from "./AddTransactions";
import FinanceSummary from "./FinanceSummary";
import CreateTask from "./CreateTask";
import DisplayTast from "./DisplayTask";
import { useGetFarmByIdQuery } from "../../../store/api/farmApi";
import {
useCropHarvestQuery,
useGetCropByIdQuery,
useSuggestFertilizersQuery,
useSuggestNextCropQuery,
useSuggestPesticidesQuery,
} from "../../../store/api/cropApi";
import { PiPottedPlantFill } from "react-icons/pi";
import { GiGrimReaper } from "react-icons/gi";
import { GiProgression } from "react-icons/gi";
function formatDate(isoString) {
const date = new Date(isoString);
return date.toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
}
export default function CropPage() {
const { cropId } = useParams();
const navigate = useNavigate();
const [farmData, setFarmData] = useState("");
const [loading, setLoading] = useState(true);
const farmId = cropId;
const { data: farm, error, isLoading } = useGetFarmByIdQuery(farmId);
const {
data: crop,
error: cropError,
isLoading: cropLoading,
} = useGetCropByIdQuery(cropId);
useEffect(() => {
if (!isLoading && !error && farm) {
setFarmData(farm);
setLoading(false);
}
}, [farm]);
const {
data: harvest,
isLoading: harvestLoading,
error: harvestError,
} = useCropHarvestQuery(cropId);
const {
data: pesticides,
isLoading: pesticideLoading,
error: pesticideError,
} = useSuggestPesticidesQuery(cropId);
const {
data: fertilizers,
isLoading: fertilizerLoading,
error: fertilizerError,
} = useSuggestFertilizersQuery(cropId);
const {
data: nextCrop,
isLoading: nextCropLoading,
error: nextCropError,
} = useSuggestNextCropQuery(cropId);
return (
<div className="w-full bg-white rounded-lg shadow p-4 space-y-8">
{/* Header Section */}
<header className="mb-4">
<div className="flex justify-between items-center">
<h2 className="text-2xl font-bold">{crop?.name}</h2>
<div className="flex items-center space-x-4">
<button
type="button"
className="bg-green-500 hover:bg-green-600 text-white font-semibold py-2 px-4 rounded"
onClick={() => navigate(`/user/dashboard`)}
>
Back
</button>
</div>
</div>
</header>
{/* Crop Table Section */}
<section className="w-full flex justify-center">
<img src={crop?.image} className="w-1/2 h-auto rounded-md" alt="" />
</section>
<section className="w-full flex justify-center flex-col">
<div className="w-full h-auto flex items-center justify-between gap-5">
<div className="w-full">
<button
data-tooltip-target="tooltip-light"
data-tooltip-style="light"
type="button"
class="text-white w-full text-md font-semibold bg-green-700 hover:bg-green-800 focus:ring-4 inline-flex items-center gap-2 focus:outline-none focus:ring-green-300 rounded-lg px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
<PiPottedPlantFill className="text-2xl" />{" "}
{formatDate(crop?.plantedDate)}
</button>
<div
id="tooltip-light"
role="tooltip"
class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg shadow-xs opacity-0 tooltip"
>
Planted Date
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
</div>
<div className="w-full">
<button
data-tooltip-target="tooltip-light1"
data-tooltip-style="light"
type="button"
class=" w-full text-black text-md font-semibold bg-green-200 hover:bg-green-300 focus:ring-4 inline-flex items-center gap-2 focus:outline-none focus:ring-green-300 rounded-lg px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
<GiGrimReaper className="text-2xl" />{" "}
{formatDate(crop?.harvestDate)}
</button>
<div
id="tooltip-light1"
role="tooltip"
class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg shadow-xs opacity-0 tooltip"
>
Harvest Date
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
</div>
<div className="w-full">
<button
data-tooltip-target="tooltip-light2"
data-tooltip-style="light"
type="button"
class="text-black w-full text-md font-semibold bg-white hover:bg-green-50 focus:ring-4 inline-flex items-center gap-2 focus:outline-none focus:ring-orange-300 border-2 border-green-200 rounded-lg px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
<GiProgression className="text-2xl" />{" "}
{formatDate(crop?.harvestDate)}
</button>
<div
id="tooltip-light2"
role="tooltip"
class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg shadow-xs opacity-0 tooltip"
>
Progress
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
</div>
</div>
</section>
<section className="w-full flex justify-center flex-col">
<h1 className="text-2xl font-bold text-center my-3 mb-10">
Automated Mentoring For Crop Health And Groth
</h1>
<div className="overflow-hidden rounded-xl">
<table>
<thead className="bg-gray-50 ">
<tr>
<th className="px-6 py-3 font-extrabold text-left text-sm text-gray-800 uppercase tracking-wider border-2">
Expected Doubts
</th>
<th className="px-6 py-3 font-extrabold text-left text-sm text-gray-800 uppercase tracking-wider border-2">
Approximate Solution
</th>
</tr>
</thead>
<tbody>
<tr className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap border-2">
Approximate Harvest Date
</td>
<td className="px-6 py-4 whitespace-pre-wrap border-2">
{harvest?.message}
</td>
</tr>
<tr className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap border-2">
Suitable Pesticides For Crop
</td>
<td className="px-6 py-4 whitespace-pre-wrap border-2">
{pesticides?.message}
</td>
</tr>
<tr className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap border-2">
Suitable fertilizers For Crop
</td>
<td className="px-6 py-4 whitespace-pre-wrap border-2">
{fertilizers?.message}
</td>
</tr>
<tr className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap border-2">
Best Crop To Grow
</td>
<td className="px-6 py-4 whitespace-pre-wrap border-2">
{nextCrop?.message}
</td>
</tr>
</tbody>
</table>
</div>
{/* <div className="flex items-start justify-start gap-5">
<h6 className="text-lg font-semibold min-w-[200px] text-nowrap">
Approximate Harvest Date:
</h6>
<p className="w-auto"></p>
</div>
<div className="flex items-start justify-start gap-5">
<h6 className="text-lg font-semibold text-nowrap">
Suitable Pesticides For Crop:
</h6>
<p>{pesticides?.message}</p>
</div>
<div className="flex items-start justify-start gap-5">
<h6 className="text-lg font-semibold text-nowrap">
Suitable fertilizers For Crop:
</h6>
<p>{fertilizers?.message}</p>
</div>
<div className="flex items-start justify-start gap-5">
<h6 className="text-lg font-semibold text-nowrap">
Best Crop To Grow:
</h6>
<p>{nextCrop?.message}</p>
</div> */}
</section>
</div>
);
}
+27 -30
View File
@@ -1,10 +1,22 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import Laoder from "../../../components/Laoder"; import Loader from "../../../components/Loader";
import { Link, useNavigate } from "react-router-dom";
import { useGetCropsByFarmQuery } from "../../../store/api/cropApi";
const CropTable = ({ farmId }) => { const CropTable = ({ farmId }) => {
const [crops, setCrops] = useState([]); const [crops, setCrops] = useState([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState(null); const [error, setError] = useState(null);
const navigate = useNavigate();
const {
data: cropsData,
error: cropsError,
isLoading: cropsLoading,
} = useGetCropsByFarmQuery(farmId);
const handleRemoveCrop = async (cropId) => { const handleRemoveCrop = async (cropId) => {
try { try {
await fetch(`http://localhost:8000/api/v1/crop/${cropId}`, { await fetch(`http://localhost:8000/api/v1/crop/${cropId}`, {
@@ -19,37 +31,16 @@ const CropTable = ({ farmId }) => {
setError(err.message); setError(err.message);
} }
}; };
useEffect(() => { useEffect(() => {
const fetchCrops = async () => { if (cropsData) {
try { setCrops(cropsData);
const response = await fetch( setLoading(false);
`http://localhost:8000/api/v1/crop/farm/${farmId}`, }
{ }, [cropsData]);
credentials: "include",
headers: {
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
throw new Error("Failed to fetch crops");
}
const data = await response.json();
setCrops(data || []);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchCrops();
}, []);
if (loading) { if (loading) {
return <Laoder></Laoder>; return <Loader></Loader>;
} }
if (error) { if (error) {
@@ -102,7 +93,13 @@ const CropTable = ({ farmId }) => {
</thead> </thead>
<tbody className="bg-white divide-y divide-gray-200"> <tbody className="bg-white divide-y divide-gray-200">
{crops.map((crop) => ( {crops.map((crop) => (
<tr key={crop._id} className="hover:bg-gray-50"> <tr
key={crop._id}
className="hover:bg-gray-50"
onClick={() => {
navigate(`/user/dashboard/croppage/${crop._id}`);
}}
>
<td className="px-6 py-4 whitespace-nowrap"> <td className="px-6 py-4 whitespace-nowrap">
<div className="h-12 w-12 rounded-full overflow-hidden"> <div className="h-12 w-12 rounded-full overflow-hidden">
{crop.image ? ( {crop.image ? (
@@ -0,0 +1,93 @@
import React, { useState, useEffect } from "react";
import Loader from "../../../components/Loader";
import { useGetTasksByFarmQuery } from "../../../store/api/taskApi";
const DisplayTast = ({ farmId }) => {
const [tasks, setTasks] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const {
data: taskList,
error: taskError,
isLoading,
} = useGetTasksByFarmQuery(farmId);
// Function to delete a task and update the state
const handleDeleteTask = async (taskId) => {
try {
const response = await fetch(
`http://localhost:8000/api/v1/task/${taskId}`,
{
method: "DELETE",
credentials: "include",
}
);
// Assuming that a successful deletion returns a 200 status code
if (!response.ok) {
throw new Error("Failed to delete task");
}
// Optionally check the response, but we'll update state regardless.
// Remove the deleted task from state.
setTasks((prevTasks) => prevTasks.filter((task) => task._id !== taskId));
} catch (error) {
console.error("Error deleting task:", error);
// Optionally, you could set an error state here.
}
};
useEffect(() => {
if (taskList) {
setTasks(taskList);
setLoading(false);
}
}, [farmId, taskList]);
if (loading) return <div>Loading tasks...</div>;
if (error) return <div className="text-red-600">Error: {error}</div>;
if (!tasks || tasks.length === 0) {
return <div className="p-4">No tasks found for this farm.</div>;
}
return (
<div className="overflow-x-auto w-full p-4">
<table className="w-full text-sm text-left border">
<thead className="text-xs text-gray-700 uppercase bg-gray-50">
<tr>
<th className="px-6 py-3">Task Type</th>
<th className="px-6 py-3">Description</th>
<th className="px-6 py-3">Assigned Date</th>
<th className="px-6 py-3">Status</th>
<th className="px-6 py-3">Action</th>
</tr>
</thead>
<tbody>
{tasks.map((task) => (
<tr key={task._id} className="bg-white border-b hover:bg-gray-50">
<td className="px-6 py-4">{task.taskType}</td>
<td className="px-6 py-4">{task.description}</td>
<td className="px-6 py-4">
{new Date(task.assignedDate).toLocaleDateString()}
</td>
<td className="px-6 py-4">{task.status}</td>
<td className="px-6 py-4">
<button
onClick={() => handleDeleteTask(task._id)}
className="block text-white bg-red-600 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5"
type="button"
>
Remove
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default DisplayTast;
+13 -10
View File
@@ -1,23 +1,26 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useDeleteFarmMutation } from "../../../store/api/farmApi";
const EditFarm = ({ _id, onDelete }) => { const EditFarm = ({ _id, onDelete }) => {
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
const [deleteFarm] = useDeleteFarmMutation();
// This function will run when the "Yes, I'm sure" button is clicked. // This function will run when the "Yes, I'm sure" button is clicked.
const handleDeleteFarm = async () => { const handleDeleteFarm = async () => {
try { try {
const response = await fetch(`http://localhost:8000/api/v1/farm/${_id}`, { const res = await deleteFarm(_id);
method: "DELETE", // const response = await fetch(`http://localhost:8000/api/v1/farm/${_id}`, {
credentials: "include", // method: "DELETE",
}); // credentials: "include",
const data = await response.json(); // });
console.log("Delete response:", data); // const data = await response.json();
if (data.success) {
// Notify the parent component to update its state
if (onDelete) onDelete(_id); if (!res) {
return null;
} }
setModalOpen(false); // Close the modal after the operation setModalOpen(false); // Close the modal after the operation
window.location.reload();
} catch (error) { } catch (error) {
console.error("Error deleting farm:", error); console.error("Error deleting farm:", error);
} }
+3 -1
View File
@@ -48,7 +48,9 @@ const Farm = ({ farmData, farmId }) => {
<td className="px-6 py-4">{farmData.soilType}</td> <td className="px-6 py-4">{farmData.soilType}</td>
<td className="px-6 py-4">{farmData.size}</td> <td className="px-6 py-4">{farmData.size}</td>
<td className="px-6 py-4">{farmData.waterContent}</td> <td className="px-6 py-4">{farmData.waterContent}</td>
<td className="px-6 py-4">Edit</td> <td className="px-6 py-4">
<EditFarm></EditFarm>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
+69 -49
View File
@@ -4,69 +4,89 @@ import Farm from "./Farm";
import CropTable from "./CropTable"; import CropTable from "./CropTable";
import Transactions from "./Transactions"; import Transactions from "./Transactions";
import CreateTransactions from "./CreateTransactions"; import CreateTransactions from "./CreateTransactions";
import Laoder from "../../../components/Laoder"; import Loader from "../../../components/Loader";
import AddTransaction from "./AddTransactions";
import FinanceSummary from "./FinanceSummary";
import CreateTask from "./CreateTask";
import DisplayTast from "./DisplayTask";
import { useGetFarmByIdQuery } from "../../../store/api/farmApi";
export default function FarmPage() { export default function FarmPage() {
const { farmId } = useParams(); const { farmId } = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
const [farmData, setFarmData] = useState(null); const [farmData, setFarmData] = useState("");
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const { data: farm, error, isLoading } = useGetFarmByIdQuery(farmId);
useEffect(() => { useEffect(() => {
async function fetching() { if (!isLoading && !error && farm) {
try { setFarmData(farm);
const response = await fetch( setLoading(false);
`http://localhost:8000/api/v1/farm/${farmId}`,
{
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
}
);
const jsonData = await response.json();
console.log(jsonData);
setFarmData(jsonData);
} catch (error) {
console.error("Error fetching farm data: ", error);
} finally {
setLoading(false);
}
} }
fetching(); }, [farm]);
}, [farmId]);
if (loading) {
return <Laoder></Laoder>;
}
if (!farmData) {
return (
<div className="w-full bg-white rounded-lg shadow p-4">
<p>No farm data found.</p>
</div>
);
}
console.log("My farm id is : ", farmId);
return ( return (
<div className="w-full bg-white rounded-lg shadow p-4"> <div className="w-full bg-white rounded-lg shadow p-4 space-y-8">
{/* Back Button */} {/* Header Section */}
<header className="mb-4">
<div className="flex justify-end">
<Farm farmData={farmData} farmId={farmId} />
</div>
</header>
<div className="mb-4 flex justify-end"> {/* Crop Table Section */}
<Farm farmData={farmData} farmId={farmId}></Farm> <section>
</div> <CropTable farmId={farmId} />
<div className="mb-4 "> </section>
<CropTable farmId={farmId}></CropTable>
</div> {/* Create Transactions Section */}
<div className="mb-4 flex justify-end"> <section>
<CreateTransactions farmId={farmId}></CreateTransactions> <div className="flex justify-end">
</div> <CreateTransactions farmId={farmId} />
<div className="mb-4 "> </div>
<Transactions farmId={farmId}></Transactions> </section>
</div>
{/* Transactions Table Section */}
<section>
<Transactions farmId={farmId} />
</section>
{/* Add Transaction Modal Section */}
<section>
<div className="flex justify-end">
<AddTransaction farmId={farmId} financeId={farmData?.finances?._id} />
</div>
</section>
{/* Finance Summary Section */}
<section>
<div className="flex justify-end">
<FinanceSummary farmId={farmId} financeId={farmData?.finances?._id} />
</div>
</section>
{/* Create Task Section */}
<section>
<div className="flex justify-end">
<CreateTask farmId={farmId} />
</div>
</section>
{/* Display Task Section */}
<section>
<div className="flex justify-end">
<DisplayTast farmId={farmId} />
</div>
</section>
</div> </div>
); );
} }
@@ -0,0 +1,127 @@
import React, { useState, useEffect } from "react";
import Loader from "../../../components/Loader";
import { useGetTransactionsQuery } from "../../../store/api/financeApi";
function formatTimestamp(isoString) {
const date = new Date(isoString);
return date.toLocaleString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: true, // Ensures AM/PM format
});
}
const FinanceSummary = ({ farmId, financeId }) => {
const [summary, setSummary] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const {
data: transaction,
error: transactionError,
isLoading,
} = useGetTransactionsQuery(financeId);
useEffect(() => {
const fetchSummary = async () => {
setLoading(true);
setError("");
try {
const response = await fetch(
`http://localhost:8000/api/v1/finance/summary/${financeId}`,
{ credentials: "include" }
);
if (!response.ok) {
throw new Error("Failed to fetch summary");
}
const data = await response.json();
setSummary(data);
} catch (err) {
console.error("Error fetching finance summary:", err);
setError("Error fetching summary");
} finally {
setLoading(false);
}
};
fetchSummary();
}, [farmId]);
// if (loading) return <Loader />;
//if (error) return <div className="p-4 text-center text-red-600">{error}</div>;
// Extract only the important fields.
const { totalExpenses, totalRevenue, transactions } = summary || {};
const transactionsCount = Array.isArray(transactions)
? transactions.length
: 0;
return (
<div className="w-full mx-auto p-8 bg-gray-50">
<div className="bg-white rounded-lg shadow overflow-hidden">
<header className="bg-blue-600 px-6 py-4">
<h2 className="text-3xl font-bold text-white">
Transactions Summary
</h2>
</header>
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" className="px-6 py-3">
Type of Transaction
</th>
<th scope="col" className="px-6 py-3">
Amount
</th>
<th scope="col" className="px-6 py-3">
Description
</th>
<th scope="col" className="px-6 py-3">
Date
</th>
<th scope="col" className="px-6 py-3">
Action
</th>
</tr>
</thead>
<tbody>
{transaction?.map((transaction) => (
<tr>
<td scope="col" className="px-6 py-3">
{transaction.type}
</td>
<td scope="col" className="px-6 py-3">
{transaction.amount}
</td>
<td scope="col" className="px-6 py-3">
{transaction.description}
</td>
<td scope="col" className="px-6 py-3">
{formatTimestamp(transaction.date)}
</td>
<td className="px-6 py-4">
<button
className="block text-white bg-red-600 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5"
type="button"
>
Remove
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};
export default FinanceSummary;
@@ -1,6 +1,6 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import Td from "../../../components/Td"; import Td from "../../../components/Td";
import Laoder from "../../../components/Laoder"; import Loader from "../../../components/Loader";
const Transactions = ({ farmId }) => { const Transactions = ({ farmId }) => {
const [data, setData] = useState([]); const [data, setData] = useState([]);
@@ -13,7 +13,7 @@ const Transactions = ({ farmId }) => {
.then((response) => response.json()) .then((response) => response.json())
.then((data) => { .then((data) => {
setData(data); setData(data);
console.log("Fetched data:", data);
setLoading(false); setLoading(false);
}) })
.catch((error) => { .catch((error) => {
@@ -25,38 +25,28 @@ const Transactions = ({ farmId }) => {
return ( return (
<div className="relative overflow-x-auto shadow-md sm:rounded-lg"> <div className="relative overflow-x-auto shadow-md sm:rounded-lg">
{loading ? ( {loading ? (
<Laoder></Laoder> <Loader />
) : ( ) : (
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400"> <table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400"> <thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr> <tr>
<th scope="col" className="px-6 py-3"> <th scope="col" className="px-6 py-3">
Farm name Total Expenses
</th> </th>
<th scope="col" className="px-6 py-3"> <th scope="col" className="px-6 py-3">
Location totalRevenue
</th>
<th scope="col" className="px-6 py-3">
Type
</th>
<th scope="col" className="px-6 py-3">
Size (acres)
</th>
<th scope="col" className="px-6 py-3">
Action
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{Array.isArray(data) && data.length > 0 ? ( <tr>
data.map((item) => <Td key={item.id} children={item} />) <td className="px-6 py-3">
) : ( {data.totalExpenses ? data.totalExpenses : "N/A"}
<tr> </td>
<td colSpan={5} className="text-center"> <td className="px-6 py-3">
No data available {data.totalRevenue ? data.totalRevenue : "N/A"}
</td> </td>
</tr> </tr>
)}
</tbody> </tbody>
</table> </table>
)} )}

Some files were not shown because too many files have changed in this diff Show More