feat: Set up RTK query for the statemanagement

This commit is contained in:
2025-03-25 17:48:15 +05:30
parent 7e204690d3
commit 914501036d
70 changed files with 141275 additions and 205 deletions
+1 -7
View File
@@ -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
+1 -1
View File
@@ -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
+14 -8
View File
@@ -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 {
+7 -15
View File
@@ -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>
);
};
+16 -27
View File
@@ -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>;
+13 -10
View File
@@ -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);
}
+49 -35
View File
@@ -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>