feat: Set up RTK query for the statemanagement
This commit is contained in:
@@ -41,13 +41,7 @@ export const HeroSecn = () => {
|
||||
<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"
|
||||
>
|
||||
{isLoggedIn ? (
|
||||
<Link to={"/user/dashboard"}>Start Managing Your Farm</Link>
|
||||
) : (
|
||||
<Link to={"/user/login"}>Log In</Link>
|
||||
)}
|
||||
</button>
|
||||
></button>
|
||||
</div>
|
||||
<div className="w-full md:w-4/5 object-contain flex justify-center items-center">
|
||||
<img
|
||||
|
||||
@@ -112,7 +112,7 @@ const Testimonial = () => {
|
||||
symptoms.
|
||||
</p>
|
||||
<a
|
||||
href="/predict"
|
||||
href="/ai"
|
||||
className="inline-flex font-medium items-center text-blue-600 hover:underline"
|
||||
>
|
||||
Check Out
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { useCreateCropMutation } from "../../../store/api/cropApi";
|
||||
|
||||
const AddCrop = ({ farmId }) => {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
@@ -12,6 +13,7 @@ const AddCrop = ({ farmId }) => {
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const [error, setError] = useState("");
|
||||
const [success, setSuccess] = useState("");
|
||||
const [createCrop] = useCreateCropMutation();
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
@@ -30,14 +32,17 @@ const AddCrop = ({ farmId }) => {
|
||||
}
|
||||
console.log(formData);
|
||||
try {
|
||||
const response = await fetch(`http://localhost:8000/api/v1/crop`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
body: formData,
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to create crop");
|
||||
}
|
||||
const response = await createCrop(formData);
|
||||
// const response = await fetch(`http://localhost:8000/api/v1/crop`, {
|
||||
// method: "POST",
|
||||
// credentials: "include",
|
||||
// body: formData,
|
||||
// });
|
||||
// if (!response.ok) {
|
||||
// throw new Error("Failed to create crop");
|
||||
// }
|
||||
|
||||
console.log(response);
|
||||
setSuccess("Crop created successfully!");
|
||||
// Reset form fields
|
||||
setName("");
|
||||
@@ -46,6 +51,7 @@ const AddCrop = ({ farmId }) => {
|
||||
setGrowthStage("");
|
||||
setHealthStatus("");
|
||||
setImage(null);
|
||||
setIsModalOpen(false);
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useCreateFarmMutation } from "../../../store/api/farmApi";
|
||||
|
||||
const AddFarm = () => {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
@@ -11,6 +12,8 @@ const AddFarm = () => {
|
||||
const [error, setError] = useState(null);
|
||||
const [success, setSuccess] = useState(false);
|
||||
const navigator = useNavigate();
|
||||
|
||||
const [createFarm] = useCreateFarmMutation();
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
const farmData = {
|
||||
@@ -24,27 +27,16 @@ const AddFarm = () => {
|
||||
console.log(farmData);
|
||||
|
||||
try {
|
||||
const response = await fetch("http://localhost:8000/api/v1/farm", {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(farmData),
|
||||
});
|
||||
const res = await createFarm(farmData);
|
||||
console.log(res);
|
||||
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to add farm");
|
||||
if (res.error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
navigator("farmpage");
|
||||
setSuccess(true);
|
||||
setError(null);
|
||||
setIsModalOpen(false);
|
||||
window.location.reload();
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
setSuccess(false);
|
||||
|
||||
@@ -1,42 +1,52 @@
|
||||
import React, { useState } from "react";
|
||||
import Loader from "../../../components/Loader";
|
||||
import { useAddTransactionMutation } from "../../../store/api/financeApi";
|
||||
|
||||
const AddTransaction = ({ farmId }) => {
|
||||
const AddTransaction = ({ farmId, financeId }) => {
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [type, setType] = useState("Expense");
|
||||
const [amount, setAmount] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [message, setMessage] = useState("");
|
||||
const [addTransaction] = useAddTransactionMutation();
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
setMessage("");
|
||||
|
||||
const transactionData = {
|
||||
type,
|
||||
amount: parseFloat(amount),
|
||||
description,
|
||||
};
|
||||
console.log("Transaction data:", transactionData);
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`http://localhost:8000/api/v1/finance/${farmId}/transaction`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
type,
|
||||
amount: parseFloat(amount),
|
||||
description,
|
||||
}),
|
||||
}
|
||||
);
|
||||
const response = await addTransaction({ financeId, transactionData });
|
||||
// const response = await fetch(
|
||||
// `http://localhost:8000/api/v1/finance/${farmId}/transaction`,
|
||||
// {
|
||||
// method: "POST",
|
||||
// credentials: "include",
|
||||
// headers: {
|
||||
// "Content-Type": "application/json",
|
||||
// },
|
||||
// body: JSON.stringify({
|
||||
// type,
|
||||
// amount: parseFloat(amount),
|
||||
// description,
|
||||
// }),
|
||||
// }
|
||||
// );
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to create transaction");
|
||||
}
|
||||
// if (!response.ok) {
|
||||
// throw new Error("Failed to create transaction");
|
||||
// }
|
||||
|
||||
const data = await response.json();
|
||||
console.log("Transaction created:", data);
|
||||
// const data = await response.json();
|
||||
console.log("Transaction created:", response);
|
||||
setMessage("Transaction created successfully!");
|
||||
// Optionally clear the form
|
||||
setType("Expense");
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
import React, { useState } from "react";
|
||||
import Loader from "../../../components/Loader";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useCreateFinanceMutation } from "../../../store/api/financeApi";
|
||||
|
||||
const CreateFinance = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [message, setMessage] = useState("");
|
||||
// Hardcoded farm ID from your example
|
||||
const farmId = "67b9e6829c4979463e64a0fc";
|
||||
const { farmId } = useParams();
|
||||
const [createFinance] = useCreateFinanceMutation();
|
||||
|
||||
const handleCreateFinance = async () => {
|
||||
setLoading(true);
|
||||
setMessage("");
|
||||
try {
|
||||
const response = await fetch("http://localhost:8000/api/v1/finance", {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ farm: farmId }),
|
||||
});
|
||||
const responce = await createFinance({ farm: farmId });
|
||||
// const response = await fetch("http://localhost:8000/api/v1/finance", {
|
||||
// method: "POST",
|
||||
// credentials: "include",
|
||||
// headers: {
|
||||
// "Content-Type": "application/json",
|
||||
// },
|
||||
// body: JSON.stringify({ farm: farmId }),
|
||||
// });
|
||||
|
||||
console.log("Trance opdien ", responce);
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to create finance");
|
||||
}
|
||||
@@ -39,7 +45,7 @@ const CreateFinance = () => {
|
||||
disabled={loading}
|
||||
className="mt-4 w-30 inline-flex items-center justify-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
>
|
||||
{loading ? <Loader></Loader> : "Create Finance"}
|
||||
Create Finance
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import Loader from "../../../components/Loader";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useGetCropsByFarmQuery } from "../../../store/api/cropApi";
|
||||
|
||||
const CropTable = ({ farmId }) => {
|
||||
const [crops, setCrops] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const {
|
||||
data: cropsData,
|
||||
error: cropsError,
|
||||
isLoading: cropsLoading,
|
||||
} = useGetCropsByFarmQuery(farmId);
|
||||
|
||||
console.log("Crops data is :", cropsData);
|
||||
const handleRemoveCrop = async (cropId) => {
|
||||
try {
|
||||
await fetch(`http://localhost:8000/api/v1/crop/${cropId}`, {
|
||||
@@ -19,34 +29,13 @@ const CropTable = ({ farmId }) => {
|
||||
setError(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const fetchCrops = async () => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`http://localhost:8000/api/v1/crop/farm/${farmId}`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch crops");
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
setCrops(data || []);
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchCrops();
|
||||
}, []);
|
||||
if (cropsData) {
|
||||
setCrops(cropsData);
|
||||
setLoading(false);
|
||||
}
|
||||
}, [cropsData]);
|
||||
|
||||
if (loading) {
|
||||
return <Loader></Loader>;
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
import React, { useState } from "react";
|
||||
import { useDeleteFarmMutation } from "../../../store/api/farmApi";
|
||||
|
||||
const EditFarm = ({ _id, onDelete }) => {
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [deleteFarm] = useDeleteFarmMutation();
|
||||
|
||||
// This function will run when the "Yes, I'm sure" button is clicked.
|
||||
const handleDeleteFarm = async () => {
|
||||
try {
|
||||
const response = await fetch(`http://localhost:8000/api/v1/farm/${_id}`, {
|
||||
method: "DELETE",
|
||||
credentials: "include",
|
||||
});
|
||||
const data = await response.json();
|
||||
console.log("Delete response:", data);
|
||||
if (data.success) {
|
||||
// Notify the parent component to update its state
|
||||
if (onDelete) onDelete(_id);
|
||||
const res = await deleteFarm(_id);
|
||||
// const response = await fetch(`http://localhost:8000/api/v1/farm/${_id}`, {
|
||||
// method: "DELETE",
|
||||
// credentials: "include",
|
||||
// });
|
||||
// const data = await response.json();
|
||||
console.log("Delete response:", res);
|
||||
|
||||
if (!res) {
|
||||
return null;
|
||||
}
|
||||
|
||||
setModalOpen(false); // Close the modal after the operation
|
||||
window.location.reload();
|
||||
} catch (error) {
|
||||
console.error("Error deleting farm:", error);
|
||||
}
|
||||
|
||||
@@ -9,49 +9,63 @@ import AddTransaction from "./AddTransactions";
|
||||
import FinanceSummary from "./FinanceSummary";
|
||||
import CreateTask from "./CreateTask";
|
||||
import DisplayTast from "./DisplayTask";
|
||||
import { useGetFarmByIdQuery } from "../../../store/api/farmApi";
|
||||
|
||||
export default function FarmPage() {
|
||||
const { farmId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [farmData, setFarmData] = useState(null);
|
||||
const [farmData, setFarmData] = useState("");
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
console.log("Farm id is : ", farmId);
|
||||
|
||||
const { data: farm, error, isLoading } = useGetFarmByIdQuery(farmId);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchFarmData() {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`http://localhost:8000/api/v1/farm/${farmId}`,
|
||||
{
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
const jsonData = await response.json();
|
||||
console.log("Fetched farm data:", jsonData);
|
||||
setFarmData(jsonData);
|
||||
} catch (error) {
|
||||
console.error("Error fetching farm data: ", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
if (!isLoading && !error && farm) {
|
||||
setFarmData(farm);
|
||||
setLoading(false);
|
||||
}
|
||||
fetchFarmData();
|
||||
}, [farmId]);
|
||||
}, [farm]);
|
||||
|
||||
if (loading) {
|
||||
return <Loader />;
|
||||
}
|
||||
console.log("djoejwrru9", farmData);
|
||||
|
||||
if (!farmData) {
|
||||
return (
|
||||
<div className="w-full bg-white rounded-lg shadow p-4">
|
||||
<p>No farm data found.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// useEffect(() => {
|
||||
// async function fetchFarmData() {
|
||||
// try {
|
||||
// const response = await fetch(
|
||||
// `http://localhost:8000/api/v1/farm/${farmId}`,
|
||||
// {
|
||||
// method: "GET",
|
||||
// credentials: "include",
|
||||
// headers: {
|
||||
// "Content-Type": "application/json",
|
||||
// },
|
||||
// }
|
||||
// );
|
||||
// const jsonData = await response.json();
|
||||
// console.log("Fetched farm data:", jsonData);
|
||||
// setFarmData(jsonData);
|
||||
// } catch (error) {
|
||||
// console.error("Error fetching farm data: ", error);
|
||||
// } finally {
|
||||
// setLoading(false);
|
||||
// }
|
||||
// }
|
||||
// fetchFarmData();
|
||||
// }, [farmId]);
|
||||
|
||||
// if (loading) {
|
||||
// return <Loader />;
|
||||
// }
|
||||
|
||||
// if (!farmData) {
|
||||
// return (
|
||||
// <div className="w-full bg-white rounded-lg shadow p-4">
|
||||
// <p>No farm data found.</p>
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
return (
|
||||
<div className="w-full bg-white rounded-lg shadow p-4 space-y-8">
|
||||
@@ -82,14 +96,14 @@ export default function FarmPage() {
|
||||
{/* Add Transaction Modal Section */}
|
||||
<section>
|
||||
<div className="flex justify-end">
|
||||
<AddTransaction farmId={farmId} />
|
||||
<AddTransaction farmId={farmId} financeId={farmData?.finances?._id} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Finance Summary Section */}
|
||||
<section>
|
||||
<div className="flex justify-end">
|
||||
<FinanceSummary farmId={farmId} />
|
||||
<FinanceSummary farmId={farmId} financeId={farmData?.finances?._id} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import Loader from "../../../components/Loader";
|
||||
|
||||
const FinanceSummary = ({ farmId }) => {
|
||||
const FinanceSummary = ({ farmId, financeId }) => {
|
||||
const [summary, setSummary] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState("");
|
||||
@@ -12,9 +12,10 @@ const FinanceSummary = ({ farmId }) => {
|
||||
setError("");
|
||||
try {
|
||||
const response = await fetch(
|
||||
`http://localhost:8000/api/v1/finance/summary/${farmId}`,
|
||||
`http://localhost:8000/api/v1/finance/summary/${financeId}`,
|
||||
{ credentials: "include" }
|
||||
);
|
||||
console.log("Summary response:", response);
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch summary");
|
||||
}
|
||||
@@ -30,45 +31,45 @@ const FinanceSummary = ({ farmId }) => {
|
||||
fetchSummary();
|
||||
}, [farmId]);
|
||||
|
||||
if (loading) return <Loader />;
|
||||
if (error) return <div className="p-4 text-center text-red-600">{error}</div>;
|
||||
// if (loading) return <Loader />;
|
||||
//if (error) return <div className="p-4 text-center text-red-600">{error}</div>;
|
||||
|
||||
// Extract only the important fields.
|
||||
const { totalExpenses, totalRevenue, transactions } = summary;
|
||||
const { totalExpenses, totalRevenue, transactions } = summary || {};
|
||||
const transactionsCount = Array.isArray(transactions)
|
||||
? transactions.length
|
||||
: 0;
|
||||
|
||||
return (
|
||||
<div className="max-w-md mx-auto p-8 bg-gray-50">
|
||||
<div className="w-full mx-auto p-8 bg-gray-50">
|
||||
<div className="bg-white rounded-lg shadow overflow-hidden">
|
||||
<header className="bg-blue-600 px-6 py-4">
|
||||
<h2 className="text-3xl font-bold text-white">Finance Summary</h2>
|
||||
<h2 className="text-3xl font-bold text-white">
|
||||
Transactions Summary
|
||||
</h2>
|
||||
</header>
|
||||
<div className="p-6">
|
||||
<table className="w-full table-auto">
|
||||
<tbody className="divide-y divide-gray-200">
|
||||
<tr className="hover:bg-gray-50">
|
||||
<td className="px-6 py-4 font-medium text-gray-600">
|
||||
Total Expenses
|
||||
</td>
|
||||
<td className="px-6 py-4 text-gray-800">{totalExpenses}</td>
|
||||
</tr>
|
||||
<tr className="hover:bg-gray-50">
|
||||
<td className="px-6 py-4 font-medium text-gray-600">
|
||||
Total Revenue
|
||||
</td>
|
||||
<td className="px-6 py-4 text-gray-800">{totalRevenue}</td>
|
||||
</tr>
|
||||
<tr className="hover:bg-gray-50">
|
||||
<td className="px-6 py-4 font-medium text-gray-600">
|
||||
Transactions
|
||||
</td>
|
||||
<td className="px-6 py-4 text-gray-800">{transactionsCount}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
||||
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||
<tr>
|
||||
<th scope="col" className="px-6 py-3">
|
||||
Farm name
|
||||
</th>
|
||||
<th scope="col" className="px-6 py-3">
|
||||
Location
|
||||
</th>
|
||||
<th scope="col" className="px-6 py-3">
|
||||
Type
|
||||
</th>
|
||||
<th scope="col" className="px-6 py-3">
|
||||
Size (acres)
|
||||
</th>
|
||||
<th scope="col" className="px-6 py-3">
|
||||
Action
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -31,34 +31,22 @@ const Transactions = ({ farmId }) => {
|
||||
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||
<tr>
|
||||
<th scope="col" className="px-6 py-3">
|
||||
Field
|
||||
Total Expenses
|
||||
</th>
|
||||
<th scope="col" className="px-6 py-3">
|
||||
Value
|
||||
totalRevenue
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{!Array.isArray(data) ? (
|
||||
// Data is an object: show key-value pairs
|
||||
Object.entries(data).map(([key, value]) => (
|
||||
<tr key={key}>
|
||||
<td className="px-6 py-3 font-bold">{key}</td>
|
||||
<td className="px-6 py-3">
|
||||
{typeof value === "object" ? JSON.stringify(value) : value}
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
) : // Data is an array: render using your Td component
|
||||
data.length > 0 ? (
|
||||
data.map((item) => <Td key={item.id} children={item} />)
|
||||
) : (
|
||||
<tr>
|
||||
<td colSpan={2} className="text-center">
|
||||
No data available
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
<tr>
|
||||
<td className="px-6 py-3">
|
||||
{data.totalExpenses ? data.totalExpenses : "N/A"}
|
||||
</td>
|
||||
<td className="px-6 py-3">
|
||||
{data.totalRevenue ? data.totalRevenue : "N/A"}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
|
||||
@@ -243,9 +243,12 @@ const MainUserPanel = () => {
|
||||
{user.address == null && "Maharashtra, Pune"}
|
||||
</p>
|
||||
<div className="flex justify-center mt-4">
|
||||
<button className="bg-gray-300 hover:bg-gray-400 text-gray-700 font-bold py-2 px-4 rounded mr-2">
|
||||
<Link
|
||||
to="/"
|
||||
className="bg-gray-300 hover:bg-gray-400 text-gray-700 font-bold py-2 px-4 rounded mr-2"
|
||||
>
|
||||
<FaHome className="text-lg font-extrabold" />
|
||||
</button>
|
||||
</Link>
|
||||
<button className="bg-gray-300 hover:bg-gray-400 text-gray-700 font-bold py-2 px-4 rounded mr-2">
|
||||
<IoMdSettings className="text-lg font-extrabold" />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user