Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
fe55abc83e
|
@@ -1,2 +0,0 @@
|
|||||||
package-lock.json
|
|
||||||
node_modules/
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Environment files
|
||||||
|
.env
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Build outputs
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Static files
|
||||||
|
public/
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Test files
|
||||||
|
coverage/
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# Database files
|
||||||
|
*.sqlite3
|
||||||
|
*.db
|
||||||
|
*.db-wal
|
||||||
|
*.db-shm
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# IDE and editor files
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
# System files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Other
|
||||||
|
*.log.*
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
const Crop = require("../Models/crop.model.js");
|
||||||
|
const Farm = require("../Models/farm.model.js");
|
||||||
|
const { uploadOnCloudinary } = require("../Utils/cloudinary.js");
|
||||||
|
const { run } = require("../Utils/model.js");
|
||||||
|
|
||||||
|
// Create a new crop
|
||||||
|
const createCrop = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { name, farm, harvestDate, growthStage, healthStatus } = req.body;
|
||||||
|
if (!req.file.path) {
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "Avatar not uploaded on cloudinary.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageUrl = await uploadOnCloudinary(req.file.path);
|
||||||
|
|
||||||
|
console.log("Image url is : ", imageUrl);
|
||||||
|
|
||||||
|
if (!imageUrl) {
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "Image not uploaded on cloudinary.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the farm exists
|
||||||
|
const existingFarm = await Farm.findById(farm);
|
||||||
|
if (!existingFarm)
|
||||||
|
return res.status(404).json({ message: "Farm not found" });
|
||||||
|
|
||||||
|
const crop = new Crop({
|
||||||
|
name,
|
||||||
|
farm,
|
||||||
|
image: imageUrl,
|
||||||
|
harvestDate,
|
||||||
|
growthStage,
|
||||||
|
healthStatus,
|
||||||
|
});
|
||||||
|
|
||||||
|
await crop.save();
|
||||||
|
|
||||||
|
// Add crop to farm
|
||||||
|
existingFarm.crops.push(crop._id);
|
||||||
|
await existingFarm.save();
|
||||||
|
|
||||||
|
res.status(201).json(crop);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all crops for a specific farm
|
||||||
|
const getCropsByFarm = async (req, res) => {
|
||||||
|
try {
|
||||||
|
console.log("My farm id is : ", req.params.farmId);
|
||||||
|
const crops = await Crop.find({ farm: req.params.farmId });
|
||||||
|
|
||||||
|
res.status(200).json(crops);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a single crop by ID
|
||||||
|
const getCropById = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const crop = await Crop.findById(req.params.cropId).populate("farm");
|
||||||
|
|
||||||
|
if (!crop) return res.status(404).json({ message: "Crop not found" });
|
||||||
|
|
||||||
|
res.status(200).json(crop);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update crop details
|
||||||
|
const updateCrop = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const updatedCrop = await Crop.findByIdAndUpdate(
|
||||||
|
req.params.cropId,
|
||||||
|
req.body,
|
||||||
|
{ new: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!updatedCrop)
|
||||||
|
return res.status(404).json({ message: "Crop not found" });
|
||||||
|
|
||||||
|
res.status(200).json(updatedCrop);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delete a crop
|
||||||
|
const deleteCrop = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const crop = await Crop.findById(req.params.cropId);
|
||||||
|
|
||||||
|
if (!crop) return res.status(404).json({ message: "Crop not found" });
|
||||||
|
|
||||||
|
await crop.deleteOne();
|
||||||
|
|
||||||
|
// Remove crop from the farm
|
||||||
|
await Farm.findByIdAndUpdate(crop.farm, { $pull: { crops: crop._id } });
|
||||||
|
|
||||||
|
res.status(200).json({ message: "Crop deleted successfully" });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update crop growth stage
|
||||||
|
const updateGrowthStage = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { growthStage } = req.body;
|
||||||
|
|
||||||
|
const crop = await Crop.findById(req.params.cropId);
|
||||||
|
if (!crop) return res.status(404).json({ message: "Crop not found" });
|
||||||
|
|
||||||
|
crop.growthStage = growthStage;
|
||||||
|
await crop.save();
|
||||||
|
|
||||||
|
res.status(200).json({ message: "Growth stage updated", crop });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update crop health status
|
||||||
|
const updateHealthStatus = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { healthStatus } = req.body;
|
||||||
|
|
||||||
|
const crop = await Crop.findById(req.params.cropId);
|
||||||
|
if (!crop) return res.status(404).json({ message: "Crop not found" });
|
||||||
|
|
||||||
|
crop.healthStatus = healthStatus;
|
||||||
|
await crop.save();
|
||||||
|
|
||||||
|
res.status(200).json({ message: "Health status updated", crop });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 = {
|
||||||
|
createCrop,
|
||||||
|
getCropsByFarm,
|
||||||
|
getCropById,
|
||||||
|
updateCrop,
|
||||||
|
deleteCrop,
|
||||||
|
updateGrowthStage,
|
||||||
|
updateHealthStatus,
|
||||||
|
cropHarvest,
|
||||||
|
suggestNextCrop,
|
||||||
|
suggestPesticides,
|
||||||
|
suggestFertilizers,
|
||||||
|
};
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
const Farm = require("../Models/farm.model.js");
|
||||||
|
const Crop = require("../Models/crop.model.js");
|
||||||
|
const Finance = require("../Models/finance.model.js");
|
||||||
|
|
||||||
|
// Create a farm
|
||||||
|
const createFarm = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { name, location, waterContent, soilType, size } = req.body;
|
||||||
|
|
||||||
|
const farm = new Farm({
|
||||||
|
name,
|
||||||
|
location,
|
||||||
|
size,
|
||||||
|
waterContent,
|
||||||
|
soilType,
|
||||||
|
owner: req.user._id,
|
||||||
|
});
|
||||||
|
|
||||||
|
await farm.save();
|
||||||
|
res.status(201).json(farm);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all farms for a user
|
||||||
|
const getUserFarms = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const farms = await Farm.find({ owner: req.user._id })
|
||||||
|
.populate("crops")
|
||||||
|
.populate("finances");
|
||||||
|
|
||||||
|
res.status(200).json(farms);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a single farm by ID
|
||||||
|
const getFarmById = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const farm = await Farm.findById(req.params.farmId)
|
||||||
|
.populate("crops")
|
||||||
|
.populate("finances");
|
||||||
|
|
||||||
|
if (!farm) return res.status(404).json({ message: "Farm not found" });
|
||||||
|
|
||||||
|
res.status(200).json(farm);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update farm details
|
||||||
|
const updateFarm = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const updatedFarm = await Farm.findByIdAndUpdate(
|
||||||
|
req.params.farmId,
|
||||||
|
req.body,
|
||||||
|
{ new: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!updatedFarm)
|
||||||
|
return res.status(404).json({ message: "Farm not found" });
|
||||||
|
|
||||||
|
res.status(200).json(updatedFarm);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delete a farm
|
||||||
|
const deleteFarm = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const farm = await Farm.findById(req.params.farmId);
|
||||||
|
|
||||||
|
if (!farm) return res.status(404).json({ message: "Farm not found" });
|
||||||
|
|
||||||
|
await Crop.deleteMany({ farm: farm._id });
|
||||||
|
await Finance.findByIdAndDelete(farm.finances);
|
||||||
|
await farm.deleteOne();
|
||||||
|
|
||||||
|
res.status(200).json({ message: "Farm deleted successfully" });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add fertilizer to a farm
|
||||||
|
const addFertilizer = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { name, quantity } = req.body;
|
||||||
|
|
||||||
|
const farm = await Farm.findById(req.params.farmId);
|
||||||
|
if (!farm) return res.status(404).json({ message: "Farm not found" });
|
||||||
|
|
||||||
|
farm.fertilizer.push({ name, quantity });
|
||||||
|
await farm.save();
|
||||||
|
|
||||||
|
res.status(200).json({ message: "Fertilizer added", farm });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add pesticide to a farm
|
||||||
|
const addPesticide = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { name, quantity } = req.body;
|
||||||
|
|
||||||
|
const farm = await Farm.findById(req.params.farmId);
|
||||||
|
if (!farm) return res.status(404).json({ message: "Farm not found" });
|
||||||
|
|
||||||
|
farm.pestisides.push({ name, quantity });
|
||||||
|
await farm.save();
|
||||||
|
|
||||||
|
res.status(200).json({ message: "Pesticide added", farm });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createFarm,
|
||||||
|
getUserFarms,
|
||||||
|
getFarmById,
|
||||||
|
updateFarm,
|
||||||
|
deleteFarm,
|
||||||
|
addFertilizer,
|
||||||
|
addPesticide,
|
||||||
|
};
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
const Finance = require("../Models/finance.model.js");
|
||||||
|
const Farm = require("../Models/farm.model.js");
|
||||||
|
|
||||||
|
// Create finance record for a farm
|
||||||
|
const createFinance = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { farm } = 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 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get finance details by farm ID
|
||||||
|
const getFinanceByFarm = async (req, res) => {
|
||||||
|
try {
|
||||||
|
console.log("My farm id is : ", req.params.farmId);
|
||||||
|
const finance = await Finance.findOne({ farm: req.params.farmId });
|
||||||
|
|
||||||
|
if (!finance)
|
||||||
|
return res.status(404).json({ message: "Finance record not found" });
|
||||||
|
|
||||||
|
res.status(200).json(finance);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add a transaction (expense/revenue)
|
||||||
|
const addTransaction = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { type, amount, description } = req.body;
|
||||||
|
|
||||||
|
const finance = await Finance.findById(req.params.financeId);
|
||||||
|
if (!finance)
|
||||||
|
return res.status(404).json({ message: "Finance record not found" });
|
||||||
|
|
||||||
|
finance.transactions.push({ type, amount, description });
|
||||||
|
|
||||||
|
// Update totals
|
||||||
|
if (type === "Expense") {
|
||||||
|
finance.totalExpenses += amount;
|
||||||
|
} else if (type === "Revenue") {
|
||||||
|
finance.totalRevenue += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
await finance.save();
|
||||||
|
res.status(200).json({ message: "Transaction added", finance });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delete a transaction
|
||||||
|
const deleteTransaction = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const finance = await Finance.findById(req.params.financeId);
|
||||||
|
if (!finance)
|
||||||
|
return res.status(404).json({ message: "Finance record not found" });
|
||||||
|
|
||||||
|
const transaction = finance.transactions.id(req.params.transactionId);
|
||||||
|
if (!transaction)
|
||||||
|
return res.status(404).json({ message: "Transaction not found" });
|
||||||
|
|
||||||
|
// Adjust totals before removing
|
||||||
|
if (transaction.type === "Expense") {
|
||||||
|
finance.totalExpenses -= transaction.amount;
|
||||||
|
} else if (transaction.type === "Revenue") {
|
||||||
|
finance.totalRevenue -= transaction.amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.remove();
|
||||||
|
await finance.save();
|
||||||
|
|
||||||
|
res.status(200).json({ message: "Transaction deleted", finance });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all transactions for a farm's finance
|
||||||
|
const getTransactions = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const finance = await Finance.findById(req.params.financeId);
|
||||||
|
if (!finance)
|
||||||
|
return res.status(404).json({ message: "Finance record not found" });
|
||||||
|
|
||||||
|
res.status(200).json(finance.transactions);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get total expenses and revenue
|
||||||
|
const getFinancialSummary = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const finance = await Finance.findById(req.params.financeId);
|
||||||
|
if (!finance)
|
||||||
|
return res.status(404).json({ message: "Finance record not found" });
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
totalExpenses: finance.totalExpenses,
|
||||||
|
totalRevenue: finance.totalRevenue,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createFinance,
|
||||||
|
getFinanceByFarm,
|
||||||
|
addTransaction,
|
||||||
|
deleteTransaction,
|
||||||
|
getTransactions,
|
||||||
|
getFinancialSummary,
|
||||||
|
};
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
const Task = require("../Models/task.model.js");
|
||||||
|
const Farm = require("../Models/farm.model.js");
|
||||||
|
const Crop = require("../Models/crop.model.js");
|
||||||
|
|
||||||
|
// Create a new task
|
||||||
|
const createTask = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { farm, crop, taskType, description, assignedDate, status } =
|
||||||
|
req.body;
|
||||||
|
|
||||||
|
// Validate farm existence
|
||||||
|
const existingFarm = await Farm.findById(farm);
|
||||||
|
if (!existingFarm)
|
||||||
|
return res.status(404).json({ message: "Farm not found" });
|
||||||
|
|
||||||
|
// Validate crop if provided
|
||||||
|
if (crop) {
|
||||||
|
const existingCrop = await Crop.findById(crop);
|
||||||
|
if (!existingCrop)
|
||||||
|
return res.status(404).json({ message: "Crop not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const task = new Task({
|
||||||
|
farm,
|
||||||
|
crop,
|
||||||
|
taskType,
|
||||||
|
description,
|
||||||
|
assignedDate,
|
||||||
|
status,
|
||||||
|
});
|
||||||
|
|
||||||
|
await task.save();
|
||||||
|
res.status(201).json(task);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all tasks for a specific farm
|
||||||
|
const getTasksByFarm = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const tasks = await Task.find({ farm: req.params.farmId }).populate("crop");
|
||||||
|
|
||||||
|
res.status(200).json(tasks);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a single task by ID
|
||||||
|
const getTaskById = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const task = await Task.findById(req.params.taskId).populate("farm crop");
|
||||||
|
|
||||||
|
if (!task) return res.status(404).json({ message: "Task not found" });
|
||||||
|
|
||||||
|
res.status(200).json(task);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update task details
|
||||||
|
const updateTask = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const updatedTask = await Task.findByIdAndUpdate(
|
||||||
|
req.params.taskId,
|
||||||
|
req.body,
|
||||||
|
{ new: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!updatedTask)
|
||||||
|
return res.status(404).json({ message: "Task not found" });
|
||||||
|
|
||||||
|
res.status(200).json(updatedTask);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delete a task
|
||||||
|
const deleteTask = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const task = await Task.findById(req.params.taskId);
|
||||||
|
|
||||||
|
if (!task) return res.status(404).json({ message: "Task not found" });
|
||||||
|
|
||||||
|
await task.deleteOne();
|
||||||
|
|
||||||
|
res.status(200).json({ message: "Task deleted successfully" });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update task status (Pending → Completed)
|
||||||
|
const updateTaskStatus = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { status } = req.body;
|
||||||
|
|
||||||
|
const task = await Task.findById(req.params.taskId);
|
||||||
|
if (!task) return res.status(404).json({ message: "Task not found" });
|
||||||
|
|
||||||
|
task.status = status;
|
||||||
|
await task.save();
|
||||||
|
|
||||||
|
res.status(200).json({ message: "Task status updated", task });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createTask,
|
||||||
|
getTasksByFarm,
|
||||||
|
getTaskById,
|
||||||
|
updateTask,
|
||||||
|
deleteTask,
|
||||||
|
updateTaskStatus,
|
||||||
|
};
|
||||||
@@ -0,0 +1,466 @@
|
|||||||
|
const catchAsyncErrors = require("../Middlewares/catchAsyncErrors.js");
|
||||||
|
const User = require("../Models/user.model.js");
|
||||||
|
const { uploadOnCloudinary } = require("../Utils/cloudinary.js");
|
||||||
|
const sendEmail = require("../Utils/sendmail.js");
|
||||||
|
const crypto = require("crypto");
|
||||||
|
const jwt = require("jsonwebtoken");
|
||||||
|
|
||||||
|
// Register or Sign up new User -- Done
|
||||||
|
const registerUser = catchAsyncErrors(async (req, res) => {
|
||||||
|
const { name, email, password, role } = req.body;
|
||||||
|
|
||||||
|
const user = await User.create({
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
role,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "User not created something went wrong.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "User is registered successfully",
|
||||||
|
data: user,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Login user in our web app -- Done
|
||||||
|
const loginUser = catchAsyncErrors(async (req, res) => {
|
||||||
|
const { email, password } = req.body;
|
||||||
|
|
||||||
|
const user = await User.findOne({ email });
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "User not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkUser = await user.isPasswordCorrect(password);
|
||||||
|
|
||||||
|
if (!checkUser) {
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "Password is incorrect",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = await user.generateRefreshToken();
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "token not created something went wrong.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
user.password = null;
|
||||||
|
|
||||||
|
return res
|
||||||
|
.status(200)
|
||||||
|
.cookie(process.env.TOKEN_NAME, token, {
|
||||||
|
path: "/",
|
||||||
|
sameSite: "None",
|
||||||
|
secure: process.env.NODE_ENV === "production",
|
||||||
|
httpOnly: true,
|
||||||
|
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
||||||
|
})
|
||||||
|
.json({
|
||||||
|
success: true,
|
||||||
|
message: "User is successfully logged in.",
|
||||||
|
data: user,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Logout user in our web app -- Done
|
||||||
|
const logoutUser = catchAsyncErrors(async (req, res) => {
|
||||||
|
return res
|
||||||
|
.clearCookie(process.env.TOKEN_NAME, {
|
||||||
|
path: "/",
|
||||||
|
sameSite: "None",
|
||||||
|
secure: process.env.NODE_ENV === "production",
|
||||||
|
httpOnly: true,
|
||||||
|
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
||||||
|
})
|
||||||
|
.status(201)
|
||||||
|
.json({
|
||||||
|
success: true,
|
||||||
|
message: "User is logged out successfully",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -- DONE
|
||||||
|
const intializeUser = catchAsyncErrors(async (req, res) => {
|
||||||
|
const tokenValue = req.cookies[process.env.TOKEN_NAME];
|
||||||
|
|
||||||
|
// console.log("I am the one who is doing this : ", tokenValue);
|
||||||
|
|
||||||
|
if (!tokenValue) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "User is not logged in.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const payload = await jwt.verify(
|
||||||
|
tokenValue,
|
||||||
|
process.env.REFRESH_TOKEN_SECRET
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!payload) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "Something went wrong",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await User.findById(payload._id).select("-password");
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "User data get successfully",
|
||||||
|
data: user,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "Something went wrong",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update user deatails -- ADMIN
|
||||||
|
const updateUserDetails = catchAsyncErrors(async (req, res) => {
|
||||||
|
const user = await User.findById(req.params.id);
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: true,
|
||||||
|
message: "User not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { name, email } = req.body;
|
||||||
|
|
||||||
|
const updateUser = await User.findByIdAndUpdate(req.params.id, {
|
||||||
|
$set: {
|
||||||
|
name: name,
|
||||||
|
email: email,
|
||||||
|
},
|
||||||
|
}).select("-password");
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "User is updated successfully",
|
||||||
|
data: updateUser,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// forget password -- Done
|
||||||
|
const forgetPassword = catchAsyncErrors(async (req, res) => {
|
||||||
|
const { email } = req.body;
|
||||||
|
const user = await User.findOne({ email });
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "User not found ",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// get reset password
|
||||||
|
|
||||||
|
const resetToken = await user.getResetPassword();
|
||||||
|
|
||||||
|
await user.save({ validateBeforeSave: false });
|
||||||
|
|
||||||
|
/*const resetPasswordUrl = `${req.protocol}://${req.get(
|
||||||
|
"host"
|
||||||
|
)}/api/v1/password/reset/${resetToken}`;*/
|
||||||
|
|
||||||
|
const resetPasswordUrl = `${process.env.FRONTEND_URI}/user/api/v1/password/reset/${resetToken}`;
|
||||||
|
|
||||||
|
const message = `Your password token is :-\n\n${resetPasswordUrl}\n\nIf you are not requested this email then please ingore this mail.`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sendEmail({
|
||||||
|
email: user.email,
|
||||||
|
subject: "MentorFlux password recovery",
|
||||||
|
message: message,
|
||||||
|
});
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: `Email sent to ${email} successfully`,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
user.resetPasswordToken = undefined;
|
||||||
|
user.resetPasswordExpiry = undefined;
|
||||||
|
await user.save({ validateBeforeSave: false });
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "Something went wrong ",
|
||||||
|
error: error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// reset users password -- DONE
|
||||||
|
const resetPassword = catchAsyncErrors(async (req, res) => {
|
||||||
|
const token = req.params.token;
|
||||||
|
|
||||||
|
const { password, confirmPassword } = req.body;
|
||||||
|
|
||||||
|
//console.log("My password is :", password);
|
||||||
|
//console.log("My confirmPassword is :", confirmPassword);
|
||||||
|
//console.log("My token is :", token);
|
||||||
|
const resetPasswordToken = await crypto
|
||||||
|
.createHash("sha256")
|
||||||
|
.update(token)
|
||||||
|
.digest("hex");
|
||||||
|
|
||||||
|
const user = await User.findOne({
|
||||||
|
resetPasswordToken,
|
||||||
|
resetPasswordExpiry: { $gte: Date.now() },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(401).json({
|
||||||
|
success: false,
|
||||||
|
message: "Reset Password token is invalid or has been expired",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password !== confirmPassword) {
|
||||||
|
return res.status(401).json({
|
||||||
|
success: false,
|
||||||
|
message: "Please enter password and confirm password",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
user.password = password;
|
||||||
|
user.resetPasswordToken = undefined;
|
||||||
|
user.resetPasswordExpiry = undefined;
|
||||||
|
|
||||||
|
//console.log("To check the user ", user);
|
||||||
|
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "Password changed successfully",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// get user personal details
|
||||||
|
const getUserDetails = catchAsyncErrors(async (req, res) => {
|
||||||
|
|
||||||
|
|
||||||
|
const user = await User.findById(req.user._id);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "Something went wrong ",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "User details are fetched successfully",
|
||||||
|
data: user,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update users password
|
||||||
|
const updatePassword = catchAsyncErrors(async (req, res) => {
|
||||||
|
const { password, oldPassword, confirmPassword } = req.body;
|
||||||
|
|
||||||
|
const user = await User.findById(req.user._id);
|
||||||
|
|
||||||
|
const isPasswordMatched = await user.isPasswordCorrect(oldPassword);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "User not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPasswordMatched) {
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "Old password is incorrect.Please enter correct password ",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password !== confirmPassword) {
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "Password and Confirm password should be same.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
user.password = password;
|
||||||
|
await user.save({ validateBeforeSave: false });
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "Password upadated successfully",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// update personal details
|
||||||
|
const updatePersonalDetails = catchAsyncErrors(async (req, res) => {
|
||||||
|
const { name, email } = req.body;
|
||||||
|
const user = await User.findByIdAndUpdate(req.user._id, {
|
||||||
|
$set: {
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "Something went wrong",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "User details updated successfully",
|
||||||
|
data: user,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get all users details -- ADMIN
|
||||||
|
const getAllusersDetail = catchAsyncErrors(async (req, res) => {
|
||||||
|
const users = await find();
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "All user fetch successfully",
|
||||||
|
data: users,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// get single user details
|
||||||
|
const getSingaluserDetail = catchAsyncErrors(async (req, res) => {
|
||||||
|
const user = await User.findById(req.params.id);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "User not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// upadate user Role -- ADMIN
|
||||||
|
const updateUserRole = catchAsyncErrors(async (req, res) => {
|
||||||
|
const { name, email, role } = req.body;
|
||||||
|
const user = await User.findByIdAndUpdate(req.params.id, {
|
||||||
|
$set: {
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
role,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "Something went wrong",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "User Role updated successfully",
|
||||||
|
data: user,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete user -- ADMIN
|
||||||
|
const DeleteUser = catchAsyncErrors(async (req, res) => {
|
||||||
|
const user = await User.findByIdAndDelete(req.params.id);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "User does not exist",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "User deleted successfully",
|
||||||
|
data: user,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// update avatar -- user
|
||||||
|
const updateAvatar = catchAsyncErrors(async (req, res) => {
|
||||||
|
//console.log("Our file is : ", req.file.path);
|
||||||
|
|
||||||
|
if (!req.file.path) {
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "Avatar not uploaded on cloudinary.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const avatarUrl = await uploadOnCloudinary(req.file.path);
|
||||||
|
|
||||||
|
if (!avatarUrl) {
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: "Avatar not uploaded on cloudinary.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log("Avatar url is : ", avatarUrl);
|
||||||
|
|
||||||
|
//console.log("our user is : ", req.user);
|
||||||
|
|
||||||
|
const user = await User.findByIdAndUpdate(req.user._id, {
|
||||||
|
$set: {
|
||||||
|
avatar: avatarUrl,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "User not found.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "Avatar updated successfully.",
|
||||||
|
data: user,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
registerUser,
|
||||||
|
loginUser,
|
||||||
|
logoutUser,
|
||||||
|
updateUserDetails,
|
||||||
|
forgetPassword,
|
||||||
|
resetPassword,
|
||||||
|
getUserDetails,
|
||||||
|
updatePassword,
|
||||||
|
updatePersonalDetails,
|
||||||
|
updateUserRole,
|
||||||
|
DeleteUser,
|
||||||
|
intializeUser,
|
||||||
|
updateAvatar,
|
||||||
|
};
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
const catchAsyncErrors = require("../Middlewares/catchAsyncErrors.js");
|
||||||
|
|
||||||
|
const DB_connect = catchAsyncErrors(async () => {
|
||||||
|
try {
|
||||||
|
const connectionInstance = await mongoose.connect(
|
||||||
|
`${process.env.MONGODB_URI}/${process.env.DATABASE_NAME}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!connectionInstance) {
|
||||||
|
console.log("MongoDB connection failed");
|
||||||
|
}
|
||||||
|
console.log(
|
||||||
|
"MongoDB connected Successfully on server : " +
|
||||||
|
connectionInstance.connection.host
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("MongoDB connection failed due to some error :", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
module.exports = DB_connect;
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
const jwt = require("jsonwebtoken");
|
||||||
|
const User = require("../Models/user.model.js");
|
||||||
|
const dotenv = require("dotenv");
|
||||||
|
dotenv.config({
|
||||||
|
path: "./.env",
|
||||||
|
});
|
||||||
|
|
||||||
|
async function checkAuthenticated(req, res, next) {
|
||||||
|
const tokenValue = req.cookies[process.env.TOKEN_NAME];
|
||||||
|
|
||||||
|
console.log("I am called", tokenValue);
|
||||||
|
if (!tokenValue) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "User is not logged in.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const payload = await jwt.verify(
|
||||||
|
tokenValue,
|
||||||
|
process.env.REFRESH_TOKEN_SECRET
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!payload) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
req.user = payload;
|
||||||
|
return next();
|
||||||
|
} catch (error) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function authorizeRoles(...roles) {
|
||||||
|
return async (req, res, next) => {
|
||||||
|
if (!roles.includes(req.user.role)) {
|
||||||
|
return res.status(401).json({
|
||||||
|
success: false,
|
||||||
|
message: "You are unauthorised to access this resource",
|
||||||
|
});
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return next();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { checkAuthenticated, authorizeRoles };
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = (theFunc) => (req, res, next) => {
|
||||||
|
Promise.resolve(theFunc(req, res, next)).catch(next);
|
||||||
|
};
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
const multer = require("multer");
|
||||||
|
|
||||||
|
const storage = multer.diskStorage({
|
||||||
|
destination: function (req, file, cb) {
|
||||||
|
cb(null, "./public/images");
|
||||||
|
},
|
||||||
|
|
||||||
|
filename: function (req, file, cb) {
|
||||||
|
const uniquePrefix = Date.now();
|
||||||
|
cb(null, uniquePrefix + "-" + file.originalname);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const upload = multer({ storage: storage });
|
||||||
|
|
||||||
|
module.exports = upload;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
|
const cropSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
name: { type: String, required: true },
|
||||||
|
farm: { type: mongoose.Schema.Types.ObjectId, ref: "Farm", required: true },
|
||||||
|
image: { type: String },
|
||||||
|
plantedDate: { type: Date, required: true, default: Date.now() },
|
||||||
|
harvestDate: { type: Date },
|
||||||
|
growthStage: {
|
||||||
|
type: String,
|
||||||
|
enum: ["Planted", "Growing", "Ready to Harvest"],
|
||||||
|
default: "Planted",
|
||||||
|
},
|
||||||
|
healthStatus: { type: String, default: "Healthy" },
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const Crop = mongoose.model("Crop", cropSchema);
|
||||||
|
|
||||||
|
module.exports = Crop;
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
|
const farmSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
name: { type: String, required: true },
|
||||||
|
location: { type: String, required: true },
|
||||||
|
owner: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: "User",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
size: { type: String },
|
||||||
|
waterContent: { type: String, required: true },
|
||||||
|
soilType: { type: String, required: true },
|
||||||
|
fertilizer: [
|
||||||
|
{
|
||||||
|
name: { type: String },
|
||||||
|
quantity: { type: Number },
|
||||||
|
addedAt: { type: Date, default: Date.now },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
pestisides: [
|
||||||
|
{
|
||||||
|
name: { type: String },
|
||||||
|
quantity: { type: Number },
|
||||||
|
addedAt: { type: Date, default: Date.now },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
crops: [{ type: mongoose.Schema.Types.ObjectId, ref: "Crop" }],
|
||||||
|
finances: { type: mongoose.Schema.Types.ObjectId, ref: "Finance" },
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const Farm = mongoose.model("Farm", farmSchema);
|
||||||
|
|
||||||
|
module.exports = Farm;
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
const financeSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
farm: { type: mongoose.Schema.Types.ObjectId, ref: "Farm", required: true },
|
||||||
|
transactions: [
|
||||||
|
{
|
||||||
|
type: { type: String, enum: ["Expense", "Revenue"], required: true },
|
||||||
|
amount: { type: Number, required: true },
|
||||||
|
description: { type: String },
|
||||||
|
date: { type: Date, default: Date.now },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
totalExpenses: { type: Number, default: 0 },
|
||||||
|
totalRevenue: { type: Number, default: 0 },
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const Finance = mongoose.model("Finance", financeSchema);
|
||||||
|
|
||||||
|
module.exports = Finance;
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
|
const taskSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
farm: { type: mongoose.Schema.Types.ObjectId, ref: "Farm", required: true },
|
||||||
|
crop: { type: mongoose.Schema.Types.ObjectId, ref: "Crop" },
|
||||||
|
taskType: {
|
||||||
|
type: String,
|
||||||
|
enum: [
|
||||||
|
"Sowing",
|
||||||
|
"Watering",
|
||||||
|
"Fertilization",
|
||||||
|
"Pest Control",
|
||||||
|
"Harvesting",
|
||||||
|
],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
description: { type: String },
|
||||||
|
assignedDate: { type: Date, required: true, default: Date.now },
|
||||||
|
status: {
|
||||||
|
type: String,
|
||||||
|
enum: ["Pending", "Completed"],
|
||||||
|
default: "Pending",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const Task = mongoose.model("Task", taskSchema);
|
||||||
|
|
||||||
|
module.exports = Task;
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
const bcrypt = require("bcrypt");
|
||||||
|
const jwt = require("jsonwebtoken");
|
||||||
|
const crypto = require("crypto");
|
||||||
|
|
||||||
|
const userSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: [true, "Please Enter your name"],
|
||||||
|
maxLength: [30, "Please Enter the valid name"],
|
||||||
|
minLength: [2, "Name should have more than 5 characters"],
|
||||||
|
},
|
||||||
|
country: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true,
|
||||||
|
lowerCase: true,
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
minLength: [6, "Password should have more than 6 characters"],
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
type: String,
|
||||||
|
default: "/images/profile.jpeg",
|
||||||
|
},
|
||||||
|
role: { type: String, enum: ["farmer", "admin"], default: "farmer" },
|
||||||
|
farms: [{ type: mongoose.Schema.Types.ObjectId, ref: "Farm" }],
|
||||||
|
|
||||||
|
resetPasswordToken: String,
|
||||||
|
resetPasswordExpiry: Date,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamps: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
userSchema.pre("save", async function (next) {
|
||||||
|
if (!this.isModified("password")) return next();
|
||||||
|
|
||||||
|
this.password = await bcrypt.hash(this.password, 10);
|
||||||
|
return next();
|
||||||
|
});
|
||||||
|
|
||||||
|
userSchema.methods.isPasswordCorrect = async function (password) {
|
||||||
|
return await bcrypt.compare(password, this.password);
|
||||||
|
};
|
||||||
|
|
||||||
|
userSchema.methods.generateRefreshToken = async function () {
|
||||||
|
return await jwt.sign(
|
||||||
|
{
|
||||||
|
_id: this._id,
|
||||||
|
email: this.email,
|
||||||
|
},
|
||||||
|
process.env.REFRESH_TOKEN_SECRET
|
||||||
|
// {
|
||||||
|
// expiresIn: process.env.REFRESH_TOKEN_EXPIRY,
|
||||||
|
// }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
userSchema.methods.getResetPassword = async function () {
|
||||||
|
// Generating token
|
||||||
|
const resetToken = await crypto.randomBytes(20).toString("hex");
|
||||||
|
|
||||||
|
// Hashing and adding reset password token to userschema
|
||||||
|
|
||||||
|
this.resetPasswordToken = crypto
|
||||||
|
.createHash("sha256")
|
||||||
|
.update(resetToken)
|
||||||
|
.digest("hex");
|
||||||
|
|
||||||
|
this.resetPasswordExpiry = Date.now() + 15 * 60 * 1000;
|
||||||
|
|
||||||
|
return resetToken;
|
||||||
|
};
|
||||||
|
|
||||||
|
const User = mongoose.model("User", userSchema);
|
||||||
|
|
||||||
|
module.exports = User;
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const {
|
||||||
|
createCrop,
|
||||||
|
getCropsByFarm,
|
||||||
|
getCropById,
|
||||||
|
updateCrop,
|
||||||
|
deleteCrop,
|
||||||
|
updateHealthStatus,
|
||||||
|
updateGrowthStage,
|
||||||
|
cropHarvest,
|
||||||
|
suggestNextCrop,
|
||||||
|
suggestPesticides,
|
||||||
|
suggestFertilizers,
|
||||||
|
} = require("../Controllers/crop.controller.js");
|
||||||
|
const { checkAuthenticated } = require("../Middlewares/authentication.js");
|
||||||
|
const upload = require("../Middlewares/multer.js");
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// Routes for crop management
|
||||||
|
router.post("/", checkAuthenticated, upload.single("image"), createCrop); // Create a new crop
|
||||||
|
router.get("/farm/:farmId", checkAuthenticated, getCropsByFarm); // Get all crops
|
||||||
|
router.get("/:cropId", checkAuthenticated, getCropById); // Get a crop by ID
|
||||||
|
router.put("/:cropId", checkAuthenticated, updateCrop); // Update crop details
|
||||||
|
router.delete("/:cropId", checkAuthenticated, deleteCrop); // Delete a crop
|
||||||
|
router.put("/health/:cropId", checkAuthenticated, updateHealthStatus);
|
||||||
|
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;
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const {
|
||||||
|
createFarm,
|
||||||
|
getUserFarms,
|
||||||
|
getFarmById,
|
||||||
|
updateFarm,
|
||||||
|
deleteFarm,
|
||||||
|
} = require("../Controllers/farm.controller.js");
|
||||||
|
const { checkAuthenticated } = require("../Middlewares/authentication.js");
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.post("/", checkAuthenticated, createFarm); // Create a new farm
|
||||||
|
router.get("/", checkAuthenticated, getUserFarms); // Get all farms
|
||||||
|
router.get("/:farmId", checkAuthenticated, getFarmById); // Get a farm by ID
|
||||||
|
router.put("/:farmId", checkAuthenticated, updateFarm); // Update a farm
|
||||||
|
router.delete("/:farmId", checkAuthenticated, deleteFarm); // Delete a farm
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const {
|
||||||
|
addTransaction,
|
||||||
|
createFinance,
|
||||||
|
getFinanceByFarm,
|
||||||
|
deleteTransaction,
|
||||||
|
getTransactions,
|
||||||
|
getFinancialSummary,
|
||||||
|
} = require("../Controllers/finance.controller.js");
|
||||||
|
const { checkAuthenticated } = require("../Middlewares/authentication.js");
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// Routes for finance management
|
||||||
|
router.post("/", checkAuthenticated, createFinance); // Create a new finance record
|
||||||
|
router.get("/:farmId", checkAuthenticated, getFinanceByFarm); // Get all finance records
|
||||||
|
router.get("/transactions/:financeId", checkAuthenticated, getTransactions); // Get a finance record by ID
|
||||||
|
router.get("/summary/:financeId", checkAuthenticated, getFinancialSummary); //
|
||||||
|
router.delete("/:financeId", checkAuthenticated, deleteTransaction); // Delete a finance record
|
||||||
|
|
||||||
|
// Add transactions (Expense/Revenue) to a finance record
|
||||||
|
router.post("/:financeId/transaction", checkAuthenticated, addTransaction);
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
const { checkAuthenticated } = require("../Middlewares/authentication.js");
|
||||||
|
|
||||||
|
const express = require("express");
|
||||||
|
const {
|
||||||
|
createTask,
|
||||||
|
getTasksByFarm,
|
||||||
|
getTaskById,
|
||||||
|
updateTask,
|
||||||
|
deleteTask,
|
||||||
|
updateTaskStatus,
|
||||||
|
} = require("../Controllers/task.controller.js");
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// Routes for task management
|
||||||
|
router.post("/", checkAuthenticated, createTask); // Create a new task
|
||||||
|
router.get("/farm/:farmId", checkAuthenticated, getTasksByFarm); // Get all tasks for a specific farm
|
||||||
|
router.get("/:taskId", checkAuthenticated, getTaskById); // Get a task by ID
|
||||||
|
router.put("/:taskId", checkAuthenticated, updateTask); // Update task details
|
||||||
|
router.delete("/:taskId", checkAuthenticated, deleteTask); // Delete a task
|
||||||
|
|
||||||
|
// Update task status (Pending → Completed)
|
||||||
|
router.patch("/:taskId/status", checkAuthenticated, updateTaskStatus);
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const {
|
||||||
|
registerUser,
|
||||||
|
loginUser,
|
||||||
|
logoutUser,
|
||||||
|
updateUserDetails,
|
||||||
|
forgetPassword,
|
||||||
|
resetPassword,
|
||||||
|
getUserDetails,
|
||||||
|
updatePassword,
|
||||||
|
updatePersonalDetails,
|
||||||
|
DeleteUser,
|
||||||
|
updateUserRole,
|
||||||
|
intializeUser,
|
||||||
|
updateAvatar,
|
||||||
|
} = require("../Controllers/user.controller.js");
|
||||||
|
|
||||||
|
const { checkAuthenticated } = require("../Middlewares/authentication.js");
|
||||||
|
|
||||||
|
const upload = require("../Middlewares/multer.js");
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.route("/register").post(registerUser);
|
||||||
|
|
||||||
|
router.route("/login").post(loginUser);
|
||||||
|
|
||||||
|
router.route("/password/forgot").post(forgetPassword);
|
||||||
|
|
||||||
|
router.route("/password/reset/:token").put(resetPassword);
|
||||||
|
|
||||||
|
router.route("/logout").get(logoutUser);
|
||||||
|
|
||||||
|
router.route("/update/:id").put(updateUserDetails);
|
||||||
|
|
||||||
|
router.route("/me").get(checkAuthenticated, getUserDetails);
|
||||||
|
|
||||||
|
router.route("/getuser").get(intializeUser);
|
||||||
|
|
||||||
|
router.route("/password/update").put(updatePassword);
|
||||||
|
|
||||||
|
router.route("/me/update").put(updatePersonalDetails);
|
||||||
|
|
||||||
|
router.route("/user/delete/:id").delete(DeleteUser);
|
||||||
|
|
||||||
|
router.route("/user/updateRole/:id").put(updateUserRole);
|
||||||
|
|
||||||
|
router
|
||||||
|
.route("/user/avatar")
|
||||||
|
.put(checkAuthenticated, upload.single("avatar"), updateAvatar);
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
const cloudinary = require("cloudinary").v2;
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
const uploadOnCloudinary = async (localFilePath) => {
|
||||||
|
try {
|
||||||
|
if (!localFilePath) return null;
|
||||||
|
|
||||||
|
const responce = await cloudinary.uploader.upload(localFilePath, {
|
||||||
|
resource_type: "auto",
|
||||||
|
});
|
||||||
|
|
||||||
|
// console.log("File is uploaded successfully");
|
||||||
|
fs.unlinkSync(localFilePath, () => {
|
||||||
|
console.log("file removed successfully");
|
||||||
|
});
|
||||||
|
return responce.url;
|
||||||
|
} catch (error) {
|
||||||
|
fs.unlinkSync(localFilePath);
|
||||||
|
console.log("file removed successfully");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
module.exports = { uploadOnCloudinary };
|
||||||
@@ -0,0 +1,456 @@
|
|||||||
|
// const {
|
||||||
|
// GoogleGenerativeAI,
|
||||||
|
// HarmCategory,
|
||||||
|
// HarmBlockThreshold,
|
||||||
|
// } = require("@google/generative-ai");
|
||||||
|
// const {
|
||||||
|
// GoogleGenerativeAI,
|
||||||
|
// HarmCategory,
|
||||||
|
// HarmBlockThreshold,
|
||||||
|
// } = require("@google/generative-ai");
|
||||||
|
// const dotenv = require("dotenv");
|
||||||
|
|
||||||
|
// dotenv.config({
|
||||||
|
// path: "./.env",
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const apiKey = process.env.GEMINI_API_KEY;
|
||||||
|
// 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",
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export async function run(message) {
|
||||||
|
// const chatSession = model.startChat({
|
||||||
|
// generationConfig,
|
||||||
|
// history: [
|
||||||
|
// {
|
||||||
|
// role: "user",
|
||||||
|
// parts: [
|
||||||
|
// {
|
||||||
|
// text: "AI Model Guidelines:\n\nContext Restriction: Only provide answers based on the content available on [Your Website Name]. Do not generate responses unrelated to the website's information.\nNo External Knowledge: If a user asks about a topic outside the website’s scope, politely inform them that you can only assist with website-related queries.\nSafe & Ethical Responses: Do not answer harmful, illegal, controversial, or inappropriate questions. If such a query is detected, respond with a neutral message stating that the request cannot be fulfilled.\nAccuracy & Clarity: Ensure responses are factual, clear, and helpful, directly referencing available website data without assumptions or speculation.\n\nGreeting should be similar lto this :\nHello! 👋\nI’m here to assist you with information available on [Your Website Name]. Here’s what I can do:\n\n✅ Answer questions based on the content from this website.\n✅ Guide you through available services, features, and resources.\n✅ Help you navigate and find what you need.\n\nuse emoji when you feel like it makes sense and increases the user understanding",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// role: "model",
|
||||||
|
// parts: [
|
||||||
|
// {
|
||||||
|
// text: "Hello! 👋\n\nI’m here to assist you with information available on [Your Website Name]. Here’s what I can do:\n\n✅ Answer questions based on the content from this website.\n✅ Guide you through available services, features, and resources.\n✅ Help you navigate and find what you need.\n\nHow can I help you today? 😃\n",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// role: "user",
|
||||||
|
// parts: [{ text: "forget everythings until now " }],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// role: "model",
|
||||||
|
// parts: [
|
||||||
|
// {
|
||||||
|
// text: "Understood. I am now reset and ready to assist you with information available on [Your Website Name], adhering to the guidelines. How can I help you?\n",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// role: "user",
|
||||||
|
// parts: [
|
||||||
|
// {
|
||||||
|
// text: "you will get some json or js object which will be some questions related to farming, you have to answer those questions and give proper description which is neccessary for a farmer to have if you recommend some kind of poisonous pestiside or something give a small warning and some things to keep some precausetions, dont answer anything unrelated to farming and strictly avoid harmful topics like war or viiolence, if farmer wants to kill pestisides then thats ok but anything else is not \n ",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// role: "model",
|
||||||
|
// parts: [
|
||||||
|
// {
|
||||||
|
// text: "Understood. I will answer questions related to farming based on the content available on [Your Website Name]. I will provide detailed descriptions where necessary, including precautions when recommending potentially harmful pesticides. I will strictly avoid topics unrelated to farming or any harmful subjects. Please provide the JSON or JS object containing the questions. I'm ready! 🚜\n",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// role: "user",
|
||||||
|
// parts: [
|
||||||
|
// {
|
||||||
|
// text: "keep the warning and precuastions short, and you are not a chatbot you are a data processing unit who will have the data and analyze it and answer accordingly\n ",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// role: "model",
|
||||||
|
// parts: [
|
||||||
|
// {
|
||||||
|
// text: "Understood. I will function as a data processing unit, analyzing the provided data related to farming and answering questions with concise warnings and precautions where applicable. I will not engage in conversational chatbot behavior. Please provide the data. I'm ready to process! 👩🌾\n",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const result = await chatSession.sendMessage(message);
|
||||||
|
// 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: "you will get some json or js object which will be some questions related to farming, you have to answer those questions and give proper description which is neccessary for a farmer to have if you recommend some kind of poisonous pestiside or something give a small warning and some things to keep some precausetions, dont answer anything unrelated to farming and strictly avoid harmful topics like war or viiolence, if farmer wants to kill pestisides then thats ok but anything else is not \n ",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// role: "model",
|
||||||
|
// parts: [
|
||||||
|
// {
|
||||||
|
// text: "Understood. I will answer questions related to farming based on the content available on [Your Website Name]. I will provide detailed descriptions where necessary, including precautions when recommending potentially harmful pesticides. I will strictly avoid topics unrelated to farming or any harmful subjects. Please provide the JSON or JS object containing the questions. I'm ready! 🚜\n",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// role: "user",
|
||||||
|
// parts: [
|
||||||
|
// {
|
||||||
|
// text: "keep the warning and precuastions short, and you are not a chatbot you are a data processing unit who will have the data and analyze it and answer accordingly\n ",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// role: "model",
|
||||||
|
// parts: [
|
||||||
|
// {
|
||||||
|
// text: "Understood. I will function as a data processing unit, analyzing the provided data related to farming and answering questions with concise warnings and precautions where applicable. I will not engage in conversational chatbot behavior. Please provide the data. I'm ready to process! 👩🌾\n",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
// const result = await chatSession.sendMessage(message);
|
||||||
|
// console.log(result.response.text());
|
||||||
|
// }
|
||||||
|
// run("How we check the farmes soil type ? ");
|
||||||
|
|
||||||
|
// 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",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const result = await chatSession.sendMessage(message);
|
||||||
|
// 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() {
|
||||||
|
// 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",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const result = await chatSession.sendMessage("INSERT_INPUT_HERE");
|
||||||
|
// 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 {
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
console.log(result.response.text());
|
||||||
|
return result.response.text();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { run };
|
||||||
|
|
||||||
|
// run("Sowing start and harvesting end which crop ?");
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
const nodemailer = require("nodemailer");
|
||||||
|
|
||||||
|
const sendEmail = async (options) => {
|
||||||
|
const transporter = await nodemailer.createTransport({
|
||||||
|
service: "gmail",
|
||||||
|
host: process.env.HOST,
|
||||||
|
port: process.env.EMAIL_PORT,
|
||||||
|
secure: false,
|
||||||
|
auth: {
|
||||||
|
user: process.env.SMPT_MAIL, // senders email
|
||||||
|
pass: process.env.SMPT_PASSWORD, // app passoword created for your app by using step :: google account> manage your google account >security>enable two step verification > search app password and create password for your app
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const mailOptions = {
|
||||||
|
from: "",
|
||||||
|
to: options.email,
|
||||||
|
subject: options.subject,
|
||||||
|
text: options.message,
|
||||||
|
};
|
||||||
|
|
||||||
|
await transporter.sendMail(mailOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = sendEmail;
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const cors = require("cors");
|
||||||
|
const cookieParser = require("cookie-parser");
|
||||||
|
|
||||||
|
const userRoute = require("./Routes/user.routes.js");
|
||||||
|
const farmRoute = require("./Routes/farm.routes.js");
|
||||||
|
const cropRoute = require("./Routes/crop.routes.js");
|
||||||
|
const financeRoute = require("./Routes/finance.routes.js");
|
||||||
|
const taskRoute = require("./Routes/task.routes.js");
|
||||||
|
const { checkAuthenticated } = require("./Middlewares/authentication.js");
|
||||||
|
const dotenv = require("dotenv");
|
||||||
|
const { run } = require("./Utils/model.js");
|
||||||
|
|
||||||
|
dotenv.config({
|
||||||
|
path: "./.env",
|
||||||
|
});
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
const corsOptions = {
|
||||||
|
origin: process.env.FRONTEND_URI,
|
||||||
|
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
|
||||||
|
credentials: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
app.use(cors(corsOptions));
|
||||||
|
app.use(express.json({ limit: "16kb" }));
|
||||||
|
app.use(express.urlencoded({ extended: true, limit: "16kb" }));
|
||||||
|
app.use(express.static("public"));
|
||||||
|
app.use(cookieParser());
|
||||||
|
|
||||||
|
app.get("/", (req, res) => {
|
||||||
|
return res.send("Hiddskpkpk...");
|
||||||
|
});
|
||||||
|
|
||||||
|
app.use("/api/v1", userRoute);
|
||||||
|
|
||||||
|
app.use("/api/v1/farm", farmRoute);
|
||||||
|
|
||||||
|
app.use("/api/v1/crop", cropRoute);
|
||||||
|
|
||||||
|
app.use("/api/v1/finance", financeRoute);
|
||||||
|
|
||||||
|
app.use("/api/v1/task", taskRoute);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = app;
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
const server = require("./app.js");
|
||||||
|
const dotenv = require("dotenv");
|
||||||
|
const cloudinary = require("cloudinary").v2;
|
||||||
|
const DB_connect = require("./Database/DB_connect.js");
|
||||||
|
const app = require("./app.js");
|
||||||
|
|
||||||
|
// dotenv Configuration
|
||||||
|
dotenv.config({
|
||||||
|
path: "./.env",
|
||||||
|
});
|
||||||
|
|
||||||
|
cloudinary.config({
|
||||||
|
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
|
||||||
|
api_key: process.env.CLOUDINARY_API_KEY,
|
||||||
|
api_secret: process.env.CLOUDINARY_API_SECRET,
|
||||||
|
});
|
||||||
|
|
||||||
|
DB_connect();
|
||||||
|
|
||||||
|
// Listening the port
|
||||||
|
app.listen(process.env.PORT, () => {
|
||||||
|
console.log("Server is Running on ", process.env.PORT);
|
||||||
|
console.log("Frontend URI : ", process.env.FRONTEND_URI);
|
||||||
|
});
|
||||||
Generated
+4823
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "backend",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"dev": "nodemon index.js"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": {
|
||||||
|
"@google/generative-ai": "^0.22.0",
|
||||||
|
"@huggingface/transformers": "^3.3.3",
|
||||||
|
"@xenova/transformers": "^2.17.2",
|
||||||
|
"bcrypt": "^5.1.1",
|
||||||
|
"cloudinary": "^2.5.1",
|
||||||
|
"cookie-parser": "^1.4.6",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"express": "^4.19.2",
|
||||||
|
"jimp": "^1.6.0",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"mongoose": "^8.6.1",
|
||||||
|
"multer": "^1.4.5-lts.1",
|
||||||
|
"nodemailer": "^6.9.15",
|
||||||
|
"socket.io": "^4.7.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"nodemon": "^3.1.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { pipeline } from "@xenova/transformers";
|
||||||
|
import Jimp from "jimp";
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const modelName = "Xenova/distilbert-base-uncased-finetuned-sst-2-english"; // Example model
|
||||||
|
|
||||||
|
// Load the model
|
||||||
|
const classifier = await pipeline("image-classification", modelName);
|
||||||
|
|
||||||
|
// Load the image
|
||||||
|
let image;
|
||||||
|
try {
|
||||||
|
image = await Jimp.read("/home/karan/Downloads/tomato.png");
|
||||||
|
image.rgba(true);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error: Unable to open image. Check the file type or path.");
|
||||||
|
console.error(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert image to buffer
|
||||||
|
const buffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
||||||
|
|
||||||
|
// Classify the image
|
||||||
|
const result = await classifier(buffer);
|
||||||
|
|
||||||
|
console.log("Predicted class:", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(console.error);
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
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
@@ -1,142 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"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
@@ -1,45 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"sources": [],
|
|
||||||
"sourcesContent": [],
|
|
||||||
"mappings": "",
|
|
||||||
"names": []
|
|
||||||
}
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"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
@@ -1,172 +0,0 @@
|
|||||||
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
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "module"
|
|
||||||
}
|
|
||||||
-10786
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-190
@@ -1,190 +0,0 @@
|
|||||||
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
@@ -1,39 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"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": []
|
|
||||||
}
|
|
||||||
-10874
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
-6454
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-8202
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-2794
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
-5338
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-17374
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
-12090
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
-293
@@ -1,293 +0,0 @@
|
|||||||
"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
Vendored
-1119
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
-6035
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
-2067
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Vendored
-6
@@ -1,6 +0,0 @@
|
|||||||
import {
|
|
||||||
require_react
|
|
||||||
} from "./chunk-W4EHDCLL.js";
|
|
||||||
import "./chunk-EWTE5DHJ.js";
|
|
||||||
export default require_react();
|
|
||||||
//# sourceMappingURL=react.js.map
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"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.
|
Before Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 581 B |
@@ -37,8 +37,7 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="w-full h-auto flex-col relative">
|
<div className="w-full h-auto flex-col relative">
|
||||||
|
<div className="pt-20"></div>
|
||||||
|
|
||||||
<Outlet />
|
<Outlet />
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from "react";
|
|||||||
const Container = ({ children }) => {
|
const Container = ({ children }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="w-full max-h-screen">{children}</div>
|
<div className="w-full h-auto">{children}</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,29 +1,24 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Td from "./Td";
|
import Td from "./Td";
|
||||||
import Loader from "./Loader";
|
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(() => {
|
||||||
const { data: farms, error, isLoading } = useGetFarmsQuery();
|
fetch("http://localhost:8000/api/v1/farm", {
|
||||||
|
credentials: "include",
|
||||||
console.log(farms);
|
method: "GET",
|
||||||
// useEffect(() => {
|
headers: { "Content-Type": "application/json" },
|
||||||
// fetch("http://localhost:8000/api/v1/farm", {
|
})
|
||||||
// credentials: "include",
|
.then((response) => response.json())
|
||||||
// method: "GET",
|
.then((data) => setData(data))
|
||||||
// headers: { "Content-Type": "application/json" },
|
.then(setLoading(false))
|
||||||
// })
|
.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">
|
||||||
{isLoading ? (
|
{loading ? (
|
||||||
<Loader></Loader>
|
<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">
|
||||||
@@ -47,8 +42,8 @@ const FarmList = () => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{farms && farms.length > 0 ? (
|
{data.length > 0 ? (
|
||||||
farms.map((item) => <Td key={item.id} children={item} />)
|
data.map((item) => <Td key={item.id} children={item} />)
|
||||||
) : (
|
) : (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={5} className="text-center">
|
<td colSpan={5} className="text-center">
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
@@ -1,38 +1,24 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { 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 (
|
||||||
useEffect(() => {
|
<div className=" flex justify-center rounded-full">
|
||||||
if (user.name !== "Unloggedin User") {
|
<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">
|
||||||
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 src="/images/logo.png" className="size-10" alt="Logo" />
|
<img
|
||||||
|
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>
|
||||||
@@ -40,17 +26,18 @@ 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"}>Get Started</Link>
|
<Link to={"/user/dashboard/addfarm"}>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"
|
||||||
>
|
>
|
||||||
@@ -89,11 +76,12 @@ const Navbar2 = () => {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div> */}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Navbar2;
|
export default Navbar2;
|
||||||
|
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,4 @@
|
|||||||
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
|
||||||
@@ -30,7 +6,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">
|
||||||
{totalSpend && totalSpend} ₹
|
₹10,000
|
||||||
</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, { useEffect, useState } from "react";
|
import React from "react";
|
||||||
import { Line } from "react-chartjs-2";
|
import { Line } from "react-chartjs-2";
|
||||||
import {
|
import {
|
||||||
Chart as ChartJS,
|
Chart as ChartJS,
|
||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
Legend,
|
Legend,
|
||||||
} from "chart.js";
|
} from "chart.js";
|
||||||
import { useGetFarmsQuery } from "../../store/api/farmApi";
|
|
||||||
|
|
||||||
ChartJS.register(
|
ChartJS.register(
|
||||||
CategoryScale,
|
CategoryScale,
|
||||||
@@ -23,35 +22,7 @@ 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",
|
||||||
@@ -69,8 +40,8 @@ const PerformanceChart = () => {
|
|||||||
],
|
],
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: "Expences",
|
label: "Yield",
|
||||||
data: spentList, // slightly improved values
|
data: [75, 68, 85, 88, 60, 62, 78, 90, 95, 92, 88, 80], // 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)",
|
||||||
@@ -82,7 +53,7 @@ const PerformanceChart = () => {
|
|||||||
responsive: true,
|
responsive: true,
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: { position: "top" },
|
legend: { position: "top" },
|
||||||
title: { display: true, text: "Expences Tracking " },
|
title: { display: true, text: "Performance Trend" },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
// 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;
|
|
||||||
@@ -27,7 +27,6 @@ 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 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}>
|
||||||
@@ -62,7 +61,6 @@ 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>
|
||||||
|
|||||||
@@ -1,47 +1,18 @@
|
|||||||
import React, { useState } from "react";
|
import React 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">
|
||||||
One stop solution for every farmer's need.
|
Anything and Everything you Need to know About
|
||||||
</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
|
||||||
@@ -57,7 +28,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"
|
||||||
@@ -128,7 +99,10 @@ 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 target="_blank">
|
<a
|
||||||
|
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
|
||||||
|
|||||||
@@ -18,16 +18,171 @@ 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 & 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">
|
||||||
© 2025{" "}
|
© 2024{" "}
|
||||||
<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>
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
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 {
|
import { CardOnlyText, CardWithButton, CardWithImage, CardWithOnlyImage, HeroSecn, } from "./Cards";
|
||||||
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 });
|
||||||
@@ -34,64 +26,33 @@ 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>
|
||||||
<Navbar2 />
|
<ScrollReveal direction='up'>
|
||||||
<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 gap-10 justify-between ">
|
<div className=" flex flex-col justify-between">
|
||||||
<ScrollReveal direction="up">
|
<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>
|
||||||
<CardOnlyText
|
</div>
|
||||||
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
|
||||||
@@ -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>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -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 min-h-[20]">
|
<div className="container mx-auto ">
|
||||||
<div className="text-center flex-col justify-center align-middle min-h-full">
|
<div className="text-center flex-col justify-center align-middle ">
|
||||||
<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,29 +50,33 @@ const Testimonial = () => {
|
|||||||
scrollArea={myRef}
|
scrollArea={myRef}
|
||||||
startDelay={100}
|
startDelay={100}
|
||||||
cursorColor="white"
|
cursorColor="white"
|
||||||
text="⠀Unparalled management for crops & farms."
|
text="Record breaking features like never before!"
|
||||||
typeSpeed={100}
|
typeSpeed={100}
|
||||||
/>
|
/>
|
||||||
</h1>
|
</h1>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col sm:flex-row justify-around mt-8 h-auto min-h-[50]">
|
<div className="flex flex-col sm:flex-row justify-around mt-8 h-auto">
|
||||||
<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">
|
||||||
<img
|
<svg
|
||||||
src="/images/dashboard.png"
|
className="w-7 h-7 text-gray-200 dark:text-gray-400 mb-3"
|
||||||
alt="dashboard"
|
aria-hidden="true"
|
||||||
className="w-7 h-7"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
></img>
|
fill="currentColor"
|
||||||
<a href="/user/dashboard/">
|
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">
|
||||||
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="#"
|
||||||
@@ -99,8 +103,16 @@ 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 pb-13">
|
<div className="max-w-sm p-6 backdrop-blur-md rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700">
|
||||||
<img src="/images/crops.png" className="w-7 h-7" alt="" />
|
<svg
|
||||||
|
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">
|
||||||
{" "}
|
{" "}
|
||||||
@@ -109,10 +121,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="/ai"
|
href="#"
|
||||||
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
|
||||||
@@ -137,8 +149,16 @@ 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">
|
||||||
<img src="/images/planner.png" className="w-7 h-7" alt="" />
|
<svg
|
||||||
<a href="/user/dashboard/monitoring">
|
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="#">
|
||||||
<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>
|
||||||
@@ -146,7 +166,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="#"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user